From 106a3f79cea57d8546c5225a4ab9b6015911a8b5 Mon Sep 17 00:00:00 2001 From: hselasky Date: Sat, 6 Feb 2016 08:58:10 +0000 Subject: MFC r294915: Fix generation of dependency rules for the LinuxKPI, the MLX5 driver and all of OFED except MLX4[EN/IB]. Sponsored by: Mellanox Technologies Approved by: re (marius) --- sys/conf/files | 131 ++++++++++++++++++-------------------------------- sys/conf/kern.post.mk | 36 +++++++++----- 2 files changed, 71 insertions(+), 96 deletions(-) diff --git a/sys/conf/files b/sys/conf/files index 9d8a183..5c46c8c 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3646,128 +3646,91 @@ nlm/sm_inter_xdr.c optional nfslockd | nfsd # OpenFabrics Enterprise Distribution (Infiniband) ofed/include/linux/linux_compat.c optional ofed | compat_linuxkpi \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/include/linux/linux_idr.c optional ofed | compat_linuxkpi \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/include/linux/linux_radix.c optional ofed | compat_linuxkpi \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/core/addr.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/agent.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/cache.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" # XXX Mad.c must be ordered before cm.c for sysinit sets to occur in # the correct order. ofed/drivers/infiniband/core/mad.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/cm.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/ -Wno-unused-function" ofed/drivers/infiniband/core/cma.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/device.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/fmr_pool.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/iwcm.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/local_sa.c optional ofed \ no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/mad_rmpp.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/multicast.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/notice.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/packer.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/sa_query.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/smi.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/sysfs.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/ucm.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/ucma.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/ud_header.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/umem.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/user_mad.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/uverbs_cmd.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/uverbs_main.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/uverbs_marshall.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/verbs.c optional ofed \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/ulp/ipoib/ipoib_cm.c optional ipoib \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" #ofed/drivers/infiniband/ulp/ipoib/ipoib_fs.c optional ipoib \ -# no-depend \ # compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c optional ipoib \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c optional ipoib \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/ipoib/ipoib_multicast.c optional ipoib \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/ipoib/ipoib_verbs.c optional ipoib \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" #ofed/drivers/infiniband/ulp/ipoib/ipoib_vlan.c optional ipoib \ -# no-depend \ # compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/sdp/sdp_bcopy.c optional sdp inet \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/ulp/sdp/sdp_main.c optional sdp inet \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/ulp/sdp/sdp_rx.c optional sdp inet \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/ulp/sdp/sdp_cma.c optional sdp inet \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/ulp/sdp/sdp_tx.c optional sdp inet \ - no-depend \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/hw/mlx4/alias_GUID.c optional mlx4ib \ @@ -3897,95 +3860,95 @@ ofed/drivers/net/mlx4/en_tx.c optional mlxen \ compile-with "${OFED_C_NOIMP} -I$S/ofed/drivers/net/mlx4/" dev/mlx5/mlx5_core/mlx5_alloc.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_cmd.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_cq.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_eq.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_flow_table.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_fw.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_health.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_mad.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_main.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_mcg.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_mr.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_pagealloc.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_pd.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_port.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_qp.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_srq.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_transobj.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_uar.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_vport.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_wq.c optional mlx5 pci \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_ethtool.c optional mlx5en pci inet inet6 \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_main.c optional mlx5en pci inet inet6 \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_tx.c optional mlx5en pci inet inet6 \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_flow_table.c optional mlx5en pci inet inet6 \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_rx.c optional mlx5en pci inet inet6 \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_txrx.c optional mlx5en pci inet inet6 \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_allocator.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_av.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_catas.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_cmd.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_cq.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_eq.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_mad.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_main.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_mcg.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_memfree.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_mr.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_pd.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_profile.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_provider.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_qp.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_reset.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_srq.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_uar.c optional mthca \ - no-depend compile-with "${OFED_C}" + compile-with "${OFED_C}" # crypto support opencrypto/cast.c optional crypto | ipsec diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk index fd85af4..ea5ba51 100644 --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -183,12 +183,20 @@ genassym.o: $S/$M/$M/genassym.c ${SYSTEM_OBJS} genassym.o vers.o: opt_global.h -# We have "special" -I include paths for opensolaris/zfs files in 'depend'. -CFILES_NOZFS= ${CFILES:N*/opensolaris/*} -SFILES_NOZFS= ${SFILES:N*/opensolaris/*} +# Normal files first +CFILES_NORMAL= ${CFILES:N*/opensolaris/*:N*/ofed/*:N*/dev/mlx5/*} +SFILES_NORMAL= ${SFILES:N*/opensolaris/*} + +# We have "special" -I include paths for zfs/dtrace files in 'depend'. CFILES_ZFS= ${CFILES:M*/opensolaris/*} SFILES_ZFS= ${SFILES:M*/opensolaris/*} +# We have "special" -I include paths for OFED. +CFILES_OFED=${CFILES:M*/ofed/*} + +# We have "special" -I include paths for MLX5. +CFILES_MLX5=${CFILES:M*/dev/mlx5/*} + kernel-depend: .depend # The argument list can be very long, so use make -V and xargs to # pass it to mkdep. @@ -196,17 +204,21 @@ SRCS= assym.s vnode_if.h ${BEFORE_DEPEND} ${CFILES} \ ${SYSTEM_CFILES} ${GEN_CFILES} ${SFILES} \ ${MFILES:T:S/.m$/.h/} .depend: .PRECIOUS ${SRCS} - rm -f .newdep - ${MAKE} -V CFILES_NOZFS -V SYSTEM_CFILES -V GEN_CFILES | \ - MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f .newdep ${CFLAGS} + rm -f ${.TARGET}.tmp +# C files + ${MAKE} -V CFILES_NORMAL -V SYSTEM_CFILES -V GEN_CFILES | \ + MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f ${.TARGET}.tmp ${CFLAGS} ${MAKE} -V CFILES_ZFS | \ - MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f .newdep ${ZFS_CFLAGS} - ${MAKE} -V SFILES_NOZFS | \ - MKDEP_CPP="${CC} -E" xargs mkdep -a -f .newdep ${ASM_CFLAGS} + MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f ${.TARGET}.tmp ${ZFS_CFLAGS} + ${MAKE} -V CFILES_OFED -V CFILES_MLX5 | \ + MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f ${.TARGET}.tmp \ + ${CFLAGS} ${OFEDINCLUDES} +# Assembly files + ${MAKE} -V SFILES_NORMAL | \ + MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f ${.TARGET}.tmp ${ASM_CFLAGS} ${MAKE} -V SFILES_ZFS | \ - MKDEP_CPP="${CC} -E" xargs mkdep -a -f .newdep ${ZFS_ASM_CFLAGS} - rm -f .depend - mv .newdep .depend + MKDEP_CPP="${CC} -E" CC="${CC}" xargs mkdep -a -f ${.TARGET}.tmp ${ZFS_ASM_CFLAGS} + mv ${.TARGET}.tmp ${.TARGET} _ILINKS= machine .if ${MACHINE} != ${MACHINE_CPUARCH} -- cgit v1.1 From 28ae8dc6dd1a3a865bee71fc2a1747316fab30f8 Mon Sep 17 00:00:00 2001 From: wblock Date: Sat, 6 Feb 2016 14:03:31 +0000 Subject: MFC r294597: Add a standards compliance note for strtok_r Approved by: re (marius@) --- lib/libc/string/strtok.3 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/libc/string/strtok.3 b/lib/libc/string/strtok.3 index 97a8b15..9dc36ee 100644 --- a/lib/libc/string/strtok.3 +++ b/lib/libc/string/strtok.3 @@ -44,7 +44,7 @@ .\" @(#)strtok.3 8.2 (Berkeley) 2/3/94 .\" $FreeBSD$ .\" -.Dd November 27, 1998 +.Dd January 22, 2016 .Dt STRTOK 3 .Os .Sh NAME @@ -149,6 +149,11 @@ The function conforms to .St -isoC . +The +.Fn strtok_r +function +conforms to +.St -p1003.1-2001 . .Sh AUTHORS .An Wes Peters , Softweyr LLC: -- cgit v1.1 From 4ef5827b6250178df59526f9bdcffe2704998fc4 Mon Sep 17 00:00:00 2001 From: pfg Date: Sat, 6 Feb 2016 16:58:56 +0000 Subject: MFC r295209; Revert r294695; passthrough any extra timestamps to the dinode struct. The original ext2fs change worked fine on disks formated with default values, but it was the cause of a regression when inodes are small. Revert it for now, while we figure out safer ways pass such values, PR: 206820 Approved by: re --- sys/fs/ext2fs/ext2_inode_cnv.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c index 9b1b0ad..b69d4e5 100644 --- a/sys/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/fs/ext2fs/ext2_inode_cnv.c @@ -149,11 +149,13 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei) ei->e2di_atime = ip->i_atime; ei->e2di_mtime = ip->i_mtime; ei->e2di_ctime = ip->i_ctime; - ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec); - ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec); - ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec); - ei->e2di_crtime = ip->i_birthtime; - ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec); + if (E2DI_HAS_XTIME(ip)) { + ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec); + ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec); + ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec); + ei->e2di_crtime = ip->i_birthtime; + ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec); + } ei->e2di_flags = 0; ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0; ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0; -- cgit v1.1 From c76cb9755e8e722ba04e0c26cf28ecc0adeb52de Mon Sep 17 00:00:00 2001 From: kib Date: Sun, 7 Feb 2016 09:51:22 +0000 Subject: MFC r295277: When matching brand to the ELF binary by notes, try to find a brand with interpreter name exactly matching one wanted by the binary. Approved by: re (delphij) --- sys/kern/imgact_elf.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 05f3a43..394d61f 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -261,7 +261,7 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, int interp_name_len, int32_t *osrel) { const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; - Elf_Brandinfo *bi; + Elf_Brandinfo *bi, *bi_m; boolean_t ret; int i; @@ -273,6 +273,7 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, */ /* Look for an ".note.ABI-tag" ELF section */ + bi_m = NULL; for (i = 0; i < MAX_BRANDS; i++) { bi = elf_brand_list[i]; if (bi == NULL) @@ -280,10 +281,28 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, if (hdr->e_machine == bi->machine && (bi->flags & (BI_BRAND_NOTE|BI_BRAND_NOTE_MANDATORY)) != 0) { ret = __elfN(check_note)(imgp, bi->brand_note, osrel); + /* + * If note checker claimed the binary, but the + * interpreter path in the image does not + * match default one for the brand, try to + * search for other brands with the same + * interpreter. Either there is better brand + * with the right interpreter, or, failing + * this, we return first brand which accepted + * our note and, optionally, header. + */ + if (ret && bi_m == NULL && (strlen(bi->interp_path) + + 1 != interp_name_len || strncmp(interp, + bi->interp_path, interp_name_len) != 0)) { + bi_m = bi; + ret = 0; + } if (ret) return (bi); } } + if (bi_m != NULL) + return (bi_m); /* If the executable has a brand, search for it in the brand list. */ for (i = 0; i < MAX_BRANDS; i++) { -- cgit v1.1 From 5a18868b2d506b9e2254047d8d9fb9df5b2a8ae0 Mon Sep 17 00:00:00 2001 From: des Date: Sun, 7 Feb 2016 11:38:54 +0000 Subject: MFH (r265214, r294333, r294407, r294467): misc prop fixes MFH (r285975, r287143): register mergeinfo for security fixes MFH (r294497, r294498, r295139): internal documentation MFH (r294328): upgrade to openssh 6.7p1, re-add libwrap MFH (r294332): upgrade to openssh 6.8p1 MFH (r294367): update pam_ssh for api changes MFH (r294909): switch usedns back on MFH (r294336): upgrade to openssh 6.9p1 MFH (r294495): re-enable dsa keys MFH (r294464): upgrade to openssh 7.0p1 MFH (r294496): upgrade to openssh 7.1p2 Approved by: re (gjb) Relnotes: yes --- crypto/openssh/.cvsignore | 28 + crypto/openssh/ChangeLog | 10484 ++++++++++++++----- crypto/openssh/FREEBSD-upgrade | 65 +- crypto/openssh/INSTALL | 31 +- crypto/openssh/Makefile.in | 177 +- crypto/openssh/OVERVIEW | 6 +- crypto/openssh/PROTOCOL | 104 +- crypto/openssh/PROTOCOL.agent | 4 +- crypto/openssh/PROTOCOL.krl | 9 +- crypto/openssh/PROTOCOL.mux | 8 +- crypto/openssh/README | 8 +- crypto/openssh/addrmatch.c | 3 +- crypto/openssh/atomicio.c | 3 +- crypto/openssh/auth-bsdauth.c | 9 +- crypto/openssh/auth-chall.c | 6 +- crypto/openssh/auth-krb5.c | 3 +- crypto/openssh/auth-options.c | 143 +- crypto/openssh/auth-options.h | 4 +- crypto/openssh/auth-pam.c | 4 +- crypto/openssh/auth-passwd.c | 3 +- crypto/openssh/auth-rh-rsa.c | 7 +- crypto/openssh/auth-rhosts.c | 66 +- crypto/openssh/auth-rsa.c | 15 +- crypto/openssh/auth.c | 89 +- crypto/openssh/auth.h | 28 +- crypto/openssh/auth1.c | 9 +- crypto/openssh/auth2-chall.c | 8 +- crypto/openssh/auth2-gss.c | 23 +- crypto/openssh/auth2-hostbased.c | 36 +- crypto/openssh/auth2-kbdint.c | 3 +- crypto/openssh/auth2-none.c | 6 +- crypto/openssh/auth2-passwd.c | 3 +- crypto/openssh/auth2-pubkey.c | 705 +- crypto/openssh/auth2.c | 21 +- crypto/openssh/authfd.c | 852 +- crypto/openssh/authfd.h | 60 +- crypto/openssh/authfile.c | 1434 +-- crypto/openssh/authfile.h | 64 +- crypto/openssh/bitmap.c | 212 + crypto/openssh/bitmap.h | 56 + crypto/openssh/bufaux.c | 340 +- crypto/openssh/bufbn.c | 216 +- crypto/openssh/bufec.c | 106 +- crypto/openssh/buffer.c | 245 +- crypto/openssh/buffer.h | 69 +- crypto/openssh/canohost.c | 35 +- crypto/openssh/chacha.h | 2 +- crypto/openssh/channels.c | 827 +- crypto/openssh/channels.h | 60 +- crypto/openssh/cipher-3des1.c | 76 +- crypto/openssh/cipher-aesctr.c | 83 + crypto/openssh/cipher-aesctr.h | 35 + crypto/openssh/cipher-bf1.c | 21 +- crypto/openssh/cipher-chachapoly.c | 32 +- crypto/openssh/cipher-chachapoly.h | 4 +- crypto/openssh/cipher-ctr.c | 4 +- crypto/openssh/cipher.c | 415 +- crypto/openssh/cipher.h | 56 +- crypto/openssh/clientloop.c | 563 +- crypto/openssh/compat.c | 79 +- crypto/openssh/compat.h | 6 +- crypto/openssh/compress.c | 167 - crypto/openssh/compress.h | 25 - crypto/openssh/config.guess | 6 + crypto/openssh/config.h | 32 +- crypto/openssh/configure.ac | 1015 +- crypto/openssh/contrib/Makefile | 4 +- crypto/openssh/contrib/README | 2 +- crypto/openssh/contrib/caldera/openssh.spec | 366 - crypto/openssh/contrib/caldera/ssh-host-keygen | 36 - crypto/openssh/contrib/caldera/sshd.init | 125 - crypto/openssh/contrib/caldera/sshd.pam | 8 - crypto/openssh/contrib/cygwin/README | 3 +- crypto/openssh/contrib/cygwin/ssh-host-config | 228 +- crypto/openssh/contrib/cygwin/ssh-user-config | 27 +- crypto/openssh/contrib/redhat/openssh.spec | 5 +- crypto/openssh/contrib/suse/openssh.spec | 5 +- crypto/openssh/deattack.c | 81 +- crypto/openssh/deattack.h | 11 +- crypto/openssh/defines.h | 52 +- crypto/openssh/dh.c | 105 +- crypto/openssh/dh.h | 7 +- crypto/openssh/digest-libc.c | 76 +- crypto/openssh/digest-openssl.c | 83 +- crypto/openssh/digest.h | 14 +- crypto/openssh/dispatch.c | 102 +- crypto/openssh/dispatch.h | 35 +- crypto/openssh/dns.c | 50 +- crypto/openssh/dns.h | 10 +- crypto/openssh/entropy.c | 25 +- crypto/openssh/ge25519.h | 4 +- crypto/openssh/groupaccess.c | 8 +- crypto/openssh/gss-genr.c | 4 +- crypto/openssh/gss-serv-krb5.c | 1 + crypto/openssh/gss-serv.c | 43 +- crypto/openssh/hmac.c | 8 +- crypto/openssh/hmac.h | 5 +- crypto/openssh/hostfile.c | 623 +- crypto/openssh/hostfile.h | 64 +- crypto/openssh/includes.h | 5 +- crypto/openssh/kex.c | 756 +- crypto/openssh/kex.h | 200 +- crypto/openssh/kexc25519.c | 99 +- crypto/openssh/kexc25519c.c | 161 +- crypto/openssh/kexc25519s.c | 135 +- crypto/openssh/kexdh.c | 90 +- crypto/openssh/kexdhc.c | 199 +- crypto/openssh/kexdhs.c | 190 +- crypto/openssh/kexecdh.c | 85 +- crypto/openssh/kexecdhc.c | 221 +- crypto/openssh/kexecdhs.c | 201 +- crypto/openssh/kexgex.c | 108 +- crypto/openssh/kexgexc.c | 299 +- crypto/openssh/kexgexs.c | 270 +- crypto/openssh/key.c | 2713 +---- crypto/openssh/key.h | 182 +- crypto/openssh/krl.c | 852 +- crypto/openssh/krl.h | 38 +- crypto/openssh/log.c | 3 +- crypto/openssh/loginrec.c | 10 +- crypto/openssh/mac.c | 99 +- crypto/openssh/mac.h | 30 +- crypto/openssh/match.c | 14 +- crypto/openssh/match.h | 6 +- crypto/openssh/misc.c | 91 +- crypto/openssh/misc.h | 31 +- crypto/openssh/moduli | 542 +- crypto/openssh/moduli.0 | 74 - crypto/openssh/moduli.c | 14 +- crypto/openssh/monitor.c | 430 +- crypto/openssh/monitor.h | 4 +- crypto/openssh/monitor_fdpass.c | 15 +- crypto/openssh/monitor_mm.c | 8 +- crypto/openssh/monitor_wrap.c | 274 +- crypto/openssh/monitor_wrap.h | 13 +- crypto/openssh/msg.c | 25 +- crypto/openssh/msg.h | 7 +- crypto/openssh/mux.c | 296 +- crypto/openssh/myproposal.h | 115 +- crypto/openssh/opacket.c | 349 + crypto/openssh/opacket.h | 168 + crypto/openssh/openbsd-compat/.cvsignore | 1 + crypto/openssh/openbsd-compat/Makefile.in | 6 +- crypto/openssh/openbsd-compat/arc4random.c | 40 +- crypto/openssh/openbsd-compat/bcrypt_pbkdf.c | 45 +- crypto/openssh/openbsd-compat/bsd-cygwin_util.c | 16 + crypto/openssh/openbsd-compat/bsd-cygwin_util.h | 6 +- crypto/openssh/openbsd-compat/bsd-misc.c | 14 +- crypto/openssh/openbsd-compat/bsd-misc.h | 2 +- crypto/openssh/openbsd-compat/bsd-snprintf.c | 4 +- crypto/openssh/openbsd-compat/explicit_bzero.c | 26 +- crypto/openssh/openbsd-compat/fake-rfc2553.h | 3 + .../openssh/openbsd-compat/getrrsetbyname-ldns.c | 2 +- crypto/openssh/openbsd-compat/kludge-fd_set.c | 28 + crypto/openssh/openbsd-compat/md5.c | 251 + crypto/openssh/openbsd-compat/md5.h | 51 + crypto/openssh/openbsd-compat/openbsd-compat.h | 37 +- crypto/openssh/openbsd-compat/openssl-compat.c | 170 +- crypto/openssh/openbsd-compat/openssl-compat.h | 124 +- crypto/openssh/openbsd-compat/port-linux.c | 4 +- crypto/openssh/openbsd-compat/port-tun.c | 17 +- crypto/openssh/openbsd-compat/port-uw.c | 1 + crypto/openssh/openbsd-compat/readpassphrase.c | 8 + crypto/openssh/openbsd-compat/reallocarray.c | 46 + crypto/openssh/openbsd-compat/realpath.c | 7 +- crypto/openssh/openbsd-compat/regress/.cvsignore | 6 + crypto/openssh/openbsd-compat/regress/Makefile.in | 6 +- .../openbsd-compat/regress/opensslvertest.c | 69 + crypto/openssh/openbsd-compat/rmd160.c | 378 + crypto/openssh/openbsd-compat/rmd160.h | 61 + crypto/openssh/openbsd-compat/sha1.c | 177 + crypto/openssh/openbsd-compat/sha1.h | 58 + crypto/openssh/openbsd-compat/sha2.c | 40 +- crypto/openssh/openbsd-compat/sha2.h | 19 +- crypto/openssh/openbsd-compat/xcrypt.c | 2 +- crypto/openssh/opensshd.init.in | 4 + crypto/openssh/packet.c | 2899 +++-- crypto/openssh/packet.h | 283 +- crypto/openssh/platform.c | 3 +- crypto/openssh/poly1305.h | 2 +- crypto/openssh/progressmeter.c | 6 +- crypto/openssh/progressmeter.h | 4 +- crypto/openssh/readconf.c | 806 +- crypto/openssh/readconf.h | 50 +- crypto/openssh/regress/.cvsignore | 31 + crypto/openssh/regress/Makefile | 51 +- crypto/openssh/regress/README.regress | 2 +- crypto/openssh/regress/agent-pkcs11.sh | 4 +- crypto/openssh/regress/agent-timeout.sh | 4 +- crypto/openssh/regress/agent.sh | 8 +- crypto/openssh/regress/broken-pipe.sh | 4 +- crypto/openssh/regress/cert-hostkey.sh | 264 +- crypto/openssh/regress/cert-userkey.sh | 64 +- crypto/openssh/regress/cfgmatch.sh | 23 +- crypto/openssh/regress/cfgparse.sh | 75 + crypto/openssh/regress/cipher-speed.sh | 10 +- crypto/openssh/regress/connect-privsep.sh | 10 +- crypto/openssh/regress/connect.sh | 4 +- crypto/openssh/regress/dhgex.sh | 6 +- crypto/openssh/regress/dynamic-forward.sh | 4 +- crypto/openssh/regress/exit-status.sh | 4 +- crypto/openssh/regress/forcecommand.sh | 26 +- crypto/openssh/regress/forward-control.sh | 6 +- crypto/openssh/regress/forwarding.sh | 40 +- crypto/openssh/regress/host-expand.sh | 4 +- crypto/openssh/regress/hostkey-agent.sh | 53 + crypto/openssh/regress/hostkey-rotate.sh | 128 + crypto/openssh/regress/integrity.sh | 19 +- crypto/openssh/regress/kextype.sh | 7 +- crypto/openssh/regress/key-options.sh | 10 +- crypto/openssh/regress/keygen-change.sh | 9 +- crypto/openssh/regress/keygen-knownhosts.sh | 197 + crypto/openssh/regress/keys-command.sh | 59 +- crypto/openssh/regress/keyscan.sh | 9 +- crypto/openssh/regress/keytype.sh | 14 +- crypto/openssh/regress/krl.sh | 93 +- crypto/openssh/regress/limit-keytype.sh | 80 + crypto/openssh/regress/localcommand.sh | 4 +- crypto/openssh/regress/login-timeout.sh | 3 +- crypto/openssh/regress/multiplex.sh | 63 +- crypto/openssh/regress/multipubkey.sh | 66 + crypto/openssh/regress/netcat.c | 1696 +++ crypto/openssh/regress/principals-command.sh | 145 + crypto/openssh/regress/proto-mismatch.sh | 6 +- crypto/openssh/regress/proto-version.sh | 10 +- crypto/openssh/regress/proxy-connect.sh | 31 +- crypto/openssh/regress/reconfigure.sh | 31 +- crypto/openssh/regress/reexec.sh | 4 +- crypto/openssh/regress/rekey.sh | 42 +- crypto/openssh/regress/ssh-com.sh | 6 +- crypto/openssh/regress/ssh2putty.sh | 6 +- crypto/openssh/regress/sshd-log-wrapper.sh | 8 +- crypto/openssh/regress/stderr-data.sh | 4 +- crypto/openssh/regress/t11.ok | 1 + crypto/openssh/regress/t4.ok | 2 +- crypto/openssh/regress/test-exec.sh | 99 +- crypto/openssh/regress/transfer.sh | 4 +- crypto/openssh/regress/try-ciphers.sh | 15 +- crypto/openssh/regress/unittests/Makefile | 5 + crypto/openssh/regress/unittests/Makefile.inc | 59 + crypto/openssh/regress/unittests/bitmap/Makefile | 12 + crypto/openssh/regress/unittests/bitmap/tests.c | 135 + crypto/openssh/regress/unittests/hostkeys/Makefile | 12 + .../regress/unittests/hostkeys/mktestdata.sh | 94 + .../regress/unittests/hostkeys/test_iterate.c | 1171 +++ .../regress/unittests/hostkeys/testdata/dsa_1.pub | 1 + .../regress/unittests/hostkeys/testdata/dsa_2.pub | 1 + .../regress/unittests/hostkeys/testdata/dsa_3.pub | 1 + .../regress/unittests/hostkeys/testdata/dsa_4.pub | 1 + .../regress/unittests/hostkeys/testdata/dsa_5.pub | 1 + .../regress/unittests/hostkeys/testdata/dsa_6.pub | 1 + .../unittests/hostkeys/testdata/ecdsa_1.pub | 1 + .../unittests/hostkeys/testdata/ecdsa_2.pub | 1 + .../unittests/hostkeys/testdata/ecdsa_3.pub | 1 + .../unittests/hostkeys/testdata/ecdsa_4.pub | 1 + .../unittests/hostkeys/testdata/ecdsa_5.pub | 1 + .../unittests/hostkeys/testdata/ecdsa_6.pub | 1 + .../unittests/hostkeys/testdata/ed25519_1.pub | 1 + .../unittests/hostkeys/testdata/ed25519_2.pub | 1 + .../unittests/hostkeys/testdata/ed25519_3.pub | 1 + .../unittests/hostkeys/testdata/ed25519_4.pub | 1 + .../unittests/hostkeys/testdata/ed25519_5.pub | 1 + .../unittests/hostkeys/testdata/ed25519_6.pub | 1 + .../unittests/hostkeys/testdata/known_hosts | 61 + .../regress/unittests/hostkeys/testdata/rsa1_1.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa1_2.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa1_3.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa1_4.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa1_5.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa1_6.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa_1.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa_2.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa_3.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa_4.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa_5.pub | 1 + .../regress/unittests/hostkeys/testdata/rsa_6.pub | 1 + crypto/openssh/regress/unittests/hostkeys/tests.c | 16 + crypto/openssh/regress/unittests/kex/Makefile | 14 + crypto/openssh/regress/unittests/kex/test_kex.c | 202 + crypto/openssh/regress/unittests/kex/tests.c | 14 + crypto/openssh/regress/unittests/sshbuf/Makefile | 14 + .../openssh/regress/unittests/sshbuf/test_sshbuf.c | 240 + .../regress/unittests/sshbuf/test_sshbuf_fixed.c | 126 + .../regress/unittests/sshbuf/test_sshbuf_fuzz.c | 127 + .../unittests/sshbuf/test_sshbuf_getput_basic.c | 484 + .../unittests/sshbuf/test_sshbuf_getput_crypto.c | 409 + .../unittests/sshbuf/test_sshbuf_getput_fuzz.c | 130 + .../regress/unittests/sshbuf/test_sshbuf_misc.c | 138 + crypto/openssh/regress/unittests/sshbuf/tests.c | 28 + crypto/openssh/regress/unittests/sshkey/Makefile | 13 + crypto/openssh/regress/unittests/sshkey/common.c | 84 + crypto/openssh/regress/unittests/sshkey/common.h | 16 + .../openssh/regress/unittests/sshkey/mktestdata.sh | 192 + .../openssh/regress/unittests/sshkey/test_file.c | 460 + .../openssh/regress/unittests/sshkey/test_fuzz.c | 411 + .../openssh/regress/unittests/sshkey/test_sshkey.c | 521 + .../regress/unittests/sshkey/testdata/dsa_1 | 12 + .../unittests/sshkey/testdata/dsa_1-cert.fp | 1 + .../unittests/sshkey/testdata/dsa_1-cert.pub | 1 + .../regress/unittests/sshkey/testdata/dsa_1.fp | 1 + .../regress/unittests/sshkey/testdata/dsa_1.fp.bb | 1 + .../unittests/sshkey/testdata/dsa_1.param.g | 1 + .../unittests/sshkey/testdata/dsa_1.param.priv | 1 + .../unittests/sshkey/testdata/dsa_1.param.pub | 1 + .../regress/unittests/sshkey/testdata/dsa_1.pub | 1 + .../regress/unittests/sshkey/testdata/dsa_1_pw | 15 + .../regress/unittests/sshkey/testdata/dsa_2 | 12 + .../regress/unittests/sshkey/testdata/dsa_2.fp | 1 + .../regress/unittests/sshkey/testdata/dsa_2.fp.bb | 1 + .../regress/unittests/sshkey/testdata/dsa_2.pub | 1 + .../regress/unittests/sshkey/testdata/dsa_n | 12 + .../regress/unittests/sshkey/testdata/dsa_n_pw | 21 + .../regress/unittests/sshkey/testdata/ecdsa_1 | 5 + .../unittests/sshkey/testdata/ecdsa_1-cert.fp | 1 + .../unittests/sshkey/testdata/ecdsa_1-cert.pub | 1 + .../regress/unittests/sshkey/testdata/ecdsa_1.fp | 1 + .../unittests/sshkey/testdata/ecdsa_1.fp.bb | 1 + .../unittests/sshkey/testdata/ecdsa_1.param.curve | 1 + .../unittests/sshkey/testdata/ecdsa_1.param.priv | 1 + .../unittests/sshkey/testdata/ecdsa_1.param.pub | 1 + .../regress/unittests/sshkey/testdata/ecdsa_1.pub | 1 + .../regress/unittests/sshkey/testdata/ecdsa_1_pw | 8 + .../regress/unittests/sshkey/testdata/ecdsa_2 | 7 + .../regress/unittests/sshkey/testdata/ecdsa_2.fp | 1 + .../unittests/sshkey/testdata/ecdsa_2.fp.bb | 1 + .../unittests/sshkey/testdata/ecdsa_2.param.curve | 1 + .../unittests/sshkey/testdata/ecdsa_2.param.priv | 1 + .../unittests/sshkey/testdata/ecdsa_2.param.pub | 1 + .../regress/unittests/sshkey/testdata/ecdsa_2.pub | 1 + .../regress/unittests/sshkey/testdata/ecdsa_n | 5 + .../regress/unittests/sshkey/testdata/ecdsa_n_pw | 9 + .../regress/unittests/sshkey/testdata/ed25519_1 | 7 + .../unittests/sshkey/testdata/ed25519_1-cert.fp | 1 + .../unittests/sshkey/testdata/ed25519_1-cert.pub | 1 + .../regress/unittests/sshkey/testdata/ed25519_1.fp | 1 + .../unittests/sshkey/testdata/ed25519_1.fp.bb | 1 + .../unittests/sshkey/testdata/ed25519_1.pub | 1 + .../regress/unittests/sshkey/testdata/ed25519_1_pw | 8 + .../regress/unittests/sshkey/testdata/ed25519_2 | 7 + .../regress/unittests/sshkey/testdata/ed25519_2.fp | 1 + .../unittests/sshkey/testdata/ed25519_2.fp.bb | 1 + .../unittests/sshkey/testdata/ed25519_2.pub | 1 + .../openssh/regress/unittests/sshkey/testdata/pw | 1 + .../regress/unittests/sshkey/testdata/rsa1_1 | Bin 0 -> 533 bytes .../regress/unittests/sshkey/testdata/rsa1_1.fp | 1 + .../regress/unittests/sshkey/testdata/rsa1_1.fp.bb | 1 + .../unittests/sshkey/testdata/rsa1_1.param.n | 1 + .../regress/unittests/sshkey/testdata/rsa1_1.pub | 1 + .../regress/unittests/sshkey/testdata/rsa1_1_pw | Bin 0 -> 533 bytes .../regress/unittests/sshkey/testdata/rsa1_2 | Bin 0 -> 981 bytes .../regress/unittests/sshkey/testdata/rsa1_2.fp | 1 + .../regress/unittests/sshkey/testdata/rsa1_2.fp.bb | 1 + .../unittests/sshkey/testdata/rsa1_2.param.n | 1 + .../regress/unittests/sshkey/testdata/rsa1_2.pub | 1 + .../regress/unittests/sshkey/testdata/rsa_1 | 15 + .../unittests/sshkey/testdata/rsa_1-cert.fp | 1 + .../unittests/sshkey/testdata/rsa_1-cert.pub | 1 + .../regress/unittests/sshkey/testdata/rsa_1.fp | 1 + .../regress/unittests/sshkey/testdata/rsa_1.fp.bb | 1 + .../unittests/sshkey/testdata/rsa_1.param.n | 1 + .../unittests/sshkey/testdata/rsa_1.param.p | 1 + .../unittests/sshkey/testdata/rsa_1.param.q | 1 + .../regress/unittests/sshkey/testdata/rsa_1.pub | 1 + .../regress/unittests/sshkey/testdata/rsa_1_pw | 18 + .../regress/unittests/sshkey/testdata/rsa_2 | 27 + .../regress/unittests/sshkey/testdata/rsa_2.fp | 1 + .../regress/unittests/sshkey/testdata/rsa_2.fp.bb | 1 + .../unittests/sshkey/testdata/rsa_2.param.n | 1 + .../unittests/sshkey/testdata/rsa_2.param.p | 1 + .../unittests/sshkey/testdata/rsa_2.param.q | 1 + .../regress/unittests/sshkey/testdata/rsa_2.pub | 1 + .../regress/unittests/sshkey/testdata/rsa_n | 15 + .../regress/unittests/sshkey/testdata/rsa_n_pw | 17 + crypto/openssh/regress/unittests/sshkey/tests.c | 27 + .../openssh/regress/unittests/test_helper/Makefile | 16 + .../openssh/regress/unittests/test_helper/fuzz.c | 438 + .../regress/unittests/test_helper/test_helper.c | 526 + .../regress/unittests/test_helper/test_helper.h | 303 + crypto/openssh/regress/valgrind-unit.sh | 20 + crypto/openssh/regress/yes-head.sh | 4 +- crypto/openssh/rijndael.c | 469 +- crypto/openssh/rijndael.h | 25 +- crypto/openssh/roaming_client.c | 8 +- crypto/openssh/roaming_common.c | 5 +- crypto/openssh/roaming_dummy.c | 13 +- crypto/openssh/rsa.c | 113 +- crypto/openssh/rsa.h | 6 +- crypto/openssh/sandbox-seccomp-filter.c | 114 +- crypto/openssh/sandbox-systrace.c | 26 +- crypto/openssh/scard/.cvsignore | 2 + crypto/openssh/scp.0 | 163 - crypto/openssh/scp.1 | 21 +- crypto/openssh/scp.c | 17 +- crypto/openssh/servconf.c | 377 +- crypto/openssh/servconf.h | 26 +- crypto/openssh/serverloop.c | 229 +- crypto/openssh/session.c | 74 +- crypto/openssh/sftp-client.c | 899 +- crypto/openssh/sftp-client.h | 48 +- crypto/openssh/sftp-common.c | 101 +- crypto/openssh/sftp-common.h | 7 +- crypto/openssh/sftp-glob.c | 4 +- crypto/openssh/sftp-server.0 | 95 - crypto/openssh/sftp-server.8 | 12 +- crypto/openssh/sftp-server.c | 615 +- crypto/openssh/sftp.0 | 370 - crypto/openssh/sftp.1 | 39 +- crypto/openssh/sftp.c | 90 +- crypto/openssh/ssh-add.0 | 123 - crypto/openssh/ssh-add.1 | 29 +- crypto/openssh/ssh-add.c | 338 +- crypto/openssh/ssh-agent.0 | 128 - crypto/openssh/ssh-agent.1 | 73 +- crypto/openssh/ssh-agent.c | 684 +- crypto/openssh/ssh-dss.c | 241 +- crypto/openssh/ssh-ecdsa.c | 236 +- crypto/openssh/ssh-ed25519.c | 187 +- crypto/openssh/ssh-keygen.0 | 562 - crypto/openssh/ssh-keygen.1 | 40 +- crypto/openssh/ssh-keygen.c | 1548 ++- crypto/openssh/ssh-keyscan.0 | 110 - crypto/openssh/ssh-keyscan.1 | 15 +- crypto/openssh/ssh-keyscan.c | 172 +- crypto/openssh/ssh-keysign.0 | 53 - crypto/openssh/ssh-keysign.c | 161 +- crypto/openssh/ssh-pkcs11-client.c | 4 +- crypto/openssh/ssh-pkcs11-helper.0 | 25 - crypto/openssh/ssh-pkcs11-helper.c | 12 +- crypto/openssh/ssh-pkcs11.c | 85 +- crypto/openssh/ssh-pkcs11.h | 8 +- crypto/openssh/ssh-rsa.c | 265 +- crypto/openssh/ssh.0 | 946 -- crypto/openssh/ssh.1 | 219 +- crypto/openssh/ssh.c | 403 +- crypto/openssh/ssh.h | 2 +- crypto/openssh/ssh_api.c | 537 + crypto/openssh/ssh_api.h | 137 + crypto/openssh/ssh_config | 2 +- crypto/openssh/ssh_config.0 | 889 -- crypto/openssh/ssh_config.5 | 361 +- crypto/openssh/ssh_namespace.h | 1556 +-- crypto/openssh/sshbuf-getput-basic.c | 462 + crypto/openssh/sshbuf-getput-crypto.c | 224 + crypto/openssh/sshbuf-misc.c | 138 + crypto/openssh/sshbuf.c | 406 + crypto/openssh/sshbuf.h | 338 + crypto/openssh/sshconnect.c | 134 +- crypto/openssh/sshconnect1.c | 94 +- crypto/openssh/sshconnect2.c | 651 +- crypto/openssh/sshd.0 | 643 -- crypto/openssh/sshd.8 | 52 +- crypto/openssh/sshd.c | 433 +- crypto/openssh/sshd_config | 4 +- crypto/openssh/sshd_config.0 | 835 -- crypto/openssh/sshd_config.5 | 487 +- crypto/openssh/ssherr.c | 141 + crypto/openssh/ssherr.h | 84 + crypto/openssh/sshkey.c | 3895 +++++++ crypto/openssh/sshkey.h | 229 + crypto/openssh/sshlogin.c | 7 +- crypto/openssh/sshpty.c | 28 +- crypto/openssh/uidswap.c | 8 +- crypto/openssh/umac.c | 59 +- crypto/openssh/uuencode.c | 4 +- crypto/openssh/version.h | 14 +- crypto/openssh/xmalloc.c | 26 +- crypto/openssh/xmalloc.h | 4 +- lib/libpam/modules/pam_ssh/pam_ssh.c | 13 +- secure/lib/libssh/Makefile | 28 +- secure/usr.sbin/sshd/Makefile | 3 +- 470 files changed, 46092 insertions(+), 24609 deletions(-) create mode 100644 crypto/openssh/.cvsignore create mode 100644 crypto/openssh/bitmap.c create mode 100644 crypto/openssh/bitmap.h create mode 100644 crypto/openssh/cipher-aesctr.c create mode 100644 crypto/openssh/cipher-aesctr.h delete mode 100644 crypto/openssh/compress.c delete mode 100644 crypto/openssh/compress.h delete mode 100644 crypto/openssh/contrib/caldera/openssh.spec delete mode 100755 crypto/openssh/contrib/caldera/ssh-host-keygen delete mode 100755 crypto/openssh/contrib/caldera/sshd.init delete mode 100644 crypto/openssh/contrib/caldera/sshd.pam delete mode 100644 crypto/openssh/moduli.0 create mode 100644 crypto/openssh/opacket.c create mode 100644 crypto/openssh/opacket.h create mode 100644 crypto/openssh/openbsd-compat/.cvsignore create mode 100644 crypto/openssh/openbsd-compat/kludge-fd_set.c create mode 100644 crypto/openssh/openbsd-compat/md5.c create mode 100644 crypto/openssh/openbsd-compat/md5.h create mode 100644 crypto/openssh/openbsd-compat/reallocarray.c create mode 100644 crypto/openssh/openbsd-compat/regress/.cvsignore create mode 100644 crypto/openssh/openbsd-compat/regress/opensslvertest.c create mode 100644 crypto/openssh/openbsd-compat/rmd160.c create mode 100644 crypto/openssh/openbsd-compat/rmd160.h create mode 100644 crypto/openssh/openbsd-compat/sha1.c create mode 100644 crypto/openssh/openbsd-compat/sha1.h create mode 100644 crypto/openssh/regress/.cvsignore create mode 100755 crypto/openssh/regress/cfgparse.sh create mode 100755 crypto/openssh/regress/hostkey-agent.sh create mode 100755 crypto/openssh/regress/hostkey-rotate.sh create mode 100755 crypto/openssh/regress/keygen-knownhosts.sh create mode 100755 crypto/openssh/regress/limit-keytype.sh create mode 100755 crypto/openssh/regress/multipubkey.sh create mode 100644 crypto/openssh/regress/netcat.c create mode 100755 crypto/openssh/regress/principals-command.sh create mode 100644 crypto/openssh/regress/t11.ok create mode 100644 crypto/openssh/regress/unittests/Makefile create mode 100644 crypto/openssh/regress/unittests/Makefile.inc create mode 100644 crypto/openssh/regress/unittests/bitmap/Makefile create mode 100644 crypto/openssh/regress/unittests/bitmap/tests.c create mode 100644 crypto/openssh/regress/unittests/hostkeys/Makefile create mode 100755 crypto/openssh/regress/unittests/hostkeys/mktestdata.sh create mode 100644 crypto/openssh/regress/unittests/hostkeys/test_iterate.c create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/dsa_1.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/dsa_2.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/dsa_3.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/dsa_4.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/dsa_5.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/dsa_6.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_1.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_2.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_3.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_4.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_5.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_6.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_1.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_2.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_3.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_4.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_5.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_6.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/known_hosts create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_1.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_2.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_3.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_4.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_5.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_6.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa_1.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa_2.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa_3.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa_4.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa_5.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/testdata/rsa_6.pub create mode 100644 crypto/openssh/regress/unittests/hostkeys/tests.c create mode 100644 crypto/openssh/regress/unittests/kex/Makefile create mode 100644 crypto/openssh/regress/unittests/kex/test_kex.c create mode 100644 crypto/openssh/regress/unittests/kex/tests.c create mode 100644 crypto/openssh/regress/unittests/sshbuf/Makefile create mode 100644 crypto/openssh/regress/unittests/sshbuf/test_sshbuf.c create mode 100644 crypto/openssh/regress/unittests/sshbuf/test_sshbuf_fixed.c create mode 100644 crypto/openssh/regress/unittests/sshbuf/test_sshbuf_fuzz.c create mode 100644 crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_basic.c create mode 100644 crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c create mode 100644 crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c create mode 100644 crypto/openssh/regress/unittests/sshbuf/test_sshbuf_misc.c create mode 100644 crypto/openssh/regress/unittests/sshbuf/tests.c create mode 100644 crypto/openssh/regress/unittests/sshkey/Makefile create mode 100644 crypto/openssh/regress/unittests/sshkey/common.c create mode 100644 crypto/openssh/regress/unittests/sshkey/common.h create mode 100755 crypto/openssh/regress/unittests/sshkey/mktestdata.sh create mode 100644 crypto/openssh/regress/unittests/sshkey/test_file.c create mode 100644 crypto/openssh/regress/unittests/sshkey/test_fuzz.c create mode 100644 crypto/openssh/regress/unittests/sshkey/test_sshkey.c create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.g create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.priv create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_1_pw create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_2 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_n create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/dsa_n_pw create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.curve create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.priv create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1_pw create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.curve create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.priv create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_n create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_n_pw create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1_pw create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/pw create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.param.n create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1_pw create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.param.n create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.n create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.p create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.q create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_1_pw create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_2 create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp.bb create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.n create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.p create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.q create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.pub create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_n create mode 100644 crypto/openssh/regress/unittests/sshkey/testdata/rsa_n_pw create mode 100644 crypto/openssh/regress/unittests/sshkey/tests.c create mode 100644 crypto/openssh/regress/unittests/test_helper/Makefile create mode 100644 crypto/openssh/regress/unittests/test_helper/fuzz.c create mode 100644 crypto/openssh/regress/unittests/test_helper/test_helper.c create mode 100644 crypto/openssh/regress/unittests/test_helper/test_helper.h create mode 100755 crypto/openssh/regress/valgrind-unit.sh create mode 100644 crypto/openssh/scard/.cvsignore delete mode 100644 crypto/openssh/scp.0 delete mode 100644 crypto/openssh/sftp-server.0 delete mode 100644 crypto/openssh/sftp.0 delete mode 100644 crypto/openssh/ssh-add.0 delete mode 100644 crypto/openssh/ssh-agent.0 delete mode 100644 crypto/openssh/ssh-keygen.0 delete mode 100644 crypto/openssh/ssh-keyscan.0 delete mode 100644 crypto/openssh/ssh-keysign.0 delete mode 100644 crypto/openssh/ssh-pkcs11-helper.0 delete mode 100644 crypto/openssh/ssh.0 create mode 100644 crypto/openssh/ssh_api.c create mode 100644 crypto/openssh/ssh_api.h delete mode 100644 crypto/openssh/ssh_config.0 create mode 100644 crypto/openssh/sshbuf-getput-basic.c create mode 100644 crypto/openssh/sshbuf-getput-crypto.c create mode 100644 crypto/openssh/sshbuf-misc.c create mode 100644 crypto/openssh/sshbuf.c create mode 100644 crypto/openssh/sshbuf.h delete mode 100644 crypto/openssh/sshd.0 delete mode 100644 crypto/openssh/sshd_config.0 create mode 100644 crypto/openssh/ssherr.c create mode 100644 crypto/openssh/ssherr.h create mode 100644 crypto/openssh/sshkey.c create mode 100644 crypto/openssh/sshkey.h diff --git a/crypto/openssh/.cvsignore b/crypto/openssh/.cvsignore new file mode 100644 index 0000000..9baaa3b --- /dev/null +++ b/crypto/openssh/.cvsignore @@ -0,0 +1,28 @@ +*.0 +*.out +Makefile +autom4te.cache +buildit.sh +buildpkg.sh +config.cache +config.h +config.h.in +config.log +config.status +configure +openssh.xml +opensshd.init +scp +sftp +sftp-server +ssh +ssh-add +ssh-agent +ssh-keygen +ssh-keyscan +ssh-keysign +ssh-pkcs11-helper +sshd +stamp-h.in +survey +survey.sh diff --git a/crypto/openssh/ChangeLog b/crypto/openssh/ChangeLog index 38de846..35a1a76 100644 --- a/crypto/openssh/ChangeLog +++ b/crypto/openssh/ChangeLog @@ -1,2887 +1,7615 @@ -20140313 - - (djm) Release OpenSSH 6.6 - -20140304 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2014/03/03 22:22:30 - [session.c] - ignore enviornment variables with embedded '=' or '\0' characters; - spotted by Jann Horn; ok deraadt@ - -20140301 - - (djm) [regress/Makefile] Disable dhgex regress test; it breaks when - no moduli file exists at the expected location. - -20140228 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2014/02/27 00:41:49 - [bufbn.c] - fix unsigned overflow that could lead to reading a short ssh protocol - 1 bignum value; found by Ben Hawkes; ok deraadt@ - - djm@cvs.openbsd.org 2014/02/27 08:25:09 - [bufbn.c] - off by one in range check - - djm@cvs.openbsd.org 2014/02/27 22:47:07 - [sshd_config.5] - bz#2184 clarify behaviour of a keyword that appears in multiple - matching Match blocks; ok dtucker@ - - djm@cvs.openbsd.org 2014/02/27 22:57:40 - [version.h] - openssh-6.6 - - dtucker@cvs.openbsd.org 2014/01/19 23:43:02 - [regress/sftp-chroot.sh] - Don't use -q on sftp as it suppresses logging, instead redirect the - output to the regress logfile. - - dtucker@cvs.openbsd.org 2014/01/20 00:00:30 - [sregress/ftp-chroot.sh] - append to rather than truncating the log file - - dtucker@cvs.openbsd.org 2014/01/25 04:35:32 - [regress/Makefile regress/dhgex.sh] - Add a test for DH GEX sizes - - djm@cvs.openbsd.org 2014/01/26 10:22:10 - [regress/cert-hostkey.sh] - automatically generate revoked keys from listed keys rather than - manually specifying each type; from portable - (Id sync only) - - djm@cvs.openbsd.org 2014/01/26 10:49:17 - [scp-ssh-wrapper.sh scp.sh] - make sure $SCP is tested on the remote end rather than whichever one - happens to be in $PATH; from portable - (Id sync only) - - djm@cvs.openbsd.org 2014/02/27 20:04:16 - [login-timeout.sh] - remove any existing LoginGraceTime from sshd_config before adding - a specific one for the test back in - - djm@cvs.openbsd.org 2014/02/27 21:21:25 - [agent-ptrace.sh agent.sh] - keep return values that are printed in error messages; - from portable - (Id sync only) - - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec] - [contrib/suse/openssh.spec] Crank version numbers - - (djm) [regress/host-expand.sh] Add RCS Id - -20140227 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2014/02/26 20:18:37 - [ssh.c] - bz#2205: avoid early hostname lookups unless canonicalisation is enabled; - ok dtucker@ markus@ - - djm@cvs.openbsd.org 2014/02/26 20:28:44 - [auth2-gss.c gss-serv.c ssh-gss.h sshd.c] - bz#2107 - cache OIDs of supported GSSAPI mechanisms before privsep - sandboxing, as running this code in the sandbox can cause violations; - ok markus@ - - djm@cvs.openbsd.org 2014/02/26 20:29:29 - [channels.c] - don't assume that the socks4 username is \0 terminated; - spotted by Ben Hawkes; ok markus@ - - markus@cvs.openbsd.org 2014/02/26 21:53:37 - [sshd.c] - ssh_gssapi_prepare_supported_oids needs GSSAPI - -20140224 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2014/02/07 06:55:54 - [cipher.c mac.c] - remove some logging that makes ssh debugging output very verbose; - ok markus - - djm@cvs.openbsd.org 2014/02/15 23:05:36 - [channels.c] - avoid spurious "getsockname failed: Bad file descriptor" errors in ssh -W; - bz#2200, debian#738692 via Colin Watson; ok dtucker@ - - djm@cvs.openbsd.org 2014/02/22 01:32:19 - [readconf.c] - when processing Match blocks, skip 'exec' clauses if previous predicates - failed to match; ok markus@ - - djm@cvs.openbsd.org 2014/02/23 20:03:42 - [ssh-ed25519.c] - check for unsigned overflow; not reachable in OpenSSH but others might - copy our code... - - djm@cvs.openbsd.org 2014/02/23 20:11:36 - [readconf.c readconf.h ssh.c ssh_config.5] - reparse ssh_config and ~/.ssh/config if hostname canonicalisation changes - the hostname. This allows users to write configurations that always - refer to canonical hostnames, e.g. - - CanonicalizeHostname yes - CanonicalDomains int.example.org example.org - CanonicalizeFallbackLocal no - - Host *.int.example.org - Compression off - Host *.example.org - User djm - - ok markus@ +commit c88ac102f0eb89f2eaa314cb2e2e0ca3c890c443 +Author: Damien Miller +Date: Thu Jan 14 11:08:19 2016 +1100 + + bump version numbers + +commit 302bc21e6fadacb04b665868cd69b625ef69df90 +Author: Damien Miller +Date: Thu Jan 14 11:04:04 2016 +1100 + + openssh-7.1p2 + +commit 6b33763242c063e4e0593877e835eeb1fd1b60aa +Author: Damien Miller +Date: Thu Jan 14 11:02:58 2016 +1100 + + forcibly disable roaming support in the client + +commit 34d364f0d2e1e30a444009f0e04299bb7c94ba13 +Author: djm@openbsd.org +Date: Mon Oct 5 17:11:21 2015 +0000 + + upstream commit + + some more bzero->explicit_bzero, from Michael McConville + + Upstream-ID: 17f19545685c33327db2efdc357c1c9225ff00d0 + +commit 8f5b93026797b9f7fba90d0c717570421ccebbd3 +Author: guenther@openbsd.org +Date: Fri Sep 11 08:50:04 2015 +0000 + + upstream commit + + Use explicit_bzero() when zeroing before free() + + from Michael McConville (mmcconv1 (at) sccs.swarthmore.edu) + ok millert@ djm@ + + Upstream-ID: 2e3337db046c3fe70c7369ee31515ac73ec00f50 + +commit d77148e3a3ef6c29b26ec74331455394581aa257 +Author: djm@openbsd.org +Date: Sun Nov 8 21:59:11 2015 +0000 + + upstream commit + + fix OOB read in packet code caused by missing return + statement found by Ben Hawkes; ok markus@ deraadt@ + + Upstream-ID: a3e3a85434ebfa0690d4879091959591f30efc62 + +commit 076d849e17ab12603627f87b301e2dca71bae518 +Author: Damien Miller +Date: Sat Nov 14 18:44:49 2015 +1100 + + read back from libcrypto RAND when privdropping + + makes certain libcrypto implementations cache a /dev/urandom fd + in preparation of sandboxing. Based on patch by Greg Hartman. + +commit f72adc0150011a28f177617a8456e1f83733099d +Author: djm@openbsd.org +Date: Sun Dec 13 22:42:23 2015 +0000 + + upstream commit + + unbreak connections with peers that set + first_kex_follows; fix from Matt Johnston va bz#2515 + + Upstream-ID: decc88ec4fc7515594fdb42b04aa03189a44184b + +commit 04bd8d019ccd906cac1a2b362517b8505f3759e6 +Author: djm@openbsd.org +Date: Tue Jan 12 23:42:54 2016 +0000 + + upstream commit + + use explicit_bzero() more liberally in the buffer code; ok + deraadt + + Upstream-ID: 0ece37069fd66bc6e4f55eb1321f93df372b65bf + +commit e91346dc2bbf460246df2ab591b7613908c1b0ad +Author: Damien Miller +Date: Fri Aug 21 14:49:03 2015 +1000 + + we don't use Github for issues/pull-requests + +commit a4f5b507c708cc3dc2c8dd2d02e4416d7514dc23 +Author: Damien Miller +Date: Fri Aug 21 14:43:55 2015 +1000 + + fix URL for connect.c + +commit d026a8d3da0f8186598442997c7d0a28e7275414 +Author: Damien Miller +Date: Fri Aug 21 13:47:10 2015 +1000 + + update version numbers for 7.1 + +commit 78f8f589f0ca1c9f41e5a9bae3cda5ce8a6b42ed +Author: djm@openbsd.org +Date: Fri Aug 21 03:45:26 2015 +0000 + + upstream commit + + openssh-7.1 + + Upstream-ID: ff7b1ef4b06caddfb45e08ba998128c88be3d73f + +commit 32a181980c62fce94f7f9ffaf6a79d90f0c309cf +Author: djm@openbsd.org +Date: Fri Aug 21 03:42:19 2015 +0000 + + upstream commit + + fix inverted logic that broke PermitRootLogin; reported + by Mantas Mikulenas; ok markus@ + + Upstream-ID: 260dd6a904c1bb7e43267e394b1c9cf70bdd5ea5 + +commit ce445b0ed927e45bd5bdce8f836eb353998dd65c +Author: deraadt@openbsd.org +Date: Thu Aug 20 22:32:42 2015 +0000 + + upstream commit + + Do not cast result of malloc/calloc/realloc* if stdlib.h + is in scope ok krw millert + + Upstream-ID: 5e50ded78cadf3841556649a16cc4b1cb6c58667 + +commit 05291e5288704d1a98bacda269eb5a0153599146 +Author: naddy@openbsd.org +Date: Thu Aug 20 19:20:06 2015 +0000 + + upstream commit + + In the certificates section, be consistent about using + "host_key" and "user_key" for the respective key types. ok sthen@ deraadt@ + + Upstream-ID: 9e037ea3b15577b238604c5533e082a3947f13cb + +commit 8543d4ef6f2e9f98c3e6b77c894ceec30c5e4ae4 +Author: djm@openbsd.org +Date: Wed Aug 19 23:21:42 2015 +0000 + + upstream commit + + Better compat matching for WinSCP, add compat matching + for FuTTY (fork of PuTTY); ok markus@ deraadt@ + + Upstream-ID: 24001d1ac115fa3260fbdc329a4b9aeb283c5389 + +commit ec6eda16ebab771aa3dfc90629b41953b999cb1e +Author: djm@openbsd.org +Date: Wed Aug 19 23:19:01 2015 +0000 + + upstream commit + + fix double-free() in error path of DSA key generation + reported by Mateusz Kocielski; ok markus@ + + Upstream-ID: 4735d8f888b10599a935fa1b374787089116713c + +commit 45b0eb752c94954a6de046bfaaf129e518ad4b5b +Author: djm@openbsd.org +Date: Wed Aug 19 23:18:26 2015 +0000 + + upstream commit + + fix free() of uninitialised pointer reported by Mateusz + Kocielski; ok markus@ + + Upstream-ID: 519552b050618501a06b7b023de5cb104e2c5663 + +commit c837643b93509a3ef538cb6624b678c5fe32ff79 +Author: djm@openbsd.org +Date: Wed Aug 19 23:17:51 2015 +0000 + + upstream commit + + fixed unlink([uninitialised memory]) reported by Mateusz + Kocielski; ok markus@ + + Upstream-ID: 14a0c4e7d891f5a8dabc4b89d4f6b7c0d5a20109 + +commit 1f8d3d629cd553031021068eb9c646a5f1e50994 +Author: jmc@openbsd.org +Date: Fri Aug 14 15:32:41 2015 +0000 + + upstream commit + + match myproposal.h order; from brian conway (i snuck in a + tweak while here) + + ok dtucker + + Upstream-ID: 35174a19b5237ea36aa3798f042bf5933b772c67 + +commit 1dc8d93ce69d6565747eb44446ed117187621b26 +Author: deraadt@openbsd.org +Date: Thu Aug 6 14:53:21 2015 +0000 + + upstream commit + + add prohibit-password as a synonymn for without-password, + since the without-password is causing too many questions. Harden it to ban + all but pubkey, hostbased, and GSSAPI auth (when the latter is enabled) from + djm, ok markus + + Upstream-ID: d53317d7b28942153e6236d3fd6e12ceb482db7a + +commit 90a95a4745a531b62b81ce3b025e892bdc434de5 +Author: Damien Miller +Date: Tue Aug 11 13:53:41 2015 +1000 + + update version in README + +commit 318c37743534b58124f1bab37a8a0087a3a9bd2f +Author: Damien Miller +Date: Tue Aug 11 13:53:09 2015 +1000 + + update versions in *.spec + +commit 5e75f5198769056089fb06c4d738ab0e5abc66f7 +Author: Damien Miller +Date: Tue Aug 11 13:34:12 2015 +1000 + + set sshpam_ctxt to NULL after free + + Avoids use-after-free in monitor when privsep child is compromised. + Reported by Moritz Jodeit; ok dtucker@ + +commit d4697fe9a28dab7255c60433e4dd23cf7fce8a8b +Author: Damien Miller +Date: Tue Aug 11 13:33:24 2015 +1000 + + Don't resend username to PAM; it already has it. + + Pointed out by Moritz Jodeit; ok dtucker@ + +commit 88763a6c893bf3dfe951ba9271bf09715e8d91ca +Author: Darren Tucker +Date: Mon Jul 27 12:14:25 2015 +1000 + + Import updated moduli file from OpenBSD. + +commit 55b263fb7cfeacb81aaf1c2036e0394c881637da +Author: Damien Miller +Date: Mon Aug 10 11:13:44 2015 +1000 + + let principals-command.sh work for noexec /var/run + +commit 2651e34cd11b1aac3a0fe23b86d8c2ff35c07897 +Author: Damien Miller +Date: Thu Aug 6 11:43:42 2015 +1000 + + work around echo -n / sed behaviour in tests + +commit d85dad81778c1aa8106acd46930b25fdf0d15b2a +Author: djm@openbsd.org +Date: Wed Aug 5 05:27:33 2015 +0000 + + upstream commit + + adjust for RSA minimum modulus switch; ok deraadt@ + + Upstream-Regress-ID: 5a72c83431b96224d583c573ca281cd3a3ebfdae + +commit 57e8e229bad5fe6056b5f1199665f5f7008192c6 +Author: djm@openbsd.org +Date: Tue Aug 4 05:23:06 2015 +0000 + + upstream commit + + backout SSH_RSA_MINIMUM_MODULUS_SIZE increase for this + release; problems spotted by sthen@ ok deraadt@ markus@ + + Upstream-ID: d0bd60dde9e8c3cd7030007680371894c1499822 + +commit f097d0ea1e0889ca0fa2e53a00214e43ab7fa22a +Author: djm@openbsd.org +Date: Sun Aug 2 09:56:42 2015 +0000 + + upstream commit + + openssh 7.0; ok deraadt@ + + Upstream-ID: c63afdef537f57f28ae84145c5a8e29e9250221f + +commit 3d5728a0f6874ce4efb16913a12963595070f3a9 +Author: chris@openbsd.org +Date: Fri Jul 31 15:38:09 2015 +0000 + + upstream commit + + Allow PermitRootLogin to be overridden by config + + ok markus@ deeradt@ + + Upstream-ID: 5cf3e26ed702888de84e2dc9d0054ccf4d9125b4 + +commit 6f941396b6835ad18018845f515b0c4fe20be21a +Author: djm@openbsd.org +Date: Thu Jul 30 23:09:15 2015 +0000 + + upstream commit + + fix pty permissions; patch from Nikolay Edigaryev; ok + deraadt + + Upstream-ID: 40ff076d2878b916fbfd8e4f45dbe5bec019e550 + +commit f4373ed1e8fbc7c8ce3fc4ea97d0ba2e0c1d7ef0 +Author: deraadt@openbsd.org +Date: Thu Jul 30 19:23:02 2015 +0000 + + upstream commit + + change default: PermitRootLogin without-password matching + install script changes coming as well ok djm markus + + Upstream-ID: 0e2a6c4441daf5498b47a61767382bead5eb8ea6 + +commit 0c30ba91f87fcda7e975e6ff8a057f624e87ea1c +Author: Damien Miller +Date: Thu Jul 30 12:31:39 2015 +1000 + + downgrade OOM adjustment logging: verbose -> debug + +commit f9eca249d4961f28ae4b09186d7dc91de74b5895 +Author: djm@openbsd.org +Date: Thu Jul 30 00:01:34 2015 +0000 + + upstream commit + + Allow ssh_config and sshd_config kex parameters options be + prefixed by a '+' to indicate that the specified items be appended to the + default rather than replacing it. + + approach suggested by dtucker@, feedback dlg@, ok markus@ + + Upstream-ID: 0f901137298fc17095d5756ff1561a7028e8882a + +commit 5cefe769105a2a2e3ca7479d28d9a325d5ef0163 +Author: djm@openbsd.org +Date: Wed Jul 29 08:34:54 2015 +0000 + + upstream commit + + fix bug in previous; was printing incorrect string for + failed host key algorithms negotiation + + Upstream-ID: 22c0dc6bc61930513065d92e11f0753adc4c6e6e + +commit f319912b0d0e1675b8bb051ed8213792c788bcb2 +Author: djm@openbsd.org +Date: Wed Jul 29 04:43:06 2015 +0000 + + upstream commit + + include the peer's offer when logging a failure to + negotiate a mutual set of algorithms (kex, pubkey, ciphers, etc.) ok markus@ + + Upstream-ID: bbb8caabf5c01790bb845f5ce135565248d7c796 + +commit b6ea0e573042eb85d84defb19227c89eb74cf05a +Author: djm@openbsd.org +Date: Tue Jul 28 23:20:42 2015 +0000 + + upstream commit + + add Cisco to the list of clients that choke on the + hostkeys update extension. Pointed out by Howard Kash + + Upstream-ID: c9eadde28ecec056c73d09ee10ba4570dfba7e84 + +commit 3f628c7b537291c1019ce86af90756fb4e66d0fd +Author: guenther@openbsd.org +Date: Mon Jul 27 16:29:23 2015 +0000 + + upstream commit + + Permit kbind(2) use in the sandbox now, to ease testing + of ld.so work using it + + reminded by miod@, ok deraadt@ + + Upstream-ID: 523922e4d1ba7a091e3824e77a8a3c818ee97413 + +commit ebe27ebe520098bbc0fe58945a87ce8490121edb +Author: millert@openbsd.org +Date: Mon Jul 20 18:44:12 2015 +0000 + + upstream commit + + Move .Pp before .Bl, not after to quiet mandoc -Tlint. + Noticed by jmc@ + + Upstream-ID: 59fadbf8407cec4e6931e50c53cfa0214a848e23 + +commit d5d91d0da819611167782c66ab629159169d94d4 +Author: millert@openbsd.org +Date: Mon Jul 20 18:42:35 2015 +0000 + + upstream commit + + Sync usage with SYNOPSIS + + Upstream-ID: 7a321a170181a54f6450deabaccb6ef60cf3f0b7 + +commit 79ec2142fbc68dd2ed9688608da355fc0b1ed743 +Author: millert@openbsd.org +Date: Mon Jul 20 15:39:52 2015 +0000 + + upstream commit + + Better desciption of Unix domain socket forwarding. + bz#2423; ok jmc@ + + Upstream-ID: 85e28874726897e3f26ae50dfa2e8d2de683805d + +commit d56fd1828074a4031b18b8faa0bf949669eb18a0 +Author: Damien Miller +Date: Mon Jul 20 11:19:51 2015 +1000 + + make realpath.c compile -Wsign-compare clean + +commit c63c9a691dca26bb7648827f5a13668832948929 +Author: djm@openbsd.org +Date: Mon Jul 20 00:30:01 2015 +0000 + + upstream commit + + mention that the default of UseDNS=no implies that + hostnames cannot be used for host matching in sshd_config and + authorized_keys; bz#2045, ok dtucker@ + + Upstream-ID: 0812705d5f2dfa59aab01f2764ee800b1741c4e1 + +commit 63ebcd0005e9894fcd6871b7b80aeea1fec0ff76 +Author: djm@openbsd.org +Date: Sat Jul 18 08:02:17 2015 +0000 + + upstream commit + + don't ignore PKCS#11 hosted keys that return empty + CKA_ID; patch by Jakub Jelen via bz#2429; ok markus + + Upstream-ID: 2f7c94744eb0342f8ee8bf97b2351d4e00116485 + +commit b15fd989c8c62074397160147a8d5bc34b3f3c63 +Author: djm@openbsd.org +Date: Sat Jul 18 08:00:21 2015 +0000 + + upstream commit + + skip uninitialised PKCS#11 slots; patch from Jakub Jelen + in bz#2427 ok markus@ + + Upstream-ID: 744c1e7796e237ad32992d0d02148e8a18f27d29 + +commit 5b64f85bb811246c59ebab70aed331f26ba37b18 +Author: djm@openbsd.org +Date: Sat Jul 18 07:57:14 2015 +0000 + + upstream commit + + only query each keyboard-interactive device once per + authentication request regardless of how many times it is listed; ok markus@ + + Upstream-ID: d73fafba6e86030436ff673656ec1f33d9ffeda1 + +commit cd7324d0667794eb5c236d8a4e0f236251babc2d +Author: djm@openbsd.org +Date: Fri Jul 17 03:34:27 2015 +0000 + + upstream commit + + remove -u flag to diff (only used for error output) to make + things easier for -portable + + Upstream-Regress-ID: a5d6777d2909540d87afec3039d9bb2414ade548 + +commit deb8d99ecba70b67f4af7880b11ca8768df9ec3a +Author: djm@openbsd.org +Date: Fri Jul 17 03:09:19 2015 +0000 + + upstream commit + + direct-streamlocal@openssh.com Unix domain foward + messages do not contain a "reserved for future use" field and in fact, + serverloop.c checks that there isn't one. Remove erroneous mention from + PROTOCOL description. bz#2421 from Daniel Black + + Upstream-ID: 3d51a19e64f72f764682f1b08f35a8aa810a43ac + +commit 356b61f365405b5257f5b2ab446e5d7bd33a7b52 +Author: djm@openbsd.org +Date: Fri Jul 17 03:04:27 2015 +0000 + + upstream commit + + describe magic for setting up Unix domain socket fowards + via the mux channel; bz#2422 patch from Daniel Black + + Upstream-ID: 943080fe3864715c423bdeb7c920bb30c4eee861 + +commit d3e2aee41487d55b8d7d40f538b84ff1db7989bc +Author: Darren Tucker +Date: Fri Jul 17 12:52:34 2015 +1000 + + Check if realpath works on nonexistent files. + + On some platforms the native realpath doesn't work with non-existent + files (this is actually specified in some versions of POSIX), however + the sftp spec says its realpath with "canonicalize any given path name". + On those platforms, use realpath from the compat library. + + In addition, when compiling with -DFORTIFY_SOURCE, glibc redefines + the realpath symbol to the checked version, so redefine ours to + something else so we pick up the compat version we want. + + bz#2428, ok djm@ + +commit 25b14610dab655646a109db5ef8cb4c4bf2a48a0 +Author: djm@openbsd.org +Date: Fri Jul 17 02:47:45 2015 +0000 + + upstream commit + + fix incorrect test for SSH1 keys when compiled without SSH1 + support + + Upstream-ID: 6004d720345b8e481c405e8ad05ce2271726e451 + +commit df56a8035d429b2184ee94aaa7e580c1ff67f73a +Author: djm@openbsd.org +Date: Wed Jul 15 08:00:11 2015 +0000 + + upstream commit + + fix NULL-deref when SSH1 reenabled + + Upstream-ID: f22fd805288c92b3e9646782d15b48894b2d5295 + +commit 41e38c4d49dd60908484e6703316651333f16b93 +Author: djm@openbsd.org +Date: Wed Jul 15 07:19:50 2015 +0000 + + upstream commit + + regen RSA1 test keys; the last batch was missing their + private parts + + Upstream-Regress-ID: 7ccf437305dd63ff0b48dd50c5fd0f4d4230c10a + +commit 5bf0933184cb622ca3f96d224bf3299fd2285acc +Author: markus@openbsd.org +Date: Fri Jul 10 06:23:25 2015 +0000 + + upstream commit + + Adapt tests, now that DSA if off by default; use + PubkeyAcceptedKeyTypes and PubkeyAcceptedKeyTypes to test DSA. + + Upstream-Regress-ID: 0ff2a3ff5ac1ce5f92321d27aa07b98656efcc5c + +commit 7a6e3fd7b41dbd3756b6bf9acd67954c0b1564cc +Author: markus@openbsd.org +Date: Tue Jul 7 14:54:16 2015 +0000 + + upstream commit + + regen test data after mktestdata.sh changes + + Upstream-Regress-ID: 3495ecb082b9a7c048a2d7c5c845d3bf181d25a4 + +commit 7c8c174c69f681d4910fa41c37646763692b28e2 +Author: markus@openbsd.org +Date: Tue Jul 7 14:53:30 2015 +0000 + + upstream commit + + adapt tests to new minimum RSA size and default FP format + + Upstream-Regress-ID: a4b30afd174ce82b96df14eb49fb0b81398ffd0e + +commit 6a977a4b68747ade189e43d302f33403fd4a47ac +Author: djm@openbsd.org +Date: Fri Jul 3 04:39:23 2015 +0000 + + upstream commit + + legacy v00 certificates are gone; adapt and don't try to + test them; "sure" markus@ dtucker@ + + Upstream-Regress-ID: c57321e69b3cd4a3b3396dfcc43f0803d047da12 + +commit 0c4123ad5e93fb90fee9c6635b13a6cdabaac385 +Author: djm@openbsd.org +Date: Wed Jul 1 23:11:18 2015 +0000 + + upstream commit + + don't expect SSH v.1 in unittests + + Upstream-Regress-ID: f8812b16668ba78e6a698646b2a652b90b653397 + +commit 3c099845798a817cdde513c39074ec2063781f18 +Author: djm@openbsd.org +Date: Mon Jun 15 06:38:50 2015 +0000 + + upstream commit + + turn SSH1 back on to match src/usr.bin/ssh being tested + + Upstream-Regress-ID: 6c4f763a2f0cc6893bf33983919e9030ae638333 + +commit b1dc2b33689668c75e95f873a42d5aea1f4af1db +Author: dtucker@openbsd.org +Date: Mon Jul 13 04:57:14 2015 +0000 + + upstream commit + + Add "PuTTY_Local:" to the clients to which we do not + offer DH-GEX. This was the string that was used for development versions + prior to September 2014 and they don't do RFC4419 DH-GEX, but unfortunately + there are some extant products based on those versions. bx2424 from Jay + Rouman, ok markus@ djm@ + + Upstream-ID: be34d41e18b966832fe09ca243d275b81882e1d5 + +commit 3a1638dda19bbc73d0ae02b4c251ce08e564b4b9 +Author: markus@openbsd.org +Date: Fri Jul 10 06:21:53 2015 +0000 + + upstream commit + + Turn off DSA by default; add HostKeyAlgorithms to the + server and PubkeyAcceptedKeyTypes to the client side, so it still can be + tested or turned back on; feedback and ok djm@ + + Upstream-ID: 8450a9e6d83f80c9bfed864ff061dfc9323cec21 + +commit 16db0a7ee9a87945cc594d13863cfcb86038db59 +Author: markus@openbsd.org +Date: Thu Jul 9 09:49:46 2015 +0000 + + upstream commit + + re-enable ed25519-certs if compiled w/o openssl; ok djm + + Upstream-ID: e10c90808b001fd2c7a93778418e9b318f5c4c49 + +commit c355bf306ac33de6545ce9dac22b84a194601e2f +Author: markus@openbsd.org +Date: Wed Jul 8 20:24:02 2015 +0000 + + upstream commit + + no need to include the old buffer/key API + + Upstream-ID: fb13c9f7c0bba2545f3eb0a0e69cb0030819f52b + +commit a3cc48cdf9853f1e832d78cb29bedfab7adce1ee +Author: markus@openbsd.org +Date: Wed Jul 8 19:09:25 2015 +0000 + + upstream commit + + typedefs for Cipher&CipherContext are unused + + Upstream-ID: 50e6a18ee92221d23ad173a96d5b6c42207cf9a7 + +commit a635bd06b5c427a57c3ae760d3a2730bb2c863c0 +Author: markus@openbsd.org +Date: Wed Jul 8 19:04:21 2015 +0000 + + upstream commit + + xmalloc.h is unused + + Upstream-ID: afb532355b7fa7135a60d944ca1e644d1d63cb58 + +commit 2521cf0e36c7f3f6b19f206da0af134f535e4a31 +Author: markus@openbsd.org +Date: Wed Jul 8 19:01:15 2015 +0000 + + upstream commit + + compress.c is gone + + Upstream-ID: 174fa7faa9b9643cba06164b5e498591356fbced + +commit c65a7aa6c43aa7a308ee1ab8a96f216169ae9615 +Author: djm@openbsd.org +Date: Fri Jul 3 04:05:54 2015 +0000 + + upstream commit + + another SSH_RSA_MINIMUM_MODULUS_SIZE that needed + cranking + + Upstream-ID: 9d8826cafe96aab4ae8e2f6fd22800874b7ffef1 + +commit b1f383da5cd3cb921fc7776f17a14f44b8a31757 +Author: djm@openbsd.org +Date: Fri Jul 3 03:56:25 2015 +0000 + + upstream commit + + add an XXX reminder for getting correct key paths from + sshd_config + + Upstream-ID: feae52b209d7782ad742df04a4260e9fe41741db + +commit 933935ce8d093996c34d7efa4d59113163080680 +Author: djm@openbsd.org +Date: Fri Jul 3 03:49:45 2015 +0000 + + upstream commit + + refuse to generate or accept RSA keys smaller than 1024 + bits; feedback and ok dtucker@ + + Upstream-ID: 7ea3d31271366ba264f06e34a3539bf1ac30f0ba + +commit bdfd29f60b74f3e678297269dc6247a5699583c1 +Author: djm@openbsd.org +Date: Fri Jul 3 03:47:00 2015 +0000 + + upstream commit + + turn off 1024 bit diffie-hellman-group1-sha1 key + exchange method (already off in server, this turns it off in the client by + default too) ok dtucker@ + + Upstream-ID: f59b88f449210ab7acf7d9d88f20f1daee97a4fa + +commit c28fc62d789d860c75e23a9fa9fb250eb2beca57 +Author: djm@openbsd.org +Date: Fri Jul 3 03:43:18 2015 +0000 + + upstream commit + + delete support for legacy v00 certificates; "sure" + markus@ dtucker@ + + Upstream-ID: b5b9bb5f9202d09e88f912989d74928601b6636f + +commit 564d63e1b4a9637a209d42a9d49646781fc9caef +Author: djm@openbsd.org +Date: Wed Jul 1 23:10:47 2015 +0000 + + upstream commit + + Compile-time disable SSH v.1 again + + Upstream-ID: 1d4b513a3a06232f02650b73bad25100d1b800af + +commit 868109b650504dd9bcccdb1f51d0906f967c20ff +Author: djm@openbsd.org +Date: Wed Jul 1 02:39:06 2015 +0000 + + upstream commit + + twiddle PermitRootLogin back + + Upstream-ID: 2bd23976305d0512e9f84d054e1fc23cd70b89f2 + +commit 7de4b03a6e4071d454b72927ffaf52949fa34545 +Author: djm@openbsd.org +Date: Wed Jul 1 02:32:17 2015 +0000 + + upstream commit + + twiddle; (this commit marks the openssh-6.9 release) + + Upstream-ID: 78500582819f61dd8adee36ec5cc9b9ac9351234 + +commit 1bf477d3cdf1a864646d59820878783d42357a1d +Author: djm@openbsd.org +Date: Wed Jul 1 02:26:31 2015 +0000 + + upstream commit + + better refuse ForwardX11Trusted=no connections attempted + after ForwardX11Timeout expires; reported by Jann Horn + + Upstream-ID: bf0fddadc1b46a0334e26c080038313b4b6dea21 + +commit 47aa7a0f8551b471fcae0447c1d78464f6dba869 +Author: djm@openbsd.org +Date: Wed Jul 1 01:56:13 2015 +0000 + + upstream commit + + put back default PermitRootLogin=no + + Upstream-ID: 7bdedd5cead99c57ed5571f3b6b7840922d5f728 + +commit 984b064fe2a23733733262f88d2e1b2a1a501662 +Author: djm@openbsd.org +Date: Wed Jul 1 01:55:13 2015 +0000 + + upstream commit + + openssh-6.9 + + Upstream-ID: 6cfe8e1904812531080e6ab6e752d7001b5b2d45 + +commit d921082ed670f516652eeba50705e1e9f6325346 +Author: djm@openbsd.org +Date: Wed Jul 1 01:55:00 2015 +0000 + + upstream commit + + reset default PermitRootLogin to 'yes' (momentarily, for + release) + + Upstream-ID: cad8513527066e65dd7a1c16363d6903e8cefa24 + +commit 66295e0e1ba860e527f191b6325d2d77dec4dbce +Author: Damien Miller +Date: Wed Jul 1 11:49:12 2015 +1000 + + crank version numbers for release + +commit 37035c07d4f26bb1fbe000d2acf78efdb008681d +Author: Damien Miller +Date: Wed Jul 1 10:49:37 2015 +1000 + + s/--with-ssh1/--without-ssh1/ + +commit 629df770dbadc2accfbe1c81b3f31f876d0acd84 +Author: djm@openbsd.org +Date: Tue Jun 30 05:25:07 2015 +0000 + + upstream commit + + fatal() when a remote window update causes the window + value to overflow. Reported by Georg Wicherski, ok markus@ + + Upstream-ID: ead397a9aceb3bf74ebfa5fcaf259d72e569f351 + +commit f715afebe735d61df3fd30ad72d9ac1c8bd3b5f2 +Author: djm@openbsd.org +Date: Tue Jun 30 05:23:25 2015 +0000 + + upstream commit + + Fix math error in remote window calculations that causes + eventual stalls for datagram channels. Reported by Georg Wicherski, ok + markus@ + + Upstream-ID: be54059d11bf64e0d85061f7257f53067842e2ab + +commit 52fb6b9b034fcfd24bf88cc7be313e9c31de9889 +Author: Damien Miller +Date: Tue Jun 30 16:05:40 2015 +1000 + + skip IPv6-related portions on hosts without IPv6 + + with Tim Rice + +commit 512caddf590857af6aa12218461b5c0441028cf5 +Author: djm@openbsd.org +Date: Mon Jun 29 22:35:12 2015 +0000 + + upstream commit + + add getpid to sandbox, reachable by grace_alarm_handler + + reported by Jakub Jelen; bz#2419 + + Upstream-ID: d0da1117c16d4c223954995d35b0f47c8f684cd8 + +commit 78c2a4f883ea9aba866358e2acd9793a7f42ca93 +Author: djm@openbsd.org +Date: Fri Jun 26 05:13:20 2015 +0000 + + upstream commit + + Fix \-escaping bug that caused forward path parsing to skip + two characters and skip past the end of the string. + + Based on patch by Salvador Fandino; ok dtucker@ + + Upstream-ID: 7b879dc446335677cbe4cb549495636a0535f3bd + +commit bc20205c91c9920361d12b15d253d4997dba494a +Author: Damien Miller +Date: Thu Jun 25 09:51:39 2015 +1000 + + add missing pselect6 + + patch from Jakub Jelen + +commit 9d27fb73b4a4e5e99cb880af790d5b1ce44f720a +Author: djm@openbsd.org +Date: Wed Jun 24 23:47:23 2015 +0000 + + upstream commit + + correct test to sshkey_sign(); spotted by Albert S. + + Upstream-ID: 5f7347f40f0ca6abdaca2edb3bd62f4776518933 + +commit 7ed01a96a1911d8b4a9ef4f3d064e1923bfad7e3 +Author: dtucker@openbsd.org +Date: Wed Jun 24 01:49:19 2015 +0000 + + upstream commit + + Revert previous commit. We still want to call setgroups + in the case where there are zero groups to remove any that we might otherwise + inherit (as pointed out by grawity at gmail.com) and since the 2nd argument + to setgroups is always a static global it's always valid to dereference in + this case. ok deraadt@ djm@ + + Upstream-ID: 895b5ac560a10befc6b82afa778641315725fd01 + +commit 882f8bf94f79528caa65b0ba71c185d705bb7195 +Author: dtucker@openbsd.org +Date: Wed Jun 24 01:49:19 2015 +0000 + + upstream commit + + Revert previous commit. We still want to call setgroups in + the case where there are zero groups to remove any that we might otherwise + inherit (as pointed out by grawity at gmail.com) and since the 2nd argument + to setgroups is always a static global it's always valid to dereference in + this case. ok deraadt@ djm@ + + Upstream-ID: 895b5ac560a10befc6b82afa778641315725fd01 + +commit 9488538a726951e82b3a4374f3c558d72c80a89b +Author: djm@openbsd.org +Date: Mon Jun 22 23:42:16 2015 +0000 + + upstream commit + + Don't count successful partial authentication as failures + in monitor; this may have caused the monitor to refuse multiple + authentications that would otherwise have successfully completed; ok markus@ + + Upstream-ID: eb74b8e506714d0f649bd5c300f762a527af04a3 + +commit 63b78d003bd8ca111a736e6cea6333da50f5f09b +Author: dtucker@openbsd.org +Date: Mon Jun 22 12:29:57 2015 +0000 + + upstream commit + + Don't call setgroups if we have zero groups; there's no + guarantee that it won't try to deref the pointer. Based on a patch from mail + at quitesimple.org, ok djm deraadt + + Upstream-ID: 2fff85e11d7a9a387ef7fddf41fbfaf566708ab1 + +commit 5c15e22c691c79a47747bcf5490126656f97cecd +Author: Damien Miller +Date: Thu Jun 18 15:07:56 2015 +1000 + + fix syntax error + +commit 596dbca82f3f567fb3d2d69af4b4e1d3ba1e6403 +Author: jsing@openbsd.org +Date: Mon Jun 15 18:44:22 2015 +0000 + + upstream commit + + If AuthorizedPrincipalsCommand is specified, however + AuthorizedPrincipalsFile is not (or is set to "none"), authentication will + potentially fail due to key_cert_check_authority() failing to locate a + principal that matches the username, even though an authorized principal has + already been matched in the output of the subprocess. Fix this by using the + same logic to determine if pw->pw_name should be passed, as is used to + determine if a authorized principal must be matched earlier on. + + ok djm@ + + Upstream-ID: 43b42302ec846b0ea68aceb40677245391b9409d + +commit aff3e94c0d75d0d0fa84ea392b50ab04f8c57905 +Author: jsing@openbsd.org +Date: Mon Jun 15 18:42:19 2015 +0000 + + upstream commit + + Make the arguments to match_principals_command() similar + to match_principals_file(), by changing the last argument a struct + sshkey_cert * and dereferencing key->cert in the caller. + + No functional change. + + ok djm@ + + Upstream-ID: 533f99b844b21b47342b32b62e198dfffcf8651c + +commit 97e2e1596c202a4693468378b16b2353fd2d6c5e +Author: Damien Miller +Date: Wed Jun 17 14:36:54 2015 +1000 + + trivial optimisation for seccomp-bpf + + When doing arg inspection and the syscall doesn't match, skip + past the instruction that reloads the syscall into the accumulator, + since the accumulator hasn't been modified at this point. + +commit 99f33d7304893bd9fa04d227cb6e870171cded19 +Author: Damien Miller +Date: Wed Jun 17 10:50:51 2015 +1000 + + aarch64 support for seccomp-bpf sandbox + + Also resort and tidy syscall list. Based on patches by Jakub Jelen + bz#2361; ok dtucker@ + +commit 4ef702e1244633c1025ec7cfe044b9ab267097bf +Author: djm@openbsd.org +Date: Mon Jun 15 01:32:50 2015 +0000 + + upstream commit + + return failure on RSA signature error; reported by Albert S + + Upstream-ID: e61bb93dbe0349625807b0810bc213a6822121fa + +commit a170f22baf18af0b1acf2788b8b715605f41a1f9 +Author: Tim Rice +Date: Tue Jun 9 22:41:13 2015 -0700 + + Fix t12 rules for out of tree builds. + +commit ec04dc4a5515c913121bc04ed261857e68fa5c18 +Author: millert@openbsd.org +Date: Fri Jun 5 15:13:13 2015 +0000 + + upstream commit + + For "ssh -L 12345:/tmp/sock" don't fail with "No forward host + name." (we have a path, not a host name). Based on a diff from Jared + Yanovich. OK djm@ + + Upstream-ID: 2846b0a8c7de037e33657f95afbd282837fc213f + +commit 732d61f417a6aea0aa5308b59cb0f563bcd6edd6 +Author: djm@openbsd.org +Date: Fri Jun 5 03:44:14 2015 +0000 + + upstream commit + + typo: accidental repetition; bz#2386 + + Upstream-ID: 45e620d99f6bc301e5949d34a54027374991c88b + +commit adfb24c69d1b6f5e758db200866c711e25a2ba73 +Author: Darren Tucker +Date: Fri Jun 5 14:51:40 2015 +1000 + + Add Linux powerpc64le and powerpcle entries. + + Stopgap to resolve bz#2409 because we are so close to release and will + update config.guess and friends shortly after the release. ok djm@ + +commit a1195a0fdc9eddddb04d3e9e44c4775431cb77da +Merge: 6397eed d2480bc +Author: Tim Rice +Date: Wed Jun 3 21:43:13 2015 -0700 + + Merge branch 'master' of git.mindrot.org:/var/git/openssh + +commit 6397eedf953b2b973d2d7cbb504ab501a07f8ddc +Author: Tim Rice +Date: Wed Jun 3 21:41:11 2015 -0700 + + Remove unneeded backslashes. Patch from Ãngel González + +commit d2480bcac1caf31b03068de877a47d6e1027bf6d +Author: Darren Tucker +Date: Thu Jun 4 14:10:55 2015 +1000 + + Remove redundant include of stdarg.h. bz#2410 + +commit 5e67859a623826ccdf2df284cbb37e2d8e2787eb +Author: djm@openbsd.org +Date: Tue Jun 2 09:10:40 2015 +0000 + + upstream commit + + mention CheckHostIP adding addresses to known_hosts; + bz#1993; ok dtucker@ + + Upstream-ID: fd44b68440fd0dc29abf9f2d3f703d74a2396cb7 + +commit d7a58bbac6583e33fd5eca8e2c2cc70c57617818 +Author: Darren Tucker +Date: Tue Jun 2 20:15:26 2015 +1000 + + Replace strcpy with strlcpy. + + ok djm, sanity check by Corinna Vinschen. + +commit 51a1c2115265c6e80ede8a5c9dccada9aeed7143 +Author: Damien Miller +Date: Fri May 29 18:27:21 2015 +1000 + + skip, rather than fatal when run without SUDO set + +commit 599f01142a376645b15cbc9349d7e8975e1cf245 +Author: Damien Miller +Date: Fri May 29 18:03:15 2015 +1000 + + fix merge botch that left ",," in KEX algs + +commit 0c2a81dfc21822f2423edd30751e5ec53467b347 +Author: Damien Miller +Date: Fri May 29 17:08:28 2015 +1000 + + re-enable SSH protocol 1 at compile time + +commit db438f9285d64282d3ac9e8c0944f59f037c0151 +Author: djm@openbsd.org +Date: Fri May 29 03:05:13 2015 +0000 + + upstream commit + + make this work without SUDO set; ok dtucker@ + + Upstream-Regress-ID: bca88217b70bce2fe52b23b8e06bdeb82d98c715 + +commit 1d9a2e2849c9864fe75daabf433436341c968e14 +Author: djm@openbsd.org +Date: Thu May 28 07:37:31 2015 +0000 + + upstream commit + + wrap all moduli-related code in #ifdef WITH_OPENSSL. + based on patch from Reuben Hawkins; bz#2388 feedback and ok dtucker@ + + Upstream-ID: d80cfc8be3e6ec65b3fac9e87c4466533b31b7cf + +commit 496aeb25bc2d6c434171292e4714771b594bd00e +Author: dtucker@openbsd.org +Date: Thu May 28 05:41:29 2015 +0000 + + upstream commit + + Increase the allowed length of the known host file name + in the log message to be consistent with other cases. Part of bz#1993, ok + deraadt. + + Upstream-ID: a9e97567be49f25daf286721450968251ff78397 + +commit dd2cfeb586c646ff8d70eb93567b2e559ace5b14 +Author: dtucker@openbsd.org +Date: Thu May 28 05:09:45 2015 +0000 + + upstream commit + + Fix typo (keywork->keyword) + + Upstream-ID: 8aacd0f4089c0a244cf43417f4f9045dfaeab534 + +commit 9cc6842493fbf23025ccc1edab064869640d3bec +Author: djm@openbsd.org +Date: Thu May 28 04:50:53 2015 +0000 + + upstream commit + + add error message on ftruncate failure; bz#2176 + + Upstream-ID: cbcc606e0b748520c74a210d8f3cc9718d3148cf + +commit d1958793a0072c22be26d136dbda5ae263e717a0 +Author: djm@openbsd.org +Date: Thu May 28 04:40:13 2015 +0000 + + upstream commit + + make ssh-keygen default to ed25519 keys when compiled + without OpenSSL; bz#2388, ok dtucker@ + + Upstream-ID: 85a471fa6d3fa57a7b8e882d22cfbfc1d84cdc71 + +commit 3ecde664c9fc5fb3667aedf9e6671462600f6496 +Author: dtucker@openbsd.org +Date: Wed May 27 23:51:10 2015 +0000 + + upstream commit + + Reorder client proposal to prefer + diffie-hellman-group-exchange-sha1 over diffie-hellman-group14-sha1. ok djm@ + + Upstream-ID: 552c08d47347c3ee1a9a57d88441ab50abe17058 + +commit 40f64292b907afd0a674fdbf3e4c2356d17a7d68 +Author: dtucker@openbsd.org +Date: Wed May 27 23:39:18 2015 +0000 + + upstream commit + + Add a stronger (4k bit) fallback group that sshd can use + when the moduli file is missing or broken, sourced from RFC3526. bz#2302, ok + markus@ (earlier version), djm@ + + Upstream-ID: b635215746a25a829d117673d5e5a76d4baee7f4 + +commit 5ab7d5fa03ad55bc438fab45dfb3aeb30a3c237a +Author: Darren Tucker +Date: Thu May 28 10:03:40 2015 +1000 + + New moduli file from OpenBSD, removing 1k groups. + + Remove 1k bit groups. ok deraadt@, markus@ + +commit a71ba58adf34e599f30cdda6e9b93ae6e3937eea +Author: djm@openbsd.org +Date: Wed May 27 05:15:02 2015 +0000 + + upstream commit + + support PKCS#11 devices with external PIN entry devices + bz#2240, based on patch from Dirk-Willem van Gulik; feedback and ok dtucker@ + + Upstream-ID: 504568992b55a8fc984375242b1bd505ced61b0d + +commit b282fec1aa05246ed3482270eb70fc3ec5f39a00 +Author: dtucker@openbsd.org +Date: Tue May 26 23:23:40 2015 +0000 + + upstream commit + + Cap DH-GEX group size at 4kbits for Cisco implementations. + Some of them will choke when asked for preferred sizes >4k instead of + returning the 4k group that they do have. bz#2209, ok djm@ + + Upstream-ID: 54b863a19713446b7431f9d06ad0532b4fcfef8d + +commit 3e91b4e8b0dc2b4b7e7d42cf6e8994a32e4cb55e +Author: djm@openbsd.org +Date: Sun May 24 23:39:16 2015 +0000 + + upstream commit + + add missing 'c' option to getopt(), case statement was + already there; from Felix Bolte + + Upstream-ID: 9b19b4e2e0b54d6fefa0dfac707c51cf4bae3081 + +commit 64a89ec07660abba4d0da7c0095b7371c98bab62 +Author: jsg@openbsd.org +Date: Sat May 23 14:28:37 2015 +0000 + + upstream commit + + fix a memory leak in an error path ok markus@ dtucker@ + + Upstream-ID: bc1da0f205494944918533d8780fde65dff6c598 + +commit f948737449257d2cb83ffcfe7275eb79b677fd4a +Author: djm@openbsd.org +Date: Fri May 22 05:28:45 2015 +0000 + + upstream commit + + mention ssh-keygen -E for comparing legacy MD5 + fingerprints; bz#2332 + + Upstream-ID: 079a3669549041dbf10dbc072d9563f0dc3b2859 + +commit 0882332616e4f0272c31cc47bf2018f9cb258a4e +Author: djm@openbsd.org +Date: Fri May 22 04:45:52 2015 +0000 + + upstream commit + + Reorder EscapeChar option parsing to avoid a single-byte + out- of-bounds read. bz#2396 from Jaak Ristioja; ok dtucker@ + + Upstream-ID: 1dc6b5b63d1c8d9a88619da0b27ade461d79b060 + +commit d7c31da4d42c115843edee2074d7d501f8804420 +Author: djm@openbsd.org +Date: Fri May 22 03:50:02 2015 +0000 + + upstream commit + + add knob to relax GSSAPI host credential check for + multihomed hosts bz#928, patch by Simon Wilkinson; ok dtucker + (kerberos/GSSAPI is not compiled by default on OpenBSD) + + Upstream-ID: 15ddf1c6f7fd9d98eea9962f480079ae3637285d + +commit aa72196a00be6e0b666215edcffbc10af234cb0e +Author: Darren Tucker +Date: Fri May 22 17:49:46 2015 +1000 + + Include signal.h for sig_atomic_t, used by kex.h. + + bz#2402, from tomas.kuthan at oracle com. + +commit 8b02481143d75e91c49d1bfae0876ac1fbf9511a +Author: Darren Tucker +Date: Fri May 22 12:47:24 2015 +1000 + + Import updated moduli file from OpenBSD. + +commit 4739e8d5e1c0be49624082bd9f6b077e9e758db9 +Author: djm@openbsd.org +Date: Thu May 21 12:01:19 2015 +0000 + + upstream commit + + Support "ssh-keygen -lF hostname" to find search known_hosts + and print key hashes. Already advertised by ssh-keygen(1), but not delivered + by code; ok dtucker@ + + Upstream-ID: 459e0e2bf39825e41b0811c336db2d56a1c23387 + +commit e97201feca10b5196da35819ae516d0b87cf3a50 +Author: Damien Miller +Date: Thu May 21 17:55:15 2015 +1000 + + conditionalise util.h inclusion + +commit 13640798c7dd011ece0a7d02841fe48e94cfa0e0 +Author: djm@openbsd.org +Date: Thu May 21 06:44:25 2015 +0000 + + upstream commit + + regress test for AuthorizedPrincipalsCommand + + Upstream-Regress-ID: c658fbf1ab6b6011dc83b73402322e396f1e1219 + +commit 84452c5d03c21f9bfb28c234e0dc1dc67dd817b1 +Author: djm@openbsd.org +Date: Thu May 21 06:40:02 2015 +0000 + + upstream commit + + regress test for AuthorizedKeysCommand arguments + + Upstream-Regress-ID: bbd65c13c6b3be9a442ec115800bff9625898f12 + +commit bcc50d816187fa9a03907ac1f3a52f04a52e10d1 +Author: djm@openbsd.org +Date: Thu May 21 06:43:30 2015 +0000 + + upstream commit + + add AuthorizedPrincipalsCommand that allows getting + authorized_principals from a subprocess rather than a file, which is quite + useful in deployments with large userbases + + feedback and ok markus@ + + Upstream-ID: aa1bdac7b16fc6d2fa3524ef08f04c7258d247f6 + +commit 24232a3e5ab467678a86aa67968bbb915caffed4 +Author: djm@openbsd.org +Date: Thu May 21 06:38:35 2015 +0000 + + upstream commit + + support arguments to AuthorizedKeysCommand + + bz#2081 loosely based on patch by Sami Hartikainen + feedback and ok markus@ + + Upstream-ID: b080387a14aa67dddd8ece67c00f268d626541f7 + +commit d80fbe41a57c72420c87a628444da16d09d66ca7 +Author: djm@openbsd.org +Date: Thu May 21 04:55:51 2015 +0000 + + upstream commit + + refactor: split base64 encoding of pubkey into its own + sshkey_to_base64() function and out of sshkey_write(); ok markus@ + + Upstream-ID: 54fc38f5832e9b91028900819bda46c3959a0c1a + +commit 7cc44ef74133a473734bbcbd3484f24d6a7328c5 +Author: deraadt@openbsd.org +Date: Mon May 18 15:06:05 2015 +0000 + + upstream commit + + getentropy() and sendsyslog() have been around long + enough. openssh-portable may want the #ifdef's but not base. discussed with + djm few weeks back + + Upstream-ID: 0506a4334de108e3fb6c66f8d6e0f9c112866926 + +commit 9173d0fbe44de7ebcad8a15618e13a8b8d78902e +Author: dtucker@openbsd.org +Date: Fri May 15 05:44:21 2015 +0000 + + upstream commit + + Use a salted hash of the lock passphrase instead of plain + text and do constant-time comparisons of it. Should prevent leaking any + information about it via timing, pointed out by Ryan Castellucci. Add a 0.1s + incrementing delay for each failed unlock attempt up to 10s. ok markus@ + (earlier version), djm@ + + Upstream-ID: c599fcc325aa1cc65496b25220b622d22208c85f + +commit d028d5d3a697c71b21e4066d8672cacab3caa0a8 +Author: Damien Miller +Date: Tue May 5 19:10:58 2015 +1000 + + upstream commit + + - tedu@cvs.openbsd.org 2015/01/12 03:20:04 + [bcrypt_pbkdf.c] + rename blocks to words. bcrypt "blocks" are unrelated to blowfish blocks, + nor are they the same size. + +commit f6391d4e59b058984163ab28f4e317e7a72478f1 +Author: Damien Miller +Date: Tue May 5 19:10:23 2015 +1000 + + upstream commit + + - deraadt@cvs.openbsd.org 2015/01/08 00:30:07 + [bcrypt_pbkdf.c] + declare a local version of MIN(), call it MINIMUM() + +commit 8ac6b13cc9113eb47cd9e86c97d7b26b4b71b77f +Author: Damien Miller +Date: Tue May 5 19:09:46 2015 +1000 + + upstream commit + + - djm@cvs.openbsd.org 2014/12/30 01:41:43 + [bcrypt_pbkdf.c] + typo in comment: ouput => output + +commit 1f792489d5cf86a4f4e3003e6e9177654033f0f2 +Author: djm@openbsd.org +Date: Mon May 4 06:10:48 2015 +0000 + + upstream commit + + Remove pattern length argument from match_pattern_list(), we + only ever use it for strlen(pattern). + + Prompted by hanno AT hboeck.de pointing an out-of-bound read + error caused by an incorrect pattern length found using AFL + and his own tools. + + ok markus@ + +commit 639d6bc57b1942393ed12fb48f00bc05d4e093e4 +Author: djm@openbsd.org +Date: Fri May 1 07:10:01 2015 +0000 + + upstream commit + + refactor ssh_dispatch_run_fatal() to use sshpkt_fatal() + to better report error conditions. Teach sshpkt_fatal() about ECONNRESET. + + Improves error messages on TCP connection resets. bz#2257 + + ok dtucker@ + +commit 9559d7de34c572d4d3fd990ca211f8ec99f62c4d +Author: djm@openbsd.org +Date: Fri May 1 07:08:08 2015 +0000 + + upstream commit + + a couple of parse targets were missing activep checks, + causing them to be misapplied in match context; bz#2272 diagnosis and + original patch from Sami Hartikainen ok dtucker@ + +commit 7e8528cad04b2775c3b7db08abf8fb42e47e6b2a +Author: djm@openbsd.org +Date: Fri May 1 04:17:51 2015 +0000 + + upstream commit + + make handling of AuthorizedPrincipalsFile=none more + consistent with other =none options; bz#2288 from Jakub Jelen; ok dtucker@ + +commit ca430d4d9cc0f62eca3b1fb1e2928395b7ce80f7 +Author: djm@openbsd.org +Date: Fri May 1 04:03:20 2015 +0000 + + upstream commit + + remove failed remote forwards established by muliplexing + from the list of active forwards; bz#2363, patch mostly by Yoann Ricordel; ok + dtucker@ + +commit 8312cfb8ad88657517b3e23ac8c56c8e38eb9792 +Author: djm@openbsd.org +Date: Fri May 1 04:01:58 2015 +0000 + + upstream commit + + reduce stderr spam when using ssh -S /path/mux -O forward + -R 0:... ok dtucker@ + +commit 179be0f5e62f1f492462571944e45a3da660d82b +Author: djm@openbsd.org +Date: Fri May 1 03:23:51 2015 +0000 + + upstream commit + + prevent authorized_keys options picked up on public key + tests without a corresponding private key authentication being applied to + other authentication methods. Reported by halex@, ok markus@ + +commit a42d67be65b719a430b7fcaba2a4e4118382723a +Author: djm@openbsd.org +Date: Fri May 1 03:20:54 2015 +0000 + + upstream commit + + Don't make parsing of authorized_keys' environment= + option conditional on PermitUserEnv - always parse it, but only use the + result if the option is enabled. This prevents the syntax of authorized_keys + changing depending on which sshd_config options were enabled. + + bz#2329; based on patch from coladict AT gmail.com, ok dtucker@ + +commit e661a86353e11592c7ed6a847e19a83609f49e77 +Author: djm@openbsd.org +Date: Mon May 4 06:10:48 2015 +0000 + + upstream commit + + Remove pattern length argument from match_pattern_list(), we + only ever use it for strlen(pattern). + + Prompted by hanno AT hboeck.de pointing an out-of-bound read + error caused by an incorrect pattern length found using AFL + and his own tools. + + ok markus@ + +commit 0ef1de742be2ee4b10381193fe90730925b7f027 +Author: dtucker@openbsd.org +Date: Thu Apr 23 05:01:19 2015 +0000 + + upstream commit + + Add a simple regression test for sshd's configuration + parser. Right now, all it does is run the output of sshd -T back through + itself and ensure the output is valid and invariant. + +commit 368f83c793275faa2c52f60eaa9bdac155c4254b +Author: djm@openbsd.org +Date: Wed Apr 22 01:38:36 2015 +0000 + + upstream commit + + use correct key for nested certificate test + +commit 8d4d1bfddbbd7d21f545dc6997081d1ea1fbc99a +Author: djm@openbsd.org +Date: Fri May 1 07:11:47 2015 +0000 + + upstream commit + + mention that the user's shell from /etc/passwd is used + for commands too; bz#1459 ok dtucker@ + +commit 5ab283d0016bbc9d4d71e8e5284d011bc5a930cf +Author: djm@openbsd.org +Date: Fri May 8 07:29:00 2015 +0000 + + upstream commit + + whitespace + + Upstream-Regress-ID: 6b708a3e709d5b7fd37890f874bafdff1f597519 + +commit 8377d5008ad260048192e1e56ad7d15a56d103dd +Author: djm@openbsd.org +Date: Fri May 8 07:26:13 2015 +0000 + + upstream commit + + whitespace at EOL + + Upstream-Regress-ID: 9c48911643d5b05173b36a012041bed4080b8554 + +commit c28a3436fa8737709ea88e4437f8f23a6ab50359 +Author: djm@openbsd.org +Date: Fri May 8 06:45:13 2015 +0000 + + upstream commit + + moar whitespace at eol + + Upstream-ID: 64eaf872a3ba52ed41e494287e80d40aaba4b515 + +commit 2b64c490468fd4ca35ac8d5cc31c0520dc1508bb +Author: djm@openbsd.org +Date: Fri May 8 06:41:56 2015 +0000 + + upstream commit + + whitespace at EOL + + Upstream-ID: 57bcf67d666c6fc1ad798aee448fdc3f70f7ec2c + +commit 4e636cf201ce6e7e3b9088568218f9d4e2c51712 +Author: djm@openbsd.org +Date: Fri May 8 03:56:51 2015 +0000 + + upstream commit + + whitespace at EOL + +commit 38b8272f823dc1dd4e29dbcee83943ed48bb12fa +Author: dtucker@openbsd.org +Date: Mon May 4 01:47:53 2015 +0000 + + upstream commit + + Use diff w/out -u for better portability + +commit 297060f42d5189a4065ea1b6f0afdf6371fb0507 +Author: dtucker@openbsd.org +Date: Fri May 8 03:25:07 2015 +0000 + + upstream commit + + Use xcalloc for permitted_adm_opens instead of xmalloc to + ensure it's zeroed. Fixes post-auth crash with permitopen=none. bz#2355, ok + djm@ + +commit 63ebf019be863b2d90492a85e248cf55a6e87403 +Author: djm@openbsd.org +Date: Fri May 8 03:17:49 2015 +0000 + + upstream commit + + don't choke on new-format private keys encrypted with an + AEAD cipher; bz#2366, patch from Ron Frederick; ok markus@ + +commit f8484dac678ab3098ae522a5f03bb2530f822987 +Author: dtucker@openbsd.org +Date: Wed May 6 05:45:17 2015 +0000 + + upstream commit + + Clarify pseudo-terminal request behaviour and use + "pseudo-terminal" consistently. bz#1716, ok jmc@ "I like it" deraadt@. + +commit ea139507bef8bad26e86ed99a42c7233ad115c38 +Author: dtucker@openbsd.org +Date: Wed May 6 04:07:18 2015 +0000 + + upstream commit + + Blacklist DH-GEX for specific PuTTY versions known to + send non-RFC4419 DH-GEX messages rather than all versions of PuTTY. + According to Simon Tatham, 0.65 and newer versions will send RFC4419 DH-GEX + messages. ok djm@ + +commit b58234f00ee3872eb84f6e9e572a9a34e902e36e +Author: dtucker@openbsd.org +Date: Tue May 5 10:17:49 2015 +0000 + + upstream commit + + WinSCP doesn't implement RFC4419 DH-GEX so flag it so we + don't offer that KEX method. ok markus@ + +commit d5b1507a207253b39e810e91e68f9598691b7a29 +Author: jsg@openbsd.org +Date: Tue May 5 02:48:17 2015 +0000 + + upstream commit + + use the sizeof the struct not the sizeof a pointer to the + struct in ssh_digest_start() + + This file is only used if ssh is built with OPENSSL=no + + ok markus@ + +commit a647b9b8e616c231594b2710c925d31b1b8afea3 +Author: Darren Tucker +Date: Fri May 8 11:07:27 2015 +1000 + + Put brackets around mblen() compat constant. + + This might help with the reported problem cross compiling for Android + ("error: expected identifier or '(' before numeric constant") but + shouldn't hurt in any case. + +commit d1680d36e17244d9af3843aeb5025cb8e40d6c07 +Author: Darren Tucker +Date: Thu Apr 30 09:18:11 2015 +1000 + + xrealloc -> xreallocarray in portable code too. + +commit 531a57a3893f9fcd4aaaba8c312b612bbbcc021e +Author: dtucker@openbsd.org +Date: Wed Apr 29 03:48:56 2015 +0000 + + upstream commit + + Allow ListenAddress, Port and AddressFamily in any + order. bz#68, ok djm@, jmc@ (for the man page bit). + +commit c1d5bcf1aaf1209af02f79e48ba1cbc76a87b56f +Author: jmc@openbsd.org +Date: Tue Apr 28 13:47:38 2015 +0000 + + upstream commit + + enviroment -> environment: apologies to darren for not + spotting that first time round... + +commit 43beea053db191cac47c2cd8d3dc1930158aff1a +Author: dtucker@openbsd.org +Date: Tue Apr 28 10:25:15 2015 +0000 + + upstream commit + + Fix typo in previous + +commit 85b96ef41374f3ddc9139581f87da09b2cd9199e +Author: dtucker@openbsd.org +Date: Tue Apr 28 10:17:58 2015 +0000 + + upstream commit + + Document that the TERM environment variable is not + subject to SendEnv and AcceptEnv. bz#2386, based loosely on a patch from + jjelen at redhat, help and ok jmc@ + +commit 88a7c598a94ff53f76df228eeaae238d2d467565 +Author: djm@openbsd.org +Date: Mon Apr 27 21:42:48 2015 +0000 + + upstream commit + + Make sshd default to PermitRootLogin=no; ok deraadt@ + rpe@ + +commit 734226b4480a6c736096c729fcf6f391400599c7 +Author: djm@openbsd.org +Date: Mon Apr 27 01:52:30 2015 +0000 + + upstream commit + + fix compilation with OPENSSL=no; ok dtucker@ + +commit a4b9d2ce1eb7703eaf0809b0c8a82ded8aa4f1c6 +Author: dtucker@openbsd.org +Date: Mon Apr 27 00:37:53 2015 +0000 + + upstream commit + + Include stdio.h for FILE (used in sshkey.h) so it + compiles with OPENSSL=no. + +commit dbcc652f4ca11fe04e5930c7ef18a219318c6cda +Author: djm@openbsd.org +Date: Mon Apr 27 00:21:21 2015 +0000 + + upstream commit + + allow "sshd -f none" to skip reading the config file, + much like "ssh -F none" does. ok dtucker + +commit b7ca276fca316c952f0b90f5adb1448c8481eedc +Author: jmc@openbsd.org +Date: Fri Apr 24 06:26:49 2015 +0000 + + upstream commit + + combine -Dd onto one line and update usage(); + +commit 2ea974630d7017e4c7666d14d9dc939707613e96 +Author: djm@openbsd.org +Date: Fri Apr 24 05:26:44 2015 +0000 + + upstream commit + + add ssh-agent -D to leave ssh-agent in foreground + without enabling debug mode; bz#2381 ok dtucker@ + +commit 8ac2ffd7aa06042f6b924c87139f2fea5c5682f7 +Author: deraadt@openbsd.org +Date: Fri Apr 24 01:36:24 2015 +0000 + + upstream commit + + 2*len -> use xreallocarray() ok djm + +commit 657a5fbc0d0aff309079ff8fb386f17e964963c2 +Author: deraadt@openbsd.org +Date: Fri Apr 24 01:36:00 2015 +0000 + + upstream commit + + rename xrealloc() to xreallocarray() since it follows + that form. ok djm + +commit 1108ae242fdd2c304307b68ddf46aebe43ebffaa +Author: dtucker@openbsd.org +Date: Thu Apr 23 04:59:10 2015 +0000 + + upstream commit + + Two small fixes for sshd -T: ListenAddress'es are added + to a list head so reverse the order when printing them to ensure the + behaviour remains the same, and print StreamLocalBindMask as octal with + leading zero. ok deraadt@ + +commit bd902b8473e1168f19378d5d0ae68d0c203525df +Author: dtucker@openbsd.org +Date: Thu Apr 23 04:53:53 2015 +0000 + + upstream commit + + Check for and reject missing arguments for + VersionAddendum and ForceCommand. bz#2281, patch from plautrba at redhat com, + ok djm@ -20140213 - - (dtucker) [configure.ac openbsd-compat/openssl-compat.{c,h}] Add compat - code for older OpenSSL versions that don't have EVP_MD_CTX_copy_ex. - -20140207 - - OpenBSD CVS Sync - - naddy@cvs.openbsd.org 2014/02/05 20:13:25 - [ssh-keygen.1 ssh-keygen.c] - tweak synopsis: calling ssh-keygen without any arguments is fine; ok jmc@ - while here, fix ordering in usage(); requested by jmc@ - - djm@cvs.openbsd.org 2014/02/06 22:21:01 - [sshconnect.c] - in ssh_create_socket(), only do the getaddrinfo for BindAddress when - BindAddress is actually specified. Fixes regression in 6.5 for - UsePrivilegedPort=yes; patch from Corinna Vinschen - -20140206 - - (dtucker) [openbsd-compat/bsd-poll.c] Don't bother checking for non-NULL - before freeing since free(NULL) is a no-op. ok djm. - - (djm) [sandbox-seccomp-filter.c] Not all Linux architectures define - __NR_shutdown; some go via the socketcall(2) multiplexer. - -20140205 - - (djm) [sandbox-capsicum.c] Don't fatal if Capsicum is offered by - headers/libc but not supported by the kernel. Patch from Loganaden - Velvindron @ AfriNIC - -20140204 - - OpenBSD CVS Sync - - markus@cvs.openbsd.org 2014/01/27 18:58:14 - [Makefile.in digest.c digest.h hostfile.c kex.h mac.c hmac.c hmac.h] - replace openssl HMAC with an implementation based on our ssh_digest_* - ok and feedback djm@ - - markus@cvs.openbsd.org 2014/01/27 19:18:54 - [auth-rsa.c cipher.c ssh-agent.c sshconnect1.c sshd.c] - replace openssl MD5 with our ssh_digest_*; ok djm@ - - markus@cvs.openbsd.org 2014/01/27 20:13:46 - [digest.c digest-openssl.c digest-libc.c Makefile.in] - rename digest.c to digest-openssl.c and add libc variant; ok djm@ - - jmc@cvs.openbsd.org 2014/01/28 14:13:39 - [ssh-keyscan.1] - kill some bad Pa; - From: Jan Stary - - djm@cvs.openbsd.org 2014/01/29 00:19:26 - [sshd.c] - use kill(0, ...) instead of killpg(0, ...); on most operating systems - they are equivalent, but SUSv2 describes the latter as having undefined - behaviour; from portable; ok dtucker - (Id sync only; change is already in portable) - - djm@cvs.openbsd.org 2014/01/29 06:18:35 - [Makefile.in auth.h auth2-jpake.c auth2.c jpake.c jpake.h monitor.c] - [monitor.h monitor_wrap.c monitor_wrap.h readconf.c readconf.h] - [schnorr.c schnorr.h servconf.c servconf.h ssh2.h sshconnect2.c] - remove experimental, never-enabled JPAKE code; ok markus@ - - jmc@cvs.openbsd.org 2014/01/29 14:04:51 - [sshd_config.5] - document kbdinteractiveauthentication; - requested From: Ross L Richardson - - dtucker/markus helped explain its workings; - - djm@cvs.openbsd.org 2014/01/30 22:26:14 - [sandbox-systrace.c] - allow shutdown(2) syscall in sandbox - it may be called by packet_close() - from portable - (Id sync only; change is already in portable) - - tedu@cvs.openbsd.org 2014/01/31 16:39:19 - [auth2-chall.c authfd.c authfile.c bufaux.c bufec.c canohost.c] - [channels.c cipher-chachapoly.c clientloop.c configure.ac hostfile.c] - [kexc25519.c krl.c monitor.c sandbox-systrace.c session.c] - [sftp-client.c ssh-keygen.c ssh.c sshconnect2.c sshd.c sshlogin.c] - [openbsd-compat/explicit_bzero.c openbsd-compat/openbsd-compat.h] - replace most bzero with explicit_bzero, except a few that cna be memset - ok djm dtucker - - djm@cvs.openbsd.org 2014/02/02 03:44:32 - [auth1.c auth2-chall.c auth2-passwd.c authfile.c bufaux.c bufbn.c] - [buffer.c cipher-3des1.c cipher.c clientloop.c gss-serv.c kex.c] - [kexdhc.c kexdhs.c kexecdhc.c kexgexc.c kexecdhs.c kexgexs.c key.c] - [monitor.c monitor_wrap.c packet.c readpass.c rsa.c serverloop.c] - [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c] - [ssh-keygen.c ssh-rsa.c sshconnect.c sshconnect1.c sshconnect2.c] - [sshd.c] - convert memset of potentially-private data to explicit_bzero() - - djm@cvs.openbsd.org 2014/02/03 23:28:00 - [ssh-ecdsa.c] - fix memory leak; ECDSA_SIG_new() allocates 'r' and 's' for us, unlike - DSA_SIG_new. Reported by Batz Spear; ok markus@ - - djm@cvs.openbsd.org 2014/02/02 03:44:31 - [digest-libc.c digest-openssl.c] - convert memset of potentially-private data to explicit_bzero() - - djm@cvs.openbsd.org 2014/02/04 00:24:29 - [ssh.c] - delay lowercasing of hostname until right before hostname - canonicalisation to unbreak case-sensitive matching of ssh_config; - reported by Ike Devolder; ok markus@ - - (djm) [openbsd-compat/Makefile.in] Add missing explicit_bzero.o - - (djm) [regress/setuid-allowed.c] Missing string.h for strerror() - -20140131 - - (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2) - syscall from sandboxes; it may be called by packet_close. - - (dtucker) [readconf.c] Include for the hton macros. Fixes - build with HP-UX's compiler. Patch from Kevin Brott. - - (tim) [Makefile.in] build regress/setuid-allow. - -20140130 - - (djm) [configure.ac] Only check for width-specified integer types - in headers that actually exist. patch from Tom G. Christensen; - ok dtucker@ - - (djm) [configure.ac atomicio.c] Kludge around NetBSD offering - different symbols for 'read' when various compiler flags are - in use, causing atomicio.c comparisons against it to break and - read/write operations to hang; ok dtucker - - (djm) Release openssh-6.5p1 - -20140129 - - (djm) [configure.ac] Fix broken shell test '==' vs '='; patch from - Tom G. Christensen - -20140128 - - (djm) [configure.ac] Search for inet_ntop in libnsl and libresovl; - ok dtucker - - (djm) [sshd.c] Use kill(0, ...) instead of killpg(0, ...); the - latter being specified to have undefined behaviour in SUSv3; - ok dtucker - - (tim) [regress/agent.sh regress/agent-ptrace.sh] Assign $? to a variable - when used as an error message inside an if statement so we display the - correct into. agent.sh patch from Petr Lautrbach. - -20140127 - - (dtucker) [Makefile.in] Remove trailing backslash which some make - implementations (eg older Solaris) do not cope with. - -20140126 - - OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2014/01/25 10:12:50 - [cipher.c cipher.h kex.c kex.h kexgexc.c] - Add a special case for the DH group size for 3des-cbc, which has an - effective strength much lower than the key size. This causes problems - with some cryptlib implementations, which don't support group sizes larger - than 4k but also don't use the largest group size it does support as - specified in the RFC. Based on a patch from Petr Lautrbach at Redhat, - reduced by me with input from Markus. ok djm@ markus@ - - markus@cvs.openbsd.org 2014/01/25 20:35:37 - [kex.c] - dh_need needs to be set to max(seclen, blocksize, ivlen, mac_len) - ok dtucker@, noted by mancha - - (djm) [configure.ac sandbox-capsicum.c sandbox-rlimit.c] Disable - RLIMIT_NOFILE pseudo-sandbox on FreeBSD. In some configurations, - libc will attempt to open additional file descriptors for crypto - offload and crash if they cannot be opened. - - (djm) [configure.ac] correct AC_DEFINE for previous. - -20140125 - - (djm) [configure.ac] Fix detection of capsicum sandbox on FreeBSD - - (djm) [configure.ac] Do not attempt to use capsicum sandbox unless - sys/capability.h exists and cap_rights_limit is in libc. Fixes - build on FreeBSD9x which provides the header but not the libc - support. - - (djm) [configure.ac] autoconf sets finds to 'yes' not '1', so test - against the correct thing. - -20140124 - - (djm) [Makefile.in regress/scp-ssh-wrapper.sh regress/scp.sh] Make - the scp regress test actually test the built scp rather than the one - in $PATH. ok dtucker@ - -20140123 - - (tim) [session.c] Improve error reporting on set_id(). - - (dtucker) [configure.ac] NetBSD's (and FreeBSD's) strnvis is gratuitously - incompatible with OpenBSD's despite post-dating it by more than a decade. - Declare it as broken, and document FreeBSD's as the same. ok djm@ - -20140122 - - (djm) [openbsd-compat/setproctitle.c] Don't fail to compile if a - platform that is expected to use the reuse-argv style setproctitle - hack surprises us by providing a setproctitle in libc; ok dtucker - - (djm) [configure.ac] Unless specifically requested, only attempt - to build Position Independent Executables on gcc >= 4.x; ok dtucker - - (djm) [configure.ac aclocal.m4] More tests to detect fallout from - platform hardening options: include some long long int arithmatic - to detect missing support functions for -ftrapv in libgcc and - equivalents, actually test linking when -ftrapv is supplied and - set either both -pie/-fPIE or neither. feedback and ok dtucker@ - -20140121 - - (dtucker) [configure.ac] Make PIE a configure-time option which defaults - to on platforms where it's known to be reliably detected and off elsewhere. - Works around platforms such as FreeBSD 9.1 where it does not interop with - -ftrapv (it seems to work but fails when trying to link ssh). ok djm@ - - (dtucker) [aclocal.m4] Differentiate between compile-time and link-time - tests in the configure output. ok djm. - - (tim) [platform.c session.c] Fix bug affecting SVR5 platforms introduced - with sftp chroot support. Move set_id call after chroot. - - (djm) [aclocal.m4] Flesh out the code run in the OSSH_CHECK_CFLAG_COMPILE - and OSSH_CHECK_LDFLAG_LINK tests to give them a better chance of - detecting toolchain-related problems; ok dtucker - -20140120 - - (dtucker) [gss-serv-krb5.c] Fall back to krb5_cc_gen_new if the Kerberos - implementation does not have krb5_cc_new_unique, similar to what we do - in auth-krb5.c. - - (djm) [regress/cert-hostkey.sh] Fix regress failure on platforms that - skip one or more key types (e.g. RHEL/CentOS 6.5); ok dtucker@ - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2014/01/20 00:08:48 - [digest.c] - memleak; found by Loganaden Velvindron @ AfriNIC; ok markus@ - -20140119 - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2014/01/17 06:23:24 - [sftp-server.c] - fix log message statvfs. ok djm - - dtucker@cvs.openbsd.org 2014/01/18 09:36:26 - [session.c] - explicitly define USE_PIPES to 1 to prevent redefinition warnings in - portable on platforms that use pipes for everything. From vinschen at - redhat. - - dtucker@cvs.openbsd.org 2014/01/19 04:17:29 - [canohost.c addrmatch.c] - Cast socklen_t when comparing to size_t and use socklen_t to iterate over - the ip options, both to prevent signed/unsigned comparison warnings. - Patch from vinschen at redhat via portable openssh, begrudging ok deraadt. - - djm@cvs.openbsd.org 2014/01/19 04:48:08 - [ssh_config.5] - fix inverted meaning of 'no' and 'yes' for CanonicalizeFallbackLocal - - dtucker@cvs.openbsd.org 2014/01/19 11:21:51 - [addrmatch.c] - Cast the sizeof to socklen_t so it'll work even if the supplied len is - negative. Suggested by and ok djm, ok deraadt. - -20140118 - - (dtucker) [uidswap.c] Prevent unused variable warnings on Cygwin. Patch - from vinschen at redhat.com - - (dtucker) [openbsd-compat/bsd-cygwin_util.h] Add missing function - declarations that stopped being included when we stopped including - from openbsd-compat/bsd-cygwin_util.h. Patch from vinschen at - redhat.com. - - (dtucker) [configure.ac] On Cygwin the getopt variables (like optargs, - optind) are defined in getopt.h already. Unfortunately they are defined as - "declspec(dllimport)" for historical reasons, because the GNU linker didn't - allow auto-import on PE/COFF targets way back when. The problem is the - dllexport attributes collide with the definitions in the various source - files in OpenSSH, which obviousy define the variables without - declspec(dllimport). The least intrusive way to get rid of these warnings - is to disable warnings for GCC compiler attributes when building on Cygwin. - Patch from vinschen at redhat.com. - - (dtucker) [sandbox-capsicum.c] Correct some error messages and make the - return value check for cap_enter() consistent with the other uses in - FreeBSD. From by Loganaden Velvindron @ AfriNIC via bz#2140. - -20140117 - - (dtucker) [aclocal.m4 configure.ac] Add some additional compiler/toolchain - hardening flags including -fstack-protector-strong. These default to on - if the toolchain supports them, but there is a configure-time knob - (--without-hardening) to disable them if necessary. ok djm@ - - (djm) [sftp-client.c] signed/unsigned comparison fix - - (dtucker) [loginrec.c] Cast to the types specfied in the format - specification to prevent warnings. - - (dtucker) [crypto_api.h] Wrap stdlib.h include inside #ifdef HAVE_STDINT_H. - - (dtucker) [poly1305.c] Wrap stdlib.h include inside #ifdef HAVE_STDINT_H. - - (dtucker) [blocks.c fe25519.c ge25519.c hash.c sc25519.c verify.c] Include - includes.h to pull in all of the compatibility stuff. - - (dtucker) [openbsd-compat/bcrypt_pbkdf.c] Wrap stdlib.h include inside - #ifdef HAVE_STDINT_H. - - (dtucker) [defines.h] Add typedefs for uintXX_t types for platforms that - don't have them. - - (dtucker) [configure.ac] Split AC_CHECK_FUNCS for OpenSSL functions into - separate lines and alphabetize for easier diffing of changes. - - (dtucker) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2014/01/17 00:21:06 - [sftp-client.c] - signed/unsigned comparison warning fix; from portable (Id sync only) - - dtucker@cvs.openbsd.org 2014/01/17 05:26:41 - [digest.c] - remove unused includes. ok djm@ - - (djm) [Makefile.in configure.ac sandbox-capsicum.c sandbox-darwin.c] - [sandbox-null.c sandbox-rlimit.c sandbox-seccomp-filter.c] - [sandbox-systrace.c ssh-sandbox.h sshd.c] Support preauth sandboxing - using the Capsicum API introduced in FreeBSD 10. Patch by Dag-Erling - Smorgrav, updated by Loganaden Velvindron @ AfriNIC; ok dtucker@ - - (dtucker) [configure.ac digest.c openbsd-compat/openssl-compat.c - openbsd-compat/openssl-compat.h] Add compatibility layer for older - openssl versions. ok djm@ - - (dtucker) Fix typo in #ifndef. - - (dtucker) [configure.ac openbsd-compat/bsd-statvfs.c - openbsd-compat/bsd-statvfs.h] Implement enough of statvfs on top of statfs - to be useful (and for the regression tests to pass) on platforms that - have statfs and fstatfs. ok djm@ - - (dtucker) [openbsd-compat/bsd-statvfs.h] Only start including headers if we - need them to cut down on the name collisions. - - (dtucker) [configure.ac] Also look in inttypes.h for uintXX_t types. - - (dtucker) [configure.ac] Have --without-hardening not turn off - stack-protector since that has a separate flag that's been around a while. - - (dtucker) [readconf.c] Wrap paths.h inside an ifdef. Allows building on - Solaris. - - (dtucker) [defines.h] Move our definitions of uintXX_t types down to after - they're defined if we have to define them ourselves. Fixes builds on old - AIX. - -20140118 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2014/01/16 07:31:09 - [sftp-client.c] - needless and incorrect cast to size_t can break resumption of - large download; patch from tobias@ - - djm@cvs.openbsd.org 2014/01/16 07:32:00 - [version.h] - openssh-6.5 - - (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec] - [contrib/suse/openssh.spec] Crank RPM spec version numbers. - - (djm) [README] update release notes URL. - -20140112 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2014/01/10 05:59:19 - [sshd_config] - the /etc/ssh/ssh_host_ed25519_key is loaded by default too - - djm@cvs.openbsd.org 2014/01/12 08:13:13 - [bufaux.c buffer.h kex.c kex.h kexc25519.c kexc25519c.c kexc25519s.c] - [kexdhc.c kexdhs.c kexecdhc.c kexecdhs.c kexgexc.c kexgexs.c] - avoid use of OpenSSL BIGNUM type and functions for KEX with - Curve25519 by adding a buffer_put_bignum2_from_string() that stores - a string using the bignum encoding rules. Will make it easier to - build a reduced-feature OpenSSH without OpenSSL in the future; +commit ca42c1758575e592239de1d5755140e054b91a0d +Author: djm@openbsd.org +Date: Wed Apr 22 01:24:01 2015 +0000 + + upstream commit + + unknown certificate extensions are non-fatal, so don't + fatal when they are encountered; bz#2387 reported by Bob Van Zant; ok + dtucker@ + +commit 39bfbf7caad231cc4bda6909fb1af0705bca04d8 +Author: jsg@openbsd.org +Date: Tue Apr 21 07:01:00 2015 +0000 + + upstream commit + + Add back a backslash removed in rev 1.42 so + KEX_SERVER_ENCRYPT will include aes again. + + ok deraadt@ + +commit 6b0d576bb87eca3efd2b309fcfe4edfefc289f9c +Author: djm@openbsd.org +Date: Fri Apr 17 13:32:09 2015 +0000 + + upstream commit + + s/recommended/required/ that private keys be og-r this + wording change was made a while ago but got accidentally reverted + +commit 44a8e7ce6f3ab4c2eb1ae49115c210b98e53c4df +Author: djm@openbsd.org +Date: Fri Apr 17 13:25:52 2015 +0000 + + upstream commit + + don't try to cleanup NULL KEX proposals in + kex_prop_free(); found by Jukka Taimisto and Markus Hietava + +commit 3038a191872d2882052306098c1810d14835e704 +Author: djm@openbsd.org +Date: Fri Apr 17 13:19:22 2015 +0000 + + upstream commit + + use error/logit/fatal instead of fprintf(stderr, ...) + and exit(0), fix a few errors that were being printed to stdout instead of + stderr and a few non-errors that were going to stderr instead of stdout + bz#2325; ok dtucker + +commit a58be33cb6cd24441fa7e634db0e5babdd56f07f +Author: djm@openbsd.org +Date: Fri Apr 17 13:16:48 2015 +0000 + + upstream commit + + debug log missing DISPLAY environment when X11 + forwarding requested; bz#1682 ok dtucker@ + +commit 17d4d9d9fbc8fb80e322f94d95eecc604588a474 +Author: djm@openbsd.org +Date: Fri Apr 17 04:32:31 2015 +0000 + + upstream commit + + don't call record_login() in monitor when UseLogin is + enabled; bz#278 reported by drk AT sgi.com; ok dtucker + +commit 40132ff87b6cbc3dc05fb5df2e9d8e3afa06aafd +Author: dtucker@openbsd.org +Date: Fri Apr 17 04:12:35 2015 +0000 + + upstream commit + + Add some missing options to sshd -T and fix the output + of VersionAddendum HostCertificate. bz#2346, patch from jjelen at redhat + com, ok djm. + +commit 6cc7cfa936afde2d829e56ee6528c7ea47a42441 +Author: dtucker@openbsd.org +Date: Thu Apr 16 23:25:50 2015 +0000 + + upstream commit + + Document "none" for PidFile XAuthLocation + TrustedUserCAKeys and RevokedKeys. bz#2382, feedback from jmc@, ok djm@ + +commit 15fdfc9b1c6808b26bc54d4d61a38b54541763ed +Author: dtucker@openbsd.org +Date: Wed Apr 15 23:23:25 2015 +0000 + + upstream commit + + Plug leak of address passed to logging. bz#2373, patch + from jjelen at redhat, ok markus@ + +commit bb2289e2a47d465eaaaeff3dee2a6b7777b4c291 +Author: dtucker@openbsd.org +Date: Tue Apr 14 04:17:03 2015 +0000 + + upstream commit + + Output remote username in debug output since with Host + and Match it's not always obvious what it will be. bz#2368, ok djm@ + +commit 70860b6d07461906730632f9758ff1b7c98c695a +Author: Darren Tucker +Date: Fri Apr 17 10:56:13 2015 +1000 + + Format UsePAM setting when using sshd -T. + + Part of bz#2346, patch from jjelen at redhat com. + +commit ee15d9c9f0720f5a8b0b34e4b10ecf21f9824814 +Author: Darren Tucker +Date: Fri Apr 17 10:40:23 2015 +1000 + + Wrap endian.h include inside ifdef (bz#2370). + +commit 408f4c2ad4a4c41baa7b9b2b7423d875abbfa70b +Author: Darren Tucker +Date: Fri Apr 17 09:39:58 2015 +1000 + + Look for '${host}-ar' before 'ar'. + + This changes configure.ac to look for '${host}-ar' as set by + AC_CANONICAL_HOST before looking for the unprefixed 'ar'. + Useful when cross-compiling when all your binutils are prefixed. + + Patch from moben at exherbo org via astrand at lysator liu se and + bz#2352. + +commit 673a1c16ad078d41558247ce739fe812c960acc8 +Author: Damien Miller +Date: Thu Apr 16 11:40:20 2015 +1000 + + remove dependency on arpa/telnet.h + +commit 202d443eeda1829d336595a3cfc07827e49f45ed +Author: Darren Tucker +Date: Wed Apr 15 15:59:49 2015 +1000 + + Remove duplicate include of pwd.h. bz#2337, patch from Mordy Ovits. + +commit 597986493412c499f2bc2209420cb195f97b3668 +Author: Damien Miller +Date: Thu Apr 9 10:14:48 2015 +1000 + + platform's with openpty don't need pty_release + +commit 318be28cda1fd9108f2e6f2f86b0b7589ba2aed0 +Author: djm@openbsd.org +Date: Mon Apr 13 02:04:08 2015 +0000 + + upstream commit + + deprecate ancient, pre-RFC4419 and undocumented + SSH2_MSG_KEX_DH_GEX_REQUEST_OLD message; ok markus@ deraadt@ "seems + reasonable" dtucker@ + +commit d8f391caef62378463a0e6b36f940170dadfe605 +Author: dtucker@openbsd.org +Date: Fri Apr 10 05:16:50 2015 +0000 + + upstream commit + + Don't send hostkey advertisments + (hostkeys-00@openssh.com) to current versions of Tera Term as they can't + handle them. Newer versions should be OK. Patch from Bryan Drewery and + IWAMOTO Kouichi, ok djm@ + +commit 2c2cfe1a1c97eb9a08cc9817fd0678209680c636 +Author: djm@openbsd.org +Date: Fri Apr 10 00:08:55 2015 +0000 + + upstream commit + + include port number if a non-default one has been + specified; based on patch from Michael Handler + +commit 4492a4f222da4cf1e8eab12689196322e27b08c4 +Author: djm@openbsd.org +Date: Tue Apr 7 23:00:42 2015 +0000 + + upstream commit + + treat Protocol=1,2|2,1 as Protocol=2 when compiled + without SSH1 support; ok dtucker@ millert@ + +commit c265e2e6e932efc6d86f6cc885dea33637a67564 +Author: miod@openbsd.org +Date: Sun Apr 5 15:43:43 2015 +0000 + + upstream commit + + Do not use int for sig_atomic_t; spotted by + christos@netbsd; ok markus@ + +commit e7bf3a5eda6a1b02bef6096fed78527ee11e54cc +Author: Darren Tucker +Date: Tue Apr 7 10:48:04 2015 +1000 + + Use do{}while(0) for no-op functions. + + From FreeBSD. + +commit bb99844abae2b6447272f79e7fa84134802eb4df +Author: Darren Tucker +Date: Tue Apr 7 10:47:15 2015 +1000 + + Wrap blf.h include in ifdef. From FreeBSD. + +commit d9b9b43656091cf0ad55c122f08fadb07dad0abd +Author: Darren Tucker +Date: Tue Apr 7 09:10:00 2015 +1000 + + Fix misspellings of regress CONFOPTS env variables. + + Patch from Bryan Drewery. + +commit 3f4ea3c9ab1d32d43c9222c4351f58ca11144156 +Author: djm@openbsd.org +Date: Fri Apr 3 22:17:27 2015 +0000 + + upstream commit + + correct return value in pubkey parsing, spotted by Ben Hawkes ok markus@ -20140110 - - (djm) OpenBSD CVS Sync - - tedu@cvs.openbsd.org 2014/01/04 17:50:55 - [mac.c monitor_mm.c monitor_mm.h xmalloc.c] - use standard types and formats for size_t like variables. ok dtucker - - guenther@cvs.openbsd.org 2014/01/09 03:26:00 - [sftp-common.c] - When formating the time for "ls -l"-style output, show dates in the future - with the year, and rearrange a comparison to avoid a potentional signed - arithmetic overflow that would give the wrong result. - ok djm@ - - djm@cvs.openbsd.org 2014/01/09 23:20:00 - [digest.c digest.h hostfile.c kex.c kex.h kexc25519.c kexc25519c.c] - [kexc25519s.c kexdh.c kexecdh.c kexecdhc.c kexecdhs.c kexgex.c kexgexc.c] - [kexgexs.c key.c key.h roaming_client.c roaming_common.c schnorr.c] - [schnorr.h ssh-dss.c ssh-ecdsa.c ssh-rsa.c sshconnect2.c] - Introduce digest API and use it to perform all hashing operations - rather than calling OpenSSL EVP_Digest* directly. Will make it easier - to build a reduced-feature OpenSSH without OpenSSL in future; - feedback, ok markus@ - - djm@cvs.openbsd.org 2014/01/09 23:26:48 - [sshconnect.c sshd.c] - ban clients/servers that suffer from SSH_BUG_DERIVEKEY, they are ancient, - deranged and might make some attacks on KEX easier; ok markus@ - -20140108 - - (djm) [regress/.cvsignore] Ignore regress test droppings; ok dtucker@ - -20131231 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/12/30 23:52:28 - [auth2-hostbased.c auth2-pubkey.c compat.c compat.h ssh-rsa.c] - [sshconnect.c sshconnect2.c sshd.c] - refuse RSA keys from old proprietary clients/servers that use the - obsolete RSA+MD5 signature scheme. it will still be possible to connect - with these clients/servers but only DSA keys will be accepted, and we'll - deprecate them entirely in a future release. ok markus@ - -20131229 - - (djm) [loginrec.c] Check for username truncation when looking up lastlog - entries - - (djm) [regress/Makefile] Add some generated files for cleaning - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/12/19 00:10:30 - [ssh-add.c] - skip requesting smartcard PIN when removing keys from agent; bz#2187 - patch from jay AT slushpupie.com; ok dtucker - - dtucker@cvs.openbsd.org 2013/12/19 00:19:12 - [serverloop.c] - Cast client_alive_interval to u_int64_t before assinging to - max_time_milliseconds to avoid potential integer overflow in the timeout. - bz#2170, patch from Loganaden Velvindron, ok djm@ - - djm@cvs.openbsd.org 2013/12/19 00:27:57 - [auth-options.c] - simplify freeing of source-address certificate restriction - - djm@cvs.openbsd.org 2013/12/19 01:04:36 - [channels.c] - bz#2147: fix multiple remote forwardings with dynamically assigned - listen ports. In the s->c message to open the channel we were sending - zero (the magic number to request a dynamic port) instead of the actual - listen port. The client therefore had no way of discriminating between - them. - - Diagnosis and fix by ronf AT timeheart.net - - djm@cvs.openbsd.org 2013/12/19 01:19:41 - [ssh-agent.c] - bz#2186: don't crash (NULL deref) when deleting PKCS#11 keys from an agent - that has a mix of normal and PKCS#11 keys; fix from jay AT slushpupie.com; - ok dtucker - - djm@cvs.openbsd.org 2013/12/19 22:57:13 - [poly1305.c poly1305.h] - use full name for author, with his permission - - tedu@cvs.openbsd.org 2013/12/21 07:10:47 - [ssh-keygen.1] - small typo - - djm@cvs.openbsd.org 2013/12/27 22:30:17 - [ssh-dss.c ssh-ecdsa.c ssh-rsa.c] - make the original RSA and DSA signing/verification code look more like - the ECDSA/Ed25519 ones: use key_type_plain() when checking the key type - rather than tediously listing all variants, use __func__ for debug/ - error messages - - djm@cvs.openbsd.org 2013/12/27 22:37:18 - [ssh-rsa.c] - correct comment - - djm@cvs.openbsd.org 2013/12/29 02:28:10 - [key.c] - allow ed25519 keys to appear as certificate authorities - - djm@cvs.openbsd.org 2013/12/29 02:37:04 - [key.c] - correct comment for key_to_certified() - - djm@cvs.openbsd.org 2013/12/29 02:49:52 - [key.c] - correct comment for key_drop_cert() - - djm@cvs.openbsd.org 2013/12/29 04:20:04 - [key.c] - to make sure we don't omit any key types as valid CA keys again, - factor the valid key type check into a key_type_is_valid_ca() - function - - djm@cvs.openbsd.org 2013/12/29 04:29:25 - [authfd.c] - allow deletion of ed25519 keys from the agent - - djm@cvs.openbsd.org 2013/12/29 04:35:50 - [authfile.c] - don't refuse to load Ed25519 certificates - - djm@cvs.openbsd.org 2013/12/29 05:42:16 - [ssh.c] - don't forget to load Ed25519 certs too - - djm@cvs.openbsd.org 2013/12/29 05:57:02 - [sshconnect.c] - when showing other hostkeys, don't forget Ed25519 keys - -20131221 - - (dtucker) [regress/keytype.sh] Actually test ecdsa key types. - -20131219 - - (dtucker) [configure.ac] bz#2178: Don't try to use BSM on Solaris versions - greater than 11 either rather than just 11. Patch from Tomas Kuthan. - - (dtucker) [auth-pam.c] bz#2163: check return value from pam_get_item(). - Patch from Loganaden Velvindron. - -20131218 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/12/07 08:08:26 - [ssh-keygen.1] - document -a and -o wrt new key format - - naddy@cvs.openbsd.org 2013/12/07 11:58:46 - [ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh-keysign.8 ssh.1] - [ssh_config.5 sshd.8 sshd_config.5] - add missing mentions of ed25519; ok djm@ - - dtucker@cvs.openbsd.org 2013/12/08 09:53:27 - [sshd_config.5] - Use a literal for the default value of KEXAlgorithms. ok deraadt jmc - - markus@cvs.openbsd.org 2013/12/09 11:03:45 - [blocks.c ed25519.c fe25519.c fe25519.h ge25519.c ge25519.h] - [ge25519_base.data hash.c sc25519.c sc25519.h verify.c] - Add Authors for the public domain ed25519/nacl code. - see also http://nacl.cr.yp.to/features.html - All of the NaCl software is in the public domain. - and http://ed25519.cr.yp.to/software.html - The Ed25519 software is in the public domain. - - markus@cvs.openbsd.org 2013/12/09 11:08:17 - [crypto_api.h] - remove unused defines - - pascal@cvs.openbsd.org 2013/12/15 18:17:26 - [ssh-add.c] - Make ssh-add also add .ssh/id_ed25519; fixes lie in manual page. - ok markus@ - - djm@cvs.openbsd.org 2013/12/15 21:42:35 - [cipher-chachapoly.c] - add some comments and constify a constant - - markus@cvs.openbsd.org 2013/12/17 10:36:38 - [crypto_api.h] - I've assempled the header file by cut&pasting from generated headers - and the source files. - -20131208 - - (djm) [openbsd-compat/bsd-setres_id.c] Missing header; from Corinna - Vinschen - - (djm) [Makefile.in regress/Makefile regress/agent-ptrace.sh] - [regress/setuid-allowed.c] Check that ssh-agent is not on a no-setuid - filesystem before running agent-ptrace.sh; ok dtucker - -20131207 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/12/05 22:59:45 - [sftp-client.c] - fix memory leak in error path in do_readdir(); pointed out by - Loganaden Velvindron @ AfriNIC in bz#2163 - - djm@cvs.openbsd.org 2013/12/06 03:40:51 - [ssh-keygen.c] - remove duplicated character ('g') in getopt() string; - document the (few) remaining option characters so we don't have to - rummage next time. - - markus@cvs.openbsd.org 2013/12/06 13:30:08 - [authfd.c key.c key.h ssh-agent.c] - move private key (de)serialization to key.c; ok djm - - markus@cvs.openbsd.org 2013/12/06 13:34:54 - [authfile.c authfile.h cipher.c cipher.h key.c packet.c ssh-agent.c] - [ssh-keygen.c PROTOCOL.key] new private key format, bcrypt as KDF by - default; details in PROTOCOL.key; feedback and lots help from djm; - ok djm@ - - markus@cvs.openbsd.org 2013/12/06 13:39:49 - [authfd.c authfile.c key.c key.h myproposal.h pathnames.h readconf.c] - [servconf.c ssh-agent.c ssh-keygen.c ssh-keyscan.1 ssh-keyscan.c] - [ssh-keysign.c ssh.c ssh_config.5 sshd.8 sshd.c verify.c ssh-ed25519.c] - [sc25519.h sc25519.c hash.c ge25519_base.data ge25519.h ge25519.c] - [fe25519.h fe25519.c ed25519.c crypto_api.h blocks.c] - support ed25519 keys (hostkeys and user identities) using the public - domain ed25519 reference code from SUPERCOP, see - http://ed25519.cr.yp.to/software.html - feedback, help & ok djm@ - - jmc@cvs.openbsd.org 2013/12/06 15:29:07 - [sshd.8] - missing comma; - - djm@cvs.openbsd.org 2013/12/07 00:19:15 - [key.c] - set k->cert = NULL after freeing it - - markus@cvs.openbsd.org 2013/12/06 13:52:46 - [regress/Makefile regress/agent.sh regress/cert-hostkey.sh] - [regress/cert-userkey.sh regress/keytype.sh] - test ed25519 support; from djm@ - - (djm) [blocks.c ed25519.c fe25519.c fe25519.h ge25519.c ge25519.h] - [ge25519_base.data hash.c sc25519.c sc25519.h verify.c] Fix RCS idents - - (djm) [Makefile.in] Add ed25519 sources - - (djm) [authfile.c] Conditionalise inclusion of util.h - - (djm) [configure.ac openbsd-compat/Makefile.in openbsd-compat/bcrypt_pbkdf.c] - [openbsd-compat/blf.h openbsd-compat/blowfish.c] - [openbsd-compat/openbsd-compat.h] Start at supporting bcrypt_pbkdf in - portable. - - (djm) [ed25519.c ssh-ed25519.c openbsd-compat/Makefile.in] - [openbsd-compat/bcrypt_pbkdf.c] Make ed25519/new key format compile on - Linux - - (djm) [regress/cert-hostkey.sh] Fix merge botch - - (djm) [Makefile.in] PATHSUBS and keygen bits for Ed25519; from - Loganaden Velvindron @ AfriNIC in bz#2179 - -20131205 - - (djm) OpenBSD CVS Sync - - jmc@cvs.openbsd.org 2013/11/21 08:05:09 - [ssh_config.5 sshd_config.5] - no need for .Pp before displays; - - deraadt@cvs.openbsd.org 2013/11/25 18:04:21 - [ssh.1 ssh.c] - improve -Q usage and such. One usage change is that the option is now - case-sensitive - ok dtucker markus djm - - jmc@cvs.openbsd.org 2013/11/26 12:14:54 - [ssh.1 ssh.c] - - put -Q in the right place - - Ar was a poor choice for the arguments to -Q. i've chosen an - admittedly equally poor Cm, at least consistent with the rest - of the docs. also no need for multiple instances - - zap a now redundant Nm - - usage() sync - - deraadt@cvs.openbsd.org 2013/11/26 19:15:09 - [pkcs11.h] - cleanup 1 << 31 idioms. Resurrection of this issue pointed out by - Eitan Adler ok markus for ssh, implies same change in kerberosV - - djm@cvs.openbsd.org 2013/12/01 23:19:05 - [PROTOCOL] - mention curve25519-sha256@libssh.org key exchange algorithm - - djm@cvs.openbsd.org 2013/12/02 02:50:27 - [PROTOCOL.chacha20poly1305] - typo; from Jon Cave - - djm@cvs.openbsd.org 2013/12/02 02:56:17 - [ssh-pkcs11-helper.c] - use-after-free; bz#2175 patch from Loganaden Velvindron @ AfriNIC - - djm@cvs.openbsd.org 2013/12/02 03:09:22 - [key.c] - make key_to_blob() return a NULL blob on failure; part of - bz#2175 from Loganaden Velvindron @ AfriNIC - - djm@cvs.openbsd.org 2013/12/02 03:13:14 - [cipher.c] - correct bzero of chacha20+poly1305 key context. bz#2177 from - Loganaden Velvindron @ AfriNIC - - Also make it a memset for consistency with the rest of cipher.c - - djm@cvs.openbsd.org 2013/12/04 04:20:01 - [sftp-client.c] - bz#2171: don't leak local_fd on error; from Loganaden Velvindron @ - AfriNIC - - djm@cvs.openbsd.org 2013/12/05 01:16:41 - [servconf.c servconf.h] - bz#2161 - fix AuthorizedKeysCommand inside a Match block and - rearrange things so the same error is harder to make next time; - with and ok dtucker@ - - (dtucker) [configure.ac] bz#2173: use pkg-config --libs to include correct - -L location for libedit. Patch from Serge van den Boom. - -20131121 - - (djm) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/11/08 11:15:19 - [bufaux.c bufbn.c buffer.c sftp-client.c sftp-common.c sftp-glob.c] - [uidswap.c] Include stdlib.h for free() as per the man page. - - markus@cvs.openbsd.org 2013/11/13 13:48:20 - [ssh-pkcs11.c] - add missing braces found by pedro - - djm@cvs.openbsd.org 2013/11/20 02:19:01 - [sshd.c] - delay closure of in/out fds until after "Bad protocol version - identification..." message, as get_remote_ipaddr/get_remote_port - require them open. - - deraadt@cvs.openbsd.org 2013/11/20 20:53:10 - [scp.c] - unsigned casts for ctype macros where neccessary - ok guenther millert markus - - deraadt@cvs.openbsd.org 2013/11/20 20:54:10 - [canohost.c clientloop.c match.c readconf.c sftp.c] - unsigned casts for ctype macros where neccessary - ok guenther millert markus - - djm@cvs.openbsd.org 2013/11/21 00:45:44 - [Makefile.in PROTOCOL PROTOCOL.chacha20poly1305 authfile.c chacha.c] - [chacha.h cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h] - [dh.c myproposal.h packet.c poly1305.c poly1305.h servconf.c ssh.1] - [ssh.c ssh_config.5 sshd_config.5] Add a new protocol 2 transport - cipher "chacha20-poly1305@openssh.com" that combines Daniel - Bernstein's ChaCha20 stream cipher and Poly1305 MAC to build an - authenticated encryption mode. - - Inspired by and similar to Adam Langley's proposal for TLS: - http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 - but differs in layout used for the MAC calculation and the use of a - second ChaCha20 instance to separately encrypt packet lengths. - Details are in the PROTOCOL.chacha20poly1305 file. - - Feedback markus@, naddy@; manpage bits Loganden Velvindron @ AfriNIC - ok markus@ naddy@ - - naddy@cvs.openbsd.org 2013/11/18 05:09:32 - [regress/forward-control.sh] - bump timeout to 10 seconds to allow slow machines (e.g. Alpha PC164) - to successfully run this; ok djm@ - - djm@cvs.openbsd.org 2013/11/21 03:15:46 - [regress/krl.sh] - add some reminders for additional tests that I'd like to implement - - djm@cvs.openbsd.org 2013/11/21 03:16:47 - [regress/modpipe.c] - use unsigned long long instead of u_int64_t here to avoid warnings - on some systems portable OpenSSH is built on. - - djm@cvs.openbsd.org 2013/11/21 03:18:51 - [regress/cipher-speed.sh regress/integrity.sh regress/rekey.sh] - [regress/try-ciphers.sh] - use new "ssh -Q cipher-auth" query to obtain lists of authenticated - encryption ciphers instead of specifying them manually; ensures that - the new chacha20poly1305@openssh.com mode is tested; - - ok markus@ and naddy@ as part of the diff to add - chacha20poly1305@openssh.com - -20131110 - - (dtucker) [regress/keytype.sh] Populate ECDSA key types to be tested by - querying the ones that are compiled in. - -20131109 - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/11/09 05:41:34 - [regress/test-exec.sh regress/rekey.sh] - Use smaller test data files to speed up tests. Grow test datafiles - where necessary for a specific test. - - (dtucker) [configure.ac kex.c key.c myproposal.h] Test for the presence of - NID_X9_62_prime256v1, NID_secp384r1 and NID_secp521r1 and test that the - latter actually works before using it. Fedora (at least) has NID_secp521r1 - that doesn't work (see https://bugzilla.redhat.com/show_bug.cgi?id=1021897). - - (dtucker) [configure.ac] Fix brackets in NID_secp521r1 test. - - (dtucker) [configure.ac] Add missing "test". - - (dtucker) [key.c] Check for the correct defines for NID_secp521r1. - -20131108 - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/11/08 01:06:14 - [regress/rekey.sh] - Rekey less frequently during tests to speed them up - - (djm) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/11/07 11:58:27 - [cipher.c cipher.h kex.c kex.h mac.c mac.h servconf.c ssh.c] - Output the effective values of Ciphers, MACs and KexAlgorithms when - the default has not been overridden. ok markus@ - - djm@cvs.openbsd.org 2013/11/08 00:39:15 - [auth-options.c auth2-chall.c authfd.c channels.c cipher-3des1.c] - [clientloop.c gss-genr.c monitor_mm.c packet.c schnorr.c umac.c] - [sftp-client.c sftp-glob.c] - use calloc for all structure allocations; from markus@ - - djm@cvs.openbsd.org 2013/11/08 01:38:11 - [version.h] - openssh-6.4 - - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec] - [contrib/suse/openssh.spec] Update version numbers following release. - - (dtucker) [openbsd-compat/openbsd-compat.h] Add null implementation of - arc4random_stir for platforms that have arc4random but don't have - arc4random_stir (right now this is only OpenBSD -current). - - (dtucker) [kex.c] Only enable CURVE25519_SHA256 if we actually have - EVP_sha256. - - (dtucker) [myproposal.h] Conditionally enable CURVE25519_SHA256. - - (dtucker) [openbsd-compat/bsd-poll.c] Add headers to prevent compile - warnings. - - (dtucker) [Makefile.in configure.ac] Set MALLOC_OPTIONS per platform - and pass in TEST_ENV. use stderr to get polluted - and the stderr-data test to fail. - - (dtucker) [contrib/cygwin/ssh-host-config] Simplify host key generation: - rather than testing and generating each key, call ssh-keygen -A. - Patch from vinschen at redhat.com. - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/11/09 05:41:34 - [regress/test-exec.sh regress/rekey.sh] - Use smaller test data files to speed up tests. Grow test datafiles - where necessary for a specific test. - -20131107 - - (djm) [ssh-pkcs11.c] Bring back "non-constant initialiser" fix (rev 1.5) - that got lost in recent merge. - - (djm) [Makefile.in monitor.c] Missed chunks of curve25519 KEX diff - - (djm) [regress/modpipe.c regress/rekey.sh] Never intended to commit these - - (djm) [configure.ac defines.h] Skip arc4random_stir() calls on platforms - that lack it but have arc4random_uniform() - - (djm) OpenBSD CVS Sync - - markus@cvs.openbsd.org 2013/11/04 11:51:16 - [monitor.c] - fix rekeying for KEX_C25519_SHA256; noted by dtucker@ - RCSID sync only; I thought this was a merge botch and fixed it already - - markus@cvs.openbsd.org 2013/11/06 16:52:11 - [monitor_wrap.c] - fix rekeying for AES-GCM modes; ok deraadt - - djm@cvs.openbsd.org 2013/11/06 23:05:59 - [ssh-pkcs11.c] - from portable: s/true/true_val/ to avoid name collisions on dump platforms - RCSID sync only - - (dtucker) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/10/09 23:44:14 - [regress/Makefile] (ID sync only) - regression test for sftp request white/blacklisting and readonly mode. - - markus@cvs.openbsd.org 2013/11/02 22:39:53 - [regress/kextype.sh] - add curve25519-sha256@libssh.org - - dtucker@cvs.openbsd.org 2013/11/04 12:27:42 - [regress/rekey.sh] - Test rekeying with all KexAlgorithms. - - dtucker@cvs.openbsd.org 2013/11/07 00:12:05 - [regress/rekey.sh] - Test rekeying for every Cipher, MAC and KEX, plus test every KEX with - the GCM ciphers. - - dtucker@cvs.openbsd.org 2013/11/07 01:12:51 - [regress/rekey.sh] - Factor out the data transfer rekey tests - - dtucker@cvs.openbsd.org 2013/11/07 02:48:38 - [regress/integrity.sh regress/cipher-speed.sh regress/try-ciphers.sh] - Use ssh -Q instead of hardcoding lists of ciphers or MACs. - - dtucker@cvs.openbsd.org 2013/11/07 03:55:41 - [regress/kextype.sh] - Use ssh -Q to get kex types instead of a static list. - - dtucker@cvs.openbsd.org 2013/11/07 04:26:56 - [regress/kextype.sh] - trailing space - - (dtucker) [Makefile.in configure.ac] Remove TEST_SSH_SHA256 environment - variable. It's no longer used now that we get the supported MACs from - ssh -Q. - -20131104 - - (djm) OpenBSD CVS Sync - - markus@cvs.openbsd.org 2013/11/02 20:03:54 - [ssh-pkcs11.c] - support pkcs#11 tokes that only provide x509 zerts instead of raw pubkeys; - fixes bz#1908; based on patch from Laurent Barbe; ok djm - - markus@cvs.openbsd.org 2013/11/02 21:59:15 - [kex.c kex.h myproposal.h ssh-keyscan.c sshconnect2.c sshd.c] - use curve25519 for default key exchange (curve25519-sha256@libssh.org); - initial patch from Aris Adamantiadis; ok djm@ - - markus@cvs.openbsd.org 2013/11/02 22:10:15 - [kexdhs.c kexecdhs.c] - no need to include monitor_wrap.h - - markus@cvs.openbsd.org 2013/11/02 22:24:24 - [kexdhs.c kexecdhs.c] - no need to include ssh-gss.h - - markus@cvs.openbsd.org 2013/11/02 22:34:01 - [auth-options.c] - no need to include monitor_wrap.h and ssh-gss.h - - markus@cvs.openbsd.org 2013/11/02 22:39:19 - [ssh_config.5 sshd_config.5] - the default kex is now curve25519-sha256@libssh.org - - djm@cvs.openbsd.org 2013/11/03 10:37:19 - [roaming_common.c] - fix a couple of function definitions foo() -> foo(void) - (-Wold-style-definition) - - (djm) [kexc25519.c kexc25519c.c kexc25519s.c] Import missed files from - KEX/curve25519 change - -20131103 - - (dtucker) [openbsd-compat/bsd-misc.c] Include time.h for nanosleep. - From OpenSMTPD where it prevents "implicit declaration" warnings (it's - a no-op in OpenSSH). From chl at openbsd. - - (dtucker) [openbsd-compat/setproctitle.c] Handle error case form the 2nd - vsnprintf. From eric at openbsd via chl@. - - (dtucker) [configure.ac defines.h] Add typedefs for intmax_t and uintmax_t - for platforms that don't have them. - -20131030 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/10/29 09:42:11 - [key.c key.h] - fix potential stack exhaustion caused by nested certificates; - report by Mateusz Kocielski; ok dtucker@ markus@ - - djm@cvs.openbsd.org 2013/10/29 09:48:02 - [servconf.c servconf.h session.c sshd_config sshd_config.5] - shd_config PermitTTY to disallow TTY allocation, mirroring the - longstanding no-pty authorized_keys option; - bz#2070, patch from Teran McKinney; ok markus@ - - jmc@cvs.openbsd.org 2013/10/29 18:49:32 - [sshd_config.5] - pty(4), not pty(7); - -20131026 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/10/25 23:04:51 - [ssh.c] - fix crash when using ProxyCommand caused by previous commit - was calling - freeaddrinfo(NULL); spotted by sthen@ and Tim Ruehsen, patch by sthen@ - -20131025 - - (djm) [ssh-keygen.c ssh-keysign.c sshconnect1.c sshd.c] Remove - unnecessary arc4random_stir() calls. The only ones left are to ensure - that the PRNG gets a different state after fork() for platforms that - have broken the API. - -20131024 - - (djm) [auth-krb5.c] bz#2032 - use local username in krb5_kuserok check - rather than full client name which may be of form user@REALM; - patch from Miguel Sanders; ok dtucker@ - - (djm) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/10/23 05:40:58 - [servconf.c] - fix comment - - djm@cvs.openbsd.org 2013/10/23 23:35:32 - [sshd.c] - include local address and port in "Connection from ..." message (only - shown at loglevel>=verbose) - - dtucker@cvs.openbsd.org 2013/10/24 00:49:49 - [moduli.c] - Periodically print progress and, if possible, expected time to completion - when screening moduli for DH groups. ok deraadt djm - - dtucker@cvs.openbsd.org 2013/10/24 00:51:48 - [readconf.c servconf.c ssh_config.5 sshd_config.5] - Disallow empty Match statements and add "Match all" which matches - everything. ok djm, man page help jmc@ - - djm@cvs.openbsd.org 2013/10/24 08:19:36 - [ssh.c] - fix bug introduced in hostname canonicalisation commit: don't try to - resolve hostnames when a ProxyCommand is set unless the user has forced - canonicalisation; spotted by Iain Morgan - - (tim) [regress/sftp-perm.sh] We need a shell that understands "! somecmd" - -20131023 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/10/20 04:39:28 - [ssh_config.5] - document % expansions performed by "Match command ..." - - djm@cvs.openbsd.org 2013/10/20 06:19:28 - [readconf.c ssh_config.5] - rename "command" subclause of the recently-added "Match" keyword to - "exec"; it's shorter, clearer in intent and we might want to add the - ability to match against the command being executed at the remote end in - the future. - - djm@cvs.openbsd.org 2013/10/20 09:51:26 - [scp.1 sftp.1] - add canonicalisation options to -o lists - - jmc@cvs.openbsd.org 2013/10/20 18:00:13 - [ssh_config.5] - tweak the "exec" description, as worded by djm; - - djm@cvs.openbsd.org 2013/10/23 03:03:07 - [readconf.c] - Hostname may have %h sequences that should be expanded prior to Match - evaluation; spotted by Iain Morgan - - djm@cvs.openbsd.org 2013/10/23 03:05:19 - [readconf.c ssh.c] - comment - - djm@cvs.openbsd.org 2013/10/23 04:16:22 - [ssh-keygen.c] - Make code match documentation: relative-specified certificate expiry time - should be relative to current time and not the validity start time. - Reported by Petr Lautrbach; ok deraadt@ - -20131018 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/10/09 23:44:14 - [regress/Makefile regress/sftp-perm.sh] - regression test for sftp request white/blacklisting and readonly mode. - - jmc@cvs.openbsd.org 2013/10/17 07:35:48 - [sftp.1 sftp.c] - tweak previous; - - djm@cvs.openbsd.org 2013/10/17 22:08:04 - [sshd.c] - include remote port in bad banner message; bz#2162 - -20131017 - - (djm) OpenBSD CVS Sync - - jmc@cvs.openbsd.org 2013/10/15 14:10:25 - [ssh.1 ssh_config.5] - tweak previous; - - djm@cvs.openbsd.org 2013/10/16 02:31:47 - [readconf.c readconf.h roaming_client.c ssh.1 ssh.c ssh_config.5] - [sshconnect.c sshconnect.h] - Implement client-side hostname canonicalisation to allow an explicit - search path of domain suffixes to use to convert unqualified host names - to fully-qualified ones for host key matching. - This is particularly useful for host certificates, which would otherwise - need to list unqualified names alongside fully-qualified ones (and this - causes a number of problems). - "looks fine" markus@ - - jmc@cvs.openbsd.org 2013/10/16 06:42:25 - [ssh_config.5] - tweak previous; - - djm@cvs.openbsd.org 2013/10/16 22:49:39 - [readconf.c readconf.h ssh.1 ssh.c ssh_config.5] - s/canonicalise/canonicalize/ for consistency with existing spelling, - e.g. authorized_keys; pointed out by naddy@ - - djm@cvs.openbsd.org 2013/10/16 22:58:01 - [ssh.c ssh_config.5] - one I missed in previous: s/isation/ization/ - - djm@cvs.openbsd.org 2013/10/17 00:30:13 - [PROTOCOL sftp-client.c sftp-client.h sftp-server.c sftp.1 sftp.c] - fsync@openssh.com protocol extension for sftp-server - client support to allow calling fsync() faster successful transfer - patch mostly by imorgan AT nas.nasa.gov; bz#1798 - "fine" markus@ "grumble OK" deraadt@ "doesn't sound bad to me" millert@ - - djm@cvs.openbsd.org 2013/10/17 00:46:49 - [ssh.c] - rearrange check to reduce diff against -portable - (Id sync only) - -20131015 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/10/09 23:42:17 - [sftp-server.8 sftp-server.c] - Add ability to whitelist and/or blacklist sftp protocol requests by name. - Refactor dispatch loop and consolidate read-only mode checks. - Make global variables static, since sftp-server is linked into sshd(8). - ok dtucker@ - - djm@cvs.openbsd.org 2013/10/10 00:53:25 - [sftp-server.c] - add -Q, -P and -p to usage() before jmc@ catches me - - djm@cvs.openbsd.org 2013/10/10 01:43:03 - [sshd.c] - bz#2139: fix re-exec fallback by ensuring that startup_pipe is correctly - updated; ok dtucker@ - - djm@cvs.openbsd.org 2013/10/11 02:45:36 - [sftp-client.c] - rename flag arguments to be more clear and consistent. - reorder some internal function arguments to make adding additional flags - easier. - no functional change - - djm@cvs.openbsd.org 2013/10/11 02:52:23 - [sftp-client.c] - missed one arg reorder - - djm@cvs.openbsd.org 2013/10/11 02:53:45 - [sftp-client.h] - obsolete comment - - jmc@cvs.openbsd.org 2013/10/14 14:18:56 - [sftp-server.8 sftp-server.c] - tweak previous; - ok djm - - djm@cvs.openbsd.org 2013/10/14 21:20:52 - [session.c session.h] - Add logging of session starts in a useful format; ok markus@ feedback and - ok dtucker@ - - djm@cvs.openbsd.org 2013/10/14 22:22:05 - [readconf.c readconf.h ssh-keysign.c ssh.c ssh_config.5] - add a "Match" keyword to ssh_config that allows matching on hostname, - user and result of arbitrary commands. "nice work" markus@ - - djm@cvs.openbsd.org 2013/10/14 23:28:23 - [canohost.c misc.c misc.h readconf.c sftp-server.c ssh.c] - refactor client config code a little: - add multistate option partsing to readconf.c, similar to servconf.c's - existing code. - move checking of options that accept "none" as an argument to readconf.c - add a lowercase() function and use it instead of explicit tolower() in - loops - part of a larger diff that was ok markus@ - - djm@cvs.openbsd.org 2013/10/14 23:31:01 - [ssh.c] - whitespace at EOL; pointed out by markus@ - - [ssh.c] g/c unused variable. - -20131010 - - (dtucker) OpenBSD CVS Sync - - sthen@cvs.openbsd.org 2013/09/16 11:35:43 - [ssh_config] - Remove gssapi config parts from ssh_config, as was already done for - sshd_config. Req by/ok ajacoutot@ - ID SYNC ONLY for portable; kerberos/gssapi is still pretty popular - - djm@cvs.openbsd.org 2013/09/19 00:24:52 - [progressmeter.c] - store the initial file offset so the progress meter doesn't freak out - when resuming sftp transfers. bz#2137; patch from Iain Morgan; ok dtucker@` - - djm@cvs.openbsd.org 2013/09/19 00:49:12 - [sftp-client.c] - fix swapped pflag and printflag in sftp upload_dir; from Iain Morgan - - djm@cvs.openbsd.org 2013/09/19 01:24:46 - [channels.c] - bz#1297 - tell the client (via packet_send_debug) when their preferred - listen address has been overridden by the server's GatewayPorts; - ok dtucker@ - - djm@cvs.openbsd.org 2013/09/19 01:26:29 - [sshconnect.c] - bz#1211: make BindAddress work with UsePrivilegedPort=yes; patch from - swp AT swp.pp.ru; ok dtucker@ - - dtucker@cvs.openbsd.org 2013/10/08 11:42:13 - [dh.c dh.h] - Increase the size of the Diffie-Hellman groups requested for a each - symmetric key size. New values from NIST Special Publication 800-57 with - the upper limit specified by RFC4419. Pointed out by Peter Backes, ok - djm@. - -20131009 - - (djm) [openbsd-compat/arc4random.c openbsd-compat/chacha_private.h] Pull - in OpenBSD implementation of arc4random, shortly to replace the existing - bsd-arc4random.c - - (djm) [openbsd-compat/Makefile.in openbsd-compat/arc4random.c] - [openbsd-compat/bsd-arc4random.c] Replace old RC4-based arc4random - implementation with recent OpenBSD's ChaCha-based PRNG. ok dtucker@, - tested tim@ - -20130922 - - (dtucker) [platform.c platform.h sshd.c] bz#2156: restore Linux oom_adj - setting when handling SIGHUP to maintain behaviour over retart. Patch - from Matthew Ife. - -20130918 - - (dtucker) [sshd_config] Trailing whitespace; from jstjohn at purdue edu. - -20130914 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/08/22 19:02:21 - [sshd.c] - Stir PRNG after post-accept fork. The child gets a different PRNG state - anyway via rexec and explicit privsep reseeds, but it's good to be sure. - ok markus@ - - mikeb@cvs.openbsd.org 2013/08/28 12:34:27 - [ssh-keygen.c] - improve batch processing a bit by making use of the quite flag a bit - more often and exit with a non zero code if asked to find a hostname - in a known_hosts file and it wasn't there; - originally from reyk@, ok djm - - djm@cvs.openbsd.org 2013/08/31 00:13:54 - [sftp.c] - make ^w match ksh behaviour (delete previous word instead of entire line) - - deraadt@cvs.openbsd.org 2013/09/02 22:00:34 - [ssh-keygen.c sshconnect1.c sshd.c] - All the instances of arc4random_stir() are bogus, since arc4random() - does this itself, inside itself, and has for a very long time.. Actually, - this was probably reducing the entropy available. - ok djm - ID SYNC ONLY for portable; we don't trust other arc4random implementations - to do this right. - - sthen@cvs.openbsd.org 2013/09/07 13:53:11 - [sshd_config] - Remove commented-out kerberos/gssapi config options from sample config, - kerberos support is currently not enabled in ssh in OpenBSD. Discussed with - various people; ok deraadt@ - ID SYNC ONLY for portable; kerberos/gssapi is still pretty popular - - djm@cvs.openbsd.org 2013/09/12 01:41:12 - [clientloop.c] - fix connection crash when sending break (~B) on ControlPersist'd session; - ok dtucker@ - - djm@cvs.openbsd.org 2013/09/13 06:54:34 - [channels.c] - avoid unaligned access in code that reused a buffer to send a - struct in_addr in a reply; simpler just use use buffer_put_int(); - from portable; spotted by and ok dtucker@ - -20130828 - - (djm) [openbsd-compat/bsd-snprintf.c] teach our local snprintf code the - 'j' (intmax_t/uintmax_t) and 'z' (size_t/ssize_t) conversions in case we - start to use them in the future. - - (djm) [openbsd-compat/bsd-snprintf.c] #ifdef noytet for intmax_t bits - until we have configure support. - -20130821 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/08/06 23:03:49 - [sftp.c] - fix some whitespace at EOL - make list of commands an enum rather than a long list of defines - add -a to usage() - - djm@cvs.openbsd.org 2013/08/06 23:05:01 - [sftp.1] - document top-level -a option (the -a option to 'get' was already - documented) - - djm@cvs.openbsd.org 2013/08/06 23:06:01 - [servconf.c] - add cast to avoid format warning; from portable - - jmc@cvs.openbsd.org 2013/08/07 06:24:51 - [sftp.1 sftp.c] - sort -a; - - djm@cvs.openbsd.org 2013/08/08 04:52:04 - [sftp.c] - fix two year old regression: symlinking a file would incorrectly - canonicalise the target path. bz#2129 report from delphij AT freebsd.org - - djm@cvs.openbsd.org 2013/08/08 05:04:03 - [sftp-client.c sftp-client.h sftp.c] - add a "-l" flag for the rename command to force it to use the silly - standard SSH_FXP_RENAME command instead of the POSIX-rename- like - posix-rename@openssh.com extension. - - intended for use in regress tests, so no documentation. - - djm@cvs.openbsd.org 2013/08/09 03:37:25 - [sftp.c] - do getopt parsing for all sftp commands (with an empty optstring for - commands without arguments) to ensure consistent behaviour - - djm@cvs.openbsd.org 2013/08/09 03:39:13 - [sftp-client.c] - two problems found by a to-be-committed regress test: 1) msg_id was not - being initialised so was starting at a random value from the heap - (harmless, but confusing). 2) some error conditions were not being - propagated back to the caller - - djm@cvs.openbsd.org 2013/08/09 03:56:42 - [sftp.c] - enable ctrl-left-arrow and ctrl-right-arrow to move forward/back a word; - matching ksh's relatively recent change. - - djm@cvs.openbsd.org 2013/08/13 18:32:08 - [ssh-keygen.c] - typo in error message; from Stephan Rickauer - - djm@cvs.openbsd.org 2013/08/13 18:33:08 - [ssh-keygen.c] - another of the same typo - - jmc@cvs.openbsd.org 2013/08/14 08:39:27 - [scp.1 ssh.1] - some Bx/Ox conversion; - From: Jan Stary - - djm@cvs.openbsd.org 2013/08/20 00:11:38 - [readconf.c readconf.h ssh_config.5 sshconnect.c] - Add a ssh_config ProxyUseFDPass option that supports the use of - ProxyCommands that establish a connection and then pass a connected - file descriptor back to ssh(1). This allows the ProxyCommand to exit - rather than have to shuffle data back and forth and enables ssh to use - getpeername, etc. to obtain address information just like it does with - regular directly-connected sockets. ok markus@ - - jmc@cvs.openbsd.org 2013/08/20 06:56:07 - [ssh.1 ssh_config.5] - some proxyusefdpass tweaks; - -20130808 - - (dtucker) [regress/Makefile regress/test-exec.sh] Don't try to use test -nt - since some platforms (eg really old FreeBSD) don't have it. Instead, - run "make clean" before a complete regress run. ok djm. - - (dtucker) [misc.c] Fall back to time(2) at runtime if clock_gettime( - CLOCK_MONOTONIC...) fails. Some older versions of RHEL have the - CLOCK_MONOTONIC define but don't actually support it. Found and tested - by Kevin Brott, ok djm. - - (dtucker) [misc.c] Remove define added for fallback testing that was - mistakenly included in the previous commit. - - (dtucker) [regress/Makefile regress/test-exec.sh] Roll back the -nt - removal. The "make clean" removes modpipe which is built by the top-level - directory before running the tests. Spotted by tim@ - - (djm) Release 6.3p1 - -20130804 - - (dtucker) [auth-krb5.c configure.ac openbsd-compat/bsd-misc.h] Add support - for building with older Heimdal versions. ok djm. - -20130801 - - (djm) [channels.c channels.h] bz#2135: On Solaris, isatty() on a non- - blocking connecting socket will clear any stored errno that might - otherwise have been retrievable via getsockopt(). A hack to limit writes - to TTYs on AIX was triggering this. Since only AIX needs the hack, wrap - it in an #ifdef. Diagnosis and patch from Ivo Raisr. - - (djm) [sshlogin.h] Fix prototype merge botch from 2006; bz#2134 - -20130725 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/07/20 22:20:42 - [krl.c] - fix verification error in (as-yet usused) KRL signature checking path - - djm@cvs.openbsd.org 2013/07/22 05:00:17 - [umac.c] - make MAC key, data to be hashed and nonce for final hash const; - checked with -Wcast-qual - - djm@cvs.openbsd.org 2013/07/22 12:20:02 - [umac.h] - oops, forgot to commit corresponding header change; - spotted by jsg and jasper - - djm@cvs.openbsd.org 2013/07/25 00:29:10 - [ssh.c] - daemonise backgrounded (ControlPersist'ed) multiplexing master to ensure - it is fully detached from its controlling terminal. based on debugging - - djm@cvs.openbsd.org 2013/07/25 00:56:52 - [sftp-client.c sftp-client.h sftp.1 sftp.c] - sftp support for resuming partial downloads; patch mostly by Loganaden - Velvindron/AfriNIC with some tweaks by me; feedback and ok dtucker@ - "Just be careful" deraadt@ - - djm@cvs.openbsd.org 2013/07/25 00:57:37 - [version.h] - openssh-6.3 for release - - dtucker@cvs.openbsd.org 2013/05/30 20:12:32 - [regress/test-exec.sh] - use ssh and sshd as testdata since it needs to be >256k for the rekey test - - dtucker@cvs.openbsd.org 2013/06/10 21:56:43 - [regress/forwarding.sh] - Add test for forward config parsing - - djm@cvs.openbsd.org 2013/06/21 02:26:26 - [regress/sftp-cmds.sh regress/test-exec.sh] - unbreak sftp-cmds for renamed test data (s/ls/data/) - - (tim) [sftp-client.c] Use of a gcc extension trips up native compilers on - Solaris and UnixWare. Feedback and OK djm@ - - (tim) [regress/forwarding.sh] Fix for building outside source tree. - -20130720 - - (djm) OpenBSD CVS Sync - - markus@cvs.openbsd.org 2013/07/19 07:37:48 - [auth.h kex.h kexdhs.c kexecdhs.c kexgexs.c monitor.c servconf.c] - [servconf.h session.c sshd.c sshd_config.5] - add ssh-agent(1) support to sshd(8); allows encrypted hostkeys, - or hostkeys on smartcards; most of the work by Zev Weiss; bz #1974 - ok djm@ - - djm@cvs.openbsd.org 2013/07/20 01:43:46 - [umac.c] - use a union to ensure correct alignment; ok deraadt - - djm@cvs.openbsd.org 2013/07/20 01:44:37 - [ssh-keygen.c ssh.c] - More useful error message on missing current user in /etc/passwd - - djm@cvs.openbsd.org 2013/07/20 01:50:20 - [ssh-agent.c] - call cleanup_handler on SIGINT when in debug mode to ensure sockets - are cleaned up on manual exit; bz#2120 - - djm@cvs.openbsd.org 2013/07/20 01:55:13 - [auth-krb5.c gss-serv-krb5.c gss-serv.c] - fix kerberos/GSSAPI deprecation warnings and linking; "looks okay" millert@ - -20130718 - - (djm) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/06/10 19:19:44 - [readconf.c] - revert 1.203 while we investigate crashes reported by okan@ - - guenther@cvs.openbsd.org 2013/06/17 04:48:42 - [scp.c] - Handle time_t values as long long's when formatting them and when - parsing them from remote servers. - Improve error checking in parsing of 'T' lines. - ok dtucker@ deraadt@ - - markus@cvs.openbsd.org 2013/06/20 19:15:06 - [krl.c] - don't leak the rdata blob on errors; ok djm@ - - djm@cvs.openbsd.org 2013/06/21 00:34:49 - [auth-rsa.c auth.h auth2-hostbased.c auth2-pubkey.c monitor.c] - for hostbased authentication, print the client host and user on - the auth success/failure line; bz#2064, ok dtucker@ - - djm@cvs.openbsd.org 2013/06/21 00:37:49 - [ssh_config.5] - explicitly mention that IdentitiesOnly can be used with IdentityFile - to control which keys are offered from an agent. - - djm@cvs.openbsd.org 2013/06/21 05:42:32 - [dh.c] - sprinkle in some error() to explain moduli(5) parse failures - - djm@cvs.openbsd.org 2013/06/21 05:43:10 - [scp.c] - make this -Wsign-compare clean after time_t conversion - - djm@cvs.openbsd.org 2013/06/22 06:31:57 - [scp.c] - improved time_t overflow check suggested by guenther@ - - jmc@cvs.openbsd.org 2013/06/27 14:05:37 - [ssh-keygen.1 ssh.1 ssh_config.5 sshd.8 sshd_config.5] - do not use Sx for sections outwith the man page - ingo informs me that - stuff like html will render with broken links; - issue reported by Eric S. Raymond, via djm - - markus@cvs.openbsd.org 2013/07/02 12:31:43 - [dh.c] - remove extra whitespace - - djm@cvs.openbsd.org 2013/07/12 00:19:59 - [auth-options.c auth-rsa.c bufaux.c buffer.h channels.c hostfile.c] - [hostfile.h mux.c packet.c packet.h roaming_common.c serverloop.c] - fix pointer-signedness warnings from clang/llvm-3.3; "seems nice" deraadt@ - - djm@cvs.openbsd.org 2013/07/12 00:20:00 - [sftp.c ssh-keygen.c ssh-pkcs11.c] - fix pointer-signedness warnings from clang/llvm-3.3; "seems nice" deraadt@ - - djm@cvs.openbsd.org 2013/07/12 00:43:50 - [misc.c] - in ssh_gai_strerror() don't fallback to strerror for EAI_SYSTEM when - errno == 0. Avoids confusing error message in some broken resolver - cases. bz#2122 patch from plautrba AT redhat.com; ok dtucker - - djm@cvs.openbsd.org 2013/07/12 05:42:03 - [ssh-keygen.c] - do_print_resource_record() can never be called with a NULL filename, so - don't attempt (and bungle) asking for one if it has not been specified - bz#2127 ok dtucker@ - - djm@cvs.openbsd.org 2013/07/12 05:48:55 - [ssh.c] - set TCP nodelay for connections started with -N; bz#2124 ok dtucker@ - - schwarze@cvs.openbsd.org 2013/07/16 00:07:52 - [scp.1 sftp-server.8 ssh-keyscan.1 ssh-keysign.8 ssh-pkcs11-helper.8] - use .Mt for email addresses; from Jan Stary ; ok jmc@ - - djm@cvs.openbsd.org 2013/07/18 01:12:26 - [ssh.1] - be more exact wrt perms for ~/.ssh/config; bz#2078 - -20130702 - - (dtucker) [contrib/cygwin/README contrib/cygwin/ssh-host-config - contrib/cygwin/ssh-user-config] Modernizes and improve readability of - the Cygwin README file (which hasn't been updated for ages), drop - unsupported OSes from the ssh-host-config help text, and drop an - unneeded option from ssh-user-config. Patch from vinschen at redhat com. - -20130610 - - (djm) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/06/07 15:37:52 - [channels.c channels.h clientloop.c] - Add an "ABANDONED" channel state and use for mux sessions that are - disconnected via the ~. escape sequence. Channels in this state will - be able to close if the server responds, but do not count as active channels. - This means that if you ~. all of the mux clients when using ControlPersist - on a broken network, the backgrounded mux master will exit when the - Control Persist time expires rather than hanging around indefinitely. - bz#1917, also reported and tested by tedu@. ok djm@ markus@. - - (dtucker) [Makefile.in configure.ac fixalgorithms] Remove unsupported - algorithms (Ciphers, MACs and HostKeyAlgorithms) from man pages. - - (dtucker) [myproposal.h] Do not advertise AES GSM ciphers if we don't have - the required OpenSSL support. Patch from naddy at freebsd. - - (dtucker) [myproposal.h] Make the conditional algorithm support consistent - and add some comments so it's clear what goes where. - -20130605 - - (dtucker) [myproposal.h] Enable sha256 kex methods based on the presence of - the necessary functions, not from the openssl version. - - (dtucker) [contrib/ssh-copy-id] bz#2117: Use portable operator in test. - Patch from cjwatson at debian. - - (dtucker) [regress/forwarding.sh] For (as yet unknown) reason, the - forwarding test is extremely slow copying data on some machines so switch - back to copying the much smaller ls binary until we can figure out why - this is. - - (dtucker) [Makefile.in] append $CFLAGS to compiler options when building - modpipe in case there's anything in there we need. - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/06/02 21:01:51 - [channels.h] - typo in comment - - dtucker@cvs.openbsd.org 2013/06/02 23:36:29 - [clientloop.h clientloop.c mux.c] - No need for the mux cleanup callback to be visible so restore it to static - and call it through the detach_user function pointer. ok djm@ - - dtucker@cvs.openbsd.org 2013/06/03 00:03:18 - [mac.c] - force the MAC output to be 64-bit aligned so umac won't see unaligned - accesses on strict-alignment architectures. bz#2101, patch from - tomas.kuthan at oracle.com, ok djm@ - - dtucker@cvs.openbsd.org 2013/06/04 19:12:23 - [scp.c] - use MAXPATHLEN for buffer size instead of fixed value. ok markus - - dtucker@cvs.openbsd.org 2013/06/04 20:42:36 - [sftp.c] - Make sftp's libedit interface marginally multibyte aware by building up - the quoted string by character instead of by byte. Prevents failures - when linked against a libedit built with wide character support (bz#1990). - "looks ok" djm - - dtucker@cvs.openbsd.org 2013/06/05 02:07:29 - [mux.c] - fix leaks in mux error paths, from Zhenbo Xu, found by Melton. bz#1967, - ok djm - - dtucker@cvs.openbsd.org 2013/06/05 02:27:50 - [sshd.c] - When running sshd -D, close stderr unless we have explicitly requesting - logging to stderr. From james.hunt at ubuntu.com via bz#1976, djm's patch - so, err, ok dtucker. - - dtucker@cvs.openbsd.org 2013/06/05 12:52:38 - [sshconnect2.c] - Fix memory leaks found by Zhenbo Xu and the Melton tool. bz#1967, ok djm - - dtucker@cvs.openbsd.org 2013/06/05 22:00:28 - [readconf.c] - plug another memleak. bz#1967, from Zhenbo Xu, detected by Melton, ok djm - - (dtucker) [configure.ac sftp.c openbsd-compat/openbsd-compat.h] Cater for - platforms that don't have multibyte character support (specifically, - mblen). - -20130602 - - (tim) [Makefile.in] Make Solaris, UnixWare, & OpenServer linkers happy - linking regress/modpipe. - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/06/02 13:33:05 - [progressmeter.c] - Add misc.h for monotime prototype. (ID sync only). - - dtucker@cvs.openbsd.org 2013/06/02 13:35:58 - [ssh-agent.c] - Make parent_alive_interval time_t to avoid signed/unsigned comparison - - (dtucker) [configure.ac] sys/un.h needs sys/socket.h on some platforms - to prevent noise from configure. Patch from Nathan Osman. (bz#2114). - - (dtucker) [configure.ac] bz#2111: don't try to use lastlog on Android. - Patch from Nathan Osman. - - (tim) [configure.ac regress/Makefile] With rev 1.47 of test-exec.sh we - need a shell that can handle "[ file1 -nt file2 ]". Rather than keep - dealing with shell portability issues in regression tests, we let - configure find us a capable shell on those platforms with an old /bin/sh. - - (tim) [aclocal.m4] Enhance OSSH_CHECK_CFLAG_COMPILE to check stderr. - feedback and ok dtucker - - (tim) [regress/sftp-chroot.sh] skip if no sudo. ok dtucker - - (dtucker) [configure.ac] Some platforms need sys/types.h before sys/un.h. - - (dtucker) [configure.ac] Some other platforms need sys/types.h before - sys/socket.h. - -20130601 - - (dtucker) [configure.ac openbsd-compat/xcrypt.c] bz#2112: fall back to - using openssl's DES_crypt function on platorms that don't have a native - one, eg Android. Based on a patch from Nathan Osman. - - (dtucker) [configure.ac defines.h] Test for fd_mask, howmany and NFDBITS - rather than trying to enumerate the plaforms that don't have them. - Based on a patch from Nathan Osman, with help from tim@. - - (dtucker) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/05/17 00:13:13 - [xmalloc.h cipher.c sftp-glob.c ssh-keyscan.c ssh.c sftp-common.c - ssh-ecdsa.c auth2-chall.c compat.c readconf.c kexgexs.c monitor.c - gss-genr.c cipher-3des1.c kex.c monitor_wrap.c ssh-pkcs11-client.c - auth-options.c rsa.c auth2-pubkey.c sftp.c hostfile.c auth2.c - servconf.c auth.c authfile.c xmalloc.c uuencode.c sftp-client.c - auth2-gss.c sftp-server.c bufaux.c mac.c session.c jpake.c kexgexc.c - sshconnect.c auth-chall.c auth2-passwd.c sshconnect1.c buffer.c - kexecdhs.c kexdhs.c ssh-rsa.c auth1.c ssh-pkcs11.c auth2-kbdint.c - kexdhc.c sshd.c umac.c ssh-dss.c auth2-jpake.c bufbn.c clientloop.c - monitor_mm.c scp.c roaming_client.c serverloop.c key.c auth-rsa.c - ssh-pkcs11-helper.c ssh-keysign.c ssh-keygen.c match.c channels.c - sshconnect2.c addrmatch.c mux.c canohost.c kexecdhc.c schnorr.c - ssh-add.c misc.c auth2-hostbased.c ssh-agent.c bufec.c groupaccess.c - dns.c packet.c readpass.c authfd.c moduli.c] - bye, bye xfree(); ok markus@ - - djm@cvs.openbsd.org 2013/05/19 02:38:28 - [auth2-pubkey.c] - fix failure to recognise cert-authority keys if a key of a different type - appeared in authorized_keys before it; ok markus@ - - djm@cvs.openbsd.org 2013/05/19 02:42:42 - [auth.h auth.c key.c monitor.c auth-rsa.c auth2.c auth1.c key.h] - Standardise logging of supplemental information during userauth. Keys - and ruser is now logged in the auth success/failure message alongside - the local username, remote host/port and protocol in use. Certificates - contents and CA are logged too. - Pushing all logging onto a single line simplifies log analysis as it is - no longer necessary to relate information scattered across multiple log - entries. "I like it" markus@ - - dtucker@cvs.openbsd.org 2013/05/31 12:28:10 - [ssh-agent.c] - Use time_t where appropriate. ok djm - - dtucker@cvs.openbsd.org 2013/06/01 13:15:52 - [ssh-agent.c clientloop.c misc.h packet.c progressmeter.c misc.c - channels.c sandbox-systrace.c] - Use clock_gettime(CLOCK_MONOTONIC ...) for ssh timers so that things like - keepalives and rekeying will work properly over clock steps. Suggested by - markus@, "looks good" djm@. - - dtucker@cvs.openbsd.org 2013/06/01 20:59:25 - [scp.c sftp-client.c] - Replace S_IWRITE, which isn't standardized, with S_IWUSR, which is. Patch - from Nathan Osman via bz#2085. ok deraadt. - - dtucker@cvs.openbsd.org 2013/06/01 22:34:50 - [sftp-client.c] - Update progressmeter when data is acked, not when it's sent. bz#2108, from - Debian via Colin Watson, ok djm@ - - (dtucker) [M auth-chall.c auth-krb5.c auth-pam.c cipher-aes.c cipher-ctr.c - groupaccess.c loginrec.c monitor.c monitor_wrap.c session.c sshd.c - sshlogin.c uidswap.c openbsd-compat/bsd-cygwin_util.c - openbsd-compat/getrrsetbyname-ldns.c openbsd-compat/port-aix.c - openbsd-compat/port-linux.c] Replace portable-specific instances of xfree - with the equivalent calls to free. - - (dtucker) [configure.ac misc.c] Look for clock_gettime in librt and fall - back to time(NULL) if we can't find it anywhere. - - (dtucker) [sandbox-seccomp-filter.c] Allow clock_gettimeofday. - -20130529 - - (dtucker) [configure.ac openbsd-compat/bsd-misc.h] bz#2087: Add a null - implementation of endgrent for platforms that don't have it (eg Android). - Loosely based on a patch from Nathan Osman, ok djm - - 20130517 - - (dtucker) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/03/07 00:20:34 - [regress/proxy-connect.sh] - repeat test with a style appended to the username - - dtucker@cvs.openbsd.org 2013/03/23 11:09:43 - [regress/test-exec.sh] - Only regenerate host keys if they don't exist or if ssh-keygen has changed - since they were. Reduces test runtime by 5-30% depending on machine - speed. - - dtucker@cvs.openbsd.org 2013/04/06 06:00:22 - [regress/rekey.sh regress/test-exec.sh regress/integrity.sh - regress/multiplex.sh Makefile regress/cfgmatch.sh] - Split the regress log into 3 parts: the debug output from ssh, the debug - log from sshd and the output from the client command (ssh, scp or sftp). - Somewhat functional now, will become more useful when ssh/sshd -E is added. - - dtucker@cvs.openbsd.org 2013/04/07 02:16:03 - [regress/Makefile regress/rekey.sh regress/integrity.sh - regress/sshd-log-wrapper.sh regress/forwarding.sh regress/test-exec.sh] - use -E option for ssh and sshd to write debuging logs to ssh{,d}.log and - save the output from any failing tests. If a test fails the debug output - from ssh and sshd for the failing tests (and only the failing tests) should - be available in failed-ssh{,d}.log. - - djm@cvs.openbsd.org 2013/04/18 02:46:12 - [regress/Makefile regress/sftp-chroot.sh] - test sshd ChrootDirectory+internal-sftp; feedback & ok dtucker@ - - dtucker@cvs.openbsd.org 2013/04/22 07:23:08 - [regress/multiplex.sh] - Write mux master logs to regress.log instead of ssh.log to keep separate - - djm@cvs.openbsd.org 2013/05/10 03:46:14 - [regress/modpipe.c] - sync some portability changes from portable OpenSSH (id sync only) - - dtucker@cvs.openbsd.org 2013/05/16 02:10:35 - [regress/rekey.sh] - Add test for time-based rekeying - - dtucker@cvs.openbsd.org 2013/05/16 03:33:30 - [regress/rekey.sh] - test rekeying when there's no data being transferred - - dtucker@cvs.openbsd.org 2013/05/16 04:26:10 - [regress/rekey.sh] - add server-side rekey test - - dtucker@cvs.openbsd.org 2013/05/16 05:48:31 - [regress/rekey.sh] - add tests for RekeyLimit parsing - - dtucker@cvs.openbsd.org 2013/05/17 00:37:40 - [regress/agent.sh regress/keytype.sh regress/cfgmatch.sh - regress/forcecommand.sh regress/proto-version.sh regress/test-exec.sh - regress/cipher-speed.sh regress/cert-hostkey.sh regress/cert-userkey.sh - regress/ssh-com.sh] - replace 'echo -n' with 'printf' since it's more portable - also remove "echon" hack. - - dtucker@cvs.openbsd.org 2013/05/17 01:16:09 - [regress/agent-timeout.sh] - Pull back some portability changes from -portable: - - TIMEOUT is a read-only variable in some shells - - not all greps have -q so redirect to /dev/null instead. - (ID sync only) - - dtucker@cvs.openbsd.org 2013/05/17 01:32:11 - [regress/integrity.sh] - don't print output from ssh before getting it (it's available in ssh.log) - - dtucker@cvs.openbsd.org 2013/05/17 04:29:14 - [regress/sftp.sh regress/putty-ciphers.sh regress/cipher-speed.sh - regress/test-exec.sh regress/sftp-batch.sh regress/dynamic-forward.sh - regress/putty-transfer.sh regress/conch-ciphers.sh regress/sftp-cmds.sh - regress/scp.sh regress/ssh-com-sftp.sh regress/rekey.sh - regress/putty-kex.sh regress/stderr-data.sh regress/stderr-after-eof.sh - regress/sftp-badcmds.sh regress/reexec.sh regress/ssh-com-client.sh - regress/sftp-chroot.sh regress/forwarding.sh regress/transfer.sh - regress/multiplex.sh] - Move the setting of DATA and COPY into test-exec.sh - - dtucker@cvs.openbsd.org 2013/05/17 10:16:26 - [regress/try-ciphers.sh] - use expr for math to keep diffs vs portable down - (id sync only) - - dtucker@cvs.openbsd.org 2013/05/17 10:23:52 - [regress/login-timeout.sh regress/reexec.sh regress/test-exec.sh] - Use SUDO when cat'ing pid files and running the sshd log wrapper so that - it works with a restrictive umask and the pid files are not world readable. - Changes from -portable. (id sync only) - - dtucker@cvs.openbsd.org 2013/05/17 10:24:48 - [regress/localcommand.sh] - use backticks for portability. (id sync only) - - dtucker@cvs.openbsd.org 2013/05/17 10:26:26 - [regress/sftp-badcmds.sh] - remove unused BATCH variable. (id sync only) - - dtucker@cvs.openbsd.org 2013/05/17 10:28:11 - [regress/sftp.sh] - only compare copied data if sftp succeeds. from portable (id sync only) - - dtucker@cvs.openbsd.org 2013/05/17 10:30:07 - [regress/test-exec.sh] - wait a bit longer for startup and use case for absolute path. - from portable (id sync only) - - dtucker@cvs.openbsd.org 2013/05/17 10:33:09 - [regress/agent-getpeereid.sh] - don't redirect stdout from sudo. from portable (id sync only) - - dtucker@cvs.openbsd.org 2013/05/17 10:34:30 - [regress/portnum.sh] - use a more portable negated if structure. from portable (id sync only) - - dtucker@cvs.openbsd.org 2013/05/17 10:35:43 - [regress/scp.sh] - use a file extention that's not special on some platforms. from portable - (id sync only) - - (dtucker) [regress/bsd.regress.mk] Remove unused file. We've never used it - in portable and it's long gone in openbsd. - - (dtucker) [regress/integrity.sh]. Force fixed Diffie-Hellman key exchange - methods. When the openssl version doesn't support ECDH then next one on - the list is DH group exchange, but that causes a bit more traffic which can - mean that the tests flip bits in the initial exchange rather than the MACed - traffic and we get different errors to what the tests look for. - - (dtucker) [openbsd-compat/getopt.h] Remove unneeded bits. - - (dtucker) [regress/cfgmatch.sh] Resync config file setup with openbsd. - - (dtucker) [regress/agent-getpeereid.sh] Resync spaces with openbsd. - - (dtucker) [regress/integrity.sh regress/krl.sh regress/test-exec.sh] - Move the jot helper function to portable-specific part of test-exec.sh. - - (dtucker) [regress/test-exec.sh] Move the portable-specific functions - together and add a couple of missing lines from openbsd. - - (dtucker) [regress/stderr-after-eof.sh regress/test-exec.sh] Move the md5 - helper function to the portable part of test-exec.sh. - - (dtucker) [regress/runtests.sh] Remove obsolete test driver script. - - (dtucker) [regress/cfgmatch.sh] Remove unneeded sleep renderd obsolete by - rev 1.6 which calls wait. - -20130516 - - (djm) [contrib/ssh-copy-id] Fix bug that could cause "rm *" to be - executed if mktemp failed; bz#2105 ok dtucker@ - - (dtucker) OpenBSD CVS Sync - - tedu@cvs.openbsd.org 2013/04/23 17:49:45 - [misc.c] - use xasprintf instead of a series of strlcats and strdup. ok djm - - tedu@cvs.openbsd.org 2013/04/24 16:01:46 - [misc.c] - remove extra parens noticed by nicm - - dtucker@cvs.openbsd.org 2013/05/06 07:35:12 - [sftp-server.8] - Reference the version of the sftp draft we actually implement. ok djm@ - - djm@cvs.openbsd.org 2013/05/10 03:40:07 - [sshconnect2.c] - fix bzero(ptr_to_struct, sizeof(ptr_to_struct)); bz#2100 from - Colin Watson - - djm@cvs.openbsd.org 2013/05/10 04:08:01 - [key.c] - memleak in cert_free(), wasn't actually freeing the struct; - bz#2096 from shm AT digitalsun.pl - - dtucker@cvs.openbsd.org 2013/05/10 10:13:50 - [ssh-pkcs11-helper.c] - remove unused extern optarg. ok markus@ - - dtucker@cvs.openbsd.org 2013/05/16 02:00:34 - [ssh_config sshconnect2.c packet.c readconf.h readconf.c clientloop.c - ssh_config.5 packet.h] - Add an optional second argument to RekeyLimit in the client to allow - rekeying based on elapsed time in addition to amount of traffic. - with djm@ jmc@, ok djm - - dtucker@cvs.openbsd.org 2013/05/16 04:09:14 - [sshd_config.5 servconf.c servconf.h packet.c serverloop.c monitor.c sshd_config - sshd.c] Add RekeyLimit to sshd with the same syntax as the client allowing - rekeying based on traffic volume or time. ok djm@, help & ok jmc@ for the man - page. - - djm@cvs.openbsd.org 2013/05/16 04:27:50 - [ssh_config.5 readconf.h readconf.c] - add the ability to ignore specific unrecognised ssh_config options; - bz#866; ok markus@ - - jmc@cvs.openbsd.org 2013/05/16 06:28:45 - [ssh_config.5] - put IgnoreUnknown in the right place; - - jmc@cvs.openbsd.org 2013/05/16 06:30:06 - [sshd_config.5] - oops! avoid Xr to self; - - dtucker@cvs.openbsd.org 2013/05/16 09:08:41 - [log.c scp.c sshd.c serverloop.c schnorr.c sftp.c] - Fix some "unused result" warnings found via clang and -portable. - ok markus@ - - dtucker@cvs.openbsd.org 2013/05/16 09:12:31 - [readconf.c servconf.c] - switch RekeyLimit traffic volume parsing to scan_scaled. ok djm@ - - dtucker@cvs.openbsd.org 2013/05/16 10:43:34 - [servconf.c readconf.c] - remove now-unused variables - - dtucker@cvs.openbsd.org 2013/05/16 10:44:06 - [servconf.c] - remove another now-unused variable - - (dtucker) [configure.ac readconf.c servconf.c - openbsd-compat/openbsd-compat.h] Add compat bits for scan_scaled. - -20130510 - - (dtucker) [configure.ac] Enable -Wsizeof-pointer-memaccess if the compiler - supports it. Mentioned by Colin Watson in bz#2100, ok djm. - - (dtucker) [openbsd-compat/getopt.c] Factor out portibility changes to - getopt.c. Preprocessed source is identical other than line numbers. - - (dtucker) [openbsd-compat/getopt_long.c] Import from OpenBSD. No - portability changes yet. - - (dtucker) [openbsd-compat/Makefile.in openbsd-compat/getopt.c - openbsd-compat/getopt_long.c regress/modpipe.c] Remove getopt.c, add - portability code to getopt_long.c and switch over Makefile and the ugly - hack in modpipe.c. Fixes bz#1448. - - (dtucker) [openbsd-compat/getopt.h openbsd-compat/getopt_long.c - openbsd-compat/openbsd-compat.h] pull in getopt.h from openbsd and plumb - in to use it when we're using our own getopt. - - (dtucker) [kex.c] Only include sha256 and ECC key exchange methods when the - underlying libraries support them. - - (dtucker) [configure.ac] Add -Werror to the -Qunused-arguments test so - we don't get a warning on compilers that *don't* support it. Add - -Wno-unknown-warning-option. Move both to the start of the list for - maximum noise suppression. Tested with gcc 4.6.3, gcc 2.95.4 and clang 2.9. - -20130423 - - (djm) [auth.c configure.ac misc.c monitor.c monitor_wrap.c] Support - platforms, such as Android, that lack struct passwd.pw_gecos. Report - and initial patch from Nathan Osman bz#2086; feedback tim@ ok dtucker@ - - (djm) OpenBSD CVS Sync - - markus@cvs.openbsd.org 2013/03/05 20:16:09 - [sshconnect2.c] - reset pubkey order on partial success; ok djm@ - - djm@cvs.openbsd.org 2013/03/06 23:35:23 - [session.c] - fatal() when ChrootDirectory specified by running without root privileges; - ok markus@ - - djm@cvs.openbsd.org 2013/03/06 23:36:53 - [readconf.c] - g/c unused variable (-Wunused) - - djm@cvs.openbsd.org 2013/03/07 00:19:59 - [auth2-pubkey.c monitor.c] - reconstruct the original username that was sent by the client, which may - have included a style (e.g. "root:skey") when checking public key - signatures. Fixes public key and hostbased auth when the client specified - a style; ok markus@ - - markus@cvs.openbsd.org 2013/03/07 19:27:25 - [auth.h auth2-chall.c auth2.c monitor.c sshd_config.5] - add submethod support to AuthenticationMethods; ok and freedback djm@ - - djm@cvs.openbsd.org 2013/03/08 06:32:58 - [ssh.c] - allow "ssh -f none ..." ok markus@ - - djm@cvs.openbsd.org 2013/04/05 00:14:00 - [auth2-gss.c krl.c sshconnect2.c] - hush some {unused, printf type} warnings - - djm@cvs.openbsd.org 2013/04/05 00:31:49 - [pathnames.h] - use the existing _PATH_SSH_USER_RC define to construct the other - pathnames; bz#2077, ok dtucker@ (no binary change) - - djm@cvs.openbsd.org 2013/04/05 00:58:51 - [mux.c] - cleanup mux-created channels that are in SSH_CHANNEL_OPENING state too - (in addition to ones already in OPEN); bz#2079, ok dtucker@ - - markus@cvs.openbsd.org 2013/04/06 16:07:00 - [channels.c sshd.c] - handle ECONNABORTED for accept(); ok deraadt some time ago... - - dtucker@cvs.openbsd.org 2013/04/07 02:10:33 - [log.c log.h ssh.1 ssh.c sshd.8 sshd.c] - Add -E option to ssh and sshd to append debugging logs to a specified file - instead of stderr or syslog. ok markus@, man page help jmc@ - - dtucker@cvs.openbsd.org 2013/04/07 09:40:27 - [sshd.8] - clarify -e text. suggested by & ok jmc@ - - djm@cvs.openbsd.org 2013/04/11 02:27:50 - [packet.c] - quiet disconnect notifications on the server from error() back to logit() - if it is a normal client closure; bz#2057 ok+feedback dtucker@ - - dtucker@cvs.openbsd.org 2013/04/17 09:04:09 - [session.c] - revert rev 1.262; it fails because uid is already set here. ok djm@ - - djm@cvs.openbsd.org 2013/04/18 02:16:07 - [sftp.c] - make "sftp -q" do what it says on the sticker: hush everything but errors; - ok dtucker@ - - djm@cvs.openbsd.org 2013/04/19 01:00:10 - [sshd_config.5] - document the requirment that the AuthorizedKeysCommand be owned by root; - ok dtucker@ markus@ - - djm@cvs.openbsd.org 2013/04/19 01:01:00 - [ssh-keygen.c] - fix some memory leaks; bz#2088 ok dtucker@ - - djm@cvs.openbsd.org 2013/04/19 01:03:01 - [session.c] - reintroduce 1.262 without the connection-killing bug: - fatal() when ChrootDirectory specified by running without root privileges; - ok markus@ - - djm@cvs.openbsd.org 2013/04/19 01:06:50 - [authfile.c cipher.c cipher.h kex.c kex.h kexecdh.c kexecdhc.c kexecdhs.c] - [key.c key.h mac.c mac.h packet.c ssh.1 ssh.c] - add the ability to query supported ciphers, MACs, key type and KEX - algorithms to ssh. Includes some refactoring of KEX and key type handling - to be table-driven; ok markus@ - - djm@cvs.openbsd.org 2013/04/19 11:10:18 - [ssh.c] - add -Q to usage; reminded by jmc@ - - djm@cvs.openbsd.org 2013/04/19 12:07:08 - [kex.c] - remove duplicated list entry pointed out by naddy@ - - dtucker@cvs.openbsd.org 2013/04/22 01:17:18 - [mux.c] - typo in debug output: evitval->exitval - -20130418 - - (djm) [config.guess config.sub] Update to last versions before they switch - to GPL3. ok dtucker@ - - (dtucker) [configure.ac] Use -Qunused-arguments to suppress warnings from - unused argument warnings (in particular, -fno-builtin-memset) from clang. - -20130404 - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2013/02/17 23:16:57 - [readconf.c ssh.c readconf.h sshconnect2.c] - Keep track of which IndentityFile options were manually supplied and which - were default options, and don't warn if the latter are missing. - ok markus@ - - dtucker@cvs.openbsd.org 2013/02/19 02:12:47 - [krl.c] - Remove bogus include. ok djm - - dtucker@cvs.openbsd.org 2013/02/22 04:45:09 - [ssh.c readconf.c readconf.h] - Don't complain if IdentityFiles specified in system-wide configs are - missing. ok djm, deraadt. - - markus@cvs.openbsd.org 2013/02/22 19:13:56 - [sshconnect.c] - support ProxyCommand=- (stdin/out already point to the proxy); ok djm@ - - djm@cvs.openbsd.org 2013/02/22 22:09:01 - [ssh.c] - Allow IdenityFile=none; ok markus deraadt (and dtucker for an earlier - version) - -20130401 - - (dtucker) [openbsd-compat/bsd-cygwin_util.{c,h}] Don't include windows.h - to avoid conflicting definitions of __int64, adding the required bits. - Patch from Corinna Vinschen. - -20130323 - - (tim) [Makefile.in] remove some duplication introduced in 20130220 commit. - -20130322 - - (djm) [contrib/ssh-copy-id contrib/ssh-copy-id.1] Updated to Phil - Hands' greatly revised version. - - (djm) Release 6.2p1 - - (dtucker) [configure.ac] Add stdlib.h to zlib check for exit() prototype. - - (dtucker) [includes.h] Check if _GNU_SOURCE is already defined before - defining it again. Prevents warnings if someone, eg, sets it in CFLAGS. - -20130318 - - (djm) [configure.ac log.c scp.c sshconnect2.c openbsd-compat/vis.c] - [openbsd-compat/vis.h] FreeBSD's strnvis isn't compatible with OpenBSD's - so mark it as broken. Patch from des AT des.no - -20130317 - - (tim) [configure.ac] OpenServer 5 wants lastlog even though it has none - of the bits the configure test looks for. - -20130316 - - (djm) [configure.ac] Disable utmp, wtmp and/or lastlog if the platform - is unable to successfully compile them. Based on patch from des AT - des.no - - (djm) [configure.ac openbsd-compat/bsd-misc.c openbsd-compat/bsd-misc.h] - Add a usleep replacement for platforms that lack it; ok dtucker - - (djm) [session.c] FreeBSD needs setusercontext(..., LOGIN_SETUMASK) to - occur after UID switch; patch from John Marshall via des AT des.no; - ok dtucker@ - -20130312 - - (dtucker) [regress/Makefile regress/cipher-speed.sh regress/test-exec.sh] - Improve portability of cipher-speed test, based mostly on a patch from - Iain Morgan. - - (dtucker) [auth.c configure.ac platform.c platform.h] Accept uid 2 ("bin") - in addition to root as an owner of system directories on AIX and HP-UX. - ok djm@ - -20130307 - - (dtucker) [INSTALL] Bump documented autoconf version to what we're - currently using. - - (dtucker) [defines.h] Remove SIZEOF_CHAR bits since the test for it - was removed in configure.ac rev 1.481 as it was redundant. - - (tim) [Makefile.in] Add another missing $(EXEEXT) I should have seen 3 days - ago. - - (djm) [configure.ac] Add a timeout to the select/rlimit test to give it a - chance to complete on broken systems; ok dtucker@ - -20130306 - - (dtucker) [regress/forward-control.sh] Wait longer for the forwarding - connection to start so that the test works on slower machines. - - (dtucker) [configure.ac] test that we can set number of file descriptors - to zero with setrlimit before enabling the rlimit sandbox. This affects - (at least) HPUX 11.11. - -20130305 - - (djm) [regress/modpipe.c] Compilation fix for AIX and parsing fix for - HP/UX. Spotted by Kevin Brott - - (dtucker) [configure.ac] use "=" for shell test and not "==". Spotted by - Amit Kulkarni and Kevin Brott. - - (dtucker) [Makefile.in] Remove trailing "\" on PATHS, which caused obscure - build breakage on (at least) HP-UX 11.11. Found by Amit Kulkarni and Kevin - Brott. - - (tim) [Makefile.in] Add missing $(EXEEXT). Found by Roumen Petrov. - -20130227 - - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec] - [contrib/suse/openssh.spec] Crank version numbers - - (tim) [regress/forward-control.sh] use sh in case login shell is csh. - - (tim) [regress/integrity.sh] shell portability fix. - - (tim) [regress/integrity.sh] keep old solaris awk from hanging. - - (tim) [regress/krl.sh] keep old solaris awk from hanging. - -20130226 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/02/20 08:27:50 - [integrity.sh] - Add an option to modpipe that warns if the modification offset it not - reached in it's stream and turn it on for t-integrity. This should catch - cases where the session is not fuzzed for being too short (cf. my last - "oops" commit) - - (djm) [regress/integrity.sh] Run sshd via $SUDO; fixes tinderbox breakage - for UsePAM=yes configuration - -20130225 - - (dtucker) [configure.ac ssh-gss.h] bz#2073: additional #includes needed - to use Solaris native GSS libs. Patch from Pierre Ossman. - -20130223 - - (djm) [configure.ac includes.h loginrec.c mux.c sftp.c] Prefer - bsd/libutil.h to libutil.h to avoid deprecation warnings on Ubuntu. - ok tim - -20130222 - - (dtucker) [Makefile.in configure.ac] bz#2072: don't link krb5 libs to - ssh(1) since they're not needed. Patch from Pierre Ossman, ok djm. - - (dtucker) [configure.ac] bz#2073: look for Solaris' differently-named - libgss too. Patch from Pierre Ossman, ok djm. - - (djm) [configure.ac sandbox-seccomp-filter.c] Support for Linux - seccomp-bpf sandbox on ARM. Patch from shawnlandden AT gmail.com; - ok dtucker - -20130221 - - (tim) [regress/forward-control.sh] shell portability fix. - -20130220 - - (tim) [regress/cipher-speed.sh regress/try-ciphers.sh] shell portability fix. - - (tim) [krl.c Makefile.in regress/Makefile regress/modpipe.c] remove unneeded - err.h include from krl.c. Additional portability fixes for modpipe. OK djm - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/02/20 08:27:50 - [regress/integrity.sh regress/modpipe.c] - Add an option to modpipe that warns if the modification offset it not - reached in it's stream and turn it on for t-integrity. This should catch - cases where the session is not fuzzed for being too short (cf. my last - "oops" commit) - - djm@cvs.openbsd.org 2013/02/20 08:29:27 - [regress/modpipe.c] - s/Id/OpenBSD/ in RCS tag - -20130219 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/02/18 22:26:47 - [integrity.sh] - crank the offset yet again; it was still fuzzing KEX one of Darren's - portable test hosts at 2800 - - djm@cvs.openbsd.org 2013/02/19 02:14:09 - [integrity.sh] - oops, forgot to increase the output of the ssh command to ensure that - we actually reach $offset - - (djm) [regress/integrity.sh] Skip SHA2-based MACs on configurations that - lack support for SHA2. - - (djm) [regress/modpipe.c] Add local err, and errx functions for platforms - that do not have them. - -20130217 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/02/17 23:16:55 - [integrity.sh] - make the ssh command generates some output to ensure that there are at - least offset+tries bytes in the stream. - -20130216 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/02/16 06:08:45 - [integrity.sh] - make sure the fuzz offset is actually past the end of KEX for all KEX - types. diffie-hellman-group-exchange-sha256 requires an offset around - 2700. Noticed via test failures in portable OpenSSH on platforms that - lack ECC and this the more byte-frugal ECDH KEX algorithms. - -20130215 - - (djm) [contrib/suse/rc.sshd] Use SSHD_BIN consistently; bz#2056 from - Iain Morgan - - (dtucker) [configure.ac openbsd-compat/bsd-misc.c openbsd-compat/bsd-misc.h] - Use getpgrp() if we don't have getpgid() (old BSDs, maybe others). - - (dtucker) [configure.ac openbsd-compat/Makefile.in openbsd-compat/strtoull.c - openbsd-compat/openbsd-compat.h] Add strtoull to compat library for - platforms that don't have it. - - (dtucker) [openbsd-compat/openbsd-compat.h] Add prototype for strtoul, - group strto* function prototypes together. - - (dtucker) [openbsd-compat/bsd-misc.c] Handle the case where setpgrp() takes - an argument. Pointed out by djm. - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/02/14 21:35:59 - [auth2-pubkey.c] - Correct error message that had a typo and was logging the wrong thing; - patch from Petr Lautrbach - - dtucker@cvs.openbsd.org 2013/02/15 00:21:01 - [sshconnect2.c] - Warn more loudly if an IdentityFile provided by the user cannot be read. - bz #1981, ok djm@ - -20130214 - - (djm) [regress/krl.sh] Don't use ecdsa keys in environment that lack ECC. - - (djm) [regress/krl.sh] typo; found by Iain Morgan - - (djm) [regress/integrity.sh] Start fuzzing from offset 2500 (instead - of 2300) to avoid clobbering the end of (non-MAC'd) KEX. Verified by - Iain Morgan - -20130212 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/01/24 21:45:37 - [krl.c] - fix handling of (unused) KRL signatures; skip string in correct buffer - - djm@cvs.openbsd.org 2013/01/24 22:08:56 - [krl.c] - skip serial lookup when cert's serial number is zero - - krw@cvs.openbsd.org 2013/01/25 05:00:27 - [krl.c] - Revert last. Breaks due to likely typo. Let djm@ fix later. - ok djm@ via dlg@ - - djm@cvs.openbsd.org 2013/01/25 10:22:19 - [krl.c] - redo last commit without the vi-vomit that snuck in: - skip serial lookup when cert's serial number is zero - (now with 100% better comment) - - djm@cvs.openbsd.org 2013/01/26 06:11:05 - [Makefile.in acss.c acss.h cipher-acss.c cipher.c] - [openbsd-compat/openssl-compat.h] - remove ACSS, now that it is gone from libcrypto too - - djm@cvs.openbsd.org 2013/01/27 10:06:12 - [krl.c] - actually use the xrealloc() return value; spotted by xi.wang AT gmail.com - - dtucker@cvs.openbsd.org 2013/02/06 00:20:42 - [servconf.c sshd_config sshd_config.5] - Change default of MaxStartups to 10:30:100 to start doing random early - drop at 10 connections up to 100 connections. This will make it harder - to DoS as CPUs have come a long way since the original value was set - back in 2000. Prompted by nion at debian org, ok markus@ - - dtucker@cvs.openbsd.org 2013/02/06 00:22:21 - [auth.c] - Fix comment, from jfree.e1 at gmail - - djm@cvs.openbsd.org 2013/02/08 00:41:12 - [sftp.c] - fix NULL deref when built without libedit and control characters - entered as command; debugging and patch from Iain Morgan an - Loganaden Velvindron in bz#1956 - - markus@cvs.openbsd.org 2013/02/10 21:19:34 - [version.h] - openssh 6.2 - - djm@cvs.openbsd.org 2013/02/10 23:32:10 - [ssh-keygen.c] - append to moduli file when screening candidates rather than overwriting. - allows resumption of interrupted screen; patch from Christophe Garault - in bz#1957; ok dtucker@ - - djm@cvs.openbsd.org 2013/02/10 23:35:24 - [packet.c] - record "Received disconnect" messages at ERROR rather than INFO priority, - since they are abnormal and result in a non-zero ssh exit status; patch - from Iain Morgan in bz#2057; ok dtucker@ - - dtucker@cvs.openbsd.org 2013/02/11 21:21:58 - [sshd.c] - Add openssl version to debug output similar to the client. ok markus@ - - djm@cvs.openbsd.org 2013/02/11 23:58:51 - [regress/try-ciphers.sh] - remove acss here too - - (djm) [regress/try-ciphers.sh] clean up CVS merge botch - -20130211 - - (djm) [configure.ac openbsd-compat/openssl-compat.h] Repair build on old - libcrypto that lacks EVP_CIPHER_CTX_ctrl - -20130208 - - (djm) [contrib/redhat/sshd.init] treat RETVAL as an integer; - patch from Iain Morgan in bz#2059 - - (dtucker) [configure.ac openbsd-compat/sys-tree.h] Test if compiler allows - __attribute__ on return values and work around if necessary. ok djm@ - -20130207 - - (djm) [configure.ac] Don't probe seccomp capability of running kernel - at configure time; the seccomp sandbox will fall back to rlimit at - runtime anyway. Patch from plautrba AT redhat.com in bz#2011 - -20130120 - - (djm) [cipher-aes.c cipher-ctr.c openbsd-compat/openssl-compat.h] - Move prototypes for replacement ciphers to openssl-compat.h; fix EVP - prototypes for openssl-1.0.0-fips. - - (djm) OpenBSD CVS Sync - - jmc@cvs.openbsd.org 2013/01/18 07:57:47 - [ssh-keygen.1] - tweak previous; - - jmc@cvs.openbsd.org 2013/01/18 07:59:46 - [ssh-keygen.c] - -u before -V in usage(); - - jmc@cvs.openbsd.org 2013/01/18 08:00:49 - [sshd_config.5] - tweak previous; - - jmc@cvs.openbsd.org 2013/01/18 08:39:04 - [ssh-keygen.1] - add -Q to the options list; ok djm - - jmc@cvs.openbsd.org 2013/01/18 21:48:43 - [ssh-keygen.1] - command-line (adj.) -> command line (n.); - - jmc@cvs.openbsd.org 2013/01/19 07:13:25 - [ssh-keygen.1] - fix some formatting; ok djm - - markus@cvs.openbsd.org 2013/01/19 12:34:55 - [krl.c] - RB_INSERT does not remove existing elments; ok djm@ - - (djm) [openbsd-compat/sys-tree.h] Sync with OpenBSD. krl.c needs newer - version. - - (djm) [regress/krl.sh] replacement for jot; most platforms lack it - -20130118 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/01/17 23:00:01 - [auth.c key.c key.h ssh-keygen.1 ssh-keygen.c sshd_config.5] - [krl.c krl.h PROTOCOL.krl] - add support for Key Revocation Lists (KRLs). These are a compact way to - represent lists of revoked keys and certificates, taking as little as - a single bit of incremental cost to revoke a certificate by serial number. - KRLs are loaded via the existing RevokedKeys sshd_config option. - feedback and ok markus@ - - djm@cvs.openbsd.org 2013/01/18 00:45:29 - [regress/Makefile regress/cert-userkey.sh regress/krl.sh] - Tests for Key Revocation Lists (KRLs) - - djm@cvs.openbsd.org 2013/01/18 03:00:32 - [krl.c] - fix KRL generation bug for list sections - -20130117 - - (djm) [regress/cipher-speed.sh regress/integrity.sh regress/try-ciphers.sh] - check for GCM support before testing GCM ciphers. - -20130112 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2013/01/12 11:22:04 - [cipher.c] - improve error message for integrity failure in AES-GCM modes; ok markus@ - - djm@cvs.openbsd.org 2013/01/12 11:23:53 - [regress/cipher-speed.sh regress/integrity.sh regress/try-ciphers.sh] - test AES-GCM modes; feedback markus@ - - (djm) [regress/integrity.sh] repair botched merge - -20130109 - - (djm) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2012/12/14 05:26:43 - [auth.c] - use correct string in error message; from rustybsd at gmx.fr - - djm@cvs.openbsd.org 2013/01/02 00:32:07 - [clientloop.c mux.c] - channel_setup_local_fwd_listener() returns 0 on failure, not -ve - bz#2055 reported by mathieu.lacage AT gmail.com - - djm@cvs.openbsd.org 2013/01/02 00:33:49 - [PROTOCOL.agent] - correct format description for SSH_AGENTC_ADD_RSA_ID_CONSTRAINED - bz#2051 from david AT lechnology.com - - djm@cvs.openbsd.org 2013/01/03 05:49:36 - [servconf.h] - add a couple of ServerOptions members that should be copied to the privsep - child (for consistency, in this case they happen only to be accessed in - the monitor); ok dtucker@ - - djm@cvs.openbsd.org 2013/01/03 12:49:01 - [PROTOCOL] - fix description of MAC calculation for EtM modes; ok markus@ - - djm@cvs.openbsd.org 2013/01/03 12:54:49 - [sftp-server.8 sftp-server.c] - allow specification of an alternate start directory for sftp-server(8) - "I like this" markus@ - - djm@cvs.openbsd.org 2013/01/03 23:22:58 - [ssh-keygen.c] - allow fingerprinting of keys hosted in PKCS#11 tokens: ssh-keygen -lD ... - ok markus@ - - jmc@cvs.openbsd.org 2013/01/04 19:26:38 - [sftp-server.8 sftp-server.c] - sftp-server.8: add argument name to -d - sftp-server.c: add -d to usage() - ok djm - - markus@cvs.openbsd.org 2013/01/08 18:49:04 - [PROTOCOL authfile.c cipher.c cipher.h kex.c kex.h monitor_wrap.c] - [myproposal.h packet.c ssh_config.5 sshd_config.5] - support AES-GCM as defined in RFC 5647 (but with simpler KEX handling) - ok and feedback djm@ - - djm@cvs.openbsd.org 2013/01/09 05:40:17 - [ssh-keygen.c] - correctly initialise fingerprint type for fingerprinting PKCS#11 keys - - (djm) [cipher.c configure.ac openbsd-compat/openssl-compat.h] - Fix merge botch, automatically detect AES-GCM in OpenSSL, move a little - cipher compat code to openssl-compat.h - -20121217 - - (dtucker) [Makefile.in] Add some scaffolding so that the new regress - tests will work with VPATH directories. - -20121213 - - (djm) OpenBSD CVS Sync - - markus@cvs.openbsd.org 2012/12/12 16:45:52 - [packet.c] - reset incoming_packet buffer for each new packet in EtM-case, too; - this happens if packets are parsed only parially (e.g. ignore - messages sent when su/sudo turn off echo); noted by sthen/millert - - naddy@cvs.openbsd.org 2012/12/12 16:46:10 - [cipher.c] - use OpenSSL's EVP_aes_{128,192,256}_ctr() API and remove our hand-rolled - counter mode code; ok djm@ - - (djm) [configure.ac cipher-ctr.c] Adapt EVP AES CTR change to retain our - compat code for older OpenSSL - - (djm) [cipher.c] Fix missing prototype for compat code - -20121212 - - (djm) OpenBSD CVS Sync - - markus@cvs.openbsd.org 2012/12/11 22:16:21 - [monitor.c] - drain the log messages after receiving the keystate from the unpriv - child. otherwise it might block while sending. ok djm@ - - markus@cvs.openbsd.org 2012/12/11 22:31:18 - [PROTOCOL authfile.c cipher.c cipher.h kex.h mac.c myproposal.h] - [packet.c ssh_config.5 sshd_config.5] - add encrypt-then-mac (EtM) modes to openssh by defining new mac algorithms - that change the packet format and compute the MAC over the encrypted - message (including the packet size) instead of the plaintext data; - these EtM modes are considered more secure and used by default. - feedback and ok djm@ - - sthen@cvs.openbsd.org 2012/12/11 22:51:45 - [mac.c] - fix typo, s/tem/etm in hmac-ripemd160-tem. ok markus@ - - markus@cvs.openbsd.org 2012/12/11 22:32:56 - [regress/try-ciphers.sh] - add etm modes - - markus@cvs.openbsd.org 2012/12/11 22:42:11 - [regress/Makefile regress/modpipe.c regress/integrity.sh] - test the integrity of the packets; with djm@ - - markus@cvs.openbsd.org 2012/12/11 23:12:13 - [try-ciphers.sh] - add hmac-ripemd160-etm@openssh.com - - (djm) [mac.c] fix merge botch - - (djm) [regress/Makefile regress/integrity.sh] Make the integrity.sh test - work on platforms without 'jot' - - (djm) [regress/integrity.sh] Fix awk quoting, packet length skip - - (djm) [regress/Makefile] fix t-exec rule - -20121207 - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2012/12/06 06:06:54 - [regress/keys-command.sh] - Fix some problems with the keys-command test: - - use string comparison rather than numeric comparison - - check for existing KEY_COMMAND file and don't clobber if it exists - - clean up KEY_COMMAND file if we do create it. - - check that KEY_COMMAND is executable (which it won't be if eg /var/run - is mounted noexec). - ok djm. - - jmc@cvs.openbsd.org 2012/12/03 08:33:03 - [ssh-add.1 sshd_config.5] - tweak previous; - - markus@cvs.openbsd.org 2012/12/05 15:42:52 - [ssh-add.c] - prevent double-free of comment; ok djm@ - - dtucker@cvs.openbsd.org 2012/12/07 01:51:35 - [serverloop.c] - Cast signal to int for logging. A no-op on openbsd (they're always ints) - but will prevent warnings in portable. ok djm@ - -20121205 - - (tim) [defines.h] Some platforms are missing ULLONG_MAX. Feedback djm@. - -20121203 - - (djm) [openbsd-compat/sys-queue.h] Sync with OpenBSD to get - TAILQ_FOREACH_SAFE needed for upcoming changes. - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2012/12/02 20:26:11 - [ssh_config.5 sshconnect2.c] - Make IdentitiesOnly apply to keys obtained from a PKCS11Provider. - This allows control of which keys are offered from tokens using - IdentityFile. ok markus@ - - djm@cvs.openbsd.org 2012/12/02 20:42:15 - [ssh-add.1 ssh-add.c] - make deleting explicit keys "ssh-add -d" symmetric with adding keys - - try to delete the corresponding certificate too and respect the -k option - to allow deleting of the key only; feedback and ok markus@ - - djm@cvs.openbsd.org 2012/12/02 20:46:11 - [auth-options.c channels.c servconf.c servconf.h serverloop.c session.c] - [sshd_config.5] - make AllowTcpForwarding accept "local" and "remote" in addition to its - current "yes"/"no" to allow the server to specify whether just local or - remote TCP forwarding is enabled. ok markus@ - - dtucker@cvs.openbsd.org 2012/10/05 02:20:48 - [regress/cipher-speed.sh regress/try-ciphers.sh] - Add umac-128@openssh.com to the list of MACs to be tested - - djm@cvs.openbsd.org 2012/10/19 05:10:42 - [regress/cert-userkey.sh] - include a serial number when generating certs - - djm@cvs.openbsd.org 2012/11/22 22:49:30 - [regress/Makefile regress/keys-command.sh] - regress for AuthorizedKeysCommand; hints from markus@ - - djm@cvs.openbsd.org 2012/12/02 20:47:48 - [Makefile regress/forward-control.sh] - regress for AllowTcpForwarding local/remote; ok markus@ - - djm@cvs.openbsd.org 2012/12/03 00:14:06 - [auth2-chall.c ssh-keygen.c] - Fix compilation with -Wall -Werror (trivial type fixes) - - (djm) [configure.ac] Turn on -g for gcc compilers. Helps pre-installation - debugging. ok dtucker@ - - (djm) [configure.ac] Revert previous. configure.ac already does this - for us. - -20121114 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2012/11/14 02:24:27 - [auth2-pubkey.c] - fix username passed to helper program - prepare stdio fds before closefrom() - spotted by landry@ - - djm@cvs.openbsd.org 2012/11/14 02:32:15 - [ssh-keygen.c] - allow the full range of unsigned serial numbers; 'fine' deraadt@ - - djm@cvs.openbsd.org 2012/12/02 20:34:10 - [auth.c auth.h auth1.c auth2-chall.c auth2-gss.c auth2-jpake.c auth2.c] - [monitor.c monitor.h] - Fixes logging of partial authentication when privsep is enabled - Previously, we recorded "Failed xxx" since we reset authenticated before - calling auth_log() in auth2.c. This adds an explcit "Partial" state. - - Add a "submethod" to auth_log() to report which submethod is used - for keyboard-interactive. - - Fix multiple authentication when one of the methods is - keyboard-interactive. - - ok markus@ - - dtucker@cvs.openbsd.org 2012/10/05 02:05:30 - [regress/multiplex.sh] - Use 'kill -0' to test for the presence of a pid since it's more portable - -20121107 - - (djm) OpenBSD CVS Sync - - eric@cvs.openbsd.org 2011/11/28 08:46:27 - [moduli.5] - fix formula +commit 7da2be0cb9601ed25460c83aa4d44052b967ba0f +Author: djm@openbsd.org +Date: Tue Mar 31 22:59:01 2015 +0000 + + upstream commit + + adapt to recent hostfile.c change: when parsing + known_hosts without fully parsing the keys therein, hostkeys_foreach() will + now correctly identify KEY_RSA1 keys; ok markus@ miod@ + +commit 9e1777a0d1c706714b055811c12ab8cc21033e4a +Author: markus@openbsd.org +Date: Tue Mar 24 20:19:15 2015 +0000 + + upstream commit + + use ${SSH} for -Q instead of installed ssh + +commit ce1b358ea414a2cc88e4430cd5a2ea7fecd9de57 +Author: djm@openbsd.org +Date: Mon Mar 16 22:46:14 2015 +0000 + + upstream commit + + make CLEANFILES clean up more of the tests' droppings + +commit 398f9ef192d820b67beba01ec234d66faca65775 +Author: djm@openbsd.org +Date: Tue Mar 31 22:57:06 2015 +0000 + + upstream commit + + downgrade error() for known_hosts parse errors to debug() + to quiet warnings from ssh1 keys present when compiled !ssh1. + + also identify ssh1 keys when scanning, even when compiled !ssh1 + + ok markus@ miod@ + +commit 9a47ab80030a31f2d122b8fd95bd48c408b9fcd9 +Author: djm@openbsd.org +Date: Tue Mar 31 22:55:50 2015 +0000 + + upstream commit + + fd leak for !ssh1 case; found by unittests; ok markus@ + +commit c9a0805a6280681901c270755a7cd630d7c5280e +Author: djm@openbsd.org +Date: Tue Mar 31 22:55:24 2015 +0000 + + upstream commit + + don't fatal when a !ssh1 sshd is reexeced from a w/ssh1 + listener; reported by miod@; ok miod@ markus@ + +commit 704d8c88988cae38fb755a6243b119731d223222 +Author: tobias@openbsd.org +Date: Tue Mar 31 11:06:49 2015 +0000 + + upstream commit + + Comments are only supported for RSA1 keys. If a user + tried to add one and entered his passphrase, explicitly clear it before exit. + This is done in all other error paths, too. + + ok djm + +commit 78de1673c05ea2c33e0d4a4b64ecb5186b6ea2e9 +Author: jmc@openbsd.org +Date: Mon Mar 30 18:28:37 2015 +0000 + + upstream commit + + ssh-askpass(1) is the default, overridden by SSH_ASKPASS; + diff originally from jiri b; + +commit 26e0bcf766fadb4a44fb6199386fb1dcab65ad00 +Author: djm@openbsd.org +Date: Mon Mar 30 00:00:29 2015 +0000 + + upstream commit + + fix uninitialised memory read when parsing a config file + consisting of a single nul byte. Found by hanno AT hboeck.de using AFL; ok + dtucker + +commit fecede00a76fbb33a349f5121c0b2f9fbc04a777 +Author: markus@openbsd.org +Date: Thu Mar 26 19:32:19 2015 +0000 + + upstream commit + + sigp and lenp are not optional in ssh_agent_sign(); ok + djm@ + +commit 1b0ef3813244c78669e6d4d54c624f600945327d +Author: naddy@openbsd.org +Date: Thu Mar 26 12:32:38 2015 +0000 + + upstream commit + + don't try to load .ssh/identity by default if SSH1 is + disabled; ok markus@ + +commit f9b78852379b74a2d14e6fc94fe52af30b7e9c31 +Author: djm@openbsd.org +Date: Thu Mar 26 07:00:04 2015 +0000 + + upstream commit + + ban all-zero curve25519 keys as recommended by latest + CFRG curves draft; ok markus + +commit b8afbe2c1aaf573565e4da775261dfafc8b1ba9c +Author: djm@openbsd.org +Date: Thu Mar 26 06:59:28 2015 +0000 + + upstream commit + + relax bits needed check to allow + diffie-hellman-group1-sha1 key exchange to complete for chacha20-poly1305 was + selected as symmetric cipher; ok markus + +commit 47842f71e31da130555353c1d57a1e5a8937f1c0 +Author: markus@openbsd.org +Date: Wed Mar 25 19:29:58 2015 +0000 + + upstream commit + + ignore v1 errors on ssh-add -D; only try v2 keys on + -l/-L (unless WITH_SSH1) ok djm@ + +commit 5f57e77f91bf2230c09eca96eb5ecec39e5f2da6 +Author: markus@openbsd.org +Date: Wed Mar 25 19:21:48 2015 +0000 + + upstream commit + + unbreak ssh_agent_sign (lenp vs *lenp) + +commit 4daeb67181054f2a377677fac919ee8f9ed3490e +Author: markus@openbsd.org +Date: Tue Mar 24 20:10:08 2015 +0000 + + upstream commit + + don't leak 'setp' on error; noted by Nicholas Lemonias; ok djm@ - - jmc@cvs.openbsd.org 2012/09/26 17:34:38 - [moduli.5] - last stage of rfc changes, using consistent Rs/Re blocks, and moving the - references into a STANDARDS section; - -20121105 - - (dtucker) [uidswap.c openbsd-compat/Makefile.in - openbsd-compat/bsd-setres_id.c openbsd-compat/bsd-setres_id.h - openbsd-compat/openbsd-compat.h] Move the fallback code for setting uids - and gids from uidswap.c to the compat library, which allows it to work with - the new setresuid calls in auth2-pubkey. with tim@, ok djm@ - - (dtucker) [auth2-pubkey.c] wrap paths.h in an ifdef for platforms that - don't have it. Spotted by tim@. - -20121104 - - (djm) OpenBSD CVS Sync - - jmc@cvs.openbsd.org 2012/10/31 08:04:50 - [sshd_config.5] - tweak previous; - - djm@cvs.openbsd.org 2012/11/04 10:38:43 - [auth2-pubkey.c sshd.c sshd_config.5] - Remove default of AuthorizedCommandUser. Administrators are now expected - to explicitly specify a user. feedback and ok markus@ - - djm@cvs.openbsd.org 2012/11/04 11:09:15 - [auth.h auth1.c auth2.c monitor.c servconf.c servconf.h sshd.c] - [sshd_config.5] - Support multiple required authentication via an AuthenticationMethods - option. This option lists one or more comma-separated lists of - authentication method names. Successful completion of all the methods in - any list is required for authentication to complete; - feedback and ok markus@ - -20121030 - - (djm) OpenBSD CVS Sync - - markus@cvs.openbsd.org 2012/10/05 12:34:39 - [sftp.c] - fix signed vs unsigned warning; feedback & ok: djm@ - - djm@cvs.openbsd.org 2012/10/30 21:29:55 - [auth-rsa.c auth.c auth.h auth2-pubkey.c servconf.c servconf.h] - [sshd.c sshd_config sshd_config.5] - new sshd_config option AuthorizedKeysCommand to support fetching - authorized_keys from a command in addition to (or instead of) from - the filesystem. The command is run as the target server user unless - another specified via a new AuthorizedKeysCommandUser option. - - patch originally by jchadima AT redhat.com, reworked by me; feedback + +commit 7d4f96f9de2a18af0d9fa75ea89a4990de0344f5 +Author: markus@openbsd.org +Date: Tue Mar 24 20:09:11 2015 +0000 + + upstream commit + + consistent check for NULL as noted by Nicholas + Lemonias; ok djm@ + +commit df100be51354e447d9345cf1ec22e6013c0eed50 +Author: markus@openbsd.org +Date: Tue Mar 24 20:03:44 2015 +0000 + + upstream commit + + correct fmt-string for size_t as noted by Nicholas + Lemonias; ok djm@ + +commit a22b9ef21285e81775732436f7c84a27bd3f71e0 +Author: djm@openbsd.org +Date: Tue Mar 24 09:17:21 2015 +0000 + + upstream commit + + promote chacha20-poly1305@openssh.com to be the default + cipher; ok markus + +commit 2aa9da1a3b360cf7b13e96fe1521534b91501fb5 +Author: djm@openbsd.org +Date: Tue Mar 24 01:29:19 2015 +0000 + + upstream commit + + Compile-time disable SSH protocol 1. You can turn it + back on using the Makefile.inc knob if you need it to talk to ancient + devices. + +commit 53097b2022154edf96b4e8526af5666f979503f7 +Author: djm@openbsd.org +Date: Tue Mar 24 01:11:12 2015 +0000 + + upstream commit + + fix double-negative error message "ssh1 is not + unsupported" + +commit 5c27e3b6ec2db711dfcd40e6359c0bcdd0b62ea9 +Author: djm@openbsd.org +Date: Mon Mar 23 06:06:38 2015 +0000 + + upstream commit + + for ssh-keygen -A, don't try (and fail) to generate ssh + v.1 keys when compiled without SSH1 support RSA/DSA/ECDSA keys when compiled + without OpenSSL based on patch by Mike Frysinger; bz#2369 + +commit 725fd22a8c41db7de73a638539a5157b7e4424ae +Author: djm@openbsd.org +Date: Wed Mar 18 01:44:21 2015 +0000 + + upstream commit + + KRL support doesn't need OpenSSL anymore, remove #ifdefs + from around call + +commit b07011c18e0b2e172c5fd09d21fb159a0bf5fcc7 +Author: djm@openbsd.org +Date: Mon Mar 16 11:09:52 2015 +0000 + + upstream commit + + #if 0 some more arrays used only for decrypting (we don't + use since we only need encrypt for AES-CTR) + +commit 1cb3016635898d287e9d58b50c430995652d5358 +Author: jsg@openbsd.org +Date: Wed Mar 11 00:48:39 2015 +0000 + + upstream commit + + add back the changes from rev 1.206, djm reverted this by + mistake in rev 1.207 + +commit 4d24b3b6a4a6383e05e7da26d183b79fa8663697 +Author: Damien Miller +Date: Fri Mar 20 09:11:59 2015 +1100 + + remove error() accidentally inserted for debugging + + pointed out by Christian Hesse + +commit 9f82e5a9042f2d872e98f48a876fcab3e25dd9bb +Author: Tim Rice +Date: Mon Mar 16 22:49:20 2015 -0700 + + portability fix: Solaris systems may not have a grep that understands -q + +commit 8ef691f7d9ef500257a549d0906d78187490668f +Author: Damien Miller +Date: Wed Mar 11 10:35:26 2015 +1100 + + fix compile with clang + +commit 4df590cf8dc799e8986268d62019b487a8ed63ad +Author: Damien Miller +Date: Wed Mar 11 10:02:39 2015 +1100 + + make unit tests work for !OPENSSH_HAS_ECC + +commit 307bb40277ca2c32e97e61d70d1ed74b571fd6ba +Author: djm@openbsd.org +Date: Sat Mar 7 04:41:48 2015 +0000 + + upstream commit + + unbreak for w/SSH1 (default) case; ok markus@ deraadt@ + +commit b44ee0c998fb4c5f3c3281f2398af5ce42840b6f +Author: Damien Miller +Date: Thu Mar 5 18:39:20 2015 -0800 + + unbreak hostkeys test for w/ SSH1 case + +commit 55e5bdeb519cb60cc18b7ba0545be581fb8598b4 +Author: djm@openbsd.org +Date: Fri Mar 6 01:40:56 2015 +0000 + + upstream commit + + fix sshkey_certify() return value for unsupported key types; + ok markus@ deraadt@ + +commit be8f658e550a434eac04256bfbc4289457a24e99 +Author: Damien Miller +Date: Wed Mar 4 15:38:03 2015 -0800 + + update version numbers to match version.h + +commit ac5e8acefa253eb5e5ba186e34236c0e8007afdc +Author: djm@openbsd.org +Date: Wed Mar 4 23:22:35 2015 +0000 + + upstream commit + + make these work with !SSH1; ok markus@ deraadt@ + +commit 2f04af92f036b0c87a23efb259c37da98cd81fe6 +Author: djm@openbsd.org +Date: Wed Mar 4 21:12:59 2015 +0000 + + upstream commit + + make ssh-add -D work with !SSH1 agent + +commit a05adf95d2af6abb2b7826ddaa7a0ec0cdc1726b +Author: Damien Miller +Date: Wed Mar 4 00:55:48 2015 -0800 + + netcat needs poll.h portability goop + +commit dad2b1892b4c1b7e58df483a8c5b983c4454e099 +Author: markus@openbsd.org +Date: Tue Mar 3 22:35:19 2015 +0000 + + upstream commit + + make it possible to run tests w/o ssh1 support; ok djm@ + +commit d48a22601bdd3eec054794c535f4ae8d8ae4c6e2 +Author: djm@openbsd.org +Date: Wed Mar 4 18:53:53 2015 +0000 + + upstream commit + + crank; ok markus, deraadt + +commit bbffb23daa0b002dd9f296e396a9ab8a5866b339 +Author: Damien Miller +Date: Tue Mar 3 13:50:27 2015 -0800 + + more --without-ssh1 fixes + +commit 6c2039286f503e2012a58a1d109e389016e7a99b +Author: Damien Miller +Date: Tue Mar 3 13:48:48 2015 -0800 + + fix merge both that broke --without-ssh1 compile + +commit 111dfb225478a76f89ecbcd31e96eaf1311b59d3 +Author: djm@openbsd.org +Date: Tue Mar 3 21:21:13 2015 +0000 + + upstream commit + + add SSH1 Makefile knob to make it easier to build without + SSH1 support; ok markus@ + +commit 3f7f5e6c5d2aa3f6710289c1a30119e534e56c5c +Author: djm@openbsd.org +Date: Tue Mar 3 20:42:49 2015 +0000 + + upstream commit + + expand __unused to full __attribute__ for better portability + +commit 2fab9b0f8720baf990c931e3f68babb0bf9949c6 +Author: Damien Miller +Date: Wed Mar 4 07:41:27 2015 +1100 + + avoid warning + +commit d1bc844322461f882b4fd2277ba9a8d4966573d2 +Author: Damien Miller +Date: Wed Mar 4 06:31:45 2015 +1100 + + Revert "define __unused to nothing if not already defined" + + This reverts commit 1598419e38afbaa8aa5df8dd6b0af98301e2c908. + + Some system headers have objects named __unused + +commit 00797e86b2d98334d1bb808f65fa1fd47f328ff1 +Author: Damien Miller +Date: Wed Mar 4 05:02:45 2015 +1100 + + check for crypt and DES_crypt in openssl block + + fixes builds on systems that use DES_crypt; based on patch + from Roumen Petrov + +commit 1598419e38afbaa8aa5df8dd6b0af98301e2c908 +Author: Damien Miller +Date: Wed Mar 4 04:59:13 2015 +1100 + + define __unused to nothing if not already defined + + fixes builds on BSD/OS + +commit d608a51daad4f14ad6ab43d7cf74ef4801cc3fe9 +Author: djm@openbsd.org +Date: Tue Mar 3 17:53:40 2015 +0000 + + upstream commit + + reorder logic for better portability; patch from Roumen + Petrov + +commit 68d2dfc464fbcdf8d6387884260f9801f4352393 +Author: djm@openbsd.org +Date: Tue Mar 3 06:48:58 2015 +0000 + + upstream commit + + Allow "ssh -Q protocol-version" to list supported SSH + protocol versions. Useful for detecting builds without SSH v.1 support; idea and ok markus@ -20121019 - - (tim) [buildpkg.sh.in] Double up on some backslashes so they end up in - the generated file as intended. - -20121005 - - (dtucker) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2012/09/17 09:54:44 - [sftp.c] - an XXX for later - - markus@cvs.openbsd.org 2012/09/17 13:04:11 - [packet.c] - clear old keys on rekeing; ok djm - - dtucker@cvs.openbsd.org 2012/09/18 10:36:12 - [sftp.c] - Add bounds check on sftp tab-completion. Part of a patch from from - Jean-Marc Robert via tech@, ok djm - - dtucker@cvs.openbsd.org 2012/09/21 10:53:07 - [sftp.c] - Fix improper handling of absolute paths when PWD is part of the completed - path. Patch from Jean-Marc Robert via tech@, ok djm. - - dtucker@cvs.openbsd.org 2012/09/21 10:55:04 - [sftp.c] - Fix handling of filenames containing escaped globbing characters and - escape "#" and "*". Patch from Jean-Marc Robert via tech@, ok djm. - - jmc@cvs.openbsd.org 2012/09/26 16:12:13 - [ssh.1] - last stage of rfc changes, using consistent Rs/Re blocks, and moving the - references into a STANDARDS section; - - naddy@cvs.openbsd.org 2012/10/01 13:59:51 - [monitor_wrap.c] - pasto; ok djm@ - - djm@cvs.openbsd.org 2012/10/02 07:07:45 - [ssh-keygen.c] - fix -z option, broken in revision 1.215 - - markus@cvs.openbsd.org 2012/10/04 13:21:50 - [myproposal.h ssh_config.5 umac.h sshd_config.5 ssh.1 sshd.8 mac.c] - add umac128 variant; ok djm@ at n2k12 - - dtucker@cvs.openbsd.org 2012/09/06 04:11:07 - [regress/try-ciphers.sh] - Restore missing space. (Id sync only). - - dtucker@cvs.openbsd.org 2012/09/09 11:51:25 - [regress/multiplex.sh] - Add test for ssh -Ostop - - dtucker@cvs.openbsd.org 2012/09/10 00:49:21 - [regress/multiplex.sh] - Log -O cmd output to the log file and make logging consistent with the - other tests. Test clean shutdown of an existing channel when testing - "stop". - - dtucker@cvs.openbsd.org 2012/09/10 01:51:19 - [regress/multiplex.sh] - use -Ocheck and waiting for completions by PID to make multiplexing test - less racy and (hopefully) more reliable on slow hardware. - - [Makefile umac.c] Add special-case target to build umac128.o. - - [umac.c] Enforce allowed umac output sizes. From djm@. - - [Makefile.in] "Using $< in a non-suffix rule context is a GNUmake idiom". - -20120917 - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2012/09/13 23:37:36 - [servconf.c] - Fix comment line length - - markus@cvs.openbsd.org 2012/09/14 16:51:34 - [sshconnect.c] - remove unused variable - -20120907 - - (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2012/09/06 09:50:13 - [clientloop.c] - Make the escape command help (~?) context sensitive so that only commands - that will work in the current session are shown. ok markus@ - - jmc@cvs.openbsd.org 2012/09/06 13:57:42 - [ssh.1] - missing letter in previous; - - dtucker@cvs.openbsd.org 2012/09/07 00:30:19 - [clientloop.c] - Print '^Z' instead of a raw ^Z when the sequence is not supported. ok djm@ - - dtucker@cvs.openbsd.org 2012/09/07 01:10:21 - [clientloop.c] - Merge escape help text for ~v and ~V; ok djm@ - - dtucker@cvs.openbsd.org 2012/09/07 06:34:21 - [clientloop.c] - when muxmaster is run with -N, make it shut down gracefully when a client - sends it "-O stop" rather than hanging around (bz#1985). ok djm@ - -20120906 - - (dtucker) OpenBSD CVS Sync - - jmc@cvs.openbsd.org 2012/08/15 18:25:50 - [ssh-keygen.1] - a little more info on certificate validity; - requested by Ross L Richardson, and provided by djm - - dtucker@cvs.openbsd.org 2012/08/17 00:45:45 - [clientloop.c clientloop.h mux.c] - Force a clean shutdown of ControlMaster client sessions when the ~. escape - sequence is used. This means that ~. should now work in mux clients even - if the server is no longer responding. Found by tedu, ok djm. - - djm@cvs.openbsd.org 2012/08/17 01:22:56 - [kex.c] - add some comments about better handling first-KEX-follows notifications - from the server. Nothing uses these right now. No binary change - - djm@cvs.openbsd.org 2012/08/17 01:25:58 - [ssh-keygen.c] - print details of which host lines were deleted when using - "ssh-keygen -R host"; ok markus@ - - djm@cvs.openbsd.org 2012/08/17 01:30:00 - [compat.c sshconnect.c] - Send client banner immediately, rather than waiting for the server to - move first for SSH protocol 2 connections (the default). Patch based on - one in bz#1999 by tls AT panix.com, feedback dtucker@ ok markus@ - - dtucker@cvs.openbsd.org 2012/09/06 04:37:39 - [clientloop.c log.c ssh.1 log.h] - Add ~v and ~V escape sequences to raise and lower the logging level - respectively. Man page help from jmc, ok deraadt jmc - -20120830 - - (dtucker) [moduli] Import new moduli file. - -20120828 - - (djm) Release openssh-6.1 - -20120828 - - (dtucker) [openbsd-compat/bsd-cygwin_util.h] define WIN32_LEAN_AND_MEAN - for compatibility with future mingw-w64 headers. Patch from vinschen at - redhat com. - -20120822 - - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec] - [contrib/suse/openssh.spec] Update version numbers - -20120731 - - (djm) OpenBSD CVS Sync - - jmc@cvs.openbsd.org 2012/07/06 06:38:03 - [ssh-keygen.c] - missing full stop in usage(); - - djm@cvs.openbsd.org 2012/07/10 02:19:15 - [servconf.c servconf.h sshd.c sshd_config] - Turn on systrace sandboxing of pre-auth sshd by default for new installs - by shipping a config that overrides the current UsePrivilegeSeparation=yes - default. Make it easier to flip the default in the future by adding too. - prodded markus@ feedback dtucker@ "get it in" deraadt@ - - dtucker@cvs.openbsd.org 2012/07/13 01:35:21 - [servconf.c] - handle long comments in config files better. bz#2025, ok markus - - markus@cvs.openbsd.org 2012/07/22 18:19:21 - [version.h] - openssh 6.1 - -20120720 - - (dtucker) Import regened moduli file. - -20120706 - - (djm) [sandbox-seccomp-filter.c] fallback to rlimit if seccomp filter is - not available. Allows use of sshd compiled on host with a filter-capable - kernel on hosts that lack the support. bz#2011 ok dtucker@ - - (djm) [configure.ac] Recursively expand $(bindir) to ensure it has no - unexpanded $(prefix) embedded. bz#2007 patch from nix-corp AT - esperi.org.uk; ok dtucker@ -- (djm) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2012/07/06 00:41:59 - [moduli.c ssh-keygen.1 ssh-keygen.c] - Add options to specify starting line number and number of lines to process - when screening moduli candidates. This allows processing of different - parts of a candidate moduli file in parallel. man page help jmc@, ok djm@ - - djm@cvs.openbsd.org 2012/07/06 01:37:21 - [mux.c] - fix memory leak of passed-in environment variables and connection - context when new session message is malformed; bz#2003 from Bert.Wesarg - AT googlemail.com - - djm@cvs.openbsd.org 2012/07/06 01:47:38 - [ssh.c] - move setting of tty_flag to after config parsing so RequestTTY options - are correctly picked up. bz#1995 patch from przemoc AT gmail.com; - ok dtucker@ +commit 39e2f1229562e1195169905607bc12290d21f021 +Author: millert@openbsd.org +Date: Sun Mar 1 15:44:40 2015 +0000 -20120704 - - (dtucker) [configure.ac openbsd-compat/bsd-misc.h] Add setlinebuf for - platforms that don't have it. "looks good" tim@ - -20120703 - - (dtucker) [configure.ac] Detect platforms that can't use select(2) with - setrlimit(RLIMIT_NOFILE, rl_zero) and disable the rlimit sandbox on those. - - (dtucker) [configure.ac sandbox-rlimit.c] Test whether or not - setrlimit(RLIMIT_FSIZE, rl_zero) and skip it if it's not supported. Its - benefit is minor, so it's not worth disabling the sandbox if it doesn't - work. - -20120702 -- (dtucker) OpenBSD CVS Sync - - naddy@cvs.openbsd.org 2012/06/29 13:57:25 - [ssh_config.5 sshd_config.5] - match the documented MAC order of preference to the actual one; - ok dtucker@ - - markus@cvs.openbsd.org 2012/06/30 14:35:09 - [sandbox-systrace.c sshd.c] - fix a during the load of the sandbox policies (child can still make - the read-syscall and wait forever for systrace-answers) by replacing - the read/write synchronisation with SIGSTOP/SIGCONT; - report and help hshoexer@; ok djm@, dtucker@ - - dtucker@cvs.openbsd.org 2012/07/02 08:50:03 - [ssh.c] - set interactive ToS for forwarded X11 sessions. ok djm@ - - dtucker@cvs.openbsd.org 2012/07/02 12:13:26 - [ssh-pkcs11-helper.c sftp-client.c] - fix a couple of "assigned but not used" warnings. ok markus@ - - dtucker@cvs.openbsd.org 2012/07/02 14:37:06 - [regress/connect-privsep.sh] - remove exit from end of test since it prevents reporting failure - - (dtucker) [regress/reexec.sh regress/sftp-cmds.sh regress/test-exec.sh] - Move cygwin detection to test-exec and use to skip reexec test on cygwin. - - (dtucker) [regress/test-exec.sh] Correct uname for cygwin/w2k. - -20120629 - - OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2012/06/21 00:16:07 - [addrmatch.c] - fix strlcpy truncation check. from carsten at debian org, ok markus - - dtucker@cvs.openbsd.org 2012/06/22 12:30:26 - [monitor.c sshconnect2.c] - remove dead code following 'for (;;)' loops. - From Steve.McClellan at radisys com, ok markus@ - - dtucker@cvs.openbsd.org 2012/06/22 14:36:33 - [sftp.c] - Remove unused variable leftover from tab-completion changes. - From Steve.McClellan at radisys com, ok markus@ - - dtucker@cvs.openbsd.org 2012/06/26 11:02:30 - [sandbox-systrace.c] - Add mquery to the list of allowed syscalls for "UsePrivilegeSeparation - sandbox" since malloc now uses it. From johnw.mail at gmail com. - - dtucker@cvs.openbsd.org 2012/06/28 05:07:45 - [mac.c myproposal.h ssh_config.5 sshd_config.5] - Remove hmac-sha2-256-96 and hmac-sha2-512-96 MACs since they were removed - from draft6 of the spec and will not be in the RFC when published. Patch - from mdb at juniper net via bz#2023, ok markus. - - naddy@cvs.openbsd.org 2012/06/29 13:57:25 - [ssh_config.5 sshd_config.5] - match the documented MAC order of preference to the actual one; ok dtucker@ - - dtucker@cvs.openbsd.org 2012/05/13 01:42:32 - [regress/addrmatch.sh] - Add "Match LocalAddress" and "Match LocalPort" to sshd and adjust tests - to match. Feedback and ok djm@ markus@. - - djm@cvs.openbsd.org 2012/06/01 00:47:35 - [regress/multiplex.sh regress/forwarding.sh] - append to rather than truncate test log; bz#2013 from openssh AT - roumenpetrov.info - - djm@cvs.openbsd.org 2012/06/01 00:52:52 - [regress/sftp-cmds.sh] - don't delete .* on cleanup due to unintended env expansion; pointed out in - bz#2014 by openssh AT roumenpetrov.info - - dtucker@cvs.openbsd.org 2012/06/26 12:06:59 - [regress/connect-privsep.sh] - test sandbox with every malloc option - - dtucker@cvs.openbsd.org 2012/06/28 05:07:45 - [regress/try-ciphers.sh regress/cipher-speed.sh] - Remove hmac-sha2-256-96 and hmac-sha2-512-96 MACs since they were removed - from draft6 of the spec and will not be in the RFC when published. Patch - from mdb at juniper net via bz#2023, ok markus. - - (dtucker) [myproposal.h] Remove trailing backslash to fix compile error. - - (dtucker) [key.c] ifdef out sha256 key types on platforms that don't have - the required functions in libcrypto. - -20120628 - - (dtucker) [openbsd-compat/getrrsetbyname-ldns.c] bz #2022: prevent null - pointer deref in the client when built with LDNS and using DNSSEC with a - CNAME. Patch from gregdlg+mr at hochet info. - -20120622 - - (dtucker) [contrib/cygwin/ssh-host-config] Ensure that user sshd runs as - can logon as a service. Patch from vinschen at redhat com. - -20120620 - - (djm) OpenBSD CVS Sync - - djm@cvs.openbsd.org 2011/12/02 00:41:56 - [mux.c] - fix bz#1948: ssh -f doesn't fork for multiplexed connection. + upstream commit + + Make sure we only call getnameinfo() for AF_INET or AF_INET6 + sockets. getpeername() of a Unix domain socket may return without error on + some systems without actually setting ss_family so getnameinfo() was getting + called with ss_family set to AF_UNSPEC. OK djm@ + +commit e47536ba9692d271b8ad89078abdecf0a1c11707 +Author: Damien Miller +Date: Sat Feb 28 08:20:11 2015 -0800 + + portability fixes for regress/netcat.c + + Mostly avoiding "err(1, NULL)" + +commit 02973ad5f6f49d8420e50a392331432b0396c100 +Author: Damien Miller +Date: Sat Feb 28 08:05:27 2015 -0800 + + twiddle another test for portability + + from Tom G. Christensen + +commit f7f3116abf2a6e2f309ab096b08c58d19613e5d0 +Author: Damien Miller +Date: Fri Feb 27 15:52:49 2015 -0800 + + twiddle test for portability + +commit 1ad3a77cc9d5568f5437ff99d377aa7a41859b83 +Author: Damien Miller +Date: Thu Feb 26 20:33:22 2015 -0800 + + make regress/netcat.c fd passing (more) portable + +commit 9e1cfca7e1fe9cf8edb634fc894e43993e4da1ea +Author: Damien Miller +Date: Thu Feb 26 20:32:58 2015 -0800 + + create OBJ/valgrind-out before running unittests + +commit bd58853102cee739f0e115e6d4b5334332ab1442 +Author: Damien Miller +Date: Wed Feb 25 16:58:22 2015 -0800 + + valgrind support + +commit f43d17269194761eded9e89f17456332f4c83824 +Author: djm@openbsd.org +Date: Thu Feb 26 20:45:47 2015 +0000 + + upstream commit + + don't printf NULL key comments; reported by Tom Christensen + +commit 6e6458b476ec854db33e3e68ebf4f489d0ab3df8 +Author: djm@openbsd.org +Date: Wed Feb 25 23:05:47 2015 +0000 + + upstream commit + + zero cmsgbuf before use; we initialise the bits we use + but valgrind still spams warning on it + +commit a63cfa26864b93ab6afefad0b630e5358ed8edfa +Author: djm@openbsd.org +Date: Wed Feb 25 19:54:02 2015 +0000 + + upstream commit + + fix small memory leak when UpdateHostkeys=no + +commit e6b950341dd75baa8526f1862bca39e52f5b879b +Author: Tim Rice +Date: Wed Feb 25 09:56:48 2015 -0800 + + Revert "Work around finicky USL linker so netcat will build." + + This reverts commit d1db656021d0cd8c001a6692f772f1de29b67c8b. + + No longer needed with commit 678e473e2af2e4802f24dd913985864d9ead7fb3 + +commit 6f621603f9cff2a5d6016a404c96cb2f8ac2dec0 +Author: djm@openbsd.org +Date: Wed Feb 25 17:29:38 2015 +0000 + + upstream commit + + don't leak validity of user in "too many authentication + failures" disconnect message; reported by Sebastian Reitenbach + +commit 6288e3a935494df12519164f52ca5c8c65fc3ca5 +Author: naddy@openbsd.org +Date: Tue Feb 24 15:24:05 2015 +0000 + + upstream commit + + add -v (show ASCII art) to -l's synopsis; ok djm@ + +commit 678e473e2af2e4802f24dd913985864d9ead7fb3 +Author: Darren Tucker +Date: Thu Feb 26 04:12:58 2015 +1100 + + Remove dependency on xmalloc. + + Remove ssh_get_progname's dependency on xmalloc, which should reduce + link order problems. ok djm@ + +commit 5d5ec165c5b614b03678afdad881f10e25832e46 +Author: Darren Tucker +Date: Wed Feb 25 15:32:49 2015 +1100 + + Restrict ECDSA and ECDH tests. + + ifdef out some more ECDSA and ECDH tests when built against an OpenSSL + that does not have eliptic curve functionality. + +commit 1734e276d99b17e92d4233fac7aef3a3180aaca7 +Author: Darren Tucker +Date: Wed Feb 25 13:40:45 2015 +1100 + + Move definition of _NSIG. + + _NSIG is only unsed in one file, so move it there prevent redefinition + warnings reported by Kevin Brott. + +commit a47ead7c95cfbeb72721066c4da2312e5b1b9f3d +Author: Darren Tucker +Date: Wed Feb 25 13:17:40 2015 +1100 + + Add includes.h for compatibility stuff. + +commit 38806bda6d2e48ad32812b461eebe17672ada771 +Author: Damien Miller +Date: Tue Feb 24 16:50:06 2015 -0800 + + include netdb.h to look for MAXHOSTNAMELEN; ok tim + +commit d1db656021d0cd8c001a6692f772f1de29b67c8b +Author: Tim Rice +Date: Tue Feb 24 10:42:08 2015 -0800 + + Work around finicky USL linker so netcat will build. + +commit cb030ce25f555737e8ba97bdd7883ac43f3ff2a3 +Author: Damien Miller +Date: Tue Feb 24 09:23:04 2015 -0800 + + include includes.h to avoid build failure on AIX + +commit 13af342458f5064144abbb07e5ac9bbd4eb42567 +Author: Tim Rice +Date: Tue Feb 24 07:56:47 2015 -0800 + + Original portability patch from djm@ for platforms missing err.h. + Fix name space clash on Solaris 10. Still more to do for Solaris 10 + to deal with msghdr structure differences. ok djm@ + +commit 910209203d0cd60c5083901cbcc0b7b44d9f48d2 +Author: Tim Rice +Date: Mon Feb 23 22:06:56 2015 -0800 + + cleaner way fix dispatch.h portion of commit + a88dd1da119052870bb2654c1a32c51971eade16 + (some systems have sig_atomic_t in signal.h, some in sys/signal.h) + Sounds good to me djm@ + +commit 676c38d7cbe65b76bbfff796861bb6615cc6a596 +Author: Tim Rice +Date: Mon Feb 23 21:51:33 2015 -0800 + + portability fix: if we can't dind a better define for HOST_NAME_MAX, use 255 + +commit 1221b22023dce38cbc90ba77eae4c5d78c77a5e6 +Author: Tim Rice +Date: Mon Feb 23 21:50:34 2015 -0800 + + portablity fix: s/__inline__/inline/ + +commit 4c356308a88d309c796325bb75dce90ca16591d5 +Author: Darren Tucker +Date: Tue Feb 24 13:49:31 2015 +1100 + + Wrap stdint.h includes in HAVE_STDINT_H. + +commit c9c88355c6a27a908e7d1e5003a2b35ea99c1614 +Author: Darren Tucker +Date: Tue Feb 24 13:43:57 2015 +1100 + + Add AI_NUMERICSERV to fake-rfc2553. + + Our getaddrinfo implementation always returns numeric values already. + +commit ef342ab1ce6fb9a4b30186c89c309d0ae9d0eeb4 +Author: Darren Tucker +Date: Tue Feb 24 13:39:57 2015 +1100 + + Include OpenSSL's objects.h before bn.h. + + Prevents compile errors on some platforms (at least old GCCs and AIX's + XLC compilers). + +commit dcc8997d116f615195aa7c9ec019fb36c28c6228 +Author: Darren Tucker +Date: Tue Feb 24 12:30:59 2015 +1100 + + Convert two macros into functions. + + Convert packet_send_debug and packet_disconnect from macros to + functions. Some older GCCs (2.7.x, 2.95.x) see to have problems with + variadic macros with only one argument so we convert these two into + functions. ok djm@ + +commit 2285c30d51b7e2052c6526445abe7e7cc7e170a1 +Author: djm@openbsd.org +Date: Mon Feb 23 22:21:21 2015 +0000 + + upstream commit + + further silence spurious error message even when -v is + specified (e.g. to get visual host keys); reported by naddy@ + +commit 9af21979c00652029e160295e988dea40758ece2 +Author: Damien Miller +Date: Tue Feb 24 09:04:32 2015 +1100 + + don't include stdint.h unless HAVE_STDINT_H set + +commit 62f678dd51660d6f8aee1da33d3222c5de10a89e +Author: Damien Miller +Date: Tue Feb 24 09:02:54 2015 +1100 + + nother sys/queue.h -> sys-queue.h fix + + spotted by Tom Christensen + +commit b3c19151cba2c0ed01b27f55de0d723ad07ca98f +Author: djm@openbsd.org +Date: Mon Feb 23 20:32:15 2015 +0000 + + upstream commit + + fix a race condition by using a mux socket rather than an + ineffectual wait statement + +commit a88dd1da119052870bb2654c1a32c51971eade16 +Author: Damien Miller +Date: Tue Feb 24 06:30:29 2015 +1100 + + various include fixes for portable + +commit 5248429b5ec524d0a65507cff0cdd6e0cb99effd +Author: djm@openbsd.org +Date: Mon Feb 23 16:55:51 2015 +0000 + + upstream commit + + add an XXX to remind me to improve sshkey_load_public + +commit e94e4b07ef2eaead38b085a60535df9981cdbcdb +Author: djm@openbsd.org +Date: Mon Feb 23 16:55:31 2015 +0000 + + upstream commit + + silence a spurious error message when listing + fingerprints for known_hosts; bz#2342 + +commit f2293a65392b54ac721f66bc0b44462e8d1d81f8 +Author: djm@openbsd.org +Date: Mon Feb 23 16:33:25 2015 +0000 + + upstream commit + + fix setting/clearing of TTY raw mode around + UpdateHostKeys=ask confirmation question; reported by Herb Goldman + +commit f2004cd1adf34492eae0a44b1ef84e0e31b06088 +Author: Darren Tucker +Date: Mon Feb 23 05:04:21 2015 +1100 + + Repair for non-ECC OpenSSL. + + Ifdef out the ECC parts when building with an OpenSSL that doesn't have + it. + +commit 37f9220db8d1a52c75894c3de1e5f2ae5bd71b6f +Author: Darren Tucker +Date: Mon Feb 23 03:07:24 2015 +1100 + + Wrap stdint.h includes in ifdefs. + +commit f81f1bbc5b892c8614ea740b1f92735652eb43f0 +Author: Tim Rice +Date: Sat Feb 21 18:12:10 2015 -0800 + + out of tree build fix + +commit 2e13a1e4d22f3b503c3bfc878562cc7386a1d1ae +Author: Tim Rice +Date: Sat Feb 21 18:08:51 2015 -0800 + + mkdir kex unit test directory so testing out of tree builds works + +commit 1797f49b1ba31e8700231cd6b1d512d80bb50d2c +Author: halex@openbsd.org +Date: Sat Feb 21 21:46:57 2015 +0000 + + upstream commit + + make "ssh-add -d" properly remove a corresponding + certificate, and also not whine and fail if there is none + + ok djm@ + +commit 7faaa32da83a609059d95dbfcb0649fdb04caaf6 +Author: Damien Miller +Date: Sun Feb 22 07:57:27 2015 +1100 + + mkdir hostkey and bitmap unit test directories + +commit bd49da2ef197efac5e38f5399263a8b47990c538 +Author: djm@openbsd.org +Date: Fri Feb 20 23:46:01 2015 +0000 + + upstream commit + + sort options useable under Match case-insensitively; prodded + jmc@ + +commit 1a779a0dd6cd8b4a1a40ea33b5415ab8408128ac +Author: djm@openbsd.org +Date: Sat Feb 21 20:51:02 2015 +0000 + + upstream commit + + correct paths to configuration files being written/updated; + they live in $OBJ not cwd; some by Roumen Petrov + +commit 28ba006c1acddff992ae946d0bc0b500b531ba6b +Author: Darren Tucker +Date: Sat Feb 21 15:41:07 2015 +1100 + + More correct checking of HAVE_DECL_AI_NUMERICSERV. + +commit e50e8c97a9cecae1f28febccaa6ca5ab3bc10f54 +Author: Darren Tucker +Date: Sat Feb 21 15:10:33 2015 +1100 + + Add null declaration of AI_NUMERICINFO. + + Some platforms (older FreeBSD and DragonFly versions) do have + getaddrinfo() but do not have AI_NUMERICINFO. so define it to zero + in those cases. + +commit 18a208d6a460d707a45916db63a571e805f5db46 +Author: djm@openbsd.org +Date: Fri Feb 20 22:40:32 2015 +0000 + + upstream commit + + more options that are available under Match; bz#2353 reported + by calestyo AT scientia.net + +commit 44732de06884238049f285f1455b2181baa7dc82 +Author: djm@openbsd.org +Date: Fri Feb 20 22:17:21 2015 +0000 + + upstream commit + + UpdateHostKeys fixes: + + I accidentally changed the format of the hostkeys@openssh.com messages + last week without changing the extension name, and this has been causing + connection failures for people who are running -current. First reported + by sthen@ + + s/hostkeys@openssh.com/hostkeys-00@openssh.com/ + Change the name of the proof message too, and reorder it a little. + + Also, UpdateHostKeys=ask is incompatible with ControlPersist (no TTY + available to read the response) so disable UpdateHostKeys if it is in + ask mode and ControlPersist is active (and document this) + +commit 13a39414d25646f93e6d355521d832a03aaaffe2 +Author: djm@openbsd.org +Date: Tue Feb 17 00:14:05 2015 +0000 + + upstream commit + + Regression: I broke logging of public key fingerprints in + 1.46. Pointed out by Pontus Lundkvist + +commit 773dda25e828c4c9a52f7bdce6e1e5924157beab +Author: Damien Miller +Date: Fri Jan 30 23:10:17 2015 +1100 + + repair --without-openssl; broken in refactor + +commit e89c780886b23600de1e1c8d74aabd1ff61f43f0 +Author: Damien Miller +Date: Tue Feb 17 10:04:55 2015 +1100 + + hook up hostkeys unittest to portable Makefiles + +commit 0abf41f99aa16ff09b263bead242d6cb2dbbcf99 +Author: djm@openbsd.org +Date: Mon Feb 16 22:21:03 2015 +0000 + + upstream commit + + enable hostkeys unit tests + +commit 68a5d647ccf0fb6782b2f749433a1eee5bc9044b +Author: djm@openbsd.org +Date: Mon Feb 16 22:20:50 2015 +0000 + + upstream commit + + check string/memory compare arguments aren't NULL + +commit ef575ef20d09f20722e26b45dab80b3620469687 +Author: djm@openbsd.org +Date: Mon Feb 16 22:18:34 2015 +0000 + + upstream commit + + unit tests for hostfile.c code, just hostkeys_foreach so + far + +commit 8ea3365e6aa2759ccf5c76eaea62cbc8a280b0e7 +Author: markus@openbsd.org +Date: Sat Feb 14 12:43:16 2015 +0000 + + upstream commit + + test server rekey limit + +commit ce63c4b063c39b2b22d4ada449c9e3fbde788cb3 +Author: djm@openbsd.org +Date: Mon Feb 16 22:30:03 2015 +0000 + + upstream commit + + partial backout of: + + revision 1.441 + date: 2015/01/31 20:30:05; author: djm; state: Exp; lines: +17 -10; commitid + : x8klYPZMJSrVlt3O; + Let sshd load public host keys even when private keys are missing. + Allows sshd to advertise additional keys for future key rotation. + Also log fingerprint of hostkeys loaded; ok markus@ + + hostkey updates now require access to the private key, so we can't + load public keys only. The improved log messages (fingerprints of keys + loaded) are kept. + +commit 523463a3a2a9bfc6cfc5afa01bae9147f76a37cc +Author: djm@openbsd.org +Date: Mon Feb 16 22:13:32 2015 +0000 + + upstream commit + + Revise hostkeys@openssh.com hostkey learning extension. + + The client will not ask the server to prove ownership of the private + halves of any hitherto-unseen hostkeys it offers to the client. + + Allow UpdateHostKeys option to take an 'ask' argument to let the + user manually review keys offered. + + ok markus@ + +commit 6c5c949782d86a6e7d58006599c7685bfcd01685 +Author: djm@openbsd.org +Date: Mon Feb 16 22:08:57 2015 +0000 + + upstream commit + + Refactor hostkeys_foreach() and dependent code Deal with + IP addresses (i.e. CheckHostIP) Don't clobber known_hosts when nothing + changed ok markus@ as part of larger commit + +commit 51b082ccbe633dc970df1d1f4c9c0497115fe721 +Author: miod@openbsd.org +Date: Mon Feb 16 18:26:26 2015 +0000 + + upstream commit + + Declare ge25519_base as extern, to prevent it from + becoming a common. Gets us rid of ``lignment 4 of symbol + `crypto_sign_ed25519_ref_ge25519_base' in mod_ge25519.o is smaller than 16 in + mod_ed25519.o'' warnings at link time. + +commit 02db468bf7e3281a8e3c058ced571b38b6407c34 +Author: markus@openbsd.org +Date: Fri Feb 13 18:57:00 2015 +0000 + + upstream commit + + make rekey_limit for sshd w/privsep work; ok djm@ + dtucker@ + +commit 8ec67d505bd23c8bf9e17b7a364b563a07a58ec8 +Author: dtucker@openbsd.org +Date: Thu Feb 12 20:34:19 2015 +0000 + + upstream commit + + Prevent sshd spamming syslog with + "ssh_dispatch_run_fatal: disconnected". ok markus@ + +commit d4c0295d1afc342057ba358237acad6be8af480b +Author: djm@openbsd.org +Date: Wed Feb 11 01:20:38 2015 +0000 + + upstream commit + + Some packet error messages show the address of the peer, + but might be generated after the socket to the peer has suffered a TCP reset. + In these cases, getpeername() won't work so cache the address earlier. + + spotted in the wild via deraadt@ and tedu@ + +commit 4af1709cf774475ce5d1bc3ddcc165f6c222897d +Author: jsg@openbsd.org +Date: Mon Feb 9 23:22:37 2015 +0000 + + upstream commit + + fix some leaks in error paths ok markus@ + +commit fd36834871d06a03e1ff8d69e41992efa1bbf85f +Author: millert@openbsd.org +Date: Fri Feb 6 23:21:59 2015 +0000 + + upstream commit + + SIZE_MAX is standard, we should be using it in preference to + the obsolete SIZE_T_MAX. OK miod@ beck@ + +commit 1910a286d7771eab84c0b047f31c0a17505236fa +Author: millert@openbsd.org +Date: Thu Feb 5 12:59:57 2015 +0000 + + upstream commit + + Include stdint.h, not limits.h to get SIZE_MAX. OK guenther@ + +commit ce4f59b2405845584f45e0b3214760eb0008c06c +Author: deraadt@openbsd.org +Date: Tue Feb 3 08:07:20 2015 +0000 + + upstream commit + + missing ; djm and mlarkin really having great + interactions recently + +commit 5d34aa94938abb12b877a25be51862757f25d54b +Author: halex@openbsd.org +Date: Tue Feb 3 00:34:14 2015 +0000 + + upstream commit + + slightly extend the passphrase prompt if running with -c + in order to give the user a chance to notice if unintentionally running + without it + + wording tweak and ok djm@ + +commit cb3bde373e80902c7d5d0db429f85068d19b2918 +Author: djm@openbsd.org +Date: Mon Feb 2 22:48:53 2015 +0000 + + upstream commit + + handle PKCS#11 C_Login returning + CKR_USER_ALREADY_LOGGED_IN; based on patch from Yuri Samoilenko; ok markus@ + +commit 15ad750e5ec3cc69765b7eba1ce90060e7083399 +Author: djm@openbsd.org +Date: Mon Feb 2 07:41:40 2015 +0000 + + upstream commit + + turn UpdateHostkeys off by default until I figure out + mlarkin@'s warning message; requested by deraadt@ + +commit 3cd5103c1e1aaa59bd66f7f52f6ebbcd5deb12f9 +Author: deraadt@openbsd.org +Date: Mon Feb 2 01:57:44 2015 +0000 + + upstream commit + + increasing encounters with difficult DNS setups in + darknets has convinced me UseDNS off by default is better ok djm + +commit 6049a548a8a68ff0bbe581ab1748ea6a59ecdc38 +Author: djm@openbsd.org +Date: Sat Jan 31 20:30:05 2015 +0000 + + upstream commit + + Let sshd load public host keys even when private keys are + missing. Allows sshd to advertise additional keys for future key rotation. + Also log fingerprint of hostkeys loaded; ok markus@ + +commit 46347ed5968f582661e8a70a45f448e0179ca0ab +Author: djm@openbsd.org +Date: Fri Jan 30 11:43:14 2015 +0000 + + upstream commit + + Add a ssh_config HostbasedKeyType option to control which + host public key types are tried during hostbased authentication. + + This may be used to prevent too many keys being sent to the server, + and blowing past its MaxAuthTries limit. + + bz#2211 based on patch by Iain Morgan; ok markus@ + +commit 802660cb70453fa4d230cb0233bc1bbdf8328de1 +Author: djm@openbsd.org +Date: Fri Jan 30 10:44:49 2015 +0000 + + upstream commit + + set a timeout to prevent hangs when talking to busted + servers; ok markus@ + +commit 86936ec245a15c7abe71a0722610998b0a28b194 +Author: djm@openbsd.org +Date: Fri Jan 30 01:11:39 2015 +0000 + + upstream commit + + regression test for 'wildcard CA' serial/key ID revocations + +commit 4509b5d4a4fa645a022635bfa7e86d09b285001f +Author: djm@openbsd.org +Date: Fri Jan 30 01:13:33 2015 +0000 + + upstream commit + + avoid more fatal/exit in the packet.c paths that + ssh-keyscan uses; feedback and "looks good" markus@ + +commit 669aee994348468af8b4b2ebd29b602cf2860b22 +Author: djm@openbsd.org +Date: Fri Jan 30 01:10:33 2015 +0000 + + upstream commit + + permit KRLs that revoke certificates by serial number or + key ID without scoping to a particular CA; ok markus@ + +commit 7a2c368477e26575d0866247d3313da4256cb2b5 +Author: djm@openbsd.org +Date: Fri Jan 30 00:59:19 2015 +0000 + + upstream commit + + missing parentheses after if in do_convert_from() broke + private key conversion from other formats some time in 2010; bz#2345 reported + by jjelen AT redhat.com + +commit 25f5f78d8bf5c22d9cea8b49de24ebeee648a355 +Author: djm@openbsd.org +Date: Fri Jan 30 00:22:25 2015 +0000 + + upstream commit + + fix ssh protocol 1, spotted by miod@ + +commit 9ce86c926dfa6e0635161b035e3944e611cbccf0 +Author: djm@openbsd.org +Date: Wed Jan 28 22:36:00 2015 +0000 + + upstream commit + + update to new API (key_fingerprint => sshkey_fingerprint) + check sshkey_fingerprint return values; ok markus + +commit 9125525c37bf73ad3ee4025520889d2ce9d10f29 +Author: djm@openbsd.org +Date: Wed Jan 28 22:05:31 2015 +0000 + + upstream commit + + avoid fatal() calls in packet code makes ssh-keyscan more + reliable against server failures ok dtucker@ markus@ + +commit fae7bbe544cba7a9e5e4ab47ff6faa3d978646eb +Author: djm@openbsd.org +Date: Wed Jan 28 21:15:47 2015 +0000 + + upstream commit + + avoid fatal() calls in packet code makes ssh-keyscan more + reliable against server failures ok dtucker@ markus@ + +commit 1a3d14f6b44a494037c7deab485abe6496bf2c60 +Author: djm@openbsd.org +Date: Wed Jan 28 11:07:25 2015 +0000 + + upstream commit + + remove obsolete comment + +commit 80c25b7bc0a71d75c43a4575d9a1336f589eb639 +Author: okan@openbsd.org +Date: Tue Jan 27 12:54:06 2015 +0000 + + upstream commit + + Since r1.2 removed the use of PRI* macros, inttypes.h is + no longer required. + + ok djm@ + +commit 69ff64f69615c2a21c97cb5878a0996c21423257 +Author: Damien Miller +Date: Tue Jan 27 23:07:43 2015 +1100 + + compile on systems without TCP_MD5SIG (e.g. OSX) + +commit 358964f3082fb90b2ae15bcab07b6105cfad5a43 +Author: Damien Miller +Date: Tue Jan 27 23:07:25 2015 +1100 + + use ssh-keygen under test rather than system's + +commit a2c95c1bf33ea53038324d1fdd774bc953f98236 +Author: Damien Miller +Date: Tue Jan 27 23:06:59 2015 +1100 + + OSX lacks HOST_NAME_MAX, has _POSIX_HOST_NAME_MAX + +commit ade31d7b6f608a19b85bee29a7a00b1e636a2919 +Author: Damien Miller +Date: Tue Jan 27 23:06:23 2015 +1100 + + these need active_state defined to link on OSX + + temporary measure until active_state goes away entirely + +commit e56aa87502f22c5844918c10190e8b4f785f067b +Author: djm@openbsd.org +Date: Tue Jan 27 12:01:36 2015 +0000 + + upstream commit + + use printf instead of echo -n to reduce diff against + -portable + +commit 9f7637f56eddfaf62ce3c0af89c25480f2cf1068 +Author: jmc@openbsd.org +Date: Mon Jan 26 13:55:29 2015 +0000 + + upstream commit + + sort previous; + +commit 3076ee7d530d5b16842fac7a6229706c7e5acd26 +Author: djm@openbsd.org +Date: Mon Jan 26 13:36:53 2015 +0000 + + upstream commit + + properly restore umask + +commit d411d395556b73ba1b9e451516a0bd6697c4b03d +Author: djm@openbsd.org +Date: Mon Jan 26 06:12:18 2015 +0000 + + upstream commit + + regression test for host key rotation + +commit fe8a3a51699afbc6407a8fae59b73349d01e49f8 +Author: djm@openbsd.org +Date: Mon Jan 26 06:11:28 2015 +0000 + + upstream commit + + adapt to sshkey API tweaks + +commit 7dd355fb1f0038a3d5cdca57ebab4356c7a5b434 +Author: miod@openbsd.org +Date: Sat Jan 24 10:39:21 2015 +0000 + + upstream commit + + Move -lz late in the linker commandline for things to + build on static arches. + +commit 0dad3b806fddb93c475b30853b9be1a25d673a33 +Author: miod@openbsd.org +Date: Fri Jan 23 21:21:23 2015 +0000 + + upstream commit + + -Wpointer-sign is supported by gcc 4 only. + +commit 2b3b1c1e4bd9577b6e780c255c278542ea66c098 +Author: djm@openbsd.org +Date: Tue Jan 20 22:58:57 2015 +0000 + + upstream commit + + use SUBDIR to recuse into unit tests; makes "make obj" + actually work + +commit 1d1092bff8db27080155541212b420703f8b9c92 +Author: djm@openbsd.org +Date: Mon Jan 26 12:16:36 2015 +0000 + + upstream commit + + correct description of UpdateHostKeys in ssh_config.5 and + add it to -o lists for ssh, scp and sftp; pointed out by jmc@ + +commit 5104db7cbd6cdd9c5971f4358e74414862fc1022 +Author: djm@openbsd.org +Date: Mon Jan 26 06:10:03 2015 +0000 + + upstream commit + + correctly match ECDSA subtype (== curve) for + offered/recevied host keys. Fixes connection-killing host key mismatches when + a server offers multiple ECDSA keys with different curve type (an extremely + unlikely configuration). + + ok markus, "looks mechanical" deraadt@ + +commit 8d4f87258f31cb6def9b3b55b6a7321d84728ff2 +Author: djm@openbsd.org +Date: Mon Jan 26 03:04:45 2015 +0000 + + upstream commit + + Host key rotation support. + + Add a hostkeys@openssh.com protocol extension (global request) for + a server to inform a client of all its available host key after + authentication has completed. The client may record the keys in + known_hosts, allowing it to upgrade to better host key algorithms + and a server to gracefully rotate its keys. + + The client side of this is controlled by a UpdateHostkeys config + option (default on). + + ok markus@ + +commit 60b1825262b1f1e24fc72050b907189c92daf18e +Author: djm@openbsd.org +Date: Mon Jan 26 02:59:11 2015 +0000 + + upstream commit + + small refactor and add some convenience functions; ok + markus + +commit a5a3e3328ddce91e76f71ff479022d53e35c60c9 +Author: jmc@openbsd.org +Date: Thu Jan 22 21:00:42 2015 +0000 + + upstream commit + + heirarchy -> hierarchy; + +commit dcff5810a11195c57e1b3343c0d6b6f2b9974c11 +Author: deraadt@openbsd.org +Date: Thu Jan 22 20:24:41 2015 +0000 + + upstream commit + + Provide a warning about chroot misuses (which sadly, seem + to have become quite popular because shiny). sshd cannot detect/manage/do + anything about these cases, best we can do is warn in the right spot in the + man page. ok markus + +commit 087266ec33c76fc8d54ac5a19efacf2f4a4ca076 +Author: deraadt@openbsd.org +Date: Tue Jan 20 23:14:00 2015 +0000 + + upstream commit + + Reduce use of and transition to + throughout. ok djm markus + +commit 57e783c8ba2c0797f93977e83b2a8644a03065d8 +Author: markus@openbsd.org +Date: Tue Jan 20 20:16:21 2015 +0000 + + upstream commit + + kex_setup errors are fatal() + +commit 1d6424a6ff94633c221297ae8f42d54e12a20912 +Author: djm@openbsd.org +Date: Tue Jan 20 08:02:33 2015 +0000 + + upstream commit + + this test would accidentally delete agent.sh if run without + obj/ + +commit 12b5f50777203e12575f1b08568281e447249ed3 +Author: djm@openbsd.org +Date: Tue Jan 20 07:56:44 2015 +0000 + + upstream commit + + make this compile with KERBEROS5 enabled + +commit e2cc6bef08941256817d44d146115b3478586ad4 +Author: djm@openbsd.org +Date: Tue Jan 20 07:55:33 2015 +0000 + + upstream commit + + fix hostkeys in agent; ok markus@ + +commit 1ca3e2155aa5d3801a7ae050f85c71f41fcb95b1 +Author: Damien Miller +Date: Tue Jan 20 10:11:31 2015 +1100 + + fix kex test + +commit c78a578107c7e6dcf5d30a2f34cb6581bef14029 +Author: markus@openbsd.org +Date: Mon Jan 19 20:45:25 2015 +0000 + + upstream commit + + finally enable the KEX tests I wrote some years ago... + +commit 31821d7217e686667d04935aeec99e1fc4a46e7e +Author: markus@openbsd.org +Date: Mon Jan 19 20:42:31 2015 +0000 + + upstream commit + + adapt to new error message (SSH_ERR_MAC_INVALID) + +commit d3716ca19e510e95d956ae14d5b367e364bff7f1 +Author: djm@openbsd.org +Date: Mon Jan 19 17:31:13 2015 +0000 + + upstream commit + + this test was broken in at least two ways, such that it + wasn't checking that a KRL was not excluding valid keys + +commit 3f797653748e7c2b037dacb57574c01d9ef3b4d3 +Author: markus@openbsd.org +Date: Mon Jan 19 20:32:39 2015 +0000 + + upstream commit + + switch ssh-keyscan from setjmp to multiple ssh transport + layer instances ok djm@ + +commit f582f0e917bb0017b00944783cd5f408bf4b0b5e +Author: markus@openbsd.org +Date: Mon Jan 19 20:30:23 2015 +0000 + + upstream commit + + add experimental api for packet layer; ok djm@ + +commit 48b3b2ba75181f11fca7f327058a591f4426cade +Author: markus@openbsd.org +Date: Mon Jan 19 20:20:20 2015 +0000 + + upstream commit + + store compat flags in struct ssh; ok djm@ + +commit 57d10cbe861a235dd269c74fb2fe248469ecee9d +Author: markus@openbsd.org +Date: Mon Jan 19 20:16:15 2015 +0000 + + upstream commit + + adapt kex to sshbuf and struct ssh; ok djm@ + +commit 3fdc88a0def4f86aa88a5846ac079dc964c0546a +Author: markus@openbsd.org +Date: Mon Jan 19 20:07:45 2015 +0000 + + upstream commit + + move dispatch to struct ssh; ok djm@ + +commit 091c302829210c41e7f57c3f094c7b9c054306f0 +Author: markus@openbsd.org +Date: Mon Jan 19 19:52:16 2015 +0000 + + upstream commit + + update packet.c & isolate, introduce struct ssh a) switch + packet.c to buffer api and isolate per-connection info into struct ssh b) + (de)serialization of the state is moved from monitor to packet.c c) the old + packet.c API is implemented in opacket.[ch] d) compress.c/h is removed and + integrated into packet.c with and ok djm@ + +commit 4e62cc68ce4ba20245d208b252e74e91d3785b74 +Author: djm@openbsd.org +Date: Mon Jan 19 17:35:48 2015 +0000 + + upstream commit + + fix format strings in (disabled) debugging + +commit d85e06245907d49a2cd0cfa0abf59150ad616f42 +Author: djm@openbsd.org +Date: Mon Jan 19 06:01:32 2015 +0000 + + upstream commit + + be a bit more careful in these tests to ensure that + known_hosts is clean + +commit 7947810eab5fe0ad311f32a48f4d4eb1f71be6cf +Author: djm@openbsd.org +Date: Sun Jan 18 22:00:18 2015 +0000 + + upstream commit + + regression test for known_host file editing using + ssh-keygen (-H / -R / -F) after hostkeys_foreach() change; feedback and ok + markus@ + +commit 3a2b09d147a565d8a47edf37491e149a02c0d3a3 +Author: djm@openbsd.org +Date: Sun Jan 18 19:54:46 2015 +0000 + + upstream commit + + more and better key tests + + test signatures and verification + test certificate generation + flesh out nested cert test + + removes most of the XXX todo markers + +commit 589e69fd82724cfc9738f128e4771da2e6405d0d +Author: djm@openbsd.org +Date: Sun Jan 18 19:53:58 2015 +0000 + + upstream commit + + make the signature fuzzing test much more rigorous: + ensure that the fuzzed input cases do not match the original (using new + fuzz_matches_original() function) and check that the verification fails in + each case + +commit 80603c0daa2538c349c1c152405580b164d5475f +Author: djm@openbsd.org +Date: Sun Jan 18 19:52:44 2015 +0000 + + upstream commit + + add a fuzz_matches_original() function to the fuzzer to + detect fuzz cases that are identical to the original data. Hacky + implementation, but very useful when you need the fuzz to be different, e.g. + when verifying signature + +commit 87d5495bd337e358ad69c524fcb9495208c0750b +Author: djm@openbsd.org +Date: Sun Jan 18 19:50:55 2015 +0000 + + upstream commit + + better dumps from the fuzzer (shown on errors) - + include the original data as well as the fuzzed copy. + +commit d59ec478c453a3fff05badbbfd96aa856364f2c2 +Author: djm@openbsd.org +Date: Sun Jan 18 19:47:55 2015 +0000 + + upstream commit + + enable hostkey-agent.sh test + +commit 26b3425170bf840e4b095e1c10bf25a0a3e3a105 +Author: djm@openbsd.org +Date: Sat Jan 17 18:54:30 2015 +0000 + + upstream commit + + unit test for hostkeys in ssh-agent + +commit 9e06a0fb23ec55d9223b26a45bb63c7649e2f2f2 +Author: markus@openbsd.org +Date: Thu Jan 15 23:41:29 2015 +0000 + + upstream commit + + add kex unit tests + +commit d2099dec6da21ae627f6289aedae6bc1d41a22ce +Author: deraadt@openbsd.org +Date: Mon Jan 19 00:32:54 2015 +0000 + + upstream commit + + djm, your /usr/include tree is old + +commit 2b3c3c76c30dc5076fe09d590f5b26880f148a54 +Author: djm@openbsd.org +Date: Sun Jan 18 21:51:19 2015 +0000 + + upstream commit + + some feedback from markus@: comment hostkeys_foreach() + context and avoid a member in it. + +commit cecb30bc2ba6d594366e657d664d5c494b6c8a7f +Author: djm@openbsd.org +Date: Sun Jan 18 21:49:42 2015 +0000 + + upstream commit + + make ssh-keygen use hostkeys_foreach(). Removes some + horrendous code; ok markus@ + +commit ec3d065df3a9557ea96b02d061fd821a18c1a0b9 +Author: djm@openbsd.org +Date: Sun Jan 18 21:48:09 2015 +0000 + + upstream commit + + convert load_hostkeys() (hostkey ordering and + known_host matching) to use the new hostkey_foreach() iterator; ok markus + +commit c29811cc480a260e42fd88849fc86a80c1e91038 +Author: djm@openbsd.org +Date: Sun Jan 18 21:40:23 2015 +0000 + + upstream commit + + introduce hostkeys_foreach() to allow iteration over a + known_hosts file or controlled subset thereof. This will allow us to pull out + some ugly and duplicated code, and will be used to implement hostkey rotation + later. + + feedback and ok markus + +commit f101d8291da01bbbfd6fb8c569cfd0cc61c0d346 +Author: deraadt@openbsd.org +Date: Sun Jan 18 14:01:00 2015 +0000 + + upstream commit + + string truncation due to sizeof(size) ok djm markus + +commit 35d6022b55b7969fc10c261cb6aa78cc4a5fcc41 +Author: djm@openbsd.org +Date: Sun Jan 18 13:33:34 2015 +0000 + + upstream commit + + avoid trailing ',' in host key algorithms + +commit 7efb455789a0cb76bdcdee91c6060a3dc8f5c007 +Author: djm@openbsd.org +Date: Sun Jan 18 13:22:28 2015 +0000 + + upstream commit + + infer key length correctly when user specified a fully- + qualified key name instead of using the -b bits option; ok markus@ + +commit 83f8ffa6a55ccd0ce9d8a205e3e7439ec18fedf5 +Author: djm@openbsd.org +Date: Sat Jan 17 18:53:34 2015 +0000 + + upstream commit + + fix hostkeys on ssh agent; found by unit test I'm about + to commit + +commit 369d61f17657b814124268f99c033e4dc6e436c1 +Author: schwarze@openbsd.org +Date: Fri Jan 16 16:20:23 2015 +0000 + + upstream commit + + garbage collect empty .No macros mandoc warns about + +commit bb8b442d32dbdb8521d610e10d8b248d938bd747 +Author: djm@openbsd.org +Date: Fri Jan 16 15:55:07 2015 +0000 + + upstream commit + + regression: incorrect error message on + otherwise-successful ssh-keygen -A. Reported by Dmitry Orlov, via deraadt@ + +commit 9010902954a40b59d0bf3df3ccbc3140a653e2bc +Author: djm@openbsd.org +Date: Fri Jan 16 07:19:48 2015 +0000 + + upstream commit + + when hostname canonicalisation is enabled, try to parse + hostnames as addresses before looking them up for canonicalisation. fixes + bz#2074 and avoids needless DNS lookups in some cases; ok markus + +commit 2ae4f337b2a5fb2841b6b0053b49496fef844d1c +Author: deraadt@openbsd.org +Date: Fri Jan 16 06:40:12 2015 +0000 + + upstream commit + + Replace with and other less + dirty headers where possible. Annotate lines with their + current reasons. Switch to PATH_MAX, NGROUPS_MAX, HOST_NAME_MAX+1, + LOGIN_NAME_MAX, etc. Change MIN() and MAX() to local definitions of + MINIMUM() and MAXIMUM() where sensible to avoid pulling in the pollution. + These are the files confirmed through binary verification. ok guenther, + millert, doug (helped with the verification protocol) + +commit 3c4726f4c24118e8f1bb80bf75f1456c76df072c +Author: markus@openbsd.org +Date: Thu Jan 15 21:38:50 2015 +0000 + + upstream commit + + remove xmalloc, switch to sshbuf + +commit e17ac01f8b763e4b83976b9e521e90a280acc097 +Author: markus@openbsd.org +Date: Thu Jan 15 21:37:14 2015 +0000 + + upstream commit + + switch to sshbuf + +commit ddef9995a1fa6c7a8ff3b38bfe6cf724bebf13d0 +Author: naddy@openbsd.org +Date: Thu Jan 15 18:32:54 2015 +0000 + + upstream commit + + handle UMAC128 initialization like UMAC; ok djm@ markus@ + +commit f14564c1f7792446bca143580aef0e7ac25dcdae +Author: djm@openbsd.org +Date: Thu Jan 15 11:04:36 2015 +0000 + + upstream commit + + fix regression reported by brad@ for passworded keys without + agent present + +commit 45c0fd70bb2a88061319dfff20cb12ef7b1bc47e +Author: Damien Miller +Date: Thu Jan 15 22:08:23 2015 +1100 + + make bitmap test compile + +commit d333f89abf7179021e5c3f28673f469abe032062 +Author: djm@openbsd.org +Date: Thu Jan 15 07:36:28 2015 +0000 + + upstream commit + + unit tests for KRL bitmap + +commit 7613f828f49c55ff356007ae9645038ab6682556 +Author: markus@openbsd.org +Date: Wed Jan 14 09:58:21 2015 +0000 + + upstream commit + + re-add comment about full path + +commit 6c43b48b307c41cd656b415621a644074579a578 +Author: markus@openbsd.org +Date: Wed Jan 14 09:54:38 2015 +0000 + + upstream commit + + don't reset to the installed sshd; connect before + reconfigure, too + +commit 771bb47a1df8b69061f09462e78aa0b66cd594bf +Author: djm@openbsd.org +Date: Tue Jan 13 14:51:51 2015 +0000 + + upstream commit + + implement a SIGINFO handler so we can discern a stuck + fuzz test from a merely glacial one; prompted by and ok markus + +commit cfaa57962f8536f3cf0fd7daf4d6a55d6f6de45f +Author: djm@openbsd.org +Date: Tue Jan 13 08:23:26 2015 +0000 + + upstream commit + + use $SSH instead of installed ssh to allow override; + spotted by markus@ + +commit 0920553d0aee117a596b03ed5b49b280d34a32c5 +Author: djm@openbsd.org +Date: Tue Jan 13 07:49:49 2015 +0000 + + upstream commit + + regress test for PubkeyAcceptedKeyTypes; ok markus@ + +commit 27ca1a5c0095eda151934bca39a77e391f875d17 +Author: markus@openbsd.org +Date: Mon Jan 12 20:13:27 2015 +0000 + + upstream commit + + unbreak parsing of pubkey comments; with gerhard; ok + djm/deraadt + +commit 55358f0b4e0b83bc0df81c5f854c91b11e0bb4dc +Author: djm@openbsd.org +Date: Mon Jan 12 11:46:32 2015 +0000 + + upstream commit + + fatal if soft-PKCS11 library is missing rather (rather + than continue and fail with a more cryptic error) + +commit c3554cdd2a1a62434b8161017aa76fa09718a003 +Author: djm@openbsd.org +Date: Mon Jan 12 11:12:38 2015 +0000 + + upstream commit + + let this test all supporte key types; pointed out/ok + markus@ + +commit 1129dcfc5a3e508635004bcc05a3574cb7687167 +Author: djm@openbsd.org +Date: Thu Jan 15 09:40:00 2015 +0000 + + upstream commit + + sync ssh-keysign, ssh-keygen and some dependencies to the + new buffer/key API; mostly mechanical, ok markus@ + +commit e4ebf5586452bf512da662ac277aaf6ecf0efe7c +Author: djm@openbsd.org +Date: Thu Jan 15 07:57:08 2015 +0000 + + upstream commit + + remove commented-out test code now that it has moved to a + proper unit test + +commit e81cba066c1e9eb70aba0f6e7c0ff220611b370f +Author: djm@openbsd.org +Date: Wed Jan 14 20:54:29 2015 +0000 + + upstream commit + + whitespace + +commit 141efe49542f7156cdbc2e4cd0a041d8b1aab622 +Author: djm@openbsd.org +Date: Wed Jan 14 20:05:27 2015 +0000 + + upstream commit + + move authfd.c and its tentacles to the new buffer/key + API; ok markus@ + +commit 0088c57af302cda278bd26d8c3ae81d5b6f7c289 +Author: djm@openbsd.org +Date: Wed Jan 14 19:33:41 2015 +0000 + + upstream commit + + fix small regression: ssh-agent would return a success + message but an empty signature if asked to sign using an unknown key; ok + markus@ + +commit b03ebe2c22b8166e4f64c37737f4278676e3488d +Author: Damien Miller +Date: Thu Jan 15 03:08:58 2015 +1100 + + more --without-openssl + + fix some regressions caused by upstream merges + + enable KRLs now that they no longer require BIGNUMs + +commit bc42cc6fe784f36df225c44c93b74830027cb5a2 +Author: Damien Miller +Date: Thu Jan 15 03:08:29 2015 +1100 + + kludge around tun API mismatch betterer + +commit c332110291089b624fa0951fbf2d1ee6de525b9f +Author: Damien Miller +Date: Thu Jan 15 02:59:51 2015 +1100 + + some systems lack SO_REUSEPORT + +commit 83b9678a62cbdc74eb2031cf1e1e4ffd58e233ae +Author: Damien Miller +Date: Thu Jan 15 02:35:50 2015 +1100 + + fix merge botch + +commit 0cdc5a3eb6fb383569a4da2a30705d9b90428d6b +Author: Damien Miller +Date: Thu Jan 15 02:35:33 2015 +1100 + + unbreak across API change + +commit 6e2549ac2b5e7f96cbc2d83a6e0784b120444b47 +Author: Damien Miller +Date: Thu Jan 15 02:30:18 2015 +1100 + + need includes.h for portable OpenSSH + +commit 72ef7c148c42db7d5632a29f137f8b87b579f2d9 +Author: Damien Miller +Date: Thu Jan 15 02:21:31 2015 +1100 + + support --without-openssl at configure time + + Disables and removes dependency on OpenSSL. Many features don't + work and the set of crypto options is greatly restricted. This + will only work on system with native arc4random or /dev/urandom. + + Considered highly experimental for now. + +commit 4f38c61c68ae7e3f9ee4b3c38bc86cd39f65ece9 +Author: Damien Miller +Date: Thu Jan 15 02:28:00 2015 +1100 + + add files missed in last commit + +commit a165bab605f7be55940bb8fae977398e8c96a46d +Author: djm@openbsd.org +Date: Wed Jan 14 15:02:39 2015 +0000 + + upstream commit + + avoid BIGNUM in KRL code by using a simple bitmap; + feedback and ok markus + +commit 7d845f4a0b7ec97887be204c3760e44de8bf1f32 +Author: djm@openbsd.org +Date: Wed Jan 14 13:54:13 2015 +0000 + + upstream commit + + update sftp client and server to new buffer API. pretty + much just mechanical changes; with & ok markus + +commit 139ca81866ec1b219c717d17061e5e7ad1059e2a +Author: markus@openbsd.org +Date: Wed Jan 14 13:09:09 2015 +0000 + + upstream commit + + switch to sshbuf/sshkey; with & ok djm@ + +commit 81bfbd0bd35683de5d7f2238b985e5f8150a9180 +Author: Damien Miller +Date: Wed Jan 14 21:48:18 2015 +1100 + + support --without-openssl at configure time + + Disables and removes dependency on OpenSSL. Many features don't + work and the set of crypto options is greatly restricted. This + will only work on system with native arc4random or /dev/urandom. + + Considered highly experimental for now. + +commit 54924b53af15ccdcbb9f89984512b5efef641a31 +Author: djm@openbsd.org +Date: Wed Jan 14 10:46:28 2015 +0000 + + upstream commit + + avoid an warning for the !OPENSSL case + +commit ae8b463217f7c9b66655bfc3945c050ffdaeb861 +Author: markus@openbsd.org +Date: Wed Jan 14 10:30:34 2015 +0000 + + upstream commit + + swith auth-options to new sshbuf/sshkey; ok djm@ + +commit 540e891191b98b89ee90aacf5b14a4a68635e763 +Author: djm@openbsd.org +Date: Wed Jan 14 10:29:45 2015 +0000 + + upstream commit + + make non-OpenSSL aes-ctr work on sshd w/ privsep; ok + markus@ + +commit 60c2c4ea5e1ad0ddfe8b2877b78ed5143be79c53 +Author: markus@openbsd.org +Date: Wed Jan 14 10:24:42 2015 +0000 + + upstream commit + + remove unneeded includes, sync my copyright across files + & whitespace; ok djm@ + +commit 128343bcdb0b60fc826f2733df8cf979ec1627b4 +Author: markus@openbsd.org +Date: Tue Jan 13 19:31:40 2015 +0000 + + upstream commit + + adapt mac.c to ssherr.h return codes (de-fatal) and + simplify dependencies ok djm@ + +commit e7fd952f4ea01f09ceb068721a5431ac2fd416ed +Author: djm@openbsd.org +Date: Tue Jan 13 19:04:35 2015 +0000 + + upstream commit + + sync changes from libopenssh; prepared by markus@ mostly + debug output tweaks, a couple of error return value changes and some other + minor stuff + +commit 76c0480a85675f03a1376167cb686abed01a3583 +Author: Damien Miller +Date: Tue Jan 13 19:38:18 2015 +1100 + + add --without-ssh1 option to configure + + Allows disabling support for SSH protocol 1. + +commit 1f729f0614d1376c3332fa1edb6a5e5cec7e9e03 +Author: djm@openbsd.org +Date: Tue Jan 13 07:39:19 2015 +0000 + + upstream commit + + add sshd_config HostbasedAcceptedKeyTypes and + PubkeyAcceptedKeyTypes options to allow sshd to control what public key types + will be accepted. Currently defaults to all. Feedback & ok markus@ + +commit 816d1538c24209a93ba0560b27c4fda57c3fff65 +Author: markus@openbsd.org +Date: Mon Jan 12 20:13:27 2015 +0000 + + upstream commit + + unbreak parsing of pubkey comments; with gerhard; ok + djm/deraadt + +commit 0097565f849851812df610b7b6b3c4bd414f6c62 +Author: markus@openbsd.org +Date: Mon Jan 12 19:22:46 2015 +0000 + + upstream commit + + missing error assigment on sshbuf_put_string() + +commit a7f49dcb527dd17877fcb8d5c3a9a6f550e0bba5 +Author: djm@openbsd.org +Date: Mon Jan 12 15:18:07 2015 +0000 + + upstream commit + + apparently memcpy(x, NULL, 0) is undefined behaviour + according to C99 (cf. sections 7.21.1 and 7.1.4), so check skip memcpy calls + when length==0; ok markus@ + +commit 905fe30fca82f38213763616d0d26eb6790bde33 +Author: markus@openbsd.org +Date: Mon Jan 12 14:05:19 2015 +0000 + + upstream commit + + free->sshkey_free; ok djm@ + +commit f067cca2bc20c86b110174c3fef04086a7f57b13 +Author: markus@openbsd.org +Date: Mon Jan 12 13:29:27 2015 +0000 + + upstream commit + + allow WITH_OPENSSL w/o WITH_SSH1; ok djm@ + +commit c4bfafcc2a9300d9cfb3c15e75572d3a7d74670d +Author: djm@openbsd.org +Date: Thu Jan 8 13:10:58 2015 +0000 + + upstream commit + + adjust for sshkey_load_file() API change + +commit e752c6d547036c602b89e9e704851463bd160e32 +Author: djm@openbsd.org +Date: Thu Jan 8 13:44:36 2015 +0000 + + upstream commit + + fix ssh_config FingerprintHash evaluation order; from Petr + Lautrbach + +commit ab24ab847b0fc94c8d5e419feecff0bcb6d6d1bf +Author: djm@openbsd.org +Date: Thu Jan 8 10:15:45 2015 +0000 + + upstream commit + + reorder hostbased key attempts to better match the + default hostkey algorithms order in myproposal.h; ok markus@ + +commit 1195f4cb07ef4b0405c839293c38600b3e9bdb46 +Author: djm@openbsd.org +Date: Thu Jan 8 10:14:08 2015 +0000 + + upstream commit + + deprecate key_load_private_pem() and + sshkey_load_private_pem() interfaces. Refactor the generic key loading API to + not require pathnames to be specified (they weren't really used). + + Fixes a few other things en passant: + + Makes ed25519 keys work for hostbased authentication (ssh-keysign + previously used the PEM-only routines). + + Fixes key comment regression bz#2306: key pathnames were being lost as + comment fields. + + ok markus@ + +commit febbe09e4e9aff579b0c5cc1623f756862e4757d +Author: tedu@openbsd.org +Date: Wed Jan 7 18:15:07 2015 +0000 + + upstream commit + + workaround for the Meyer, et al, Bleichenbacher Side + Channel Attack. fake up a bignum key before RSA decryption. discussed/ok djm + markus + +commit 5191df927db282d3123ca2f34a04d8d96153911a +Author: djm@openbsd.org +Date: Tue Dec 23 22:42:48 2014 +0000 + + upstream commit + + KNF and add a little more debug() + +commit 8abd80315d3419b20e6938f74d37e2e2b547f0b7 +Author: jmc@openbsd.org +Date: Mon Dec 22 09:26:31 2014 +0000 + + upstream commit + + add fingerprinthash to the options list; + +commit 296ef0560f60980da01d83b9f0e1a5257826536f +Author: jmc@openbsd.org +Date: Mon Dec 22 09:24:59 2014 +0000 + + upstream commit + + tweak previous; + +commit 462082eacbd37778a173afb6b84c6f4d898a18b5 +Author: Damien Miller +Date: Tue Dec 30 08:16:11 2014 +1100 + + avoid uninitialised free of ldns_res + + If an invalid rdclass was passed to getrrsetbyname() then + this would execute a free on an uninitialised pointer. + OpenSSH only ever calls this with a fixed and valid rdclass. + + Reported by Joshua Rogers + +commit 01b63498801053f131a0740eb9d13faf35d636c8 +Author: Damien Miller +Date: Mon Dec 29 18:10:18 2014 +1100 + + pull updated OpenBSD BCrypt PBKDF implementation + + Includes fix for 1 byte output overflow for large key length + requests (not reachable in OpenSSH). + + Pointed out by Joshua Rogers + +commit c528c1b4af2f06712177b3de9b30705752f7cbcb +Author: Damien Miller +Date: Tue Dec 23 15:26:13 2014 +1100 + + fix variable name for IPv6 case in construct_utmpx + + patch from writeonce AT midipix.org via bz#2296 + +commit 293cac52dcda123244b2e594d15592e5e481c55e +Author: Damien Miller +Date: Mon Dec 22 16:30:42 2014 +1100 + + include and use OpenBSD netcat in regress/ + +commit 8f6784f0cb56dc4fd00af3e81a10050a5785228d +Author: djm@openbsd.org +Date: Mon Dec 22 09:05:17 2014 +0000 + + upstream commit + + mention ssh -Q feature to list supported { MAC, cipher, + KEX, key } algorithms in more places and include the query string used to + list the relevant information; bz#2288 + +commit 449e11b4d7847079bd0a2daa6e3e7ea03d8ef700 +Author: jmc@openbsd.org +Date: Mon Dec 22 08:24:17 2014 +0000 + + upstream commit + + tweak previous; + +commit 4bea0ab3290c0b9dd2aa199e932de8e7e18062d6 +Author: djm@openbsd.org +Date: Mon Dec 22 08:06:03 2014 +0000 + + upstream commit + + regression test for multiple required pubkey authentication; + ok markus@ + +commit f1c4d8ec52158b6f57834b8cd839605b0a33e7f2 +Author: djm@openbsd.org +Date: Mon Dec 22 08:04:23 2014 +0000 + + upstream commit + + correct description of what will happen when a + AuthorizedKeysCommand is specified but AuthorizedKeysCommandUser is not (sshd + will refuse to start) + +commit 161cf419f412446635013ac49e8c660cadc36080 +Author: djm@openbsd.org +Date: Mon Dec 22 07:55:51 2014 +0000 + + upstream commit + + make internal handling of filename arguments of "none" + more consistent with ssh. "none" arguments are now replaced with NULL when + the configuration is finalised. + + Simplifies checking later on (just need to test not-NULL rather than + that + strcmp) and cleans up some inconsistencies. ok markus@ + +commit f69b69b8625be447b8826b21d87713874dac25a6 +Author: djm@openbsd.org +Date: Mon Dec 22 07:51:30 2014 +0000 + + upstream commit + + remember which public keys have been used for + authentication and refuse to accept previously-used keys. + + This allows AuthenticationMethods=publickey,publickey to require + that users authenticate using two _different_ pubkeys. + + ok markus@ + +commit 46ac2ed4677968224c4ca825bc98fc68dae183f0 +Author: djm@openbsd.org +Date: Mon Dec 22 07:24:11 2014 +0000 + + upstream commit + + fix passing of wildcard forward bind addresses when + connection multiplexing is in use; patch from Sami Hartikainen via bz#2324; ok dtucker@ - - djm@cvs.openbsd.org 2011/12/04 23:16:12 - [mux.c] - revert: - > revision 1.32 - > date: 2011/12/02 00:41:56; author: djm; state: Exp; lines: +4 -1 - > fix bz#1948: ssh -f doesn't fork for multiplexed connection. - > ok dtucker@ - it interacts badly with ControlPersist - - djm@cvs.openbsd.org 2012/01/07 21:11:36 - [mux.c] - fix double-free in new session handler - NB. Id sync only - - djm@cvs.openbsd.org 2012/05/23 03:28:28 - [dns.c dns.h key.c key.h ssh-keygen.c] - add support for RFC6594 SSHFP DNS records for ECDSA key types. - patch from bugzilla-m67 AT nulld.me in bz#1978; ok + tweak markus@ - (Original authors OndÅ™ej Surý, OndÅ™ej Caletka and Daniel Black) - - djm@cvs.openbsd.org 2012/06/01 00:49:35 - [PROTOCOL.mux] - correct types of port numbers (integers, not strings); bz#2004 from - bert.wesarg AT googlemail.com - - djm@cvs.openbsd.org 2012/06/01 01:01:22 - [mux.c] - fix memory leak when mux socket creation fails; bz#2002 from bert.wesarg - AT googlemail.com - - dtucker@cvs.openbsd.org 2012/06/18 11:43:53 - [jpake.c] - correct sizeof usage. patch from saw at online.de, ok deraadt - - dtucker@cvs.openbsd.org 2012/06/18 11:49:58 - [ssh_config.5] - RSA instead of DSA twice. From Steve.McClellan at radisys com - - dtucker@cvs.openbsd.org 2012/06/18 12:07:07 - [ssh.1 sshd.8] - Remove mention of 'three' key files since there are now four. From - Steve.McClellan at radisys com. - - dtucker@cvs.openbsd.org 2012/06/18 12:17:18 - [ssh.1] - Clarify description of -W. Noted by Steve.McClellan at radisys com, - ok jmc - - markus@cvs.openbsd.org 2012/06/19 18:25:28 - [servconf.c servconf.h sshd_config.5] - sshd_config: extend Match to allow AcceptEnv and {Allow,Deny}{Users,Groups} - this allows 'Match LocalPort 1022' combined with 'AllowUser bauer' - ok djm@ (back in March) - - jmc@cvs.openbsd.org 2012/06/19 21:35:54 - [sshd_config.5] - tweak previous; ok markus - - djm@cvs.openbsd.org 2012/06/20 04:42:58 - [clientloop.c serverloop.c] - initialise accept() backoff timer to avoid EINVAL from select(2) in - rekeying - -20120519 - - (dtucker) [configure.ac] bz#2010: fix non-portable shell construct. Patch - from cjwatson at debian org. - - (dtucker) [configure.ac contrib/Makefile] bz#1996: use AC_PATH_TOOL to find - pkg-config so it does the right thing when cross-compiling. Patch from - cjwatson at debian org. -- (dtucker) OpenBSD CVS Sync - - dtucker@cvs.openbsd.org 2012/05/13 01:42:32 - [servconf.h servconf.c sshd.8 sshd.c auth.c sshd_config.5] - Add "Match LocalAddress" and "Match LocalPort" to sshd and adjust tests - to match. Feedback and ok djm@ markus@. - - dtucker@cvs.openbsd.org 2012/05/19 06:30:30 - [sshd_config.5] - Document PermitOpen none. bz#2001, patch from Loganaden Velvindron - -20120504 - - (dtucker) [configure.ac] Include rather than - to fix building on some plaforms. Fom bowman at math utah edu and - des at des no. - -20120427 - - (dtucker) [regress/addrmatch.sh] skip tests when running on a non-ipv6 - platform rather than exiting early, so that we still clean up and return - success or failure to test-exec.sh - -20120426 - - (djm) [auth-passwd.c] Handle crypt() returning NULL; from Paul Wouters - via Niels - - (djm) [auth-krb5.c] Save errno across calls that might modify it; - ok dtucker@ - -20120423 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2012/04/23 08:18:17 - [channels.c] - fix function proto/source mismatch - -20120422 - - OpenBSD CVS Sync - - djm@cvs.openbsd.org 2012/02/29 11:21:26 - [ssh-keygen.c] - allow conversion of RSA1 keys to public PEM and PKCS8; "nice" markus@ - - guenther@cvs.openbsd.org 2012/03/15 03:10:27 - [session.c] - root should always be excluded from the test for /etc/nologin instead - of having it always enforced even when marked as ignorenologin. This - regressed when the logic was incompletely flipped around in rev 1.251 - ok halex@ millert@ - - djm@cvs.openbsd.org 2012/03/28 07:23:22 - [PROTOCOL.certkeys] - explain certificate extensions/crit split rationale. Mention requirement - that each appear at most once per cert. - - dtucker@cvs.openbsd.org 2012/03/29 23:54:36 - [channels.c channels.h servconf.c] - Add PermitOpen none option based on patch from Loganaden Velvindron - (bz #1949). ok djm@ - - djm@cvs.openbsd.org 2012/04/11 13:16:19 - [channels.c channels.h clientloop.c serverloop.c] - don't spin in accept() when out of fds (ENFILE/ENFILE) - back off for a - while; ok deraadt@ markus@ - - djm@cvs.openbsd.org 2012/04/11 13:17:54 - [auth.c] - Support "none" as an argument for AuthorizedPrincipalsFile to indicate - no file should be read. - - djm@cvs.openbsd.org 2012/04/11 13:26:40 - [sshd.c] - don't spin in accept() when out of fds (ENFILE/ENFILE) - back off for a - while; ok deraadt@ markus@ - - djm@cvs.openbsd.org 2012/04/11 13:34:17 - [ssh-keyscan.1 ssh-keyscan.c] - now that sshd defaults to offering ECDSA keys, ssh-keyscan should also - look for them by default; bz#1971 - - djm@cvs.openbsd.org 2012/04/12 02:42:32 - [servconf.c servconf.h sshd.c sshd_config sshd_config.5] - VersionAddendum option to allow server operators to append some arbitrary - text to the SSH-... banner; ok deraadt@ "don't care" markus@ - - djm@cvs.openbsd.org 2012/04/12 02:43:55 - [sshd_config sshd_config.5] - mention AuthorizedPrincipalsFile=none default - - djm@cvs.openbsd.org 2012/04/20 03:24:23 - [sftp.c] - setlinebuf(3) is more readable than setvbuf(.., _IOLBF, ...) - - jmc@cvs.openbsd.org 2012/04/20 16:26:22 - [ssh.1] - use "brackets" instead of "braces", for consistency; - -20120420 - - (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec] - [contrib/suse/openssh.spec] Update for release 6.0 - - (djm) [README] Update URL to release notes. - - (djm) Release openssh-6.0 +commit 0d1b241a262e4d0a6bbfdd595489ab1b853c43a1 +Author: djm@openbsd.org +Date: Mon Dec 22 06:14:29 2014 +0000 + + upstream commit + + make this slightly easier to diff against portable + +commit 0715bcdddbf68953964058f17255bf54734b8737 +Author: Damien Miller +Date: Mon Dec 22 13:47:07 2014 +1100 + + add missing regress output file + +commit 1e30483c8ad2c2f39445d4a4b6ab20c241e40593 +Author: djm@openbsd.org +Date: Mon Dec 22 02:15:52 2014 +0000 + + upstream commit + + adjust for new SHA256 key fingerprints and + slightly-different MD5 hex fingerprint format + +commit 6b40567ed722df98593ad8e6a2d2448fc2b4b151 +Author: djm@openbsd.org +Date: Mon Dec 22 01:14:49 2014 +0000 + + upstream commit + + poll changes to netcat (usr.bin/netcat.c r1.125) broke + this test; fix it by ensuring more stdio fds are sent to devnull + +commit a5375ccb970f49dddf7d0ef63c9b713ede9e7260 +Author: jmc@openbsd.org +Date: Sun Dec 21 23:35:14 2014 +0000 + + upstream commit + + tweak previous; + +commit b79efde5c3badf5ce4312fe608d8307eade533c5 +Author: djm@openbsd.org +Date: Sun Dec 21 23:12:42 2014 +0000 + + upstream commit + + document FingerprintHash here too + +commit d16bdd8027dd116afa01324bb071a4016cdc1a75 +Author: Damien Miller +Date: Mon Dec 22 10:18:09 2014 +1100 + + missing include for base64 encoding + +commit 56d1c83cdd1ac76f1c6bd41e01e80dad834f3994 +Author: djm@openbsd.org +Date: Sun Dec 21 22:27:55 2014 +0000 + + upstream commit + + Add FingerprintHash option to control algorithm used for + key fingerprints. Default changes from MD5 to SHA256 and format from hex to + base64. + + Feedback and ok naddy@ markus@ + +commit 058f839fe15c51be8b3a844a76ab9a8db550be4f +Author: djm@openbsd.org +Date: Thu Dec 18 23:58:04 2014 +0000 + + upstream commit + + don't count partial authentication success as a failure + against MaxAuthTries; ok deraadt@ + +commit c7219f4f54d64d6dde66dbcf7a2699daa782d2a1 +Author: djm@openbsd.org +Date: Fri Dec 12 00:02:17 2014 +0000 + + upstream commit + + revert chunk I didn't mean to commit yet; via jmc@ + +commit 7de5991aa3997e2981440f39c1ea01273a0a2c7b +Author: Damien Miller +Date: Thu Dec 18 11:44:06 2014 +1100 + + upstream libc change + + revision 1.2 + date: 2014/12/08 03:45:00; author: bcook; state: Exp; lines: +2 -2; commitid: 7zWEBgJJOCZ2hvTV; + avoid left shift overflow in reallocarray. + + Some 64-bit platforms (e.g. Windows 64) have a 32-bit long. So, shifting + 1UL 32-bits to the left causes an overflow. This replaces the constant 1UL with + (size_t)1 so that we get the correct constant size for the platform. + + discussed with tedu@ & deraadt@ + +commit 2048f85a5e6da8bc6e0532efe02ecfd4e63c978c +Author: Damien Miller +Date: Thu Dec 18 10:15:49 2014 +1100 + + include CFLAGS in gnome askpass targets + + from Fedora + +commit 48b68ce19ca42fa488960028048dec023f7899bb +Author: djm@openbsd.org +Date: Thu Dec 11 08:20:09 2014 +0000 + + upstream commit + + explicitly include sys/param.h in files that use the + howmany() macro; from portable + +commit d663bea30a294d440fef4398e5cd816317bd4518 +Author: djm@openbsd.org +Date: Thu Dec 11 05:25:06 2014 +0000 + + upstream commit + + mention AuthorizedKeysCommandUser must be set for + AuthorizedKeysCommand to be run; bz#2287 + +commit 17bf3d81e00f2abb414a4fd271118cf4913f049f +Author: djm@openbsd.org +Date: Thu Dec 11 05:13:28 2014 +0000 + + upstream commit + + show in debug output which hostkeys are being tried when + attempting hostbased auth; patch from Iain Morgan + +commit da0277e3717eadf5b15e03379fc29db133487e94 +Author: djm@openbsd.org +Date: Thu Dec 11 04:16:14 2014 +0000 + + upstream commit + + Make manual reflect reality: sftp-server's -d option + accepts a "%d" option, not a "%h" one. + + bz#2316; reported by Kirk Wolf + +commit 4cf87f4b81fa9380bce5fcff7b0f8382ae3ad996 +Author: djm@openbsd.org +Date: Wed Dec 10 01:24:09 2014 +0000 + + upstream commit + + better error value for invalid signature length + +commit 4bfad14ca56f8ae04f418997816b4ba84e2cfc3c +Author: Darren Tucker +Date: Wed Dec 10 02:12:51 2014 +1100 + + Resync more with OpenBSD's rijndael.c, in particular "#if 0"-ing out some + unused code. Should fix compile error reported by plautrba at redhat. + +commit 642652d280499691c8212ec6b79724b50008ce09 +Author: Darren Tucker +Date: Wed Dec 10 01:32:23 2014 +1100 + + Add reallocarray to compat library + +commit 3dfd8d93dfcc69261f5af99df56f3ff598581979 +Author: djm@openbsd.org +Date: Thu Dec 4 22:31:50 2014 +0000 + + upstream commit + + add tests for new client RevokedHostKeys option; refactor + to make it a bit more readable + +commit a31046cad1aed16a0b55171192faa6d02665ccec +Author: krw@openbsd.org +Date: Wed Nov 19 13:35:37 2014 +0000 + + upstream commit + + Nuke yet more obvious #include duplications. + + ok deraadt@ + +commit a7c762e5b2c1093542c0bc1df25ccec0b4cf479f +Author: djm@openbsd.org +Date: Thu Dec 4 20:47:36 2014 +0000 + + upstream commit + + key_in_file() wrapper is no longer used + +commit 5e39a49930d885aac9c76af3129332b6e772cd75 +Author: djm@openbsd.org +Date: Thu Dec 4 02:24:32 2014 +0000 + + upstream commit + + add RevokedHostKeys option for the client + + Allow textfile or KRL-based revocation of hostkeys. + +commit 74de254bb92c684cf53461da97f52d5ba34ded80 +Author: djm@openbsd.org +Date: Thu Dec 4 01:49:59 2014 +0000 + + upstream commit + + convert KRL code to new buffer API + + ok markus@ + +commit db995f2eed5fc432598626fa3e30654503bf7151 +Author: millert@openbsd.org +Date: Wed Nov 26 18:34:51 2014 +0000 + + upstream commit + + Prefer setvbuf() to setlinebuf() for portability; ok + deraadt@ + +commit 72bba3d179ced8b425272efe6956a309202a91f3 +Author: jsg@openbsd.org +Date: Mon Nov 24 03:39:22 2014 +0000 + + upstream commit + + Fix crashes in the handling of the sshd config file found + with the afl fuzzer. + + ok deraadt@ djm@ + +commit 867f49c666adcfe92bf539d9c37c1accdea08bf6 +Author: Damien Miller +Date: Wed Nov 26 13:22:41 2014 +1100 + + Avoid Cygwin ssh-host-config reading /etc/group + + Patch from Corinna Vinschen + +commit 8b66f36291a721b1ba7c44f24a07fdf39235593e +Author: Damien Miller +Date: Wed Nov 26 13:20:35 2014 +1100 + + allow custom service name for sshd on Cygwin + + Permits the use of multiple sshd running with different service names. + + Patch by Florian Friesdorf via Corinna Vinschen + +commit 08c0eebf55d70a9ae1964399e609288ae3186a0c +Author: jmc@openbsd.org +Date: Sat Nov 22 19:21:03 2014 +0000 + + upstream commit + + restore word zapped in previous, and remove some useless + "No" macros; + +commit a1418a0033fba43f061513e992e1cbcc3343e563 +Author: deraadt@openbsd.org +Date: Sat Nov 22 18:15:41 2014 +0000 + + upstream commit + + /dev/random has created the same effect as /dev/arandom + (and /dev/urandom) for quite some time. Mop up the last few, by using + /dev/random where we actually want it, or not even mentioning arandom where + it is irrelevant. + +commit b6de5ac9ed421362f479d1ad4fa433d2e25dad5b +Author: djm@openbsd.org +Date: Fri Nov 21 01:00:38 2014 +0000 + + upstream commit + + fix NULL pointer dereference crash on invalid timestamp + + found using Michal Zalewski's afl fuzzer + +commit a1f8110cd5ed818d59b3a2964fab7de76e92c18e +Author: mikeb@openbsd.org +Date: Tue Nov 18 22:38:48 2014 +0000 + + upstream commit + + Sync AES code to the one shipped in OpenSSL/LibreSSL. + + This includes a commit made by Andy Polyakov + to the OpenSSL source tree on Wed, 28 Jun 2006 with the following + message: "Mitigate cache-collision timing attack on last round." + + OK naddy, miod, djm + +commit 335c83d5f35d8620e16b8aa26592d4f836e09ad2 +Author: krw@openbsd.org +Date: Tue Nov 18 20:54:28 2014 +0000 + + upstream commit + + Nuke more obvious #include duplications. + + ok deraadt@ millert@ tedu@ + +commit 51b64e44121194ae4bf153dee391228dada2abcb +Author: djm@openbsd.org +Date: Mon Nov 17 00:21:40 2014 +0000 + + upstream commit + + fix KRL generation when multiple CAs are in use + + We would generate an invalid KRL when revoking certs by serial + number for multiple CA keys due to a section being written out + twice. + + Also extend the regress test to catch this case by having it + produce a multi-CA KRL. + + Reported by peter AT pean.org + +commit d2d51003a623e21fb2b25567c4878d915e90aa2a +Author: djm@openbsd.org +Date: Tue Nov 18 01:02:25 2014 +0000 + + upstream commit + + fix NULL pointer dereference crash in key loading + + found by Michal Zalewski's AFL fuzzer + +commit 9f9fad0191028edc43d100d0ded39419b6895fdf +Author: djm@openbsd.org +Date: Mon Nov 17 00:21:40 2014 +0000 + + upstream commit + + fix KRL generation when multiple CAs are in use + + We would generate an invalid KRL when revoking certs by serial + number for multiple CA keys due to a section being written out + twice. + + Also extend the regress test to catch this case by having it + produce a multi-CA KRL. + + Reported by peter AT pean.org + +commit da8af83d3f7ec00099963e455010e0ed1d7d0140 +Author: bentley@openbsd.org +Date: Sat Nov 15 14:41:03 2014 +0000 + + upstream commit + + Reduce instances of `` '' in manuals. + + troff displays these as typographic quotes, but nroff implementations + almost always print them literally, which rarely has the intended effect + with modern fonts, even in stock xterm. + + These uses of `` '' can be replaced either with more semantic alternatives + or with Dq, which prints typographic quotes in a UTF-8 locale (but will + automatically fall back to `` '' in an ASCII locale). + + improvements and ok schwarze@ + +commit fc302561369483bb755b17f671f70fb894aec01d +Author: djm@openbsd.org +Date: Mon Nov 10 22:25:49 2014 +0000 + + upstream commit + + mux-related manual tweaks + + mention ControlPersist=0 is the same as ControlPersist=yes + + recommend that ControlPath sockets be placed in a og-w directory + +commit 0e4cff5f35ed11102fe3783779960ef07e0cd381 +Author: Damien Miller +Date: Wed Nov 5 11:01:31 2014 +1100 + + Prepare scripts for next Cygwin release + + Makes the Cygwin-specific ssh-user-config script independent of the + existence of /etc/passwd. The next Cygwin release will allow to + generate passwd and group entries from the Windows account DBs, so the + scripts have to adapt. + + from Corinna Vinschen + +commit 7d0ba5336651731949762eb8877ce9e3b52df436 +Author: Damien Miller +Date: Thu Oct 30 10:45:41 2014 +1100 + + include version number in OpenSSL-too-old error + +commit 3bcb92e04d9207e9f78d82f7918c6d3422054ce9 +Author: lteo@openbsd.org +Date: Fri Oct 24 02:01:20 2014 +0000 + + upstream commit + + Remove unnecessary include: netinet/in_systm.h is not needed + by these programs. + + NB. skipped for portable + + ok deraadt@ millert@ + +commit 6fdcaeb99532e28a69f1a1599fbd540bb15b70a0 +Author: djm@openbsd.org +Date: Mon Oct 20 03:43:01 2014 +0000 + + upstream commit + + whitespace + +commit 165bc8786299e261706ed60342985f9de93a7461 +Author: daniel@openbsd.org +Date: Tue Oct 14 03:09:59 2014 +0000 + + upstream commit + + plug a memory leak; from Maxime Villard. + + ok djm@ + +commit b1ba15f3885947c245c2dbfaad0a04ba050abea0 +Author: jmc@openbsd.org +Date: Thu Oct 9 06:21:31 2014 +0000 + + upstream commit + + tweak previous; + +commit 259a02ebdf74ad90b41d116ecf70aa823fa4c6e7 +Author: djm@openbsd.org +Date: Mon Oct 13 00:38:35 2014 +0000 + + upstream commit + + whitespace + +commit 957fbceb0f3166e41b76fdb54075ab3b9cc84cba +Author: djm@openbsd.org +Date: Wed Oct 8 22:20:25 2014 +0000 + + upstream commit + + Tweak config reparsing with host canonicalisation + + Make the second pass through the config files always run when + hostname canonicalisation is enabled. + + Add a "Match canonical" criteria that allows ssh_config Match + blocks to trigger only in the second config pass. + + Add a -G option to ssh that causes it to parse its configuration + and dump the result to stdout, similar to "sshd -T" + + Allow ssh_config Port options set in the second config parse + phase to be applied (they were being ignored). + + bz#2267 bz#2286; ok markus + +commit 5c0dafd38bf66feeeb45fa0741a5baf5ad8039ba +Author: djm@openbsd.org +Date: Wed Oct 8 22:15:27 2014 +0000 + + upstream commit + + another -Wpointer-sign from clang + +commit bb005dc815ebda9af3ae4b39ca101c4da918f835 +Author: djm@openbsd.org +Date: Wed Oct 8 22:15:06 2014 +0000 + + upstream commit + + fix a few -Wpointer-sign warnings from clang + +commit 3cc1fbb4fb0e804bfb873fd363cea91b27fc8188 +Author: djm@openbsd.org +Date: Wed Oct 8 21:45:48 2014 +0000 + + upstream commit + + parse cert sections using nested buffers to reduce + copies; ok markus + +commit 4a45922aebf99164e2fc83d34fe55b11ae1866ef +Author: djm@openbsd.org +Date: Mon Oct 6 00:47:15 2014 +0000 + + upstream commit + + correct options in usage(); from mancha1 AT zoho.com + +commit 48dffd5bebae6fed0556dc5c36cece0370690618 +Author: djm@openbsd.org +Date: Tue Sep 9 09:45:36 2014 +0000 + + upstream commit + + mention permissions on tun(4) devices in PermitTunnel + documentation; bz#2273 + +commit a5883d4eccb94b16c355987f58f86a7dee17a0c2 +Author: djm@openbsd.org +Date: Wed Sep 3 18:55:07 2014 +0000 + + upstream commit + + tighten permissions on pty when the "tty" group does + not exist; pointed out by Corinna Vinschen; ok markus + +commit 180bcb406b58bf30723c01a6b010e48ee626dda8 +Author: sobrado@openbsd.org +Date: Sat Aug 30 16:32:25 2014 +0000 + + upstream commit + + typo. + +commit f70b22bcdd52f6bf127047b3584371e6e5d45627 +Author: sobrado@openbsd.org +Date: Sat Aug 30 15:33:50 2014 +0000 + + upstream commit + + improve capitalization for the Ed25519 public-key + signature system. + + ok djm@ + +commit 7df8818409c752cf3f0c3f8044fe9aebed8647bd +Author: doug@openbsd.org +Date: Thu Aug 21 01:08:52 2014 +0000 + + upstream commit + + Free resources on error in mkstemp and fdopen + + ok djm@ + +commit 40ba4c9733aaed08304714faeb61529f18da144b +Author: deraadt@openbsd.org +Date: Wed Aug 20 01:28:55 2014 +0000 + + upstream commit + + djm how did you make a typo like that... + +commit 57d378ec9278ba417a726f615daad67d157de666 +Author: djm@openbsd.org +Date: Tue Aug 19 23:58:28 2014 +0000 + + upstream commit + + When dumping the server configuration (sshd -T), print + correct KEX, MAC and cipher defaults. Spotted by Iain Morgan + +commit 7ff880ede5195d0b17e7f1e3b6cfbc4cb6f85240 +Author: djm@openbsd.org +Date: Tue Aug 19 23:57:18 2014 +0000 + + upstream commit + + ~-expand lcd paths + +commit 4460a7ad0c78d4cd67c467f6e9f4254d0404ed59 +Author: Damien Miller +Date: Sun Oct 12 12:35:48 2014 +1100 + + remove duplicated KEX_DH1 entry + +commit c9b8426a616138d0d762176c94f51aff3faad5ff +Author: Damien Miller +Date: Thu Oct 9 10:34:06 2014 +1100 + + remove ChangeLog file + + Commit logs will be generated from git at release time. + +commit 81d18ff7c93a04affbf3903e0963859763219aed +Author: Damien Miller +Date: Tue Oct 7 21:24:25 2014 +1100 + + delete contrib/caldera directory + +commit 0ec9e87d3638206456968202f05bb5123670607a +Author: Damien Miller +Date: Tue Oct 7 19:57:27 2014 +1100 + + test commit + +commit 8fb65a44568701b779f3d77326bceae63412d28d +Author: Damien Miller +Date: Tue Oct 7 09:21:49 2014 +1100 + + - (djm) Release OpenSSH-6.7 + +commit e8c9f2602c46f6781df5e52e6cd8413dab4602a3 +Author: Damien Miller +Date: Fri Oct 3 09:24:56 2014 +1000 + + - (djm) [sshd_config.5] typo; from Iain Morgan + +commit 703b98a26706f5083801d11059486d77491342ae +Author: Damien Miller +Date: Wed Oct 1 09:43:07 2014 +1000 + + - (djm) [openbsd-compat/Makefile.in openbsd-compat/kludge-fd_set.c] + [openbsd-compat/openbsd-compat.h] Kludge around bad glibc + _FORTIFY_SOURCE check that doesn't grok heap-allocated fd_sets; + ok dtucker@ + +commit 0fa0ed061bbfedb0daa705e220748154a84c3413 +Author: Damien Miller +Date: Wed Sep 10 08:15:34 2014 +1000 + + - (djm) [sandbox-seccomp-filter.c] Allow mremap and exit for DietLibc; + patch from Felix von Leitner; ok dtucker + +commit ad7d23d461c3b7e1dcb15db13aee5f4b94dc1a95 +Author: Darren Tucker +Date: Tue Sep 9 12:23:10 2014 +1000 + + 20140908 + - (dtucker) [INSTALL] Update info about egd. ok djm@ + +commit 2a8699f37cc2515e3bc60e0c677ba060f4d48191 +Author: Damien Miller +Date: Thu Sep 4 03:46:05 2014 +1000 + + - (djm) [openbsd-compat/arc4random.c] Zero seed after keying PRNG + +commit 44988defb1f5e3afe576d86000365e1f07a1b494 +Author: Damien Miller +Date: Wed Sep 3 05:35:32 2014 +1000 + + - (djm) [contrib/cygwin/ssh-host-config] Fix old code leading to + permissions/ACLs; from Corinna Vinschen + +commit 23f269562b7537b2f6f5014e50a25e5dcc55a837 +Author: Damien Miller +Date: Wed Sep 3 05:33:25 2014 +1000 + + - (djm) [defines.h sshbuf.c] Move __predict_true|false to defines.h and + conditionalise to avoid duplicate definition. + +commit 41c8de2c0031cf59e7cf0c06b5bcfbf4852c1fda +Author: Damien Miller +Date: Sat Aug 30 16:23:06 2014 +1000 + + - (djm) [Makefile.in] Make TEST_SHELL a variable; "good idea" tim@ + +commit d7c81e216a7bd9eed6e239c970d9261bb1651947 +Author: Damien Miller +Date: Sat Aug 30 04:18:28 2014 +1000 + + - (djm) [openbsd-compat/openssl-compat.h] add include guard + +commit 4687802dda57365b984b897fc3c8e2867ea09b22 +Author: Damien Miller +Date: Sat Aug 30 03:29:19 2014 +1000 + + - (djm) [misc.c] Missing newline between functions + +commit 51c77e29220dee87c53be2dc47092934acab26fe +Author: Damien Miller +Date: Sat Aug 30 02:30:30 2014 +1000 + + - (djm) [openbsd-compat/openssl-compat.h] add + OPENSSL_[RD]SA_MAX_MODULUS_BITS defines for OpenSSL that lacks them + +commit 3d673d103bad35afaec6e7ef73e5277216ce33a3 +Author: Damien Miller +Date: Wed Aug 27 06:32:01 2014 +1000 + + - (djm) [openbsd-compat/explicit_bzero.c] implement explicit_bzero() + using memset_s() where possible; improve fallback to indirect bzero + via a volatile pointer to give it more of a chance to avoid being + optimised away. + +commit 146218ac11a1eb0dcade6f793d7acdef163b5ddc +Author: Damien Miller +Date: Wed Aug 27 04:11:55 2014 +1000 + + - (djm) [monitor.c sshd.c] SIGXFSZ needs to be ignored in postauth + monitor, not preauth; bz#2263 + +commit 1b215c098b3b37e38aa4e4c91bb908eee41183b1 +Author: Damien Miller +Date: Wed Aug 27 04:04:40 2014 +1000 + + - (djm) [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c] + [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] + [regress/unittests/sshkey/common.c] + [regress/unittests/sshkey/test_file.c] + [regress/unittests/sshkey/test_fuzz.c] + [regress/unittests/sshkey/test_sshkey.c] Don't include openssl/ec.h + on !ECC OpenSSL systems + +commit ad013944af0a19e3f612089d0099bb397cf6502d +Author: Damien Miller +Date: Tue Aug 26 09:27:28 2014 +1000 + + - (djm) [INSTALL] Recommend libcrypto be built -fPIC, mention LibreSSL, + update OpenSSL version requirement. + +commit ed126de8ee04c66640a0ea2697c4aaf36801f100 +Author: Damien Miller +Date: Tue Aug 26 08:37:47 2014 +1000 + + - (djm) [bufec.c] Skip this file on !ECC OpenSSL + +commit 9c1dede005746864a4fdb36a7cdf6c51296ca909 +Author: Damien Miller +Date: Sun Aug 24 03:01:06 2014 +1000 + + - (djm) [sftp-server.c] Some systems (e.g. Irix) have prctl() but not + PR_SET_DUMPABLE, so adjust ifdef; reported by Tom Christensen + +commit d244a5816fd1312a33404b436e4dd83594f1119e +Author: Damien Miller +Date: Sat Aug 23 17:06:49 2014 +1000 + + - (djm) [configure.ac] We now require a working vsnprintf everywhere (not + just for systems that lack asprintf); check for it always and extend + test to catch more brokenness. Fixes builds on Solaris <= 9 + +commit 4cec036362a358e398e6a2e6d19d8e5780558634 +Author: Damien Miller +Date: Sat Aug 23 03:11:09 2014 +1000 + + - (djm) [sshd.c] Ignore SIGXFSZ in preauth monitor child; can explode on + lastlog writing on platforms with high UIDs; bz#2263 + +commit 394a60f2598d28b670d934b93942a3370b779b39 +Author: Damien Miller +Date: Fri Aug 22 18:06:20 2014 +1000 + + - (djm) [configure.ac] double braces to appease autoconf + +commit 4d69aeabd6e60afcdc7cca177ca751708ab79a9d +Author: Damien Miller +Date: Fri Aug 22 17:48:27 2014 +1000 + + - (djm) [openbsd-compat/bsd-snprintf.c] Fix compilation failure (prototype/ + definition mismatch) and warning for broken/missing snprintf case. + +commit 0c11f1ac369d2c0aeb0ab0458a7cd04c72fe5e9e +Author: Damien Miller +Date: Fri Aug 22 17:36:56 2014 +1000 + + - (djm) [sshbuf-getput-crypto.c] Fix compilation when OpenSSL lacks ECC + +commit 6d62784b8973340b251fea6b04890f471adf28db +Author: Damien Miller +Date: Fri Aug 22 17:36:19 2014 +1000 + + - (djm) [configure.ac] include leading zero characters in OpenSSL version + number; fixes test for unsupported versions + +commit 4f1ff1ed782117f5d5204d4e91156ed5da07cbb7 +Author: Damien Miller +Date: Thu Aug 21 15:54:50 2014 +1000 + + - (djm) [regress/unittests/test_helper/test_helper.c] Fix for systems that + don't set __progname. Diagnosed by Tom Christensen. + +commit 005a64da0f457410045ef0bfa93c863c2450447d +Author: Damien Miller +Date: Thu Aug 21 10:48:41 2014 +1000 + + - (djm) [key.h] Fix ifdefs for no-ECC OpenSSL + +commit aa6598ebb3343c7380e918388e10e8ca5852b613 +Author: Damien Miller +Date: Thu Aug 21 10:47:54 2014 +1000 + + - (djm) [Makefile.in] fix reference to libtest_helper.a in sshkey test too. + +commit 54703e3cf63f0c80d4157e5ad7dbc2b363ee2c56 +Author: Damien Miller +Date: Wed Aug 20 11:10:51 2014 +1000 + + - (djm) [contrib/cygwin/README] Correct build instructions; from Corinna + +commit f0935698f0461f24d8d1f1107b476ee5fd4db1cb +Author: Damien Miller +Date: Wed Aug 20 11:06:50 2014 +1000 + + - (djm) [sshkey.h] Fix compilation when OpenSSL lacks ECC + +commit c5089ecaec3b2c02f014f4e67518390702a4ba14 +Author: Damien Miller +Date: Wed Aug 20 11:06:20 2014 +1000 + + - (djm) [Makefile.in] refer to libtest_helper.a by explicit path rather than + -L/-l; fixes linking problems on some platforms + +commit 2195847e503a382f83ee969b0a8bd3dfe0e55c18 +Author: Damien Miller +Date: Wed Aug 20 11:05:03 2014 +1000 + + - (djm) [configure.ac] Check OpenSSL version is supported at configure time; + suggested by Kevin Brott + +commit a75aca1bbc989aa9f8b1b08489d37855f3d24d1a +Author: Damien Miller +Date: Tue Aug 19 11:36:07 2014 +1000 + + - (djm) [INSTALL contrib/caldera/openssh.spec contrib/cygwin/README] + [contrib/redhat/openssh.spec contrib/suse/openssh.spec] Remove mentions + of TCP wrappers. + +commit 3f022b5a9477abceeb1bbeab04b055f3cc7ca8f6 +Author: Damien Miller +Date: Tue Aug 19 11:32:34 2014 +1000 + + - (djm) [ssh-dss.c] Include openssl/dsa.h for DSA_SIG + +commit 88137902632aceb923990e98cf5dc923bb3ef2f5 +Author: Damien Miller +Date: Tue Aug 19 11:28:11 2014 +1000 + + - (djm) [sshbuf.h] Fix compilation on systems without OPENSSL_HAS_ECC. + +commit 2f3d1e7fb2eabd3cfbfd8d0f7bdd2f9a1888690b +Author: Damien Miller +Date: Tue Aug 19 11:14:36 2014 +1000 + + - (djm) [myproposal.h] Make curve25519 KEX dependent on + HAVE_EVP_SHA256 instead of OPENSSL_HAS_ECC. + +commit d4e7d59d01a6c7f59e8c1f94a83c086e9a33d8aa +Author: Damien Miller +Date: Tue Aug 19 11:14:17 2014 +1000 + + - (djm) [serverloop.c] Fix syntax error on Cygwin; from Corinna Vinschen + +commit 9eaeea2cf2b6af5f166cfa9ad3c7a90711a147a9 +Author: Damien Miller +Date: Sun Aug 10 11:35:05 2014 +1000 + + - (djm) [README contrib/caldera/openssh.spec] + [contrib/redhat/openssh.spec contrib/suse/openssh.spec] Update versions + +commit f8988fbef0c9801d19fa2f8f4f041690412bec37 +Author: Damien Miller +Date: Fri Aug 1 13:31:52 2014 +1000 + + - (djm) [regress/multiplex.sh] Use -d (detach stdin) flag to disassociate + nc from stdin, it's more portable + +commit 5b3879fd4b7a4e3d43bab8f40addda39bc1169d0 +Author: Damien Miller +Date: Fri Aug 1 12:28:31 2014 +1000 + + - (djm) [regress/multiplex.sh] Instruct nc not to quit as soon as stdin + is closed; avoid regress failures when stdin is /dev/null + +commit a9c46746d266f8a1b092a72b2150682d1af8ebfc +Author: Damien Miller +Date: Fri Aug 1 12:26:49 2014 +1000 + + - (djm) [regress/multiplex.sh] Skip test for non-OpenBSD netcat. We need + a better solution, but this will have to do for now. + +commit 426117b2e965e43f47015942b5be8dd88fe74b88 +Author: Damien Miller +Date: Wed Jul 30 12:33:20 2014 +1000 + + - schwarze@cvs.openbsd.org 2014/07/28 15:40:08 + [sftp-server.8 sshd_config.5] + some systems no longer need /dev/log; + issue noticed by jirib; + ok deraadt + +commit f497794b6962eaf802ab4ac2a7b22ae591cca1d5 +Author: Damien Miller +Date: Wed Jul 30 12:32:46 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/07/25 21:22:03 + [ssh-agent.c] + Clear buffer used for handling messages. This prevents keys being + left in memory after they have been expired or deleted in some cases + (but note that ssh-agent is setgid so you would still need root to + access them). Pointed out by Kevin Burns, ok deraadt + +commit a8a0f65c57c8ecba94d65948e9090da54014dfef +Author: Damien Miller +Date: Wed Jul 30 12:32:28 2014 +1000 + + - OpenBSD CVS Sync + - millert@cvs.openbsd.org 2014/07/24 22:57:10 + [ssh.1] + Mention UNIX-domain socket forwarding too. OK jmc@ deraadt@ + +commit 56b840f2b81e14a2f95c203403633a72566736f8 +Author: Damien Miller +Date: Fri Jul 25 08:11:30 2014 +1000 + + - (djm) [regress/multiplex.sh] restore incorrectly deleted line; + pointed out by Christian Hesse + +commit dd417b60d5ca220565d1014e92b7f8f43dc081eb +Author: Darren Tucker +Date: Wed Jul 23 10:41:21 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/07/22 23:35:38 + [regress/unittests/sshkey/testdata/*] + Regenerate test keys with certs signed with ed25519 instead of ecdsa. + These can be used in -portable on platforms that don't support ECDSA. + +commit 40e50211896369dba8f64f3b5e5fd58b76f5ac3f +Author: Darren Tucker +Date: Wed Jul 23 10:35:45 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/07/22 23:57:40 + [regress/unittests/sshkey/mktestdata.sh] + Add $OpenBSD tag to make syncs easier + +commit 07e644251e809b1d4c062cf85bd1146a7e3f5a8a +Author: Darren Tucker +Date: Wed Jul 23 10:34:26 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/07/22 23:23:22 + [regress/unittests/sshkey/mktestdata.sh] + Sign test certs with ed25519 instead of ecdsa so that they'll work in + -portable on platforms that don't have ECDSA in their OpenSSL. ok djm + +commit cea099a7c4eaecb01b001e5453bb4e5c25006c22 +Author: Darren Tucker +Date: Wed Jul 23 10:04:02 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/22 01:32:12 + [regress/multiplex.sh] + change the test for still-open Unix domain sockets to be robust against + nc implementations that produce error messages. from -portable + (Id sync only) + +commit 31eb78078d349b32ea41952ecc944b3ad6cb0d45 +Author: Darren Tucker +Date: Wed Jul 23 09:43:42 2014 +1000 + + - guenther@cvs.openbsd.org 2014/07/22 07:13:42 + [umac.c] + Convert from to the shiney new + ok dtucker@, who also confirmed that -portable handles this already + (ID sync only, includes.h pulls in endian.h if available.) + +commit 820763efef2d19d965602533036c2b4badc9d465 +Author: Darren Tucker +Date: Wed Jul 23 09:40:46 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/07/22 01:18:50 + [key.c] + Prevent spam from key_load_private_pem during hostbased auth. ok djm@ + +commit c4ee219a66f3190fa96cbd45b4d11015685c6306 +Author: Darren Tucker +Date: Wed Jul 23 04:27:50 2014 +1000 + + - (dtucker) [regress/unittests/sshkey/test_{file,fuzz,sshkey}.c] Wrap ecdsa- + specific tests inside OPENSSL_HAS_ECC. + +commit 04f4824940ea3edd60835416ececbae16438968a +Author: Damien Miller +Date: Tue Jul 22 11:31:47 2014 +1000 + + - (djm) [regress/multiplex.sh] change the test for still-open Unix + domain sockets to be robust against nc implementations that produce + error messages. + +commit 5ea4fe00d55453aaa44007330bb4c3181bd9b796 +Author: Damien Miller +Date: Tue Jul 22 09:39:19 2014 +1000 + + - (djm) [regress/multiplex.sh] ssh mux master lost -N somehow; + put it back + +commit 948a1774a79a85f9deba6d74db95f402dee32c69 +Author: Darren Tucker +Date: Tue Jul 22 01:07:11 2014 +1000 + + - (dtucker) [sshkey.c] ifdef out unused variable when compiling without + OPENSSL_HAS_ECC. + +commit c8f610f6cc57ae129758052439d9baf13699097b +Author: Damien Miller +Date: Mon Jul 21 10:23:27 2014 +1000 + + - (djm) [regress/multiplex.sh] Not all netcat accept the -N option. + +commit 0e4e95566cd95c887f69272499b8f3880b3ec0f5 +Author: Damien Miller +Date: Mon Jul 21 09:52:54 2014 +1000 + + - millert@cvs.openbsd.org 2014/07/15 15:54:15 + [forwarding.sh multiplex.sh] + Add support for Unix domain socket forwarding. A remote TCP port + may be forwarded to a local Unix domain socket and vice versa or + both ends may be a Unix domain socket. This is a reimplementation + of the streamlocal patches by William Ahern from: + http://www.25thandclement.com/~william/projects/streamlocal.html + OK djm@ markus@ + +commit 93a87ab27ecdc709169fb24411133998f81e2761 +Author: Darren Tucker +Date: Mon Jul 21 06:30:25 2014 +1000 + + - (dtucker) [regress/unittests/sshkey/ + {common,test_file,test_fuzz,test_sshkey}.c] Wrap stdint.h includes in + ifdefs. + +commit 5573171352ea23df2dc6d2fe0324d023b7ba697c +Author: Darren Tucker +Date: Mon Jul 21 02:24:59 2014 +1000 + + - (dtucker) [cipher.c openbsd-compat/openssl-compat.h] Restore the bits + needed to build AES CTR mode against OpenSSL 0.9.8f and above. ok djm + +commit 74e28682711d005026c7c8f15f96aea9d3c8b5a3 +Author: Tim Rice +Date: Fri Jul 18 20:00:11 2014 -0700 + + - (tim) [openbsd-compat/port-uw.c] Include misc.h for fwd_opts, used + in servconf.h. + +commit d1a0421f8e5e933fee6fb58ee6b9a22c63c8a613 +Author: Darren Tucker +Date: Sat Jul 19 07:23:55 2014 +1000 + + - (dtucker) [key.c sshkey.c] Put new ecdsa bits inside ifdef OPENSSL_HAS_ECC. + +commit f0fe9ea1be62227c130b317769de3d1e736b6dc1 +Author: Darren Tucker +Date: Sat Jul 19 06:33:12 2014 +1000 + + - (dtucker) [Makefile.in] Add a t-exec target to run just the executable + tests. + +commit 450bc1180d4b061434a4b733c5c8814fa30b022b +Author: Darren Tucker +Date: Sat Jul 19 06:23:18 2014 +1000 + + - (dtucker) [auth2-gss.c gss-serv-krb5.c] Include misc.h for fwd_opts, used + in servconf.h. + +commit ab2ec586baad122ed169285c31927ccf58bc7b28 +Author: Damien Miller +Date: Fri Jul 18 15:04:47 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/18 02:46:01 + [ssh-agent.c] + restore umask around listener socket creation (dropped in streamlocal patch + merge) + +commit 357610d15946381ae90c271837dcdd0cdce7145f +Author: Damien Miller +Date: Fri Jul 18 15:04:10 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/17 07:22:19 + [mux.c ssh.c] + reflect stdio-forward ("ssh -W host:port ...") failures in exit status. + previously we were always returning 0. bz#2255 reported by Brendan + Germain; ok dtucker + +commit dad9a4a0b7c2b5d78605f8df28718f116524134e +Author: Damien Miller +Date: Fri Jul 18 15:03:49 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/17 00:12:03 + [key.c] + silence "incorrect passphrase" error spam; reported and ok dtucker@ + +commit f42f7684ecbeec6ce50e0310f80b3d6da2aaf533 +Author: Damien Miller +Date: Fri Jul 18 15:03:27 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/17 00:10:18 + [mux.c] + preserve errno across syscall + +commit 1b83320628cb0733e3688b85bfe4d388a7c51909 +Author: Damien Miller +Date: Fri Jul 18 15:03:02 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/17 00:10:56 + [sandbox-systrace.c] + ifdef SYS_sendsyslog so this will compile without patching on -stable + +commit 6d57656331bcd754d912950e4a18ad259d596e61 +Author: Damien Miller +Date: Fri Jul 18 15:02:06 2014 +1000 + + - jmc@cvs.openbsd.org 2014/07/16 14:48:57 + [ssh.1] + add the streamlocal* options to ssh's -o list; millert says they're + irrelevant for scp/sftp; + + ok markus millert + +commit 7acefbbcbeab725420ea07397ae35992f505f702 +Author: Damien Miller +Date: Fri Jul 18 14:11:24 2014 +1000 + + - millert@cvs.openbsd.org 2014/07/15 15:54:14 + [PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c] + [auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c] + [auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h] + [clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c] + [readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c] + [ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c] + [sshd_config.5 sshlogin.c] + Add support for Unix domain socket forwarding. A remote TCP port + may be forwarded to a local Unix domain socket and vice versa or + both ends may be a Unix domain socket. This is a reimplementation + of the streamlocal patches by William Ahern from: + http://www.25thandclement.com/~william/projects/streamlocal.html + OK djm@ markus@ + +commit 6262d760e00714523633bd989d62e273a3dca99a +Author: Damien Miller +Date: Thu Jul 17 09:52:07 2014 +1000 + + - tedu@cvs.openbsd.org 2014/07/11 13:54:34 + [myproposal.h] + by popular demand, add back hamc-sha1 to server proposal for better compat + with many clients still in use. ok deraadt + +commit 9d69d937b46ecba17f16d923e538ceda7b705c7a +Author: Damien Miller +Date: Thu Jul 17 09:49:37 2014 +1000 + + - deraadt@cvs.openbsd.org 2014/07/11 08:09:54 + [sandbox-systrace.c] + Permit use of SYS_sendsyslog from inside the sandbox. Clock is ticking, + update your kernels and sshd soon.. libc will start using sendsyslog() + in about 4 days. + +commit f6293a0b4129826fc2e37e4062f96825df43c326 +Author: Damien Miller +Date: Thu Jul 17 09:01:25 2014 +1000 + + - (djm) [digest-openssl.c] Preserve array order when disabling digests. + Reported by Petr Lautrbach. + +commit 00f9cd230709c04399ef5ff80492d70a55230694 +Author: Damien Miller +Date: Tue Jul 15 10:41:38 2014 +1000 + + - (djm) [configure.ac] Delay checks for arc4random* until after libcrypto + has been located; fixes builds agains libressl-portable + +commit 1d0df3249c87019556b83306c28d4769375c2edc +Author: Damien Miller +Date: Fri Jul 11 09:19:04 2014 +1000 + + - OpenBSD CVS Sync + - benno@cvs.openbsd.org 2014/07/09 14:15:56 + [ssh-add.c] + fix ssh-add crash while loading more than one key + ok markus@ + +commit 7a57eb3d105aa4ced15fb47001092c58811e6d9d +Author: Damien Miller +Date: Wed Jul 9 13:22:31 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/07 08:15:26 + [multiplex.sh] + remove forced-fatal that I stuck in there to test the new cleanup + logic and forgot to remove... + +commit 612f965239a30fe536b11ece1834d9f470aeb029 +Author: Damien Miller +Date: Wed Jul 9 13:22:03 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/06 07:42:03 + [multiplex.sh test-exec.sh] + add a hook to the cleanup() function to kill $SSH_PID if it is set + + use it to kill the mux master started in multiplex.sh (it was being left + around on fatal failures) + +commit d0bb950485ba121e43a77caf434115ed6417b46f +Author: Damien Miller +Date: Wed Jul 9 13:07:28 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/09 03:02:15 + [key.c] + downgrade more error() to debug() to better match what old authfile.c + did; suppresses spurious errors with hostbased authentication enabled + +commit 0070776a038655c57f57e70cd05e4c38a5de9d84 +Author: Damien Miller +Date: Wed Jul 9 13:07:06 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/09 01:45:10 + [sftp.c] + more useful error message when GLOB_NOSPACE occurs; + bz#2254, patch from Orion Poplawski + +commit 079bac2a43c74ef7cf56850afbab3b1932534c50 +Author: Damien Miller +Date: Wed Jul 9 13:06:25 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/07 08:19:12 + [ssh_config.5] + mention that ProxyCommand is executed using shell "exec" to avoid + a lingering process; bz#1977 + +commit 3a48cc090096cf99b9de592deb5f90e444edebfb +Author: Damien Miller +Date: Sun Jul 6 09:32:49 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/05 23:11:48 + [channels.c] + fix remote-forward cancel regression; ok markus@ + +commit 48bae3a38cb578713e676708164f6e7151cc64fa +Author: Damien Miller +Date: Sun Jul 6 09:27:06 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 23:18:35 + [authfile.h] + remove leakmalloc droppings + +commit 72e6b5c9ed5e72ca3a6ccc3177941b7c487a0826 +Author: Damien Miller +Date: Fri Jul 4 09:00:04 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 22:40:43 + [servconf.c servconf.h session.c sshd.8 sshd_config.5] + Add a sshd_config PermitUserRC option to control whether ~/.ssh/rc is + executed, mirroring the no-user-rc authorized_keys option; + bz#2160; ok markus@ + +commit 602943d1179a08dfa70af94f62296ea5e3d6ebb8 +Author: Damien Miller +Date: Fri Jul 4 08:59:41 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 22:33:41 + [channels.c] + allow explicit ::1 and 127.0.0.1 forwarding bind addresses when + GatewayPorts=no; allows client to choose address family; + bz#2222 ok markus@ + +commit 6b37fbb7921d156b31e2c8f39d9e1b6746c34983 +Author: Damien Miller +Date: Fri Jul 4 08:59:24 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 22:23:46 + [sshconnect.c] + when rekeying, skip file/DNS lookup if it is the same as the key sent + during initial key exchange. bz#2154 patch from Iain Morgan; ok markus@ + +commit d2c3cd5f2e47ee24cf7093ce8e948c2e79dfc3fd +Author: Damien Miller +Date: Fri Jul 4 08:59:01 2014 +1000 + + - jsing@cvs.openbsd.org 2014/07/03 12:42:16 + [cipher-chachapoly.c] + Call chacha_ivsetup() immediately before chacha_encrypt_bytes() - this + makes it easier to verify that chacha_encrypt_bytes() is only called once + per chacha_ivsetup() call. + ok djm@ + +commit 686feb560ec43a06ba04da82b50f3c183c947309 +Author: Damien Miller +Date: Thu Jul 3 21:29:38 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 11:16:55 + [auth.c auth.h auth1.c auth2.c] + make the "Too many authentication failures" message include the + user, source address, port and protocol in a format similar to the + authentication success / failure messages; bz#2199, ok dtucker + +commit 0f12341402e18fd9996ec23189b9418d2722453f +Author: Damien Miller +Date: Thu Jul 3 21:28:09 2014 +1000 + + - jmc@cvs.openbsd.org 2014/07/03 07:45:27 + [ssh_config.5] + escape %C since groff thinks it part of an Rs/Re block; + +commit 9c38643c5cd47a19db2cc28279dcc28abadc22b3 +Author: Damien Miller +Date: Thu Jul 3 21:27:46 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 06:39:19 + [ssh.c ssh_config.5] + Add a %C escape sequence for LocalCommand and ControlPath that expands + to a unique identifer based on a has of the tuple of (local host, + remote user, hostname, port). + + Helps avoid exceeding sockaddr_un's miserly pathname limits for mux + control paths. + + bz#2220, based on patch from mancha1 AT zoho.com; ok markus@ + +commit 49d9bfe2b2f3e90cc158a215dffa7675e57e7830 +Author: Damien Miller +Date: Thu Jul 3 21:26:42 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 05:38:17 + [ssh.1] + document that -g will only work in the multiplexed case if applied to + the mux master + +commit ef9f13ba4c58057b2166d1f2e790535da402fbe5 +Author: Damien Miller +Date: Thu Jul 3 21:26:21 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 05:32:36 + [ssh_config.5] + mention '%%' escape sequence in HostName directives and how it may + be used to specify IPv6 link-local addresses + +commit e6a407789e5432dd2e53336fb73476cc69048c54 +Author: Damien Miller +Date: Thu Jul 3 21:25:03 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 04:36:45 + [digest.h] + forward-declare struct sshbuf so consumers don't need to include sshbuf.h + +commit 4a1d3d50f02d0a8a4ef95ea4749293cbfb89f919 +Author: Damien Miller +Date: Thu Jul 3 21:24:40 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 03:47:27 + [ssh-keygen.c] + When hashing or removing hosts using ssh-keygen, don't choke on + @revoked markers and don't remove @cert-authority markers; + bz#2241, reported by mlindgren AT runelind.net + +commit e5c0d52ceb575c3db8c313e0b1aa3845943d7ba8 +Author: Damien Miller +Date: Thu Jul 3 21:24:19 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 03:34:09 + [gss-serv.c session.c ssh-keygen.c] + standardise on NI_MAXHOST for gethostname() string lengths; about + 1/2 the cases were using it already. Fixes bz#2239 en passant + +commit c174a3b7c14e0d178c61219de2aa1110e209950c +Author: Damien Miller +Date: Thu Jul 3 21:23:24 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 03:26:43 + [digest-openssl.c] + use EVP_Digest() for one-shot hash instead of creating, updating, + finalising and destroying a context. + bz#2231, based on patch from Timo Teras + +commit d7ca2cd31ecc4d63a055e2dcc4bf35c13f2db4c5 +Author: Damien Miller +Date: Thu Jul 3 21:23:01 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 03:15:01 + [ssh-add.c] + make stdout line-buffered; saves partial output getting lost when + ssh-add fatal()s part-way through (e.g. when listing keys from an + agent that supports key types that ssh-add doesn't); + bz#2234, reported by Phil Pennock + +commit b1e967c8d7c7578dd0c172d85b3046cf54ea42ba +Author: Damien Miller +Date: Thu Jul 3 21:22:40 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 03:11:03 + [ssh-agent.c] + Only cleanup agent socket in the main agent process and not in any + subprocesses it may have started (e.g. forked askpass). Fixes + agent sockets being zapped when askpass processes fatal(); + bz#2236 patch from Dmitry V. Levin + +commit 61e28e55c3438d796b02ef878bcd28620d452670 +Author: Damien Miller +Date: Thu Jul 3 21:22:22 2014 +1000 + + - djm@cvs.openbsd.org 2014/07/03 01:45:38 + [sshkey.c] + make Ed25519 keys' title fit properly in the randomart border; bz#2247 + based on patch from Christian Hesse + +commit 9eb4cd9a32c32d40d36450b68ed93badc6a94c68 +Author: Damien Miller +Date: Thu Jul 3 13:29:50 2014 +1000 + + - (djm) [monitor_fdpass.c] Use sys/poll.h if poll.h doesn't exist; + bz#2237 + +commit 8da0fa24934501909408327298097b1629b89eaa +Author: Damien Miller +Date: Thu Jul 3 11:54:19 2014 +1000 + + - (djm) [digest-openssl.c configure.ac] Disable RIPEMD160 if libcrypto + doesn't support it. + +commit 81309c857dd0dbc0a1245a16d621c490ad48cfbb +Author: Damien Miller +Date: Wed Jul 2 17:45:55 2014 +1000 + + - (djm) [regress/Makefile] fix execution of sshkey unit/fuzz test + +commit 82b2482ce68654815ee049b9bf021bb362a35ff2 +Author: Damien Miller +Date: Wed Jul 2 17:43:41 2014 +1000 + + - (djm) [sshkey.c] Conditionalise inclusion of util.h + +commit dd8b1dd7933eb6f5652641b0cdced34a387f2e80 +Author: Damien Miller +Date: Wed Jul 2 17:38:31 2014 +1000 + + - djm@cvs.openbsd.org 2014/06/24 01:14:17 + [Makefile.in regress/Makefile regress/unittests/Makefile] + [regress/unittests/sshkey/Makefile] + [regress/unittests/sshkey/common.c] + [regress/unittests/sshkey/common.h] + [regress/unittests/sshkey/mktestdata.sh] + [regress/unittests/sshkey/test_file.c] + [regress/unittests/sshkey/test_fuzz.c] + [regress/unittests/sshkey/test_sshkey.c] + [regress/unittests/sshkey/tests.c] + [regress/unittests/sshkey/testdata/dsa_1] + [regress/unittests/sshkey/testdata/dsa_1-cert.fp] + [regress/unittests/sshkey/testdata/dsa_1-cert.pub] + [regress/unittests/sshkey/testdata/dsa_1.fp] + [regress/unittests/sshkey/testdata/dsa_1.fp.bb] + [regress/unittests/sshkey/testdata/dsa_1.param.g] + [regress/unittests/sshkey/testdata/dsa_1.param.priv] + [regress/unittests/sshkey/testdata/dsa_1.param.pub] + [regress/unittests/sshkey/testdata/dsa_1.pub] + [regress/unittests/sshkey/testdata/dsa_1_pw] + [regress/unittests/sshkey/testdata/dsa_2] + [regress/unittests/sshkey/testdata/dsa_2.fp] + [regress/unittests/sshkey/testdata/dsa_2.fp.bb] + [regress/unittests/sshkey/testdata/dsa_2.pub] + [regress/unittests/sshkey/testdata/dsa_n] + [regress/unittests/sshkey/testdata/dsa_n_pw] + [regress/unittests/sshkey/testdata/ecdsa_1] + [regress/unittests/sshkey/testdata/ecdsa_1-cert.fp] + [regress/unittests/sshkey/testdata/ecdsa_1-cert.pub] + [regress/unittests/sshkey/testdata/ecdsa_1.fp] + [regress/unittests/sshkey/testdata/ecdsa_1.fp.bb] + [regress/unittests/sshkey/testdata/ecdsa_1.param.curve] + [regress/unittests/sshkey/testdata/ecdsa_1.param.priv] + [regress/unittests/sshkey/testdata/ecdsa_1.param.pub] + [regress/unittests/sshkey/testdata/ecdsa_1.pub] + [regress/unittests/sshkey/testdata/ecdsa_1_pw] + [regress/unittests/sshkey/testdata/ecdsa_2] + [regress/unittests/sshkey/testdata/ecdsa_2.fp] + [regress/unittests/sshkey/testdata/ecdsa_2.fp.bb] + [regress/unittests/sshkey/testdata/ecdsa_2.param.curve] + [regress/unittests/sshkey/testdata/ecdsa_2.param.priv] + [regress/unittests/sshkey/testdata/ecdsa_2.param.pub] + [regress/unittests/sshkey/testdata/ecdsa_2.pub] + [regress/unittests/sshkey/testdata/ecdsa_n] + [regress/unittests/sshkey/testdata/ecdsa_n_pw] + [regress/unittests/sshkey/testdata/ed25519_1] + [regress/unittests/sshkey/testdata/ed25519_1-cert.fp] + [regress/unittests/sshkey/testdata/ed25519_1-cert.pub] + [regress/unittests/sshkey/testdata/ed25519_1.fp] + [regress/unittests/sshkey/testdata/ed25519_1.fp.bb] + [regress/unittests/sshkey/testdata/ed25519_1.pub] + [regress/unittests/sshkey/testdata/ed25519_1_pw] + [regress/unittests/sshkey/testdata/ed25519_2] + [regress/unittests/sshkey/testdata/ed25519_2.fp] + [regress/unittests/sshkey/testdata/ed25519_2.fp.bb] + [regress/unittests/sshkey/testdata/ed25519_2.pub] + [regress/unittests/sshkey/testdata/pw] + [regress/unittests/sshkey/testdata/rsa1_1] + [regress/unittests/sshkey/testdata/rsa1_1.fp] + [regress/unittests/sshkey/testdata/rsa1_1.fp.bb] + [regress/unittests/sshkey/testdata/rsa1_1.param.n] + [regress/unittests/sshkey/testdata/rsa1_1.pub] + [regress/unittests/sshkey/testdata/rsa1_1_pw] + [regress/unittests/sshkey/testdata/rsa1_2] + [regress/unittests/sshkey/testdata/rsa1_2.fp] + [regress/unittests/sshkey/testdata/rsa1_2.fp.bb] + [regress/unittests/sshkey/testdata/rsa1_2.param.n] + [regress/unittests/sshkey/testdata/rsa1_2.pub] + [regress/unittests/sshkey/testdata/rsa_1] + [regress/unittests/sshkey/testdata/rsa_1-cert.fp] + [regress/unittests/sshkey/testdata/rsa_1-cert.pub] + [regress/unittests/sshkey/testdata/rsa_1.fp] + [regress/unittests/sshkey/testdata/rsa_1.fp.bb] + [regress/unittests/sshkey/testdata/rsa_1.param.n] + [regress/unittests/sshkey/testdata/rsa_1.param.p] + [regress/unittests/sshkey/testdata/rsa_1.param.q] + [regress/unittests/sshkey/testdata/rsa_1.pub] + [regress/unittests/sshkey/testdata/rsa_1_pw] + [regress/unittests/sshkey/testdata/rsa_2] + [regress/unittests/sshkey/testdata/rsa_2.fp] + [regress/unittests/sshkey/testdata/rsa_2.fp.bb] + [regress/unittests/sshkey/testdata/rsa_2.param.n] + [regress/unittests/sshkey/testdata/rsa_2.param.p] + [regress/unittests/sshkey/testdata/rsa_2.param.q] + [regress/unittests/sshkey/testdata/rsa_2.pub] + [regress/unittests/sshkey/testdata/rsa_n] + [regress/unittests/sshkey/testdata/rsa_n_pw] + unit and fuzz tests for new key API + +commit c1dc24b71f087f385b92652b9673f52af64e0428 +Author: Damien Miller +Date: Wed Jul 2 17:02:03 2014 +1000 + + - djm@cvs.openbsd.org 2014/06/24 01:04:43 + [regress/krl.sh] + regress test for broken consecutive revoked serial number ranges + +commit 43d3ed2dd3feca6d0326c7dc82588d2faa115e92 +Author: Damien Miller +Date: Wed Jul 2 17:01:08 2014 +1000 + + - djm@cvs.openbsd.org 2014/05/21 07:04:21 + [regress/integrity.sh] + when failing because of unexpected output, show the offending output + +commit 5a96707ffc8d227c2e7d94fa6b0317f8a152cf4e +Author: Damien Miller +Date: Wed Jul 2 15:38:05 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/30 05:32:00 + [regress/Makefile] + unit tests for new buffer API; including basic fuzz testing + NB. Id sync only. + +commit 3ff92ba756aee48e4ae3e0aeff7293517b3dd185 +Author: Damien Miller +Date: Wed Jul 2 15:33:09 2014 +1000 + + - djm@cvs.openbsd.org 2014/06/30 12:54:39 + [key.c] + suppress spurious error message when loading key with a passphrase; + reported by kettenis@ ok markus@ + - djm@cvs.openbsd.org 2014/07/02 04:59:06 + [cipher-3des1.c] + fix ssh protocol 1 on the server that regressed with the sshkey change + (sometimes fatal() after auth completed), make file return useful status + codes. + NB. Id sync only for these two. They were bundled into the sshkey merge + above, since it was easier to sync the entire file and then apply + portable-specific changed atop it. + +commit ec3d0e24a1e46873d80507f5cd8ee6d0d03ac5dc +Author: Damien Miller +Date: Wed Jul 2 15:30:00 2014 +1000 + + - markus@cvs.openbsd.org 2014/06/27 18:50:39 + [ssh-add.c] + fix loading of private keys + +commit 4b3ed647d5b328cf68e6a8ffbee490d8e0683e82 +Author: Damien Miller +Date: Wed Jul 2 15:29:40 2014 +1000 + + - markus@cvs.openbsd.org 2014/06/27 16:41:56 + [channels.c channels.h clientloop.c ssh.c] + fix remote fwding with same listen port but different listen address + with gerhard@, ok djm@ + +commit 9e01ff28664921ce9b6500681333e42fb133b4d0 +Author: Damien Miller +Date: Wed Jul 2 15:29:21 2014 +1000 + + - deraadt@cvs.openbsd.org 2014/06/25 14:16:09 + [sshbuf.c] + unblock SIGSEGV before raising it + ok djm + +commit 1845fe6bda0729e52f4c645137f4fc3070b5438a +Author: Damien Miller +Date: Wed Jul 2 15:29:01 2014 +1000 + + - djm@cvs.openbsd.org 2014/06/24 02:21:01 + [scp.c] + when copying local->remote fails during read, don't send uninitialised + heap to the remote end. Reported by Jann Horn + +commit 19439e9a2a0ac0b4b3b1210e89695418beb1c883 +Author: Damien Miller +Date: Wed Jul 2 15:28:40 2014 +1000 + + - djm@cvs.openbsd.org 2014/06/24 02:19:48 + [ssh.c] + don't fatal() when hostname canonicalisation fails with a + ProxyCommand in use; continue and allow the ProxyCommand to + connect anyway (e.g. to a host with a name outside the DNS + behind a bastion) + +commit 8668706d0f52654fe64c0ca41a96113aeab8d2b8 +Author: Damien Miller +Date: Wed Jul 2 15:28:02 2014 +1000 + + - djm@cvs.openbsd.org 2014/06/24 01:13:21 + [Makefile.in auth-bsdauth.c auth-chall.c auth-options.c auth-rsa.c + [auth2-none.c auth2-pubkey.c authfile.c authfile.h cipher-3des1.c + [cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h + [digest-libc.c digest-openssl.c digest.h dns.c entropy.c hmac.h + [hostfile.c key.c key.h krl.c monitor.c packet.c rsa.c rsa.h + [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c + [ssh-keygen.c ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c + [ssh-rsa.c sshbuf-misc.c sshbuf.h sshconnect.c sshconnect1.c + [sshconnect2.c sshd.c sshkey.c sshkey.h + [openbsd-compat/openssl-compat.c openbsd-compat/openssl-compat.h] + New key API: refactor key-related functions to be more library-like, + existing API is offered as a set of wrappers. + + with and ok markus@ + + Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew + Dempsky and Ron Bowes for a detailed review a few months ago. + + NB. This commit also removes portable OpenSSH support for OpenSSL + <0.9.8e. + +commit 2cd7929250cf9e9f658d70dcd452f529ba08c942 +Author: Damien Miller +Date: Wed Jul 2 12:48:30 2014 +1000 + + - djm@cvs.openbsd.org 2014/06/24 00:52:02 + [krl.c] + fix bug in KRL generation: multiple consecutive revoked certificate + serial number ranges could be serialised to an invalid format. + + Readers of a broken KRL caused by this bug will fail closed, so no + should-have-been-revoked key will be accepted. + +commit 99db840ee8dbbd2b3fbc6c45d0ee2f6a65e96898 +Author: Damien Miller +Date: Wed Jul 2 12:48:04 2014 +1000 + + - naddy@cvs.openbsd.org 2014/06/18 15:42:09 + [sshbuf-getput-crypto.c] + The ssh_get_bignum functions must accept the same range of bignums + the corresponding ssh_put_bignum functions create. This fixes the + use of 16384-bit RSA keys (bug reported by Eivind Evensen). + ok djm@ + +commit 84a89161a9629239b64171ef3e22ef6a3e462d51 +Author: Damien Miller +Date: Wed Jul 2 12:47:48 2014 +1000 + + - matthew@cvs.openbsd.org 2014/06/18 02:59:13 + [sandbox-systrace.c] + Now that we have a dedicated getentropy(2) system call for + arc4random(3), we can disallow __sysctl(2) in OpenSSH's systrace + sandbox. + + ok djm + +commit 51504ceec627c0ad57b9f75585c7b3d277f326be +Author: Damien Miller +Date: Wed Jul 2 12:47:25 2014 +1000 + + - deraadt@cvs.openbsd.org 2014/06/13 08:26:29 + [sandbox-systrace.c] + permit SYS_getentropy + from matthew + +commit a261b8df59117f7dc52abb3a34b35a40c2c9fa88 +Author: Tim Rice +Date: Wed Jun 18 16:17:28 2014 -0700 + + - (tim) [openssh/session.c] Work around to get chroot sftp working on UnixWare + +commit 316fac6f18f87262a315c79bcf68b9f92c9337e4 +Author: Darren Tucker +Date: Tue Jun 17 23:06:07 2014 +1000 + + - (dtucker) [entropy.c openbsd-compat/openssl-compat.{c,h} + openbsd-compat/regress/{.cvsignore,Makefile.in,opensslvertest.c}] + Move the OpenSSL header/library version test into its own function and add + tests for it. Fix it to allow fix version upgrades (but not downgrades). + Prompted by chl@ via OpenSMTPD (issue #462) and Debian (bug #748150). + ok djm@ chl@ + +commit af665bb7b092a59104db1e65577851cf35b86e32 +Author: Darren Tucker +Date: Mon Jun 16 22:50:55 2014 +1000 + + - (dtucker) [defines.h] Fix undef of _PATH_MAILDIR. From rak at debian via + OpenSMTPD and chl@ + +commit f9696566fb41320820f3b257ab564fa321bb3751 +Author: Darren Tucker +Date: Fri Jun 13 11:06:04 2014 +1000 + + - (dtucker) [configure.ac] Remove tcpwrappers support, support has already + been removed from sshd.c. + +commit 5e2b8894b0b24af4ad0a2f7aa33ebf255df7a8bc +Author: Tim Rice +Date: Wed Jun 11 18:31:10 2014 -0700 + + - (tim) [regress/unittests/test_helper/test_helper.h] Add includes.h for + u_intXX_t types. + +commit 985ee2cbc3e43bc65827c3c0d4df3faa99160c37 +Author: Darren Tucker +Date: Thu Jun 12 05:32:29 2014 +1000 + + - (dtucker) [regress/unittests/sshbuf/*.c regress/unittests/test_helper/*] + Wrap stdlib.h include an ifdef for platforms that don't have it. + +commit cf5392c2db2bb1dbef9818511d34056404436109 +Author: Darren Tucker +Date: Thu Jun 12 05:22:49 2014 +1000 + + - (dtucker) [defines.h] Add va_copy if we don't already have it, taken from + openbsd-compat/bsd-asprintf.c. + +commit 58538d795e0b662f2f4e5a7193f1204bbe992ddd +Author: Darren Tucker +Date: Wed Jun 11 13:39:24 2014 +1000 + + - (dtucker) [bufaux.c bufbn.c bufec.c buffer.c] Pull in includes.h for + compat stuff, specifically whether or not OpenSSL has ECC. + +commit eb012ac581fd0abc16ee86ee3a68cf07c8ce4d08 +Author: Darren Tucker +Date: Wed Jun 11 13:10:00 2014 +1000 + + - (dtucker) [openbsd-compat/arc4random.c] Use explicit_bzero instead of an + assigment that might get optimized out. ok djm@ + +commit b9609fd86c623d6d440e630f5f9a63295f7aea20 +Author: Darren Tucker +Date: Wed Jun 11 08:04:02 2014 +1000 + + - (dtucker) [sshbuf.h] Only declare ECC functions if building without + OpenSSL or if OpenSSL has ECC. + +commit a54a040f66944c6e8913df8635a01a2327219be9 +Author: Darren Tucker +Date: Wed Jun 11 07:58:35 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/06/10 21:46:11 + [sshbuf.h] + Group ECC functions together to make things a little easier in -portable. + "doesn't bother me" deraadt@ + +commit 9f92c53bad04a89067756be8198d4ec2d8a08875 +Author: Darren Tucker +Date: Wed Jun 11 07:57:58 2014 +1000 + + - djm@cvs.openbsd.org 2014/06/05 22:17:50 + [sshconnect2.c] + fix inverted test that caused PKCS#11 keys that were explicitly listed + not to be preferred. Reported by Dirk-Willem van Gulik + +commit 15c254a25394f96643da2ad0f674acdc51e89856 +Author: Darren Tucker +Date: Wed Jun 11 07:38:49 2014 +1000 + + - (dtucker) [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] ifdef + ECC variable too. + +commit d7af0cc5bf273eeed0897a99420bc26841d07d8f +Author: Darren Tucker +Date: Wed Jun 11 07:37:25 2014 +1000 + + - (dtucker) [myprosal.h] Don't include curve25519-sha256@libssh.org in + the proposal if the version of OpenSSL we're using doesn't support ECC. + +commit 67508ac2563c33d582be181a3e777c65f549d22f +Author: Darren Tucker +Date: Wed Jun 11 06:27:16 2014 +1000 + + - (dtucker) [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c + regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] Only do NISTP256 + curve tests if OpenSSL has them. + +commit 6482d90a65459a88c18c925368525855832272b3 +Author: Damien Miller +Date: Tue May 27 14:34:42 2014 +1000 + + - (djm) [configure.ac openbsd-compat/bsd-cygwin_util.c] + [openbsd-compat/bsd-cygwin_util.h] On Cygwin, determine privilege + separation user at runtime, since it may need to be a domain account. + Patch from Corinna Vinschen. + +commit f9eb5e0734f7a7f6e975809eb54684d2a06a7ffc +Author: Damien Miller +Date: Tue May 27 14:31:58 2014 +1000 + + - (djm) [contrib/cygwin/ssh-host-config] Updated Cygwin ssh-host-config + from Corinna Vinschen, fixing a number of bugs and preparing for + Cygwin 1.7.30. + +commit eae88744662e6b149f43ef071657727f1a157d95 +Author: Damien Miller +Date: Tue May 27 14:27:02 2014 +1000 + + - (djm) [cipher.c] Fix merge botch. + +commit 564b5e253c1d95c26a00e8288f0089a2571661c3 +Author: Damien Miller +Date: Thu May 22 08:23:59 2014 +1000 + + - (djm) [Makefile.in] typo in path + +commit e84d10302aeaf7a1acb05c451f8718143656856a +Author: Damien Miller +Date: Wed May 21 17:13:36 2014 +1000 + + revert a diff I didn't mean to commit + +commit 795b86313f1f1aab9691666c4f2d5dae6e4acd50 +Author: Damien Miller +Date: Wed May 21 17:12:53 2014 +1000 + + - (djm) [misc.c] Use CLOCK_BOOTTIME in preference to CLOCK_MONOTONIC + when it is available. It takes into account time spent suspended, + thereby ensuring timeouts (e.g. for expiring agent keys) fire + correctly. bz#2228 reported by John Haxby + +commit 18912775cb97c0b1e75e838d3c7d4b56648137b5 +Author: Damien Miller +Date: Wed May 21 17:06:46 2014 +1000 + + - (djm) [commit configure.ac defines.h sshpty.c] don't attempt to use + vhangup on Linux. It doens't work for non-root users, and for them + it just messes up the tty settings. + +commit 7f1c264d3049cd95234e91970ccb5406e1d15b27 +Author: Damien Miller +Date: Thu May 15 18:01:52 2014 +1000 + + - (djm) [sshbuf.c] need __predict_false + +commit e7429f2be8643e1100380a8a7389d85cc286c8fe +Author: Damien Miller +Date: Thu May 15 18:01:01 2014 +1000 + + - (djm) [regress/Makefile Makefile.in] + [regress/unittests/sshbuf/test_sshbuf.c + [regress/unittests/sshbuf/test_sshbuf_fixed.c] + [regress/unittests/sshbuf/test_sshbuf_fuzz.c] + [regress/unittests/sshbuf/test_sshbuf_getput_basic.c] + [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c] + [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] + [regress/unittests/sshbuf/test_sshbuf_misc.c] + [regress/unittests/sshbuf/tests.c] + [regress/unittests/test_helper/fuzz.c] + [regress/unittests/test_helper/test_helper.c] + Hook new unit tests into the build and "make tests" + +commit def1de086707b0e6b046fe7e115c60aca0227a99 +Author: Damien Miller +Date: Thu May 15 15:17:15 2014 +1000 + + - (djm) [regress/unittests/Makefile] + [regress/unittests/Makefile.inc] + [regress/unittests/sshbuf/Makefile] + [regress/unittests/sshbuf/test_sshbuf.c] + [regress/unittests/sshbuf/test_sshbuf_fixed.c] + [regress/unittests/sshbuf/test_sshbuf_fuzz.c] + [regress/unittests/sshbuf/test_sshbuf_getput_basic.c] + [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c] + [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] + [regress/unittests/sshbuf/test_sshbuf_misc.c] + [regress/unittests/sshbuf/tests.c] + [regress/unittests/test_helper/Makefile] + [regress/unittests/test_helper/fuzz.c] + [regress/unittests/test_helper/test_helper.c] + [regress/unittests/test_helper/test_helper.h] + Import new unit tests from OpenBSD; not yet hooked up to build. + +commit 167685756fde8bc213a8df2c8e1848e312db0f46 +Author: Damien Miller +Date: Thu May 15 15:08:40 2014 +1000 + + - logan@cvs.openbsd.org 2014/05/04 10:40:59 + [connect-privsep.sh] + Remove the Z flag from the list of malloc options as it + was removed from malloc.c 10 days ago. + + OK from miod@ + +commit d0b69fe90466920d69c96069312e24b581771bd7 +Author: Damien Miller +Date: Thu May 15 15:08:19 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/05/03 18:46:14 + [proxy-connect.sh] + Add tests for with and without compression, with and without privsep. + +commit edb1af50441d19fb2dd9ccb4d75bf14473fca584 +Author: Damien Miller +Date: Thu May 15 15:07:53 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/21 22:15:37 + [dhgex.sh integrity.sh kextype.sh rekey.sh try-ciphers.sh] + repair regress tests broken by server-side default cipher/kex/mac changes + by ensuring that the option under test is included in the server's + algorithm list + +commit 54343e95c70994695f8842fb22836321350198d3 +Author: Damien Miller +Date: Thu May 15 15:07:33 2014 +1000 + + - djm@cvs.openbsd.org 2014/03/13 20:44:49 + [login-timeout.sh] + this test is a sorry mess of race conditions; add another sleep + to avoid a failure on slow machines (at least until I find a + better way) + +commit e5b9f0f2ee6e133894307e44e862b66426990733 +Author: Damien Miller +Date: Thu May 15 14:58:07 2014 +1000 + + - (djm) [Makefile.in configure.ac sshbuf-getput-basic.c] + [sshbuf-getput-crypto.c sshbuf.c] compilation and portability fixes + +commit b9c566788a9ebd6a9d466f47a532124f111f0542 +Author: Damien Miller +Date: Thu May 15 14:43:37 2014 +1000 + + - (djm) [configure.ac] Unconditionally define WITH_OPENSSL until we write + portability glue to support building without libcrypto + +commit 3dc27178b42234b653a32f7a87292d7994045ee3 +Author: Damien Miller +Date: Thu May 15 14:37:59 2014 +1000 + + - logan@cvs.openbsd.org 2014/05/05 07:02:30 + [sftp.c] + Zap extra whitespace. + + OK from djm@ and dtucker@ + +commit c31a0cd5b31961f01c5b731f62a6cb9d4f767472 +Author: Damien Miller +Date: Thu May 15 14:37:39 2014 +1000 + + - markus@cvs.openbsd.org 2014/05/03 17:20:34 + [monitor.c packet.c packet.h] + unbreak compression, by re-init-ing the compression code in the + post-auth child. the new buffer code is more strict, and requires + buffer_init() while the old code was happy after a bzero(); + originally from djm@ + +commit 686c7d9ee6f44b2be4128d7860b6b37adaeba733 +Author: Damien Miller +Date: Thu May 15 14:37:03 2014 +1000 + + - djm@cvs.openbsd.org 2014/05/02 03:27:54 + [chacha.h cipher-chachapoly.h digest.h hmac.h kex.h kexc25519.c] + [misc.h poly1305.h ssh-pkcs11.c defines.h] + revert __bounded change; it causes way more problems for portable than + it solves; pointed out by dtucker@ + +commit 294c58a007cfb2f3bddc4fc3217e255857ffb9bf +Author: Damien Miller +Date: Thu May 15 14:35:03 2014 +1000 + + - naddy@cvs.openbsd.org 2014/04/30 19:07:48 + [mac.c myproposal.h umac.c] + UMAC can use our local fallback implementation of AES when OpenSSL isn't + available. Glue code straight from Ted Krovetz's original umac.c. + ok markus@ + +commit 05e82c3b963c33048128baf72a6f6b3a1c10b4c1 +Author: Damien Miller +Date: Thu May 15 14:33:43 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/30 05:29:56 + [bufaux.c bufbn.c bufec.c buffer.c buffer.h sshbuf-getput-basic.c] + [sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c sshbuf.h ssherr.c] + [ssherr.h] + New buffer API; the first installment of the conversion/replacement + of OpenSSH's internals to make them usable as a standalone library. + + This includes a set of wrappers to make it compatible with the + existing buffer API so replacement can occur incrementally. + + With and ok markus@ + + Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew + Dempsky and Ron Bowes for a detailed review. + +commit 380948180f847a26f2d0c85b4dad3dca2ed2fd8b +Author: Damien Miller +Date: Thu May 15 14:25:18 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/04/29 20:36:51 + [sftp.c] + Don't attempt to append a nul quote char to the filename. Should prevent + fatal'ing with "el_insertstr failed" when there's a single quote char + somewhere in the string. bz#2238, ok markus@ + +commit d7fd8bedd4619a2ec7fd02aae4c4e1db4431ad9f +Author: Damien Miller +Date: Thu May 15 14:24:59 2014 +1000 + + - dtucker@cvs.openbsd.org 2014/04/29 19:58:50 + [sftp.c] + Move nulling of variable next to where it's freed. ok markus@ + +commit 1f0311c7c7d10c94ff7f823de9c5b2ed79368b14 +Author: Damien Miller +Date: Thu May 15 14:24:09 2014 +1000 + + - markus@cvs.openbsd.org 2014/04/29 18:01:49 + [auth.c authfd.c authfile.c bufaux.c cipher.c cipher.h hostfile.c] + [kex.c key.c mac.c monitor.c monitor_wrap.c myproposal.h packet.c] + [roaming_client.c ssh-agent.c ssh-keygen.c ssh-keyscan.c ssh-keysign.c] + [ssh-pkcs11.h ssh.c sshconnect.c sshconnect2.c sshd.c] + make compiling against OpenSSL optional (make OPENSSL=no); + reduces algorithms to curve25519, aes-ctr, chacha, ed25519; + allows us to explore further options; with and ok djm + +commit c5893785564498cea73cb60d2cf199490483e080 +Author: Damien Miller +Date: Thu May 15 13:48:49 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/29 13:10:30 + [clientloop.c serverloop.c] + bz#1818 - don't send channel success/failre replies on channels that + have sent a close already; analysis and patch from Simon Tatham; + ok markus@ + +commit 633de33b192d808d87537834c316dc8b75fe1880 +Author: Damien Miller +Date: Thu May 15 13:48:26 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/28 03:09:18 + [authfile.c bufaux.c buffer.h channels.c krl.c mux.c packet.c packet.h] + [ssh-keygen.c] + buffer_get_string_ptr's return should be const to remind + callers that futzing with it will futz with the actual buffer + contents + +commit 15271907843e4ae50dcfc83b3594014cf5e9607b +Author: Damien Miller +Date: Thu May 15 13:47:56 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/23 12:42:34 + [readconf.c] + don't record duplicate IdentityFiles + +commit 798a02568b13a2e46efebd81f08c8f4bb33a6dc7 +Author: Damien Miller +Date: Thu May 15 13:47:37 2014 +1000 + + - jmc@cvs.openbsd.org 2014/04/22 14:16:30 + [sftp.1] + zap eol whitespace; + +commit d875ff78d2b8436807381051de112f0ebf9b9ae1 +Author: Damien Miller +Date: Thu May 15 13:47:15 2014 +1000 + + - logan@cvs.openbsd.org 2014/04/22 12:42:04 + [sftp.1] + Document sftp upload resume. + OK from djm@, with feedback from okan@. + +commit b15cd7bb097fd80dc99520f45290ef775da1ef19 +Author: Damien Miller +Date: Thu May 15 13:46:52 2014 +1000 + + - logan@cvs.openbsd.org 2014/04/22 10:07:12 + [sftp.c] + Sort the sftp command list. + OK from djm@ + +commit d8accc0aa72656ba63d50937165c5ae49db1dcd6 +Author: Damien Miller +Date: Thu May 15 13:46:25 2014 +1000 + + - logan@cvs.openbsd.org 2014/04/21 14:36:16 + [sftp-client.c sftp-client.h sftp.c] + Implement sftp upload resume support. + OK from djm@, with input from guenther@, mlarkin@ and + okan@ + +commit 16cd3928a87d20c77b13592a74b60b08621d3ce6 +Author: Damien Miller +Date: Thu May 15 13:45:58 2014 +1000 + + - logan@cvs.openbsd.org 2014/04/20 09:24:26 + [dns.c dns.h ssh-keygen.c] + Add support for SSHFP DNS records for ED25519 key types. + OK from djm@ + +commit ec0b67eb3b4e12f296ced1fafa01860c374f7eea +Author: Damien Miller +Date: Thu May 15 13:45:26 2014 +1000 + + - (djm) [rijndael.c rijndael.h] Sync with newly-ressurected versions ine + OpenBSD + +commit f028460d0b2e5a584355321015cde69bf6fd933e +Author: Darren Tucker +Date: Thu May 1 02:24:35 2014 +1000 + + - (dtucker) [defines.h] Define __GNUC_PREREQ__ macro if we don't already + have it. Only attempt to use __attribute__(__bounded__) for gcc. + +commit b628cc4c3e4a842bab5e4584d18c2bc5fa4d0edf +Author: Damien Miller +Date: Sun Apr 20 13:33:58 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/20 02:49:32 + [compat.c] + add a canonical 6.6 + curve25519 bignum fix fake version that I can + recommend people use ahead of the openssh-6.7 release + +commit 888566913933a802f3a329ace123ebcb7154cf78 +Author: Damien Miller +Date: Sun Apr 20 13:33:19 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/20 02:30:25 + [misc.c misc.h umac.c] + use get/put_u32 to load values rather than *((UINT32 *)p) that breaks on + strict-alignment architectures; reported by and ok stsp@ + +commit 16f85cbc7e5139950e6a38317e7c8b368beafa5d +Author: Damien Miller +Date: Sun Apr 20 13:29:28 2014 +1000 + + - tedu@cvs.openbsd.org 2014/04/19 18:42:19 + [ssh.1] + delete .xr to hosts.equiv. there's still an unfortunate amount of + documentation referring to rhosts equivalency in here. + +commit 69cb24b7356ec3f0fc5ff04a68f98f2c55c766f4 +Author: Damien Miller +Date: Sun Apr 20 13:29:06 2014 +1000 + + - tedu@cvs.openbsd.org 2014/04/19 18:15:16 + [sshd.8] + remove some really old rsh references + +commit 84c1e7bca8c4ceaccf4d5557e39a833585a3c77e +Author: Damien Miller +Date: Sun Apr 20 13:27:53 2014 +1000 + + - tedu@cvs.openbsd.org 2014/04/19 14:53:48 + [ssh-keysign.c sshd.c] + Delete futile calls to RAND_seed. ok djm + NB. Id sync only. This only applies to OpenBSD's libcrypto slashathon + +commit 0e6b67423b8662f9ca4c92750309e144fd637ef1 +Author: Damien Miller +Date: Sun Apr 20 13:27:01 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/19 05:54:59 + [compat.c] + missing wildcard; pointed out by naddy@ + +commit 9395b28223334826837c15e8c1bb4dfb3b0d2ca5 +Author: Damien Miller +Date: Sun Apr 20 13:25:30 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/18 23:52:25 + [compat.c compat.h sshconnect2.c sshd.c version.h] + OpenSSH 6.5 and 6.6 have a bug that causes ~0.2% of connections + using the curve25519-sha256@libssh.org KEX exchange method to fail + when connecting with something that implements the spec properly. + + Disable this KEX method when speaking to one of the affected + versions. + + reported by Aris Adamantiadis; ok markus@ + +commit 8c492da58f8ceb85cf5f7066f23e26fb813a963d +Author: Damien Miller +Date: Sun Apr 20 13:25:09 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/16 23:28:12 + [ssh-agent.1] + remove the identity files from this manpage - ssh-agent doesn't deal + with them at all and the same information is duplicated in ssh-add.1 + (which does deal with them); prodded by deraadt@ + +commit adbfdbbdccc70c9bd70d81ae096db115445c6e26 +Author: Damien Miller +Date: Sun Apr 20 13:24:49 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/16 23:22:45 + [bufaux.c] + skip leading zero bytes in buffer_put_bignum2_from_string(); + reported by jan AT mojzis.com; ok markus@ + +commit 75c62728dc87af6805696eeb520b9748faa136c8 +Author: Damien Miller +Date: Sun Apr 20 13:24:31 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/12 04:55:53 + [sshd.c] + avoid crash at exit: check that pmonitor!=NULL before dereferencing; + bz#2225, patch from kavi AT juniper.net + +commit 2a328437fb1b0976f2f4522d8645803d5a5d0967 +Author: Damien Miller +Date: Sun Apr 20 13:24:01 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/01 05:32:57 + [packet.c] + demote a debug3 to PACKET_DEBUG; ok markus@ + +commit 7d6a9fb660c808882d064e152d6070ffc3844c3f +Author: Damien Miller +Date: Sun Apr 20 13:23:43 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/01 03:34:10 + [sshconnect.c] + When using VerifyHostKeyDNS with a DNSSEC resolver, down-convert any + certificate keys to plain keys and attempt SSHFP resolution. + + Prevents a server from skipping SSHFP lookup and forcing a new-hostkey + dialog by offering only certificate keys. + + Reported by mcv21 AT cam.ac.uk + +commit fcd62c0b66b8415405ed0af29c236329eb88cc0f +Author: Damien Miller +Date: Sun Apr 20 13:23:21 2014 +1000 + + - djm@cvs.openbsd.org 2014/04/01 02:05:27 + [ssh-keysign.c] + include fingerprint of key not found + use arc4random_buf() instead of loop+arc4random() + +commit 43b156cf72f900f88065b0a1c1ebd09ab733ca46 +Author: Damien Miller +Date: Sun Apr 20 13:23:03 2014 +1000 + + - jmc@cvs.openbsd.org 2014/03/31 13:39:34 + [ssh-keygen.1] + the text for the -K option was inserted in the wrong place in -r1.108; + fix From: Matthew Clarke + +commit c1621c84f2dc1279065ab9fde2aa9327af418900 +Author: Damien Miller +Date: Sun Apr 20 13:22:46 2014 +1000 + + - naddy@cvs.openbsd.org 2014/03/28 05:17:11 + [ssh_config.5 sshd_config.5] + sync available and default algorithms, improve algorithm list formatting + help from jmc@ and schwarze@, ok deraadt@ + +commit f2719b7c2b8a3b14d778d8a6d8dc729b5174b054 +Author: Damien Miller +Date: Sun Apr 20 13:22:18 2014 +1000 + + - tedu@cvs.openbsd.org 2014/03/26 19:58:37 + [sshd.8 sshd.c] + remove libwrap support. ok deraadt djm mfriedl + +commit 4f40209aa4060b9c066a2f0d9332ace7b8dfb391 +Author: Damien Miller +Date: Sun Apr 20 13:21:22 2014 +1000 + + - djm@cvs.openbsd.org 2014/03/26 04:55:35 + [chacha.h cipher-chachapoly.h digest.h hmac.h kex.h kexc25519.c + [misc.h poly1305.h ssh-pkcs11.c] + use __bounded(...) attribute recently added to sys/cdefs.h instead of + longform __attribute__(__bounded(...)); + + for brevity and a warning free compilation with llvm/clang + +commit 9235a030ad1b16903fb495d81544e0f7c7449523 +Author: Damien Miller +Date: Sun Apr 20 13:17:20 2014 +1000 + + Three commits in one (since they touch the same heavily-diverged file + repeatedly): + + - markus@cvs.openbsd.org 2014/03/25 09:40:03 + [myproposal.h] + trimm default proposals. + + This commit removes the weaker pre-SHA2 hashes, the broken ciphers + (arcfour), and the broken modes (CBC) from the default configuration + (the patch only changes the default, all the modes are still available + for the config files). + + ok djm@, reminded by tedu@ & naddy@ and discussed with many + - deraadt@cvs.openbsd.org 2014/03/26 17:16:26 + [myproposal.h] + The current sharing of myproposal[] between both client and server code + makes the previous diff highly unpallatable. We want to go in that + direction for the server, but not for the client. Sigh. + Brought up by naddy. + - markus@cvs.openbsd.org 2014/03/27 23:01:27 + [myproposal.h ssh-keyscan.c sshconnect2.c sshd.c] + disable weak proposals in sshd, but keep them in ssh; ok djm@ + +commit 6e1777f592f15f4559728c78204617537b1ac076 +Author: Damien Miller +Date: Sun Apr 20 13:02:58 2014 +1000 + + - tedu@cvs.openbsd.org 2014/03/19 14:42:44 + [scp.1] + there is no need for rcp anymore + ok deraadt millert + +commit eb1b7c514d2a7b1802ccee8cd50e565a4d419887 +Author: Damien Miller +Date: Sun Apr 20 13:02:26 2014 +1000 + + - tedu@cvs.openbsd.org 2014/03/17 19:44:10 + [ssh.1] + old descriptions of des and blowfish are old. maybe ok deraadt + +commit f0858de6e1324ec730752387074b111b8551081e +Author: Damien Miller +Date: Sun Apr 20 13:01:30 2014 +1000 + + - deraadt@cvs.openbsd.org 2014/03/15 17:28:26 + [ssh-agent.c ssh-keygen.1 ssh-keygen.c] + Improve usage() and documentation towards the standard form. + In particular, this line saves a lot of man page reading time. + usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1] + [-N new_passphrase] [-C comment] [-f output_keyfile] + ok schwarze jmc + +commit 94bfe0fbd6e91a56b5b0ab94ac955d2a67d101aa +Author: Damien Miller +Date: Sun Apr 20 13:00:51 2014 +1000 + + - naddy@cvs.openbsd.org 2014/03/12 13:06:59 + [ssh-keyscan.1] + scan for Ed25519 keys by default too + +commit 3819519288b2b3928c6882f5883b0f55148f4fc0 +Author: Damien Miller +Date: Sun Apr 20 13:00:28 2014 +1000 + + - djm@cvs.openbsd.org 2014/03/12 04:51:12 + [authfile.c] + correct test that kdf name is not "none" or "bcrypt" + +commit 8f9cd709c7cf0655d414306a0ed28306b33802be +Author: Damien Miller +Date: Sun Apr 20 13:00:11 2014 +1000 + + - djm@cvs.openbsd.org 2014/03/12 04:50:32 + [auth-bsdauth.c ssh-keygen.c] + don't count on things that accept arguments by reference to clear + things for us on error; most things do, but it's unsafe form. + +commit 1c7ef4be83f6dec84509a312518b9df00ab491d9 +Author: Damien Miller +Date: Sun Apr 20 12:59:46 2014 +1000 + + - djm@cvs.openbsd.org 2014/03/12 04:44:58 + [ssh-keyscan.c] + scan for Ed25519 keys by default too + +commit c10bf4d051c97939b30a1616c0499310057d07da +Author: Damien Miller +Date: Sun Apr 20 12:58:04 2014 +1000 + + - djm@cvs.openbsd.org 2014/03/03 22:22:30 + [session.c] + ignore enviornment variables with embedded '=' or '\0' characters; + spotted by Jann Horn; ok deraadt@ + Id sync only - portable already has this. + +commit c2e49062faccbcd7135c40d1c78c5c329c58fc2e +Author: Damien Miller +Date: Tue Apr 1 14:42:46 2014 +1100 + + - (djm) Use full release (e.g. 6.5p1) in debug output rather than just + version. From des@des.no + +commit 14928b7492abec82afa4c2b778fc03f78cd419b6 +Author: Damien Miller +Date: Tue Apr 1 14:38:07 2014 +1100 + + - (djm) On platforms that support it, use prctl() to prevent sftp-server + from accessing /proc/self/{mem,maps}; patch from jann AT thejh.net + +commit 48abc47e60048461fe9117e108a7e99ea1ac2bb8 +Author: Damien Miller +Date: Mon Mar 17 14:45:56 2014 +1100 + + - (djm) [sandbox-seccomp-filter.c] Soft-fail stat() syscalls. Add XXX to + remind myself to add sandbox violation logging via the log socket. + +commit 9c36698ca2f554ec221dc7ef29c7a89e97c88705 +Author: Tim Rice +Date: Fri Mar 14 12:45:01 2014 -0700 + + 20140314 + - (tim) [opensshd.init.in] Add support for ed25519 + +commit 19158b2447e35838d69b2b735fb640d1e86061ea +Author: Damien Miller +Date: Thu Mar 13 13:14:21 2014 +1100 + + - (djm) Release OpenSSH 6.6 + +commit 8569eba5d7f7348ce3955eeeb399f66f25c52ece +Author: Damien Miller +Date: Tue Mar 4 09:35:17 2014 +1100 + + - djm@cvs.openbsd.org 2014/03/03 22:22:30 + [session.c] + ignore enviornment variables with embedded '=' or '\0' characters; + spotted by Jann Horn; ok deraadt@ + +commit 2476c31b96e89aec7d4e73cb6fbfb9a4290de3a7 +Author: Damien Miller +Date: Sun Mar 2 04:01:00 2014 +1100 + + - (djm) [regress/Makefile] Disable dhgex regress test; it breaks when + no moduli file exists at the expected location. + +commit c83fdf30e9db865575b2521b1fe46315cf4c70ae +Author: Damien Miller +Date: Fri Feb 28 10:34:03 2014 +1100 + + - (djm) [regress/host-expand.sh] Add RCS Id + +commit 834aeac3555e53f7d29a6fcf3db010dfb99681c7 +Author: Damien Miller +Date: Fri Feb 28 10:25:16 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/27 21:21:25 + [agent-ptrace.sh agent.sh] + keep return values that are printed in error messages; + from portable + (Id sync only) + +commit 4f7f1a9a0de24410c30952c7e16d433240422182 +Author: Damien Miller +Date: Fri Feb 28 10:24:11 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/27 20:04:16 + [login-timeout.sh] + remove any existing LoginGraceTime from sshd_config before adding + a specific one for the test back in + +commit d705d987c27f68080c8798eeb5262adbdd6b4ffd +Author: Damien Miller +Date: Fri Feb 28 10:23:26 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/26 10:49:17 + [scp-ssh-wrapper.sh scp.sh] + make sure $SCP is tested on the remote end rather than whichever one + happens to be in $PATH; from portable + (Id sync only) + +commit 624a3ca376e3955a4b9d936c9e899e241b65d357 +Author: Damien Miller +Date: Fri Feb 28 10:22:37 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/26 10:22:10 + [regress/cert-hostkey.sh] + automatically generate revoked keys from listed keys rather than + manually specifying each type; from portable + (Id sync only) + +commit b84392328425e4b9a71f8bde5fe6a4a4c48d3ec4 +Author: Damien Miller +Date: Fri Feb 28 10:21:26 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/25 04:35:32 + [regress/Makefile regress/dhgex.sh] + Add a test for DH GEX sizes + +commit 1e2aa3d90472293ea19008f02336d6d68aa05793 +Author: Damien Miller +Date: Fri Feb 28 10:19:51 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/20 00:00:30 + [sftp-chroot.sh] + append to rather than truncating the log file + +commit f483cc16fe7314e24a37aa3a4422b03c013c3213 +Author: Damien Miller +Date: Fri Feb 28 10:19:11 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/19 23:43:02 + [regress/sftp-chroot.sh] + Don't use -q on sftp as it suppresses logging, instead redirect the + output to the regress logfile. + +commit 6486f16f1c0ebd6f39286f6ab5e08286d90a994a +Author: Damien Miller +Date: Fri Feb 28 10:03:52 2014 +1100 + + - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec] + [contrib/suse/openssh.spec] Crank version numbers + +commit 92cf5adea194140380e6af6ec32751f9ad540794 +Author: Damien Miller +Date: Fri Feb 28 10:01:53 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/27 22:57:40 + [version.h] + openssh-6.6 + +commit fc5d6759aba71eb205b296b5f148010ffc828583 +Author: Damien Miller +Date: Fri Feb 28 10:01:28 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/27 22:47:07 + [sshd_config.5] + bz#2184 clarify behaviour of a keyword that appears in multiple + matching Match blocks; ok dtucker@ + +commit 172ec7e0af1a5f1d682f6a2dca335c6c186153d5 +Author: Damien Miller +Date: Fri Feb 28 10:00:57 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/27 08:25:09 + [bufbn.c] + off by one in range check + +commit f9a9aaba437c2787e40cf7cc928281950e161678 +Author: Damien Miller +Date: Fri Feb 28 10:00:27 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/27 00:41:49 + [bufbn.c] + fix unsigned overflow that could lead to reading a short ssh protocol + 1 bignum value; found by Ben Hawkes; ok deraadt@ + +commit fb3423b612713d9cde67c8a75f6f51188d6a3de3 +Author: Damien Miller +Date: Thu Feb 27 10:20:07 2014 +1100 + + - markus@cvs.openbsd.org 2014/02/26 21:53:37 + [sshd.c] + ssh_gssapi_prepare_supported_oids needs GSSAPI + +commit 1348129a34f0f7728c34d86c100a32dcc8d1f922 +Author: Damien Miller +Date: Thu Feb 27 10:18:32 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/26 20:29:29 + [channels.c] + don't assume that the socks4 username is \0 terminated; + spotted by Ben Hawkes; ok markus@ + +commit e6a74aeeacd01d885262ff8e50eb28faee8c8039 +Author: Damien Miller +Date: Thu Feb 27 10:17:49 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/26 20:28:44 + [auth2-gss.c gss-serv.c ssh-gss.h sshd.c] + bz#2107 - cache OIDs of supported GSSAPI mechanisms before privsep + sandboxing, as running this code in the sandbox can cause violations; + ok markus@ + +commit 08b57c67f3609340ff703fe2782d7058acf2529e +Author: Damien Miller +Date: Thu Feb 27 10:17:13 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/26 20:18:37 + [ssh.c] + bz#2205: avoid early hostname lookups unless canonicalisation is enabled; + ok dtucker@ markus@ + +commit 13f97b2286142fd0b8eab94e4ce84fe124eeb752 +Author: Damien Miller +Date: Mon Feb 24 15:57:55 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/23 20:11:36 + [readconf.c readconf.h ssh.c ssh_config.5] + reparse ssh_config and ~/.ssh/config if hostname canonicalisation changes + the hostname. This allows users to write configurations that always + refer to canonical hostnames, e.g. + + CanonicalizeHostname yes + CanonicalDomains int.example.org example.org + CanonicalizeFallbackLocal no + + Host *.int.example.org + Compression off + Host *.example.org + User djm + + ok markus@ + +commit bee3a234f3d1ad4244952bcff1b4b7c525330dc2 +Author: Damien Miller +Date: Mon Feb 24 15:57:22 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/23 20:03:42 + [ssh-ed25519.c] + check for unsigned overflow; not reachable in OpenSSH but others might + copy our code... + +commit 0628780abe61e7e50cba48cdafb1837f49ff23b2 +Author: Damien Miller +Date: Mon Feb 24 15:56:45 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/22 01:32:19 + [readconf.c] + when processing Match blocks, skip 'exec' clauses if previous predicates + failed to match; ok markus@ + +commit 0890dc8191bb201eb01c3429feec0300a9d3a930 +Author: Damien Miller +Date: Mon Feb 24 15:56:07 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/15 23:05:36 + [channels.c] + avoid spurious "getsockname failed: Bad file descriptor" errors in ssh -W; + bz#2200, debian#738692 via Colin Watson; ok dtucker@ + +commit d3cf67e1117c25d151d0f86396e77ee3a827045a +Author: Damien Miller +Date: Mon Feb 24 15:55:36 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/07 06:55:54 + [cipher.c mac.c] + remove some logging that makes ssh debugging output very verbose; + ok markus + +commit 03ae081aeaa118361c81ece76eb7cc1aaa2b40c5 +Author: Tim Rice +Date: Fri Feb 21 09:09:34 2014 -0800 + + 20140221 + - (tim) [configure.ac] Fix cut-and-paste error. Patch from Bryan Drewery. + +commit 4a20959d2e3c90e9d66897c0b4032c785672d815 +Author: Darren Tucker +Date: Thu Feb 13 16:38:32 2014 +1100 + + - (dtucker) [configure.ac openbsd-compat/openssl-compat.{c,h}] Add compat + code for older OpenSSL versions that don't have EVP_MD_CTX_copy_ex. + +commit d1a7a9c0fd1ac2e3314cceb2891959fd2cd9eabb +Author: Damien Miller +Date: Fri Feb 7 09:24:33 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/06 22:21:01 + [sshconnect.c] + in ssh_create_socket(), only do the getaddrinfo for BindAddress when + BindAddress is actually specified. Fixes regression in 6.5 for + UsePrivilegedPort=yes; patch from Corinna Vinschen + +commit 6ce35b6cc4ead1bf98abec34cb2e2d6ca0abb15e +Author: Damien Miller +Date: Fri Feb 7 09:24:14 2014 +1100 + + - naddy@cvs.openbsd.org 2014/02/05 20:13:25 + [ssh-keygen.1 ssh-keygen.c] + tweak synopsis: calling ssh-keygen without any arguments is fine; ok jmc@ + while here, fix ordering in usage(); requested by jmc@ + +commit 6434cb2cfbbf0a46375d2d22f2ff9927feb5e478 +Author: Damien Miller +Date: Thu Feb 6 11:17:50 2014 +1100 + + - (djm) [sandbox-seccomp-filter.c] Not all Linux architectures define + __NR_shutdown; some go via the socketcall(2) multiplexer. + +commit 8d36f9ac71eff2e9f5770c0518b73d875f270647 +Author: Darren Tucker +Date: Thu Feb 6 10:44:13 2014 +1100 + + - (dtucker) [openbsd-compat/bsd-poll.c] Don't bother checking for non-NULL + before freeing since free(NULL) is a no-op. ok djm. + +commit a0959da3680b4ce8cf911caf3293a6d90f88eeb7 +Author: Damien Miller +Date: Wed Feb 5 10:33:45 2014 +1100 + + - (djm) [sandbox-capsicum.c] Don't fatal if Capsicum is offered by + headers/libc but not supported by the kernel. Patch from Loganaden + Velvindron @ AfriNIC + +commit 9c449bc183b256c84d8f740727b0bc54d247b15e +Author: Damien Miller +Date: Tue Feb 4 11:38:28 2014 +1100 + + - (djm) [regress/setuid-allowed.c] Missing string.h for strerror() + +commit bf7e0f03be661b6f5b3bfe325135ce19391f9c4d +Author: Damien Miller +Date: Tue Feb 4 11:37:50 2014 +1100 + + - (djm) [openbsd-compat/Makefile.in] Add missing explicit_bzero.o + +commit eb6d870a0ea8661299bb2ea8f013d3ace04e2024 +Author: Damien Miller +Date: Tue Feb 4 11:26:34 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/04 00:24:29 + [ssh.c] + delay lowercasing of hostname until right before hostname + canonicalisation to unbreak case-sensitive matching of ssh_config; + reported by Ike Devolder; ok markus@ + +commit d56b44d2dfa093883a5c4e91be3f72d99946b170 +Author: Damien Miller +Date: Tue Feb 4 11:26:04 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/04 00:24:29 + [ssh.c] + delay lowercasing of hostname until right before hostname + canonicalisation to unbreak case-sensitive matching of ssh_config; + reported by Ike Devolder; ok markus@ + +commit db3c595ea74ea9ccd5aa644d7e1f8dc675710731 +Author: Damien Miller +Date: Tue Feb 4 11:25:45 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/02 03:44:31 + [digest-libc.c digest-openssl.c] + convert memset of potentially-private data to explicit_bzero() + +commit aae07e2e2000dd318418fd7fd4597760904cae32 +Author: Damien Miller +Date: Tue Feb 4 11:20:40 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/03 23:28:00 + [ssh-ecdsa.c] + fix memory leak; ECDSA_SIG_new() allocates 'r' and 's' for us, unlike + DSA_SIG_new. Reported by Batz Spear; ok markus@ + +commit a5103f413bde6f31bff85d6e1fd29799c647d765 +Author: Damien Miller +Date: Tue Feb 4 11:20:14 2014 +1100 + + - djm@cvs.openbsd.org 2014/02/02 03:44:32 + [auth1.c auth2-chall.c auth2-passwd.c authfile.c bufaux.c bufbn.c] + [buffer.c cipher-3des1.c cipher.c clientloop.c gss-serv.c kex.c] + [kexdhc.c kexdhs.c kexecdhc.c kexgexc.c kexecdhs.c kexgexs.c key.c] + [monitor.c monitor_wrap.c packet.c readpass.c rsa.c serverloop.c] + [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c] + [ssh-keygen.c ssh-rsa.c sshconnect.c sshconnect1.c sshconnect2.c] + [sshd.c] + convert memset of potentially-private data to explicit_bzero() + +commit 1d2c4564265ee827147af246a16f3777741411ed +Author: Damien Miller +Date: Tue Feb 4 11:18:20 2014 +1100 + + - tedu@cvs.openbsd.org 2014/01/31 16:39:19 + [auth2-chall.c authfd.c authfile.c bufaux.c bufec.c canohost.c] + [channels.c cipher-chachapoly.c clientloop.c configure.ac hostfile.c] + [kexc25519.c krl.c monitor.c sandbox-systrace.c session.c] + [sftp-client.c ssh-keygen.c ssh.c sshconnect2.c sshd.c sshlogin.c] + [openbsd-compat/explicit_bzero.c openbsd-compat/openbsd-compat.h] + replace most bzero with explicit_bzero, except a few that cna be memset + ok djm dtucker + +commit 3928de067c286683a95fbdbdb5fdb3c78a0e5efd +Author: Damien Miller +Date: Tue Feb 4 11:13:54 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/30 22:26:14 + [sandbox-systrace.c] + allow shutdown(2) syscall in sandbox - it may be called by packet_close() + from portable + (Id sync only; change is already in portable) + +commit e1e480aee8a9af6cfbe7188667b7b940d6b57f9f +Author: Damien Miller +Date: Tue Feb 4 11:13:17 2014 +1100 + + - jmc@cvs.openbsd.org 2014/01/29 14:04:51 + [sshd_config.5] + document kbdinteractiveauthentication; + requested From: Ross L Richardson + + dtucker/markus helped explain its workings; + +commit 7cc194f70d4a5ec9a82d19422eaf18db4a6624c6 +Author: Damien Miller +Date: Tue Feb 4 11:12:56 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/29 06:18:35 + [Makefile.in auth.h auth2-jpake.c auth2.c jpake.c jpake.h monitor.c] + [monitor.h monitor_wrap.c monitor_wrap.h readconf.c readconf.h] + [schnorr.c schnorr.h servconf.c servconf.h ssh2.h sshconnect2.c] + remove experimental, never-enabled JPAKE code; ok markus@ + +commit b0f26544cf6f4feeb1a4f6db09fca834f5c9867d +Author: Damien Miller +Date: Tue Feb 4 11:10:01 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/29 00:19:26 + [sshd.c] + use kill(0, ...) instead of killpg(0, ...); on most operating systems + they are equivalent, but SUSv2 describes the latter as having undefined + behaviour; from portable; ok dtucker + (Id sync only; change is already in portable) + +commit f8f35bc471500348bb262039fb1fc43175d251b0 +Author: Damien Miller +Date: Tue Feb 4 11:09:12 2014 +1100 + + - jmc@cvs.openbsd.org 2014/01/28 14:13:39 + [ssh-keyscan.1] + kill some bad Pa; + From: Jan Stary + +commit 0ba85d696ae9daf66002c2e4ab0d6bb111e1a787 +Author: Damien Miller +Date: Tue Feb 4 11:08:38 2014 +1100 + + ignore a few more regress droppings + +commit ec93d15170b7a6ddf63fd654bd0f6a752acc19dd +Author: Damien Miller +Date: Tue Feb 4 11:07:13 2014 +1100 + + - markus@cvs.openbsd.org 2014/01/27 20:13:46 + [digest.c digest-openssl.c digest-libc.c Makefile.in] + rename digest.c to digest-openssl.c and add libc variant; ok djm@ + +commit 4a1c7aa640fb97d3472d51b215b6a0ec0fd025c7 +Author: Damien Miller +Date: Tue Feb 4 11:03:36 2014 +1100 + + - markus@cvs.openbsd.org 2014/01/27 19:18:54 + [auth-rsa.c cipher.c ssh-agent.c sshconnect1.c sshd.c] + replace openssl MD5 with our ssh_digest_*; ok djm@ + +commit 4e8d937af79ce4e253f77ec93489d098b25becc3 +Author: Damien Miller +Date: Tue Feb 4 11:02:42 2014 +1100 + + - markus@cvs.openbsd.org 2014/01/27 18:58:14 + [Makefile.in digest.c digest.h hostfile.c kex.h mac.c hmac.c hmac.h] + replace openssl HMAC with an implementation based on our ssh_digest_* + ok and feedback djm@ + +commit 69d0d09f76bab5aec86fbf78489169f63bd16475 +Author: Tim Rice +Date: Fri Jan 31 14:25:18 2014 -0800 + + - (tim) [Makefile.in] build regress/setuid-allow. + +commit 0eeafcd76b972a3d159f3118227c149a4d7817fe +Author: Darren Tucker +Date: Fri Jan 31 14:18:51 2014 +1100 + + - (dtucker) [readconf.c] Include for the hton macros. Fixes + build with HP-UX's compiler. Patch from Kevin Brott. + +commit 7e5cec6070673e9f9785ffc749837ada22fbe99f +Author: Damien Miller +Date: Fri Jan 31 09:25:34 2014 +1100 + + - (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2) + syscall from sandboxes; it may be called by packet_close. + +commit cdb6c90811caa5df2df856be9b0b16db020fe31d +Author: Damien Miller +Date: Thu Jan 30 12:50:17 2014 +1100 + + - (djm) Release openssh-6.5p1 + +commit 996ea80b1884b676a901439f1f2681eb6ff68501 +Author: Damien Miller +Date: Thu Jan 30 12:49:55 2014 +1100 + + trim entries prior to openssh-6.0p1 + +commit f5bbd3b657b6340551c8a95f74a70857ff8fac79 +Author: Damien Miller +Date: Thu Jan 30 11:26:46 2014 +1100 + + - (djm) [configure.ac atomicio.c] Kludge around NetBSD offering + different symbols for 'read' when various compiler flags are + in use, causing atomicio.c comparisons against it to break and + read/write operations to hang; ok dtucker + +commit c2868192ddc4e1420a50389e18c05db20b0b1f32 +Author: Damien Miller +Date: Thu Jan 30 10:21:19 2014 +1100 + + - (djm) [configure.ac] Only check for width-specified integer types + in headers that actually exist. patch from Tom G. Christensen; + ok dtucker@ + +commit c161fc90fc86e2035710570238a9e1ca7a68d2a5 +Author: Damien Miller +Date: Wed Jan 29 21:01:33 2014 +1100 + + - (djm) [configure.ac] Fix broken shell test '==' vs '='; patch from + Tom G. Christensen + +commit 6f917ad376481995ab7d29fb53b08ec8d507eb9e +Author: Tim Rice +Date: Tue Jan 28 10:26:25 2014 -0800 + + - (tim) [regress/agent.sh regress/agent-ptrace.sh] Assign $? to a variable + when used as an error message inside an if statement so we display the + correct into. agent.sh patch from Petr Lautrbach. + +commit ab16ef4152914d44ce6f76e48167d26d22f66a06 +Author: Damien Miller +Date: Tue Jan 28 15:08:12 2014 +1100 + + - (djm) [sshd.c] Use kill(0, ...) instead of killpg(0, ...); the + latter being specified to have undefined behaviour in SUSv3; + ok dtucker + +commit ab0394905884dc6e58c3721211c6b38fb8fc2ca8 +Author: Damien Miller +Date: Tue Jan 28 15:07:10 2014 +1100 + + - (djm) [configure.ac] Search for inet_ntop in libnsl and libresovl; + ok dtucker + +commit 4ab20a82d4d4168d62318923f62382f6ef242fcd +Author: Darren Tucker +Date: Mon Jan 27 17:35:04 2014 +1100 + + - (dtucker) [Makefile.in] Remove trailing backslash which some make + implementations (eg older Solaris) do not cope with. + +commit e7e8b3cfe9f8665faaf0e68b33df5bbb431bd129 +Author: Darren Tucker +Date: Mon Jan 27 17:32:50 2014 +1100 + + Welcome to 2014 + +commit 5b447c0aac0dd444251e276f6bb3bbbe1c05331c +Author: Damien Miller +Date: Sun Jan 26 09:46:53 2014 +1100 + + - (djm) [configure.ac] correct AC_DEFINE for previous. + +commit 2035b2236d3b1f76c749c642a43e03c85eae76e6 +Author: Damien Miller +Date: Sun Jan 26 09:39:53 2014 +1100 + + - (djm) [configure.ac sandbox-capsicum.c sandbox-rlimit.c] Disable + RLIMIT_NOFILE pseudo-sandbox on FreeBSD. In some configurations, + libc will attempt to open additional file descriptors for crypto + offload and crash if they cannot be opened. + +commit a92ac7410475fbb00383c7402aa954dc0a75ae19 +Author: Damien Miller +Date: Sun Jan 26 09:38:03 2014 +1100 + + - markus@cvs.openbsd.org 2014/01/25 20:35:37 + [kex.c] + dh_need needs to be set to max(seclen, blocksize, ivlen, mac_len) + ok dtucker@, noted by mancha + +commit 76eea4ab4e658670ca6e76dd1e6d17f262208b57 +Author: Damien Miller +Date: Sun Jan 26 09:37:25 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/25 10:12:50 + [cipher.c cipher.h kex.c kex.h kexgexc.c] + Add a special case for the DH group size for 3des-cbc, which has an + effective strength much lower than the key size. This causes problems + with some cryptlib implementations, which don't support group sizes larger + than 4k but also don't use the largest group size it does support as + specified in the RFC. Based on a patch from Petr Lautrbach at Redhat, + reduced by me with input from Markus. ok djm@ markus@ + +commit 603b8f47f1cd9ed95a2017447db8e60ca6704594 +Author: Damien Miller +Date: Sat Jan 25 13:16:59 2014 +1100 + + - (djm) [configure.ac] autoconf sets finds to 'yes' not '1', so test + against the correct thing. + +commit c96d85376d779b6ac61525b5440010d344d2f23f +Author: Damien Miller +Date: Sat Jan 25 13:12:28 2014 +1100 + + - (djm) [configure.ac] Do not attempt to use capsicum sandbox unless + sys/capability.h exists and cap_rights_limit is in libc. Fixes + build on FreeBSD9x which provides the header but not the libc + support. + +commit f62ecef9939cb3dbeb10602fd705d4db3976d822 +Author: Damien Miller +Date: Sat Jan 25 12:34:38 2014 +1100 + + - (djm) [configure.ac] Fix detection of capsicum sandbox on FreeBSD + +commit b0e0f760b861676a3fe5c40133b270713d5321a9 +Author: Damien Miller +Date: Fri Jan 24 14:27:04 2014 +1100 + + - (djm) [Makefile.in regress/scp-ssh-wrapper.sh regress/scp.sh] Make + the scp regress test actually test the built scp rather than the one + in $PATH. ok dtucker@ + +commit 42a092530159637da9cb7f9e1b5f4679e34a85e6 +Author: Darren Tucker +Date: Thu Jan 23 23:14:39 2014 +1100 + + - (dtucker) [configure.ac] NetBSD's (and FreeBSD's) strnvis is gratuitously + incompatible with OpenBSD's despite post-dating it by more than a decade. + Declare it as broken, and document FreeBSD's as the same. ok djm@ + +commit 617da33c20cb59f9ea6c99c881d92493371ef7b8 +Author: Tim Rice +Date: Wed Jan 22 19:16:10 2014 -0800 + + - (tim) [session.c] Improve error reporting on set_id(). + +commit 5c2ff5e31f57d303ebb414d84a934c02728fa568 +Author: Damien Miller +Date: Wed Jan 22 21:30:12 2014 +1100 + + - (djm) [configure.ac aclocal.m4] More tests to detect fallout from + platform hardening options: include some long long int arithmatic + to detect missing support functions for -ftrapv in libgcc and + equivalents, actually test linking when -ftrapv is supplied and + set either both -pie/-fPIE or neither. feedback and ok dtucker@ + +commit 852472a54b8a0dc3e53786b313baaa86850a4273 +Author: Damien Miller +Date: Wed Jan 22 16:31:18 2014 +1100 + + - (djm) [configure.ac] Unless specifically requested, only attempt + to build Position Independent Executables on gcc >= 4.x; ok dtucker + +commit ee87838786cef0194db36ae0675b3e7c4e8ec661 +Author: Damien Miller +Date: Wed Jan 22 16:30:15 2014 +1100 + + - (djm) [openbsd-compat/setproctitle.c] Don't fail to compile if a + platform that is expected to use the reuse-argv style setproctitle + hack surprises us by providing a setproctitle in libc; ok dtucker + +commit 5c96a154c7940fa67b1f11c421e390dbbc159f27 +Author: Damien Miller +Date: Tue Jan 21 13:10:26 2014 +1100 + + - (djm) [aclocal.m4] Flesh out the code run in the OSSH_CHECK_CFLAG_COMPILE + and OSSH_CHECK_LDFLAG_LINK tests to give them a better chance of + detecting toolchain-related problems; ok dtucker + +commit 9464ba6fb34bb42eb3501ec3c5143662e75674bf +Author: Tim Rice +Date: Mon Jan 20 17:59:28 2014 -0800 + + - (tim) [platform.c session.c] Fix bug affecting SVR5 platforms introduced + with sftp chroot support. Move set_id call after chroot. + +commit a6d573caa14d490e6c42fb991bcb5c6860ec704b +Author: Darren Tucker +Date: Tue Jan 21 12:50:46 2014 +1100 + + - (dtucker) [aclocal.m4] Differentiate between compile-time and link-time + tests in the configure output. ok djm. + +commit 096118dc73ab14810b3c12785c0b5acb01ad6123 +Author: Darren Tucker +Date: Tue Jan 21 12:48:51 2014 +1100 + + - (dtucker) [configure.ac] Make PIE a configure-time option which defaults + to on platforms where it's known to be reliably detected and off elsewhere. + Works around platforms such as FreeBSD 9.1 where it does not interop with + -ftrapv (it seems to work but fails when trying to link ssh). ok djm@ + +commit f9df7f6f477792254eab33cdef71a6d66488cb88 +Author: Damien Miller +Date: Mon Jan 20 20:07:15 2014 +1100 + + - (djm) [regress/cert-hostkey.sh] Fix regress failure on platforms that + skip one or more key types (e.g. RHEL/CentOS 6.5); ok dtucker@ + +commit c74e70eb52ccc0082bd5a70b5798bb01c114d138 +Author: Darren Tucker +Date: Mon Jan 20 13:18:09 2014 +1100 + + - (dtucker) [gss-serv-krb5.c] Fall back to krb5_cc_gen_new if the Kerberos + implementation does not have krb5_cc_new_unique, similar to what we do + in auth-krb5.c. + +commit 3510979e83b6a18ec8773c64c3fa04aa08b2e783 +Author: Damien Miller +Date: Mon Jan 20 12:41:53 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/20 00:08:48 + [digest.c] + memleak; found by Loganaden Velvindron @ AfriNIC; ok markus@ + +commit 7eee358d7a6580479bee5cd7e52810ebfd03e5b2 +Author: Darren Tucker +Date: Sun Jan 19 22:37:02 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/19 11:21:51 + [addrmatch.c] + Cast the sizeof to socklen_t so it'll work even if the supplied len is + negative. Suggested by and ok djm, ok deraadt. + +commit b7e01c09b56ab26e8fac56bbce0fd25e36d12bb0 +Author: Darren Tucker +Date: Sun Jan 19 22:36:13 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/19 04:48:08 + [ssh_config.5] + fix inverted meaning of 'no' and 'yes' for CanonicalizeFallbackLocal + +commit 7b1ded04adce42efa25ada7c3a39818d3109b724 +Author: Darren Tucker +Date: Sun Jan 19 15:30:02 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/19 04:17:29 + [canohost.c addrmatch.c] + Cast socklen_t when comparing to size_t and use socklen_t to iterate over + the ip options, both to prevent signed/unsigned comparison warnings. + Patch from vinschen at redhat via portable openssh, begrudging ok deraadt. + +commit 293ee3c9f0796d99ebb033735f0e315f2e0180bf +Author: Darren Tucker +Date: Sun Jan 19 15:28:01 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/18 09:36:26 + [session.c] + explicitly define USE_PIPES to 1 to prevent redefinition warnings in + portable on platforms that use pipes for everything. From redhat @ + redhat. + +commit 2aca159d05f9e7880d1d8f1ce49a218840057f53 +Author: Darren Tucker +Date: Sun Jan 19 15:25:34 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/17 06:23:24 + [sftp-server.c] + fix log message statvfs. ok djm + +commit 841f7da89ae8b367bb502d61c5c41916c6e7ae4c +Author: Darren Tucker +Date: Sat Jan 18 22:12:15 2014 +1100 + + - (dtucker) [sandbox-capsicum.c] Correct some error messages and make the + return value check for cap_enter() consistent with the other uses in + FreeBSD. From by Loganaden Velvindron @ AfriNIC via bz#2140. + +commit fdce3731660699b2429e93e822f2ccbaccd163ae +Author: Darren Tucker +Date: Sat Jan 18 21:12:42 2014 +1100 + + - (dtucker) [configure.ac] On Cygwin the getopt variables (like optargs, + optind) are defined in getopt.h already. Unfortunately they are defined as + "declspec(dllimport)" for historical reasons, because the GNU linker didn't + allow auto-import on PE/COFF targets way back when. The problem is the + dllexport attributes collide with the definitions in the various source + files in OpenSSH, which obviousy define the variables without + declspec(dllimport). The least intrusive way to get rid of these warnings + is to disable warnings for GCC compiler attributes when building on Cygwin. + Patch from vinschen at redhat.com. + +commit 1411c9263f46e1ee49d0d302bf7258ebe69ce827 +Author: Darren Tucker +Date: Sat Jan 18 21:03:59 2014 +1100 + + - (dtucker) [openbsd-compat/bsd-cygwin_util.h] Add missing function + declarations that stopped being included when we stopped including + from openbsd-compat/bsd-cygwin_util.h. Patch from vinschen at + redhat.com. + +commit 89c532d843c95a085777c66365067d64d1937eb9 +Author: Darren Tucker +Date: Sat Jan 18 20:43:49 2014 +1100 + + - (dtucker) [uidswap.c] Prevent unused variable warnings on Cygwin. Patch + from vinschen at redhat.com + +commit 355f861022be7b23d3009fae8f3c9f6f7fc685f7 +Author: Darren Tucker +Date: Sat Jan 18 00:12:38 2014 +1100 + + - (dtucker) [defines.h] Move our definitions of uintXX_t types down to after + they're defined if we have to define them ourselves. Fixes builds on old + AIX. + +commit a3357661ee1d5d553294f36e4940e8285c7f1332 +Author: Darren Tucker +Date: Sat Jan 18 00:03:57 2014 +1100 + + - (dtucker) [readconf.c] Wrap paths.h inside an ifdef. Allows building on + Solaris. + +commit 9edcbff46ff01c8d5dee9c1aa843f09e9ad8a80e +Author: Darren Tucker +Date: Fri Jan 17 21:54:32 2014 +1100 + + - (dtucker) [configure.ac] Have --without-toolchain-hardening not turn off + stack-protector since that has a separate flag that's been around a while. + +commit 6d725687c490d4ba957a1bbc0ba0a2956c09fa69 +Author: Darren Tucker +Date: Fri Jan 17 19:17:34 2014 +1100 + + - (dtucker) [configure.ac] Also look in inttypes.h for uintXX_t types. + +commit 5055699c7f7c7ef21703a443ec73117da392f6ae +Author: Darren Tucker +Date: Fri Jan 17 18:48:22 2014 +1100 + + - (dtucker) [openbsd-compat/bsd-statvfs.h] Only start including headers if we + need them to cut down on the name collisions. + +commit a5cf1e220def07290260e4125e74f41ac75cf88d +Author: Darren Tucker +Date: Fri Jan 17 18:10:58 2014 +1100 + + - (dtucker) [configure.ac openbsd-compat/bsd-statvfs.c + openbsd-compat/bsd-statvfs.h] Implement enough of statvfs on top of statfs + to be useful (and for the regression tests to pass) on platforms that + have statfs and fstatfs. ok djm@ + +commit 1357d71d7b6d269969520aaa3e84d312ec971d5b +Author: Darren Tucker +Date: Fri Jan 17 18:00:40 2014 +1100 + + - (dtucker) Fix typo in #ifndef. + +commit d23a91ffb289d3553a58b7a60cec39fba9f0f506 +Author: Darren Tucker +Date: Fri Jan 17 17:32:30 2014 +1100 + + - (dtucker) [configure.ac digest.c openbsd-compat/openssl-compat.c + openbsd-compat/openssl-compat.h] Add compatibility layer for older + openssl versions. ok djm@ + +commit 868ea1ea1c1bfdbee5dbad78f81999c5983ecf31 +Author: Damien Miller +Date: Fri Jan 17 16:47:04 2014 +1100 + + - (djm) [Makefile.in configure.ac sandbox-capsicum.c sandbox-darwin.c] + [sandbox-null.c sandbox-rlimit.c sandbox-seccomp-filter.c] + [sandbox-systrace.c ssh-sandbox.h sshd.c] Support preauth sandboxing + using the Capsicum API introduced in FreeBSD 10. Patch by Dag-Erling + Smorgrav, updated by Loganaden Velvindron @ AfriNIC; ok dtucker@ + +commit a9d186a8b50d18869a10e9203abf71c83ddb1f79 +Author: Darren Tucker +Date: Fri Jan 17 16:30:49 2014 +1100 + + - dtucker@cvs.openbsd.org 2014/01/17 05:26:41 + [digest.c] + remove unused includes. ok djm@ + +commit 5f1c57a7a7eb39c0e4fee3367712337dbcaef024 +Author: Darren Tucker +Date: Fri Jan 17 16:29:45 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/17 00:21:06 + [sftp-client.c] + signed/unsigned comparison warning fix; from portable (Id sync only) + +commit c548722361d89fb12c108528f96b306a26477b18 +Author: Darren Tucker +Date: Fri Jan 17 15:12:16 2014 +1100 + + - (dtucker) [configure.ac] Split AC_CHECK_FUNCS for OpenSSL functions into + separate lines and alphabetize for easier diffing of changes. + +commit acad351a5b1c37de9130c9c1710445cc45a7f6b9 +Author: Darren Tucker +Date: Fri Jan 17 14:20:05 2014 +1100 + + - (dtucker) [defines.h] Add typedefs for uintXX_t types for platforms that + don't have them. + +commit c3ed065ce8417aaa46490836648c173a5010f226 +Author: Darren Tucker +Date: Fri Jan 17 14:18:45 2014 +1100 + + - (dtucker) [openbsd-compat/bcrypt_pbkdf.c] Wrap stdlib.h include inside + #ifdef HAVE_STDINT_H. + +commit f45f78ae437062c7d9506c5f475b7215f486be44 +Author: Darren Tucker +Date: Fri Jan 17 12:43:43 2014 +1100 + + - (dtucker) [blocks.c fe25519.c ge25519.c hash.c sc25519.c verify.c] Include + includes.h to pull in all of the compatibility stuff. + +commit 99df369d0340caac145d57f700d830147ff18b87 +Author: Darren Tucker +Date: Fri Jan 17 12:42:17 2014 +1100 + + - (dtucker) [poly1305.c] Wrap stdlib.h include inside #ifdef HAVE_STDINT_H. + +commit ac413b62ea1957e80c711acbe0c11b908273fc01 +Author: Darren Tucker +Date: Fri Jan 17 12:31:33 2014 +1100 + + - (dtucker) [crypto_api.h] Wrap stdlib.h include inside #ifdef HAVE_STDINT_H. + +commit 1c4a011e9c939e74815346a560843e1862c300b8 +Author: Darren Tucker +Date: Fri Jan 17 12:23:23 2014 +1100 + + - (dtucker) [loginrec.c] Cast to the types specfied in the format + specification to prevent warnings. + +commit c3d483f9a8275be1113535a1e0d0e384f605f3c4 +Author: Damien Miller +Date: Fri Jan 17 11:20:26 2014 +1100 + + - (djm) [sftp-client.c] signed/unsigned comparison fix + +commit fd994379dd972417d0491767f7cd9b5bf23f4975 +Author: Darren Tucker +Date: Fri Jan 17 09:53:24 2014 +1100 + + - (dtucker) [aclocal.m4 configure.ac] Add some additional compiler/toolchain + hardening flags including -fstack-protector-strong. These default to on + if the toolchain supports them, but there is a configure-time knob + (--without-hardening) to disable them if necessary. ok djm@ + +commit 366224d21768ee8ec28cfbcc5fbade1b32582d58 +Author: Damien Miller +Date: Thu Jan 16 18:51:44 2014 +1100 + + - (djm) [README] update release notes URL. + +commit 2ae77e64f8fa82cbf25c9755e8e847709b978b40 +Author: Damien Miller +Date: Thu Jan 16 18:51:07 2014 +1100 + + - (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec] + [contrib/suse/openssh.spec] Crank RPM spec version numbers. + +commit 0fa29e6d777c73a1b4ddd3b996b06ee20022ae8a +Author: Damien Miller +Date: Thu Jan 16 18:42:31 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/16 07:32:00 + [version.h] + openssh-6.5 + +commit 52c371cd6d2598cc73d4e633811b3012119c47e2 +Author: Damien Miller +Date: Thu Jan 16 18:42:10 2014 +1100 + + - djm@cvs.openbsd.org 2014/01/16 07:31:09 + [sftp-client.c] + needless and incorrect cast to size_t can break resumption of + large download; patch from tobias@ diff --git a/crypto/openssh/FREEBSD-upgrade b/crypto/openssh/FREEBSD-upgrade index 11f9bda..7acd51f 100644 --- a/crypto/openssh/FREEBSD-upgrade +++ b/crypto/openssh/FREEBSD-upgrade @@ -1,5 +1,4 @@ - FreeBSD maintainer's guide to OpenSSH-portable ============================================== @@ -34,10 +33,11 @@ 07) Tag: $ svn copy -m "Tag OpenSSH X.YpZ." \ - svn+ssh://svn.freebsd.org/base/vendor-crypto/openssh/dist \ - svn+ssh://svn.freebsd.org/base/vendor-crypto/openssh/X.YpZ + svn+ssh://svn.freebsd.org/base/vendor-crypto/openssh/dist \ + svn+ssh://svn.freebsd.org/base/vendor-crypto/openssh/X.YpZ -08) Check out head and run the pre-merge script: +08) Check out head and run the pre-merge script, which strips our RCS + tags from files that have them: $ svn co svn+ssh://svn.freebsd.org/base/head $ cd head/crypto/openssh @@ -53,14 +53,16 @@ 0B) Diff against the vendor branch: - $ svn diff \^/vendor-crypto/openssh/dist . + $ svn diff --no-diff-deleted --no-diff-added \ + --ignore-properties \^/vendor-crypto/openssh/X.YpZ . Files that have modifications relative to the vendor code, and only those files, must have the svn:keywords property set to FreeBSD=%H and be listed in the 'keywords' file created by the pre-merge script. -0C) Run the post-merge script: +0C) Run the post-merge script, which re-adds RCS tags to files that + need them: $ sh freebsd-post-merge.sh @@ -68,7 +70,7 @@ $ sh freebsd-configure.sh -0E) Check config.h very carefully. +0E) Review changes to config.h very carefully. 0F) If source files have been added or removed, update the appropriate makefiles to reflect changes in the vendor's Makefile.in. @@ -92,8 +94,6 @@ An overview of FreeBSD changes to OpenSSH-portable ================================================== -XXX This section is out of date - 0) VersionAddendum The SSH protocol allows for a human-readable version string of up @@ -103,26 +103,29 @@ XXX This section is out of date is vulnerable when an OpenSSH advisory goes out. Some people, however, dislike advertising their patch level in the protocol handshake, so we've added a VersionAddendum configuration variable - to allow them to change or disable it. + to allow them to change or disable it. Upstream added support for + VersionAddendum on the server side, but we also support it on the + client side. 1) Modified server-side defaults We've modified some configuration defaults in sshd: - - PasswordAuthentication defaults to "no". - - - LoginGraceTime defaults to 120 seconds instead of 600. - + - UsePAM defaults to "yes". - PermitRootLogin defaults to "no". - - - X11Forwarding defaults to "yes" (it's a threat to the client, - not to the server.) + - X11Forwarding defaults to "yes". + - PasswordAuthentication defaults to "no". + - VersionAddendum defaults to "FreeBSD-YYYYMMDD". + - PrivilegeSeparation defaults to "sandbox". + - UseDNS defaults to "yes". 2) Modified client-side defaults We've modified some configuration defaults in ssh: - CheckHostIP defaults to "no". + - VerifyHostKeyDNS defaults to "yes" if built with LDNS. + - VersionAddendum defaults to "FreeBSD-YYYYMMDD". 3) Canonic host names @@ -135,6 +138,34 @@ XXX This section is out of date Our setusercontext(3) can set environment variables, which we must take care to transfer to the child's environment. +5) TCP wrappers + + Support for TCP wrappers was removed in upstream 6.7p1. We've + added it back by porting the 6.6p1 code forward. + +6) DSA keys + + DSA keys were disabled by default in upstream 6.9p1. We've added + them back. + +7) Agent client reference counting + + We've added code to ssh-agent.c to implement client reference + counting; the agent will automatically exit when the last client + disconnects. + +8) Class-based login restrictions + + We've added code to auth2.c to enforce the host.allow, host.deny, + times.allow and times.deny login class capabilities. + +9) HPN + + We no longer have the HPN patches (adaptive buffer size for + increased throughput on high-BxD links), but we recognize and + ignore HPN-related configuration options to avoid breaking existing + configurations. + This port was brought to you by (in no particular order) DARPA, NAI diff --git a/crypto/openssh/INSTALL b/crypto/openssh/INSTALL index 5767230..3dfe08d 100644 --- a/crypto/openssh/INSTALL +++ b/crypto/openssh/INSTALL @@ -1,22 +1,26 @@ 1. Prerequisites ---------------- -You will need working installations of Zlib and OpenSSL. +You will need working installations of Zlib and libcrypto (LibreSSL / +OpenSSL) Zlib 1.1.4 or 1.2.1.2 or greater (ealier 1.2.x versions have problems): http://www.gzip.org/zlib/ -OpenSSL 0.9.6 or greater: -http://www.openssl.org/ +libcrypto (LibreSSL or OpenSSL >= 0.9.8f) +LibreSSL http://www.libressl.org/ ; or +OpenSSL http://www.openssl.org/ -(OpenSSL 0.9.5a is partially supported, but some ciphers (SSH protocol 1 -Blowfish) do not work correctly.) +LibreSSL/OpenSSL should be compiled as a position-independent library +(i.e. with -fPIC) otherwise OpenSSH will not be able to link with it. +If you must use a non-position-independent libcrypto, then you may need +to configure OpenSSH --without-pie. The remaining items are optional. NB. If you operating system supports /dev/random, you should configure -OpenSSL to use it. OpenSSH relies on OpenSSL's direct support of -/dev/random, or failing that, either prngd or egd +libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto's +direct support of /dev/random, or failing that, either prngd or egd PRNGD: @@ -27,10 +31,10 @@ http://prngd.sourceforge.net/ EGD: -The Entropy Gathering Daemon (EGD) is supported if you have a system which -lacks /dev/random and don't want to use OpenSSH's internal entropy collection. +If the kernel lacks /dev/random the Entropy Gathering Daemon (EGD) is +supported only if libcrypto supports it. -http://www.lothar.com/tech/crypto/ +http://egd.sourceforge.net/ PAM: @@ -204,10 +208,11 @@ created. --with-xauth=PATH specifies the location of the xauth binary ---with-ssl-dir=DIR allows you to specify where your OpenSSL libraries +--with-ssl-dir=DIR allows you to specify where your Libre/OpenSSL +libraries are installed. ---with-ssl-engine enables OpenSSL's (hardware) ENGINE support +--with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support --with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to real (AF_INET) IPv4 addresses. Works around some quirks on Linux. @@ -266,4 +271,4 @@ Please refer to the "reporting bugs" section of the webpage at http://www.openssh.com/ -$Id: INSTALL,v 1.88 2013/03/07 01:33:35 dtucker Exp $ +$Id: INSTALL,v 1.91 2014/09/09 02:23:11 dtucker Exp $ diff --git a/crypto/openssh/Makefile.in b/crypto/openssh/Makefile.in index 28a8ec4..40cc7aa 100644 --- a/crypto/openssh/Makefile.in +++ b/crypto/openssh/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.356 2014/02/04 00:12:56 djm Exp $ +# $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@ @@ -29,6 +29,7 @@ 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@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ @@ -63,20 +64,34 @@ MANFMT=@MANFMT@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) -LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ - canohost.o channels.o cipher.o cipher-aes.o \ +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 compress.o crc32.o deattack.o fatal.o hostfile.o \ - log.o match.o md-sha256.o moduli.o nchan.o packet.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 kex.o mac.o uidswap.o uuencode.o misc.o \ + atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ - kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ - ssh-pkcs11.o krl.o smult_curve25519_ref.o \ - kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ - ssh-ed25519.o digest-openssl.o hmac.o \ - sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.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 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect1.o sshconnect2.o mux.o \ @@ -89,8 +104,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ auth-chall.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_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ - kexc25519s.o auth-krb5.o \ + monitor_mm.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 \ @@ -135,7 +149,7 @@ $(SSHOBJS): Makefile.in config.h $(SSHDOBJS): Makefile.in config.h .c.o: - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ LIBCOMPAT=openbsd-compat/libopenbsd-compat.a $(LIBCOMPAT): always @@ -214,6 +228,18 @@ umac128.o: umac.c 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/hostkeys/*.o + rm -f regress/unittests/hostkeys/test_hostkeys + rm -f regress/unittests/kex/*.o + rm -f regress/unittests/kex/test_kex (cd openbsd-compat && $(MAKE) clean) distclean: regressclean @@ -222,6 +248,18 @@ distclean: regressclean 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/hostkeys/*.o + rm -f regress/unittests/hostkeys/test_hostkeys + rm -f regress/unittests/kex/*.o + rm -f regress/unittests/kex/test_kex (cd openbsd-compat && $(MAKE) distclean) if test -d pkg ; then \ rm -fr pkg ; \ @@ -394,23 +432,116 @@ uninstall: -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 -regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c - [ -d `pwd`/regress ] || mkdir -p `pwd`/regress - [ -f `pwd`/regress/Makefile ] || \ +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/hostkeys ] || \ + mkdir -p `pwd`/regress/unittests/hostkeys + [ -d `pwd`/regress/unittests/kex ] || \ + mkdir -p `pwd`/regress/unittests/kex + [ -f `pwd`/regress/Makefile ] || \ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile + +regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c - [ -d `pwd`/regress ] || mkdir -p `pwd`/regress - [ -f `pwd`/regress/Makefile ] || \ - ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) -tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$(EXEEXT) +regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ + $(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_KEX_OBJS=\ + regress/unittests/kex/tests.o \ + regress/unittests/kex/test_kex.o \ + roaming_dummy.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) + +REGRESS_BINARIES=\ + regress/modpipe$(EXEEXT) \ + regress/setuid-allowed$(EXEEXT) \ + regress/netcat$(EXEEXT) \ + regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ + regress/unittests/sshkey/test_sshkey$(EXEEXT) \ + regress/unittests/bitmap/test_bitmap$(EXEEXT) \ + regress/unittests/hostkeys/test_hostkeys$(EXEEXT) \ + regress/unittests/kex/test_kex$(EXEEXT) + +tests interop-tests t-exec: regress-prep $(TARGETS) $(REGRESS_BINARIES) BUILDDIR=`pwd`; \ - TEST_SHELL="@TEST_SHELL@"; \ TEST_SSH_SCP="$${BUILDDIR}/scp"; \ TEST_SSH_SSH="$${BUILDDIR}/ssh"; \ TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \ @@ -434,7 +565,6 @@ tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$ OBJ="$${BUILDDIR}/regress/" \ PATH="$${BUILDDIR}:$${PATH}" \ TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ - TEST_SHELL="$${TEST_SHELL}" \ TEST_SSH_SCP="$${TEST_SSH_SCP}" \ TEST_SSH_SSH="$${TEST_SSH_SSH}" \ TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \ @@ -450,6 +580,7 @@ tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$ TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \ TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \ TEST_SSH_ECC="$${TEST_SSH_ECC}" \ + TEST_SHELL="${TEST_SHELL}" \ EXEEXT="$(EXEEXT)" \ $@ && echo all tests passed diff --git a/crypto/openssh/OVERVIEW b/crypto/openssh/OVERVIEW index 2e1cc0b..fde72c8 100644 --- a/crypto/openssh/OVERVIEW +++ b/crypto/openssh/OVERVIEW @@ -65,8 +65,8 @@ these programs. packets. CRC code comes from crc32.c. - The code in packet.c calls the buffer manipulation routines - (buffer.c, bufaux.c), compression routines (compress.c, zlib), - and the encryption routines. + (buffer.c, bufaux.c), compression routines (zlib), and the + encryption routines. X11, TCP/IP, and Agent forwarding @@ -165,4 +165,4 @@ these programs. uidswap.c uid-swapping xmalloc.c "safe" malloc routines -$OpenBSD: OVERVIEW,v 1.11 2006/08/03 03:34:41 deraadt Exp $ +$OpenBSD: OVERVIEW,v 1.12 2015/07/08 19:01:15 markus Exp $ diff --git a/crypto/openssh/PROTOCOL b/crypto/openssh/PROTOCOL index 4a5088f..131adfe 100644 --- a/crypto/openssh/PROTOCOL +++ b/crypto/openssh/PROTOCOL @@ -40,8 +40,8 @@ http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt "ecdsa-sha2-nistp521-cert-v01@openssh.com" OpenSSH introduces new public key algorithms to support certificate -authentication for users and hostkeys. These methods are documented in -the file PROTOCOL.certkeys +authentication for users and host keys. These methods are documented +in the file PROTOCOL.certkeys 1.4. transport: Elliptic Curve cryptography @@ -175,7 +175,7 @@ whitelisted to receive this message upon request. OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com" channel type. This channel type supports forwarding of network packets -with datagram boundaries intact between endpoints equipped with +with datagram boundaries intact between endpoints equipped with interfaces like the BSD tun(4) device. Tunnel forwarding channels are requested by the client with the following packet: @@ -232,6 +232,102 @@ The contents of the "data" field for layer 2 packets is: The "frame" field contains an IEEE 802.3 Ethernet frame, including header. +2.4. connection: Unix domain socket forwarding + +OpenSSH supports local and remote Unix domain socket forwarding +using the "streamlocal" extension. Forwarding is initiated as per +TCP sockets but with a single path instead of a host and port. + +Similar to direct-tcpip, direct-streamlocal is sent by the client +to request that the server make a connection to a Unix domain socket. + + byte SSH_MSG_CHANNEL_OPEN + string "direct-streamlocal@openssh.com" + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + string socket path + +Similar to forwarded-tcpip, forwarded-streamlocal is sent by the +server when the client has previously send the server a streamlocal-forward +GLOBAL_REQUEST. + + byte SSH_MSG_CHANNEL_OPEN + string "forwarded-streamlocal@openssh.com" + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + string socket path + string reserved for future use + +The reserved field is not currently defined and is ignored on the +remote end. It is intended to be used in the future to pass +information about the socket file, such as ownership and mode. +The client currently sends the empty string for this field. + +Similar to tcpip-forward, streamlocal-forward is sent by the client +to request remote forwarding of a Unix domain socket. + + byte SSH2_MSG_GLOBAL_REQUEST + string "streamlocal-forward@openssh.com" + boolean TRUE + string socket path + +Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent +by the client cancel the forwarding of a Unix domain socket. + + byte SSH2_MSG_GLOBAL_REQUEST + string "cancel-streamlocal-forward@openssh.com" + boolean FALSE + string socket path + +2.5. connection: hostkey update and rotation "hostkeys-00@openssh.com" +and "hostkeys-prove-00@openssh.com" + +OpenSSH supports a protocol extension allowing a server to inform +a client of all its protocol v.2 host keys after user-authentication +has completed. + + byte SSH_MSG_GLOBAL_REQUEST + string "hostkeys-00@openssh.com" + string[] hostkeys + +Upon receiving this message, a client should check which of the +supplied host keys are present in known_hosts. For keys that are +not present, it should send a "hostkeys-prove@openssh.com" message +to request the server prove ownership of the private half of the +key. + + byte SSH_MSG_GLOBAL_REQUEST + string "hostkeys-prove-00@openssh.com" + char 1 /* want-reply */ + string[] hostkeys + +When a server receives this message, it should generate a signature +using each requested key over the following: + + string "hostkeys-prove-00@openssh.com" + string session identifier + string hostkey + +These signatures should be included in the reply, in the order matching +the hostkeys in the request: + + byte SSH_MSG_REQUEST_SUCCESS + string[] signatures + +When the client receives this reply (and not a failure), it should +validate the signatures and may update its known_hosts file, adding keys +that it has not seen before and deleting keys for the server host that +are no longer offered. + +These extensions let a client learn key types that it had not previously +encountered, thereby allowing it to potentially upgrade from weaker +key algorithms to better ones. It also supports graceful key rotation: +a server may offer multiple keys of the same type for a period (to +give clients an opportunity to learn them using this extension) before +removing the deprecated key from those offered. + 3. SFTP protocol changes 3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK @@ -356,4 +452,4 @@ respond with a SSH_FXP_STATUS message. This extension is advertised in the SSH_FXP_VERSION hello with version "1". -$OpenBSD: PROTOCOL,v 1.23 2013/12/01 23:19:05 djm Exp $ +$OpenBSD: PROTOCOL,v 1.29 2015/07/17 03:09:19 djm Exp $ diff --git a/crypto/openssh/PROTOCOL.agent b/crypto/openssh/PROTOCOL.agent index 3fcaa14..27ec0c1 100644 --- a/crypto/openssh/PROTOCOL.agent +++ b/crypto/openssh/PROTOCOL.agent @@ -413,7 +413,7 @@ It may be requested using this message: "rsa_e" and "rsa_n" are used to identify which private key to use. "encrypted_challenge" is a challenge blob that has (presumably) -been encrypted with the public key and must be in the range +been encrypted with the public key and must be in the range 1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1 session ID (computed from the server host key, the server semi-ephemeral key and the session cookie). @@ -557,4 +557,4 @@ Locking and unlocking affects both protocol 1 and protocol 2 keys. SSH_AGENT_CONSTRAIN_LIFETIME 1 SSH_AGENT_CONSTRAIN_CONFIRM 2 -$OpenBSD: PROTOCOL.agent,v 1.7 2013/01/02 00:33:49 djm Exp $ +$OpenBSD: PROTOCOL.agent,v 1.8 2015/05/08 03:56:51 djm Exp $ diff --git a/crypto/openssh/PROTOCOL.krl b/crypto/openssh/PROTOCOL.krl index e8caa45..b969510 100644 --- a/crypto/openssh/PROTOCOL.krl +++ b/crypto/openssh/PROTOCOL.krl @@ -37,7 +37,7 @@ The available section types are: #define KRL_SECTION_FINGERPRINT_SHA1 3 #define KRL_SECTION_SIGNATURE 4 -3. Certificate serial section +2. Certificate section These sections use type KRL_SECTION_CERTIFICATES to revoke certificates by serial number or key ID. The consist of the CA key that issued the @@ -47,6 +47,11 @@ ignored. string ca_key string reserved +Where "ca_key" is the standard SSH wire serialisation of the CA's +public key. Alternately, "ca_key" may be an empty string to indicate +the certificate section applies to all CAs (this is most useful when +revoking key IDs). + Followed by one or more sections: byte cert_section_type @@ -161,4 +166,4 @@ Implementations that retrieve KRLs over untrusted channels must verify signatures. Signature sections are optional for KRLs distributed by trusted means. -$OpenBSD: PROTOCOL.krl,v 1.2 2013/01/18 00:24:58 djm Exp $ +$OpenBSD: PROTOCOL.krl,v 1.3 2015/01/30 01:10:33 djm Exp $ diff --git a/crypto/openssh/PROTOCOL.mux b/crypto/openssh/PROTOCOL.mux index b583256..f042961 100644 --- a/crypto/openssh/PROTOCOL.mux +++ b/crypto/openssh/PROTOCOL.mux @@ -116,6 +116,12 @@ A client may request the master to establish a port forward: forwarding type may be MUX_FWD_LOCAL, MUX_FWD_REMOTE, MUX_FWD_DYNAMIC. +If listen port is (unsigned int) -2, then the listen host is treated as +a unix socket path name. + +If connect port is (unsigned int) -2, then the connect host is treated +as a unix socket path name. + A server may reply with a MUX_S_OK, a MUX_S_REMOTE_PORT, a MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE. @@ -219,4 +225,4 @@ XXX inject packet (what about replies) XXX server->client error/warning notifications XXX send signals via mux -$OpenBSD: PROTOCOL.mux,v 1.9 2012/06/01 00:49:35 djm Exp $ +$OpenBSD: PROTOCOL.mux,v 1.10 2015/07/17 03:04:27 djm Exp $ diff --git a/crypto/openssh/README b/crypto/openssh/README index 368dca5..ea6e228 100644 --- a/crypto/openssh/README +++ b/crypto/openssh/README @@ -1,4 +1,8 @@ -See http://www.openssh.com/txt/release-6.6 for the release notes. +See http://www.openssh.com/txt/release-7.1p2 for the release notes. + +Please read http://www.openssh.com/report.html for bug reporting +instructions and note that we do not use Github for bug reporting or +patch/pull-request management. - A Japanese translation of this document and of the OpenSSH FAQ is - available at http://www.unixuser.org/~haruyama/security/openssh/index.html @@ -62,4 +66,4 @@ References - [6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9 [7] http://www.openssh.com/faq.html -$Id: README,v 1.86 2014/02/27 23:03:53 djm Exp $ +$Id: README,v 1.87 2014/08/10 01:35:06 djm Exp $ diff --git a/crypto/openssh/addrmatch.c b/crypto/openssh/addrmatch.c index c443146..70b050e 100644 --- a/crypto/openssh/addrmatch.c +++ b/crypto/openssh/addrmatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: addrmatch.c,v 1.9 2014/01/19 11:21:51 dtucker Exp $ */ +/* $OpenBSD: addrmatch.c,v 1.10 2015/07/08 19:04:21 markus Exp $ */ /* * Copyright (c) 2004-2008 Damien Miller @@ -31,7 +31,6 @@ #include "match.h" #include "log.h" -#include "xmalloc.h" struct xaddr { sa_family_t af; diff --git a/crypto/openssh/atomicio.c b/crypto/openssh/atomicio.c index 2bac36c..b1ec234 100644 --- a/crypto/openssh/atomicio.c +++ b/crypto/openssh/atomicio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atomicio.c,v 1.26 2010/09/22 22:58:51 djm Exp $ */ +/* $OpenBSD: atomicio.c,v 1.27 2015/01/16 06:40:12 deraadt Exp $ */ /* * Copyright (c) 2006 Damien Miller. All rights reserved. * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. @@ -41,6 +41,7 @@ #endif #include #include +#include #include "atomicio.h" diff --git a/crypto/openssh/auth-bsdauth.c b/crypto/openssh/auth-bsdauth.c index 0b3262b..37ff893 100644 --- a/crypto/openssh/auth-bsdauth.c +++ b/crypto/openssh/auth-bsdauth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-bsdauth.c,v 1.11 2007/09/21 08:15:29 djm Exp $ */ +/* $OpenBSD: auth-bsdauth.c,v 1.13 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -26,6 +26,8 @@ #include "includes.h" #include +#include +#include #include @@ -54,6 +56,11 @@ bsdauth_query(void *ctx, char **name, char **infotxt, Authctxt *authctxt = ctx; char *challenge = NULL; + *infotxt = NULL; + *numprompts = 0; + *prompts = NULL; + *echo_on = NULL; + if (authctxt->as != NULL) { debug2("bsdauth_query: try reuse session"); challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); diff --git a/crypto/openssh/auth-chall.c b/crypto/openssh/auth-chall.c index 0005aa8..60c9f14 100644 --- a/crypto/openssh/auth-chall.c +++ b/crypto/openssh/auth-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-chall.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -26,14 +26,16 @@ #include "includes.h" #include - #include +#include +#include #include "xmalloc.h" #include "key.h" #include "hostfile.h" #include "auth.h" #include "log.h" +#include "misc.h" #include "servconf.h" /* limited protocol v1 interface to kbd-interactive authentication */ diff --git a/crypto/openssh/auth-krb5.c b/crypto/openssh/auth-krb5.c index b97fcf1..0089b18 100644 --- a/crypto/openssh/auth-krb5.c +++ b/crypto/openssh/auth-krb5.c @@ -2,7 +2,7 @@ /* * Kerberos v5 authentication and ticket-passing routines. * - * $FreeBSD$ + * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $ */ /* * Copyright (c) 2002 Daniel Kouril. All rights reserved. @@ -40,6 +40,7 @@ #include "packet.h" #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" #include "uidswap.h" #include "key.h" diff --git a/crypto/openssh/auth-options.c b/crypto/openssh/auth-options.c index fa209ea..e387697 100644 --- a/crypto/openssh/auth-options.c +++ b/crypto/openssh/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.62 2013/12/19 00:27:57 djm Exp $ */ +/* $OpenBSD: auth-options.c,v 1.68 2015/07/03 03:43:18 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -21,15 +21,19 @@ #include #include "openbsd-compat/sys-queue.h" + +#include "key.h" /* XXX for typedef */ +#include "buffer.h" /* XXX for typedef */ #include "xmalloc.h" #include "match.h" +#include "ssherr.h" #include "log.h" #include "canohost.h" -#include "buffer.h" +#include "sshbuf.h" +#include "misc.h" #include "channels.h" #include "servconf.h" -#include "misc.h" -#include "key.h" +#include "sshkey.h" #include "auth-options.h" #include "hostfile.h" #include "auth.h" @@ -205,8 +209,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) goto next_option; } cp = "environment=\""; - if (options.permit_user_env && - strncasecmp(opts, cp, strlen(cp)) == 0) { + if (strncasecmp(opts, cp, strlen(cp)) == 0) { char *s; struct envstring *new_envstring; @@ -232,13 +235,19 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) goto bad_option; } s[i] = '\0'; - auth_debug_add("Adding to environment: %.900s", s); - debug("Adding to environment: %.900s", s); opts++; - new_envstring = xcalloc(1, sizeof(struct envstring)); - new_envstring->s = s; - new_envstring->next = custom_environment; - custom_environment = new_envstring; + if (options.permit_user_env) { + auth_debug_add("Adding to environment: " + "%.900s", s); + debug("Adding to environment: %.900s", s); + new_envstring = xcalloc(1, + sizeof(*new_envstring)); + new_envstring->s = s; + new_envstring->next = custom_environment; + custom_environment = new_envstring; + s = NULL; + } + free(s); goto next_option; } cp = "from=\""; @@ -325,6 +334,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) patterns[i] = '\0'; opts++; p = patterns; + /* XXX - add streamlocal support */ host = hpdelim(&p); if (host == NULL || strlen(host) >= NI_MAXHOST) { debug("%.100s, line %lu: Bad permitopen " @@ -416,7 +426,7 @@ bad_option: #define OPTIONS_CRITICAL 1 #define OPTIONS_EXTENSIONS 2 static int -parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, +parse_option_list(struct sshbuf *oblob, struct passwd *pw, u_int which, int crit, int *cert_no_port_forwarding_flag, int *cert_no_agent_forwarding_flag, @@ -429,26 +439,25 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, char *command, *allowed; const char *remote_ip; char *name = NULL; - u_char *data_blob = NULL; - u_int nlen, dlen, clen; - Buffer c, data; - int ret = -1, result, found; - - buffer_init(&data); + struct sshbuf *c = NULL, *data = NULL; + int r, ret = -1, result, found; - /* Make copy to avoid altering original */ - buffer_init(&c); - buffer_append(&c, optblob, optblob_len); + if ((c = sshbuf_fromb(oblob)) == NULL) { + error("%s: sshbuf_fromb failed", __func__); + goto out; + } - while (buffer_len(&c) > 0) { - if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL || - (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { - error("Certificate options corrupt"); + while (sshbuf_len(c) > 0) { + sshbuf_free(data); + data = NULL; + if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 || + (r = sshbuf_froms(c, &data)) != 0) { + error("Unable to parse certificate options: %s", + ssh_err(r)); goto out; } - buffer_append(&data, data_blob, dlen); - debug3("found certificate option \"%.100s\" len %u", - name, dlen); + debug3("found certificate option \"%.100s\" len %zu", + name, sshbuf_len(data)); found = 0; if ((which & OPTIONS_EXTENSIONS) != 0) { if (strcmp(name, "permit-X11-forwarding") == 0) { @@ -472,10 +481,10 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, } if (!found && (which & OPTIONS_CRITICAL) != 0) { if (strcmp(name, "force-command") == 0) { - if ((command = buffer_get_cstring_ret(&data, - &clen)) == NULL) { - error("Certificate constraint \"%s\" " - "corrupt", name); + if ((r = sshbuf_get_cstring(data, &command, + NULL)) != 0) { + error("Unable to parse \"%s\" " + "section: %s", name, ssh_err(r)); goto out; } if (*cert_forced_command != NULL) { @@ -488,10 +497,10 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, found = 1; } if (strcmp(name, "source-address") == 0) { - if ((allowed = buffer_get_cstring_ret(&data, - &clen)) == NULL) { - error("Certificate constraint " - "\"%s\" corrupt", name); + if ((r = sshbuf_get_cstring(data, &allowed, + NULL)) != 0) { + error("Unable to parse \"%s\" " + "section: %s", name, ssh_err(r)); goto out; } if ((*cert_source_address_done)++) { @@ -539,16 +548,13 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, logit("Certificate extension \"%s\" " "is not supported", name); } - } else if (buffer_len(&data) != 0) { + } else if (sshbuf_len(data) != 0) { error("Certificate option \"%s\" corrupt " "(extra data)", name); goto out; } - buffer_clear(&data); free(name); - free(data_blob); name = NULL; - data_blob = NULL; } /* successfully parsed all options */ ret = 0; @@ -562,10 +568,8 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, } if (name != NULL) free(name); - if (data_blob != NULL) - free(data_blob); - buffer_free(&data); - buffer_free(&c); + sshbuf_free(data); + sshbuf_free(c); return ret; } @@ -574,7 +578,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, * options so this must be called after auth_parse_options(). */ int -auth_cert_options(Key *k, struct passwd *pw) +auth_cert_options(struct sshkey *k, struct passwd *pw) { int cert_no_port_forwarding_flag = 1; int cert_no_agent_forwarding_flag = 1; @@ -584,38 +588,21 @@ auth_cert_options(Key *k, struct passwd *pw) char *cert_forced_command = NULL; int cert_source_address_done = 0; - if (key_cert_is_legacy(k)) { - /* All options are in the one field for v00 certs */ - if (parse_option_list(buffer_ptr(&k->cert->critical), - buffer_len(&k->cert->critical), pw, - OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, - &cert_no_port_forwarding_flag, - &cert_no_agent_forwarding_flag, - &cert_no_x11_forwarding_flag, - &cert_no_pty_flag, - &cert_no_user_rc, - &cert_forced_command, - &cert_source_address_done) == -1) - return -1; - } else { - /* Separate options and extensions for v01 certs */ - if (parse_option_list(buffer_ptr(&k->cert->critical), - buffer_len(&k->cert->critical), pw, - OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, - &cert_forced_command, - &cert_source_address_done) == -1) - return -1; - if (parse_option_list(buffer_ptr(&k->cert->extensions), - buffer_len(&k->cert->extensions), pw, - OPTIONS_EXTENSIONS, 1, - &cert_no_port_forwarding_flag, - &cert_no_agent_forwarding_flag, - &cert_no_x11_forwarding_flag, - &cert_no_pty_flag, - &cert_no_user_rc, - NULL, NULL) == -1) - return -1; - } + /* Separate options and extensions for v01 certs */ + if (parse_option_list(k->cert->critical, pw, + OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, + &cert_forced_command, + &cert_source_address_done) == -1) + return -1; + if (parse_option_list(k->cert->extensions, pw, + OPTIONS_EXTENSIONS, 0, + &cert_no_port_forwarding_flag, + &cert_no_agent_forwarding_flag, + &cert_no_x11_forwarding_flag, + &cert_no_pty_flag, + &cert_no_user_rc, + NULL, NULL) == -1) + return -1; no_port_forwarding_flag |= cert_no_port_forwarding_flag; no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; diff --git a/crypto/openssh/auth-options.h b/crypto/openssh/auth-options.h index 7455c94..34852e5 100644 --- a/crypto/openssh/auth-options.h +++ b/crypto/openssh/auth-options.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.h,v 1.20 2010/05/07 11:30:29 djm Exp $ */ +/* $OpenBSD: auth-options.h,v 1.21 2015/01/14 10:30:34 markus Exp $ */ /* * Author: Tatu Ylonen @@ -35,6 +35,6 @@ extern char *authorized_principals; int auth_parse_options(struct passwd *, char *, char *, u_long); void auth_clear_options(void); -int auth_cert_options(Key *, struct passwd *); +int auth_cert_options(struct sshkey *, struct passwd *); #endif diff --git a/crypto/openssh/auth-pam.c b/crypto/openssh/auth-pam.c index d789bad..d94c828 100644 --- a/crypto/openssh/auth-pam.c +++ b/crypto/openssh/auth-pam.c @@ -738,7 +738,7 @@ sshpam_query(void *ctx, char **name, char **info, case PAM_PROMPT_ECHO_OFF: *num = 1; len = plen + mlen + 1; - **prompts = xrealloc(**prompts, 1, len); + **prompts = xreallocarray(**prompts, 1, len); strlcpy(**prompts + plen, msg, len - plen); plen += mlen; **echo_on = (type == PAM_PROMPT_ECHO_ON); @@ -748,7 +748,7 @@ sshpam_query(void *ctx, char **name, char **info, case PAM_TEXT_INFO: /* accumulate messages */ len = plen + mlen + 2; - **prompts = xrealloc(**prompts, 1, len); + **prompts = xreallocarray(**prompts, 1, len); strlcpy(**prompts + plen, msg, len - plen); plen += mlen; strlcat(**prompts + plen, "\n", len - plen); diff --git a/crypto/openssh/auth-passwd.c b/crypto/openssh/auth-passwd.c index 68bbd18..63ccf3c 100644 --- a/crypto/openssh/auth-passwd.c +++ b/crypto/openssh/auth-passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */ +/* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -48,6 +48,7 @@ #include "packet.h" #include "buffer.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "key.h" #include "hostfile.h" diff --git a/crypto/openssh/auth-rh-rsa.c b/crypto/openssh/auth-rh-rsa.c index b21a0f4..2e20396 100644 --- a/crypto/openssh/auth-rh-rsa.c +++ b/crypto/openssh/auth-rh-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -15,6 +15,8 @@ #include "includes.h" +#ifdef WITH_SSH1 + #include #include @@ -24,6 +26,7 @@ #include "uidswap.h" #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" #include "key.h" #include "hostfile.h" @@ -101,3 +104,5 @@ auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key) packet_send_debug("Rhosts with RSA host authentication accepted."); return 1; } + +#endif /* WITH_SSH1 */ diff --git a/crypto/openssh/auth-rhosts.c b/crypto/openssh/auth-rhosts.c index 06ae7f0..ee9e827 100644 --- a/crypto/openssh/auth-rhosts.c +++ b/crypto/openssh/auth-rhosts.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */ +/* $OpenBSD: auth-rhosts.c,v 1.46 2014/12/23 22:42:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,12 +34,12 @@ #include "uidswap.h" #include "pathnames.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "canohost.h" #include "key.h" #include "hostfile.h" #include "auth.h" -#include "misc.h" /* import */ extern ServerOptions options; @@ -57,7 +57,8 @@ check_rhosts_file(const char *filename, const char *hostname, const char *server_user) { FILE *f; - char buf[1024]; /* Must not be larger than host, user, dummy below. */ +#define RBUFLN 1024 + char buf[RBUFLN];/* Must not be larger than host, user, dummy below. */ int fd; struct stat st; @@ -80,8 +81,9 @@ check_rhosts_file(const char *filename, const char *hostname, return 0; } while (fgets(buf, sizeof(buf), f)) { - /* All three must be at least as big as buf to avoid overflows. */ - char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp; + /* All three must have length >= buf to avoid overflows. */ + char hostbuf[RBUFLN], userbuf[RBUFLN], dummy[RBUFLN]; + char *host, *user, *cp; int negated; for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) @@ -140,8 +142,8 @@ check_rhosts_file(const char *filename, const char *hostname, /* Check for empty host/user names (particularly '+'). */ if (!host[0] || !user[0]) { /* We come here if either was '+' or '-'. */ - auth_debug_add("Ignoring wild host/user names in %.100s.", - filename); + auth_debug_add("Ignoring wild host/user names " + "in %.100s.", filename); continue; } /* Verify that host name matches. */ @@ -149,7 +151,8 @@ check_rhosts_file(const char *filename, const char *hostname, if (!innetgr(host + 1, hostname, NULL, NULL) && !innetgr(host + 1, ipaddr, NULL, NULL)) continue; - } else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0) + } else if (strcasecmp(host, hostname) && + strcmp(host, ipaddr) != 0) continue; /* Different hostname. */ /* Verify that user name matches. */ @@ -208,7 +211,8 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam /* Switch to the user's uid. */ temporarily_use_uid(pw); /* - * Quick check: if the user has no .shosts or .rhosts files, return + * Quick check: if the user has no .shosts or .rhosts files and + * no system hosts.equiv/shosts.equiv files exist then return * failure immediately without doing costly lookups from name * servers. */ @@ -223,27 +227,38 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam /* Switch back to privileged uid. */ restore_uid(); - /* Deny if The user has no .shosts or .rhosts file and there are no system-wide files. */ + /* + * Deny if The user has no .shosts or .rhosts file and there + * are no system-wide files. + */ if (!rhosts_files[rhosts_file_index] && stat(_PATH_RHOSTS_EQUIV, &st) < 0 && - stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0) + stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0) { + debug3("%s: no hosts access files exist", __func__); return 0; + } - /* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */ - if (pw->pw_uid != 0) { + /* + * If not logging in as superuser, try /etc/hosts.equiv and + * shosts.equiv. + */ + if (pw->pw_uid == 0) + debug3("%s: root user, ignoring system hosts files", __func__); + else { if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, client_user, pw->pw_name)) { - auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.", - hostname, ipaddr); + auth_debug_add("Accepted for %.100s [%.100s] by " + "/etc/hosts.equiv.", hostname, ipaddr); return 1; } if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr, client_user, pw->pw_name)) { - auth_debug_add("Accepted for %.100s [%.100s] by %.100s.", - hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); + auth_debug_add("Accepted for %.100s [%.100s] by " + "%.100s.", hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); return 1; } } + /* * Check that the home directory is owned by root or the user, and is * not group or world writable. @@ -290,20 +305,25 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam auth_debug_add("Bad file modes for %.200s", buf); continue; } - /* Check if we have been configured to ignore .rhosts and .shosts files. */ + /* + * Check if we have been configured to ignore .rhosts + * and .shosts files. + */ if (options.ignore_rhosts) { - auth_debug_add("Server has been configured to ignore %.100s.", - rhosts_files[rhosts_file_index]); + auth_debug_add("Server has been configured to " + "ignore %.100s.", rhosts_files[rhosts_file_index]); continue; } /* Check if authentication is permitted by the file. */ - if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) { + if (check_rhosts_file(buf, hostname, ipaddr, + client_user, pw->pw_name)) { auth_debug_add("Accepted by %.100s.", rhosts_files[rhosts_file_index]); /* Restore the privileged uid. */ restore_uid(); - auth_debug_add("Accepted host %s ip %s client_user %s server_user %s", - hostname, ipaddr, client_user, pw->pw_name); + auth_debug_add("Accepted host %s ip %s client_user " + "%s server_user %s", hostname, ipaddr, + client_user, pw->pw_name); return 1; } } diff --git a/crypto/openssh/auth-rsa.c b/crypto/openssh/auth-rsa.c index 5dad6c3..cbd971b 100644 --- a/crypto/openssh/auth-rsa.c +++ b/crypto/openssh/auth-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rsa.c,v 1.86 2014/01/27 19:18:54 markus Exp $ */ +/* $OpenBSD: auth-rsa.c,v 1.90 2015/01/28 22:36:00 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -16,6 +16,8 @@ #include "includes.h" +#ifdef WITH_SSH1 + #include #include @@ -35,6 +37,7 @@ #include "buffer.h" #include "pathnames.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "key.h" #include "auth-options.h" @@ -45,7 +48,6 @@ #endif #include "monitor_wrap.h" #include "ssh.h" -#include "misc.h" #include "digest.h" @@ -144,7 +146,8 @@ auth_rsa_challenge_dialog(Key *key) challenge = PRIVSEP(auth_rsa_generate_challenge(key)); /* Encrypt the challenge with the public key. */ - rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); + if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0) + fatal("%s: rsa_public_encrypt failed", __func__); /* Send the encrypted challenge to the client. */ packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); @@ -235,7 +238,9 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, "actual %d vs. announced %d.", file, linenum, BN_num_bits(key->rsa->n), bits); - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + continue; debug("matching key found: file %s, line %lu %s %s", file, linenum, key_type(key), fp); free(fp); @@ -340,3 +345,5 @@ auth_rsa(Authctxt *authctxt, BIGNUM *client_n) packet_send_debug("RSA authentication accepted."); return (1); } + +#endif /* WITH_SSH1 */ diff --git a/crypto/openssh/auth.c b/crypto/openssh/auth.c index a085de4..ba908801 100644 --- a/crypto/openssh/auth.c +++ b/crypto/openssh/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.103 2013/05/19 02:42:42 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.113 2015/08/21 03:42:19 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -28,7 +28,6 @@ __RCSID("$FreeBSD$"); #include #include -#include #include @@ -51,12 +50,14 @@ __RCSID("$FreeBSD$"); #include #include #include +#include #include "xmalloc.h" #include "match.h" #include "groupaccess.h" #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" #include "key.h" #include "hostfile.h" @@ -64,7 +65,6 @@ __RCSID("$FreeBSD$"); #include "auth-options.h" #include "canohost.h" #include "uidswap.h" -#include "misc.h" #include "packet.h" #include "loginrec.h" #ifdef GSSAPI @@ -72,7 +72,8 @@ __RCSID("$FreeBSD$"); #endif #include "authfile.h" #include "monitor_wrap.h" -#include "krl.h" +#include "authfile.h" +#include "ssherr.h" #include "compat.h" /* import */ @@ -327,6 +328,21 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, #endif } + +void +auth_maxtries_exceeded(Authctxt *authctxt) +{ + error("maximum authentication attempts exceeded for " + "%s%.100s from %.200s port %d %s", + authctxt->valid ? "" : "invalid user ", + authctxt->user, + get_remote_ipaddr(), + get_remote_port(), + compat20 ? "ssh2" : "ssh1"); + packet_disconnect("Too many authentication failures"); + /* NOTREACHED */ +} + /* * Check whether root logins are disallowed. */ @@ -337,7 +353,9 @@ auth_root_allowed(const char *method) case PERMIT_YES: return 1; case PERMIT_NO_PASSWD: - if (strcmp(method, "password") != 0) + if (strcmp(method, "publickey") == 0 || + strcmp(method, "hostbased") == 0 || + strcmp(method, "gssapi-with-mic") == 0) return 1; break; case PERMIT_FORCED_ONLY: @@ -362,7 +380,7 @@ auth_root_allowed(const char *method) char * expand_authorized_keys(const char *filename, struct passwd *pw) { - char *file, ret[MAXPATHLEN]; + char *file, ret[PATH_MAX]; int i; file = percent_expand(filename, "h", pw->pw_dir, @@ -385,8 +403,7 @@ expand_authorized_keys(const char *filename, struct passwd *pw) char * authorized_principals_file(struct passwd *pw) { - if (options.authorized_principals_file == NULL || - strcasecmp(options.authorized_principals_file, "none") == 0) + if (options.authorized_principals_file == NULL) return NULL; return expand_authorized_keys(options.authorized_principals_file, pw); } @@ -454,7 +471,7 @@ int auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, uid_t uid, char *err, size_t errlen) { - char buf[MAXPATHLEN], homedir[MAXPATHLEN]; + char buf[PATH_MAX], homedir[PATH_MAX]; char *cp; int comparehome = 0; struct stat st; @@ -660,39 +677,39 @@ getpwnamallow(const char *user) int auth_key_is_revoked(Key *key) { - char *key_fp; + char *fp = NULL; + int r; if (options.revoked_keys_file == NULL) return 0; - switch (ssh_krl_file_contains_key(options.revoked_keys_file, key)) { - case 0: - return 0; /* Not revoked */ - case -2: - break; /* Not a KRL */ - default: - goto revoked; + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + error("%s: fingerprint key: %s", __func__, ssh_err(r)); + goto out; } - debug3("%s: treating %s as a key list", __func__, - options.revoked_keys_file); - switch (key_in_file(key, options.revoked_keys_file, 0)) { + + r = sshkey_check_revoked(key, options.revoked_keys_file); + switch (r) { case 0: - /* key not revoked */ - return 0; - case -1: - /* Error opening revoked_keys_file: refuse all keys */ - error("Revoked keys file is unreadable: refusing public key " - "authentication"); - return 1; - case 1: - revoked: - /* Key revoked */ - key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - error("WARNING: authentication attempt with a revoked " - "%s key %s ", key_type(key), key_fp); - free(key_fp); - return 1; + break; /* not revoked */ + case SSH_ERR_KEY_REVOKED: + error("Authentication key %s %s revoked by file %s", + sshkey_type(key), fp, options.revoked_keys_file); + goto out; + default: + error("Error checking authentication key %s %s in " + "revoked keys file %s: %s", sshkey_type(key), fp, + options.revoked_keys_file, ssh_err(r)); + goto out; } - fatal("key_in_file returned junk"); + + /* Success */ + r = 0; + + out: + free(fp); + return r == 0 ? 0 : 1; } void diff --git a/crypto/openssh/auth.h b/crypto/openssh/auth.h index 124e597..8b27575 100644 --- a/crypto/openssh/auth.h +++ b/crypto/openssh/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.77 2014/01/29 06:18:35 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.84 2015/05/08 06:41:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -42,6 +42,9 @@ #include #endif +struct ssh; +struct sshkey; + typedef struct Authctxt Authctxt; typedef struct Authmethod Authmethod; typedef struct KbdintDevice KbdintDevice; @@ -53,7 +56,7 @@ struct Authctxt { int valid; /* user exists and is allowed to login */ int attempt; int failures; - int server_caused_failure; + int server_caused_failure; int force_pwchange; char *user; /* username sent by the client */ char *service; @@ -75,6 +78,9 @@ struct Authctxt { #endif Buffer *loginmsg; void *methoddata; + + struct sshkey **prev_userkeys; + u_int nprev_userkeys; }; /* * Every authentication method has to handle authentication requests for @@ -120,9 +126,11 @@ int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); -int user_key_allowed(struct passwd *, Key *); +int user_key_allowed(struct passwd *, Key *, int); void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) __attribute__((__format__ (printf, 3, 4))); +void auth2_record_userkey(Authctxt *, struct sshkey *); +int auth2_userkey_already_used(Authctxt *, struct sshkey *); struct stat; int auth_secure_path(const char *, struct stat *, const char *, uid_t, @@ -154,6 +162,7 @@ void auth_info(Authctxt *authctxt, const char *, ...) __attribute__((__format__ (printf, 2, 3))) __attribute__((__nonnull__ (2))); void auth_log(Authctxt *, int, int, const char *, const char *); +void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn)); void userauth_finish(Authctxt *, int, const char *, const char *); int auth_root_allowed(const char *); @@ -194,12 +203,13 @@ check_key_in_hostfiles(struct passwd *, Key *, const char *, /* hostkey handling */ Key *get_hostkey_by_index(int); -Key *get_hostkey_public_by_index(int); -Key *get_hostkey_public_by_type(int); -Key *get_hostkey_private_by_type(int); -int get_hostkey_index(Key *); +Key *get_hostkey_public_by_index(int, struct ssh *); +Key *get_hostkey_public_by_type(int, int, struct ssh *); +Key *get_hostkey_private_by_type(int, int, struct ssh *); +int get_hostkey_index(Key *, int, struct ssh *); int ssh1_session_key(BIGNUM *); -void sshd_hostkey_sign(Key *, Key *, u_char **, u_int *, u_char *, u_int); +int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, + const u_char *, size_t, u_int); /* debug messages during authentication */ void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); @@ -210,8 +220,6 @@ struct passwd *fakepw(void); int sys_auth_passwd(Authctxt *, const char *); -#define AUTH_FAIL_MSG "Too many authentication failures for %.100s" - #define SKEY_PROMPT "\nS/Key Password: " #if defined(KRB5) && !defined(HEIMDAL) diff --git a/crypto/openssh/auth1.c b/crypto/openssh/auth1.c index 0f870b3..5073c49 100644 --- a/crypto/openssh/auth1.c +++ b/crypto/openssh/auth1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth1.c,v 1.80 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -12,6 +12,8 @@ #include "includes.h" +#ifdef WITH_SSH1 + #include #include @@ -27,6 +29,7 @@ #include "packet.h" #include "buffer.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "compat.h" #include "key.h" @@ -363,7 +366,7 @@ do_authloop(Authctxt *authctxt) #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); #endif - packet_disconnect(AUTH_FAIL_MSG, authctxt->user); + auth_maxtries_exceeded(authctxt); } packet_start(SSH_SMSG_FAILURE); @@ -437,3 +440,5 @@ do_authentication(Authctxt *authctxt) packet_send(); packet_write_wait(); } + +#endif /* WITH_SSH1 */ diff --git a/crypto/openssh/auth2-chall.c b/crypto/openssh/auth2-chall.c index 791be5c..4aff09d 100644 --- a/crypto/openssh/auth2-chall.c +++ b/crypto/openssh/auth2-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-chall.c,v 1.41 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: auth2-chall.c,v 1.43 2015/07/18 07:57:14 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. @@ -41,6 +41,7 @@ #include "packet.h" #include "dispatch.h" #include "log.h" +#include "misc.h" #include "servconf.h" /* import */ @@ -48,7 +49,7 @@ extern ServerOptions options; static int auth2_challenge_start(Authctxt *); static int send_userauth_info_request(Authctxt *); -static void input_userauth_info_response(int, u_int32_t, void *); +static int input_userauth_info_response(int, u_int32_t, void *); #ifdef BSD_AUTH extern KbdintDevice bsdauth_device; @@ -283,7 +284,7 @@ send_userauth_info_request(Authctxt *authctxt) return 1; } -static void +static int input_userauth_info_response(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; @@ -348,6 +349,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt) } userauth_finish(authctxt, authenticated, "keyboard-interactive", devicename); + return 0; } void diff --git a/crypto/openssh/auth2-gss.c b/crypto/openssh/auth2-gss.c index c28a705..1ca8357 100644 --- a/crypto/openssh/auth2-gss.c +++ b/crypto/openssh/auth2-gss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-gss.c,v 1.21 2014/02/26 20:28:44 djm Exp $ */ +/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -40,6 +40,7 @@ #include "log.h" #include "dispatch.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" #include "packet.h" #include "ssh-gss.h" @@ -47,10 +48,10 @@ extern ServerOptions options; -static void input_gssapi_token(int type, u_int32_t plen, void *ctxt); -static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); -static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); -static void input_gssapi_errtok(int, u_int32_t, void *); +static int input_gssapi_token(int type, u_int32_t plen, void *ctxt); +static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt); +static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); +static int input_gssapi_errtok(int, u_int32_t, void *); /* * We only support those mechanisms that we know about (ie ones that we know @@ -125,7 +126,7 @@ userauth_gssapi(Authctxt *authctxt) return (0); } -static void +static int input_gssapi_token(int type, u_int32_t plen, void *ctxt) { Authctxt *authctxt = ctxt; @@ -177,9 +178,10 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) } gss_release_buffer(&min_status, &send_tok); + return 0; } -static void +static int input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) { Authctxt *authctxt = ctxt; @@ -211,6 +213,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) /* The client will have already moved on to the next auth */ gss_release_buffer(&maj_status, &send_tok); + return 0; } /* @@ -219,7 +222,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) * which only enables it once the GSSAPI exchange is complete. */ -static void +static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) { Authctxt *authctxt = ctxt; @@ -243,9 +246,10 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + return 0; } -static void +static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt) { Authctxt *authctxt = ctxt; @@ -283,6 +287,7 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + return 0; } Authmethod method_gssapi = { diff --git a/crypto/openssh/auth2-hostbased.c b/crypto/openssh/auth2-hostbased.c index 488008f..e2327cf 100644 --- a/crypto/openssh/auth2-hostbased.c +++ b/crypto/openssh/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.17 2013/12/30 23:52:27 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.25 2015/05/04 06:10:48 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -36,6 +36,7 @@ #include "packet.h" #include "buffer.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "compat.h" #include "key.h" @@ -47,6 +48,7 @@ #endif #include "monitor_wrap.h" #include "pathnames.h" +#include "match.h" /* import */ extern ServerOptions options; @@ -106,6 +108,13 @@ userauth_hostbased(Authctxt *authctxt) "signature format"); goto done; } + if (match_pattern_list(sshkey_ssh_name(key), + options.hostbased_key_types, 0) != 1) { + logit("%s: key type %s not in HostbasedAcceptedKeyTypes", + __func__, sshkey_type(key)); + goto done; + } + service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : authctxt->service; buffer_init(&b); @@ -162,7 +171,7 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, resolvedname = get_canonical_hostname(options.use_dns); ipaddr = get_remote_ipaddr(); - debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", + debug2("%s: chost %s resolvedname %s ipaddr %s", __func__, chost, resolvedname, ipaddr); if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { @@ -171,19 +180,27 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, } if (options.hostbased_uses_name_from_packet_only) { - if (auth_rhosts2(pw, cuser, chost, chost) == 0) + if (auth_rhosts2(pw, cuser, chost, chost) == 0) { + debug2("%s: auth_rhosts2 refused " + "user \"%.100s\" host \"%.100s\" (from packet)", + __func__, cuser, chost); return 0; + } lookup = chost; } else { if (strcasecmp(resolvedname, chost) != 0) logit("userauth_hostbased mismatch: " "client sends %s, but we resolve %s to %s", chost, ipaddr, resolvedname); - if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) + if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) { + debug2("%s: auth_rhosts2 refused " + "user \"%.100s\" host \"%.100s\" addr \"%.100s\"", + __func__, cuser, resolvedname, ipaddr); return 0; + } lookup = resolvedname; } - debug2("userauth_hostbased: access allowed by auth_rhosts2"); + debug2("%s: access allowed by auth_rhosts2", __func__); if (key_is_cert(key) && key_cert_check_authority(key, 1, 0, lookup, &reason)) { @@ -206,14 +223,17 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, if (host_status == HOST_OK) { if (key_is_cert(key)) { - fp = key_fingerprint(key->cert->signature_key, - SSH_FP_MD5, SSH_FP_HEX); + if ((fp = sshkey_fingerprint(key->cert->signature_key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); verbose("Accepted certificate ID \"%s\" signed by " "%s CA %s from %s@%s", key->cert->key_id, key_type(key->cert->signature_key), fp, cuser, lookup); } else { - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + if ((fp = sshkey_fingerprint(key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); verbose("Accepted %s public key %s from %s@%s", key_type(key), fp, cuser, lookup); } diff --git a/crypto/openssh/auth2-kbdint.c b/crypto/openssh/auth2-kbdint.c index c39bdc6..bf75c60 100644 --- a/crypto/openssh/auth2-kbdint.c +++ b/crypto/openssh/auth2-kbdint.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-kbdint.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -36,6 +36,7 @@ #include "auth.h" #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" /* import */ diff --git a/crypto/openssh/auth2-none.c b/crypto/openssh/auth2-none.c index c8c6c74..e71e221 100644 --- a/crypto/openssh/auth2-none.c +++ b/crypto/openssh/auth2-none.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-none.c,v 1.16 2010/06/25 08:46:17 djm Exp $ */ +/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -30,9 +30,10 @@ #include #include -#include #include #include +#include +#include #include "atomicio.h" #include "xmalloc.h" @@ -42,6 +43,7 @@ #include "packet.h" #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" #include "compat.h" #include "ssh2.h" diff --git a/crypto/openssh/auth2-passwd.c b/crypto/openssh/auth2-passwd.c index 707680c..b638e87 100644 --- a/crypto/openssh/auth2-passwd.c +++ b/crypto/openssh/auth2-passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-passwd.c,v 1.11 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -41,6 +41,7 @@ #include "ssh-gss.h" #endif #include "monitor_wrap.h" +#include "misc.h" #include "servconf.h" /* import */ diff --git a/crypto/openssh/auth2-pubkey.c b/crypto/openssh/auth2-pubkey.c index 0fd27bb..5aa319c 100644 --- a/crypto/openssh/auth2-pubkey.c +++ b/crypto/openssh/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.39 2013/12/30 23:52:27 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.53 2015/06/15 18:44:22 jsing Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -41,6 +41,7 @@ #include #include #include +#include #include "xmalloc.h" #include "ssh.h" @@ -48,6 +49,7 @@ #include "packet.h" #include "buffer.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "compat.h" #include "key.h" @@ -61,9 +63,11 @@ #include "ssh-gss.h" #endif #include "monitor_wrap.h" -#include "misc.h" #include "authfile.h" #include "match.h" +#include "ssherr.h" +#include "channels.h" /* XXX for session.h */ +#include "session.h" /* XXX for child_set_env(); refactor? */ /* import */ extern ServerOptions options; @@ -122,6 +126,17 @@ userauth_pubkey(Authctxt *authctxt) "signature scheme"); goto done; } + if (auth2_userkey_already_used(authctxt, key)) { + logit("refusing previously-used %s key", key_type(key)); + goto done; + } + if (match_pattern_list(sshkey_ssh_name(key), + options.pubkey_key_types, 0) != 1) { + logit("%s: key type %s not in PubkeyAcceptedKeyTypes", + __func__, sshkey_ssh_name(key)); + goto done; + } + if (have_sig) { sig = packet_get_string(&slen); packet_check_eom(); @@ -157,10 +172,14 @@ userauth_pubkey(Authctxt *authctxt) /* test for correct signature */ authenticated = 0; - if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && + if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) && PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) + buffer_len(&b))) == 1) { authenticated = 1; + /* Record the successful key to prevent reuse */ + auth2_record_userkey(authctxt, key); + key = NULL; /* Don't free below */ + } buffer_free(&b); free(sig); } else { @@ -175,7 +194,7 @@ userauth_pubkey(Authctxt *authctxt) * if a user is not allowed to login. is this an * issue? -markus */ - if (PRIVSEP(user_key_allowed(authctxt->pw, key))) { + if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) { packet_start(SSH2_MSG_USERAUTH_PK_OK); packet_put_string(pkalg, alen); packet_put_string(pkblob, blen); @@ -212,25 +231,310 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) } if (key_is_cert(key)) { - fp = key_fingerprint(key->cert->signature_key, - SSH_FP_MD5, SSH_FP_HEX); + fp = sshkey_fingerprint(key->cert->signature_key, + options.fingerprint_hash, SSH_FP_DEFAULT); auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", key_type(key), key->cert->key_id, (unsigned long long)key->cert->serial, - key_type(key->cert->signature_key), fp, + key_type(key->cert->signature_key), + fp == NULL ? "(null)" : fp, extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } else { - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - auth_info(authctxt, "%s %s%s%s", key_type(key), fp, + fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT); + auth_info(authctxt, "%s %s%s%s", key_type(key), + fp == NULL ? "(null)" : fp, extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } free(extra); } +/* + * Splits 's' into an argument vector. Handles quoted string and basic + * escape characters (\\, \", \'). Caller must free the argument vector + * and its members. + */ +static int +split_argv(const char *s, int *argcp, char ***argvp) +{ + int r = SSH_ERR_INTERNAL_ERROR; + int argc = 0, quote, i, j; + char *arg, **argv = xcalloc(1, sizeof(*argv)); + + *argvp = NULL; + *argcp = 0; + + for (i = 0; s[i] != '\0'; i++) { + /* Skip leading whitespace */ + if (s[i] == ' ' || s[i] == '\t') + continue; + + /* Start of a token */ + quote = 0; + if (s[i] == '\\' && + (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\')) + i++; + else if (s[i] == '\'' || s[i] == '"') + quote = s[i++]; + + argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); + arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); + argv[argc] = NULL; + + /* Copy the token in, removing escapes */ + for (j = 0; s[i] != '\0'; i++) { + if (s[i] == '\\') { + if (s[i + 1] == '\'' || + s[i + 1] == '\"' || + s[i + 1] == '\\') { + i++; /* Skip '\' */ + arg[j++] = s[i]; + } else { + /* Unrecognised escape */ + arg[j++] = s[i]; + } + } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) + break; /* done */ + else if (quote != 0 && s[i] == quote) + break; /* done */ + else + arg[j++] = s[i]; + } + if (s[i] == '\0') { + if (quote != 0) { + /* Ran out of string looking for close quote */ + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + break; + } + } + /* Success */ + *argcp = argc; + *argvp = argv; + argc = 0; + argv = NULL; + r = 0; + out: + if (argc != 0 && argv != NULL) { + for (i = 0; i < argc; i++) + free(argv[i]); + free(argv); + } + return r; +} + +/* + * Reassemble an argument vector into a string, quoting and escaping as + * necessary. Caller must free returned string. + */ +static char * +assemble_argv(int argc, char **argv) +{ + int i, j, ws, r; + char c, *ret; + struct sshbuf *buf, *arg; + + if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + + for (i = 0; i < argc; i++) { + ws = 0; + sshbuf_reset(arg); + for (j = 0; argv[i][j] != '\0'; j++) { + r = 0; + c = argv[i][j]; + switch (c) { + case ' ': + case '\t': + ws = 1; + r = sshbuf_put_u8(arg, c); + break; + case '\\': + case '\'': + case '"': + if ((r = sshbuf_put_u8(arg, '\\')) != 0) + break; + /* FALLTHROUGH */ + default: + r = sshbuf_put_u8(arg, c); + break; + } + if (r != 0) + fatal("%s: sshbuf_put_u8: %s", + __func__, ssh_err(r)); + } + if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || + (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || + (r = sshbuf_putb(buf, arg)) != 0 || + (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + } + if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) + fatal("%s: malloc failed", __func__); + memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); + ret[sshbuf_len(buf)] = '\0'; + sshbuf_free(buf); + sshbuf_free(arg); + return ret; +} + +/* + * Runs command in a subprocess. Returns pid on success and a FILE* to the + * subprocess' stdout or 0 on failure. + * NB. "command" is only used for logging. + */ +static pid_t +subprocess(const char *tag, struct passwd *pw, const char *command, + int ac, char **av, FILE **child) +{ + FILE *f; + struct stat st; + int devnull, p[2], i; + pid_t pid; + char *cp, errmsg[512]; + u_int envsize; + char **child_env; + + *child = NULL; + + debug3("%s: %s command \"%s\" running as %s", __func__, + tag, command, pw->pw_name); + + /* Verify the path exists and is safe-ish to execute */ + if (*av[0] != '/') { + error("%s path is not absolute", tag); + return 0; + } + temporarily_use_uid(pw); + if (stat(av[0], &st) < 0) { + error("Could not stat %s \"%s\": %s", tag, + av[0], strerror(errno)); + restore_uid(); + return 0; + } + if (auth_secure_path(av[0], &st, NULL, 0, + errmsg, sizeof(errmsg)) != 0) { + error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); + restore_uid(); + return 0; + } + + /* + * Run the command; stderr is left in place, stdout is the + * authorized_keys output. + */ + if (pipe(p) != 0) { + error("%s: pipe: %s", tag, strerror(errno)); + restore_uid(); + return 0; + } + + /* + * Don't want to call this in the child, where it can fatal() and + * run cleanup_exit() code. + */ + restore_uid(); + + switch ((pid = fork())) { + case -1: /* error */ + error("%s: fork: %s", tag, strerror(errno)); + close(p[0]); + close(p[1]); + return 0; + case 0: /* child */ + /* Prepare a minimal environment for the child. */ + envsize = 5; + child_env = xcalloc(sizeof(*child_env), envsize); + child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH); + child_set_env(&child_env, &envsize, "USER", pw->pw_name); + child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name); + child_set_env(&child_env, &envsize, "HOME", pw->pw_dir); + if ((cp = getenv("LANG")) != NULL) + child_set_env(&child_env, &envsize, "LANG", cp); + + for (i = 0; i < NSIG; i++) + signal(i, SIG_DFL); + + if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { + error("%s: open %s: %s", tag, _PATH_DEVNULL, + strerror(errno)); + _exit(1); + } + /* Keep stderr around a while longer to catch errors */ + if (dup2(devnull, STDIN_FILENO) == -1 || + dup2(p[1], STDOUT_FILENO) == -1) { + error("%s: dup2: %s", tag, strerror(errno)); + _exit(1); + } + closefrom(STDERR_FILENO + 1); + + /* Don't use permanently_set_uid() here to avoid fatal() */ + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { + error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, + strerror(errno)); + _exit(1); + } + if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) { + error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid, + strerror(errno)); + _exit(1); + } + /* stdin is pointed to /dev/null at this point */ + if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) { + error("%s: dup2: %s", tag, strerror(errno)); + _exit(1); + } + + execve(av[0], av, child_env); + error("%s exec \"%s\": %s", tag, command, strerror(errno)); + _exit(127); + default: /* parent */ + break; + } + + close(p[1]); + if ((f = fdopen(p[0], "r")) == NULL) { + error("%s: fdopen: %s", tag, strerror(errno)); + close(p[0]); + /* Don't leave zombie child */ + kill(pid, SIGTERM); + while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) + ; + return 0; + } + /* Success */ + debug3("%s: %s pid %ld", __func__, tag, (long)pid); + *child = f; + return pid; +} + +/* Returns 0 if pid exited cleanly, non-zero otherwise */ +static int +exited_cleanly(pid_t pid, const char *tag, const char *cmd) +{ + int status; + + while (waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) { + error("%s: waitpid: %s", tag, strerror(errno)); + return -1; + } + } + if (WIFSIGNALED(status)) { + error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); + return -1; + } else if (WEXITSTATUS(status) != 0) { + error("%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); + return -1; + } + return 0; +} + static int -match_principals_option(const char *principal_list, struct KeyCert *cert) +match_principals_option(const char *principal_list, struct sshkey_cert *cert) { char *result; u_int i; @@ -250,19 +554,13 @@ match_principals_option(const char *principal_list, struct KeyCert *cert) } static int -match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert) +process_principals(FILE *f, char *file, struct passwd *pw, + struct sshkey_cert *cert) { - FILE *f; char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts; u_long linenum = 0; u_int i; - temporarily_use_uid(pw); - debug("trying authorized principals file %s", file); - if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) { - restore_uid(); - return 0; - } while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { /* Skip leading whitespace. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) @@ -290,24 +588,128 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert) } for (i = 0; i < cert->nprincipals; i++) { if (strcmp(cp, cert->principals[i]) == 0) { - debug3("matched principal \"%.100s\" " - "from file \"%s\" on line %lu", - cert->principals[i], file, linenum); + debug3("%s:%lu: matched principal \"%.100s\"", + file == NULL ? "(command)" : file, + linenum, cert->principals[i]); if (auth_parse_options(pw, line_opts, file, linenum) != 1) continue; - fclose(f); - restore_uid(); return 1; } } } + return 0; +} + +static int +match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert) +{ + FILE *f; + int success; + + temporarily_use_uid(pw); + debug("trying authorized principals file %s", file); + if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) { + restore_uid(); + return 0; + } + success = process_principals(f, file, pw, cert); fclose(f); restore_uid(); - return 0; + return success; } /* + * Checks whether principal is allowed in output of command. + * returns 1 if the principal is allowed or 0 otherwise. + */ +static int +match_principals_command(struct passwd *user_pw, struct sshkey_cert *cert) +{ + FILE *f = NULL; + int ok, found_principal = 0; + struct passwd *pw; + int i, ac = 0, uid_swapped = 0; + pid_t pid; + char *tmp, *username = NULL, *command = NULL, **av = NULL; + void (*osigchld)(int); + + if (options.authorized_principals_command == NULL) + return 0; + if (options.authorized_principals_command_user == NULL) { + error("No user for AuthorizedPrincipalsCommand specified, " + "skipping"); + return 0; + } + + /* + * NB. all returns later this function should go via "out" to + * ensure the original SIGCHLD handler is restored properly. + */ + osigchld = signal(SIGCHLD, SIG_DFL); + + /* Prepare and verify the user for the command */ + username = percent_expand(options.authorized_principals_command_user, + "u", user_pw->pw_name, (char *)NULL); + pw = getpwnam(username); + if (pw == NULL) { + error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s", + username, strerror(errno)); + goto out; + } + + /* Turn the command into an argument vector */ + if (split_argv(options.authorized_principals_command, &ac, &av) != 0) { + error("AuthorizedPrincipalsCommand \"%s\" contains " + "invalid quotes", command); + goto out; + } + if (ac == 0) { + error("AuthorizedPrincipalsCommand \"%s\" yielded no arguments", + command); + goto out; + } + for (i = 1; i < ac; i++) { + tmp = percent_expand(av[i], + "u", user_pw->pw_name, + "h", user_pw->pw_dir, + (char *)NULL); + if (tmp == NULL) + fatal("%s: percent_expand failed", __func__); + free(av[i]); + av[i] = tmp; + } + /* Prepare a printable command for logs, etc. */ + command = assemble_argv(ac, av); + + if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command, + ac, av, &f)) == 0) + goto out; + + uid_swapped = 1; + temporarily_use_uid(pw); + + ok = process_principals(f, NULL, pw, cert); + + if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0) + goto out; + + /* Read completed successfully */ + found_principal = ok; + out: + if (f != NULL) + fclose(f); + signal(SIGCHLD, osigchld); + for (i = 0; i < ac; i++) + free(av[i]); + free(av); + if (uid_swapped) + restore_uid(); + free(command); + free(username); + return found_principal; +} +/* * Checks whether key is allowed in authorized_keys-format file, * returns 1 if the key is allowed or 0 otherwise. */ @@ -365,8 +767,9 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) continue; if (!key_is_cert_authority) continue; - fp = key_fingerprint(found, SSH_FP_MD5, - SSH_FP_HEX); + if ((fp = sshkey_fingerprint(found, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + continue; debug("matching CA found: file %s, line %lu, %s %s", file, linenum, key_type(found), fp); /* @@ -405,11 +808,13 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) continue; if (key_is_cert_authority) continue; - found_key = 1; - fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + if ((fp = sshkey_fingerprint(found, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + continue; debug("matching key found: file %s, line %lu %s %s", file, linenum, key_type(found), fp); free(fp); + found_key = 1; break; } } @@ -426,16 +831,17 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) { char *ca_fp, *principals_file = NULL; const char *reason; - int ret = 0; + int ret = 0, found_principal = 0, use_authorized_principals; if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) return 0; - ca_fp = key_fingerprint(key->cert->signature_key, - SSH_FP_MD5, SSH_FP_HEX); + if ((ca_fp = sshkey_fingerprint(key->cert->signature_key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + return 0; - if (key_in_file(key->cert->signature_key, - options.trusted_user_ca_keys, 1) != 1) { + if (sshkey_in_file(key->cert->signature_key, + options.trusted_user_ca_keys, 1, 0) != 0) { debug2("%s: CA %s %s is not listed in %s", __func__, key_type(key->cert->signature_key), ca_fp, options.trusted_user_ca_keys); @@ -447,17 +853,24 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) * against the username. */ if ((principals_file = authorized_principals_file(pw)) != NULL) { - if (!match_principals_file(principals_file, pw, key->cert)) { - reason = "Certificate does not contain an " - "authorized principal"; + if (match_principals_file(principals_file, pw, key->cert)) + found_principal = 1; + } + /* Try querying command if specified */ + if (!found_principal && match_principals_command(pw, key->cert)) + found_principal = 1; + /* If principals file or command is specified, then require a match */ + use_authorized_principals = principals_file != NULL || + options.authorized_principals_command != NULL; + if (!found_principal && use_authorized_principals) { + reason = "Certificate does not contain an authorized principal"; fail_reason: - error("%s", reason); - auth_debug_add("%s", reason); - goto out; - } + error("%s", reason); + auth_debug_add("%s", reason); + goto out; } if (key_cert_check_authority(key, 0, 1, - principals_file == NULL ? pw->pw_name : NULL, &reason) != 0) + use_authorized_principals ? NULL : pw->pw_name, &reason) != 0) goto fail_reason; if (auth_cert_options(key, pw) != 0) goto out; @@ -503,144 +916,117 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) static int user_key_command_allowed2(struct passwd *user_pw, Key *key) { - FILE *f; - int ok, found_key = 0; + FILE *f = NULL; + int r, ok, found_key = 0; struct passwd *pw; - struct stat st; - int status, devnull, p[2], i; + int i, uid_swapped = 0, ac = 0; pid_t pid; - char *username, errmsg[512]; + char *username = NULL, *key_fp = NULL, *keytext = NULL; + char *tmp, *command = NULL, **av = NULL; + void (*osigchld)(int); - if (options.authorized_keys_command == NULL || - options.authorized_keys_command[0] != '/') + if (options.authorized_keys_command == NULL) return 0; - if (options.authorized_keys_command_user == NULL) { error("No user for AuthorizedKeysCommand specified, skipping"); return 0; } + /* + * NB. all returns later this function should go via "out" to + * ensure the original SIGCHLD handler is restored properly. + */ + osigchld = signal(SIGCHLD, SIG_DFL); + + /* Prepare and verify the user for the command */ username = percent_expand(options.authorized_keys_command_user, "u", user_pw->pw_name, (char *)NULL); pw = getpwnam(username); if (pw == NULL) { error("AuthorizedKeysCommandUser \"%s\" not found: %s", username, strerror(errno)); - free(username); - return 0; + goto out; } - free(username); - - temporarily_use_uid(pw); - if (stat(options.authorized_keys_command, &st) < 0) { - error("Could not stat AuthorizedKeysCommand \"%s\": %s", - options.authorized_keys_command, strerror(errno)); + /* Prepare AuthorizedKeysCommand */ + if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) { + error("%s: sshkey_fingerprint failed", __func__); goto out; } - if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0, - errmsg, sizeof(errmsg)) != 0) { - error("Unsafe AuthorizedKeysCommand: %s", errmsg); + if ((r = sshkey_to_base64(key, &keytext)) != 0) { + error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); goto out; } - if (pipe(p) != 0) { - error("%s: pipe: %s", __func__, strerror(errno)); + /* Turn the command into an argument vector */ + if (split_argv(options.authorized_keys_command, &ac, &av) != 0) { + error("AuthorizedKeysCommand \"%s\" contains invalid quotes", + command); goto out; } - - debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"", - options.authorized_keys_command, user_pw->pw_name, pw->pw_name); + if (ac == 0) { + error("AuthorizedKeysCommand \"%s\" yielded no arguments", + command); + goto out; + } + for (i = 1; i < ac; i++) { + tmp = percent_expand(av[i], + "u", user_pw->pw_name, + "h", user_pw->pw_dir, + "t", sshkey_ssh_name(key), + "f", key_fp, + "k", keytext, + (char *)NULL); + if (tmp == NULL) + fatal("%s: percent_expand failed", __func__); + free(av[i]); + av[i] = tmp; + } + /* Prepare a printable command for logs, etc. */ + command = assemble_argv(ac, av); /* - * Don't want to call this in the child, where it can fatal() and - * run cleanup_exit() code. + * If AuthorizedKeysCommand was run without arguments + * then fall back to the old behaviour of passing the + * target username as a single argument. */ - restore_uid(); - - switch ((pid = fork())) { - case -1: /* error */ - error("%s: fork: %s", __func__, strerror(errno)); - close(p[0]); - close(p[1]); - return 0; - case 0: /* child */ - for (i = 0; i < NSIG; i++) - signal(i, SIG_DFL); - - if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { - error("%s: open %s: %s", __func__, _PATH_DEVNULL, - strerror(errno)); - _exit(1); - } - /* Keep stderr around a while longer to catch errors */ - if (dup2(devnull, STDIN_FILENO) == -1 || - dup2(p[1], STDOUT_FILENO) == -1) { - error("%s: dup2: %s", __func__, strerror(errno)); - _exit(1); - } - closefrom(STDERR_FILENO + 1); - - /* Don't use permanently_set_uid() here to avoid fatal() */ - if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { - error("setresgid %u: %s", (u_int)pw->pw_gid, - strerror(errno)); - _exit(1); - } - if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) { - error("setresuid %u: %s", (u_int)pw->pw_uid, - strerror(errno)); - _exit(1); - } - /* stdin is pointed to /dev/null at this point */ - if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) { - error("%s: dup2: %s", __func__, strerror(errno)); - _exit(1); - } - - execl(options.authorized_keys_command, - options.authorized_keys_command, user_pw->pw_name, NULL); - - error("AuthorizedKeysCommand %s exec failed: %s", - options.authorized_keys_command, strerror(errno)); - _exit(127); - default: /* parent */ - break; + if (ac == 1) { + av = xreallocarray(av, ac + 2, sizeof(*av)); + av[1] = xstrdup(user_pw->pw_name); + av[2] = NULL; + /* Fix up command too, since it is used in log messages */ + free(command); + xasprintf(&command, "%s %s", av[0], av[1]); } + if ((pid = subprocess("AuthorizedKeysCommand", pw, command, + ac, av, &f)) == 0) + goto out; + + uid_swapped = 1; temporarily_use_uid(pw); - close(p[1]); - if ((f = fdopen(p[0], "r")) == NULL) { - error("%s: fdopen: %s", __func__, strerror(errno)); - close(p[0]); - /* Don't leave zombie child */ - kill(pid, SIGTERM); - while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) - ; - goto out; - } ok = check_authkeys_file(f, options.authorized_keys_command, key, pw); - fclose(f); - while (waitpid(pid, &status, 0) == -1) { - if (errno != EINTR) { - error("%s: waitpid: %s", __func__, strerror(errno)); - goto out; - } - } - if (WIFSIGNALED(status)) { - error("AuthorizedKeysCommand %s exited on signal %d", - options.authorized_keys_command, WTERMSIG(status)); + if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0) goto out; - } else if (WEXITSTATUS(status) != 0) { - error("AuthorizedKeysCommand %s returned status %d", - options.authorized_keys_command, WEXITSTATUS(status)); - goto out; - } + + /* Read completed successfully */ found_key = ok; out: - restore_uid(); + if (f != NULL) + fclose(f); + signal(SIGCHLD, osigchld); + for (i = 0; i < ac; i++) + free(av[i]); + free(av); + if (uid_swapped) + restore_uid(); + free(command); + free(username); + free(key_fp); + free(keytext); return found_key; } @@ -648,7 +1034,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key) * Check whether key authenticates and authorises the user. */ int -user_key_allowed(struct passwd *pw, Key *key) +user_key_allowed(struct passwd *pw, Key *key, int auth_attempt) { u_int success, i; char *file; @@ -680,6 +1066,35 @@ user_key_allowed(struct passwd *pw, Key *key) return success; } +/* Records a public key in the list of previously-successful keys */ +void +auth2_record_userkey(Authctxt *authctxt, struct sshkey *key) +{ + struct sshkey **tmp; + + if (authctxt->nprev_userkeys >= INT_MAX || + (tmp = reallocarray(authctxt->prev_userkeys, + authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL) + fatal("%s: reallocarray failed", __func__); + authctxt->prev_userkeys = tmp; + authctxt->prev_userkeys[authctxt->nprev_userkeys] = key; + authctxt->nprev_userkeys++; +} + +/* Checks whether a key has already been used successfully for authentication */ +int +auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key) +{ + u_int i; + + for (i = 0; i < authctxt->nprev_userkeys; i++) { + if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) { + return 1; + } + } + return 0; +} + Authmethod method_pubkey = { "publickey", userauth_pubkey, diff --git a/crypto/openssh/auth2.c b/crypto/openssh/auth2.c index 9747a23..1d9aab0 100644 --- a/crypto/openssh/auth2.c +++ b/crypto/openssh/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.130 2014/01/29 06:18:35 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.135 2015/01/19 20:07:45 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -42,6 +42,7 @@ __RCSID("$FreeBSD$"); #include "packet.h" #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" #include "compat.h" #include "key.h" @@ -88,8 +89,8 @@ Authmethod *authmethods[] = { /* protocol */ -static void input_service_request(int, u_int32_t, void *); -static void input_userauth_request(int, u_int32_t, void *); +static int input_service_request(int, u_int32_t, void *); +static int input_userauth_request(int, u_int32_t, void *); /* helper */ static Authmethod *authmethod_lookup(Authctxt *, const char *); @@ -152,9 +153,7 @@ userauth_banner(void) { char *banner = NULL; - if (options.banner == NULL || - strcasecmp(options.banner, "none") == 0 || - (datafellows & SSH_BUG_BANNER) != 0) + if (options.banner == NULL || (datafellows & SSH_BUG_BANNER) != 0) return; if ((banner = PRIVSEP(auth2_read_banner())) == NULL) @@ -177,7 +176,7 @@ do_authentication2(Authctxt *authctxt) } /*ARGSUSED*/ -static void +static int input_service_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; @@ -208,10 +207,11 @@ input_service_request(int type, u_int32_t seq, void *ctxt) packet_disconnect("bad service request %s", service); } free(service); + return 0; } /*ARGSUSED*/ -static void +static int input_userauth_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; @@ -315,6 +315,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) free(service); free(user); free(method); + return 0; } void @@ -385,14 +386,14 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, } else { /* Allow initial try of "none" auth without failure penalty */ - if (!authctxt->server_caused_failure && + if (!partial && !authctxt->server_caused_failure && (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); #endif - packet_disconnect(AUTH_FAIL_MSG, authctxt->user); + auth_maxtries_exceeded(authctxt); } methods = authmethods_get(authctxt); debug3("%s: failure partial=%d next methods=\"%s\"", __func__, diff --git a/crypto/openssh/authfd.c b/crypto/openssh/authfd.c index cea3f97..eaa1426 100644 --- a/crypto/openssh/authfd.c +++ b/crypto/openssh/authfd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.92 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: authfd.c,v 1.98 2015/07/03 03:43:18 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -41,133 +41,127 @@ #include #include -#include -#include - #include #include #include #include #include #include +#include #include "xmalloc.h" #include "ssh.h" #include "rsa.h" -#include "buffer.h" -#include "key.h" +#include "sshbuf.h" +#include "sshkey.h" #include "authfd.h" #include "cipher.h" -#include "kex.h" #include "compat.h" #include "log.h" #include "atomicio.h" #include "misc.h" +#include "ssherr.h" -static int agent_present = 0; - -/* helper */ -int decode_reply(int type); +#define MAX_AGENT_IDENTITIES 2048 /* Max keys in agent reply */ +#define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */ /* macro to check for "agent failure" message */ #define agent_failed(x) \ - ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \ + ((x == SSH_AGENT_FAILURE) || \ + (x == SSH_COM_AGENT2_FAILURE) || \ (x == SSH2_AGENT_FAILURE)) -int -ssh_agent_present(void) +/* Convert success/failure response from agent to a err.h status */ +static int +decode_reply(u_char type) { - int authfd; - - if (agent_present) - return 1; - if ((authfd = ssh_get_authentication_socket()) == -1) + if (agent_failed(type)) + return SSH_ERR_AGENT_FAILURE; + else if (type == SSH_AGENT_SUCCESS) return 0; - else { - ssh_close_authentication_socket(authfd); - return 1; - } + else + return SSH_ERR_INVALID_FORMAT; } /* Returns the number of the authentication fd, or -1 if there is none. */ - int -ssh_get_authentication_socket(void) +ssh_get_authentication_socket(int *fdp) { const char *authsocket; - int sock; + int sock, oerrno; struct sockaddr_un sunaddr; + if (fdp != NULL) + *fdp = -1; + authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); if (!authsocket) - return -1; + return SSH_ERR_AGENT_NOT_PRESENT; memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - return -1; + if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return SSH_ERR_SYSTEM_ERROR; /* close on exec */ - if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { + if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 || + connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { + oerrno = errno; close(sock); - return -1; + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; } - if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) { + if (fdp != NULL) + *fdp = sock; + else close(sock); - return -1; - } - agent_present = 1; - return sock; + return 0; } +/* Communicate with agent: send request and read reply */ static int -ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply) +ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply) { - u_int l, len; + int r; + size_t l, len; char buf[1024]; /* Get the length of the message, and format it in the buffer. */ - len = buffer_len(request); + len = sshbuf_len(request); put_u32(buf, len); /* Send the length and then the packet to the agent. */ - if (atomicio(vwrite, auth->fd, buf, 4) != 4 || - atomicio(vwrite, auth->fd, buffer_ptr(request), - buffer_len(request)) != buffer_len(request)) { - error("Error writing to authentication socket."); - return 0; - } + if (atomicio(vwrite, sock, buf, 4) != 4 || + atomicio(vwrite, sock, (u_char *)sshbuf_ptr(request), + sshbuf_len(request)) != sshbuf_len(request)) + return SSH_ERR_AGENT_COMMUNICATION; /* * Wait for response from the agent. First read the length of the * response packet. */ - if (atomicio(read, auth->fd, buf, 4) != 4) { - error("Error reading response length from authentication socket."); - return 0; - } + if (atomicio(read, sock, buf, 4) != 4) + return SSH_ERR_AGENT_COMMUNICATION; /* Extract the length, and check it for sanity. */ len = get_u32(buf); - if (len > 256 * 1024) - fatal("Authentication response too long: %u", len); + if (len > MAX_AGENT_REPLY_LEN) + return SSH_ERR_INVALID_FORMAT; /* Read the rest of the response in to the buffer. */ - buffer_clear(reply); + sshbuf_reset(reply); while (len > 0) { l = len; if (l > sizeof(buf)) l = sizeof(buf); - if (atomicio(read, auth->fd, buf, l) != l) { - error("Error reading response from authentication socket."); - return 0; - } - buffer_append(reply, buf, l); + if (atomicio(read, sock, buf, l) != l) + return SSH_ERR_AGENT_COMMUNICATION; + if ((r = sshbuf_put(reply, buf, l)) != 0) + return r; len -= l; } - return 1; + return 0; } /* @@ -175,7 +169,6 @@ ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply * obtained). The argument must have been returned by * ssh_get_authentication_socket(). */ - void ssh_close_authentication_socket(int sock) { @@ -183,80 +176,103 @@ ssh_close_authentication_socket(int sock) close(sock); } -/* - * Opens and connects a private socket for communication with the - * authentication agent. Returns the file descriptor (which must be - * shut down and closed by the caller when no longer needed). - * Returns NULL if an error occurred and the connection could not be - * opened. - */ - -AuthenticationConnection * -ssh_get_authentication_connection(void) +/* Lock/unlock agent */ +int +ssh_lock_agent(int sock, int lock, const char *password) { - AuthenticationConnection *auth; - int sock; - - sock = ssh_get_authentication_socket(); - - /* - * Fail if we couldn't obtain a connection. This happens if we - * exited due to a timeout. - */ - if (sock < 0) - return NULL; - - auth = xcalloc(1, sizeof(*auth)); - auth->fd = sock; - buffer_init(&auth->identities); - auth->howmany = 0; - - return auth; + int r; + u_char type = lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK; + struct sshbuf *msg; + + if ((msg = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_u8(msg, type)) != 0 || + (r = sshbuf_put_cstring(msg, password)) != 0) + goto out; + if ((r = ssh_request_reply(sock, msg, msg)) != 0) + goto out; + if ((r = sshbuf_get_u8(msg, &type)) != 0) + goto out; + r = decode_reply(type); + out: + sshbuf_free(msg); + return r; } -/* - * Closes the connection to the authentication agent and frees any associated - * memory. - */ - -void -ssh_close_authentication_connection(AuthenticationConnection *auth) +#ifdef WITH_SSH1 +static int +deserialise_identity1(struct sshbuf *ids, struct sshkey **keyp, char **commentp) { - buffer_free(&auth->identities); - close(auth->fd); - free(auth); + struct sshkey *key; + int r, keybits; + u_int32_t bits; + char *comment = NULL; + + if ((key = sshkey_new(KEY_RSA1)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_get_u32(ids, &bits)) != 0 || + (r = sshbuf_get_bignum1(ids, key->rsa->e)) != 0 || + (r = sshbuf_get_bignum1(ids, key->rsa->n)) != 0 || + (r = sshbuf_get_cstring(ids, &comment, NULL)) != 0) + goto out; + keybits = BN_num_bits(key->rsa->n); + /* XXX previously we just warned here. I think we should be strict */ + if (keybits < 0 || bits != (u_int)keybits) { + r = SSH_ERR_KEY_BITS_MISMATCH; + goto out; + } + if (keyp != NULL) { + *keyp = key; + key = NULL; + } + if (commentp != NULL) { + *commentp = comment; + comment = NULL; + } + r = 0; + out: + sshkey_free(key); + free(comment); + return r; } +#endif -/* Lock/unlock agent */ -int -ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password) +static int +deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp) { - int type; - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK); - buffer_put_cstring(&msg, password); - - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; + int r; + char *comment = NULL; + const u_char *blob; + size_t blen; + + if ((r = sshbuf_get_string_direct(ids, &blob, &blen)) != 0 || + (r = sshbuf_get_cstring(ids, &comment, NULL)) != 0) + goto out; + if ((r = sshkey_from_blob(blob, blen, keyp)) != 0) + goto out; + if (commentp != NULL) { + *commentp = comment; + comment = NULL; } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); + r = 0; + out: + free(comment); + return r; } /* - * Returns the first authentication identity held by the agent. + * Fetch list of identities held by the agent. */ - int -ssh_get_num_identities(AuthenticationConnection *auth, int version) +ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp) { - int type, code1 = 0, code2 = 0; - Buffer request; + u_char type, code1 = 0, code2 = 0; + u_int32_t num, i; + struct sshbuf *msg; + struct ssh_identitylist *idl = NULL; + int r; + /* Determine request and expected response types */ switch (version) { case 1: code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; @@ -267,320 +283,375 @@ ssh_get_num_identities(AuthenticationConnection *auth, int version) code2 = SSH2_AGENT_IDENTITIES_ANSWER; break; default: - return 0; + return SSH_ERR_INVALID_ARGUMENT; } /* * Send a message to the agent requesting for a list of the * identities it can represent. */ - buffer_init(&request); - buffer_put_char(&request, code1); + if ((msg = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_u8(msg, code1)) != 0) + goto out; - buffer_clear(&auth->identities); - if (ssh_request_reply(auth, &request, &auth->identities) == 0) { - buffer_free(&request); - return 0; - } - buffer_free(&request); + if ((r = ssh_request_reply(sock, msg, msg)) != 0) + goto out; /* Get message type, and verify that we got a proper answer. */ - type = buffer_get_char(&auth->identities); + if ((r = sshbuf_get_u8(msg, &type)) != 0) + goto out; if (agent_failed(type)) { - return 0; + r = SSH_ERR_AGENT_FAILURE; + goto out; } else if (type != code2) { - fatal("Bad authentication reply message type: %d", type); + r = SSH_ERR_INVALID_FORMAT; + goto out; } /* Get the number of entries in the response and check it for sanity. */ - auth->howmany = buffer_get_int(&auth->identities); - if ((u_int)auth->howmany > 1024) - fatal("Too many identities in authentication reply: %d", - auth->howmany); - - return auth->howmany; -} + if ((r = sshbuf_get_u32(msg, &num)) != 0) + goto out; + if (num > MAX_AGENT_IDENTITIES) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (num == 0) { + r = SSH_ERR_AGENT_NO_IDENTITIES; + goto out; + } -Key * -ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version) -{ - /* get number of identities and return the first entry (if any). */ - if (ssh_get_num_identities(auth, version) > 0) - return ssh_get_next_identity(auth, comment, version); - return NULL; + /* Deserialise the response into a list of keys/comments */ + if ((idl = calloc(1, sizeof(*idl))) == NULL || + (idl->keys = calloc(num, sizeof(*idl->keys))) == NULL || + (idl->comments = calloc(num, sizeof(*idl->comments))) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + for (i = 0; i < num;) { + switch (version) { + case 1: +#ifdef WITH_SSH1 + if ((r = deserialise_identity1(msg, + &(idl->keys[i]), &(idl->comments[i]))) != 0) + goto out; +#endif + break; + case 2: + if ((r = deserialise_identity2(msg, + &(idl->keys[i]), &(idl->comments[i]))) != 0) { + if (r == SSH_ERR_KEY_TYPE_UNKNOWN) { + /* Gracefully skip unknown key types */ + num--; + continue; + } else + goto out; + } + break; + } + i++; + } + idl->nkeys = num; + *idlp = idl; + idl = NULL; + r = 0; + out: + sshbuf_free(msg); + if (idl != NULL) + ssh_free_identitylist(idl); + return r; } -Key * -ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) +void +ssh_free_identitylist(struct ssh_identitylist *idl) { - int keybits; - u_int bits; - u_char *blob; - u_int blen; - Key *key = NULL; - - /* Return failure if no more entries. */ - if (auth->howmany <= 0) - return NULL; - - /* - * Get the next entry from the packet. These will abort with a fatal - * error if the packet is too short or contains corrupt data. - */ - switch (version) { - case 1: - key = key_new(KEY_RSA1); - bits = buffer_get_int(&auth->identities); - buffer_get_bignum(&auth->identities, key->rsa->e); - buffer_get_bignum(&auth->identities, key->rsa->n); - *comment = buffer_get_string(&auth->identities, NULL); - keybits = BN_num_bits(key->rsa->n); - if (keybits < 0 || bits != (u_int)keybits) - logit("Warning: identity keysize mismatch: actual %d, announced %u", - BN_num_bits(key->rsa->n), bits); - break; - case 2: - blob = buffer_get_string(&auth->identities, &blen); - *comment = buffer_get_string(&auth->identities, NULL); - key = key_from_blob(blob, blen); - free(blob); - break; - default: - return NULL; + size_t i; + + if (idl == NULL) + return; + for (i = 0; i < idl->nkeys; i++) { + if (idl->keys != NULL) + sshkey_free(idl->keys[i]); + if (idl->comments != NULL) + free(idl->comments[i]); } - /* Decrement the number of remaining entries. */ - auth->howmany--; - return key; + free(idl); } /* - * Generates a random challenge, sends it to the agent, and waits for - * response from the agent. Returns true (non-zero) if the agent gave the - * correct answer, zero otherwise. Response type selects the style of - * response desired, with 0 corresponding to protocol version 1.0 (no longer - * supported) and 1 corresponding to protocol version 1.1. + * Sends a challenge (typically from a server via ssh(1)) to the agent, + * and waits for a response from the agent. + * Returns true (non-zero) if the agent gave the correct answer, zero + * otherwise. */ +#ifdef WITH_SSH1 int -ssh_decrypt_challenge(AuthenticationConnection *auth, - Key* key, BIGNUM *challenge, - u_char session_id[16], - u_int response_type, - u_char response[16]) +ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, + u_char session_id[16], u_char response[16]) { - Buffer buffer; - int success = 0; - int i; - int type; + struct sshbuf *msg; + int r; + u_char type; if (key->type != KEY_RSA1) - return 0; - if (response_type == 0) { - logit("Compatibility with ssh protocol version 1.0 no longer supported."); - return 0; - } - buffer_init(&buffer); - buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE); - buffer_put_int(&buffer, BN_num_bits(key->rsa->n)); - buffer_put_bignum(&buffer, key->rsa->e); - buffer_put_bignum(&buffer, key->rsa->n); - buffer_put_bignum(&buffer, challenge); - buffer_append(&buffer, session_id, 16); - buffer_put_int(&buffer, response_type); - - if (ssh_request_reply(auth, &buffer, &buffer) == 0) { - buffer_free(&buffer); - return 0; - } - type = buffer_get_char(&buffer); - + return SSH_ERR_INVALID_ARGUMENT; + if ((msg = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + 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_bignum1(msg, key->rsa->e)) != 0 || + (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0 || + (r = sshbuf_put_bignum1(msg, challenge)) != 0 || + (r = sshbuf_put(msg, session_id, 16)) != 0 || + (r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */ + goto out; + if ((r = ssh_request_reply(sock, msg, msg)) != 0) + goto out; + if ((r = sshbuf_get_u8(msg, &type)) != 0) + goto out; if (agent_failed(type)) { - logit("Agent admitted failure to authenticate using the key."); + r = SSH_ERR_AGENT_FAILURE; + goto out; } else if (type != SSH_AGENT_RSA_RESPONSE) { - fatal("Bad authentication response: %d", type); - } else { - success = 1; - /* - * Get the response from the packet. This will abort with a - * fatal error if the packet is corrupt. - */ - for (i = 0; i < 16; i++) - response[i] = (u_char)buffer_get_char(&buffer); + r = SSH_ERR_INVALID_FORMAT; + goto out; } - buffer_free(&buffer); - return success; + if ((r = sshbuf_get(msg, response, 16)) != 0) + goto out; + r = 0; + out: + sshbuf_free(msg); + return r; } +#endif -/* ask agent to sign data, returns -1 on error, 0 on success */ +/* ask agent to sign data, returns err.h code on error, 0 on success */ int -ssh_agent_sign(AuthenticationConnection *auth, - Key *key, - u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) +ssh_agent_sign(int sock, struct sshkey *key, + u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) { - extern int datafellows; - Buffer msg; - u_char *blob; - u_int blen; - int type, flags = 0; - int ret = -1; - - if (key_to_blob(key, &blob, &blen) == 0) - return -1; - - if (datafellows & SSH_BUG_SIGBLOB) - flags = SSH_AGENT_OLD_SIGNATURE; - - buffer_init(&msg); - buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); - buffer_put_string(&msg, blob, blen); - buffer_put_string(&msg, data, datalen); - buffer_put_int(&msg, flags); - free(blob); - - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return -1; - } - type = buffer_get_char(&msg); + struct sshbuf *msg; + u_char *blob = NULL, type; + size_t blen = 0, len = 0; + u_int flags = 0; + int r = SSH_ERR_INTERNAL_ERROR; + + *sigp = NULL; + *lenp = 0; + + if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) + return SSH_ERR_INVALID_ARGUMENT; + if (compat & SSH_BUG_SIGBLOB) + flags |= SSH_AGENT_OLD_SIGNATURE; + if ((msg = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) + goto out; + if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || + (r = sshbuf_put_string(msg, blob, blen)) != 0 || + (r = sshbuf_put_string(msg, data, datalen)) != 0 || + (r = sshbuf_put_u32(msg, flags)) != 0) + goto out; + if ((r = ssh_request_reply(sock, msg, msg) != 0)) + goto out; + if ((r = sshbuf_get_u8(msg, &type)) != 0) + goto out; if (agent_failed(type)) { - logit("Agent admitted failure to sign using the key."); + r = SSH_ERR_AGENT_FAILURE; + goto out; } else if (type != SSH2_AGENT_SIGN_RESPONSE) { - fatal("Bad authentication response: %d", type); - } else { - ret = 0; - *sigp = buffer_get_string(&msg, lenp); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_get_string(msg, sigp, &len)) != 0) + goto out; + *lenp = len; + r = 0; + out: + if (blob != NULL) { + explicit_bzero(blob, blen); + free(blob); } - buffer_free(&msg); - return ret; + sshbuf_free(msg); + return r; } /* Encode key for a message to the agent. */ -static void -ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) +#ifdef WITH_SSH1 +static int +ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment) { - buffer_put_int(b, BN_num_bits(key->n)); - buffer_put_bignum(b, key->n); - buffer_put_bignum(b, key->e); - buffer_put_bignum(b, key->d); + int r; + /* To keep within the protocol: p < q for ssh. in SSL p > q */ - buffer_put_bignum(b, key->iqmp); /* ssh key->u */ - buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */ - buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ - buffer_put_cstring(b, comment); + if ((r = sshbuf_put_u32(b, BN_num_bits(key->n))) != 0 || + (r = sshbuf_put_bignum1(b, key->n)) != 0 || + (r = sshbuf_put_bignum1(b, key->e)) != 0 || + (r = sshbuf_put_bignum1(b, key->d)) != 0 || + (r = sshbuf_put_bignum1(b, key->iqmp)) != 0 || + (r = sshbuf_put_bignum1(b, key->q)) != 0 || + (r = sshbuf_put_bignum1(b, key->p)) != 0 || + (r = sshbuf_put_cstring(b, comment)) != 0) + return r; + return 0; } +#endif -static void -ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) +static int +ssh_encode_identity_ssh2(struct sshbuf *b, struct sshkey *key, + const char *comment) { - key_private_serialize(key, b); - buffer_put_cstring(b, comment); + int r; + + if ((r = sshkey_private_serialize(key, b)) != 0 || + (r = sshbuf_put_cstring(b, comment)) != 0) + return r; + return 0; +} + +static int +encode_constraints(struct sshbuf *m, u_int life, u_int confirm) +{ + int r; + + if (life != 0) { + if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_LIFETIME)) != 0 || + (r = sshbuf_put_u32(m, life)) != 0) + goto out; + } + if (confirm != 0) { + if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_CONFIRM)) != 0) + goto out; + } + r = 0; + out: + return r; } /* - * Adds an identity to the authentication server. This call is not meant to - * be used by normal applications. + * Adds an identity to the authentication server. + * This call is intended only for use by ssh-add(1) and like applications. */ - int -ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, - const char *comment, u_int life, u_int confirm) +ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, + u_int life, u_int confirm) { - Buffer msg; - int type, constrained = (life || confirm); + struct sshbuf *msg; + int r, constrained = (life || confirm); + u_char type; - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; switch (key->type) { +#ifdef WITH_SSH1 case KEY_RSA1: type = constrained ? SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : SSH_AGENTC_ADD_RSA_IDENTITY; - buffer_put_char(&msg, type); - ssh_encode_identity_rsa1(&msg, key->rsa, comment); + if ((r = sshbuf_put_u8(msg, type)) != 0 || + (r = ssh_encode_identity_rsa1(msg, key->rsa, comment)) != 0) + goto out; break; +#endif +#ifdef WITH_OPENSSL case KEY_RSA: case KEY_RSA_CERT: - case KEY_RSA_CERT_V00: case KEY_DSA: case KEY_DSA_CERT: - case KEY_DSA_CERT_V00: case KEY_ECDSA: case KEY_ECDSA_CERT: +#endif case KEY_ED25519: case KEY_ED25519_CERT: type = constrained ? SSH2_AGENTC_ADD_ID_CONSTRAINED : SSH2_AGENTC_ADD_IDENTITY; - buffer_put_char(&msg, type); - ssh_encode_identity_ssh2(&msg, key, comment); + if ((r = sshbuf_put_u8(msg, type)) != 0 || + (r = ssh_encode_identity_ssh2(msg, key, comment)) != 0) + goto out; break; default: - buffer_free(&msg); - return 0; + r = SSH_ERR_INVALID_ARGUMENT; + goto out; } - if (constrained) { - if (life != 0) { - buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); - buffer_put_int(&msg, life); - } - if (confirm != 0) - buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM); - } - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; - } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); + if (constrained && + (r = encode_constraints(msg, life, confirm)) != 0) + goto out; + if ((r = ssh_request_reply(sock, msg, msg)) != 0) + goto out; + if ((r = sshbuf_get_u8(msg, &type)) != 0) + goto out; + r = decode_reply(type); + out: + sshbuf_free(msg); + return r; } /* - * Removes an identity from the authentication server. This call is not - * meant to be used by normal applications. + * Removes an identity from the authentication server. + * This call is intended only for use by ssh-add(1) and like applications. */ - int -ssh_remove_identity(AuthenticationConnection *auth, Key *key) +ssh_remove_identity(int sock, struct sshkey *key) { - Buffer msg; - int type; - u_char *blob; - u_int blen; + struct sshbuf *msg; + int r; + u_char type, *blob = NULL; + size_t blen; - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; +#ifdef WITH_SSH1 if (key->type == KEY_RSA1) { - buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); - buffer_put_int(&msg, BN_num_bits(key->rsa->n)); - buffer_put_bignum(&msg, key->rsa->e); - buffer_put_bignum(&msg, key->rsa->n); - } else if (key->type != KEY_UNSPEC) { - key_to_blob(key, &blob, &blen); - buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); - buffer_put_string(&msg, blob, blen); - free(blob); + if ((r = sshbuf_put_u8(msg, + SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 || + (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || + (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || + (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0) + goto out; + } else +#endif + if (key->type != KEY_UNSPEC) { + if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) + goto out; + if ((r = sshbuf_put_u8(msg, + SSH2_AGENTC_REMOVE_IDENTITY)) != 0 || + (r = sshbuf_put_string(msg, blob, blen)) != 0) + goto out; } else { - buffer_free(&msg); - return 0; + r = SSH_ERR_INVALID_ARGUMENT; + goto out; } - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; + if ((r = ssh_request_reply(sock, msg, msg)) != 0) + goto out; + if ((r = sshbuf_get_u8(msg, &type)) != 0) + goto out; + r = decode_reply(type); + out: + if (blob != NULL) { + explicit_bzero(blob, blen); + free(blob); } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); + sshbuf_free(msg); + return r; } +/* + * Add/remove an token-based identity from the authentication server. + * This call is intended only for use by ssh-add(1) and like applications. + */ int -ssh_update_card(AuthenticationConnection *auth, int add, - const char *reader_id, const char *pin, u_int life, u_int confirm) +ssh_update_card(int sock, int add, const char *reader_id, const char *pin, + u_int life, u_int confirm) { - Buffer msg; - int type, constrained = (life || confirm); + struct sshbuf *msg; + int r, constrained = (life || confirm); + u_char type; if (add) { type = constrained ? @@ -589,69 +660,48 @@ ssh_update_card(AuthenticationConnection *auth, int add, } else type = SSH_AGENTC_REMOVE_SMARTCARD_KEY; - buffer_init(&msg); - buffer_put_char(&msg, type); - buffer_put_cstring(&msg, reader_id); - buffer_put_cstring(&msg, pin); - - if (constrained) { - if (life != 0) { - buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); - buffer_put_int(&msg, life); - } - if (confirm != 0) - buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM); - } - - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; - } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); + if ((msg = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_u8(msg, type)) != 0 || + (r = sshbuf_put_cstring(msg, reader_id)) != 0 || + (r = sshbuf_put_cstring(msg, pin)) != 0) + goto out; + if (constrained && + (r = encode_constraints(msg, life, confirm)) != 0) + goto out; + if ((r = ssh_request_reply(sock, msg, msg)) != 0) + goto out; + if ((r = sshbuf_get_u8(msg, &type)) != 0) + goto out; + r = decode_reply(type); + out: + sshbuf_free(msg); + return r; } /* - * Removes all identities from the agent. This call is not meant to be used - * by normal applications. + * Removes all identities from the agent. + * This call is intended only for use by ssh-add(1) and like applications. */ - int -ssh_remove_all_identities(AuthenticationConnection *auth, int version) +ssh_remove_all_identities(int sock, int version) { - Buffer msg; - int type; - int code = (version==1) ? - SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES : - SSH2_AGENTC_REMOVE_ALL_IDENTITIES; - - buffer_init(&msg); - buffer_put_char(&msg, code); - - if (ssh_request_reply(auth, &msg, &msg) == 0) { - buffer_free(&msg); - return 0; - } - type = buffer_get_char(&msg); - buffer_free(&msg); - return decode_reply(type); -} - -int -decode_reply(int type) -{ - switch (type) { - case SSH_AGENT_FAILURE: - case SSH_COM_AGENT2_FAILURE: - case SSH2_AGENT_FAILURE: - logit("SSH_AGENT_FAILURE"); - return 0; - case SSH_AGENT_SUCCESS: - return 1; - default: - fatal("Bad response from authentication agent: %d", type); - } - /* NOTREACHED */ - return 0; + struct sshbuf *msg; + u_char type = (version == 1) ? + SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES : + SSH2_AGENTC_REMOVE_ALL_IDENTITIES; + int r; + + if ((msg = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_u8(msg, type)) != 0) + goto out; + if ((r = ssh_request_reply(sock, msg, msg)) != 0) + goto out; + if ((r = sshbuf_get_u8(msg, &type)) != 0) + goto out; + r = decode_reply(type); + out: + sshbuf_free(msg); + return r; } diff --git a/crypto/openssh/authfd.h b/crypto/openssh/authfd.h index 2582a27..bea20c2 100644 --- a/crypto/openssh/authfd.h +++ b/crypto/openssh/authfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.h,v 1.37 2009/08/27 17:44:52 djm Exp $ */ +/* $OpenBSD: authfd.h,v 1.38 2015/01/14 20:05:27 djm Exp $ */ /* * Author: Tatu Ylonen @@ -16,6 +16,33 @@ #ifndef AUTHFD_H #define AUTHFD_H +/* List of identities returned by ssh_fetch_identitylist() */ +struct ssh_identitylist { + size_t nkeys; + struct sshkey **keys; + char **comments; +}; + +int ssh_get_authentication_socket(int *fdp); +void ssh_close_authentication_socket(int sock); + +int ssh_lock_agent(int sock, int lock, const char *password); +int ssh_fetch_identitylist(int sock, int version, + struct ssh_identitylist **idlp); +void ssh_free_identitylist(struct ssh_identitylist *idl); +int ssh_add_identity_constrained(int sock, struct sshkey *key, + const char *comment, u_int life, u_int confirm); +int ssh_remove_identity(int sock, struct sshkey *key); +int ssh_update_card(int sock, int add, const char *reader_id, + const char *pin, u_int life, u_int confirm); +int ssh_remove_all_identities(int sock, int version); + +int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, + u_char session_id[16], u_char response[16]); +int ssh_agent_sign(int sock, struct sshkey *key, + u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat); + /* Messages for the authentication agent connection. */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 @@ -60,35 +87,4 @@ #define SSH_AGENT_OLD_SIGNATURE 0x01 -typedef struct { - int fd; - Buffer identities; - int howmany; -} AuthenticationConnection; - -int ssh_agent_present(void); -int ssh_get_authentication_socket(void); -void ssh_close_authentication_socket(int); - -AuthenticationConnection *ssh_get_authentication_connection(void); -void ssh_close_authentication_connection(AuthenticationConnection *); -int ssh_get_num_identities(AuthenticationConnection *, int); -Key *ssh_get_first_identity(AuthenticationConnection *, char **, int); -Key *ssh_get_next_identity(AuthenticationConnection *, char **, int); -int ssh_add_identity_constrained(AuthenticationConnection *, Key *, - const char *, u_int, u_int); -int ssh_remove_identity(AuthenticationConnection *, Key *); -int ssh_remove_all_identities(AuthenticationConnection *, int); -int ssh_lock_agent(AuthenticationConnection *, int, const char *); -int ssh_update_card(AuthenticationConnection *, int, const char *, - const char *, u_int, u_int); - -int -ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16], - u_int, u_char[16]); - -int -ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *, - u_int); - #endif /* AUTHFD_H */ diff --git a/crypto/openssh/authfile.c b/crypto/openssh/authfile.c index d7eaa9d..58f589a 100644 --- a/crypto/openssh/authfile.c +++ b/crypto/openssh/authfile.c @@ -1,18 +1,5 @@ -/* $OpenBSD: authfile.c,v 1.103 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: authfile.c,v 1.116 2015/07/09 09:49:46 markus Exp $ */ /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * This file contains functions for reading and writing identity files, and - * for reading the passphrase from the user. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,937 +27,151 @@ #include #include -#include #include -#include -#include -#include - -/* compatibility with old or broken OpenSSL versions */ -#include "openbsd-compat/openssl-compat.h" - -#include "crypto_api.h" - #include #include -#include #include +#include #include #include #include +#include -#ifdef HAVE_UTIL_H -#include -#endif - -#include "xmalloc.h" #include "cipher.h" -#include "buffer.h" -#include "key.h" #include "ssh.h" #include "log.h" #include "authfile.h" #include "rsa.h" #include "misc.h" #include "atomicio.h" -#include "uuencode.h" - -/* openssh private key file format */ -#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" -#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" -#define KDFNAME "bcrypt" -#define AUTH_MAGIC "openssh-key-v1" -#define SALT_LEN 16 -#define DEFAULT_CIPHERNAME "aes256-cbc" -#define DEFAULT_ROUNDS 16 +#include "sshkey.h" +#include "sshbuf.h" +#include "ssherr.h" +#include "krl.h" #define MAX_KEY_FILE_SIZE (1024 * 1024) -/* Version identification string for SSH v1 identity files. */ -static const char authfile_id_string[] = - "SSH PRIVATE KEY FILE FORMAT 1.1\n"; - -static int -key_private_to_blob2(Key *prv, Buffer *blob, const char *passphrase, - const char *comment, const char *ciphername, int rounds) -{ - u_char *key, *cp, salt[SALT_LEN]; - size_t keylen, ivlen, blocksize, authlen; - u_int len, check; - int i, n; - const Cipher *c; - Buffer encoded, b, kdf; - CipherContext ctx; - const char *kdfname = KDFNAME; - - if (rounds <= 0) - rounds = DEFAULT_ROUNDS; - if (passphrase == NULL || !strlen(passphrase)) { - ciphername = "none"; - kdfname = "none"; - } else if (ciphername == NULL) - ciphername = DEFAULT_CIPHERNAME; - else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) - fatal("invalid cipher"); - - if ((c = cipher_by_name(ciphername)) == NULL) - fatal("unknown cipher name"); - buffer_init(&kdf); - blocksize = cipher_blocksize(c); - keylen = cipher_keylen(c); - ivlen = cipher_ivlen(c); - authlen = cipher_authlen(c); - key = xcalloc(1, keylen + ivlen); - if (strcmp(kdfname, "none") != 0) { - arc4random_buf(salt, SALT_LEN); - if (bcrypt_pbkdf(passphrase, strlen(passphrase), - salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) - fatal("bcrypt_pbkdf failed"); - buffer_put_string(&kdf, salt, SALT_LEN); - buffer_put_int(&kdf, rounds); - } - cipher_init(&ctx, c, key, keylen, key + keylen , ivlen, 1); - explicit_bzero(key, keylen + ivlen); - free(key); - - buffer_init(&encoded); - buffer_append(&encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC)); - buffer_put_cstring(&encoded, ciphername); - buffer_put_cstring(&encoded, kdfname); - buffer_put_string(&encoded, buffer_ptr(&kdf), buffer_len(&kdf)); - buffer_put_int(&encoded, 1); /* number of keys */ - key_to_blob(prv, &cp, &len); /* public key */ - buffer_put_string(&encoded, cp, len); - - explicit_bzero(cp, len); - free(cp); - - buffer_free(&kdf); - - /* set up the buffer that will be encrypted */ - buffer_init(&b); - - /* Random check bytes */ - check = arc4random(); - buffer_put_int(&b, check); - buffer_put_int(&b, check); - - /* append private key and comment*/ - key_private_serialize(prv, &b); - buffer_put_cstring(&b, comment); - - /* padding */ - i = 0; - while (buffer_len(&b) % blocksize) - buffer_put_char(&b, ++i & 0xff); - - /* length */ - buffer_put_int(&encoded, buffer_len(&b)); - - /* encrypt */ - cp = buffer_append_space(&encoded, buffer_len(&b) + authlen); - if (cipher_crypt(&ctx, 0, cp, buffer_ptr(&b), buffer_len(&b), 0, - authlen) != 0) - fatal("%s: cipher_crypt failed", __func__); - buffer_free(&b); - cipher_cleanup(&ctx); - - /* uuencode */ - len = 2 * buffer_len(&encoded); - cp = xmalloc(len); - n = uuencode(buffer_ptr(&encoded), buffer_len(&encoded), - (char *)cp, len); - if (n < 0) - fatal("%s: uuencode", __func__); - - buffer_clear(blob); - buffer_append(blob, MARK_BEGIN, sizeof(MARK_BEGIN) - 1); - for (i = 0; i < n; i++) { - buffer_put_char(blob, cp[i]); - if (i % 70 == 69) - buffer_put_char(blob, '\n'); - } - if (i % 70 != 69) - buffer_put_char(blob, '\n'); - buffer_append(blob, MARK_END, sizeof(MARK_END) - 1); - free(cp); - - return buffer_len(blob); -} - -static Key * -key_parse_private2(Buffer *blob, int type, const char *passphrase, - char **commentp) -{ - u_char *key = NULL, *cp, *salt = NULL, pad, last; - char *comment = NULL, *ciphername = NULL, *kdfname = NULL, *kdfp; - u_int keylen = 0, ivlen, blocksize, slen, klen, len, rounds, nkeys; - u_int check1, check2, m1len, m2len; - size_t authlen; - const Cipher *c; - Buffer b, encoded, copy, kdf; - CipherContext ctx; - Key *k = NULL; - int dlen, ret, i; - - buffer_init(&b); - buffer_init(&kdf); - buffer_init(&encoded); - buffer_init(©); - - /* uudecode */ - m1len = sizeof(MARK_BEGIN) - 1; - m2len = sizeof(MARK_END) - 1; - cp = buffer_ptr(blob); - len = buffer_len(blob); - if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) { - debug("%s: missing begin marker", __func__); - goto out; - } - cp += m1len; - len -= m1len; - while (len) { - if (*cp != '\n' && *cp != '\r') - buffer_put_char(&encoded, *cp); - last = *cp; - len--; - cp++; - if (last == '\n') { - if (len >= m2len && !memcmp(cp, MARK_END, m2len)) { - buffer_put_char(&encoded, '\0'); - break; - } - } - } - if (!len) { - debug("%s: no end marker", __func__); - goto out; - } - len = buffer_len(&encoded); - if ((cp = buffer_append_space(©, len)) == NULL) { - error("%s: buffer_append_space", __func__); - goto out; - } - if ((dlen = uudecode(buffer_ptr(&encoded), cp, len)) < 0) { - error("%s: uudecode failed", __func__); - goto out; - } - if ((u_int)dlen > len) { - error("%s: crazy uudecode length %d > %u", __func__, dlen, len); - goto out; - } - buffer_consume_end(©, len - dlen); - if (buffer_len(©) < sizeof(AUTH_MAGIC) || - memcmp(buffer_ptr(©), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { - error("%s: bad magic", __func__); - goto out; - } - buffer_consume(©, sizeof(AUTH_MAGIC)); - - ciphername = buffer_get_cstring_ret(©, NULL); - if (ciphername == NULL || - (c = cipher_by_name(ciphername)) == NULL) { - error("%s: unknown cipher name", __func__); - goto out; - } - if ((passphrase == NULL || !strlen(passphrase)) && - strcmp(ciphername, "none") != 0) { - /* passphrase required */ - goto out; - } - kdfname = buffer_get_cstring_ret(©, NULL); - if (kdfname == NULL || - (!strcmp(kdfname, "none") && !strcmp(kdfname, "bcrypt"))) { - error("%s: unknown kdf name", __func__); - goto out; - } - if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) { - error("%s: cipher %s requires kdf", __func__, ciphername); - goto out; - } - /* kdf options */ - kdfp = buffer_get_string_ptr_ret(©, &klen); - if (kdfp == NULL) { - error("%s: kdf options not set", __func__); - goto out; - } - if (klen > 0) { - if ((cp = buffer_append_space(&kdf, klen)) == NULL) { - error("%s: kdf alloc failed", __func__); - goto out; - } - memcpy(cp, kdfp, klen); - } - /* number of keys */ - if (buffer_get_int_ret(&nkeys, ©) < 0) { - error("%s: key counter missing", __func__); - goto out; - } - if (nkeys != 1) { - error("%s: only one key supported", __func__); - goto out; - } - /* pubkey */ - if ((cp = buffer_get_string_ret(©, &len)) == NULL) { - error("%s: pubkey not found", __func__); - goto out; - } - free(cp); /* XXX check pubkey against decrypted private key */ - - /* size of encrypted key blob */ - len = buffer_get_int(©); - blocksize = cipher_blocksize(c); - authlen = cipher_authlen(c); - if (len < blocksize) { - error("%s: encrypted data too small", __func__); - goto out; - } - if (len % blocksize) { - error("%s: length not multiple of blocksize", __func__); - goto out; - } - - /* setup key */ - keylen = cipher_keylen(c); - ivlen = cipher_ivlen(c); - key = xcalloc(1, keylen + ivlen); - if (!strcmp(kdfname, "bcrypt")) { - if ((salt = buffer_get_string_ret(&kdf, &slen)) == NULL) { - error("%s: salt not set", __func__); - goto out; - } - if (buffer_get_int_ret(&rounds, &kdf) < 0) { - error("%s: rounds not set", __func__); - goto out; - } - if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, - key, keylen + ivlen, rounds) < 0) { - error("%s: bcrypt_pbkdf failed", __func__); - goto out; - } - } - - cp = buffer_append_space(&b, len); - cipher_init(&ctx, c, key, keylen, key + keylen, ivlen, 0); - ret = cipher_crypt(&ctx, 0, cp, buffer_ptr(©), len, 0, authlen); - cipher_cleanup(&ctx); - buffer_consume(©, len); - - /* fail silently on decryption errors */ - if (ret != 0) { - debug("%s: decrypt failed", __func__); - goto out; - } - - if (buffer_len(©) != 0) { - error("%s: key blob has trailing data (len = %u)", __func__, - buffer_len(©)); - goto out; - } - - /* check bytes */ - if (buffer_get_int_ret(&check1, &b) < 0 || - buffer_get_int_ret(&check2, &b) < 0) { - error("check bytes missing"); - goto out; - } - if (check1 != check2) { - debug("%s: decrypt failed: 0x%08x != 0x%08x", __func__, - check1, check2); - goto out; - } - - k = key_private_deserialize(&b); - - /* comment */ - comment = buffer_get_cstring_ret(&b, NULL); - - i = 0; - while (buffer_len(&b)) { - if (buffer_get_char_ret(&pad, &b) == -1 || - pad != (++i & 0xff)) { - error("%s: bad padding", __func__); - key_free(k); - k = NULL; - goto out; - } - } - - if (k && commentp) { - *commentp = comment; - comment = NULL; - } - - /* XXX decode pubkey and check against private */ - out: - free(ciphername); - free(kdfname); - free(salt); - free(comment); - if (key) - explicit_bzero(key, keylen + ivlen); - free(key); - buffer_free(&encoded); - buffer_free(©); - buffer_free(&kdf); - buffer_free(&b); - return k; -} - -/* - * Serialises the authentication (private) key to a blob, encrypting it with - * passphrase. The identification of the blob (lowest 64 bits of n) will - * precede the key to provide identification of the key without needing a - * passphrase. - */ -static int -key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase, - const char *comment) -{ - Buffer buffer, encrypted; - u_char buf[100], *cp; - int i, cipher_num; - CipherContext ciphercontext; - const Cipher *cipher; - u_int32_t rnd; - - /* - * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting - * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. - */ - cipher_num = (strcmp(passphrase, "") == 0) ? - SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER; - if ((cipher = cipher_by_number(cipher_num)) == NULL) - fatal("save_private_key_rsa: bad cipher"); - - /* This buffer is used to built the secret part of the private key. */ - buffer_init(&buffer); - - /* Put checkbytes for checking passphrase validity. */ - rnd = arc4random(); - buf[0] = rnd & 0xff; - buf[1] = (rnd >> 8) & 0xff; - buf[2] = buf[0]; - buf[3] = buf[1]; - buffer_append(&buffer, buf, 4); - - /* - * Store the private key (n and e will not be stored because they - * will be stored in plain text, and storing them also in encrypted - * format would just give known plaintext). - */ - buffer_put_bignum(&buffer, key->rsa->d); - buffer_put_bignum(&buffer, key->rsa->iqmp); - buffer_put_bignum(&buffer, key->rsa->q); /* reverse from SSL p */ - buffer_put_bignum(&buffer, key->rsa->p); /* reverse from SSL q */ - - /* Pad the part to be encrypted until its size is a multiple of 8. */ - while (buffer_len(&buffer) % 8 != 0) - buffer_put_char(&buffer, 0); - - /* This buffer will be used to contain the data in the file. */ - buffer_init(&encrypted); - - /* First store keyfile id string. */ - for (i = 0; authfile_id_string[i]; i++) - buffer_put_char(&encrypted, authfile_id_string[i]); - buffer_put_char(&encrypted, 0); - - /* Store cipher type. */ - buffer_put_char(&encrypted, cipher_num); - buffer_put_int(&encrypted, 0); /* For future extension */ - - /* Store public key. This will be in plain text. */ - buffer_put_int(&encrypted, BN_num_bits(key->rsa->n)); - buffer_put_bignum(&encrypted, key->rsa->n); - buffer_put_bignum(&encrypted, key->rsa->e); - buffer_put_cstring(&encrypted, comment); - - /* Allocate space for the private part of the key in the buffer. */ - cp = buffer_append_space(&encrypted, buffer_len(&buffer)); - - cipher_set_key_string(&ciphercontext, cipher, passphrase, - CIPHER_ENCRYPT); - if (cipher_crypt(&ciphercontext, 0, cp, - buffer_ptr(&buffer), buffer_len(&buffer), 0, 0) != 0) - fatal("%s: cipher_crypt failed", __func__); - cipher_cleanup(&ciphercontext); - explicit_bzero(&ciphercontext, sizeof(ciphercontext)); - - /* Destroy temporary data. */ - explicit_bzero(buf, sizeof(buf)); - buffer_free(&buffer); - - buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted)); - buffer_free(&encrypted); - - return 1; -} - -/* convert SSH v2 key in OpenSSL PEM format */ -static int -key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase, - const char *comment) -{ - int success = 0; - int blen, len = strlen(_passphrase); - u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; -#if (OPENSSL_VERSION_NUMBER < 0x00907000L) - const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; -#else - const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; -#endif - const u_char *bptr; - BIO *bio; - - if (len > 0 && len <= 4) { - error("passphrase too short: have %d bytes, need > 4", len); - return 0; - } - if ((bio = BIO_new(BIO_s_mem())) == NULL) { - error("%s: BIO_new failed", __func__); - return 0; - } - switch (key->type) { - case KEY_DSA: - success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, - cipher, passphrase, len, NULL, NULL); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, - cipher, passphrase, len, NULL, NULL); - break; -#endif - case KEY_RSA: - success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, - cipher, passphrase, len, NULL, NULL); - break; - } - if (success) { - if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) - success = 0; - else - buffer_append(blob, bptr, blen); - } - BIO_free(bio); - return success; -} - /* Save a key blob to a file */ static int -key_save_private_blob(Buffer *keybuf, const char *filename) +sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename) { - int fd; + int fd, oerrno; - if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { - error("open %s failed: %s.", filename, strerror(errno)); - return 0; - } - if (atomicio(vwrite, fd, buffer_ptr(keybuf), - buffer_len(keybuf)) != buffer_len(keybuf)) { - error("write to key file %s failed: %s", filename, - strerror(errno)); + if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) + return SSH_ERR_SYSTEM_ERROR; + if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf), + sshbuf_len(keybuf)) != sshbuf_len(keybuf)) { + oerrno = errno; close(fd); unlink(filename); - return 0; + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; } close(fd); - return 1; -} - -/* Serialise "key" to buffer "blob" */ -static int -key_private_to_blob(Key *key, Buffer *blob, const char *passphrase, - const char *comment, int force_new_format, const char *new_format_cipher, - int new_format_rounds) -{ - switch (key->type) { - case KEY_RSA1: - return key_private_rsa1_to_blob(key, blob, passphrase, comment); - case KEY_DSA: - case KEY_ECDSA: - case KEY_RSA: - if (force_new_format) { - return key_private_to_blob2(key, blob, passphrase, - comment, new_format_cipher, new_format_rounds); - } - return key_private_pem_to_blob(key, blob, passphrase, comment); - case KEY_ED25519: - return key_private_to_blob2(key, blob, passphrase, - comment, new_format_cipher, new_format_rounds); - default: - error("%s: cannot save key type %d", __func__, key->type); - return 0; - } + return 0; } int -key_save_private(Key *key, const char *filename, const char *passphrase, - const char *comment, int force_new_format, const char *new_format_cipher, - int new_format_rounds) +sshkey_save_private(struct sshkey *key, const char *filename, + const char *passphrase, const char *comment, + int force_new_format, const char *new_format_cipher, int new_format_rounds) { - Buffer keyblob; - int success = 0; + struct sshbuf *keyblob = NULL; + int r; - buffer_init(&keyblob); - if (!key_private_to_blob(key, &keyblob, passphrase, comment, - force_new_format, new_format_cipher, new_format_rounds)) + if ((keyblob = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment, + force_new_format, new_format_cipher, new_format_rounds)) != 0) goto out; - if (!key_save_private_blob(&keyblob, filename)) + if ((r = sshkey_save_private_blob(keyblob, filename)) != 0) goto out; - success = 1; + r = 0; out: - buffer_free(&keyblob); - return success; -} - -/* - * Parse the public, unencrypted portion of a RSA1 key. - */ -static Key * -key_parse_public_rsa1(Buffer *blob, char **commentp) -{ - Key *pub; - Buffer copy; - - /* Check that it is at least big enough to contain the ID string. */ - if (buffer_len(blob) < sizeof(authfile_id_string)) { - debug3("Truncated RSA1 identifier"); - return NULL; - } - - /* - * Make sure it begins with the id string. Consume the id string - * from the buffer. - */ - if (memcmp(buffer_ptr(blob), authfile_id_string, - sizeof(authfile_id_string)) != 0) { - debug3("Incorrect RSA1 identifier"); - return NULL; - } - buffer_init(©); - buffer_append(©, buffer_ptr(blob), buffer_len(blob)); - buffer_consume(©, sizeof(authfile_id_string)); - - /* Skip cipher type and reserved data. */ - (void) buffer_get_char(©); /* cipher type */ - (void) buffer_get_int(©); /* reserved */ - - /* Read the public key from the buffer. */ - (void) buffer_get_int(©); - pub = key_new(KEY_RSA1); - buffer_get_bignum(©, pub->rsa->n); - buffer_get_bignum(©, pub->rsa->e); - if (commentp) - *commentp = buffer_get_string(©, NULL); - /* The encrypted private part is not parsed by this function. */ - buffer_free(©); - - return pub; + sshbuf_free(keyblob); + return r; } /* Load a key from a fd into a buffer */ int -key_load_file(int fd, const char *filename, Buffer *blob) +sshkey_load_file(int fd, struct sshbuf *blob) { u_char buf[1024]; size_t len; struct stat st; + int r; - if (fstat(fd, &st) < 0) { - error("%s: fstat of key file %.200s%sfailed: %.100s", __func__, - filename == NULL ? "" : filename, - filename == NULL ? "" : " ", - strerror(errno)); - return 0; - } + if (fstat(fd, &st) < 0) + return SSH_ERR_SYSTEM_ERROR; if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && - st.st_size > MAX_KEY_FILE_SIZE) { - toobig: - error("%s: key file %.200s%stoo large", __func__, - filename == NULL ? "" : filename, - filename == NULL ? "" : " "); - return 0; - } - buffer_clear(blob); + st.st_size > MAX_KEY_FILE_SIZE) + return SSH_ERR_INVALID_FORMAT; for (;;) { if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { if (errno == EPIPE) break; - debug("%s: read from key file %.200s%sfailed: %.100s", - __func__, filename == NULL ? "" : filename, - filename == NULL ? "" : " ", strerror(errno)); - buffer_clear(blob); - explicit_bzero(buf, sizeof(buf)); - return 0; + r = SSH_ERR_SYSTEM_ERROR; + goto out; } - buffer_append(blob, buf, len); - if (buffer_len(blob) > MAX_KEY_FILE_SIZE) { - buffer_clear(blob); - explicit_bzero(buf, sizeof(buf)); - goto toobig; + if ((r = sshbuf_put(blob, buf, len)) != 0) + goto out; + if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) { + r = SSH_ERR_INVALID_FORMAT; + goto out; } } - explicit_bzero(buf, sizeof(buf)); if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && - st.st_size != buffer_len(blob)) { - debug("%s: key file %.200s%schanged size while reading", - __func__, filename == NULL ? "" : filename, - filename == NULL ? "" : " "); - buffer_clear(blob); - return 0; + st.st_size != (off_t)sshbuf_len(blob)) { + r = SSH_ERR_FILE_CHANGED; + goto out; } + r = 0; - return 1; + out: + explicit_bzero(buf, sizeof(buf)); + if (r != 0) + sshbuf_reset(blob); + return r; } +#ifdef WITH_SSH1 /* * Loads the public part of the ssh v1 key file. Returns NULL if an error was * encountered (the file does not exist or is not readable), and the key * otherwise. */ -static Key * -key_load_public_rsa1(int fd, const char *filename, char **commentp) -{ - Buffer buffer; - Key *pub; - - buffer_init(&buffer); - if (!key_load_file(fd, filename, &buffer)) { - buffer_free(&buffer); - return NULL; - } - - pub = key_parse_public_rsa1(&buffer, commentp); - if (pub == NULL) - debug3("Could not load \"%s\" as a RSA1 public key", filename); - buffer_free(&buffer); - return pub; -} - -/* load public key from private-key file, works only for SSH v1 */ -Key * -key_load_public_type(int type, const char *filename, char **commentp) -{ - Key *pub; - int fd; - - if (type == KEY_RSA1) { - fd = open(filename, O_RDONLY); - if (fd < 0) - return NULL; - pub = key_load_public_rsa1(fd, filename, commentp); - close(fd); - return pub; - } - return NULL; -} - -static Key * -key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp) +static int +sshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp) { - int check1, check2, cipher_type; - Buffer decrypted; - u_char *cp; - CipherContext ciphercontext; - const Cipher *cipher; - Key *prv = NULL; - Buffer copy; - - /* Check that it is at least big enough to contain the ID string. */ - if (buffer_len(blob) < sizeof(authfile_id_string)) { - debug3("Truncated RSA1 identifier"); - return NULL; - } - - /* - * Make sure it begins with the id string. Consume the id string - * from the buffer. - */ - if (memcmp(buffer_ptr(blob), authfile_id_string, - sizeof(authfile_id_string)) != 0) { - debug3("Incorrect RSA1 identifier"); - return NULL; - } - buffer_init(©); - buffer_append(©, buffer_ptr(blob), buffer_len(blob)); - buffer_consume(©, sizeof(authfile_id_string)); - - /* Read cipher type. */ - cipher_type = buffer_get_char(©); - (void) buffer_get_int(©); /* Reserved data. */ - - /* Read the public key from the buffer. */ - (void) buffer_get_int(©); - prv = key_new_private(KEY_RSA1); - - buffer_get_bignum(©, prv->rsa->n); - buffer_get_bignum(©, prv->rsa->e); - if (commentp) - *commentp = buffer_get_string(©, NULL); - else - (void)buffer_get_string_ptr(©, NULL); - - /* Check that it is a supported cipher. */ - cipher = cipher_by_number(cipher_type); - if (cipher == NULL) { - debug("Unsupported RSA1 cipher %d", cipher_type); - buffer_free(©); - goto fail; - } - /* Initialize space for decrypted data. */ - buffer_init(&decrypted); - cp = buffer_append_space(&decrypted, buffer_len(©)); - - /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ - cipher_set_key_string(&ciphercontext, cipher, passphrase, - CIPHER_DECRYPT); - if (cipher_crypt(&ciphercontext, 0, cp, - buffer_ptr(©), buffer_len(©), 0, 0) != 0) - fatal("%s: cipher_crypt failed", __func__); - cipher_cleanup(&ciphercontext); - explicit_bzero(&ciphercontext, sizeof(ciphercontext)); - buffer_free(©); - - check1 = buffer_get_char(&decrypted); - check2 = buffer_get_char(&decrypted); - if (check1 != buffer_get_char(&decrypted) || - check2 != buffer_get_char(&decrypted)) { - if (strcmp(passphrase, "") != 0) - debug("Bad passphrase supplied for RSA1 key"); - /* Bad passphrase. */ - buffer_free(&decrypted); - goto fail; - } - /* Read the rest of the private key. */ - buffer_get_bignum(&decrypted, prv->rsa->d); - buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */ - /* in SSL and SSH v1 p and q are exchanged */ - buffer_get_bignum(&decrypted, prv->rsa->q); /* p */ - buffer_get_bignum(&decrypted, prv->rsa->p); /* q */ - - /* calculate p-1 and q-1 */ - rsa_generate_additional_parameters(prv->rsa); - - buffer_free(&decrypted); - - /* enable blinding */ - if (RSA_blinding_on(prv->rsa, NULL) != 1) { - error("%s: RSA_blinding_on failed", __func__); - goto fail; - } - return prv; + struct sshbuf *b = NULL; + int r; -fail: + *keyp = NULL; if (commentp != NULL) - free(*commentp); - key_free(prv); - return NULL; -} - -static Key * -key_parse_private_pem(Buffer *blob, int type, const char *passphrase, - char **commentp) -{ - EVP_PKEY *pk = NULL; - Key *prv = NULL; - char *name = ""; - BIO *bio; - - if ((bio = BIO_new_mem_buf(buffer_ptr(blob), - buffer_len(blob))) == NULL) { - error("%s: BIO_new_mem_buf failed", __func__); - return NULL; - } - - pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase); - BIO_free(bio); - if (pk == NULL) { - debug("%s: PEM_read_PrivateKey failed", __func__); - (void)ERR_get_error(); - } else if (pk->type == EVP_PKEY_RSA && - (type == KEY_UNSPEC||type==KEY_RSA)) { - prv = key_new(KEY_UNSPEC); - prv->rsa = EVP_PKEY_get1_RSA(pk); - prv->type = KEY_RSA; - name = "rsa w/o comment"; -#ifdef DEBUG_PK - RSA_print_fp(stderr, prv->rsa, 8); -#endif - if (RSA_blinding_on(prv->rsa, NULL) != 1) { - error("%s: RSA_blinding_on failed", __func__); - key_free(prv); - prv = NULL; - } - } else if (pk->type == EVP_PKEY_DSA && - (type == KEY_UNSPEC||type==KEY_DSA)) { - prv = key_new(KEY_UNSPEC); - prv->dsa = EVP_PKEY_get1_DSA(pk); - prv->type = KEY_DSA; - name = "dsa w/o comment"; -#ifdef DEBUG_PK - DSA_print_fp(stderr, prv->dsa, 8); -#endif -#ifdef OPENSSL_HAS_ECC - } else if (pk->type == EVP_PKEY_EC && - (type == KEY_UNSPEC||type==KEY_ECDSA)) { - prv = key_new(KEY_UNSPEC); - prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); - prv->type = KEY_ECDSA; - if ((prv->ecdsa_nid = key_ecdsa_key_to_nid(prv->ecdsa)) == -1 || - key_curve_nid_to_name(prv->ecdsa_nid) == NULL || - key_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), - EC_KEY_get0_public_key(prv->ecdsa)) != 0 || - key_ec_validate_private(prv->ecdsa) != 0) { - error("%s: bad ECDSA key", __func__); - key_free(prv); - prv = NULL; - } - name = "ecdsa w/o comment"; -#ifdef DEBUG_PK - if (prv != NULL && prv->ecdsa != NULL) - key_dump_ec_key(prv->ecdsa); -#endif -#endif /* OPENSSL_HAS_ECC */ - } else { - error("%s: PEM_read_PrivateKey: mismatch or " - "unknown EVP_PKEY save_type %d", __func__, pk->save_type); - } - if (pk != NULL) - EVP_PKEY_free(pk); - if (prv != NULL && commentp) - *commentp = xstrdup(name); - debug("read PEM private key done: type %s", - prv ? key_type(prv) : ""); - return prv; -} + *commentp = NULL; -Key * -key_load_private_pem(int fd, int type, const char *passphrase, - char **commentp) -{ - Buffer buffer; - Key *prv; - - buffer_init(&buffer); - if (!key_load_file(fd, NULL, &buffer)) { - buffer_free(&buffer); - return NULL; - } - prv = key_parse_private_pem(&buffer, type, passphrase, commentp); - buffer_free(&buffer); - return prv; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_load_file(fd, b)) != 0) + goto out; + if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0) + goto out; + r = 0; + out: + sshbuf_free(b); + return r; } +#endif /* WITH_SSH1 */ +/* XXX remove error() calls from here? */ int -key_perm_ok(int fd, const char *filename) +sshkey_perm_ok(int fd, const char *filename) { struct stat st; if (fstat(fd, &st) < 0) - return 0; + return SSH_ERR_SYSTEM_ERROR; /* * if a key owned by the user is accessed, then we check the * permissions of the file. if the key owned by a different user, @@ -987,296 +188,325 @@ key_perm_ok(int fd, const char *filename) (u_int)st.st_mode & 0777, filename); error("It is required that your private key files are NOT accessible by others."); error("This private key will be ignored."); - return 0; + return SSH_ERR_KEY_BAD_PERMISSIONS; } - return 1; + return 0; } -static Key * -key_parse_private_type(Buffer *blob, int type, const char *passphrase, - char **commentp) +/* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */ +int +sshkey_load_private_type(int type, const char *filename, const char *passphrase, + struct sshkey **keyp, char **commentp, int *perm_ok) { - Key *k; + int fd, r; - switch (type) { - case KEY_RSA1: - return key_parse_private_rsa1(blob, passphrase, commentp); - case KEY_DSA: - case KEY_ECDSA: - case KEY_RSA: - return key_parse_private_pem(blob, type, passphrase, commentp); - case KEY_ED25519: - return key_parse_private2(blob, type, passphrase, commentp); - case KEY_UNSPEC: - if ((k = key_parse_private2(blob, type, passphrase, commentp))) - return k; - return key_parse_private_pem(blob, type, passphrase, commentp); - default: - error("%s: cannot parse key type %d", __func__, type); - break; - } - return NULL; -} - -Key * -key_load_private_type(int type, const char *filename, const char *passphrase, - char **commentp, int *perm_ok) -{ - int fd; - Key *ret; - Buffer buffer; + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; - fd = open(filename, O_RDONLY); - if (fd < 0) { - debug("could not open key file '%s': %s", filename, - strerror(errno)); + if ((fd = open(filename, O_RDONLY)) < 0) { if (perm_ok != NULL) *perm_ok = 0; - return NULL; + return SSH_ERR_SYSTEM_ERROR; } - if (!key_perm_ok(fd, filename)) { + if (sshkey_perm_ok(fd, filename) != 0) { if (perm_ok != NULL) *perm_ok = 0; - error("bad permissions: ignore key: %s", filename); - close(fd); - return NULL; + r = SSH_ERR_KEY_BAD_PERMISSIONS; + goto out; } if (perm_ok != NULL) *perm_ok = 1; - buffer_init(&buffer); - if (!key_load_file(fd, filename, &buffer)) { - buffer_free(&buffer); - close(fd); - return NULL; - } + r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp); + out: close(fd); - ret = key_parse_private_type(&buffer, type, passphrase, commentp); - buffer_free(&buffer); - return ret; + return r; } -Key * -key_parse_private(Buffer *buffer, const char *filename, - const char *passphrase, char **commentp) +int +sshkey_load_private_type_fd(int fd, int type, const char *passphrase, + struct sshkey **keyp, char **commentp) { - Key *pub, *prv; + struct sshbuf *buffer = NULL; + int r; - /* it's a SSH v1 key if the public key part is readable */ - pub = key_parse_public_rsa1(buffer, commentp); - if (pub == NULL) { - prv = key_parse_private_type(buffer, KEY_UNSPEC, - passphrase, NULL); - /* use the filename as a comment for PEM */ - if (commentp && prv) - *commentp = xstrdup(filename); - } else { - key_free(pub); - /* key_parse_public_rsa1() has already loaded the comment */ - prv = key_parse_private_type(buffer, KEY_RSA1, passphrase, - NULL); + if ((buffer = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } - return prv; + if ((r = sshkey_load_file(fd, buffer)) != 0 || + (r = sshkey_parse_private_fileblob_type(buffer, type, + passphrase, keyp, commentp)) != 0) + goto out; + + /* success */ + r = 0; + out: + if (buffer != NULL) + sshbuf_free(buffer); + return r; } -Key * -key_load_private(const char *filename, const char *passphrase, - char **commentp) +/* XXX this is almost identical to sshkey_load_private_type() */ +int +sshkey_load_private(const char *filename, const char *passphrase, + struct sshkey **keyp, char **commentp) { - Key *prv; - Buffer buffer; - int fd; + struct sshbuf *buffer = NULL; + int r, fd; - fd = open(filename, O_RDONLY); - if (fd < 0) { - debug("could not open key file '%s': %s", filename, - strerror(errno)); - return NULL; - } - if (!key_perm_ok(fd, filename)) { - error("bad permissions: ignore key: %s", filename); - close(fd); - return NULL; + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; + + if ((fd = open(filename, O_RDONLY)) < 0) + return SSH_ERR_SYSTEM_ERROR; + if (sshkey_perm_ok(fd, filename) != 0) { + r = SSH_ERR_KEY_BAD_PERMISSIONS; + goto out; } - buffer_init(&buffer); - if (!key_load_file(fd, filename, &buffer)) { - buffer_free(&buffer); - close(fd); - return NULL; + if ((buffer = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } + if ((r = sshkey_load_file(fd, buffer)) != 0 || + (r = sshkey_parse_private_fileblob(buffer, passphrase, filename, + keyp, commentp)) != 0) + goto out; + r = 0; + out: close(fd); - - prv = key_parse_private(&buffer, filename, passphrase, commentp); - buffer_free(&buffer); - return prv; + if (buffer != NULL) + sshbuf_free(buffer); + return r; } static int -key_try_load_public(Key *k, const char *filename, char **commentp) +sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) { FILE *f; char line[SSH_MAX_PUBKEY_BYTES]; char *cp; u_long linenum = 0; + int r; - f = fopen(filename, "r"); - if (f != NULL) { - while (read_keyfile_line(f, filename, line, sizeof(line), - &linenum) != -1) { - cp = line; - switch (*cp) { - case '#': - case '\n': - case '\0': - continue; - } - /* Abort loading if this looks like a private key */ - if (strncmp(cp, "-----BEGIN", 10) == 0) - break; - /* Skip leading whitespace. */ - for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) - ; - if (*cp) { - if (key_read(k, &cp) == 1) { - cp[strcspn(cp, "\r\n")] = '\0'; - if (commentp) { - *commentp = xstrdup(*cp ? - cp : filename); - } - fclose(f); - return 1; + if (commentp != NULL) + *commentp = NULL; + if ((f = fopen(filename, "r")) == NULL) + return SSH_ERR_SYSTEM_ERROR; + while (read_keyfile_line(f, filename, line, sizeof(line), + &linenum) != -1) { + cp = line; + switch (*cp) { + case '#': + case '\n': + case '\0': + continue; + } + /* Abort loading if this looks like a private key */ + if (strncmp(cp, "-----BEGIN", 10) == 0 || + strcmp(cp, "SSH PRIVATE KEY FILE") == 0) + break; + /* Skip leading whitespace. */ + for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) + ; + if (*cp) { + if ((r = sshkey_read(k, &cp)) == 0) { + cp[strcspn(cp, "\r\n")] = '\0'; + if (commentp) { + *commentp = strdup(*cp ? + cp : filename); + if (*commentp == NULL) + r = SSH_ERR_ALLOC_FAIL; } + fclose(f); + return r; } } - fclose(f); } - return 0; + fclose(f); + return SSH_ERR_INVALID_FORMAT; } /* load public key from ssh v1 private or any pubkey file */ -Key * -key_load_public(const char *filename, char **commentp) +int +sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) { - Key *pub; - char file[MAXPATHLEN]; + struct sshkey *pub = NULL; + char file[PATH_MAX]; + int r, fd; + + if (keyp != NULL) + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; + /* XXX should load file once and attempt to parse each format */ + + if ((fd = open(filename, O_RDONLY)) < 0) + goto skip; +#ifdef WITH_SSH1 /* try rsa1 private key */ - pub = key_load_public_type(KEY_RSA1, filename, commentp); - if (pub != NULL) - return pub; + r = sshkey_load_public_rsa1(fd, keyp, commentp); + close(fd); + switch (r) { + case SSH_ERR_INTERNAL_ERROR: + case SSH_ERR_ALLOC_FAIL: + case SSH_ERR_INVALID_ARGUMENT: + case SSH_ERR_SYSTEM_ERROR: + case 0: + return r; + } +#else /* WITH_SSH1 */ + close(fd); +#endif /* WITH_SSH1 */ + + /* try ssh2 public key */ + if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { + if (keyp != NULL) + *keyp = pub; + return 0; + } + sshkey_free(pub); +#ifdef WITH_SSH1 /* try rsa1 public key */ - pub = key_new(KEY_RSA1); - if (key_try_load_public(pub, filename, commentp) == 1) - return pub; - key_free(pub); + if ((pub = sshkey_new(KEY_RSA1)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { + if (keyp != NULL) + *keyp = pub; + return 0; + } + sshkey_free(pub); +#endif /* WITH_SSH1 */ - /* try ssh2 public key */ - pub = key_new(KEY_UNSPEC); - if (key_try_load_public(pub, filename, commentp) == 1) - return pub; + skip: + /* try .pub suffix */ + if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) + return SSH_ERR_ALLOC_FAIL; + r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */ if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && (strlcat(file, ".pub", sizeof file) < sizeof(file)) && - (key_try_load_public(pub, file, commentp) == 1)) - return pub; - key_free(pub); - return NULL; + (r = sshkey_try_load_public(pub, file, commentp)) == 0) { + if (keyp != NULL) + *keyp = pub; + return 0; + } + sshkey_free(pub); + + return r; } /* Load the certificate associated with the named private key */ -Key * -key_load_cert(const char *filename) +int +sshkey_load_cert(const char *filename, struct sshkey **keyp) { - Key *pub; - char *file; + struct sshkey *pub = NULL; + char *file = NULL; + int r = SSH_ERR_INTERNAL_ERROR; - pub = key_new(KEY_UNSPEC); - xasprintf(&file, "%s-cert.pub", filename); - if (key_try_load_public(pub, file, NULL) == 1) { - free(file); - return pub; + *keyp = NULL; + + if (asprintf(&file, "%s-cert.pub", filename) == -1) + return SSH_ERR_ALLOC_FAIL; + + if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { + goto out; } - free(file); - key_free(pub); - return NULL; + if ((r = sshkey_try_load_public(pub, file, NULL)) != 0) + goto out; + + *keyp = pub; + pub = NULL; + r = 0; + + out: + if (file != NULL) + free(file); + if (pub != NULL) + sshkey_free(pub); + return r; } /* Load private key and certificate */ -Key * -key_load_private_cert(int type, const char *filename, const char *passphrase, - int *perm_ok) +int +sshkey_load_private_cert(int type, const char *filename, const char *passphrase, + struct sshkey **keyp, int *perm_ok) { - Key *key, *pub; + struct sshkey *key = NULL, *cert = NULL; + int r; + + *keyp = NULL; switch (type) { +#ifdef WITH_OPENSSL case KEY_RSA: case KEY_DSA: case KEY_ECDSA: +#endif /* WITH_OPENSSL */ case KEY_ED25519: + case KEY_UNSPEC: break; default: - error("%s: unsupported key type", __func__); - return NULL; + return SSH_ERR_KEY_TYPE_UNKNOWN; } - if ((key = key_load_private_type(type, filename, - passphrase, NULL, perm_ok)) == NULL) - return NULL; - - if ((pub = key_load_cert(filename)) == NULL) { - key_free(key); - return NULL; - } + if ((r = sshkey_load_private_type(type, filename, + passphrase, &key, NULL, perm_ok)) != 0 || + (r = sshkey_load_cert(filename, &cert)) != 0) + goto out; /* Make sure the private key matches the certificate */ - if (key_equal_public(key, pub) == 0) { - error("%s: certificate does not match private key %s", - __func__, filename); - } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) { - error("%s: key_to_certified failed", __func__); - } else { - key_cert_copy(pub, key); - key_free(pub); - return key; + if (sshkey_equal_public(key, cert) == 0) { + r = SSH_ERR_KEY_CERT_MISMATCH; + goto out; } - key_free(key); - key_free(pub); - return NULL; + if ((r = sshkey_to_certified(key)) != 0 || + (r = sshkey_cert_copy(cert, key)) != 0) + goto out; + r = 0; + *keyp = key; + key = NULL; + out: + if (key != NULL) + sshkey_free(key); + if (cert != NULL) + sshkey_free(cert); + return r; } /* - * Returns 1 if the specified "key" is listed in the file "filename", - * 0 if the key is not listed or -1 on error. - * If strict_type is set then the key type must match exactly, + * Returns success if the specified "key" is listed in the file "filename", + * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error. + * If "strict_type" is set then the key type must match exactly, * otherwise a comparison that ignores certficiate data is performed. + * If "check_ca" is set and "key" is a certificate, then its CA key is + * also checked and sshkey_in_file() will return success if either is found. */ int -key_in_file(Key *key, const char *filename, int strict_type) +sshkey_in_file(struct sshkey *key, const char *filename, int strict_type, + int check_ca) { FILE *f; char line[SSH_MAX_PUBKEY_BYTES]; char *cp; u_long linenum = 0; - int ret = 0; - Key *pub; - int (*key_compare)(const Key *, const Key *) = strict_type ? - key_equal : key_equal_public; + int r = 0; + struct sshkey *pub = NULL; + int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) = + strict_type ? sshkey_equal : sshkey_equal_public; - if ((f = fopen(filename, "r")) == NULL) { - if (errno == ENOENT) { - debug("%s: keyfile \"%s\" missing", __func__, filename); - return 0; - } else { - error("%s: could not open keyfile \"%s\": %s", __func__, - filename, strerror(errno)); - return -1; - } - } + if ((f = fopen(filename, "r")) == NULL) + return SSH_ERR_SYSTEM_ERROR; while (read_keyfile_line(f, filename, line, sizeof(line), - &linenum) != -1) { + &linenum) != -1) { cp = line; /* Skip leading whitespace. */ @@ -1291,18 +521,60 @@ key_in_file(Key *key, const char *filename, int strict_type) continue; } - pub = key_new(KEY_UNSPEC); - if (key_read(pub, &cp) != 1) { - key_free(pub); - continue; + if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } - if (key_compare(key, pub)) { - ret = 1; - key_free(pub); - break; + if ((r = sshkey_read(pub, &cp)) != 0) + goto out; + if (sshkey_compare(key, pub) || + (check_ca && sshkey_is_cert(key) && + sshkey_compare(key->cert->signature_key, pub))) { + r = 0; + goto out; } - key_free(pub); + sshkey_free(pub); + pub = NULL; } + r = SSH_ERR_KEY_NOT_FOUND; + out: + if (pub != NULL) + sshkey_free(pub); fclose(f); - return ret; + return r; +} + +/* + * Checks whether the specified key is revoked, returning 0 if not, + * SSH_ERR_KEY_REVOKED if it is or another error code if something + * unexpected happened. + * This will check both the key and, if it is a certificate, its CA key too. + * "revoked_keys_file" may be a KRL or a one-per-line list of public keys. + */ +int +sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file) +{ + int r; + + r = ssh_krl_file_contains_key(revoked_keys_file, key); + /* If this was not a KRL to begin with then continue below */ + if (r != SSH_ERR_KRL_BAD_MAGIC) + return r; + + /* + * If the file is not a KRL or we can't handle KRLs then attempt to + * parse the file as a flat list of keys. + */ + switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) { + case 0: + /* Key found => revoked */ + return SSH_ERR_KEY_REVOKED; + case SSH_ERR_KEY_NOT_FOUND: + /* Key not found => not revoked */ + return 0; + default: + /* Some other error occurred */ + return r; + } } + diff --git a/crypto/openssh/authfile.h b/crypto/openssh/authfile.h index 8ba1c2d..624d269 100644 --- a/crypto/openssh/authfile.h +++ b/crypto/openssh/authfile.h @@ -1,32 +1,52 @@ -/* $OpenBSD: authfile.h,v 1.17 2013/12/06 13:34:54 markus Exp $ */ +/* $OpenBSD: authfile.h,v 1.21 2015/01/08 10:14:08 djm Exp $ */ /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved + * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef AUTHFILE_H #define AUTHFILE_H -int key_save_private(Key *, const char *, const char *, const char *, - int, const char *, int); -int key_load_file(int, const char *, Buffer *); -Key *key_load_cert(const char *); -Key *key_load_public(const char *, char **); -Key *key_load_public_type(int, const char *, char **); -Key *key_parse_private(Buffer *, const char *, const char *, char **); -Key *key_load_private(const char *, const char *, char **); -Key *key_load_private_cert(int, const char *, const char *, int *); -Key *key_load_private_type(int, const char *, const char *, char **, int *); -Key *key_load_private_pem(int, int, const char *, char **); -int key_perm_ok(int, const char *); -int key_in_file(Key *, const char *, int); +struct sshbuf; +struct sshkey; + +/* XXX document these */ +/* XXX some of these could probably be merged/retired */ + +int sshkey_save_private(struct sshkey *, const char *, + const char *, const char *, int, const char *, int); +int sshkey_load_file(int, struct sshbuf *); +int sshkey_load_cert(const char *, struct sshkey **); +int sshkey_load_public(const char *, struct sshkey **, char **); +int sshkey_load_private(const char *, const char *, struct sshkey **, char **); +int sshkey_load_private_cert(int, const char *, const char *, + struct sshkey **, int *); +int sshkey_load_private_type(int, const char *, const char *, + struct sshkey **, char **, int *); +int sshkey_load_private_type_fd(int fd, int type, const char *passphrase, + struct sshkey **keyp, char **commentp); +int sshkey_perm_ok(int, const char *); +int sshkey_in_file(struct sshkey *, const char *, int, int); +int sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file); #endif diff --git a/crypto/openssh/bitmap.c b/crypto/openssh/bitmap.c new file mode 100644 index 0000000..f950322 --- /dev/null +++ b/crypto/openssh/bitmap.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2015 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include +#include +#include + +#include "bitmap.h" + +#define BITMAP_WTYPE u_int +#define BITMAP_MAX (1<<24) +#define BITMAP_BYTES (sizeof(BITMAP_WTYPE)) +#define BITMAP_BITS (sizeof(BITMAP_WTYPE) * 8) +#define BITMAP_WMASK ((BITMAP_WTYPE)BITMAP_BITS - 1) +struct bitmap { + BITMAP_WTYPE *d; + size_t len; /* number of words allocated */ + size_t top; /* index of top word allocated */ +}; + +struct bitmap * +bitmap_new(void) +{ + struct bitmap *ret; + + if ((ret = calloc(1, sizeof(*ret))) == NULL) + return NULL; + if ((ret->d = calloc(1, BITMAP_BYTES)) == NULL) { + free(ret); + return NULL; + } + ret->len = 1; + ret->top = 0; + return ret; +} + +void +bitmap_free(struct bitmap *b) +{ + if (b != NULL && b->d != NULL) { + explicit_bzero(b->d, b->len); + free(b->d); + } + free(b); +} + +void +bitmap_zero(struct bitmap *b) +{ + memset(b->d, 0, b->len * BITMAP_BYTES); + b->top = 0; +} + +int +bitmap_test_bit(struct bitmap *b, u_int n) +{ + if (b->top >= b->len) + return 0; /* invalid */ + if (b->len == 0 || (n / BITMAP_BITS) > b->top) + return 0; + return (b->d[n / BITMAP_BITS] >> (n & BITMAP_WMASK)) & 1; +} + +static int +reserve(struct bitmap *b, u_int n) +{ + BITMAP_WTYPE *tmp; + size_t nlen; + + if (b->top >= b->len || n > BITMAP_MAX) + return -1; /* invalid */ + nlen = (n / BITMAP_BITS) + 1; + if (b->len < nlen) { + if ((tmp = reallocarray(b->d, nlen, BITMAP_BYTES)) == NULL) + return -1; + b->d = tmp; + memset(b->d + b->len, 0, (nlen - b->len) * BITMAP_BYTES); + b->len = nlen; + } + return 0; +} + +int +bitmap_set_bit(struct bitmap *b, u_int n) +{ + int r; + size_t offset; + + if ((r = reserve(b, n)) != 0) + return r; + offset = n / BITMAP_BITS; + if (offset > b->top) + b->top = offset; + b->d[offset] |= (BITMAP_WTYPE)1 << (n & BITMAP_WMASK); + return 0; +} + +/* Resets b->top to point to the most significant bit set in b->d */ +static void +retop(struct bitmap *b) +{ + if (b->top >= b->len) + return; + while (b->top > 0 && b->d[b->top] == 0) + b->top--; +} + +void +bitmap_clear_bit(struct bitmap *b, u_int n) +{ + size_t offset; + + if (b->top >= b->len || n > BITMAP_MAX) + return; /* invalid */ + offset = n / BITMAP_BITS; + if (offset > b->top) + return; + b->d[offset] &= ~((BITMAP_WTYPE)1 << (n & BITMAP_WMASK)); + /* The top may have changed as a result of the clear */ + retop(b); +} + +size_t +bitmap_nbits(struct bitmap *b) +{ + size_t bits; + BITMAP_WTYPE w; + + retop(b); + if (b->top >= b->len) + return 0; /* invalid */ + if (b->len == 0 || (b->top == 0 && b->d[0] == 0)) + return 0; + /* Find MSB set */ + w = b->d[b->top]; + bits = (b->top + 1) * BITMAP_BITS; + while (!(w & ((BITMAP_WTYPE)1 << (BITMAP_BITS - 1)))) { + w <<= 1; + bits--; + } + return bits; +} + +size_t +bitmap_nbytes(struct bitmap *b) +{ + return (bitmap_nbits(b) + 7) / 8; +} + +int +bitmap_to_string(struct bitmap *b, void *p, size_t l) +{ + u_char *s = (u_char *)p; + size_t i, j, k, need = bitmap_nbytes(b); + + if (l < need || b->top >= b->len) + return -1; + if (l > need) + l = need; + /* Put the bytes from LSB backwards */ + for (i = k = 0; i < b->top + 1; i++) { + for (j = 0; j < BITMAP_BYTES; j++) { + if (k >= l) + break; + s[need - 1 - k++] = (b->d[i] >> (j * 8)) & 0xff; + } + } + return 0; +} + +int +bitmap_from_string(struct bitmap *b, const void *p, size_t l) +{ + int r; + size_t i, offset, shift; + u_char *s = (u_char *)p; + + if (l > BITMAP_MAX / 8) + return -1; + if ((r = reserve(b, l * 8)) != 0) + return r; + bitmap_zero(b); + if (l == 0) + return 0; + b->top = offset = ((l + (BITMAP_BYTES - 1)) / BITMAP_BYTES) - 1; + shift = ((l + (BITMAP_BYTES - 1)) % BITMAP_BYTES) * 8; + for (i = 0; i < l; i++) { + b->d[offset] |= (BITMAP_WTYPE)s[i] << shift; + if (shift == 0) { + offset--; + shift = BITMAP_BITS - 8; + } else + shift -= 8; + } + retop(b); + return 0; +} diff --git a/crypto/openssh/bitmap.h b/crypto/openssh/bitmap.h new file mode 100644 index 0000000..c1bb174 --- /dev/null +++ b/crypto/openssh/bitmap.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _BITMAP_H +#define _BITMAP_H + +#include + +/* Simple bit vector routines */ + +struct bitmap; + +/* Allocate a new bitmap. Returns NULL on allocation failure. */ +struct bitmap *bitmap_new(void); + +/* Free a bitmap */ +void bitmap_free(struct bitmap *b); + +/* Zero an existing bitmap */ +void bitmap_zero(struct bitmap *b); + +/* Test whether a bit is set in a bitmap. */ +int bitmap_test_bit(struct bitmap *b, u_int n); + +/* Set a bit in a bitmap. Returns 0 on success or -1 on error */ +int bitmap_set_bit(struct bitmap *b, u_int n); + +/* Clear a bit in a bitmap */ +void bitmap_clear_bit(struct bitmap *b, u_int n); + +/* Return the number of bits in a bitmap (i.e. the position of the MSB) */ +size_t bitmap_nbits(struct bitmap *b); + +/* Return the number of bytes needed to represent a bitmap */ +size_t bitmap_nbytes(struct bitmap *b); + +/* Convert a bitmap to a big endian byte string */ +int bitmap_to_string(struct bitmap *b, void *p, size_t l); + +/* Convert a big endian byte string to a bitmap */ +int bitmap_from_string(struct bitmap *b, const void *p, size_t l); + +#endif /* _BITMAP_H */ diff --git a/crypto/openssh/bufaux.c b/crypto/openssh/bufaux.c index f6a6f2a..3976896 100644 --- a/crypto/openssh/bufaux.c +++ b/crypto/openssh/bufaux.c @@ -1,70 +1,40 @@ -/* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */ +/* $OpenBSD: bufaux.c,v 1.60 2014/04/30 05:29:56 djm Exp $ */ /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Auxiliary functions for storing and retrieving various data types to/from - * Buffers. + * Copyright (c) 2012 Damien Miller * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * - * SSH2 packet format added by Markus Friedl - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ + #include "includes.h" #include -#include - -#include -#include -#include - -#include "xmalloc.h" #include "buffer.h" #include "log.h" -#include "misc.h" - -/* - * Returns integers from the buffer (msb first). - */ +#include "ssherr.h" int -buffer_get_short_ret(u_short *ret, Buffer *buffer) +buffer_get_short_ret(u_short *v, Buffer *buffer) { - u_char buf[2]; + int ret; - if (buffer_get_ret(buffer, (char *) buf, 2) == -1) - return (-1); - *ret = get_u16(buf); - return (0); + if ((ret = sshbuf_get_u16(buffer, v)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; + } + return 0; } u_short @@ -73,21 +43,21 @@ buffer_get_short(Buffer *buffer) u_short ret; if (buffer_get_short_ret(&ret, buffer) == -1) - fatal("buffer_get_short: buffer error"); + fatal("%s: buffer error", __func__); return (ret); } int -buffer_get_int_ret(u_int *ret, Buffer *buffer) +buffer_get_int_ret(u_int *v, Buffer *buffer) { - u_char buf[4]; + int ret; - if (buffer_get_ret(buffer, (char *) buf, 4) == -1) - return (-1); - if (ret != NULL) - *ret = get_u32(buf); - return (0); + if ((ret = sshbuf_get_u32(buffer, v)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; + } + return 0; } u_int @@ -96,21 +66,21 @@ buffer_get_int(Buffer *buffer) u_int ret; if (buffer_get_int_ret(&ret, buffer) == -1) - fatal("buffer_get_int: buffer error"); + fatal("%s: buffer error", __func__); return (ret); } int -buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) +buffer_get_int64_ret(u_int64_t *v, Buffer *buffer) { - u_char buf[8]; + int ret; - if (buffer_get_ret(buffer, (char *) buf, 8) == -1) - return (-1); - if (ret != NULL) - *ret = get_u64(buf); - return (0); + if ((ret = sshbuf_get_u64(buffer, v)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; + } + return 0; } u_int64_t @@ -119,78 +89,52 @@ buffer_get_int64(Buffer *buffer) u_int64_t ret; if (buffer_get_int64_ret(&ret, buffer) == -1) - fatal("buffer_get_int: buffer error"); + fatal("%s: buffer error", __func__); return (ret); } -/* - * Stores integers in the buffer, msb first. - */ void buffer_put_short(Buffer *buffer, u_short value) { - char buf[2]; + int ret; - put_u16(buf, value); - buffer_append(buffer, buf, 2); + if ((ret = sshbuf_put_u16(buffer, value)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); } void buffer_put_int(Buffer *buffer, u_int value) { - char buf[4]; + int ret; - put_u32(buf, value); - buffer_append(buffer, buf, 4); + if ((ret = sshbuf_put_u32(buffer, value)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); } void buffer_put_int64(Buffer *buffer, u_int64_t value) { - char buf[8]; + int ret; - put_u64(buf, value); - buffer_append(buffer, buf, 8); + if ((ret = sshbuf_put_u64(buffer, value)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); } -/* - * Returns an arbitrary binary string from the buffer. The string cannot - * be longer than 256k. The returned value points to memory allocated - * with xmalloc; it is the responsibility of the calling function to free - * the data. If length_ptr is non-NULL, the length of the returned data - * will be stored there. A null character will be automatically appended - * to the returned string, and is not counted in length. - */ void * buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) { + size_t len; + int ret; u_char *value; - u_int len; - /* Get the length. */ - if (buffer_get_int_ret(&len, buffer) != 0) { - error("buffer_get_string_ret: cannot extract length"); - return (NULL); - } - if (len > 256 * 1024) { - error("buffer_get_string_ret: bad string length %u", len); - return (NULL); - } - /* Allocate space for the string. Add one byte for a null character. */ - value = xmalloc(len + 1); - /* Get the string. */ - if (buffer_get_ret(buffer, value, len) == -1) { - error("buffer_get_string_ret: buffer_get failed"); - free(value); - return (NULL); + if ((ret = sshbuf_get_string(buffer, &value, &len)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return NULL; } - /* Append a null character to make processing easier. */ - value[len] = '\0'; - /* Optionally return the length of the string. */ - if (length_ptr) - *length_ptr = len; - return (value); + if (length_ptr != NULL) + *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ + return value; } void * @@ -199,31 +143,24 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr) void *ret; if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) - fatal("buffer_get_string: buffer error"); + fatal("%s: buffer error", __func__); return (ret); } char * buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) { - u_int length; - char *cp, *ret = buffer_get_string_ret(buffer, &length); + size_t len; + int ret; + char *value; - if (ret == NULL) + if ((ret = sshbuf_get_cstring(buffer, &value, &len)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); return NULL; - if ((cp = memchr(ret, '\0', length)) != NULL) { - /* XXX allow \0 at end-of-string for a while, remove later */ - if (cp == ret + length - 1) - error("buffer_get_cstring_ret: string contains \\0"); - else { - explicit_bzero(ret, length); - free(ret); - return NULL; - } } if (length_ptr != NULL) - *length_ptr = length; - return ret; + *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ + return value; } char * @@ -232,162 +169,91 @@ buffer_get_cstring(Buffer *buffer, u_int *length_ptr) char *ret; if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) - fatal("buffer_get_cstring: buffer error"); + fatal("%s: buffer error", __func__); return ret; } -void * +const void * buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) { - void *ptr; - u_int len; + size_t len; + int ret; + const u_char *value; - if (buffer_get_int_ret(&len, buffer) != 0) - return NULL; - if (len > 256 * 1024) { - error("buffer_get_string_ptr: bad string length %u", len); + if ((ret = sshbuf_get_string_direct(buffer, &value, &len)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); return NULL; } - ptr = buffer_ptr(buffer); - buffer_consume(buffer, len); - if (length_ptr) - *length_ptr = len; - return (ptr); + if (length_ptr != NULL) + *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */ + return value; } -void * +const void * buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr) { - void *ret; + const void *ret; if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) - fatal("buffer_get_string_ptr: buffer error"); + fatal("%s: buffer error", __func__); return (ret); } -/* - * Stores and arbitrary binary string in the buffer. - */ void buffer_put_string(Buffer *buffer, const void *buf, u_int len) { - buffer_put_int(buffer, len); - buffer_append(buffer, buf, len); + int ret; + + if ((ret = sshbuf_put_string(buffer, buf, len)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); } + void buffer_put_cstring(Buffer *buffer, const char *s) { - if (s == NULL) - fatal("buffer_put_cstring: s == NULL"); - buffer_put_string(buffer, s, strlen(s)); + int ret; + + if ((ret = sshbuf_put_cstring(buffer, s)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); } -/* - * Returns a character from the buffer (0 - 255). - */ int -buffer_get_char_ret(u_char *ret, Buffer *buffer) +buffer_get_char_ret(char *v, Buffer *buffer) { - if (buffer_get_ret(buffer, ret, 1) == -1) { - error("buffer_get_char_ret: buffer_get_ret failed"); - return (-1); + int ret; + + if ((ret = sshbuf_get_u8(buffer, (u_char *)v)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; } - return (0); + return 0; } int buffer_get_char(Buffer *buffer) { - u_char ch; + char ch; if (buffer_get_char_ret(&ch, buffer) == -1) - fatal("buffer_get_char: buffer error"); - return ch; + fatal("%s: buffer error", __func__); + return (u_char) ch; } -/* - * Stores a character in the buffer. - */ void buffer_put_char(Buffer *buffer, int value) { - char ch = value; + int ret; - buffer_append(buffer, &ch, 1); + if ((ret = sshbuf_put_u8(buffer, value)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); } -/* Pseudo bignum functions */ - -void * -buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr) -{ - u_int len; - u_char *bin, *p, *ret; - - if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) { - error("%s: invalid bignum", __func__); - return NULL; - } - - if (len > 0 && (bin[0] & 0x80)) { - error("%s: negative numbers not supported", __func__); - free(bin); - return NULL; - } - if (len > 8 * 1024) { - error("%s: cannot handle BN of size %d", __func__, len); - free(bin); - return NULL; - } - /* Skip zero prefix on numbers with the MSB set */ - if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) { - p++; - len--; - } - ret = xmalloc(len); - memcpy(ret, p, len); - explicit_bzero(p, len); - free(bin); - return ret; -} - -void * -buffer_get_bignum2_as_string(Buffer *buffer, u_int *l) -{ - void *ret = buffer_get_bignum2_as_string_ret(buffer, l); - - if (ret == NULL) - fatal("%s: buffer error", __func__); - return ret; -} - -/* - * Stores a string using the bignum encoding rules (\0 pad if MSB set). - */ void buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) { - u_char *buf, *p; - int pad = 0; - - if (l > 8 * 1024) - fatal("%s: length %u too long", __func__, l); - /* Skip leading zero bytes */ - for (; l > 0 && *s == 0; l--, s++) - ; - p = buf = xmalloc(l + 1); - /* - * If most significant bit is set then prepend a zero byte to - * avoid interpretation as a negative number. - */ - if (l > 0 && (s[0] & 0x80) != 0) { - *p++ = '\0'; - pad = 1; - } - memcpy(p, s, l); - buffer_put_string(buffer, buf, l + pad); - explicit_bzero(buf, l + pad); - free(buf); -} + int ret; + if ((ret = sshbuf_put_bignum2_bytes(buffer, s, l)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); +} diff --git a/crypto/openssh/bufbn.c b/crypto/openssh/bufbn.c index 1d2e012..33ae7f7 100644 --- a/crypto/openssh/bufbn.c +++ b/crypto/openssh/bufbn.c @@ -1,229 +1,109 @@ -/* $OpenBSD: bufbn.c,v 1.11 2014/02/27 08:25:09 djm Exp $*/ +/* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */ + /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Auxiliary functions for storing and retrieving various data types to/from - * Buffers. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * SSH2 packet format added by Markus Friedl - * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2012 Damien Miller * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "includes.h" +/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ -#include +#include "includes.h" -#include +#ifdef WITH_OPENSSL -#include -#include -#include +#include -#include "xmalloc.h" #include "buffer.h" #include "log.h" -#include "misc.h" +#include "ssherr.h" -/* - * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed - * by (bits+7)/8 bytes of binary data, msb first. - */ +#ifdef WITH_SSH1 int buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value) { - int bits = BN_num_bits(value); - int bin_size = (bits + 7) / 8; - u_char *buf = xmalloc(bin_size); - int oi; - char msg[2]; - - /* Get the value of in binary */ - oi = BN_bn2bin(value, buf); - if (oi != bin_size) { - error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d", - oi, bin_size); - free(buf); - return (-1); - } - - /* Store the number of bits in the buffer in two bytes, msb first. */ - put_u16(msg, bits); - buffer_append(buffer, msg, 2); - /* Store the binary data. */ - buffer_append(buffer, buf, oi); + int ret; - explicit_bzero(buf, bin_size); - free(buf); - - return (0); + if ((ret = sshbuf_put_bignum1(buffer, value)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; + } + return 0; } void buffer_put_bignum(Buffer *buffer, const BIGNUM *value) { if (buffer_put_bignum_ret(buffer, value) == -1) - fatal("buffer_put_bignum: buffer error"); + fatal("%s: buffer error", __func__); } -/* - * Retrieves a BIGNUM from the buffer. - */ int buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value) { - u_int bits, bytes; - u_char buf[2], *bin; + int ret; - /* Get the number of bits. */ - if (buffer_get_ret(buffer, (char *) buf, 2) == -1) { - error("buffer_get_bignum_ret: invalid length"); - return (-1); + if ((ret = sshbuf_get_bignum1(buffer, value)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; } - bits = get_u16(buf); - if (bits > 65535-7) { - error("buffer_get_bignum_ret: cannot handle BN of size %d", - bits); - return (-1); - } - /* Compute the number of binary bytes that follow. */ - bytes = (bits + 7) / 8; - if (bytes > 8 * 1024) { - error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes); - return (-1); - } - if (buffer_len(buffer) < bytes) { - error("buffer_get_bignum_ret: input buffer too small"); - return (-1); - } - bin = buffer_ptr(buffer); - if (BN_bin2bn(bin, bytes, value) == NULL) { - error("buffer_get_bignum_ret: BN_bin2bn failed"); - return (-1); - } - if (buffer_consume_ret(buffer, bytes) == -1) { - error("buffer_get_bignum_ret: buffer_consume failed"); - return (-1); - } - return (0); + return 0; } void buffer_get_bignum(Buffer *buffer, BIGNUM *value) { if (buffer_get_bignum_ret(buffer, value) == -1) - fatal("buffer_get_bignum: buffer error"); + fatal("%s: buffer error", __func__); } +#endif /* WITH_SSH1 */ -/* - * Stores a BIGNUM in the buffer in SSH2 format. - */ int buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value) { - u_int bytes; - u_char *buf; - int oi; - u_int hasnohigh = 0; - - if (BN_is_zero(value)) { - buffer_put_int(buffer, 0); - return 0; - } - if (value->neg) { - error("buffer_put_bignum2_ret: negative numbers not supported"); - return (-1); - } - bytes = BN_num_bytes(value) + 1; /* extra padding byte */ - if (bytes < 2) { - error("buffer_put_bignum2_ret: BN too small"); - return (-1); - } - buf = xmalloc(bytes); - buf[0] = 0x00; - /* Get the value of in binary */ - oi = BN_bn2bin(value, buf+1); - if (oi < 0 || (u_int)oi != bytes - 1) { - error("buffer_put_bignum2_ret: BN_bn2bin() failed: " - "oi %d != bin_size %d", oi, bytes); - free(buf); - return (-1); + int ret; + + if ((ret = sshbuf_put_bignum2(buffer, value)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; } - hasnohigh = (buf[1] & 0x80) ? 0 : 1; - buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); - explicit_bzero(buf, bytes); - free(buf); - return (0); + return 0; } void buffer_put_bignum2(Buffer *buffer, const BIGNUM *value) { if (buffer_put_bignum2_ret(buffer, value) == -1) - fatal("buffer_put_bignum2: buffer error"); + fatal("%s: buffer error", __func__); } int buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value) { - u_int len; - u_char *bin; - - if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) { - error("buffer_get_bignum2_ret: invalid bignum"); - return (-1); - } + int ret; - if (len > 0 && (bin[0] & 0x80)) { - error("buffer_get_bignum2_ret: negative numbers not supported"); - free(bin); - return (-1); - } - if (len > 8 * 1024) { - error("buffer_get_bignum2_ret: cannot handle BN of size %d", - len); - free(bin); - return (-1); + if ((ret = sshbuf_get_bignum2(buffer, value)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; } - if (BN_bin2bn(bin, len, value) == NULL) { - error("buffer_get_bignum2_ret: BN_bin2bn failed"); - free(bin); - return (-1); - } - free(bin); - return (0); + return 0; } void buffer_get_bignum2(Buffer *buffer, BIGNUM *value) { if (buffer_get_bignum2_ret(buffer, value) == -1) - fatal("buffer_get_bignum2: buffer error"); + fatal("%s: buffer error", __func__); } + +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/bufec.c b/crypto/openssh/bufec.c index 89482b9..749ce9d 100644 --- a/crypto/openssh/bufec.c +++ b/crypto/openssh/bufec.c @@ -1,6 +1,7 @@ -/* $OpenBSD: bufec.c,v 1.3 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: bufec.c,v 1.4 2014/04/30 05:29:56 djm Exp $ */ + /* - * Copyright (c) 2010 Damien Miller + * Copyright (c) 2012 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,73 +16,29 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "includes.h" +/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ -#ifdef OPENSSL_HAS_ECC +#include "includes.h" #include -#include -#include - -#include -#include - -#include "xmalloc.h" #include "buffer.h" #include "log.h" -#include "misc.h" +#include "ssherr.h" -/* - * Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed - * encoding represents this as two bitstring points that should each - * be no longer than the field length, SEC1 specifies a 1 byte - * point type header. - * Being paranoid here may insulate us to parsing problems in - * EC_POINT_oct2point. - */ -#define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1) +#ifdef OPENSSL_HAS_ECC -/* - * Append an EC_POINT to the buffer as a string containing a SEC1 encoded - * uncompressed point. Fortunately OpenSSL handles the gory details for us. - */ int buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, const EC_POINT *point) { - u_char *buf = NULL; - size_t len; - BN_CTX *bnctx; - int ret = -1; + int ret; - /* Determine length */ - if ((bnctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new failed", __func__); - len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, bnctx); - if (len > BUFFER_MAX_ECPOINT_LEN) { - error("%s: giant EC point: len = %lu (max %u)", - __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN); - goto out; - } - /* Convert */ - buf = xmalloc(len); - if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, - buf, len, bnctx) != len) { - error("%s: EC_POINT_point2oct length mismatch", __func__); - goto out; - } - /* Append */ - buffer_put_string(buffer, buf, len); - ret = 0; - out: - if (buf != NULL) { - explicit_bzero(buf, len); - free(buf); + if ((ret = sshbuf_put_ec(buffer, point, curve)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; } - BN_CTX_free(bnctx); - return ret; + return 0; } void @@ -96,43 +53,13 @@ int buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, EC_POINT *point) { - u_char *buf; - u_int len; - BN_CTX *bnctx; - int ret = -1; + int ret; - if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) { - error("%s: invalid point", __func__); + if ((ret = sshbuf_get_ec(buffer, point, curve)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); return -1; } - if ((bnctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new failed", __func__); - if (len > BUFFER_MAX_ECPOINT_LEN) { - error("%s: EC_POINT too long: %u > max %u", __func__, - len, BUFFER_MAX_ECPOINT_LEN); - goto out; - } - if (len == 0) { - error("%s: EC_POINT buffer is empty", __func__); - goto out; - } - if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) { - error("%s: EC_POINT is in an incorrect form: " - "0x%02x (want 0x%02x)", __func__, buf[0], - POINT_CONVERSION_UNCOMPRESSED); - goto out; - } - if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) { - error("buffer_get_bignum2_ret: BN_bin2bn failed"); - goto out; - } - /* EC_POINT_oct2point verifies that the point is on the curve for us */ - ret = 0; - out: - BN_CTX_free(bnctx); - explicit_bzero(buf, len); - free(buf); - return ret; + return 0; } void @@ -144,3 +71,4 @@ buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve, } #endif /* OPENSSL_HAS_ECC */ + diff --git a/crypto/openssh/buffer.c b/crypto/openssh/buffer.c index d240f67..c5f708a 100644 --- a/crypto/openssh/buffer.c +++ b/crypto/openssh/buffer.c @@ -1,253 +1,118 @@ -/* $OpenBSD: buffer.c,v 1.35 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: buffer.c,v 1.36 2014/04/30 05:29:56 djm Exp $ */ + /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Functions for manipulating fifo buffers (that can grow if needed). + * Copyright (c) 2012 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "includes.h" +/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ -#include +#include "includes.h" -#include -#include -#include -#include +#include -#include "xmalloc.h" #include "buffer.h" #include "log.h" - -#define BUFFER_MAX_CHUNK 0x100000 -#define BUFFER_MAX_LEN 0xa00000 -#define BUFFER_ALLOCSZ 0x008000 - -/* Initializes the buffer structure. */ - -void -buffer_init(Buffer *buffer) -{ - const u_int len = 4096; - - buffer->alloc = 0; - buffer->buf = xmalloc(len); - buffer->alloc = len; - buffer->offset = 0; - buffer->end = 0; -} - -/* Frees any memory used for the buffer. */ - -void -buffer_free(Buffer *buffer) -{ - if (buffer->alloc > 0) { - explicit_bzero(buffer->buf, buffer->alloc); - buffer->alloc = 0; - free(buffer->buf); - } -} - -/* - * Clears any data from the buffer, making it empty. This does not actually - * zero the memory. - */ - -void -buffer_clear(Buffer *buffer) -{ - buffer->offset = 0; - buffer->end = 0; -} - -/* Appends data to the buffer, expanding it if necessary. */ +#include "ssherr.h" void buffer_append(Buffer *buffer, const void *data, u_int len) { - void *p; - p = buffer_append_space(buffer, len); - memcpy(p, data, len); -} + int ret; -static int -buffer_compact(Buffer *buffer) -{ - /* - * If the buffer is quite empty, but all data is at the end, move the - * data to the beginning. - */ - if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) { - memmove(buffer->buf, buffer->buf + buffer->offset, - buffer->end - buffer->offset); - buffer->end -= buffer->offset; - buffer->offset = 0; - return (1); - } - return (0); + if ((ret = sshbuf_put(buffer, data, len)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); } -/* - * Appends space to the buffer, expanding the buffer if necessary. This does - * not actually copy the data into the buffer, but instead returns a pointer - * to the allocated region. - */ - void * buffer_append_space(Buffer *buffer, u_int len) { - u_int newlen; - void *p; + int ret; + u_char *p; - if (len > BUFFER_MAX_CHUNK) - fatal("buffer_append_space: len %u not supported", len); - - /* If the buffer is empty, start using it from the beginning. */ - if (buffer->offset == buffer->end) { - buffer->offset = 0; - buffer->end = 0; - } -restart: - /* If there is enough space to store all data, store it now. */ - if (buffer->end + len < buffer->alloc) { - p = buffer->buf + buffer->end; - buffer->end += len; - return p; - } - - /* Compact data back to the start of the buffer if necessary */ - if (buffer_compact(buffer)) - goto restart; - - /* Increase the size of the buffer and retry. */ - newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ); - if (newlen > BUFFER_MAX_LEN) - fatal("buffer_append_space: alloc %u not supported", - newlen); - buffer->buf = xrealloc(buffer->buf, 1, newlen); - buffer->alloc = newlen; - goto restart; - /* NOTREACHED */ + if ((ret = sshbuf_reserve(buffer, len, &p)) != 0) + fatal("%s: %s", __func__, ssh_err(ret)); + return p; } -/* - * Check whether an allocation of 'len' will fit in the buffer - * This must follow the same math as buffer_append_space - */ int buffer_check_alloc(Buffer *buffer, u_int len) { - if (buffer->offset == buffer->end) { - buffer->offset = 0; - buffer->end = 0; - } - restart: - if (buffer->end + len < buffer->alloc) - return (1); - if (buffer_compact(buffer)) - goto restart; - if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN) - return (1); - return (0); -} - -/* Returns the number of bytes of data in the buffer. */ + int ret = sshbuf_check_reserve(buffer, len); -u_int -buffer_len(const Buffer *buffer) -{ - return buffer->end - buffer->offset; + if (ret == 0) + return 1; + if (ret == SSH_ERR_NO_BUFFER_SPACE) + return 0; + fatal("%s: %s", __func__, ssh_err(ret)); } -/* Gets data from the beginning of the buffer. */ - int buffer_get_ret(Buffer *buffer, void *buf, u_int len) { - if (len > buffer->end - buffer->offset) { - error("buffer_get_ret: trying to get more bytes %d than in buffer %d", - len, buffer->end - buffer->offset); - return (-1); + int ret; + + if ((ret = sshbuf_get(buffer, buf, len)) != 0) { + error("%s: %s", __func__, ssh_err(ret)); + return -1; } - memcpy(buf, buffer->buf + buffer->offset, len); - buffer->offset += len; - return (0); + return 0; } void buffer_get(Buffer *buffer, void *buf, u_int len) { if (buffer_get_ret(buffer, buf, len) == -1) - fatal("buffer_get: buffer error"); + fatal("%s: buffer error", __func__); } -/* Consumes the given number of bytes from the beginning of the buffer. */ - int buffer_consume_ret(Buffer *buffer, u_int bytes) { - if (bytes > buffer->end - buffer->offset) { - error("buffer_consume_ret: trying to get more bytes than in buffer"); - return (-1); - } - buffer->offset += bytes; - return (0); + int ret = sshbuf_consume(buffer, bytes); + + if (ret == 0) + return 0; + if (ret == SSH_ERR_MESSAGE_INCOMPLETE) + return -1; + fatal("%s: %s", __func__, ssh_err(ret)); } void buffer_consume(Buffer *buffer, u_int bytes) { if (buffer_consume_ret(buffer, bytes) == -1) - fatal("buffer_consume: buffer error"); + fatal("%s: buffer error", __func__); } -/* Consumes the given number of bytes from the end of the buffer. */ - int buffer_consume_end_ret(Buffer *buffer, u_int bytes) { - if (bytes > buffer->end - buffer->offset) - return (-1); - buffer->end -= bytes; - return (0); + int ret = sshbuf_consume_end(buffer, bytes); + + if (ret == 0) + return 0; + if (ret == SSH_ERR_MESSAGE_INCOMPLETE) + return -1; + fatal("%s: %s", __func__, ssh_err(ret)); } void buffer_consume_end(Buffer *buffer, u_int bytes) { if (buffer_consume_end_ret(buffer, bytes) == -1) - fatal("buffer_consume_end: trying to get more bytes than in buffer"); -} - -/* Returns a pointer to the first used byte in the buffer. */ - -void * -buffer_ptr(const Buffer *buffer) -{ - return buffer->buf + buffer->offset; + fatal("%s: buffer error", __func__); } -/* Dumps the contents of the buffer to stderr. */ -void -buffer_dump(const Buffer *buffer) -{ - u_int i; - u_char *ucp = buffer->buf; - - for (i = buffer->offset; i < buffer->end; i++) { - fprintf(stderr, "%02x", ucp[i]); - if ((i-buffer->offset)%16==15) - fprintf(stderr, "\r\n"); - else if ((i-buffer->offset)%2==1) - fprintf(stderr, " "); - } - fprintf(stderr, "\r\n"); -} diff --git a/crypto/openssh/buffer.h b/crypto/openssh/buffer.h index 7df8a38..df1aebc 100644 --- a/crypto/openssh/buffer.h +++ b/crypto/openssh/buffer.h @@ -1,57 +1,59 @@ -/* $OpenBSD: buffer.h,v 1.23 2014/01/12 08:13:13 djm Exp $ */ +/* $OpenBSD: buffer.h,v 1.25 2014/04/30 05:29:56 djm Exp $ */ /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Code for manipulating FIFO buffers. + * Copyright (c) 2012 Damien Miller * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */ + #ifndef BUFFER_H #define BUFFER_H -typedef struct { - u_char *buf; /* Buffer for data. */ - u_int alloc; /* Number of bytes allocated for data. */ - u_int offset; /* Offset of first byte containing data. */ - u_int end; /* Offset of last byte containing data. */ -} Buffer; +#include "sshbuf.h" + +typedef struct sshbuf Buffer; -void buffer_init(Buffer *); -void buffer_clear(Buffer *); -void buffer_free(Buffer *); +#define buffer_init(b) sshbuf_init(b) +#define buffer_clear(b) sshbuf_reset(b) +#define buffer_free(b) sshbuf_free(b) +#define buffer_dump(b) sshbuf_dump(b, stderr) -u_int buffer_len(const Buffer *); -void *buffer_ptr(const Buffer *); +/* XXX cast is safe: sshbuf never stores more than len 2^31 */ +#define buffer_len(b) ((u_int) sshbuf_len(b)) +#define buffer_ptr(b) sshbuf_mutable_ptr(b) void buffer_append(Buffer *, const void *, u_int); void *buffer_append_space(Buffer *, u_int); - int buffer_check_alloc(Buffer *, u_int); - void buffer_get(Buffer *, void *, u_int); void buffer_consume(Buffer *, u_int); void buffer_consume_end(Buffer *, u_int); -void buffer_dump(const Buffer *); int buffer_get_ret(Buffer *, void *, u_int); int buffer_consume_ret(Buffer *, u_int); int buffer_consume_end_ret(Buffer *, u_int); +#include #include - void buffer_put_bignum(Buffer *, const BIGNUM *); void buffer_put_bignum2(Buffer *, const BIGNUM *); void buffer_get_bignum(Buffer *, BIGNUM *); void buffer_get_bignum2(Buffer *, BIGNUM *); +void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int); u_short buffer_get_short(Buffer *); void buffer_put_short(Buffer *, u_short); @@ -66,13 +68,12 @@ int buffer_get_char(Buffer *); void buffer_put_char(Buffer *, int); void *buffer_get_string(Buffer *, u_int *); -void *buffer_get_string_ptr(Buffer *, u_int *); +const void *buffer_get_string_ptr(Buffer *, u_int *); void buffer_put_string(Buffer *, const void *, u_int); char *buffer_get_cstring(Buffer *, u_int *); void buffer_put_cstring(Buffer *, const char *); -#define buffer_skip_string(b) \ - do { u_int l = buffer_get_int(b); buffer_consume(b, l); } while (0) +#define buffer_skip_string(b) (void)buffer_get_string_ptr(b, NULL); int buffer_put_bignum_ret(Buffer *, const BIGNUM *); int buffer_get_bignum_ret(Buffer *, BIGNUM *); @@ -83,20 +84,16 @@ int buffer_get_int_ret(u_int *, Buffer *); int buffer_get_int64_ret(u_int64_t *, Buffer *); void *buffer_get_string_ret(Buffer *, u_int *); char *buffer_get_cstring_ret(Buffer *, u_int *); -void *buffer_get_string_ptr_ret(Buffer *, u_int *); -int buffer_get_char_ret(u_char *, Buffer *); - -void *buffer_get_bignum2_as_string_ret(Buffer *, u_int *); -void *buffer_get_bignum2_as_string(Buffer *, u_int *); -void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int); +const void *buffer_get_string_ptr_ret(Buffer *, u_int *); +int buffer_get_char_ret(char *, Buffer *); #ifdef OPENSSL_HAS_ECC #include - int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *); void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *); int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *); void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *); #endif -#endif /* BUFFER_H */ +#endif /* BUFFER_H */ + diff --git a/crypto/openssh/canohost.c b/crypto/openssh/canohost.c index a61a8c9..223964e 100644 --- a/crypto/openssh/canohost.c +++ b/crypto/openssh/canohost.c @@ -1,4 +1,4 @@ -/* $OpenBSD: canohost.c,v 1.70 2014/01/19 04:17:29 dtucker Exp $ */ +/* $OpenBSD: canohost.c,v 1.72 2015/03/01 15:44:40 millert Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -259,19 +260,29 @@ get_socket_address(int sock, int remote, int flags) } /* Work around Linux IPv6 weirdness */ - if (addr.ss_family == AF_INET6) + if (addr.ss_family == AF_INET6) { addrlen = sizeof(struct sockaddr_in6); + ipv64_normalise_mapped(&addr, &addrlen); + } - ipv64_normalise_mapped(&addr, &addrlen); - - /* Get the address in ascii. */ - if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop, - sizeof(ntop), NULL, 0, flags)) != 0) { - error("get_socket_address: getnameinfo %d failed: %s", flags, - ssh_gai_strerror(r)); + switch (addr.ss_family) { + case AF_INET: + case AF_INET6: + /* Get the address in ascii. */ + if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop, + sizeof(ntop), NULL, 0, flags)) != 0) { + error("get_socket_address: getnameinfo %d failed: %s", + flags, ssh_gai_strerror(r)); + return NULL; + } + return xstrdup(ntop); + case AF_UNIX: + /* Get the Unix domain socket path. */ + return xstrdup(((struct sockaddr_un *)&addr)->sun_path); + default: + /* We can't look up remote Unix domain sockets. */ return NULL; } - return xstrdup(ntop); } char * @@ -384,6 +395,10 @@ get_sock_port(int sock, int local) if (from.ss_family == AF_INET6) fromlen = sizeof(struct sockaddr_in6); + /* Non-inet sockets don't have a port number. */ + if (from.ss_family != AF_INET && from.ss_family != AF_INET6) + return 0; + /* Return port number. */ if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, strport, sizeof(strport), NI_NUMERICSERV)) != 0) diff --git a/crypto/openssh/chacha.h b/crypto/openssh/chacha.h index 4ef42cc..40eaf2d 100644 --- a/crypto/openssh/chacha.h +++ b/crypto/openssh/chacha.h @@ -1,4 +1,4 @@ -/* $OpenBSD: chacha.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ +/* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */ /* chacha-merged.c version 20080118 diff --git a/crypto/openssh/channels.c b/crypto/openssh/channels.c index 9efe89c..a84b487 100644 --- a/crypto/openssh/channels.c +++ b/crypto/openssh/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.331 2014/02/26 20:29:29 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.347 2015/07/01 02:26:31 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -42,6 +42,8 @@ #include "includes.h" #include +#include /* MIN MAX */ +#include #include #include #include @@ -55,6 +57,9 @@ #include #include #include +#ifdef HAVE_STDINT_H +#include +#endif #include #include #include @@ -107,10 +112,15 @@ static int channel_max_fd = 0; * a corrupt remote server from accessing arbitrary TCP/IP ports on our local * network (which might be behind a firewall). */ +/* XXX: streamlocal wants a path instead of host:port */ +/* Overload host_to_connect; we could just make this match Forward */ +/* XXX - can we use listen_host instead of listen_path? */ typedef struct { char *host_to_connect; /* Connect to 'host'. */ - u_short port_to_connect; /* Connect to 'port'. */ - u_short listen_port; /* Remote side should listen port number. */ + int port_to_connect; /* Connect to 'port'. */ + char *listen_host; /* Remote side should listen address. */ + char *listen_path; /* Remote side should listen path. */ + int listen_port; /* Remote side should listen port. */ } ForwardPermission; /* List of all permitted host/port pairs to connect by the user. */ @@ -151,6 +161,9 @@ static char *x11_saved_proto = NULL; static char *x11_saved_data = NULL; static u_int x11_saved_data_len = 0; +/* Deadline after which all X11 connections are refused */ +static u_int x11_refuse_time; + /* * Fake X11 authentication data. This is what the server will be sending us; * we should replace any occurrences of this by the real data. @@ -296,7 +309,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, if (channels_alloc > 10000) fatal("channel_new: internal error: channels_alloc %d " "too big.", channels_alloc); - channels = xrealloc(channels, channels_alloc + 10, + channels = xreallocarray(channels, channels_alloc + 10, sizeof(Channel *)); channels_alloc += 10; debug2("channel: expanding %d", channels_alloc); @@ -473,6 +486,8 @@ channel_stop_listening(void) case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_X11_LISTENER: + case SSH_CHANNEL_UNIX_LISTENER: + case SSH_CHANNEL_RUNIX_LISTENER: channel_close_fd(&c->sock); channel_free(c); break; @@ -535,6 +550,8 @@ channel_still_open(void) case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: + case SSH_CHANNEL_UNIX_LISTENER: + case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: if (!compat20) @@ -581,6 +598,8 @@ channel_find_open(void) case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: + case SSH_CHANNEL_UNIX_LISTENER: + case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_AUTH_SOCKET: @@ -631,6 +650,8 @@ channel_open_message(void) case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_MUX_CLIENT: case SSH_CHANNEL_MUX_LISTENER: + case SSH_CHANNEL_UNIX_LISTENER: + case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_OPENING: @@ -655,7 +676,7 @@ channel_open_message(void) } } buffer_append(&buffer, "\0", 1); - cp = xstrdup(buffer_ptr(&buffer)); + cp = xstrdup((char *)buffer_ptr(&buffer)); buffer_free(&buffer); return cp; } @@ -894,6 +915,13 @@ x11_open_helper(Buffer *b) u_char *ucp; u_int proto_len, data_len; + /* Is this being called after the refusal deadline? */ + if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) { + verbose("Rejected X11 connection after ForwardX11Timeout " + "expired"); + return -1; + } + /* Check if the fixed size part of the packet is in buffer. */ if (buffer_len(b) < 12) return 0; @@ -1041,7 +1069,7 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) len = sizeof(s4_req); if (have < len) return 0; - p = buffer_ptr(&c->input); + p = (char *)buffer_ptr(&c->input); need = 1; /* SOCKS4A uses an invalid IP address 0.0.0.x */ @@ -1071,7 +1099,7 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) buffer_get(&c->input, (char *)&s4_req.dest_port, 2); buffer_get(&c->input, (char *)&s4_req.dest_addr, 4); have = buffer_len(&c->input); - p = buffer_ptr(&c->input); + p = (char *)buffer_ptr(&c->input); if (memchr(p, '\0', have) == NULL) fatal("channel %d: decode socks4: user not nul terminated", c->self); @@ -1091,7 +1119,7 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) c->path = xstrdup(host); } else { /* SOCKS4A: two strings */ have = buffer_len(&c->input); - p = buffer_ptr(&c->input); + p = (char *)buffer_ptr(&c->input); len = strlen(p); debug2("channel %d: decode socks4a: host %s/%d", c->self, p, len); @@ -1386,7 +1414,6 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset) static void port_open_helper(Channel *c, char *rtype) { - int direct; char buf[1024]; char *local_ipaddr = get_local_ipaddr(c->sock); int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1); @@ -1400,8 +1427,6 @@ port_open_helper(Channel *c, char *rtype) remote_port = 65535; } - direct = (strcmp(rtype, "direct-tcpip") == 0); - snprintf(buf, sizeof buf, "%s: listening port %d for %.100s port %d, " "connect from %.200s port %d to %.100s port %d", @@ -1417,18 +1442,29 @@ port_open_helper(Channel *c, char *rtype) packet_put_int(c->self); packet_put_int(c->local_window_max); packet_put_int(c->local_maxpacket); - if (direct) { + if (strcmp(rtype, "direct-tcpip") == 0) { /* target host, port */ packet_put_cstring(c->path); packet_put_int(c->host_port); + } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { + /* target path */ + packet_put_cstring(c->path); + } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { + /* listen path */ + packet_put_cstring(c->path); } else { /* listen address, port */ packet_put_cstring(c->path); packet_put_int(local_port); } - /* originator host and port */ - packet_put_cstring(remote_ipaddr); - packet_put_int((u_int)remote_port); + if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { + /* reserved for future owner/mode info */ + packet_put_cstring(""); + } else { + /* originator host and port */ + packet_put_cstring(remote_ipaddr); + packet_put_int((u_int)remote_port); + } packet_send(); } else { packet_start(SSH_MSG_PORT_OPEN); @@ -1457,6 +1493,12 @@ channel_set_reuseaddr(int fd) error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno)); } +void +channel_set_x11_refuse_time(u_int refuse_time) +{ + x11_refuse_time = refuse_time; +} + /* * This socket is listening for connections to a forwarded TCP/IP port. */ @@ -1478,14 +1520,18 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) if (c->type == SSH_CHANNEL_RPORT_LISTENER) { nextstate = SSH_CHANNEL_OPENING; rtype = "forwarded-tcpip"; + } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { + nextstate = SSH_CHANNEL_OPENING; + rtype = "forwarded-streamlocal@openssh.com"; + } else if (c->host_port == PORT_STREAMLOCAL) { + nextstate = SSH_CHANNEL_OPENING; + rtype = "direct-streamlocal@openssh.com"; + } else if (c->host_port == 0) { + nextstate = SSH_CHANNEL_DYNAMIC; + rtype = "dynamic-tcpip"; } else { - if (c->host_port == 0) { - nextstate = SSH_CHANNEL_DYNAMIC; - rtype = "dynamic-tcpip"; - } else { - nextstate = SSH_CHANNEL_OPENING; - rtype = "direct-tcpip"; - } + nextstate = SSH_CHANNEL_OPENING; + rtype = "direct-tcpip"; } addrlen = sizeof(addr); @@ -1498,7 +1544,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) c->notbefore = monotime() + 1; return; } - set_nodelay(newsock); + if (c->host_port != PORT_STREAMLOCAL) + set_nodelay(newsock); nc = channel_new(rtype, nextstate, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, rtype, 1); nc->listening_port = c->listening_port; @@ -1987,6 +2034,8 @@ channel_handler_init_20(void) channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; + channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; + channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; @@ -1997,6 +2046,8 @@ channel_handler_init_20(void) channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; + channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; + channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; @@ -2151,14 +2202,14 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, nfdset = howmany(n+1, NFDBITS); /* Explicitly test here, because xrealloc isn't always called */ - if (nfdset && SIZE_T_MAX / nfdset < sizeof(fd_mask)) + if (nfdset && SIZE_MAX / nfdset < sizeof(fd_mask)) fatal("channel_prepare_select: max_fd (%d) is too large", n); sz = nfdset * sizeof(fd_mask); /* perhaps check sz < nalloc/2 and shrink? */ if (*readsetp == NULL || sz > *nallocp) { - *readsetp = xrealloc(*readsetp, nfdset, sizeof(fd_mask)); - *writesetp = xrealloc(*writesetp, nfdset, sizeof(fd_mask)); + *readsetp = xreallocarray(*readsetp, nfdset, sizeof(fd_mask)); + *writesetp = xreallocarray(*writesetp, nfdset, sizeof(fd_mask)); *nallocp = sz; } *maxfdp = n; @@ -2235,7 +2286,7 @@ channel_output_poll(void) packet_put_int(c->remote_id); packet_put_string(data, dlen); packet_send(); - c->remote_window -= dlen + 4; + c->remote_window -= dlen; free(data); } continue; @@ -2311,11 +2362,11 @@ channel_output_poll(void) /* -- protocol input */ /* ARGSUSED */ -void +int channel_input_data(int type, u_int32_t seq, void *ctxt) { int id; - char *data; + const u_char *data; u_int data_len, win_len; Channel *c; @@ -2328,7 +2379,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) /* Ignore any data for non-open channels (might happen on close) */ if (c->type != SSH_CHANNEL_OPEN && c->type != SSH_CHANNEL_X11_OPEN) - return; + return 0; /* Get the data. */ data = packet_get_string_ptr(&data_len); @@ -2348,7 +2399,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) c->local_window -= win_len; c->local_consumed += win_len; } - return; + return 0; } if (compat20) { @@ -2359,7 +2410,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) if (win_len > c->local_window) { logit("channel %d: rcvd too much data %d, win %d", c->self, win_len, c->local_window); - return; + return 0; } c->local_window -= win_len; } @@ -2368,10 +2419,11 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) else buffer_append(&c->output, data, data_len); packet_check_eom(); + return 0; } /* ARGSUSED */ -void +int channel_input_extended_data(int type, u_int32_t seq, void *ctxt) { int id; @@ -2387,7 +2439,7 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt) packet_disconnect("Received extended_data for bad channel %d.", id); if (c->type != SSH_CHANNEL_OPEN) { logit("channel %d: ext data for non open", id); - return; + return 0; } if (c->flags & CHAN_EOF_RCVD) { if (datafellows & SSH_BUG_EXTEOF) @@ -2401,7 +2453,7 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt) c->extended_usage != CHAN_EXTENDED_WRITE || tcode != SSH2_EXTENDED_DATA_STDERR) { logit("channel %d: bad ext data", c->self); - return; + return 0; } data = packet_get_string(&data_len); packet_check_eom(); @@ -2409,16 +2461,17 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt) logit("channel %d: rcvd too much extended_data %d, win %d", c->self, data_len, c->local_window); free(data); - return; + return 0; } debug2("channel %d: rcvd ext data %d", c->self, data_len); c->local_window -= data_len; buffer_append(&c->extended, data, data_len); free(data); + return 0; } /* ARGSUSED */ -void +int channel_input_ieof(int type, u_int32_t seq, void *ctxt) { int id; @@ -2438,11 +2491,11 @@ channel_input_ieof(int type, u_int32_t seq, void *ctxt) if (buffer_len(&c->input) == 0) chan_ibuf_empty(c); } - + return 0; } /* ARGSUSED */ -void +int channel_input_close(int type, u_int32_t seq, void *ctxt) { int id; @@ -2477,11 +2530,12 @@ channel_input_close(int type, u_int32_t seq, void *ctxt) buffer_clear(&c->input); c->type = SSH_CHANNEL_OUTPUT_DRAINING; } + return 0; } /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */ /* ARGSUSED */ -void +int channel_input_oclose(int type, u_int32_t seq, void *ctxt) { int id = packet_get_int(); @@ -2491,10 +2545,11 @@ channel_input_oclose(int type, u_int32_t seq, void *ctxt) if (c == NULL) packet_disconnect("Received oclose for nonexistent channel %d.", id); chan_rcvd_oclose(c); + return 0; } /* ARGSUSED */ -void +int channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt) { int id = packet_get_int(); @@ -2508,10 +2563,11 @@ channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt) packet_disconnect("Received close confirmation for " "non-closed channel %d (type %d).", id, c->type); channel_free(c); + return 0; } /* ARGSUSED */ -void +int channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) { int id, remote_id; @@ -2540,6 +2596,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) c->remote_window, c->remote_maxpacket); } packet_check_eom(); + return 0; } static char * @@ -2559,7 +2616,7 @@ reason2txt(int reason) } /* ARGSUSED */ -void +int channel_input_open_failure(int type, u_int32_t seq, void *ctxt) { int id, reason; @@ -2591,18 +2648,19 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt) packet_check_eom(); /* Schedule the channel for cleanup/deletion. */ chan_mark_dead(c); + return 0; } /* ARGSUSED */ -void +int channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) { Channel *c; int id; - u_int adjust; + u_int adjust, tmp; if (!compat20) - return; + return 0; /* Get the channel number and verify it. */ id = packet_get_int(); @@ -2610,16 +2668,20 @@ channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) if (c == NULL) { logit("Received window adjust for non-open channel %d.", id); - return; + return 0; } adjust = packet_get_int(); packet_check_eom(); debug2("channel %d: rcvd adjust %u", id, adjust); - c->remote_window += adjust; + if ((tmp = c->remote_window + adjust) < c->remote_window) + fatal("channel %d: adjust %u overflows remote window %u", + id, adjust, c->remote_window); + c->remote_window = tmp; + return 0; } /* ARGSUSED */ -void +int channel_input_port_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; @@ -2637,7 +2699,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt) originator_string = xstrdup("unknown (remote did not supply name)"); } packet_check_eom(); - c = channel_connect_to(host, host_port, + c = channel_connect_to_port(host, host_port, "connected socket", originator_string); free(originator_string); free(host); @@ -2647,10 +2709,11 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt) packet_send(); } else c->remote_id = remote_id; + return 0; } /* ARGSUSED */ -void +int channel_input_status_confirm(int type, u_int32_t seq, void *ctxt) { Channel *c; @@ -2667,15 +2730,15 @@ channel_input_status_confirm(int type, u_int32_t seq, void *ctxt) if ((c = channel_lookup(id)) == NULL) { logit("channel_input_status_confirm: %d: unknown", id); - return; + return 0; } - ; if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) - return; + return 0; cc->cb(type, c, cc->ctx); TAILQ_REMOVE(&c->status_confirms, cc, entry); explicit_bzero(cc, sizeof(*cc)); free(cc); + return 0; } /* -- tcp forwarding */ @@ -2700,23 +2763,24 @@ channel_set_af(int af) * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR * "" (empty string), "*" -> wildcard v4/v6 * "localhost" -> loopback v4/v6 + * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set */ static const char * channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, - int is_client, int gateway_ports) + int is_client, struct ForwardOptions *fwd_opts) { const char *addr = NULL; int wildcard = 0; if (listen_addr == NULL) { /* No address specified: default to gateway_ports setting */ - if (gateway_ports) + if (fwd_opts->gateway_ports) wildcard = 1; - } else if (gateway_ports || is_client) { + } else if (fwd_opts->gateway_ports || is_client) { if (((datafellows & SSH_OLD_FORWARD_ADDR) && strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || - (!is_client && gateway_ports == 1)) { + (!is_client && fwd_opts->gateway_ports == 1)) { wildcard = 1; /* * Notify client if they requested a specific listen @@ -2729,9 +2793,20 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, "\"%s\" overridden by server " "GatewayPorts", listen_addr); } - } - else if (strcmp(listen_addr, "localhost") != 0) + } else if (strcmp(listen_addr, "localhost") != 0 || + strcmp(listen_addr, "127.0.0.1") == 0 || + strcmp(listen_addr, "::1") == 0) { + /* Accept localhost address when GatewayPorts=yes */ addr = listen_addr; + } + } else if (strcmp(listen_addr, "127.0.0.1") == 0 || + strcmp(listen_addr, "::1") == 0) { + /* + * If a specific IPv4/IPv6 localhost address has been + * requested then accept it even if gateway_ports is in + * effect. This allows the client to prefer IPv4 or IPv6. + */ + addr = listen_addr; } if (wildcardp != NULL) *wildcardp = wildcard; @@ -2739,9 +2814,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, } static int -channel_setup_fwd_listener(int type, const char *listen_addr, - u_short listen_port, int *allocated_listen_port, - const char *host_to_connect, u_short port_to_connect, int gateway_ports) +channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, + int *allocated_listen_port, struct ForwardOptions *fwd_opts) { Channel *c; int sock, r, success = 0, wildcard = 0, is_client; @@ -2750,23 +2824,27 @@ channel_setup_fwd_listener(int type, const char *listen_addr, char ntop[NI_MAXHOST], strport[NI_MAXSERV]; in_port_t *lport_p; - host = (type == SSH_CHANNEL_RPORT_LISTENER) ? - listen_addr : host_to_connect; is_client = (type == SSH_CHANNEL_PORT_LISTENER); - if (host == NULL) { - error("No forward host name."); - return 0; - } - if (strlen(host) >= NI_MAXHOST) { - error("Forward host name too long."); - return 0; + if (is_client && fwd->connect_path != NULL) { + host = fwd->connect_path; + } else { + host = (type == SSH_CHANNEL_RPORT_LISTENER) ? + fwd->listen_host : fwd->connect_host; + if (host == NULL) { + error("No forward host name."); + return 0; + } + if (strlen(host) >= NI_MAXHOST) { + error("Forward host name too long."); + return 0; + } } /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ - addr = channel_fwd_bind_addr(listen_addr, &wildcard, - is_client, gateway_ports); - debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", + addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard, + is_client, fwd_opts); + debug3("%s: type %d wildcard %d addr %s", __func__, type, wildcard, (addr == NULL) ? "NULL" : addr); /* @@ -2777,15 +2855,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr, hints.ai_family = IPv4or6; hints.ai_flags = wildcard ? AI_PASSIVE : 0; hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", listen_port); + snprintf(strport, sizeof strport, "%d", fwd->listen_port); if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { if (addr == NULL) { /* This really shouldn't happen */ packet_disconnect("getaddrinfo: fatal error: %s", ssh_gai_strerror(r)); } else { - error("channel_setup_fwd_listener: " - "getaddrinfo(%.64s): %s", addr, + error("%s: getaddrinfo(%.64s): %s", __func__, addr, ssh_gai_strerror(r)); } return 0; @@ -2809,13 +2886,13 @@ channel_setup_fwd_listener(int type, const char *listen_addr, * If allocating a port for -R forwards, then use the * same port for all address families. */ - if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && + if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && allocated_listen_port != NULL && *allocated_listen_port > 0) *lport_p = htons(*allocated_listen_port); if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("channel_setup_fwd_listener: getnameinfo failed"); + error("%s: getnameinfo failed", __func__); continue; } /* Create a port to listen for the host. */ @@ -2852,10 +2929,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr, } /* - * listen_port == 0 requests a dynamically allocated port - + * fwd->listen_port == 0 requests a dynamically allocated port - * record what we got. */ - if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && + if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && allocated_listen_port != NULL && *allocated_listen_port == 0) { *allocated_listen_port = get_sock_port(sock, 1); @@ -2868,24 +2945,98 @@ channel_setup_fwd_listener(int type, const char *listen_addr, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "port listener", 1); c->path = xstrdup(host); - c->host_port = port_to_connect; + c->host_port = fwd->connect_port; c->listening_addr = addr == NULL ? NULL : xstrdup(addr); - if (listen_port == 0 && allocated_listen_port != NULL && + if (fwd->listen_port == 0 && allocated_listen_port != NULL && !(datafellows & SSH_BUG_DYNAMIC_RPORT)) c->listening_port = *allocated_listen_port; else - c->listening_port = listen_port; + c->listening_port = fwd->listen_port; success = 1; } if (success == 0) - error("channel_setup_fwd_listener: cannot listen to port: %d", - listen_port); + error("%s: cannot listen to port: %d", __func__, + fwd->listen_port); freeaddrinfo(aitop); return success; } -int -channel_cancel_rport_listener(const char *host, u_short port) +static int +channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd, + struct ForwardOptions *fwd_opts) +{ + struct sockaddr_un sunaddr; + const char *path; + Channel *c; + int port, sock; + mode_t omask; + + switch (type) { + case SSH_CHANNEL_UNIX_LISTENER: + if (fwd->connect_path != NULL) { + if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) { + error("Local connecting path too long: %s", + fwd->connect_path); + return 0; + } + path = fwd->connect_path; + port = PORT_STREAMLOCAL; + } else { + if (fwd->connect_host == NULL) { + error("No forward host name."); + return 0; + } + if (strlen(fwd->connect_host) >= NI_MAXHOST) { + error("Forward host name too long."); + return 0; + } + path = fwd->connect_host; + port = fwd->connect_port; + } + break; + case SSH_CHANNEL_RUNIX_LISTENER: + path = fwd->listen_path; + port = PORT_STREAMLOCAL; + break; + default: + error("%s: unexpected channel type %d", __func__, type); + return 0; + } + + if (fwd->listen_path == NULL) { + error("No forward path name."); + return 0; + } + if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) { + error("Local listening path too long: %s", fwd->listen_path); + return 0; + } + + debug3("%s: type %d path %s", __func__, type, fwd->listen_path); + + /* Start a Unix domain listener. */ + omask = umask(fwd_opts->streamlocal_bind_mask); + sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG, + fwd_opts->streamlocal_bind_unlink); + umask(omask); + if (sock < 0) + return 0; + + debug("Local forwarding listening on path %s.", fwd->listen_path); + + /* Allocate a channel number for the socket. */ + c = channel_new("unix listener", type, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, + 0, "unix listener", 1); + c->path = xstrdup(path); + c->host_port = port; + c->listening_port = PORT_STREAMLOCAL; + c->listening_addr = xstrdup(fwd->listen_path); + return 1; +} + +static int +channel_cancel_rport_listener_tcpip(const char *host, u_short port) { u_int i; int found = 0; @@ -2904,13 +3055,44 @@ channel_cancel_rport_listener(const char *host, u_short port) return (found); } +static int +channel_cancel_rport_listener_streamlocal(const char *path) +{ + u_int i; + int found = 0; + + for (i = 0; i < channels_alloc; i++) { + Channel *c = channels[i]; + if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER) + continue; + if (c->path == NULL) + continue; + if (strcmp(c->path, path) == 0) { + debug2("%s: close channel %d", __func__, i); + channel_free(c); + found = 1; + } + } + + return (found); +} + int -channel_cancel_lport_listener(const char *lhost, u_short lport, - int cport, int gateway_ports) +channel_cancel_rport_listener(struct Forward *fwd) +{ + if (fwd->listen_path != NULL) + return channel_cancel_rport_listener_streamlocal(fwd->listen_path); + else + return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port); +} + +static int +channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport, + int cport, struct ForwardOptions *fwd_opts) { u_int i; int found = 0; - const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports); + const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts); for (i = 0; i < channels_alloc; i++) { Channel *c = channels[i]; @@ -2939,24 +3121,68 @@ channel_cancel_lport_listener(const char *lhost, u_short lport, return (found); } +static int +channel_cancel_lport_listener_streamlocal(const char *path) +{ + u_int i; + int found = 0; + + if (path == NULL) { + error("%s: no path specified.", __func__); + return 0; + } + + for (i = 0; i < channels_alloc; i++) { + Channel *c = channels[i]; + if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER) + continue; + if (c->listening_addr == NULL) + continue; + if (strcmp(c->listening_addr, path) == 0) { + debug2("%s: close channel %d", __func__, i); + channel_free(c); + found = 1; + } + } + + return (found); +} + +int +channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) +{ + if (fwd->listen_path != NULL) + return channel_cancel_lport_listener_streamlocal(fwd->listen_path); + else + return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts); +} + /* protocol local port fwd, used by ssh (and sshd in v1) */ int -channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, - const char *host_to_connect, u_short port_to_connect, int gateway_ports) +channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts) { - return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, - listen_host, listen_port, NULL, host_to_connect, port_to_connect, - gateway_ports); + if (fwd->listen_path != NULL) { + return channel_setup_fwd_listener_streamlocal( + SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts); + } else { + return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER, + fwd, NULL, fwd_opts); + } } /* protocol v2 remote port fwd, used by sshd */ int -channel_setup_remote_fwd_listener(const char *listen_address, - u_short listen_port, int *allocated_listen_port, int gateway_ports) +channel_setup_remote_fwd_listener(struct Forward *fwd, + int *allocated_listen_port, struct ForwardOptions *fwd_opts) { - return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, - listen_address, listen_port, allocated_listen_port, - NULL, 0, gateway_ports); + if (fwd->listen_path != NULL) { + return channel_setup_fwd_listener_streamlocal( + SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); + } else { + return channel_setup_fwd_listener_tcpip( + SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port, + fwd_opts); + } } /* @@ -2987,27 +3213,32 @@ channel_rfwd_bind_host(const char *listen_host) * channel_update_permitted_opens(). */ int -channel_request_remote_forwarding(const char *listen_host, u_short listen_port, - const char *host_to_connect, u_short port_to_connect) +channel_request_remote_forwarding(struct Forward *fwd) { int type, success = 0, idx = -1; /* Send the forward request to the remote side. */ if (compat20) { packet_start(SSH2_MSG_GLOBAL_REQUEST); - packet_put_cstring("tcpip-forward"); - packet_put_char(1); /* boolean: want reply */ - packet_put_cstring(channel_rfwd_bind_host(listen_host)); - packet_put_int(listen_port); + if (fwd->listen_path != NULL) { + packet_put_cstring("streamlocal-forward@openssh.com"); + packet_put_char(1); /* boolean: want reply */ + packet_put_cstring(fwd->listen_path); + } else { + packet_put_cstring("tcpip-forward"); + packet_put_char(1); /* boolean: want reply */ + packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host)); + packet_put_int(fwd->listen_port); + } packet_send(); packet_write_wait(); /* Assume that server accepts the request */ success = 1; - } else { + } else if (fwd->listen_path == NULL) { packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); - packet_put_int(listen_port); - packet_put_cstring(host_to_connect); - packet_put_int(port_to_connect); + packet_put_int(fwd->listen_port); + packet_put_cstring(fwd->connect_host); + packet_put_int(fwd->connect_port); packet_send(); packet_write_wait(); @@ -3024,25 +3255,102 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port, packet_disconnect("Protocol error for port forward request:" "received packet type %d.", type); } + } else { + logit("Warning: Server does not support remote stream local forwarding."); } if (success) { /* Record that connection to this host/port is permitted. */ - permitted_opens = xrealloc(permitted_opens, + permitted_opens = xreallocarray(permitted_opens, num_permitted_opens + 1, sizeof(*permitted_opens)); idx = num_permitted_opens++; - permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); - permitted_opens[idx].port_to_connect = port_to_connect; - permitted_opens[idx].listen_port = listen_port; + if (fwd->connect_path != NULL) { + permitted_opens[idx].host_to_connect = + xstrdup(fwd->connect_path); + permitted_opens[idx].port_to_connect = + PORT_STREAMLOCAL; + } else { + permitted_opens[idx].host_to_connect = + xstrdup(fwd->connect_host); + permitted_opens[idx].port_to_connect = + fwd->connect_port; + } + if (fwd->listen_path != NULL) { + permitted_opens[idx].listen_host = NULL; + permitted_opens[idx].listen_path = + xstrdup(fwd->listen_path); + permitted_opens[idx].listen_port = PORT_STREAMLOCAL; + } else { + permitted_opens[idx].listen_host = + fwd->listen_host ? xstrdup(fwd->listen_host) : NULL; + permitted_opens[idx].listen_path = NULL; + permitted_opens[idx].listen_port = fwd->listen_port; + } } return (idx); } +static int +open_match(ForwardPermission *allowed_open, const char *requestedhost, + int requestedport) +{ + if (allowed_open->host_to_connect == NULL) + return 0; + if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT && + allowed_open->port_to_connect != requestedport) + return 0; + if (strcmp(allowed_open->host_to_connect, requestedhost) != 0) + return 0; + return 1; +} + +/* + * Note that in the listen host/port case + * we don't support FWD_PERMIT_ANY_PORT and + * need to translate between the configured-host (listen_host) + * and what we've sent to the remote server (channel_rfwd_bind_host) + */ +static int +open_listen_match_tcpip(ForwardPermission *allowed_open, + const char *requestedhost, u_short requestedport, int translate) +{ + const char *allowed_host; + + if (allowed_open->host_to_connect == NULL) + return 0; + if (allowed_open->listen_port != requestedport) + return 0; + if (!translate && allowed_open->listen_host == NULL && + requestedhost == NULL) + return 1; + allowed_host = translate ? + channel_rfwd_bind_host(allowed_open->listen_host) : + allowed_open->listen_host; + if (allowed_host == NULL || + strcmp(allowed_host, requestedhost) != 0) + return 0; + return 1; +} + +static int +open_listen_match_streamlocal(ForwardPermission *allowed_open, + const char *requestedpath) +{ + if (allowed_open->host_to_connect == NULL) + return 0; + if (allowed_open->listen_port != PORT_STREAMLOCAL) + return 0; + if (allowed_open->listen_path == NULL || + strcmp(allowed_open->listen_path, requestedpath) != 0) + return 0; + return 1; +} + /* * Request cancellation of remote forwarding of connection host:port from * local side. */ -int -channel_request_rforward_cancel(const char *host, u_short port) +static int +channel_request_rforward_cancel_tcpip(const char *host, u_short port) { int i; @@ -3050,8 +3358,7 @@ channel_request_rforward_cancel(const char *host, u_short port) return -1; for (i = 0; i < num_permitted_opens; i++) { - if (permitted_opens[i].host_to_connect != NULL && - permitted_opens[i].listen_port == port) + if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0)) break; } if (i >= num_permitted_opens) { @@ -3069,9 +3376,64 @@ channel_request_rforward_cancel(const char *host, u_short port) permitted_opens[i].port_to_connect = 0; free(permitted_opens[i].host_to_connect); permitted_opens[i].host_to_connect = NULL; + free(permitted_opens[i].listen_host); + permitted_opens[i].listen_host = NULL; + permitted_opens[i].listen_path = NULL; + + return 0; +} + +/* + * Request cancellation of remote forwarding of Unix domain socket + * path from local side. + */ +static int +channel_request_rforward_cancel_streamlocal(const char *path) +{ + int i; + + if (!compat20) + return -1; + + for (i = 0; i < num_permitted_opens; i++) { + if (open_listen_match_streamlocal(&permitted_opens[i], path)) + break; + } + if (i >= num_permitted_opens) { + debug("%s: requested forward not found", __func__); + return -1; + } + packet_start(SSH2_MSG_GLOBAL_REQUEST); + packet_put_cstring("cancel-streamlocal-forward@openssh.com"); + packet_put_char(0); + packet_put_cstring(path); + packet_send(); + + permitted_opens[i].listen_port = 0; + permitted_opens[i].port_to_connect = 0; + free(permitted_opens[i].host_to_connect); + permitted_opens[i].host_to_connect = NULL; + permitted_opens[i].listen_host = NULL; + free(permitted_opens[i].listen_path); + permitted_opens[i].listen_path = NULL; return 0; } + +/* + * Request cancellation of remote forwarding of a connection from local side. + */ +int +channel_request_rforward_cancel(struct Forward *fwd) +{ + if (fwd->listen_path != NULL) { + return (channel_request_rforward_cancel_streamlocal( + fwd->listen_path)); + } else { + return (channel_request_rforward_cancel_tcpip(fwd->listen_host, + fwd->listen_port ? fwd->listen_port : fwd->allocated_port)); + } +} /* * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates @@ -3079,36 +3441,35 @@ channel_request_rforward_cancel(const char *host, u_short port) * message if there was an error). */ int -channel_input_port_forward_request(int is_root, int gateway_ports) +channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts) { - u_short port, host_port; int success = 0; - char *hostname; + struct Forward fwd; /* Get arguments from the packet. */ - port = packet_get_int(); - hostname = packet_get_string(NULL); - host_port = packet_get_int(); + memset(&fwd, 0, sizeof(fwd)); + fwd.listen_port = packet_get_int(); + fwd.connect_host = packet_get_string(NULL); + fwd.connect_port = packet_get_int(); #ifndef HAVE_CYGWIN /* * Check that an unprivileged user is not trying to forward a * privileged port. */ - if (port < IPPORT_RESERVED && !is_root) + if (fwd.listen_port < IPPORT_RESERVED && !is_root) packet_disconnect( "Requested forwarding of port %d but user is not root.", - port); - if (host_port == 0) + fwd.listen_port); + if (fwd.connect_port == 0) packet_disconnect("Dynamic forwarding denied."); #endif /* Initiate forwarding */ - success = channel_setup_local_fwd_listener(NULL, port, hostname, - host_port, gateway_ports); + success = channel_setup_local_fwd_listener(&fwd, fwd_opts); /* Free the argument string. */ - free(hostname); + free(fwd.connect_host); return (success ? 0 : -1); } @@ -3130,10 +3491,13 @@ channel_add_permitted_opens(char *host, int port) { debug("allow port forwarding to host %s port %d", host, port); - permitted_opens = xrealloc(permitted_opens, + permitted_opens = xreallocarray(permitted_opens, num_permitted_opens + 1, sizeof(*permitted_opens)); permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); permitted_opens[num_permitted_opens].port_to_connect = port; + permitted_opens[num_permitted_opens].listen_host = NULL; + permitted_opens[num_permitted_opens].listen_path = NULL; + permitted_opens[num_permitted_opens].listen_port = 0; num_permitted_opens++; all_opens_permitted = 0; @@ -3165,6 +3529,10 @@ channel_update_permitted_opens(int idx, int newport) permitted_opens[idx].port_to_connect = 0; free(permitted_opens[idx].host_to_connect); permitted_opens[idx].host_to_connect = NULL; + free(permitted_opens[idx].listen_host); + permitted_opens[idx].listen_host = NULL; + free(permitted_opens[idx].listen_path); + permitted_opens[idx].listen_path = NULL; } } @@ -3173,11 +3541,14 @@ channel_add_adm_permitted_opens(char *host, int port) { debug("config allows port forwarding to host %s port %d", host, port); - permitted_adm_opens = xrealloc(permitted_adm_opens, + permitted_adm_opens = xreallocarray(permitted_adm_opens, num_adm_permitted_opens + 1, sizeof(*permitted_adm_opens)); permitted_adm_opens[num_adm_permitted_opens].host_to_connect = xstrdup(host); permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; + permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL; + permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL; + permitted_adm_opens[num_adm_permitted_opens].listen_port = 0; return ++num_adm_permitted_opens; } @@ -3185,7 +3556,7 @@ void channel_disable_adm_local_opens(void) { channel_clear_adm_permitted_opens(); - permitted_adm_opens = xmalloc(sizeof(*permitted_adm_opens)); + permitted_adm_opens = xcalloc(sizeof(*permitted_adm_opens), 1); permitted_adm_opens[num_adm_permitted_opens].host_to_connect = NULL; num_adm_permitted_opens = 1; } @@ -3195,8 +3566,11 @@ channel_clear_permitted_opens(void) { int i; - for (i = 0; i < num_permitted_opens; i++) + for (i = 0; i < num_permitted_opens; i++) { free(permitted_opens[i].host_to_connect); + free(permitted_opens[i].listen_host); + free(permitted_opens[i].listen_path); + } free(permitted_opens); permitted_opens = NULL; num_permitted_opens = 0; @@ -3207,8 +3581,11 @@ channel_clear_adm_permitted_opens(void) { int i; - for (i = 0; i < num_adm_permitted_opens; i++) + for (i = 0; i < num_adm_permitted_opens; i++) { free(permitted_adm_opens[i].host_to_connect); + free(permitted_adm_opens[i].listen_host); + free(permitted_adm_opens[i].listen_path); + } free(permitted_adm_opens); permitted_adm_opens = NULL; num_adm_permitted_opens = 0; @@ -3246,30 +3623,32 @@ permitopen_port(const char *p) return -1; } -static int -port_match(u_short allowedport, u_short requestedport) -{ - if (allowedport == FWD_PERMIT_ANY_PORT || - allowedport == requestedport) - return 1; - return 0; -} - /* Try to start non-blocking connect to next host in cctx list */ static int connect_next(struct channel_connect *cctx) { int sock, saved_errno; - char ntop[NI_MAXHOST], strport[NI_MAXSERV]; + struct sockaddr_un *sunaddr; + char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))]; for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { - if (cctx->ai->ai_family != AF_INET && - cctx->ai->ai_family != AF_INET6) - continue; - if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, - ntop, sizeof(ntop), strport, sizeof(strport), - NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("connect_next: getnameinfo failed"); + switch (cctx->ai->ai_family) { + case AF_UNIX: + /* unix:pathname instead of host:port */ + sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr; + strlcpy(ntop, "unix", sizeof(ntop)); + strlcpy(strport, sunaddr->sun_path, sizeof(strport)); + break; + case AF_INET: + case AF_INET6: + if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, + ntop, sizeof(ntop), strport, sizeof(strport), + NI_NUMERICHOST|NI_NUMERICSERV) != 0) { + error("connect_next: getnameinfo failed"); + continue; + } + break; + default: continue; } if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, @@ -3292,10 +3671,11 @@ connect_next(struct channel_connect *cctx) errno = saved_errno; continue; /* fail -- try next */ } + if (cctx->ai->ai_family != AF_UNIX) + set_nodelay(sock); debug("connect_next: host %.100s ([%.100s]:%s) " "in progress, fd=%d", cctx->host, ntop, strport, sock); cctx->ai = cctx->ai->ai_next; - set_nodelay(sock); return sock; } return -1; @@ -3305,14 +3685,18 @@ static void channel_connect_ctx_free(struct channel_connect *cctx) { free(cctx->host); - if (cctx->aitop) - freeaddrinfo(cctx->aitop); + if (cctx->aitop) { + if (cctx->aitop->ai_family == AF_UNIX) + free(cctx->aitop); + else + freeaddrinfo(cctx->aitop); + } memset(cctx, 0, sizeof(*cctx)); } -/* Return CONNECTING channel to remote host, port */ +/* Return CONNECTING channel to remote host:port or local socket path */ static Channel * -connect_to(const char *host, u_short port, char *ctype, char *rname) +connect_to(const char *name, int port, char *ctype, char *rname) { struct addrinfo hints; int gaierr; @@ -3322,23 +3706,51 @@ connect_to(const char *host, u_short port, char *ctype, char *rname) Channel *c; memset(&cctx, 0, sizeof(cctx)); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", port); - if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) { - error("connect_to %.100s: unknown host (%s)", host, - ssh_gai_strerror(gaierr)); - return NULL; + + if (port == PORT_STREAMLOCAL) { + struct sockaddr_un *sunaddr; + struct addrinfo *ai; + + if (strlen(name) > sizeof(sunaddr->sun_path)) { + error("%.100s: %.100s", name, strerror(ENAMETOOLONG)); + return (NULL); + } + + /* + * Fake up a struct addrinfo for AF_UNIX connections. + * channel_connect_ctx_free() must check ai_family + * and use free() not freeaddirinfo() for AF_UNIX. + */ + ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr)); + memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr)); + ai->ai_addr = (struct sockaddr *)(ai + 1); + ai->ai_addrlen = sizeof(*sunaddr); + ai->ai_family = AF_UNIX; + ai->ai_socktype = SOCK_STREAM; + ai->ai_protocol = PF_UNSPEC; + sunaddr = (struct sockaddr_un *)ai->ai_addr; + sunaddr->sun_family = AF_UNIX; + strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path)); + cctx.aitop = ai; + } else { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = IPv4or6; + hints.ai_socktype = SOCK_STREAM; + snprintf(strport, sizeof strport, "%d", port); + if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) { + error("connect_to %.100s: unknown host (%s)", name, + ssh_gai_strerror(gaierr)); + return NULL; + } } - cctx.host = xstrdup(host); + cctx.host = xstrdup(name); cctx.port = port; cctx.ai = cctx.aitop; if ((sock = connect_next(&cctx)) == -1) { error("connect to %.100s port %d failed: %s", - host, port, strerror(errno)); + name, port, strerror(errno)); channel_connect_ctx_free(&cctx); return NULL; } @@ -3349,13 +3761,14 @@ connect_to(const char *host, u_short port, char *ctype, char *rname) } Channel * -channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname) +channel_connect_by_listen_address(const char *listen_host, + u_short listen_port, char *ctype, char *rname) { int i; for (i = 0; i < num_permitted_opens; i++) { - if (permitted_opens[i].host_to_connect != NULL && - port_match(permitted_opens[i].listen_port, listen_port)) { + if (open_listen_match_tcpip(&permitted_opens[i], listen_host, + listen_port, 1)) { return connect_to( permitted_opens[i].host_to_connect, permitted_opens[i].port_to_connect, ctype, rname); @@ -3366,29 +3779,45 @@ channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname) return NULL; } +Channel * +channel_connect_by_listen_path(const char *path, char *ctype, char *rname) +{ + int i; + + for (i = 0; i < num_permitted_opens; i++) { + if (open_listen_match_streamlocal(&permitted_opens[i], path)) { + return connect_to( + permitted_opens[i].host_to_connect, + permitted_opens[i].port_to_connect, ctype, rname); + } + } + error("WARNING: Server requests forwarding for unknown path %.100s", + path); + return NULL; +} + /* Check if connecting to that port is permitted and connect. */ Channel * -channel_connect_to(const char *host, u_short port, char *ctype, char *rname) +channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname) { int i, permit, permit_adm = 1; permit = all_opens_permitted; if (!permit) { for (i = 0; i < num_permitted_opens; i++) - if (permitted_opens[i].host_to_connect != NULL && - port_match(permitted_opens[i].port_to_connect, port) && - strcmp(permitted_opens[i].host_to_connect, host) == 0) + if (open_match(&permitted_opens[i], host, port)) { permit = 1; + break; + } } if (num_adm_permitted_opens > 0) { permit_adm = 0; for (i = 0; i < num_adm_permitted_opens; i++) - if (permitted_adm_opens[i].host_to_connect != NULL && - port_match(permitted_adm_opens[i].port_to_connect, port) && - strcmp(permitted_adm_opens[i].host_to_connect, host) - == 0) + if (open_match(&permitted_adm_opens[i], host, port)) { permit_adm = 1; + break; + } } if (!permit || !permit_adm) { @@ -3399,6 +3828,38 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname) return connect_to(host, port, ctype, rname); } +/* Check if connecting to that path is permitted and connect. */ +Channel * +channel_connect_to_path(const char *path, char *ctype, char *rname) +{ + int i, permit, permit_adm = 1; + + permit = all_opens_permitted; + if (!permit) { + for (i = 0; i < num_permitted_opens; i++) + if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) { + permit = 1; + break; + } + } + + if (num_adm_permitted_opens > 0) { + permit_adm = 0; + for (i = 0; i < num_adm_permitted_opens; i++) + if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) { + permit_adm = 1; + break; + } + } + + if (!permit || !permit_adm) { + logit("Received request to connect to path %.100s, " + "but the request was denied.", path); + return NULL; + } + return connect_to(path, PORT_STREAMLOCAL, ctype, rname); +} + void channel_send_window_changes(void) { @@ -3669,7 +4130,7 @@ x11_connect_display(void) */ /* ARGSUSED */ -void +int x11_input_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; @@ -3709,11 +4170,12 @@ x11_input_open(int type, u_int32_t seq, void *ctxt) packet_put_int(c->self); } packet_send(); + return 0; } /* dummy protocol handler that denies SSH-1 requests (agent/x11) */ /* ARGSUSED */ -void +int deny_input_open(int type, u_int32_t seq, void *ctxt) { int rchan = packet_get_int(); @@ -3733,6 +4195,7 @@ deny_input_open(int type, u_int32_t seq, void *ctxt) packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); packet_put_int(rchan); packet_send(); + return 0; } /* diff --git a/crypto/openssh/channels.h b/crypto/openssh/channels.h index 4fab9d7..9d76c9d 100644 --- a/crypto/openssh/channels.h +++ b/crypto/openssh/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.113 2013/06/07 15:37:52 dtucker Exp $ */ +/* $OpenBSD: channels.h,v 1.118 2015/07/01 02:26:31 djm Exp $ */ /* * Author: Tatu Ylonen @@ -56,7 +56,9 @@ #define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */ #define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */ #define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ -#define SSH_CHANNEL_MAX_TYPE 18 +#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */ +#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */ +#define SSH_CHANNEL_MAX_TYPE 20 #define CHANNEL_CANCEL_PORT_STATIC -1 @@ -111,7 +113,7 @@ struct Channel { time_t notbefore; /* Pause IO until deadline (time_t) */ int delayed; /* post-select handlers for newly created * channels are delayed until the first call - * to a matching pre-select handler. + * to a matching pre-select handler. * this way post-select handlers are not * accidentally called if a FD gets reused */ Buffer input; /* data read from socket, to be sent over @@ -228,17 +230,17 @@ void channel_send_window_changes(void); /* protocol handler */ -void channel_input_close(int, u_int32_t, void *); -void channel_input_close_confirmation(int, u_int32_t, void *); -void channel_input_data(int, u_int32_t, void *); -void channel_input_extended_data(int, u_int32_t, void *); -void channel_input_ieof(int, u_int32_t, void *); -void channel_input_oclose(int, u_int32_t, void *); -void channel_input_open_confirmation(int, u_int32_t, void *); -void channel_input_open_failure(int, u_int32_t, void *); -void channel_input_port_open(int, u_int32_t, void *); -void channel_input_window_adjust(int, u_int32_t, void *); -void channel_input_status_confirm(int, u_int32_t, void *); +int channel_input_close(int, u_int32_t, void *); +int channel_input_close_confirmation(int, u_int32_t, void *); +int channel_input_data(int, u_int32_t, void *); +int channel_input_extended_data(int, u_int32_t, void *); +int channel_input_ieof(int, u_int32_t, void *); +int channel_input_oclose(int, u_int32_t, void *); +int channel_input_open_confirmation(int, u_int32_t, void *); +int channel_input_open_failure(int, u_int32_t, void *); +int channel_input_port_open(int, u_int32_t, void *); +int channel_input_window_adjust(int, u_int32_t, void *); +int channel_input_status_confirm(int, u_int32_t, void *); /* file descriptor handling (read/write) */ @@ -254,6 +256,8 @@ char *channel_open_message(void); int channel_find_open(void); /* tcp forwarding */ +struct Forward; +struct ForwardOptions; void channel_set_af(int af); void channel_permit_all_opens(void); void channel_add_permitted_opens(char *, int); @@ -263,28 +267,30 @@ void channel_update_permitted_opens(int, int); void channel_clear_permitted_opens(void); void channel_clear_adm_permitted_opens(void); void channel_print_adm_permitted_opens(void); -int channel_input_port_forward_request(int, int); -Channel *channel_connect_to(const char *, u_short, char *, char *); +int channel_input_port_forward_request(int, struct ForwardOptions *); +Channel *channel_connect_to_port(const char *, u_short, char *, char *); +Channel *channel_connect_to_path(const char *, char *, char *); Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); -Channel *channel_connect_by_listen_address(u_short, char *, char *); -int channel_request_remote_forwarding(const char *, u_short, - const char *, u_short); -int channel_setup_local_fwd_listener(const char *, u_short, - const char *, u_short, int); -int channel_request_rforward_cancel(const char *host, u_short port); -int channel_setup_remote_fwd_listener(const char *, u_short, int *, int); -int channel_cancel_rport_listener(const char *, u_short); -int channel_cancel_lport_listener(const char *, u_short, int, int); +Channel *channel_connect_by_listen_address(const char *, u_short, + char *, char *); +Channel *channel_connect_by_listen_path(const char *, char *, char *); +int channel_request_remote_forwarding(struct Forward *); +int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *); +int channel_request_rforward_cancel(struct Forward *); +int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *); +int channel_cancel_rport_listener(struct Forward *); +int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *); int permitopen_port(const char *); /* x11 forwarding */ +void channel_set_x11_refuse_time(u_int); int x11_connect_display(void); int x11_create_display_inet(int, int, int, u_int *, int **); -void x11_input_open(int, u_int32_t, void *); +int x11_input_open(int, u_int32_t, void *); void x11_request_forwarding_with_spoofing(int, const char *, const char *, const char *, int); -void deny_input_open(int, u_int32_t, void *); +int deny_input_open(int, u_int32_t, void *); /* agent forwarding */ diff --git a/crypto/openssh/cipher-3des1.c b/crypto/openssh/cipher-3des1.c index b282359..6a0f1f3 100644 --- a/crypto/openssh/cipher-3des1.c +++ b/crypto/openssh/cipher-3des1.c @@ -1,15 +1,10 @@ -/* $OpenBSD: cipher-3des1.c,v 1.10 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: cipher-3des1.c,v 1.12 2015/01/14 10:24:42 markus Exp $ */ /* * Copyright (c) 2003 Markus Friedl. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -26,16 +21,10 @@ #include "includes.h" #include - -#include - -#include #include +#include -#include "xmalloc.h" -#include "log.h" - -#include "openbsd-compat/openssl-compat.h" +#include "ssherr.h" /* * This is used by SSH1: @@ -57,7 +46,7 @@ struct ssh1_3des_ctx }; const EVP_CIPHER * evp_ssh1_3des(void); -void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); +int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, @@ -67,11 +56,12 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, u_char *k1, *k2, *k3; if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - c = xcalloc(1, sizeof(*c)); + if ((c = calloc(1, sizeof(*c))) == NULL) + return 0; EVP_CIPHER_CTX_set_app_data(ctx, c); } if (key == NULL) - return (1); + return 1; if (enc == -1) enc = ctx->encrypt; k1 = k2 = k3 = (u_char *) key; @@ -85,44 +75,29 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, EVP_CIPHER_CTX_init(&c->k1); EVP_CIPHER_CTX_init(&c->k2); EVP_CIPHER_CTX_init(&c->k3); -#ifdef SSH_OLD_EVP - EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc); - EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc); - EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc); -#else if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { explicit_bzero(c, sizeof(*c)); free(c); EVP_CIPHER_CTX_set_app_data(ctx, NULL); - return (0); + return 0; } -#endif - return (1); + return 1; } static int -ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, - LIBCRYPTO_EVP_INL_TYPE len) +ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len) { struct ssh1_3des_ctx *c; - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - error("ssh1_3des_cbc: no context"); - return (0); - } -#ifdef SSH_OLD_EVP - EVP_Cipher(&c->k1, dest, (u_char *)src, len); - EVP_Cipher(&c->k2, dest, dest, len); - EVP_Cipher(&c->k3, dest, dest, len); -#else + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) + return 0; if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || EVP_Cipher(&c->k2, dest, dest, len) == 0 || EVP_Cipher(&c->k3, dest, dest, len) == 0) - return (0); -#endif - return (1); + return 0; + return 1; } static int @@ -138,29 +113,28 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) free(c); EVP_CIPHER_CTX_set_app_data(ctx, NULL); } - return (1); + return 1; } -void +int ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) { struct ssh1_3des_ctx *c; if (len != 24) - fatal("%s: bad 3des iv length: %d", __func__, len); + return SSH_ERR_INVALID_ARGUMENT; if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) - fatal("%s: no 3des context", __func__); + return SSH_ERR_INTERNAL_ERROR; if (doset) { - debug3("%s: Installed 3DES IV", __func__); memcpy(c->k1.iv, iv, 8); memcpy(c->k2.iv, iv + 8, 8); memcpy(c->k3.iv, iv + 16, 8); } else { - debug3("%s: Copying 3DES IV", __func__); memcpy(iv, c->k1.iv, 8); memcpy(iv + 8, c->k2.iv, 8); memcpy(iv + 16, c->k3.iv, 8); } + return 0; } const EVP_CIPHER * @@ -168,7 +142,7 @@ evp_ssh1_3des(void) { static EVP_CIPHER ssh1_3des; - memset(&ssh1_3des, 0, sizeof(EVP_CIPHER)); + memset(&ssh1_3des, 0, sizeof(ssh1_3des)); ssh1_3des.nid = NID_undef; ssh1_3des.block_size = 8; ssh1_3des.iv_len = 0; @@ -176,8 +150,6 @@ evp_ssh1_3des(void) ssh1_3des.init = ssh1_3des_init; ssh1_3des.cleanup = ssh1_3des_cleanup; ssh1_3des.do_cipher = ssh1_3des_cbc; -#ifndef SSH_OLD_EVP ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; -#endif - return (&ssh1_3des); + return &ssh1_3des; } diff --git a/crypto/openssh/cipher-aesctr.c b/crypto/openssh/cipher-aesctr.c new file mode 100644 index 0000000..eed95c3 --- /dev/null +++ b/crypto/openssh/cipher-aesctr.c @@ -0,0 +1,83 @@ +/* $OpenBSD: cipher-aesctr.c,v 1.2 2015/01/14 10:24:42 markus Exp $ */ +/* + * Copyright (c) 2003 Markus Friedl. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include +#include + +#ifndef WITH_OPENSSL + +#include "cipher-aesctr.h" + +/* + * increment counter 'ctr', + * the counter is of size 'len' bytes and stored in network-byte-order. + * (LSB at ctr[len-1], MSB at ctr[0]) + */ +static inline void +aesctr_inc(u8 *ctr, u32 len) +{ + ssize_t i; + +#ifndef CONSTANT_TIME_INCREMENT + for (i = len - 1; i >= 0; i--) + if (++ctr[i]) /* continue on overflow */ + return; +#else + u8 x, add = 1; + + for (i = len - 1; i >= 0; i--) { + ctr[i] += add; + /* constant time for: x = ctr[i] ? 1 : 0 */ + x = ctr[i]; + x = (x | (x >> 4)) & 0xf; + x = (x | (x >> 2)) & 0x3; + x = (x | (x >> 1)) & 0x1; + add *= (x^1); + } +#endif +} + +void +aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits) +{ + x->rounds = rijndaelKeySetupEnc(x->ek, k, kbits); +} + +void +aesctr_ivsetup(aesctr_ctx *x,const u8 *iv) +{ + memcpy(x->ctr, iv, AES_BLOCK_SIZE); +} + +void +aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes) +{ + u32 n = 0; + u8 buf[AES_BLOCK_SIZE]; + + while ((bytes--) > 0) { + if (n == 0) { + rijndaelEncrypt(x->ek, x->rounds, x->ctr, buf); + aesctr_inc(x->ctr, AES_BLOCK_SIZE); + } + *(c++) = *(m++) ^ buf[n]; + n = (n + 1) % AES_BLOCK_SIZE; + } +} +#endif /* !WITH_OPENSSL */ diff --git a/crypto/openssh/cipher-aesctr.h b/crypto/openssh/cipher-aesctr.h new file mode 100644 index 0000000..85d55bb --- /dev/null +++ b/crypto/openssh/cipher-aesctr.h @@ -0,0 +1,35 @@ +/* $OpenBSD: cipher-aesctr.h,v 1.1 2014/04/29 15:39:33 markus Exp $ */ +/* + * Copyright (c) 2014 Markus Friedl + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef OPENSSH_AESCTR_H +#define OPENSSH_AESCTR_H + +#include "rijndael.h" + +#define AES_BLOCK_SIZE 16 + +typedef struct aesctr_ctx { + int rounds; /* keylen-dependent #rounds */ + u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */ + u8 ctr[AES_BLOCK_SIZE]; /* counter */ +} aesctr_ctx; + +void aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits); +void aesctr_ivsetup(aesctr_ctx *x,const u8 *iv); +void aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes); + +#endif diff --git a/crypto/openssh/cipher-bf1.c b/crypto/openssh/cipher-bf1.c index 309509d..ee72ac08 100644 --- a/crypto/openssh/cipher-bf1.c +++ b/crypto/openssh/cipher-bf1.c @@ -1,15 +1,10 @@ -/* $OpenBSD: cipher-bf1.c,v 1.6 2010/10/01 23:05:32 djm Exp $ */ +/* $OpenBSD: cipher-bf1.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */ /* * Copyright (c) 2003 Markus Friedl. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -25,15 +20,14 @@ #include "includes.h" -#include +#ifdef WITH_OPENSSL -#include +#include #include #include -#include "xmalloc.h" -#include "log.h" +#include #include "openbsd-compat/openssl-compat.h" @@ -106,3 +100,4 @@ evp_ssh1_bf(void) ssh1_bf.key_len = 32; return (&ssh1_bf); } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/cipher-chachapoly.c b/crypto/openssh/cipher-chachapoly.c index 251b94e..7f31ff4 100644 --- a/crypto/openssh/cipher-chachapoly.c +++ b/crypto/openssh/cipher-chachapoly.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: cipher-chachapoly.c,v 1.4 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: cipher-chachapoly.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */ #include "includes.h" @@ -24,16 +24,18 @@ #include /* needed for misc.h */ #include "log.h" -#include "misc.h" +#include "sshbuf.h" +#include "ssherr.h" #include "cipher-chachapoly.h" -void chachapoly_init(struct chachapoly_ctx *ctx, +int chachapoly_init(struct chachapoly_ctx *ctx, const u_char *key, u_int keylen) { if (keylen != (32 + 32)) /* 2 x 256 bit keys */ - fatal("%s: invalid keylen %u", __func__, keylen); + return SSH_ERR_INVALID_ARGUMENT; chacha_keysetup(&ctx->main_ctx, key, 256); chacha_keysetup(&ctx->header_ctx, key + 32, 256); + return 0; } /* @@ -52,33 +54,37 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest, u_char seqbuf[8]; const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */ u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; - int r = -1; + int r = SSH_ERR_INTERNAL_ERROR; /* * Run ChaCha20 once to generate the Poly1305 key. The IV is the * packet sequence number. */ memset(poly_key, 0, sizeof(poly_key)); - put_u64(seqbuf, seqnr); + POKE_U64(seqbuf, seqnr); chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL); chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key)); - /* Set Chacha's block counter to 1 */ - chacha_ivsetup(&ctx->main_ctx, seqbuf, one); /* If decrypting, check tag before anything else */ if (!do_encrypt) { const u_char *tag = src + aadlen + len; poly1305_auth(expected_tag, src, aadlen + len, poly_key); - if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) + if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) { + r = SSH_ERR_MAC_INVALID; goto out; + } } + /* Crypt additional data */ if (aadlen) { chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen); } + + /* Set Chacha's block counter to 1 */ + chacha_ivsetup(&ctx->main_ctx, seqbuf, one); chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen, dest + aadlen, len); @@ -88,7 +94,6 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest, poly_key); } r = 0; - out: explicit_bzero(expected_tag, sizeof(expected_tag)); explicit_bzero(seqbuf, sizeof(seqbuf)); @@ -104,11 +109,10 @@ chachapoly_get_length(struct chachapoly_ctx *ctx, u_char buf[4], seqbuf[8]; if (len < 4) - return -1; /* Insufficient length */ - put_u64(seqbuf, seqnr); + return SSH_ERR_MESSAGE_INCOMPLETE; + POKE_U64(seqbuf, seqnr); chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4); - *plenp = get_u32(buf); + *plenp = PEEK_U32(buf); return 0; } - diff --git a/crypto/openssh/cipher-chachapoly.h b/crypto/openssh/cipher-chachapoly.h index 1628693..b7072be 100644 --- a/crypto/openssh/cipher-chachapoly.h +++ b/crypto/openssh/cipher-chachapoly.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher-chachapoly.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ +/* $OpenBSD: cipher-chachapoly.h,v 1.4 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) Damien Miller 2013 @@ -28,7 +28,7 @@ struct chachapoly_ctx { struct chacha_ctx main_ctx, header_ctx; }; -void chachapoly_init(struct chachapoly_ctx *cpctx, +int chachapoly_init(struct chachapoly_ctx *cpctx, const u_char *key, u_int keylen) __attribute__((__bounded__(__buffer__, 2, 3))); int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr, diff --git a/crypto/openssh/cipher-ctr.c b/crypto/openssh/cipher-ctr.c index ea0f9b3..32771f2 100644 --- a/crypto/openssh/cipher-ctr.c +++ b/crypto/openssh/cipher-ctr.c @@ -16,7 +16,7 @@ */ #include "includes.h" -#ifndef OPENSSL_HAVE_EVPCTR +#if defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR) #include #include @@ -143,4 +143,4 @@ evp_aes_128_ctr(void) return (&aes_ctr); } -#endif /* OPENSSL_HAVE_EVPCTR */ +#endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR) */ diff --git a/crypto/openssh/cipher.c b/crypto/openssh/cipher.c index 53d9b4f..02dae6f 100644 --- a/crypto/openssh/cipher.c +++ b/crypto/openssh/cipher.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.c,v 1.97 2014/02/07 06:55:54 djm Exp $ */ +/* $OpenBSD: cipher.c,v 1.100 2015/01/14 10:29:45 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -43,21 +43,21 @@ #include #include -#include "xmalloc.h" -#include "log.h" -#include "misc.h" #include "cipher.h" -#include "buffer.h" +#include "misc.h" +#include "sshbuf.h" +#include "ssherr.h" #include "digest.h" -/* compatibility with old or broken OpenSSL versions */ #include "openbsd-compat/openssl-compat.h" +#ifdef WITH_SSH1 extern const EVP_CIPHER *evp_ssh1_bf(void); extern const EVP_CIPHER *evp_ssh1_3des(void); -extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); +extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); +#endif -struct Cipher { +struct sshcipher { char *name; int number; /* for ssh1 only */ u_int block_size; @@ -68,15 +68,23 @@ struct Cipher { u_int flags; #define CFLAG_CBC (1<<0) #define CFLAG_CHACHAPOLY (1<<1) +#define CFLAG_AESCTR (1<<2) +#define CFLAG_NONE (1<<3) +#ifdef WITH_OPENSSL const EVP_CIPHER *(*evptype)(void); +#else + void *ignored; +#endif }; -static const struct Cipher ciphers[] = { - { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, +static const struct sshcipher ciphers[] = { +#ifdef WITH_SSH1 { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, - +#endif /* WITH_SSH1 */ +#ifdef WITH_OPENSSL + { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, @@ -93,26 +101,33 @@ static const struct Cipher ciphers[] = { { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, -#ifdef OPENSSL_HAVE_EVPGCM +# ifdef OPENSSL_HAVE_EVPGCM { "aes128-gcm@openssh.com", SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, { "aes256-gcm@openssh.com", SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, -#endif +# endif /* OPENSSL_HAVE_EVPGCM */ +#else /* WITH_OPENSSL */ + { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL }, + { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL }, + { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL }, + { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL }, +#endif /* WITH_OPENSSL */ { "chacha20-poly1305@openssh.com", SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, + { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } }; /*--*/ -/* Returns a list of supported ciphers separated by the specified char. */ +/* Returns a comma-separated list of supported ciphers. */ char * cipher_alg_list(char sep, int auth_only) { - char *ret = NULL; + char *tmp, *ret = NULL; size_t nlen, rlen = 0; - const Cipher *c; + const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) { if (c->number != SSH_CIPHER_SSH2) @@ -122,7 +137,11 @@ cipher_alg_list(char sep, int auth_only) if (ret != NULL) ret[rlen++] = sep; nlen = strlen(c->name); - ret = xrealloc(ret, 1, rlen + nlen + 2); + if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { + free(ret); + return NULL; + } + ret = tmp; memcpy(ret + rlen, c->name, nlen + 1); rlen += nlen; } @@ -130,19 +149,19 @@ cipher_alg_list(char sep, int auth_only) } u_int -cipher_blocksize(const Cipher *c) +cipher_blocksize(const struct sshcipher *c) { return (c->block_size); } u_int -cipher_keylen(const Cipher *c) +cipher_keylen(const struct sshcipher *c) { return (c->key_len); } u_int -cipher_seclen(const Cipher *c) +cipher_seclen(const struct sshcipher *c) { if (strcmp("3des-cbc", c->name) == 0) return 14; @@ -150,13 +169,13 @@ cipher_seclen(const Cipher *c) } u_int -cipher_authlen(const Cipher *c) +cipher_authlen(const struct sshcipher *c) { return (c->auth_len); } u_int -cipher_ivlen(const Cipher *c) +cipher_ivlen(const struct sshcipher *c) { /* * Default is cipher block size, except for chacha20+poly1305 that @@ -167,13 +186,13 @@ cipher_ivlen(const Cipher *c) } u_int -cipher_get_number(const Cipher *c) +cipher_get_number(const struct sshcipher *c) { return (c->number); } u_int -cipher_is_cbc(const Cipher *c) +cipher_is_cbc(const struct sshcipher *c) { return (c->flags & CFLAG_CBC) != 0; } @@ -190,20 +209,20 @@ cipher_mask_ssh1(int client) return mask; } -const Cipher * +const struct sshcipher * cipher_by_name(const char *name) { - const Cipher *c; + const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) if (strcmp(c->name, name) == 0) return c; return NULL; } -const Cipher * +const struct sshcipher * cipher_by_number(int id) { - const Cipher *c; + const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) if (c->number == id) return c; @@ -214,23 +233,22 @@ cipher_by_number(int id) int ciphers_valid(const char *names) { - const Cipher *c; + const struct sshcipher *c; char *cipher_list, *cp; char *p; if (names == NULL || strcmp(names, "") == 0) return 0; - cipher_list = cp = xstrdup(names); + if ((cipher_list = cp = strdup(names)) == NULL) + return 0; for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); if (c == NULL || c->number != SSH_CIPHER_SSH2) { - debug("bad cipher %s [%s]", p, names); free(cipher_list); return 0; } } - debug3("ciphers ok: [%s]", names); free(cipher_list); return 1; } @@ -243,7 +261,7 @@ ciphers_valid(const char *names) int cipher_number(const char *name) { - const Cipher *c; + const struct sshcipher *c; if (name == NULL) return -1; for (c = ciphers; c->name != NULL; c++) @@ -255,90 +273,104 @@ cipher_number(const char *name) char * cipher_name(int id) { - const Cipher *c = cipher_by_number(id); + const struct sshcipher *c = cipher_by_number(id); return (c==NULL) ? "" : c->name; } -void -cipher_init(CipherContext *cc, const Cipher *cipher, +const char * +cipher_warning_message(const struct sshcipher_ctx *cc) +{ + if (cc == NULL || cc->cipher == NULL) + return NULL; + if (cc->cipher->number == SSH_CIPHER_DES) + return "use of DES is strongly discouraged due to " + "cryptographic weaknesses"; + return NULL; +} + +int +cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher, const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, int do_encrypt) { - static int dowarn = 1; -#ifdef SSH_OLD_EVP - EVP_CIPHER *type; -#else +#ifdef WITH_OPENSSL + int ret = SSH_ERR_INTERNAL_ERROR; const EVP_CIPHER *type; int klen; -#endif u_char *junk, *discard; if (cipher->number == SSH_CIPHER_DES) { - if (dowarn) { - error("Warning: use of DES is strongly discouraged " - "due to cryptographic weaknesses"); - dowarn = 0; - } if (keylen > 8) keylen = 8; } +#endif cc->plaintext = (cipher->number == SSH_CIPHER_NONE); cc->encrypt = do_encrypt; - if (keylen < cipher->key_len) - fatal("cipher_init: key length %d is insufficient for %s.", - keylen, cipher->name); - if (iv != NULL && ivlen < cipher_ivlen(cipher)) - fatal("cipher_init: iv length %d is insufficient for %s.", - ivlen, cipher->name); - cc->cipher = cipher; + if (keylen < cipher->key_len || + (iv != NULL && ivlen < cipher_ivlen(cipher))) + return SSH_ERR_INVALID_ARGUMENT; + cc->cipher = cipher; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { - chachapoly_init(&cc->cp_ctx, key, keylen); - return; + return chachapoly_init(&cc->cp_ctx, key, keylen); } - type = (*cipher->evptype)(); - EVP_CIPHER_CTX_init(&cc->evp); -#ifdef SSH_OLD_EVP - if (type->key_len > 0 && type->key_len != keylen) { - debug("cipher_init: set keylen (%d -> %d)", - type->key_len, keylen); - type->key_len = keylen; +#ifndef WITH_OPENSSL + if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { + aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); + aesctr_ivsetup(&cc->ac_ctx, iv); + return 0; } - EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv, - (do_encrypt == CIPHER_ENCRYPT)); + if ((cc->cipher->flags & CFLAG_NONE) != 0) + return 0; + return SSH_ERR_INVALID_ARGUMENT; #else + type = (*cipher->evptype)(); + EVP_CIPHER_CTX_init(&cc->evp); if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, - (do_encrypt == CIPHER_ENCRYPT)) == 0) - fatal("cipher_init: EVP_CipherInit failed for %s", - cipher->name); + (do_encrypt == CIPHER_ENCRYPT)) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto bad; + } if (cipher_authlen(cipher) && !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, - -1, (u_char *)iv)) - fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s", - cipher->name); + -1, (u_char *)iv)) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto bad; + } klen = EVP_CIPHER_CTX_key_length(&cc->evp); if (klen > 0 && keylen != (u_int)klen) { - debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); - if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) - fatal("cipher_init: set keylen failed (%d -> %d)", - klen, keylen); + if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto bad; + } + } + if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto bad; } - if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) - fatal("cipher_init: EVP_CipherInit: set key failed for %s", - cipher->name); -#endif if (cipher->discard_len > 0) { - junk = xmalloc(cipher->discard_len); - discard = xmalloc(cipher->discard_len); - if (EVP_Cipher(&cc->evp, discard, junk, - cipher->discard_len) == 0) - fatal("evp_crypt: EVP_Cipher failed during discard"); + if ((junk = malloc(cipher->discard_len)) == NULL || + (discard = malloc(cipher->discard_len)) == NULL) { + if (junk != NULL) + free(junk); + ret = SSH_ERR_ALLOC_FAIL; + goto bad; + } + ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len); explicit_bzero(discard, cipher->discard_len); free(junk); free(discard); + if (ret != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + bad: + EVP_CIPHER_CTX_cleanup(&cc->evp); + return ret; + } } +#endif + return 0; } /* @@ -350,204 +382,252 @@ cipher_init(CipherContext *cc, const Cipher *cipher, * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. * This tag is written on encryption and verified on decryption. * Both 'aadlen' and 'authlen' can be set to 0. - * cipher_crypt() returns 0 on success and -1 if the decryption integrity - * check fails. */ int -cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src, - u_int len, u_int aadlen, u_int authlen) +cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest, + const u_char *src, u_int len, u_int aadlen, u_int authlen) { - if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) - return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, - aadlen, authlen, cc->encrypt); + if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { + return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, + len, aadlen, authlen, cc->encrypt); + } +#ifndef WITH_OPENSSL + if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { + if (aadlen) + memcpy(dest, src, aadlen); + aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen, + dest + aadlen, len); + return 0; + } + if ((cc->cipher->flags & CFLAG_NONE) != 0) { + memcpy(dest, src, aadlen + len); + return 0; + } + return SSH_ERR_INVALID_ARGUMENT; +#else if (authlen) { u_char lastiv[1]; if (authlen != cipher_authlen(cc->cipher)) - fatal("%s: authlen mismatch %d", __func__, authlen); + return SSH_ERR_INVALID_ARGUMENT; /* increment IV */ if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv)) - fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); + return SSH_ERR_LIBCRYPTO_ERROR; /* set tag on decyption */ if (!cc->encrypt && !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, authlen, (u_char *)src + aadlen + len)) - fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__); + return SSH_ERR_LIBCRYPTO_ERROR; } if (aadlen) { if (authlen && EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) - fatal("%s: EVP_Cipher(aad) failed", __func__); + return SSH_ERR_LIBCRYPTO_ERROR; memcpy(dest, src, aadlen); } if (len % cc->cipher->block_size) - fatal("%s: bad plaintext length %d", __func__, len); + return SSH_ERR_INVALID_ARGUMENT; if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, len) < 0) - fatal("%s: EVP_Cipher failed", __func__); + return SSH_ERR_LIBCRYPTO_ERROR; if (authlen) { /* compute tag (on encrypt) or verify tag (on decrypt) */ - if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) { - if (cc->encrypt) - fatal("%s: EVP_Cipher(final) failed", __func__); - else - return -1; - } + if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) + return cc->encrypt ? + SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID; if (cc->encrypt && !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, authlen, dest + aadlen + len)) - fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); + return SSH_ERR_LIBCRYPTO_ERROR; } return 0; +#endif } /* Extract the packet length, including any decryption necessary beforehand */ int -cipher_get_length(CipherContext *cc, u_int *plenp, u_int seqnr, +cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, const u_char *cp, u_int len) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, cp, len); if (len < 4) - return -1; + return SSH_ERR_MESSAGE_INCOMPLETE; *plenp = get_u32(cp); return 0; } -void -cipher_cleanup(CipherContext *cc) +int +cipher_cleanup(struct sshcipher_ctx *cc) { + if (cc == NULL || cc->cipher == NULL) + return 0; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); + else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) + explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx)); +#ifdef WITH_OPENSSL else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) - error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); + return SSH_ERR_LIBCRYPTO_ERROR; +#endif + return 0; } /* * Selects the cipher, and keys if by computing the MD5 checksum of the * passphrase and using the resulting 16 bytes as the key. */ - -void -cipher_set_key_string(CipherContext *cc, const Cipher *cipher, +int +cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher, const char *passphrase, int do_encrypt) { u_char digest[16]; + int r = SSH_ERR_INTERNAL_ERROR; - if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), - digest, sizeof(digest)) < 0) - fatal("%s: md5 failed", __func__); - - cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); + if ((r = ssh_digest_memory(SSH_DIGEST_MD5, + passphrase, strlen(passphrase), + digest, sizeof(digest))) != 0) + goto out; + r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); + out: explicit_bzero(digest, sizeof(digest)); + return r; } /* - * Exports an IV from the CipherContext required to export the key + * Exports an IV from the sshcipher_ctx required to export the key * state back from the unprivileged child to the privileged parent * process. */ - int -cipher_get_keyiv_len(const CipherContext *cc) +cipher_get_keyiv_len(const struct sshcipher_ctx *cc) { - const Cipher *c = cc->cipher; - int ivlen; + const struct sshcipher *c = cc->cipher; + int ivlen = 0; if (c->number == SSH_CIPHER_3DES) ivlen = 24; else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) ivlen = 0; + else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) + ivlen = sizeof(cc->ac_ctx.ctr); +#ifdef WITH_OPENSSL else ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); +#endif /* WITH_OPENSSL */ return (ivlen); } -void -cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) +int +cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) { - const Cipher *c = cc->cipher; - int evplen; + const struct sshcipher *c = cc->cipher; +#ifdef WITH_OPENSSL + int evplen; +#endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { if (len != 0) - fatal("%s: wrong iv length %d != %d", __func__, len, 0); - return; + return SSH_ERR_INVALID_ARGUMENT; + return 0; + } + if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { + if (len != sizeof(cc->ac_ctx.ctr)) + return SSH_ERR_INVALID_ARGUMENT; + memcpy(iv, cc->ac_ctx.ctr, len); + return 0; } + if ((cc->cipher->flags & CFLAG_NONE) != 0) + return 0; switch (c->number) { +#ifdef WITH_OPENSSL case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); - if (evplen <= 0) - return; + if (evplen == 0) + return 0; + else if (evplen < 0) + return SSH_ERR_LIBCRYPTO_ERROR; if ((u_int)evplen != len) - fatal("%s: wrong iv length %d != %d", __func__, - evplen, len); -#ifdef USE_BUILTIN_RIJNDAEL - if (c->evptype == evp_rijndael) - ssh_rijndael_iv(&cc->evp, 0, iv, len); - else -#endif + return SSH_ERR_INVALID_ARGUMENT; #ifndef OPENSSL_HAVE_EVPCTR if (c->evptype == evp_aes_128_ctr) ssh_aes_ctr_iv(&cc->evp, 0, iv, len); else #endif - memcpy(iv, cc->evp.iv, len); + if (cipher_authlen(c)) { + if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, + len, iv)) + return SSH_ERR_LIBCRYPTO_ERROR; + } else + memcpy(iv, cc->evp.iv, len); break; +#endif +#ifdef WITH_SSH1 case SSH_CIPHER_3DES: - ssh1_3des_iv(&cc->evp, 0, iv, 24); - break; + return ssh1_3des_iv(&cc->evp, 0, iv, 24); +#endif default: - fatal("%s: bad cipher %d", __func__, c->number); + return SSH_ERR_INVALID_ARGUMENT; } + return 0; } -void -cipher_set_keyiv(CipherContext *cc, u_char *iv) +int +cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) { - const Cipher *c = cc->cipher; - int evplen = 0; + const struct sshcipher *c = cc->cipher; +#ifdef WITH_OPENSSL + int evplen = 0; +#endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) - return; + return 0; + if ((cc->cipher->flags & CFLAG_NONE) != 0) + return 0; switch (c->number) { +#ifdef WITH_OPENSSL case SSH_CIPHER_SSH2: case SSH_CIPHER_DES: case SSH_CIPHER_BLOWFISH: evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); - if (evplen == 0) - return; -#ifdef USE_BUILTIN_RIJNDAEL - if (c->evptype == evp_rijndael) - ssh_rijndael_iv(&cc->evp, 1, iv, evplen); - else -#endif -#ifndef OPENSSL_HAVE_EVPCTR - if (c->evptype == evp_aes_128_ctr) - ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen); - else -#endif - memcpy(cc->evp.iv, iv, evplen); + if (evplen <= 0) + return SSH_ERR_LIBCRYPTO_ERROR; + if (cipher_authlen(c)) { + /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ + if (!EVP_CIPHER_CTX_ctrl(&cc->evp, + EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) + return SSH_ERR_LIBCRYPTO_ERROR; + } else + memcpy(cc->evp.iv, iv, evplen); break; +#endif +#ifdef WITH_SSH1 case SSH_CIPHER_3DES: - ssh1_3des_iv(&cc->evp, 1, iv, 24); - break; + return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24); +#endif default: - fatal("%s: bad cipher %d", __func__, c->number); + return SSH_ERR_INVALID_ARGUMENT; } + return 0; } +#ifdef WITH_OPENSSL +#define EVP_X_STATE(evp) (evp).cipher_data +#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size +#endif + int -cipher_get_keycontext(const CipherContext *cc, u_char *dat) +cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat) { - const Cipher *c = cc->cipher; +#ifdef WITH_OPENSSL + const struct sshcipher *c = cc->cipher; int plen = 0; if (c->evptype == EVP_rc4) { @@ -557,16 +637,21 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat) memcpy(dat, EVP_X_STATE(cc->evp), plen); } return (plen); +#else + return 0; +#endif } void -cipher_set_keycontext(CipherContext *cc, u_char *dat) +cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat) { - const Cipher *c = cc->cipher; +#ifdef WITH_OPENSSL + const struct sshcipher *c = cc->cipher; int plen; if (c->evptype == EVP_rc4) { plen = EVP_X_STATE_LEN(cc->evp); memcpy(EVP_X_STATE(cc->evp), dat, plen); } +#endif } diff --git a/crypto/openssh/cipher.h b/crypto/openssh/cipher.h index 133d2e7..06d4be4 100644 --- a/crypto/openssh/cipher.h +++ b/crypto/openssh/cipher.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.h,v 1.44 2014/01/25 10:12:50 dtucker Exp $ */ +/* $OpenBSD: cipher.h,v 1.48 2015/07/08 19:09:25 markus Exp $ */ /* * Author: Tatu Ylonen @@ -37,8 +37,10 @@ #ifndef CIPHER_H #define CIPHER_H +#include #include #include "cipher-chachapoly.h" +#include "cipher-aesctr.h" /* * Cipher types for SSH-1. New types can be added, but old types should not @@ -60,44 +62,44 @@ #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 -typedef struct Cipher Cipher; -typedef struct CipherContext CipherContext; - -struct Cipher; -struct CipherContext { +struct sshcipher; +struct sshcipher_ctx { int plaintext; int encrypt; EVP_CIPHER_CTX evp; struct chachapoly_ctx cp_ctx; /* XXX union with evp? */ - const Cipher *cipher; + struct aesctr_ctx ac_ctx; /* XXX union with evp? */ + const struct sshcipher *cipher; }; u_int cipher_mask_ssh1(int); -const Cipher *cipher_by_name(const char *); -const Cipher *cipher_by_number(int); +const struct sshcipher *cipher_by_name(const char *); +const struct sshcipher *cipher_by_number(int); int cipher_number(const char *); char *cipher_name(int); +const char *cipher_warning_message(const struct sshcipher_ctx *); int ciphers_valid(const char *); char *cipher_alg_list(char, int); -void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int, - const u_char *, u_int, int); -int cipher_crypt(CipherContext *, u_int, u_char *, const u_char *, +int cipher_init(struct sshcipher_ctx *, const struct sshcipher *, + const u_char *, u_int, const u_char *, u_int, int); +int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *, u_int, u_int, u_int); -int cipher_get_length(CipherContext *, u_int *, u_int, +int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int, const u_char *, u_int); -void cipher_cleanup(CipherContext *); -void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); -u_int cipher_blocksize(const Cipher *); -u_int cipher_keylen(const Cipher *); -u_int cipher_seclen(const Cipher *); -u_int cipher_authlen(const Cipher *); -u_int cipher_ivlen(const Cipher *); -u_int cipher_is_cbc(const Cipher *); +int cipher_cleanup(struct sshcipher_ctx *); +int cipher_set_key_string(struct sshcipher_ctx *, const struct sshcipher *, + const char *, int); +u_int cipher_blocksize(const struct sshcipher *); +u_int cipher_keylen(const struct sshcipher *); +u_int cipher_seclen(const struct sshcipher *); +u_int cipher_authlen(const struct sshcipher *); +u_int cipher_ivlen(const struct sshcipher *); +u_int cipher_is_cbc(const struct sshcipher *); -u_int cipher_get_number(const Cipher *); -void cipher_get_keyiv(CipherContext *, u_char *, u_int); -void cipher_set_keyiv(CipherContext *, u_char *); -int cipher_get_keyiv_len(const CipherContext *); -int cipher_get_keycontext(const CipherContext *, u_char *); -void cipher_set_keycontext(CipherContext *, u_char *); +u_int cipher_get_number(const struct sshcipher *); +int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int); +int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *); +int cipher_get_keyiv_len(const struct sshcipher_ctx *); +int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *); +void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *); #endif /* CIPHER_H */ diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c index 59ad3a2..87ceb3d 100644 --- a/crypto/openssh/clientloop.c +++ b/crypto/openssh/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.258 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.275 2015/07/10 06:21:53 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -61,9 +61,9 @@ #include "includes.h" +#include /* MIN MAX */ #include #include -#include #ifdef HAVE_SYS_STAT_H # include #endif @@ -85,6 +85,7 @@ #include #include #include +#include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" @@ -99,17 +100,20 @@ #include "key.h" #include "cipher.h" #include "kex.h" +#include "myproposal.h" #include "log.h" +#include "misc.h" #include "readconf.h" #include "clientloop.h" #include "sshconnect.h" #include "authfd.h" #include "atomicio.h" #include "sshpty.h" -#include "misc.h" #include "match.h" #include "msg.h" #include "roaming.h" +#include "ssherr.h" +#include "hostfile.h" /* import options */ extern Options options; @@ -160,7 +164,7 @@ static int connection_in; /* Connection to server (input). */ static int connection_out; /* Connection to server (output). */ static int need_rekeying; /* Set to non-zero if rekeying is requested. */ static int session_closed; /* In SSH2: login session closed. */ -static int x11_refuse_time; /* If >0, refuse x11 opens after this time. */ +static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */ static void client_init_dispatch(void); int session_ident = -1; @@ -191,9 +195,6 @@ TAILQ_HEAD(global_confirms, global_confirm); static struct global_confirms global_confirms = TAILQ_HEAD_INITIALIZER(global_confirms); -/*XXX*/ -extern Kex *xxx_kex; - void ssh_process_session2_setup(int, int, int, Buffer *); /* Restores stdin to blocking mode. */ @@ -298,7 +299,8 @@ client_x11_display_valid(const char *display) return 1; } -#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" +#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" +#define X11_TIMEOUT_SLACK 60 void client_x11_get_proto(const char *display, const char *xauth_path, u_int trusted, u_int timeout, char **_proto, char **_data) @@ -311,7 +313,7 @@ client_x11_get_proto(const char *display, const char *xauth_path, int got_data = 0, generated = 0, do_unlink = 0, i; char *xauthdir, *xauthfile; struct stat st; - u_int now; + u_int now, x11_timeout_real; xauthdir = xauthfile = NULL; *_proto = proto; @@ -341,27 +343,39 @@ client_x11_get_proto(const char *display, const char *xauth_path, display = xdisplay; } if (trusted == 0) { - xauthdir = xmalloc(MAXPATHLEN); - xauthfile = xmalloc(MAXPATHLEN); - mktemp_proto(xauthdir, MAXPATHLEN); + xauthdir = xmalloc(PATH_MAX); + xauthfile = xmalloc(PATH_MAX); + mktemp_proto(xauthdir, PATH_MAX); + /* + * The authentication cookie should briefly outlive + * ssh's willingness to forward X11 connections to + * avoid nasty fail-open behaviour in the X server. + */ + if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK) + x11_timeout_real = UINT_MAX; + else + x11_timeout_real = timeout + X11_TIMEOUT_SLACK; if (mkdtemp(xauthdir) != NULL) { do_unlink = 1; - snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile", + snprintf(xauthfile, PATH_MAX, "%s/xauthfile", xauthdir); snprintf(cmd, sizeof(cmd), "%s -f %s generate %s " SSH_X11_PROTO " untrusted timeout %u 2>" _PATH_DEVNULL, - xauth_path, xauthfile, display, timeout); + xauth_path, xauthfile, display, + x11_timeout_real); debug2("x11_get_proto: %s", cmd); - if (system(cmd) == 0) - generated = 1; if (x11_refuse_time == 0) { now = monotime() + 1; if (UINT_MAX - timeout < now) x11_refuse_time = UINT_MAX; else x11_refuse_time = now + timeout; + channel_set_x11_refuse_time( + x11_refuse_time); } + if (system(cmd) == 0) + generated = 1; } } @@ -538,13 +552,13 @@ client_check_window_change(void) } } -static void +static int client_global_request_reply(int type, u_int32_t seq, void *ctxt) { struct global_confirm *gc; if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) - return; + return 0; if (gc->cb != NULL) gc->cb(type, seq, gc->ctx); if (--gc->ref_count <= 0) { @@ -554,6 +568,7 @@ client_global_request_reply(int type, u_int32_t seq, void *ctxt) } packet_set_alive_timeouts(0); + return 0; } static void @@ -871,13 +886,11 @@ static void process_cmdline(void) { void (*handler)(int); - char *s, *cmd, *cancel_host; - int delete = 0, local = 0, remote = 0, dynamic = 0; - int cancel_port, ok; - Forward fwd; + char *s, *cmd; + int ok, delete = 0, local = 0, remote = 0, dynamic = 0; + struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); - fwd.listen_host = fwd.connect_host = NULL; leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); handler = signal(SIGINT, SIG_IGN); @@ -943,29 +956,20 @@ process_cmdline(void) /* XXX update list of forwards in options */ if (delete) { - cancel_port = 0; - cancel_host = hpdelim(&s); /* may be NULL */ - if (s != NULL) { - cancel_port = a2port(s); - cancel_host = cleanhostname(cancel_host); - } else { - cancel_port = a2port(cancel_host); - cancel_host = NULL; - } - if (cancel_port <= 0) { - logit("Bad forwarding close port"); + /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */ + if (!parse_forward(&fwd, s, 1, 0)) { + logit("Bad forwarding close specification."); goto out; } if (remote) - ok = channel_request_rforward_cancel(cancel_host, - cancel_port) == 0; + ok = channel_request_rforward_cancel(&fwd) == 0; else if (dynamic) - ok = channel_cancel_lport_listener(cancel_host, - cancel_port, 0, options.gateway_ports) > 0; + ok = channel_cancel_lport_listener(&fwd, + 0, &options.fwd_opts) > 0; else - ok = channel_cancel_lport_listener(cancel_host, - cancel_port, CHANNEL_CANCEL_PORT_STATIC, - options.gateway_ports) > 0; + ok = channel_cancel_lport_listener(&fwd, + CHANNEL_CANCEL_PORT_STATIC, + &options.fwd_opts) > 0; if (!ok) { logit("Unkown port forwarding."); goto out; @@ -977,16 +981,13 @@ process_cmdline(void) goto out; } if (local || dynamic) { - if (!channel_setup_local_fwd_listener(fwd.listen_host, - fwd.listen_port, fwd.connect_host, - fwd.connect_port, options.gateway_ports)) { + if (!channel_setup_local_fwd_listener(&fwd, + &options.fwd_opts)) { logit("Port forwarding failed."); goto out; } } else { - if (channel_request_remote_forwarding(fwd.listen_host, - fwd.listen_port, fwd.connect_host, - fwd.connect_port) < 0) { + if (channel_request_remote_forwarding(&fwd) < 0) { logit("Port forwarding failed."); goto out; } @@ -999,7 +1000,9 @@ out: enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); free(cmd); free(fwd.listen_host); + free(fwd.listen_path); free(fwd.connect_host); + free(fwd.connect_path); } /* reasons to suppress output of an escape command in help output */ @@ -1426,8 +1429,7 @@ client_process_output(fd_set *writeset) static void client_process_buffered_input_packets(void) { - dispatch_run(DISPATCH_NONBLOCK, &quit_pending, - compat20 ? xxx_kex : NULL); + dispatch_run(DISPATCH_NONBLOCK, &quit_pending, active_state); } /* scan buf[] for '~' before sending data to the peer */ @@ -1481,7 +1483,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) { fd_set *readset = NULL, *writeset = NULL; double start_time, total_time; - int max_fd = 0, max_fd2 = 0, len, rekeying = 0; + int r, max_fd = 0, max_fd2 = 0, len, rekeying = 0; u_int64_t ibytes, obytes; u_int nalloc = 0; char buf[100]; @@ -1566,7 +1568,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) if (compat20 && session_closed && !channel_still_open()) break; - rekeying = (xxx_kex != NULL && !xxx_kex->done); + rekeying = (active_state->kex != NULL && !active_state->kex->done); if (rekeying) { debug("rekeying in progress"); @@ -1610,8 +1612,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) channel_after_select(readset, writeset); if (need_rekeying || packet_need_rekeying()) { debug("need rekeying"); - xxx_kex->done = 0; - kex_send_kexinit(xxx_kex); + active_state->kex->done = 0; + if ((r = kex_send_kexinit(active_state)) != 0) + fatal("%s: kex_send_kexinit: %s", + __func__, ssh_err(r)); need_rekeying = 0; } } @@ -1740,8 +1744,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* Report bytes transferred, and transfer rates. */ total_time = get_current_time() - start_time; - packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); - packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); + packet_get_bytes(&ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds", (unsigned long long)obytes, (unsigned long long)ibytes, total_time); if (total_time > 0) @@ -1754,7 +1757,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /*********/ -static void +static int client_input_stdout_data(int type, u_int32_t seq, void *ctxt) { u_int data_len; @@ -1763,8 +1766,9 @@ client_input_stdout_data(int type, u_int32_t seq, void *ctxt) buffer_append(&stdout_buffer, data, data_len); explicit_bzero(data, data_len); free(data); + return 0; } -static void +static int client_input_stderr_data(int type, u_int32_t seq, void *ctxt) { u_int data_len; @@ -1773,8 +1777,9 @@ client_input_stderr_data(int type, u_int32_t seq, void *ctxt) buffer_append(&stderr_buffer, data, data_len); explicit_bzero(data, data_len); free(data); + return 0; } -static void +static int client_input_exit_status(int type, u_int32_t seq, void *ctxt) { exit_status = packet_get_int(); @@ -1789,12 +1794,14 @@ client_input_exit_status(int type, u_int32_t seq, void *ctxt) packet_write_wait(); /* Flag that we want to exit. */ quit_pending = 1; + return 0; } -static void + +static int client_input_agent_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; - int remote_id, sock; + int r, remote_id, sock; /* Read the remote channel number from the message. */ remote_id = packet_get_int(); @@ -1804,7 +1811,11 @@ client_input_agent_open(int type, u_int32_t seq, void *ctxt) * Get a connection to the local authentication agent (this may again * get forwarded). */ - sock = ssh_get_authentication_socket(); + if ((r = ssh_get_authentication_socket(&sock)) != 0 && + r != SSH_ERR_AGENT_NOT_PRESENT) + debug("%s: ssh_get_authentication_socket: %s", + __func__, ssh_err(r)); + /* * If we could not connect the agent, send an error message back to @@ -1829,6 +1840,7 @@ client_input_agent_open(int type, u_int32_t seq, void *ctxt) packet_put_int(c->self); } packet_send(); + return 0; } static Channel * @@ -1845,11 +1857,10 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) originator_port = packet_get_int(); packet_check_eom(); - debug("client_request_forwarded_tcpip: listen %s port %d, " - "originator %s port %d", listen_address, listen_port, - originator_address, originator_port); + debug("%s: listen %s port %d, originator %s port %d", __func__, + listen_address, listen_port, originator_address, originator_port); - c = channel_connect_by_listen_address(listen_port, + c = channel_connect_by_listen_address(listen_address, listen_port, "forwarded-tcpip", originator_address); free(originator_address); @@ -1858,6 +1869,27 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) } static Channel * +client_request_forwarded_streamlocal(const char *request_type, int rchan) +{ + Channel *c = NULL; + char *listen_path; + + /* Get the remote path. */ + listen_path = packet_get_string(NULL); + /* XXX: Skip reserved field for now. */ + if (packet_get_string_ptr(NULL) == NULL) + fatal("%s: packet_get_string_ptr failed", __func__); + packet_check_eom(); + + debug("%s: %s", __func__, listen_path); + + c = channel_connect_by_listen_path(listen_path, + "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); + free(listen_path); + return c; +} + +static Channel * client_request_x11(const char *request_type, int rchan) { Channel *c = NULL; @@ -1871,7 +1903,7 @@ client_request_x11(const char *request_type, int rchan) "malicious server."); return NULL; } - if (x11_refuse_time != 0 && monotime() >= x11_refuse_time) { + if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) { verbose("Rejected X11 connection after ForwardX11Timeout " "expired"); return NULL; @@ -1902,7 +1934,7 @@ static Channel * client_request_agent(const char *request_type, int rchan) { Channel *c = NULL; - int sock; + int r, sock; if (!options.forward_agent) { error("Warning: ssh server tried agent forwarding."); @@ -1910,9 +1942,12 @@ client_request_agent(const char *request_type, int rchan) "malicious server."); return NULL; } - sock = ssh_get_authentication_socket(); - if (sock < 0) + if ((r = ssh_get_authentication_socket(&sock)) != 0) { + if (r != SSH_ERR_AGENT_NOT_PRESENT) + debug("%s: ssh_get_authentication_socket: %s", + __func__, ssh_err(r)); return NULL; + } c = channel_new("authentication agent connection", SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, @@ -1966,7 +2001,7 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) } /* XXXX move to generic input handler */ -static void +static int client_input_channel_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; @@ -1984,6 +2019,8 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt) if (strcmp(ctype, "forwarded-tcpip") == 0) { c = client_request_forwarded_tcpip(ctype, rchan); + } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { + c = client_request_forwarded_streamlocal(ctype, rchan); } else if (strcmp(ctype, "x11") == 0) { c = client_request_x11(ctype, rchan); } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { @@ -2015,8 +2052,10 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt) packet_send(); } free(ctype); + return 0; } -static void + +static int client_input_channel_req(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; @@ -2054,25 +2093,402 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) } packet_check_eom(); } - if (reply && c != NULL) { + if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); packet_put_int(c->remote_id); packet_send(); } free(rtype); + return 0; } + +struct hostkeys_update_ctx { + /* The hostname and (optionally) IP address string for the server */ + char *host_str, *ip_str; + + /* + * Keys received from the server and a flag for each indicating + * whether they already exist in known_hosts. + * keys_seen is filled in by hostkeys_find() and later (for new + * keys) by client_global_hostkeys_private_confirm(). + */ + struct sshkey **keys; + int *keys_seen; + size_t nkeys; + + size_t nnew; + + /* + * Keys that are in known_hosts, but were not present in the update + * from the server (i.e. scheduled to be deleted). + * Filled in by hostkeys_find(). + */ + struct sshkey **old_keys; + size_t nold; +}; + static void +hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx) +{ + size_t i; + + if (ctx == NULL) + return; + for (i = 0; i < ctx->nkeys; i++) + sshkey_free(ctx->keys[i]); + free(ctx->keys); + free(ctx->keys_seen); + for (i = 0; i < ctx->nold; i++) + sshkey_free(ctx->old_keys[i]); + free(ctx->old_keys); + free(ctx->host_str); + free(ctx->ip_str); + free(ctx); +} + +static int +hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) +{ + struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; + size_t i; + struct sshkey **tmp; + + if (l->status != HKF_STATUS_MATCHED || l->key == NULL || + l->key->type == KEY_RSA1) + return 0; + + /* Mark off keys we've already seen for this host */ + for (i = 0; i < ctx->nkeys; i++) { + if (sshkey_equal(l->key, ctx->keys[i])) { + debug3("%s: found %s key at %s:%ld", __func__, + sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum); + ctx->keys_seen[i] = 1; + return 0; + } + } + /* This line contained a key that not offered by the server */ + debug3("%s: deprecated %s key at %s:%ld", __func__, + sshkey_ssh_name(l->key), l->path, l->linenum); + if ((tmp = reallocarray(ctx->old_keys, ctx->nold + 1, + sizeof(*ctx->old_keys))) == NULL) + fatal("%s: reallocarray failed nold = %zu", + __func__, ctx->nold); + ctx->old_keys = tmp; + ctx->old_keys[ctx->nold++] = l->key; + l->key = NULL; + + return 0; +} + +static void +update_known_hosts(struct hostkeys_update_ctx *ctx) +{ + int r, was_raw = 0; + int loglevel = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK ? + SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE; + char *fp, *response; + size_t i; + + for (i = 0; i < ctx->nkeys; i++) { + if (ctx->keys_seen[i] != 2) + continue; + if ((fp = sshkey_fingerprint(ctx->keys[i], + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint failed", __func__); + do_log2(loglevel, "Learned new hostkey: %s %s", + sshkey_type(ctx->keys[i]), fp); + free(fp); + } + for (i = 0; i < ctx->nold; i++) { + if ((fp = sshkey_fingerprint(ctx->old_keys[i], + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint failed", __func__); + do_log2(loglevel, "Deprecating obsolete hostkey: %s %s", + sshkey_type(ctx->old_keys[i]), fp); + free(fp); + } + if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { + if (get_saved_tio() != NULL) { + leave_raw_mode(1); + was_raw = 1; + } + response = NULL; + for (i = 0; !quit_pending && i < 3; i++) { + free(response); + response = read_passphrase("Accept updated hostkeys? " + "(yes/no): ", RP_ECHO); + if (strcasecmp(response, "yes") == 0) + break; + else if (quit_pending || response == NULL || + strcasecmp(response, "no") == 0) { + options.update_hostkeys = 0; + break; + } else { + do_log2(loglevel, "Please enter " + "\"yes\" or \"no\""); + } + } + if (quit_pending || i >= 3 || response == NULL) + options.update_hostkeys = 0; + free(response); + if (was_raw) + enter_raw_mode(1); + } + + /* + * Now that all the keys are verified, we can go ahead and replace + * them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't + * cancel the operation). + */ + if (options.update_hostkeys != 0 && + (r = hostfile_replace_entries(options.user_hostfiles[0], + ctx->host_str, ctx->ip_str, ctx->keys, ctx->nkeys, + options.hash_known_hosts, 0, + options.fingerprint_hash)) != 0) + error("%s: hostfile_replace_entries failed: %s", + __func__, ssh_err(r)); +} + +static void +client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx) +{ + struct ssh *ssh = active_state; /* XXX */ + struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; + size_t i, ndone; + struct sshbuf *signdata; + int r; + const u_char *sig; + size_t siglen; + + if (ctx->nnew == 0) + fatal("%s: ctx->nnew == 0", __func__); /* sanity */ + if (type != SSH2_MSG_REQUEST_SUCCESS) { + error("Server failed to confirm ownership of " + "private host keys"); + hostkeys_update_ctx_free(ctx); + return; + } + if ((signdata = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + /* Don't want to accidentally accept an unbound signature */ + if (ssh->kex->session_id_len == 0) + fatal("%s: ssh->kex->session_id_len == 0", __func__); + /* + * Expect a signature for each of the ctx->nnew private keys we + * haven't seen before. They will be in the same order as the + * ctx->keys where the corresponding ctx->keys_seen[i] == 0. + */ + for (ndone = i = 0; i < ctx->nkeys; i++) { + if (ctx->keys_seen[i]) + continue; + /* Prepare data to be signed: session ID, unique string, key */ + sshbuf_reset(signdata); + if ( (r = sshbuf_put_cstring(signdata, + "hostkeys-prove-00@openssh.com")) != 0 || + (r = sshbuf_put_string(signdata, ssh->kex->session_id, + ssh->kex->session_id_len)) != 0 || + (r = sshkey_puts(ctx->keys[i], signdata)) != 0) + fatal("%s: failed to prepare signature: %s", + __func__, ssh_err(r)); + /* Extract and verify signature */ + if ((r = sshpkt_get_string_direct(ssh, &sig, &siglen)) != 0) { + error("%s: couldn't parse message: %s", + __func__, ssh_err(r)); + goto out; + } + if ((r = sshkey_verify(ctx->keys[i], sig, siglen, + sshbuf_ptr(signdata), sshbuf_len(signdata), 0)) != 0) { + error("%s: server gave bad signature for %s key %zu", + __func__, sshkey_type(ctx->keys[i]), i); + goto out; + } + /* Key is good. Mark it as 'seen' */ + ctx->keys_seen[i] = 2; + ndone++; + } + if (ndone != ctx->nnew) + fatal("%s: ndone != ctx->nnew (%zu / %zu)", __func__, + ndone, ctx->nnew); /* Shouldn't happen */ + ssh_packet_check_eom(ssh); + + /* Make the edits to known_hosts */ + update_known_hosts(ctx); + out: + hostkeys_update_ctx_free(ctx); +} + +/* + * Handle hostkeys-00@openssh.com global request to inform the client of all + * the server's hostkeys. The keys are checked against the user's + * HostkeyAlgorithms preference before they are accepted. + */ +static int +client_input_hostkeys(void) +{ + struct ssh *ssh = active_state; /* XXX */ + const u_char *blob = NULL; + size_t i, len = 0; + struct sshbuf *buf = NULL; + struct sshkey *key = NULL, **tmp; + int r; + char *fp; + static int hostkeys_seen = 0; /* XXX use struct ssh */ + extern struct sockaddr_storage hostaddr; /* XXX from ssh.c */ + struct hostkeys_update_ctx *ctx = NULL; + + if (hostkeys_seen) + fatal("%s: server already sent hostkeys", __func__); + if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK && + options.batch_mode) + return 1; /* won't ask in batchmode, so don't even try */ + if (!options.update_hostkeys || options.num_user_hostfiles <= 0) + return 1; + + ctx = xcalloc(1, sizeof(*ctx)); + while (ssh_packet_remaining(ssh) > 0) { + sshkey_free(key); + key = NULL; + if ((r = sshpkt_get_string_direct(ssh, &blob, &len)) != 0) { + error("%s: couldn't parse message: %s", + __func__, ssh_err(r)); + goto out; + } + if ((r = sshkey_from_blob(blob, len, &key)) != 0) { + error("%s: parse key: %s", __func__, ssh_err(r)); + goto out; + } + fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT); + debug3("%s: received %s key %s", __func__, + sshkey_type(key), fp); + free(fp); + + /* Check that the key is accepted in HostkeyAlgorithms */ + if (match_pattern_list(sshkey_ssh_name(key), + options.hostkeyalgorithms ? options.hostkeyalgorithms : + KEX_DEFAULT_PK_ALG, 0) != 1) { + debug3("%s: %s key not permitted by HostkeyAlgorithms", + __func__, sshkey_ssh_name(key)); + continue; + } + /* Skip certs */ + if (sshkey_is_cert(key)) { + debug3("%s: %s key is a certificate; skipping", + __func__, sshkey_ssh_name(key)); + continue; + } + /* Ensure keys are unique */ + for (i = 0; i < ctx->nkeys; i++) { + if (sshkey_equal(key, ctx->keys[i])) { + error("%s: received duplicated %s host key", + __func__, sshkey_ssh_name(key)); + goto out; + } + } + /* Key is good, record it */ + if ((tmp = reallocarray(ctx->keys, ctx->nkeys + 1, + sizeof(*ctx->keys))) == NULL) + fatal("%s: reallocarray failed nkeys = %zu", + __func__, ctx->nkeys); + ctx->keys = tmp; + ctx->keys[ctx->nkeys++] = key; + key = NULL; + } + + if (ctx->nkeys == 0) { + debug("%s: server sent no hostkeys", __func__); + goto out; + } + + if ((ctx->keys_seen = calloc(ctx->nkeys, + sizeof(*ctx->keys_seen))) == NULL) + fatal("%s: calloc failed", __func__); + + get_hostfile_hostname_ipaddr(host, + options.check_host_ip ? (struct sockaddr *)&hostaddr : NULL, + options.port, &ctx->host_str, + options.check_host_ip ? &ctx->ip_str : NULL); + + /* Find which keys we already know about. */ + if ((r = hostkeys_foreach(options.user_hostfiles[0], hostkeys_find, + ctx, ctx->host_str, ctx->ip_str, + HKF_WANT_PARSE_KEY|HKF_WANT_MATCH)) != 0) { + error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r)); + goto out; + } + + /* Figure out if we have any new keys to add */ + ctx->nnew = 0; + for (i = 0; i < ctx->nkeys; i++) { + if (!ctx->keys_seen[i]) + ctx->nnew++; + } + + debug3("%s: %zu keys from server: %zu new, %zu retained. %zu to remove", + __func__, ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold); + + if (ctx->nnew == 0 && ctx->nold != 0) { + /* We have some keys to remove. Just do it. */ + update_known_hosts(ctx); + } else if (ctx->nnew != 0) { + /* + * We have received hitherto-unseen keys from the server. + * Ask the server to confirm ownership of the private halves. + */ + debug3("%s: asking server to prove ownership for %zu keys", + __func__, ctx->nnew); + if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || + (r = sshpkt_put_cstring(ssh, + "hostkeys-prove-00@openssh.com")) != 0 || + (r = sshpkt_put_u8(ssh, 1)) != 0) /* bool: want reply */ + fatal("%s: cannot prepare packet: %s", + __func__, ssh_err(r)); + if ((buf = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + for (i = 0; i < ctx->nkeys; i++) { + if (ctx->keys_seen[i]) + continue; + sshbuf_reset(buf); + if ((r = sshkey_putb(ctx->keys[i], buf)) != 0) + fatal("%s: sshkey_putb: %s", + __func__, ssh_err(r)); + if ((r = sshpkt_put_stringb(ssh, buf)) != 0) + fatal("%s: sshpkt_put_string: %s", + __func__, ssh_err(r)); + } + if ((r = sshpkt_send(ssh)) != 0) + fatal("%s: sshpkt_send: %s", __func__, ssh_err(r)); + client_register_global_confirm( + client_global_hostkeys_private_confirm, ctx); + ctx = NULL; /* will be freed in callback */ + } + + /* Success */ + out: + hostkeys_update_ctx_free(ctx); + sshkey_free(key); + sshbuf_free(buf); + /* + * NB. Return success for all cases. The server doesn't need to know + * what the client does with its hosts file. + */ + return 1; +} + +static int client_input_global_request(int type, u_int32_t seq, void *ctxt) { char *rtype; int want_reply; int success = 0; - rtype = packet_get_string(NULL); + rtype = packet_get_cstring(NULL); want_reply = packet_get_char(); debug("client_input_global_request: rtype %s want_reply %d", rtype, want_reply); + if (strcmp(rtype, "hostkeys-00@openssh.com") == 0) + success = client_input_hostkeys(); if (want_reply) { packet_start(success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); @@ -2080,6 +2496,7 @@ client_input_global_request(int type, u_int32_t seq, void *ctxt) packet_write_wait(); } free(rtype); + return 0; } void diff --git a/crypto/openssh/compat.c b/crypto/openssh/compat.c index 2709dc5..5583804 100644 --- a/crypto/openssh/compat.c +++ b/crypto/openssh/compat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.c,v 1.82 2013/12/30 23:52:27 djm Exp $ */ +/* $OpenBSD: compat.c,v 1.97 2015/08/19 23:21:42 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -57,7 +57,7 @@ enable_compat13(void) compat13 = 1; } /* datafellows bug compatibility */ -void +u_int compat_datafellows(const char *version) { int i; @@ -152,6 +152,8 @@ compat_datafellows(const char *version) "1.2.22*", SSH_BUG_IGNOREMSG }, { "1.3.2*", /* F-Secure */ SSH_BUG_IGNOREMSG }, + { "Cisco-1.*", SSH_BUG_DHGEX_LARGE| + SSH_BUG_HOSTKEYS }, { "*SSH Compatible Server*", /* Netscreen */ SSH_BUG_PASSWORDPAD }, { "*OSU_0*," @@ -165,22 +167,54 @@ compat_datafellows(const char *version) "OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD }, { "*SSH_Version_Mapper*", SSH_BUG_SCANNER }, + { "PuTTY_Local:*," /* dev versions < Sep 2014 */ + "PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */ + "PuTTY_Release_0.5*," /* 0.58-0.59 */ + "PuTTY_Release_0.60*," + "PuTTY_Release_0.61*," + "PuTTY_Release_0.62*," + "PuTTY_Release_0.63*," + "PuTTY_Release_0.64*", + SSH_OLD_DHGEX }, + { "FuTTY*", SSH_OLD_DHGEX }, /* Putty Fork */ { "Probe-*", SSH_BUG_PROBE }, + { "TeraTerm SSH*," + "TTSSH/1.5.*," + "TTSSH/2.1*," + "TTSSH/2.2*," + "TTSSH/2.3*," + "TTSSH/2.4*," + "TTSSH/2.5*," + "TTSSH/2.6*," + "TTSSH/2.70*," + "TTSSH/2.71*," + "TTSSH/2.72*", SSH_BUG_HOSTKEYS }, + { "WinSCP_release_4*," + "WinSCP_release_5.0*," + "WinSCP_release_5.1*," + "WinSCP_release_5.5*," + "WinSCP_release_5.6*," + "WinSCP_release_5.7," + "WinSCP_release_5.7.1," + "WinSCP_release_5.7.2," + "WinSCP_release_5.7.3," + "WinSCP_release_5.7.4", + SSH_OLD_DHGEX }, { NULL, 0 } }; /* process table, return first match */ for (i = 0; check[i].pat; i++) { - if (match_pattern_list(version, check[i].pat, - strlen(check[i].pat), 0) == 1) { - datafellows = check[i].bugs; + if (match_pattern_list(version, check[i].pat, 0) == 1) { debug("match: %s pat %s compat 0x%08x", - version, check[i].pat, datafellows); - return; + version, check[i].pat, check[i].bugs); + datafellows = check[i].bugs; /* XXX for now */ + return check[i].bugs; } } debug("no match: %s", version); + return 0; } #define SEP "," @@ -192,13 +226,17 @@ proto_spec(const char *spec) if (spec == NULL) return ret; - q = s = xstrdup(spec); + q = s = strdup(spec); + if (s == NULL) + return ret; for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { switch (atoi(p)) { case 1: +#ifdef WITH_SSH1 if (ret == SSH_PROTO_UNKNOWN) ret |= SSH_PROTO_1_PREFERRED; ret |= SSH_PROTO_1; +#endif break; case 2: ret |= SSH_PROTO_2; @@ -226,7 +264,7 @@ filter_proposal(char *proposal, const char *filter) buffer_init(&b); tmp = orig_prop = xstrdup(proposal); while ((cp = strsep(&tmp, ",")) != NULL) { - if (match_pattern_list(cp, filter, strlen(cp), 0) != 1) { + if (match_pattern_list(cp, filter, 0) != 1) { if (buffer_len(&b) > 0) buffer_append(&b, ",", 1); buffer_append(&b, cp, strlen(cp)); @@ -234,7 +272,7 @@ filter_proposal(char *proposal, const char *filter) debug2("Compat: skipping algorithm \"%s\"", cp); } buffer_append(&b, "\0", 1); - fix_prop = xstrdup(buffer_ptr(&b)); + fix_prop = xstrdup((char *)buffer_ptr(&b)); buffer_free(&b); free(orig_prop); @@ -268,15 +306,20 @@ compat_pkalg_proposal(char *pkalg_prop) } char * -compat_kex_proposal(char *kex_prop) +compat_kex_proposal(char *p) { - if (!(datafellows & SSH_BUG_CURVE25519PAD)) - return kex_prop; - debug2("%s: original KEX proposal: %s", __func__, kex_prop); - kex_prop = filter_proposal(kex_prop, "curve25519-sha256@libssh.org"); - debug2("%s: compat KEX proposal: %s", __func__, kex_prop); - if (*kex_prop == '\0') + if ((datafellows & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) + return p; + debug2("%s: original KEX proposal: %s", __func__, p); + if ((datafellows & SSH_BUG_CURVE25519PAD) != 0) + p = filter_proposal(p, "curve25519-sha256@libssh.org"); + if ((datafellows & SSH_OLD_DHGEX) != 0) { + p = filter_proposal(p, "diffie-hellman-group-exchange-sha256"); + p = filter_proposal(p, "diffie-hellman-group-exchange-sha1"); + } + debug2("%s: compat KEX proposal: %s", __func__, p); + if (*p == '\0') fatal("No supported key exchange algorithms found"); - return kex_prop; + return p; } diff --git a/crypto/openssh/compat.h b/crypto/openssh/compat.h index a6c3f3d..2be290a 100644 --- a/crypto/openssh/compat.h +++ b/crypto/openssh/compat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.h,v 1.44 2013/12/30 23:52:27 djm Exp $ */ +/* $OpenBSD: compat.h,v 1.48 2015/05/26 23:23:40 dtucker Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. @@ -60,10 +60,12 @@ #define SSH_NEW_OPENSSH 0x04000000 #define SSH_BUG_DYNAMIC_RPORT 0x08000000 #define SSH_BUG_CURVE25519PAD 0x10000000 +#define SSH_BUG_HOSTKEYS 0x20000000 +#define SSH_BUG_DHGEX_LARGE 0x40000000 void enable_compat13(void); void enable_compat20(void); -void compat_datafellows(const char *); +u_int compat_datafellows(const char *); int proto_spec(const char *); char *compat_cipher_proposal(char *); char *compat_pkalg_proposal(char *); diff --git a/crypto/openssh/compress.c b/crypto/openssh/compress.c deleted file mode 100644 index 24778e5..0000000 --- a/crypto/openssh/compress.c +++ /dev/null @@ -1,167 +0,0 @@ -/* $OpenBSD: compress.c,v 1.26 2010/09/08 04:13:31 deraadt Exp $ */ -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Interface to packet compression for ssh. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" - -#include - -#include - -#include "log.h" -#include "buffer.h" -#include "compress.h" - -#include - -z_stream incoming_stream; -z_stream outgoing_stream; -static int compress_init_send_called = 0; -static int compress_init_recv_called = 0; -static int inflate_failed = 0; -static int deflate_failed = 0; - -/* - * Initializes compression; level is compression level from 1 to 9 - * (as in gzip). - */ - -void -buffer_compress_init_send(int level) -{ - if (compress_init_send_called == 1) - deflateEnd(&outgoing_stream); - compress_init_send_called = 1; - debug("Enabling compression at level %d.", level); - if (level < 1 || level > 9) - fatal("Bad compression level %d.", level); - deflateInit(&outgoing_stream, level); -} -void -buffer_compress_init_recv(void) -{ - if (compress_init_recv_called == 1) - inflateEnd(&incoming_stream); - compress_init_recv_called = 1; - inflateInit(&incoming_stream); -} - -/* Frees any data structures allocated for compression. */ - -void -buffer_compress_uninit(void) -{ - debug("compress outgoing: raw data %llu, compressed %llu, factor %.2f", - (unsigned long long)outgoing_stream.total_in, - (unsigned long long)outgoing_stream.total_out, - outgoing_stream.total_in == 0 ? 0.0 : - (double) outgoing_stream.total_out / outgoing_stream.total_in); - debug("compress incoming: raw data %llu, compressed %llu, factor %.2f", - (unsigned long long)incoming_stream.total_out, - (unsigned long long)incoming_stream.total_in, - incoming_stream.total_out == 0 ? 0.0 : - (double) incoming_stream.total_in / incoming_stream.total_out); - if (compress_init_recv_called == 1 && inflate_failed == 0) - inflateEnd(&incoming_stream); - if (compress_init_send_called == 1 && deflate_failed == 0) - deflateEnd(&outgoing_stream); -} - -/* - * Compresses the contents of input_buffer into output_buffer. All packets - * compressed using this function will form a single compressed data stream; - * however, data will be flushed at the end of every call so that each - * output_buffer can be decompressed independently (but in the appropriate - * order since they together form a single compression stream) by the - * receiver. This appends the compressed data to the output buffer. - */ - -void -buffer_compress(Buffer * input_buffer, Buffer * output_buffer) -{ - u_char buf[4096]; - int status; - - /* This case is not handled below. */ - if (buffer_len(input_buffer) == 0) - return; - - /* Input is the contents of the input buffer. */ - outgoing_stream.next_in = buffer_ptr(input_buffer); - outgoing_stream.avail_in = buffer_len(input_buffer); - - /* Loop compressing until deflate() returns with avail_out != 0. */ - do { - /* Set up fixed-size output buffer. */ - outgoing_stream.next_out = buf; - outgoing_stream.avail_out = sizeof(buf); - - /* Compress as much data into the buffer as possible. */ - status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH); - switch (status) { - case Z_OK: - /* Append compressed data to output_buffer. */ - buffer_append(output_buffer, buf, - sizeof(buf) - outgoing_stream.avail_out); - break; - default: - deflate_failed = 1; - fatal("buffer_compress: deflate returned %d", status); - /* NOTREACHED */ - } - } while (outgoing_stream.avail_out == 0); -} - -/* - * Uncompresses the contents of input_buffer into output_buffer. All packets - * uncompressed using this function will form a single compressed data - * stream; however, data will be flushed at the end of every call so that - * each output_buffer. This must be called for the same size units that the - * buffer_compress was called, and in the same order that buffers compressed - * with that. This appends the uncompressed data to the output buffer. - */ - -void -buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer) -{ - u_char buf[4096]; - int status; - - incoming_stream.next_in = buffer_ptr(input_buffer); - incoming_stream.avail_in = buffer_len(input_buffer); - - for (;;) { - /* Set up fixed-size output buffer. */ - incoming_stream.next_out = buf; - incoming_stream.avail_out = sizeof(buf); - - status = inflate(&incoming_stream, Z_PARTIAL_FLUSH); - switch (status) { - case Z_OK: - buffer_append(output_buffer, buf, - sizeof(buf) - incoming_stream.avail_out); - break; - case Z_BUF_ERROR: - /* - * Comments in zlib.h say that we should keep calling - * inflate() until we get an error. This appears to - * be the error that we get. - */ - return; - default: - inflate_failed = 1; - fatal("buffer_uncompress: inflate returned %d", status); - /* NOTREACHED */ - } - } -} diff --git a/crypto/openssh/compress.h b/crypto/openssh/compress.h deleted file mode 100644 index 418d6fd..0000000 --- a/crypto/openssh/compress.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $OpenBSD: compress.h,v 1.12 2006/03/25 22:22:43 djm Exp $ */ - -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Interface to packet compression for ssh. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#ifndef COMPRESS_H -#define COMPRESS_H - -void buffer_compress_init_send(int); -void buffer_compress_init_recv(void); -void buffer_compress_uninit(void); -void buffer_compress(Buffer *, Buffer *); -void buffer_uncompress(Buffer *, Buffer *); - -#endif /* COMPRESS_H */ diff --git a/crypto/openssh/config.guess b/crypto/openssh/config.guess index b94cde8..c563628 100755 --- a/crypto/openssh/config.guess +++ b/crypto/openssh/config.guess @@ -982,6 +982,12 @@ EOF ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-gnu + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-gnu + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; diff --git a/crypto/openssh/config.h b/crypto/openssh/config.h index 77c8e18..f7ac9a4 100644 --- a/crypto/openssh/config.h +++ b/crypto/openssh/config.h @@ -52,8 +52,8 @@ against it */ /* #undef BROKEN_READ_COMPARISON */ -/* Define if you have a broken realpath. */ -/* #undef BROKEN_REALPATH */ +/* realpath does not work with nonexistent files */ +#define BROKEN_REALPATH 1 /* Needed for NeXT */ /* #undef BROKEN_SAVED_UIDS */ @@ -292,6 +292,10 @@ /* Define if your libraries define daemon() */ #define HAVE_DAEMON 1 +/* Define to 1 if you have the declaration of `AI_NUMERICSERV', and to 0 if + you don't. */ +#define HAVE_DECL_AI_NUMERICSERV 1 + /* Define to 1 if you have the declaration of `authenticate', and to 0 if you don't. */ /* #undef HAVE_DECL_AUTHENTICATE */ @@ -421,6 +425,9 @@ /* Define to 1 if you have the `EVP_MD_CTX_init' function. */ #define HAVE_EVP_MD_CTX_INIT 1 +/* Define to 1 if you have the `EVP_ripemd160' function. */ +#define HAVE_EVP_RIPEMD160 1 + /* Define to 1 if you have the `EVP_sha256' function. */ #define HAVE_EVP_SHA256 1 @@ -769,6 +776,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 +/* Define to 1 if you have the `memset_s' function. */ +/* #undef HAVE_MEMSET_S */ + /* Define to 1 if you have the `mkdtemp' function. */ #define HAVE_MKDTEMP 1 @@ -869,6 +879,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_READPASSPHRASE_H 1 +/* Define to 1 if you have the `reallocarray' function. */ +/* #undef HAVE_REALLOCARRAY */ + /* Define to 1 if you have the `realpath' function. */ #define HAVE_REALPATH 1 @@ -1139,8 +1152,8 @@ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_BSDTTY_H */ -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_CAPABILITY_H 1 +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_CAPSICUM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_CDEFS_H 1 @@ -1325,9 +1338,6 @@ /* Define if va_copy exists */ #define HAVE_VA_COPY 1 -/* Define to 1 if you have the `vhangup' function. */ -/* #undef HAVE_VHANGUP */ - /* Define to 1 if you have the header file. */ #define HAVE_VIS_H 1 @@ -1468,7 +1478,7 @@ /* libcrypto is missing AES 192 and 256 bit functions */ /* #undef OPENSSL_LOBOTOMISED_AES */ -/* Define if you want OpenSSL's internally seeded PRNG only */ +/* Define if you want the OpenSSL internally seeded PRNG only */ #define OPENSSL_PRNG_ONLY 1 /* Define to the address where bug reports for this package should be sent. */ @@ -1663,9 +1673,15 @@ /* Define if you want IRIX project management */ /* #undef WITH_IRIX_PROJECT */ +/* use libcrypto for cryptography */ +#define WITH_OPENSSL 1 + /* Define if you want SELinux support. */ /* #undef WITH_SELINUX */ +/* include SSH protocol version 1 support */ +#define WITH_SSH1 1 + /* 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 diff --git a/crypto/openssh/configure.ac b/crypto/openssh/configure.ac index aeec10f..ddc9a8a 100644 --- a/crypto/openssh/configure.ac +++ b/crypto/openssh/configure.ac @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.571 2014/02/21 17:09:34 tim Exp $ +# $Id: configure.ac,v 1.583 2014/08/26 20:32:01 djm Exp $ # $FreeBSD$ # # Copyright (c) 1999-2004 Damien Miller @@ -16,7 +16,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) -AC_REVISION($Revision: 1.571 $) +AC_REVISION($Revision: 1.583 $) AC_CONFIG_SRCDIR([ssh.c]) AC_LANG([C]) @@ -31,7 +31,7 @@ AC_PROG_CPP AC_PROG_RANLIB AC_PROG_INSTALL AC_PROG_EGREP -AC_PATH_PROG([AR], [ar]) +AC_CHECK_TOOLS([AR], [ar]) AC_PATH_PROG([CAT], [cat]) AC_PATH_PROG([KILL], [kill]) AC_PATH_PROGS([PERL], [perl5 perl]) @@ -122,6 +122,47 @@ AC_CHECK_DECL([PR_SET_NO_NEW_PRIVS], [have_linux_no_new_privs=1], , [ #include ]) +openssl=yes +ssh1=yes +AC_ARG_WITH([openssl], + [ --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ], + [ if test "x$withval" = "xno" ; then + openssl=no + ssh1=no + fi + ] +) +AC_MSG_CHECKING([whether OpenSSL will be used for cryptography]) +if test "x$openssl" = "xyes" ; then + AC_MSG_RESULT([yes]) + AC_DEFINE_UNQUOTED([WITH_OPENSSL], [1], [use libcrypto for cryptography]) +else + AC_MSG_RESULT([no]) +fi + +AC_ARG_WITH([ssh1], + [ --without-ssh1 Enable support for SSH protocol 1], + [ + if test "x$withval" = "xyes" ; then + if test "x$openssl" = "xno" ; then + AC_MSG_ERROR([Cannot enable SSH protocol 1 with OpenSSL disabled]) + fi + ssh1=yes + elif test "x$withval" = "xno" ; then + ssh1=no + else + AC_MSG_ERROR([unknown --with-ssh1 argument]) + fi + ] +) +AC_MSG_CHECKING([whether SSH protocol 1 support is enabled]) +if test "x$ssh1" = "xyes" ; then + AC_MSG_RESULT([yes]) + AC_DEFINE_UNQUOTED([WITH_SSH1], [1], [include SSH protocol version 1 support]) +else + AC_MSG_RESULT([no]) +fi + use_stack_protector=1 use_toolchain_hardening=1 AC_ARG_WITH([stackprotect], @@ -365,7 +406,6 @@ AC_CHECK_HEADERS([ \ sys/audit.h \ sys/bitypes.h \ sys/bsdtty.h \ - sys/capability.h \ sys/cdefs.h \ sys/dir.h \ sys/mman.h \ @@ -395,6 +435,13 @@ AC_CHECK_HEADERS([ \ vis.h \ ]) +# sys/capsicum.h requires sys/types.h +AC_CHECK_HEADERS([sys/capsicum.h], [], [], [ +#ifdef HAVE_SYS_TYPES_H +# include +#endif +]) + # lastlog.h requires sys/time.h to be included first on Solaris AC_CHECK_HEADERS([lastlog.h], [], [], [ #ifdef HAVE_SYS_TIME_H @@ -741,14 +788,17 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) i*86-*) seccomp_audit_arch=AUDIT_ARCH_I386 ;; - arm*-*) + arm*-*) seccomp_audit_arch=AUDIT_ARCH_ARM - ;; + ;; + aarch64*-*) + seccomp_audit_arch=AUDIT_ARCH_AARCH64 + ;; esac if test "x$seccomp_audit_arch" != "x" ; then AC_MSG_RESULT(["$seccomp_audit_arch"]) - AC_DEFINE_UNQUOTED([SECCOMP_AUDIT_ARCH], [$seccomp_audit_arch], - [Specify the system call convention in use]) + AC_DEFINE_UNQUOTED([SECCOMP_AUDIT_ARCH], [$seccomp_audit_arch], + [Specify the system call convention in use]) else AC_MSG_RESULT([architecture not supported]) fi @@ -1297,7 +1347,7 @@ g.gl_statv = NULL; AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) - + ]) AC_CHECK_DECLS([GLOB_NOMATCH], , , [#include ]) @@ -1580,7 +1630,7 @@ AC_ARG_WITH([audit], ) AC_ARG_WITH([pie], - [ --with-pie Build Position Independent Executables if possible], [ + [ --with-pie Build Position Independent Executables if possible], [ if test "x$withval" = "xno"; then use_pie=no fi @@ -1632,10 +1682,6 @@ AC_CHECK_FUNCS([ \ Blowfish_expandstate \ Blowfish_expand0state \ Blowfish_stream2word \ - arc4random \ - arc4random_buf \ - arc4random_stir \ - arc4random_uniform \ asprintf \ b64_ntop \ __b64_ntop \ @@ -1679,6 +1725,7 @@ AC_CHECK_FUNCS([ \ mblen \ md5_crypt \ memmove \ + memset_s \ mkdtemp \ mmap \ ngetaddrinfo \ @@ -1689,7 +1736,7 @@ AC_CHECK_FUNCS([ \ prctl \ pstat \ readpassphrase \ - realpath \ + reallocarray \ recvmsg \ rresvport_af \ sendmsg \ @@ -1737,7 +1784,6 @@ AC_CHECK_FUNCS([ \ user_from_uid \ usleep \ vasprintf \ - vhangup \ vsnprintf \ waitpid \ ]) @@ -1749,10 +1795,13 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) -# PKCS#11 support requires dlopen() and co -AC_SEARCH_LIBS([dlopen], [dl], - [AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support])] -) +# PKCS11 depends on OpenSSL. +if test "x$openssl" = "xyes" ; then + # PKCS#11 support requires dlopen() and co + AC_SEARCH_LIBS([dlopen], [dl], + [AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support])] + ) +fi # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ @@ -1904,6 +1953,32 @@ AC_CHECK_FUNCS([setresgid], [ ) ]) +AC_CHECK_FUNCS([realpath], [ + dnl the sftp v3 spec says SSH_FXP_REALPATH will "canonicalize any given + dnl path name", however some implementations of realpath (and some + dnl versions of the POSIX spec) do not work on non-existent files, + dnl so we use the OpenBSD implementation on those platforms. + AC_MSG_CHECKING([if realpath works with non-existent files]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ + char buf[PATH_MAX]; + if (realpath("/opensshnonexistentfilename1234", buf) == NULL) + if (errno == ENOENT) + exit(1); + exit(0); + ]])], + [AC_MSG_RESULT([yes])], + [AC_DEFINE([BROKEN_REALPATH], [1], + [realpath does not work with nonexistent files]) + AC_MSG_RESULT([no])], + [AC_MSG_WARN([cross compiling: assuming working])] + ) +]) + dnl Checks for time functions AC_CHECK_FUNCS([gettimeofday time]) dnl Checks for utmp functions @@ -1949,11 +2024,9 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then ) fi -# If we don't have a working asprintf, then we strongly depend on vsnprintf -# returning the right thing on overflow: the number of characters it tried to -# create (as per SUSv3) -if test "x$ac_cv_func_asprintf" != "xyes" && \ - test "x$ac_cv_func_vsnprintf" = "xyes" ; then +# We depend on vsnprintf returning the right thing on overflow: the +# number of characters it tried to create (as per SUSv3) +if test "x$ac_cv_func_vsnprintf" = "xyes" ; then AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ @@ -1961,15 +2034,23 @@ if test "x$ac_cv_func_asprintf" != "xyes" && \ #include #include -int x_snprintf(char *str,size_t count,const char *fmt,...) +int x_snprintf(char *str, size_t count, const char *fmt, ...) { - size_t ret; va_list ap; - va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); return ret; } ]], [[ - char x[1]; - exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1); +char x[1]; +if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) + return 1; +if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) + return 1; +return 0; ]])], [AC_MSG_RESULT([yes])], [ @@ -2212,6 +2293,13 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ ) fi +if test "x$ac_cv_func_getaddrinfo" = "xyes"; then + AC_CHECK_DECLS(AI_NUMERICSERV, , , + [#include + #include + #include ]) +fi + if test "x$check_for_conflicting_getspnam" = "x1"; then AC_MSG_CHECKING([for conflicting getspnam in shadow.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], @@ -2235,6 +2323,9 @@ saved_LDFLAGS="$LDFLAGS" AC_ARG_WITH([ssl-dir], [ --with-ssl-dir=PATH Specify path to OpenSSL installation ], [ + if test "x$openssl" = "xno" ; then + AC_MSG_ERROR([cannot use --with-ssl-dir when OpenSSL disabled]) + fi if test "x$withval" != "xno" ; then case "$withval" in # Relative paths @@ -2267,424 +2358,464 @@ AC_ARG_WITH([ssl-dir], fi ] ) -LIBS="-lcrypto $LIBS" -AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1], - [Define if your ssl headers are included - with #include ])], + +AC_ARG_WITH([openssl-header-check], + [ --without-openssl-header-check Disable OpenSSL version consistency check], [ - dnl Check default openssl install dir - if test -n "${need_dash_r}"; then - LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}" - else - LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}" + if test "x$withval" = "xno" ; then + openssl_check_nonfatal=1 fi - CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}" - AC_CHECK_HEADER([openssl/opensslv.h], , - [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])]) - AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL])], - [ - AC_MSG_ERROR([*** Can't find recent OpenSSL libcrypto (see config.log for details) ***]) - ] - ) ] ) -# Determine OpenSSL header version -AC_MSG_CHECKING([OpenSSL header version]) -AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include -#include -#define DATA "conftest.sslincver" - ]], [[ - FILE *fd; - int rc; - - fd = fopen(DATA,"w"); - if(fd == NULL) - exit(1); - - if ((rc = fprintf(fd ,"%x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0) - exit(1); - - exit(0); - ]])], - [ - ssl_header_ver=`cat conftest.sslincver` - AC_MSG_RESULT([$ssl_header_ver]) - ], - [ - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([OpenSSL version header not found.]) - ], +openssl_engine=no +AC_ARG_WITH([ssl-engine], + [ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support ], [ - AC_MSG_WARN([cross compiling: not checking]) + if test "x$openssl" = "xno" ; then + AC_MSG_ERROR([cannot use --with-ssl-engine when OpenSSL disabled]) + fi + if test "x$withval" != "xno" ; then + openssl_engine=yes + fi ] ) -# Determine OpenSSL library version -AC_MSG_CHECKING([OpenSSL library version]) -AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include -#include -#include -#define DATA "conftest.ssllibver" - ]], [[ - FILE *fd; - int rc; +if test "x$openssl" = "xyes" ; then + LIBS="-lcrypto $LIBS" + AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1], + [Define if your ssl headers are included + with #include ])], + [ + dnl Check default openssl install dir + if test -n "${need_dash_r}"; then + LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}" + else + LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}" + fi + CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}" + AC_CHECK_HEADER([openssl/opensslv.h], , + [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])]) + AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL])], + [ + AC_MSG_ERROR([*** Can't find recent OpenSSL libcrypto (see config.log for details) ***]) + ] + ) + ] + ) - fd = fopen(DATA,"w"); - if(fd == NULL) - exit(1); + # Determine OpenSSL header version + AC_MSG_CHECKING([OpenSSL header version]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + #include + #define DATA "conftest.sslincver" + ]], [[ + FILE *fd; + int rc; - if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0) - exit(1); + fd = fopen(DATA,"w"); + if(fd == NULL) + exit(1); - exit(0); - ]])], - [ - ssl_library_ver=`cat conftest.ssllibver` - AC_MSG_RESULT([$ssl_library_ver]) - ], - [ - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([OpenSSL library not found.]) - ], - [ - AC_MSG_WARN([cross compiling: not checking]) - ] -) + if ((rc = fprintf(fd ,"%08x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0) + exit(1); -AC_ARG_WITH([openssl-header-check], - [ --without-openssl-header-check Disable OpenSSL version consistency check], - [ if test "x$withval" = "xno" ; then - openssl_check_nonfatal=1 - fi - ] -) + exit(0); + ]])], + [ + ssl_header_ver=`cat conftest.sslincver` + AC_MSG_RESULT([$ssl_header_ver]) + ], + [ + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([OpenSSL version header not found.]) + ], + [ + AC_MSG_WARN([cross compiling: not checking]) + ] + ) -# Sanity check OpenSSL headers -AC_MSG_CHECKING([whether OpenSSL's headers match the library]) -AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include - ]], [[ - exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1); - ]])], - [ - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - if test "x$openssl_check_nonfatal" = "x"; then - AC_MSG_ERROR([Your OpenSSL headers do not match your -library. Check config.log for details. -If you are sure your installation is consistent, you can disable the check -by running "./configure --without-openssl-header-check". -Also see contrib/findssl.sh for help identifying header/library mismatches. -]) - else - AC_MSG_WARN([Your OpenSSL headers do not match your -library. Check config.log for details. -Also see contrib/findssl.sh for help identifying header/library mismatches.]) - fi - ], - [ - AC_MSG_WARN([cross compiling: not checking]) - ] -) + # Determine OpenSSL library version + AC_MSG_CHECKING([OpenSSL library version]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + #include + #include + #define DATA "conftest.ssllibver" + ]], [[ + FILE *fd; + int rc; -AC_MSG_CHECKING([if programs using OpenSSL functions will link]) -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ #include ]], - [[ SSLeay_add_all_algorithms(); ]])], - [ - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - saved_LIBS="$LIBS" - LIBS="$LIBS -ldl" - AC_MSG_CHECKING([if programs using OpenSSL need -ldl]) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ #include ]], - [[ SSLeay_add_all_algorithms(); ]])], - [ - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - LIBS="$saved_LIBS" - ] - ) - ] -) + fd = fopen(DATA,"w"); + if(fd == NULL) + exit(1); -AC_CHECK_FUNCS([ \ - BN_is_prime_ex \ - DSA_generate_parameters_ex \ - EVP_DigestInit_ex \ - EVP_DigestFinal_ex \ - EVP_MD_CTX_init \ - EVP_MD_CTX_cleanup \ - EVP_MD_CTX_copy_ex \ - HMAC_CTX_init \ - RSA_generate_key_ex \ - RSA_get_default_method \ -]) + if ((rc = fprintf(fd ,"%08x (%s)\n", SSLeay(), + SSLeay_version(SSLEAY_VERSION))) <0) + exit(1); -AC_ARG_WITH([ssl-engine], - [ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support ], - [ if test "x$withval" != "xno" ; then + exit(0); + ]])], + [ + ssl_library_ver=`cat conftest.ssllibver` + # Check version is supported. + case "$ssl_library_ver" in + 0090[[0-7]]*|009080[[0-5]]*) + AC_MSG_ERROR([OpenSSL >= 0.9.8f required (have "$ssl_library_ver")]) + ;; + *) ;; + esac + AC_MSG_RESULT([$ssl_library_ver]) + ], + [ + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([OpenSSL library not found.]) + ], + [ + AC_MSG_WARN([cross compiling: not checking]) + ] + ) + + # Sanity check OpenSSL headers + AC_MSG_CHECKING([whether OpenSSL's headers match the library]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1); + ]])], + [ + AC_MSG_RESULT([yes]) + ], + [ + AC_MSG_RESULT([no]) + if test "x$openssl_check_nonfatal" = "x"; then + AC_MSG_ERROR([Your OpenSSL headers do not match your + library. Check config.log for details. + If you are sure your installation is consistent, you can disable the check + by running "./configure --without-openssl-header-check". + Also see contrib/findssl.sh for help identifying header/library mismatches. + ]) + else + AC_MSG_WARN([Your OpenSSL headers do not match your + library. Check config.log for details. + Also see contrib/findssl.sh for help identifying header/library mismatches.]) + fi + ], + [ + AC_MSG_WARN([cross compiling: not checking]) + ] + ) + + AC_MSG_CHECKING([if programs using OpenSSL functions will link]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ #include ]], + [[ SSLeay_add_all_algorithms(); ]])], + [ + AC_MSG_RESULT([yes]) + ], + [ + AC_MSG_RESULT([no]) + saved_LIBS="$LIBS" + LIBS="$LIBS -ldl" + AC_MSG_CHECKING([if programs using OpenSSL need -ldl]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ #include ]], + [[ SSLeay_add_all_algorithms(); ]])], + [ + AC_MSG_RESULT([yes]) + ], + [ + AC_MSG_RESULT([no]) + LIBS="$saved_LIBS" + ] + ) + ] + ) + + AC_CHECK_FUNCS([ \ + BN_is_prime_ex \ + DSA_generate_parameters_ex \ + EVP_DigestInit_ex \ + EVP_DigestFinal_ex \ + EVP_MD_CTX_init \ + EVP_MD_CTX_cleanup \ + EVP_MD_CTX_copy_ex \ + HMAC_CTX_init \ + RSA_generate_key_ex \ + RSA_get_default_method \ + ]) + + if test "x$openssl_engine" = "xyes" ; then AC_MSG_CHECKING([for OpenSSL ENGINE support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include + #include ]], [[ - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([USE_OPENSSL_ENGINE], [1], [Enable OpenSSL engine support]) ], [ AC_MSG_ERROR([OpenSSL ENGINE support not found]) ]) - fi ] -) + fi -# Check for OpenSSL without EVP_aes_{192,256}_cbc -AC_MSG_CHECKING([whether OpenSSL has crippled AES support]) -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include - ]], [[ - exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL); - ]])], - [ - AC_MSG_RESULT([no]) - ], - [ - AC_MSG_RESULT([yes]) - AC_DEFINE([OPENSSL_LOBOTOMISED_AES], [1], - [libcrypto is missing AES 192 and 256 bit functions]) - ] -) + # Check for OpenSSL without EVP_aes_{192,256}_cbc + AC_MSG_CHECKING([whether OpenSSL has crippled AES support]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL); + ]])], + [ + AC_MSG_RESULT([no]) + ], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([OPENSSL_LOBOTOMISED_AES], [1], + [libcrypto is missing AES 192 and 256 bit functions]) + ] + ) -# Check for OpenSSL with EVP_aes_*ctr -AC_MSG_CHECKING([whether OpenSSL has AES CTR via EVP]) -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include - ]], [[ - exit(EVP_aes_128_ctr() == NULL || - EVP_aes_192_cbc() == NULL || - EVP_aes_256_cbc() == NULL); - ]])], - [ - AC_MSG_RESULT([yes]) - AC_DEFINE([OPENSSL_HAVE_EVPCTR], [1], - [libcrypto has EVP AES CTR]) - ], - [ - AC_MSG_RESULT([no]) - ] -) + # Check for OpenSSL with EVP_aes_*ctr + AC_MSG_CHECKING([whether OpenSSL has AES CTR via EVP]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + exit(EVP_aes_128_ctr() == NULL || + EVP_aes_192_cbc() == NULL || + EVP_aes_256_cbc() == NULL); + ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([OPENSSL_HAVE_EVPCTR], [1], + [libcrypto has EVP AES CTR]) + ], + [ + AC_MSG_RESULT([no]) + ] + ) -# Check for OpenSSL with EVP_aes_*gcm -AC_MSG_CHECKING([whether OpenSSL has AES GCM via EVP]) -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include - ]], [[ - exit(EVP_aes_128_gcm() == NULL || - EVP_aes_256_gcm() == NULL || - EVP_CTRL_GCM_SET_IV_FIXED == 0 || - EVP_CTRL_GCM_IV_GEN == 0 || - EVP_CTRL_GCM_SET_TAG == 0 || - EVP_CTRL_GCM_GET_TAG == 0 || - EVP_CIPHER_CTX_ctrl(NULL, 0, 0, NULL) == 0); - ]])], - [ - AC_MSG_RESULT([yes]) - AC_DEFINE([OPENSSL_HAVE_EVPGCM], [1], - [libcrypto has EVP AES GCM]) - ], - [ - AC_MSG_RESULT([no]) - unsupported_algorithms="$unsupported_cipers \ - aes128-gcm@openssh.com aes256-gcm@openssh.com" - ] -) + # Check for OpenSSL with EVP_aes_*gcm + AC_MSG_CHECKING([whether OpenSSL has AES GCM via EVP]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + exit(EVP_aes_128_gcm() == NULL || + EVP_aes_256_gcm() == NULL || + EVP_CTRL_GCM_SET_IV_FIXED == 0 || + EVP_CTRL_GCM_IV_GEN == 0 || + EVP_CTRL_GCM_SET_TAG == 0 || + EVP_CTRL_GCM_GET_TAG == 0 || + EVP_CIPHER_CTX_ctrl(NULL, 0, 0, NULL) == 0); + ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([OPENSSL_HAVE_EVPGCM], [1], + [libcrypto has EVP AES GCM]) + ], + [ + AC_MSG_RESULT([no]) + unsupported_algorithms="$unsupported_cipers \ + aes128-gcm@openssh.com aes256-gcm@openssh.com" + ] + ) -AC_SEARCH_LIBS([EVP_CIPHER_CTX_ctrl], [crypto], - [AC_DEFINE([HAVE_EVP_CIPHER_CTX_CTRL], [1], - [Define if libcrypto has EVP_CIPHER_CTX_ctrl])]) + AC_SEARCH_LIBS([EVP_CIPHER_CTX_ctrl], [crypto], + [AC_DEFINE([HAVE_EVP_CIPHER_CTX_CTRL], [1], + [Define if libcrypto has EVP_CIPHER_CTX_ctrl])]) -AC_MSG_CHECKING([if EVP_DigestUpdate returns an int]) -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include - ]], [[ - if(EVP_DigestUpdate(NULL, NULL,0)) - exit(0); - ]])], - [ - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - AC_DEFINE([OPENSSL_EVP_DIGESTUPDATE_VOID], [1], - [Define if EVP_DigestUpdate returns void]) - ] -) + AC_MSG_CHECKING([if EVP_DigestUpdate returns an int]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + if(EVP_DigestUpdate(NULL, NULL,0)) + exit(0); + ]])], + [ + AC_MSG_RESULT([yes]) + ], + [ + AC_MSG_RESULT([no]) + AC_DEFINE([OPENSSL_EVP_DIGESTUPDATE_VOID], [1], + [Define if EVP_DigestUpdate returns void]) + ] + ) -# Some systems want crypt() from libcrypt, *not* the version in OpenSSL, -# because the system crypt() is more featureful. -if test "x$check_for_libcrypt_before" = "x1"; then - AC_CHECK_LIB([crypt], [crypt]) -fi + # Some systems want crypt() from libcrypt, *not* the version in OpenSSL, + # because the system crypt() is more featureful. + if test "x$check_for_libcrypt_before" = "x1"; then + AC_CHECK_LIB([crypt], [crypt]) + fi -# Some Linux systems (Slackware) need crypt() from libcrypt, *not* the -# version in OpenSSL. -if test "x$check_for_libcrypt_later" = "x1"; then - AC_CHECK_LIB([crypt], [crypt], [LIBS="$LIBS -lcrypt"]) -fi -AC_CHECK_FUNCS([crypt DES_crypt]) - -# Search for SHA256 support in libc and/or OpenSSL -AC_CHECK_FUNCS([SHA256_Update EVP_sha256], , - [unsupported_algorithms="$unsupported_algorithms \ - hmac-sha2-256 hmac-sha2-512 \ - diffie-hellman-group-exchange-sha256 \ - hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com" - ] -) + # Some Linux systems (Slackware) need crypt() from libcrypt, *not* the + # version in OpenSSL. + if test "x$check_for_libcrypt_later" = "x1"; then + AC_CHECK_LIB([crypt], [crypt], [LIBS="$LIBS -lcrypt"]) + fi + AC_CHECK_FUNCS([crypt DES_crypt]) + + # Search for SHA256 support in libc and/or OpenSSL + AC_CHECK_FUNCS([SHA256_Update EVP_sha256], , + [unsupported_algorithms="$unsupported_algorithms \ + hmac-sha2-256 hmac-sha2-512 \ + diffie-hellman-group-exchange-sha256 \ + hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com" + ] + ) + # Search for RIPE-MD support in OpenSSL + AC_CHECK_FUNCS([EVP_ripemd160], , + [unsupported_algorithms="$unsupported_algorithms \ + hmac-ripemd160 + hmac-ripemd160@openssh.com + hmac-ripemd160-etm@openssh.com" + ] + ) -# Check complete ECC support in OpenSSL -AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1]) -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include -#include -#include -#include -#include -#if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ -# error "OpenSSL < 0.9.8g has unreliable ECC code" -#endif - ]], [[ - EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - const EVP_MD *m = EVP_sha256(); /* We need this too */ - ]])], - [ AC_MSG_RESULT([yes]) - enable_nistp256=1 ], - [ AC_MSG_RESULT([no]) ] -) + # Check complete ECC support in OpenSSL + AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + #include + #include + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + ]], [[ + EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + const EVP_MD *m = EVP_sha256(); /* We need this too */ + ]])], + [ AC_MSG_RESULT([yes]) + enable_nistp256=1 ], + [ AC_MSG_RESULT([no]) ] + ) -AC_MSG_CHECKING([whether OpenSSL has NID_secp384r1]) -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include -#include -#include -#include -#include -#if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ -# error "OpenSSL < 0.9.8g has unreliable ECC code" -#endif - ]], [[ - EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); - const EVP_MD *m = EVP_sha384(); /* We need this too */ - ]])], - [ AC_MSG_RESULT([yes]) - enable_nistp384=1 ], - [ AC_MSG_RESULT([no]) ] -) + AC_MSG_CHECKING([whether OpenSSL has NID_secp384r1]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + #include + #include + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + ]], [[ + EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); + const EVP_MD *m = EVP_sha384(); /* We need this too */ + ]])], + [ AC_MSG_RESULT([yes]) + enable_nistp384=1 ], + [ AC_MSG_RESULT([no]) ] + ) -AC_MSG_CHECKING([whether OpenSSL has NID_secp521r1]) -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include -#include -#include -#include -#include -#if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ -# error "OpenSSL < 0.9.8g has unreliable ECC code" -#endif - ]], [[ - EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); - const EVP_MD *m = EVP_sha512(); /* We need this too */ - ]])], - [ AC_MSG_RESULT([yes]) - AC_MSG_CHECKING([if OpenSSL's NID_secp521r1 is functional]) - AC_RUN_IFELSE( + AC_MSG_CHECKING([whether OpenSSL has NID_secp521r1]) + AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ -#include -#include -#include -#include -#include -#include - ]],[[ + #include + #include + #include + #include + #include + #include + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ - exit(e == NULL || m == NULL); ]])], [ AC_MSG_RESULT([yes]) - enable_nistp521=1 ], - [ AC_MSG_RESULT([no]) ], - [ AC_MSG_WARN([cross-compiling: assuming yes]) - enable_nistp521=1 ] - )], - AC_MSG_RESULT([no]) -) + AC_MSG_CHECKING([if OpenSSL's NID_secp521r1 is functional]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + #include + #include + #include + #include + ]],[[ + EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); + const EVP_MD *m = EVP_sha512(); /* We need this too */ + exit(e == NULL || m == NULL); + ]])], + [ AC_MSG_RESULT([yes]) + enable_nistp521=1 ], + [ AC_MSG_RESULT([no]) ], + [ AC_MSG_WARN([cross-compiling: assuming yes]) + enable_nistp521=1 ] + )], + AC_MSG_RESULT([no]) + ) -COMMENT_OUT_ECC="#no ecc#" -TEST_SSH_ECC=no + COMMENT_OUT_ECC="#no ecc#" + TEST_SSH_ECC=no -if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \ - test x$enable_nistp521 = x1; then - AC_DEFINE(OPENSSL_HAS_ECC, [1], [OpenSSL has ECC]) -fi -if test x$enable_nistp256 = x1; then - AC_DEFINE([OPENSSL_HAS_NISTP256], [1], - [libcrypto has NID_X9_62_prime256v1]) - TEST_SSH_ECC=yes - COMMENT_OUT_ECC="" -else - unsupported_algorithms="$unsupported_algorithms ecdsa-sha2-nistp256 \ - ecdh-sha2-nistp256 ecdsa-sha2-nistp256-cert-v01@openssh.com" -fi -if test x$enable_nistp384 = x1; then - AC_DEFINE([OPENSSL_HAS_NISTP384], [1], [libcrypto has NID_secp384r1]) - TEST_SSH_ECC=yes - COMMENT_OUT_ECC="" -else - unsupported_algorithms="$unsupported_algorithms ecdsa-sha2-nistp384 \ - ecdh-sha2-nistp384 ecdsa-sha2-nistp384-cert-v01@openssh.com" -fi -if test x$enable_nistp521 = x1; then - AC_DEFINE([OPENSSL_HAS_NISTP521], [1], [libcrypto has NID_secp521r1]) - TEST_SSH_ECC=yes - COMMENT_OUT_ECC="" + if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \ + test x$enable_nistp521 = x1; then + AC_DEFINE(OPENSSL_HAS_ECC, [1], [OpenSSL has ECC]) + fi + if test x$enable_nistp256 = x1; then + AC_DEFINE([OPENSSL_HAS_NISTP256], [1], + [libcrypto has NID_X9_62_prime256v1]) + TEST_SSH_ECC=yes + COMMENT_OUT_ECC="" + else + unsupported_algorithms="$unsupported_algorithms ecdsa-sha2-nistp256 \ + ecdh-sha2-nistp256 ecdsa-sha2-nistp256-cert-v01@openssh.com" + fi + if test x$enable_nistp384 = x1; then + AC_DEFINE([OPENSSL_HAS_NISTP384], [1], [libcrypto has NID_secp384r1]) + TEST_SSH_ECC=yes + COMMENT_OUT_ECC="" + else + unsupported_algorithms="$unsupported_algorithms ecdsa-sha2-nistp384 \ + ecdh-sha2-nistp384 ecdsa-sha2-nistp384-cert-v01@openssh.com" + fi + if test x$enable_nistp521 = x1; then + AC_DEFINE([OPENSSL_HAS_NISTP521], [1], [libcrypto has NID_secp521r1]) + TEST_SSH_ECC=yes + COMMENT_OUT_ECC="" + else + unsupported_algorithms="$unsupported_algorithms ecdh-sha2-nistp521 \ + ecdsa-sha2-nistp521 ecdsa-sha2-nistp521-cert-v01@openssh.com" + fi + + AC_SUBST([TEST_SSH_ECC]) + AC_SUBST([COMMENT_OUT_ECC]) else - unsupported_algorithms="$unsupported_algorithms ecdh-sha2-nistp521 \ - ecdsa-sha2-nistp521 ecdsa-sha2-nistp521-cert-v01@openssh.com" + AC_CHECK_LIB([crypt], [crypt], [LIBS="$LIBS -lcrypt"]) + AC_CHECK_FUNCS([crypt]) fi -AC_SUBST([TEST_SSH_ECC]) -AC_SUBST([COMMENT_OUT_ECC]) +AC_CHECK_FUNCS([ \ + arc4random \ + arc4random_buf \ + arc4random_stir \ + arc4random_uniform \ +]) saved_LIBS="$LIBS" AC_CHECK_LIB([iaf], [ia_openinfo], [ @@ -2699,28 +2830,30 @@ LIBS="$saved_LIBS" ### Configure cryptographic random number support # Check wheter OpenSSL seeds itself -AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) -AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include - ]], [[ - exit(RAND_status() == 1 ? 0 : 1); - ]])], - [ - OPENSSL_SEEDS_ITSELF=yes - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - ], - [ - AC_MSG_WARN([cross compiling: assuming yes]) - # This is safe, since we will fatal() at runtime if - # OpenSSL is not seeded correctly. - OPENSSL_SEEDS_ITSELF=yes - ] -) +if test "x$openssl" = "xyes" ; then + AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + exit(RAND_status() == 1 ? 0 : 1); + ]])], + [ + OPENSSL_SEEDS_ITSELF=yes + AC_MSG_RESULT([yes]) + ], + [ + AC_MSG_RESULT([no]) + ], + [ + AC_MSG_WARN([cross compiling: assuming yes]) + # This is safe, since we will fatal() at runtime if + # OpenSSL is not seeded correctly. + OPENSSL_SEEDS_ITSELF=yes + ] + ) +fi # PRNGD TCP socket AC_ARG_WITH([prngd-port], @@ -2802,8 +2935,10 @@ elif test ! -z "$PRNGD_SOCKET" ; then RAND_MSG="PRNGd socket $PRNGD_SOCKET" elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then AC_DEFINE([OPENSSL_PRNG_ONLY], [1], - [Define if you want OpenSSL's internally seeded PRNG only]) + [Define if you want the OpenSSL internally seeded PRNG only]) RAND_MSG="OpenSSL internal ONLY" +elif test "x$openssl" = "xno" ; then + AC_MSG_WARN([OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible]) else AC_MSG_ERROR([OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options]) fi @@ -2865,11 +3000,18 @@ if test "x$PAM_MSG" = "xyes" ; then which takes only one argument to pam_strerror]) AC_MSG_RESULT([yes]) PAM_MSG="yes (old library)" - + ]) fi -SSH_PRIVSEP_USER=sshd +case "$host" in +*-*-cygwin*) + SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER + ;; +*) + SSH_PRIVSEP_USER=sshd + ;; +esac AC_ARG_WITH([privsep-user], [ --with-privsep-user=user Specify non-privileged user for privilege separation], [ @@ -2879,8 +3021,13 @@ AC_ARG_WITH([privsep-user], fi ] ) -AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"], - [non-privileged user for privilege separation]) +if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then + AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], [CYGWIN_SSH_PRIVSEP_USER], + [Cygwin function to fetch non-privileged user for privilege separation]) +else + AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"], + [non-privileged user for privilege separation]) +fi AC_SUBST([SSH_PRIVSEP_USER]) if test "x$have_linux_no_new_privs" = "x1" ; then @@ -3045,10 +3192,10 @@ elif test "x$sandbox_arg" = "xseccomp_filter" || \ AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter]) elif test "x$sandbox_arg" = "xcapsicum" || \ ( test -z "$sandbox_arg" && \ - test "x$ac_cv_header_sys_capability_h" = "xyes" && \ + test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \ test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then - test "x$ac_cv_header_sys_capability_h" != "xyes" && \ - AC_MSG_ERROR([capsicum sandbox requires sys/capability.h header]) + test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \ + AC_MSG_ERROR([capsicum sandbox requires sys/capsicum.h header]) test "x$ac_cv_func_cap_rights_limit" != "xyes" && \ AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function]) SANDBOX_STYLE="capsicum" @@ -4300,7 +4447,7 @@ if test ! -z "$IPADDR_IN_DISPLAY" ; then else DISPLAY_HACK_MSG="no" AC_ARG_WITH([ipaddr-display], - [ --with-ipaddr-display Use ip address instead of hostname in \$DISPLAY], + [ --with-ipaddr-display Use ip address instead of hostname in $DISPLAY], [ if test "x$withval" != "xno" ; then AC_DEFINE([IPADDR_IN_DISPLAY]) @@ -4346,7 +4493,7 @@ fi # Whether to mess with the default path SERVER_PATH_MSG="(default)" AC_ARG_WITH([default-path], - [ --with-default-path= Specify default \$PATH environment for server], + [ --with-default-path= Specify default $PATH environment for server], [ if test "x$external_path_file" = "x/etc/login.conf" ; then AC_MSG_WARN([ diff --git a/crypto/openssh/contrib/Makefile b/crypto/openssh/contrib/Makefile index c6c48e7..eaf7fe2 100644 --- a/crypto/openssh/contrib/Makefile +++ b/crypto/openssh/contrib/Makefile @@ -4,12 +4,12 @@ all: @echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2" gnome-ssh-askpass1: gnome-ssh-askpass1.c - $(CC) `gnome-config --cflags gnome gnomeui` \ + $(CC) $(CFLAGS) `gnome-config --cflags gnome gnomeui` \ gnome-ssh-askpass1.c -o gnome-ssh-askpass1 \ `gnome-config --libs gnome gnomeui` gnome-ssh-askpass2: gnome-ssh-askpass2.c - $(CC) `$(PKG_CONFIG) --cflags gtk+-2.0` \ + $(CC) $(CFLAGS) `$(PKG_CONFIG) --cflags gtk+-2.0` \ gnome-ssh-askpass2.c -o gnome-ssh-askpass2 \ `$(PKG_CONFIG) --libs gtk+-2.0 x11` diff --git a/crypto/openssh/contrib/README b/crypto/openssh/contrib/README index c002238..60e19ba 100644 --- a/crypto/openssh/contrib/README +++ b/crypto/openssh/contrib/README @@ -11,7 +11,7 @@ which allows the use of outbound SSH from behind a SOCKS4, SOCKS5 or https CONNECT style proxy server. His page for connect.c has extensive documentation on its use as well as compiled versions for Win32. -http://www.taiyo.co.jp/~gotoh/ssh/connect.html +https://bitbucket.org/gotoh/connect/wiki/Home X11 SSH Askpass: diff --git a/crypto/openssh/contrib/caldera/openssh.spec b/crypto/openssh/contrib/caldera/openssh.spec deleted file mode 100644 index 0061fe9..0000000 --- a/crypto/openssh/contrib/caldera/openssh.spec +++ /dev/null @@ -1,366 +0,0 @@ - -# Some of this will need re-evaluation post-LSB. The SVIdir is there -# because the link appeared broken. The rest is for easy compilation, -# the tradeoff open to discussion. (LC957) - -%define SVIdir /etc/rc.d/init.d -%{!?_defaultdocdir:%define _defaultdocdir %{_prefix}/share/doc/packages} -%{!?SVIcdir:%define SVIcdir /etc/sysconfig/daemons} - -%define _mandir %{_prefix}/share/man/en -%define _sysconfdir /etc/ssh -%define _libexecdir %{_libdir}/ssh - -# Do we want to disable root_login? (1=yes 0=no) -%define no_root_login 0 - -#old cvs stuff. please update before use. may be deprecated. -%define use_stable 1 -%define version 6.6p1 -%if %{use_stable} - %define cvs %{nil} - %define release 1 -%else - %define cvs cvs20050315 - %define release 0r1 -%endif -%define xsa x11-ssh-askpass -%define askpass %{xsa}-1.2.4.1 - -# OpenSSH privilege separation requires a user & group ID -%define sshd_uid 67 -%define sshd_gid 67 - -Name : openssh -Version : %{version}%{cvs} -Release : %{release} -Group : System/Network - -Summary : OpenSSH free Secure Shell (SSH) implementation. -Summary(de) : OpenSSH - freie Implementation der Secure Shell (SSH). -Summary(es) : OpenSSH implementación libre de Secure Shell (SSH). -Summary(fr) : Implémentation libre du shell sécurisé OpenSSH (SSH). -Summary(it) : Implementazione gratuita OpenSSH della Secure Shell. -Summary(pt) : Implementação livre OpenSSH do protocolo 'Secure Shell' (SSH). -Summary(pt_BR) : Implementação livre OpenSSH do protocolo Secure Shell (SSH). - -Copyright : BSD -Packager : Raymund Will -URL : http://www.openssh.com/ - -Obsoletes : ssh, ssh-clients, openssh-clients - -BuildRoot : /tmp/%{name}-%{version} -BuildRequires : XFree86-imake - -# %{use_stable}==1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable -# %{use_stable}==0: :pserver:cvs@bass.directhit.com:/cvs/openssh_cvs -Source0: see-above:/.../openssh-%{version}.tar.gz -%if %{use_stable} -Source1: see-above:/.../openssh-%{version}.tar.gz.asc -%endif -Source2: http://www.jmknoble.net/software/%{xsa}/%{askpass}.tar.gz -Source3: http://www.openssh.com/faq.html - -%Package server -Group : System/Network -Requires : openssh = %{version} -Obsoletes : ssh-server - -Summary : OpenSSH Secure Shell protocol server (sshd). -Summary(de) : OpenSSH Secure Shell Protocol-Server (sshd). -Summary(es) : Servidor del protocolo OpenSSH Secure Shell (sshd). -Summary(fr) : Serveur de protocole du shell sécurisé OpenSSH (sshd). -Summary(it) : Server OpenSSH per il protocollo Secure Shell (sshd). -Summary(pt) : Servidor do protocolo 'Secure Shell' OpenSSH (sshd). -Summary(pt_BR) : Servidor do protocolo Secure Shell OpenSSH (sshd). - - -%Package askpass -Group : System/Network -Requires : openssh = %{version} -URL : http://www.jmknoble.net/software/x11-ssh-askpass/ -Obsoletes : ssh-extras - -Summary : OpenSSH X11 pass-phrase dialog. -Summary(de) : OpenSSH X11 Passwort-Dialog. -Summary(es) : Aplicación de petición de frase clave OpenSSH X11. -Summary(fr) : Dialogue pass-phrase X11 d'OpenSSH. -Summary(it) : Finestra di dialogo X11 per la frase segreta di OpenSSH. -Summary(pt) : Diálogo de pedido de senha para X11 do OpenSSH. -Summary(pt_BR) : Diálogo de pedido de senha para X11 do OpenSSH. - - -%Description -OpenSSH (Secure Shell) provides access to a remote system. It replaces -telnet, rlogin, rexec, and rsh, and provides secure encrypted -communications between two untrusted hosts over an insecure network. -X11 connections and arbitrary TCP/IP ports can also be forwarded over -the secure channel. - -%Description -l de -OpenSSH (Secure Shell) stellt den Zugang zu anderen Rechnern her. Es ersetzt -telnet, rlogin, rexec und rsh und stellt eine sichere, verschlüsselte -Verbindung zwischen zwei nicht vertrauenswürdigen Hosts über eine unsicheres -Netzwerk her. X11 Verbindungen und beliebige andere TCP/IP Ports können ebenso -über den sicheren Channel weitergeleitet werden. - -%Description -l es -OpenSSH (Secure Shell) proporciona acceso a sistemas remotos. Reemplaza a -telnet, rlogin, rexec, y rsh, y proporciona comunicaciones seguras encriptadas -entre dos equipos entre los que no se ha establecido confianza a través de una -red insegura. Las conexiones X11 y puertos TCP/IP arbitrarios también pueden -ser canalizadas sobre el canal seguro. - -%Description -l fr -OpenSSH (Secure Shell) fournit un accès à un système distant. Il remplace -telnet, rlogin, rexec et rsh, tout en assurant des communications cryptées -securisées entre deux hôtes non fiabilisés sur un réseau non sécurisé. Des -connexions X11 et des ports TCP/IP arbitraires peuvent également être -transmis sur le canal sécurisé. - -%Description -l it -OpenSSH (Secure Shell) fornisce l'accesso ad un sistema remoto. -Sostituisce telnet, rlogin, rexec, e rsh, e fornisce comunicazioni sicure -e crittate tra due host non fidati su una rete non sicura. Le connessioni -X11 ad una porta TCP/IP arbitraria possono essere inoltrate attraverso -un canale sicuro. - -%Description -l pt -OpenSSH (Secure Shell) fornece acesso a um sistema remoto. Substitui o -telnet, rlogin, rexec, e o rsh e fornece comunicações seguras e cifradas -entre duas máquinas sem confiança mútua sobre uma rede insegura. -Ligações X11 e portos TCP/IP arbitrários também poder ser reenviados -pelo canal seguro. - -%Description -l pt_BR -O OpenSSH (Secure Shell) fornece acesso a um sistema remoto. Substitui o -telnet, rlogin, rexec, e o rsh e fornece comunicações seguras e criptografadas -entre duas máquinas sem confiança mútua sobre uma rede insegura. -Ligações X11 e portas TCP/IP arbitrárias também podem ser reenviadas -pelo canal seguro. - -%Description server -This package installs the sshd, the server portion of OpenSSH. - -%Description -l de server -Dieses Paket installiert den sshd, den Server-Teil der OpenSSH. - -%Description -l es server -Este paquete instala sshd, la parte servidor de OpenSSH. - -%Description -l fr server -Ce paquetage installe le 'sshd', partie serveur de OpenSSH. - -%Description -l it server -Questo pacchetto installa sshd, il server di OpenSSH. - -%Description -l pt server -Este pacote intala o sshd, o servidor do OpenSSH. - -%Description -l pt_BR server -Este pacote intala o sshd, o servidor do OpenSSH. - -%Description askpass -This package contains an X11-based pass-phrase dialog used per -default by ssh-add(1). It is based on %{askpass} -by Jim Knoble . - - -%Prep -%setup %([ -z "%{cvs}" ] || echo "-n %{name}_cvs") -a2 -%if ! %{use_stable} - autoreconf -%endif - - -%Build -CFLAGS="$RPM_OPT_FLAGS" \ -%configure \ - --with-pam \ - --with-tcp-wrappers \ - --with-privsep-path=%{_var}/empty/sshd \ - #leave this line for easy edits. - -%__make - -cd %{askpass} -%configure \ - #leave this line for easy edits. - -xmkmf -%__make includes -%__make - - -%Install -[ %{buildroot} != "/" ] && rm -rf %{buildroot} - -make install DESTDIR=%{buildroot} -%makeinstall -C %{askpass} \ - BINDIR=%{_libexecdir} \ - MANPATH=%{_mandir} \ - DESTDIR=%{buildroot} - -# OpenLinux specific configuration -mkdir -p %{buildroot}{/etc/pam.d,%{SVIcdir},%{SVIdir}} -mkdir -p %{buildroot}%{_var}/empty/sshd - -# enabling X11 forwarding on the server is convenient and okay, -# on the client side it's a potential security risk! -%__perl -pi -e 's:#X11Forwarding no:X11Forwarding yes:g' \ - %{buildroot}%{_sysconfdir}/sshd_config - -%if %{no_root_login} -%__perl -pi -e 's:#PermitRootLogin yes:PermitRootLogin no:g' \ - %{buildroot}%{_sysconfdir}/sshd_config -%endif - -install -m644 contrib/caldera/sshd.pam %{buildroot}/etc/pam.d/sshd -# FIXME: disabled, find out why this doesn't work with nis -%__perl -pi -e 's:(.*pam_limits.*):#$1:' \ - %{buildroot}/etc/pam.d/sshd - -install -m 0755 contrib/caldera/sshd.init %{buildroot}%{SVIdir}/sshd - -# the last one is needless, but more future-proof -find %{buildroot}%{SVIdir} -type f -exec \ - %__perl -pi -e 's:\@SVIdir\@:%{SVIdir}:g;\ - s:\@sysconfdir\@:%{_sysconfdir}:g; \ - s:/usr/sbin:%{_sbindir}:g'\ - \{\} \; - -cat <<-EoD > %{buildroot}%{SVIcdir}/sshd - IDENT=sshd - DESCRIPTIVE="OpenSSH secure shell daemon" - # This service will be marked as 'skipped' on boot if there - # is no host key. Use ssh-host-keygen to generate one - ONBOOT="yes" - OPTIONS="" -EoD - -SKG=%{buildroot}%{_sbindir}/ssh-host-keygen -install -m 0755 contrib/caldera/ssh-host-keygen $SKG -# Fix up some path names in the keygen toy^Hol - %__perl -pi -e 's:\@sysconfdir\@:%{_sysconfdir}:g; \ - s:\@sshkeygen\@:%{_bindir}/ssh-keygen:g' \ - %{buildroot}%{_sbindir}/ssh-host-keygen - -# This looks terrible. Expect it to change. -# install remaining docs -DocD="%{buildroot}%{_defaultdocdir}/%{name}-%{version}" -mkdir -p $DocD/%{askpass} -cp -a CREDITS ChangeLog LICENCE OVERVIEW README* TODO PROTOCOL* $DocD -install -p -m 0444 %{SOURCE3} $DocD/faq.html -cp -a %{askpass}/{README,ChangeLog,TODO,SshAskpass*.ad} $DocD/%{askpass} -%if %{use_stable} - cp -p %{askpass}/%{xsa}.man $DocD/%{askpass}/%{xsa}.1 -%else - cp -p %{askpass}/%{xsa}.man %{buildroot}%{_mandir}man1/%{xsa}.1 - ln -s %{xsa}.1 %{buildroot}%{_mandir}man1/ssh-askpass.1 -%endif - -find %{buildroot}%{_mandir} -type f -not -name '*.gz' -print0 | xargs -0r %__gzip -9nf -rm %{buildroot}%{_mandir}/man1/slogin.1 && \ - ln -s %{_mandir}/man1/ssh.1.gz \ - %{buildroot}%{_mandir}/man1/slogin.1.gz - - -%Clean -#%{rmDESTDIR} -[ %{buildroot} != "/" ] && rm -rf %{buildroot} - -%Post -# Generate host key when none is present to get up and running, -# both client and server require this for host-based auth! -# ssh-host-keygen checks for existing keys. -/usr/sbin/ssh-host-keygen -: # to protect the rpm database - -%pre server -%{_sbindir}/groupadd -g %{sshd_gid} sshd 2>/dev/null || : -%{_sbindir}/useradd -d /var/empty/sshd -s /bin/false -u %{sshd_uid} \ - -c "SSH Daemon virtual user" -g sshd sshd 2>/dev/null || : -: # to protect the rpm database - -%Post server -if [ -x %{LSBinit}-install ]; then - %{LSBinit}-install sshd -else - lisa --SysV-init install sshd S55 2:3:4:5 K45 0:1:6 -fi - -! %{SVIdir}/sshd status || %{SVIdir}/sshd restart -: # to protect the rpm database - - -%PreUn server -[ "$1" = 0 ] || exit 0 -! %{SVIdir}/sshd status || %{SVIdir}/sshd stop -if [ -x %{LSBinit}-remove ]; then - %{LSBinit}-remove sshd -else - lisa --SysV-init remove sshd $1 -fi -: # to protect the rpm database - -%Files -%defattr(-,root,root) -%dir %{_sysconfdir} -%config %{_sysconfdir}/ssh_config -%{_bindir}/scp -%{_bindir}/sftp -%{_bindir}/ssh -%{_bindir}/slogin -%{_bindir}/ssh-add -%attr(2755,root,nobody) %{_bindir}/ssh-agent -%{_bindir}/ssh-keygen -%{_bindir}/ssh-keyscan -%dir %{_libexecdir} -%attr(4711,root,root) %{_libexecdir}/ssh-keysign -%{_libexecdir}/ssh-pkcs11-helper -%{_sbindir}/ssh-host-keygen -%dir %{_defaultdocdir}/%{name}-%{version} -%{_defaultdocdir}/%{name}-%{version}/CREDITS -%{_defaultdocdir}/%{name}-%{version}/ChangeLog -%{_defaultdocdir}/%{name}-%{version}/LICENCE -%{_defaultdocdir}/%{name}-%{version}/OVERVIEW -%{_defaultdocdir}/%{name}-%{version}/README* -%{_defaultdocdir}/%{name}-%{version}/TODO -%{_defaultdocdir}/%{name}-%{version}/faq.html -%{_mandir}/man1/* -%{_mandir}/man8/ssh-keysign.8.gz -%{_mandir}/man8/ssh-pkcs11-helper.8.gz -%{_mandir}/man5/ssh_config.5.gz - -%Files server -%defattr(-,root,root) -%dir %{_var}/empty/sshd -%config %{SVIdir}/sshd -%config /etc/pam.d/sshd -%config %{_sysconfdir}/moduli -%config %{_sysconfdir}/sshd_config -%config %{SVIcdir}/sshd -%{_libexecdir}/sftp-server -%{_sbindir}/sshd -%{_mandir}/man5/moduli.5.gz -%{_mandir}/man5/sshd_config.5.gz -%{_mandir}/man8/sftp-server.8.gz -%{_mandir}/man8/sshd.8.gz - -%Files askpass -%defattr(-,root,root) -%{_libexecdir}/ssh-askpass -%{_libexecdir}/x11-ssh-askpass -%{_defaultdocdir}/%{name}-%{version}/%{askpass} - - -%ChangeLog -* Tue Jan 18 2011 Tim Rice -- Use CFLAGS from Makefile instead of RPM so build completes. -- Signatures were changed to .asc since 4.1p1. - -* Mon Jan 01 1998 ... -Template Version: 1.31 - -$Id: openssh.spec,v 1.83 2014/02/27 23:03:55 djm Exp $ diff --git a/crypto/openssh/contrib/caldera/ssh-host-keygen b/crypto/openssh/contrib/caldera/ssh-host-keygen deleted file mode 100755 index 86382dd..0000000 --- a/crypto/openssh/contrib/caldera/ssh-host-keygen +++ /dev/null @@ -1,36 +0,0 @@ -#! /bin/sh -# -# $Id: ssh-host-keygen,v 1.3 2008/11/03 09:16:01 djm Exp $ -# -# This script is normally run only *once* for a given host -# (in a given period of time) -- on updates/upgrades/recovery -# the ssh_host_key* files _should_ be retained! Otherwise false -# "man-in-the-middle-attack" alerts will frighten unsuspecting -# clients... - -keydir=@sysconfdir@ -keygen=@sshkeygen@ - -if [ -f $keydir/ssh_host_key -o \ - -f $keydir/ssh_host_key.pub ]; then - echo "You already have an SSH1 RSA host key in $keydir/ssh_host_key." -else - echo "Generating SSH1 RSA host key." - $keygen -t rsa1 -f $keydir/ssh_host_key -C '' -N '' -fi - -if [ -f $keydir/ssh_host_rsa_key -o \ - -f $keydir/ssh_host_rsa_key.pub ]; then - echo "You already have an SSH2 RSA host key in $keydir/ssh_host_rsa_key." -else - echo "Generating SSH2 RSA host key." - $keygen -t rsa -f $keydir/ssh_host_rsa_key -C '' -N '' -fi - -if [ -f $keydir/ssh_host_dsa_key -o \ - -f $keydir/ssh_host_dsa_key.pub ]; then - echo "You already have an SSH2 DSA host key in $keydir/ssh_host_dsa_key." -else - echo "Generating SSH2 DSA host key." - $keygen -t dsa -f $keydir/ssh_host_dsa_key -C '' -N '' -fi diff --git a/crypto/openssh/contrib/caldera/sshd.init b/crypto/openssh/contrib/caldera/sshd.init deleted file mode 100755 index 983146f..0000000 --- a/crypto/openssh/contrib/caldera/sshd.init +++ /dev/null @@ -1,125 +0,0 @@ -#! /bin/bash -# -# $Id: sshd.init,v 1.4 2003/11/21 12:48:57 djm Exp $ -# -### BEGIN INIT INFO -# Provides: -# Required-Start: $network -# Required-Stop: -# Default-Start: 3 4 5 -# Default-Stop: 0 1 2 6 -# Description: sshd -# Bring up/down the OpenSSH secure shell daemon. -### END INIT INFO -# -# Written by Miquel van Smoorenburg . -# Modified for Debian GNU/Linux by Ian Murdock . -# Modified for OpenLinux by Raymund Will - -NAME=sshd -DAEMON=/usr/sbin/$NAME -# Hack-Alert(TM)! This is necessary to get around the 'reload'-problem -# created by recent OpenSSH daemon/ssd combinations. See Caldera internal -# PR [linux/8278] for details... -PIDF=/var/run/$NAME.pid -NAME=$DAEMON - -_status() { - [ -z "$1" ] || local pidf="$1" - local ret=-1 - local pid - if [ -n "$pidf" ] && [ -r "$pidf" ]; then - pid=$(head -1 $pidf) - else - pid=$(pidof $NAME) - fi - - if [ ! -e $SVIlock ]; then - # no lock-file => not started == stopped? - ret=3 - elif [ -n "$pidf" -a ! -f "$pidf" ] || [ -z "$pid" ]; then - # pid-file given but not present or no pid => died, but was not stopped - ret=2 - elif [ -r /proc/$pid/cmdline ] && - echo -ne $NAME'\000' | cmp -s - /proc/$pid/cmdline; then - # pid-file given and present or pid found => check process... - # but don't compare exe, as this will fail after an update! - # compares OK => all's well, that ends well... - ret=0 - else - # no such process or exe does not match => stale pid-file or process died - # just recently... - ret=1 - fi - return $ret -} - -# Source function library (and set vital variables). -. @SVIdir@/functions - -case "$1" in - start) - [ ! -e $SVIlock ] || exit 0 - [ -x $DAEMON ] || exit 5 - SVIemptyConfig @sysconfdir@/sshd_config && exit 6 - - if [ ! \( -f @sysconfdir@/ssh_host_key -a \ - -f @sysconfdir@/ssh_host_key.pub \) -a \ - ! \( -f @sysconfdir@/ssh_host_rsa_key -a \ - -f @sysconfdir@/ssh_host_rsa_key.pub \) -a \ - ! \( -f @sysconfdir@/ssh_host_dsa_key -a \ - -f @sysconfdir@/ssh_host_dsa_key.pub \) ]; then - - echo "$SVIsubsys: host key not initialized: skipped!" - echo "$SVIsubsys: use ssh-host-keygen to generate one!" - exit 6 - fi - - echo -n "Starting $SVIsubsys services: " - ssd -S -x $DAEMON -n $NAME -- $OPTIONS - ret=$? - - echo "." - touch $SVIlock - ;; - - stop) - [ -e $SVIlock ] || exit 0 - - echo -n "Stopping $SVIsubsys services: " - ssd -K -p $PIDF -n $NAME - ret=$? - - echo "." - rm -f $SVIlock - ;; - - force-reload|reload) - [ -e $SVIlock ] || exit 0 - - echo "Reloading $SVIsubsys configuration files: " - ssd -K --signal 1 -q -p $PIDF -n $NAME - ret=$? - echo "done." - ;; - - restart) - $0 stop - $0 start - ret=$? - ;; - - status) - _status $PIDF - ret=$? - ;; - - *) - echo "Usage: $SVIscript {[re]start|stop|[force-]reload|status}" - ret=2 - ;; - -esac - -exit $ret - diff --git a/crypto/openssh/contrib/caldera/sshd.pam b/crypto/openssh/contrib/caldera/sshd.pam deleted file mode 100644 index f050a9a..0000000 --- a/crypto/openssh/contrib/caldera/sshd.pam +++ /dev/null @@ -1,8 +0,0 @@ -#%PAM-1.0 -auth required /lib/security/pam_pwdb.so shadow nodelay -account required /lib/security/pam_nologin.so -account required /lib/security/pam_pwdb.so -password required /lib/security/pam_cracklib.so -password required /lib/security/pam_pwdb.so shadow nullok use_authtok -session required /lib/security/pam_pwdb.so -session required /lib/security/pam_limits.so diff --git a/crypto/openssh/contrib/cygwin/README b/crypto/openssh/contrib/cygwin/README index 2562b61..1396d99 100644 --- a/crypto/openssh/contrib/cygwin/README +++ b/crypto/openssh/contrib/cygwin/README @@ -69,7 +69,7 @@ Building OpenSSH Building from source is easy. Just unpack the source archive, cd to that directory, and call cygport: - cygport openssh.cygport almostall + cygport openssh.cygport all You must have installed the following packages to be able to build OpenSSH with the aforementioned cygport script: @@ -77,7 +77,6 @@ with the aforementioned cygport script: zlib crypt openssl-devel - libwrap-devel libedit-devel libkrb5-devel diff --git a/crypto/openssh/contrib/cygwin/ssh-host-config b/crypto/openssh/contrib/cygwin/ssh-host-config index 05efd3b..d934d09 100644 --- a/crypto/openssh/contrib/cygwin/ssh-host-config +++ b/crypto/openssh/contrib/cygwin/ssh-host-config @@ -1,6 +1,6 @@ #!/bin/bash # -# ssh-host-config, Copyright 2000-2011 Red Hat Inc. +# ssh-host-config, Copyright 2000-2014 Red Hat Inc. # # This file is part of the Cygwin port of OpenSSH. # @@ -34,9 +34,9 @@ declare -a csih_required_commands=( /usr/bin/mv coreutils /usr/bin/rm coreutils /usr/bin/cygpath cygwin + /usr/bin/mkpasswd cygwin /usr/bin/mount cygwin /usr/bin/ps cygwin - /usr/bin/setfacl cygwin /usr/bin/umount cygwin /usr/bin/cmp diffutils /usr/bin/grep grep @@ -59,8 +59,10 @@ PREFIX=/usr SYSCONFDIR=/etc LOCALSTATEDIR=/var +sshd_config_configured=no port_number=22 -privsep_configured=no +service_name=sshd +strictmodes=yes privsep_used=yes cygwin_value="" user_account= @@ -89,28 +91,8 @@ update_services_file() { # Depends on the above mount _wservices=`cygpath -w "${_services}"` - # Remove sshd 22/port from services - if [ `/usr/bin/grep -q 'sshd[ \t][ \t]*22' "${_services}"; echo $?` -eq 0 ] - then - /usr/bin/grep -v 'sshd[ \t][ \t]*22' "${_services}" > "${_serv_tmp}" - if [ -f "${_serv_tmp}" ] - then - if /usr/bin/mv "${_serv_tmp}" "${_services}" - then - csih_inform "Removing sshd from ${_wservices}" - else - csih_warning "Removing sshd from ${_wservices} failed!" - let ++ret - fi - /usr/bin/rm -f "${_serv_tmp}" - else - csih_warning "Removing sshd from ${_wservices} failed!" - let ++ret - fi - fi - # Add ssh 22/tcp and ssh 22/udp to services - if [ `/usr/bin/grep -q 'ssh[ \t][ \t]*22' "${_services}"; echo $?` -ne 0 ] + if [ `/usr/bin/grep -q 'ssh[[:space:]][[:space:]]*22' "${_services}"; echo $?` -ne 0 ] then if /usr/bin/awk '{ if ( $2 ~ /^23\/tcp/ ) print "ssh 22/tcp'"${_spaces}"'SSH Remote Login Protocol\nssh 22/udp'"${_spaces}"'SSH Remote Login Protocol"; print $0; }' < "${_services}" > "${_serv_tmp}" then @@ -132,17 +114,45 @@ update_services_file() { } # --- End of update_services_file --- # # ====================================================================== +# Routine: sshd_strictmodes +# MODIFIES: strictmodes +# ====================================================================== +sshd_strictmodes() { + if [ "${sshd_config_configured}" != "yes" ] + then + echo + csih_inform "StrictModes is set to 'yes' by default." + csih_inform "This is the recommended setting, but it requires that the POSIX" + csih_inform "permissions of the user's home directory, the user's .ssh" + csih_inform "directory, and the user's ssh key files are tight so that" + csih_inform "only the user has write permissions." + csih_inform "On the other hand, StrictModes don't work well with default" + csih_inform "Windows permissions of a home directory mounted with the" + csih_inform "'noacl' option, and they don't work at all if the home" + csih_inform "directory is on a FAT or FAT32 partition." + if ! csih_request "Should StrictModes be used?" + then + strictmodes=no + fi + fi + return 0 +} + +# ====================================================================== # Routine: sshd_privsep -# MODIFIES: privsep_configured privsep_used +# MODIFIES: privsep_used # ====================================================================== sshd_privsep() { - local sshdconfig_tmp local ret=0 - if [ "${privsep_configured}" != "yes" ] + if [ "${sshd_config_configured}" != "yes" ] then - csih_inform "Privilege separation is set to yes by default since OpenSSH 3.3." - csih_inform "However, this requires a non-privileged account called 'sshd'." + echo + csih_inform "Privilege separation is set to 'sandbox' by default since" + csih_inform "OpenSSH 6.1. This is unsupported by Cygwin and has to be set" + csih_inform "to 'yes' or 'no'." + csih_inform "However, using privilege separation requires a non-privileged account" + csih_inform "called 'sshd'." csih_inform "For more info on privilege separation read /usr/share/doc/openssh/README.privsep." if csih_request "Should privilege separation be used?" then @@ -159,36 +169,53 @@ sshd_privsep() { privsep_used=no fi fi + return $ret +} # --- End of sshd_privsep --- # - # Create default sshd_config from skeleton files in /etc/defaults/etc or - # modify to add the missing privsep configuration option - if /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1 +# ====================================================================== +# Routine: sshd_config_tweak +# ====================================================================== +sshd_config_tweak() { + local ret=0 + + # Modify sshd_config + csih_inform "Updating ${SYSCONFDIR}/sshd_config file" + if [ "${port_number}" -ne 22 ] then - csih_inform "Updating ${SYSCONFDIR}/sshd_config file" - sshdconfig_tmp=${SYSCONFDIR}/sshd_config.$$ - /usr/bin/sed -e "s/^#UsePrivilegeSeparation yes/UsePrivilegeSeparation ${privsep_used}/ - s/^#Port 22/Port ${port_number}/ - s/^#StrictModes yes/StrictModes no/" \ - < ${SYSCONFDIR}/sshd_config \ - > "${sshdconfig_tmp}" - if ! /usr/bin/mv "${sshdconfig_tmp}" ${SYSCONFDIR}/sshd_config + /usr/bin/sed -i -e "s/^#\?[[:space:]]*Port[[:space:]].*/Port ${port_number}/" \ + ${SYSCONFDIR}/sshd_config + if [ $? -ne 0 ] then - csih_warning "Setting privilege separation to 'yes' failed!" - csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" - let ++ret + csih_warning "Setting listening port to ${port_number} failed!" + csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" + let ++ret fi - elif [ "${privsep_configured}" != "yes" ] + fi + if [ "${strictmodes}" = "no" ] then - echo >> ${SYSCONFDIR}/sshd_config - if ! echo "UsePrivilegeSeparation ${privsep_used}" >> ${SYSCONFDIR}/sshd_config + /usr/bin/sed -i -e "s/^#\?[[:space:]]*StrictModes[[:space:]].*/StrictModes no/" \ + ${SYSCONFDIR}/sshd_config + if [ $? -ne 0 ] then - csih_warning "Setting privilege separation to 'yes' failed!" - csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" - let ++ret + csih_warning "Setting StrictModes to 'no' failed!" + csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" + let ++ret + fi + fi + if [ "${sshd_config_configured}" != "yes" ] + then + /usr/bin/sed -i -e " + s/^#\?UsePrivilegeSeparation .*/UsePrivilegeSeparation ${privsep_used}/" \ + ${SYSCONFDIR}/sshd_config + if [ $? -ne 0 ] + then + csih_warning "Setting privilege separation failed!" + csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" + let ++ret fi fi return $ret -} # --- End of sshd_privsep --- # +} # --- End of sshd_config_tweak --- # # ====================================================================== # Routine: update_inetd_conf @@ -207,11 +234,11 @@ update_inetd_conf() { # we have inetutils-1.5 inetd.d support if [ -f "${_inetcnf}" ] then - /usr/bin/grep -q '^[ \t]*ssh' "${_inetcnf}" && _with_comment=0 + /usr/bin/grep -q '^[[:space:]]*ssh' "${_inetcnf}" && _with_comment=0 # check for sshd OR ssh in top-level inetd.conf file, and remove # will be replaced by a file in inetd.d/ - if [ `/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?` -eq 0 ] + if [ $(/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?) -eq 0 ] then /usr/bin/grep -v '^[# \t]*ssh' "${_inetcnf}" >> "${_inetcnf_tmp}" if [ -f "${_inetcnf_tmp}" ] @@ -236,9 +263,9 @@ update_inetd_conf() { then if [ "${_with_comment}" -eq 0 ] then - /usr/bin/sed -e 's/@COMMENT@[ \t]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" + /usr/bin/sed -e 's/@COMMENT@[[:space:]]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" else - /usr/bin/sed -e 's/@COMMENT@[ \t]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" + /usr/bin/sed -e 's/@COMMENT@[[:space:]]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" fi if /usr/bin/mv "${_sshd_inetd_conf_tmp}" "${_sshd_inetd_conf}" then @@ -251,13 +278,13 @@ update_inetd_conf() { elif [ -f "${_inetcnf}" ] then - /usr/bin/grep -q '^[ \t]*sshd' "${_inetcnf}" && _with_comment=0 + /usr/bin/grep -q '^[[:space:]]*sshd' "${_inetcnf}" && _with_comment=0 # check for sshd in top-level inetd.conf file, and remove # will be replaced by a file in inetd.d/ - if [ `/usr/bin/grep -q '^[# \t]*sshd' "${_inetcnf}"; echo $?` -eq 0 ] + if [ `/usr/bin/grep -q '^#\?[[:space:]]*sshd' "${_inetcnf}"; echo $?` -eq 0 ] then - /usr/bin/grep -v '^[# \t]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}" + /usr/bin/grep -v '^#\?[[:space:]]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}" if [ -f "${_inetcnf_tmp}" ] then if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}" @@ -305,24 +332,31 @@ check_service_files_ownership() { if [ -z "${run_service_as}" ] then - accnt_name=$(/usr/bin/cygrunsrv -VQ sshd | /usr/bin/sed -ne 's/^Account *: *//gp') + accnt_name=$(/usr/bin/cygrunsrv -VQ sshd | + /usr/bin/sed -ne 's/^Account *: *//gp') if [ "${accnt_name}" = "LocalSystem" ] then # Convert "LocalSystem" to "SYSTEM" as is the correct account name - accnt_name="SYSTEM:" - elif [[ "${accnt_name}" =~ ^\.\\ ]] - then - # Convert "." domain to local machine name - accnt_name="U-${COMPUTERNAME}${accnt_name#.}," + run_service_as="SYSTEM" + else + dom="${accnt_name%%\\*}" + accnt_name="${accnt_name#*\\}" + if [ "${dom}" = '.' ] + then + # Check local account + run_service_as=$(/usr/bin/mkpasswd -l -u "${accnt_name}" | + /usr/bin/awk -F: '{print $1;}') + else + # Check domain + run_service_as=$(/usr/bin/mkpasswd -d "${dom}" -u "${accnt_name}" | + /usr/bin/awk -F: '{print $1;}') + fi fi - run_service_as=$(/usr/bin/grep -Fi "${accnt_name}" /etc/passwd | /usr/bin/awk -F: '{print $1;}') if [ -z "${run_service_as}" ] then - csih_warning "Couldn't determine name of user running sshd service from /etc/passwd!" + csih_warning "Couldn't determine name of user running sshd service from account database!" csih_warning "As a result, this script cannot make sure that the files used" csih_warning "by the sshd service belong to the user running the service." - csih_warning "Please re-run the mkpasswd tool to make sure the /etc/passwd" - csih_warning "file is in a good shape." return 1 fi fi @@ -375,7 +409,7 @@ install_service() { local ret=0 echo - if /usr/bin/cygrunsrv -Q sshd >/dev/null 2>&1 + if /usr/bin/cygrunsrv -Q ${service_name} >/dev/null 2>&1 then csih_inform "Sshd service is already installed." check_service_files_ownership "" || let ret+=$? @@ -431,7 +465,7 @@ install_service() { fi if [ -z "${password}" ] then - if /usr/bin/cygrunsrv -I sshd -d "CYGWIN sshd" -p /usr/sbin/sshd \ + if /usr/bin/cygrunsrv -I ${service_name} -d "CYGWIN ${service_name}" -p /usr/sbin/sshd \ -a "-D" -y tcpip "${cygwin_env[@]}" then echo @@ -441,20 +475,20 @@ install_service() { csih_inform "will start automatically after the next reboot." fi else - if /usr/bin/cygrunsrv -I sshd -d "CYGWIN sshd" -p /usr/sbin/sshd \ + if /usr/bin/cygrunsrv -I ${service_name} -d "CYGWIN ${service_name}" -p /usr/sbin/sshd \ -a "-D" -y tcpip "${cygwin_env[@]}" \ -u "${run_service_as}" -w "${password}" then /usr/bin/editrights -u "${run_service_as}" -a SeServiceLogonRight echo csih_inform "The sshd service has been installed under the '${run_service_as}'" - csih_inform "account. To start the service now, call \`net start sshd' or" - csih_inform "\`cygrunsrv -S sshd'. Otherwise, it will start automatically" + csih_inform "account. To start the service now, call \`net start ${service_name}' or" + csih_inform "\`cygrunsrv -S ${service_name}'. Otherwise, it will start automatically" csih_inform "after the next reboot." fi fi - if /usr/bin/cygrunsrv -Q sshd >/dev/null 2>&1 + if /usr/bin/cygrunsrv -Q ${service_name} >/dev/null 2>&1 then check_service_files_ownership "${run_service_as}" || let ret+=$? else @@ -528,6 +562,11 @@ do shift ;; + -N | --name ) + service_name=$1 + shift + ;; + -p | --port ) port_number=$1 shift @@ -557,6 +596,7 @@ do echo " --yes -y Answer all questions with \"yes\" automatically." echo " --no -n Answer all questions with \"no\" automatically." echo " --cygwin -c Use \"options\" as value for CYGWIN environment var." + echo " --name -N sshd windows service name." echo " --port -p sshd listens on port n." echo " --user -u privileged user for service, default 'cyg_server'." echo " --pwd -w Use \"pwd\" as password for privileged user." @@ -590,10 +630,7 @@ then csih_warning "However, it seems your account does not have these privileges." csih_warning "Here's the list of groups in your user token:" echo - for i in $(/usr/bin/id -G) - do - /usr/bin/awk -F: "/[^:]*:[^:]*:$i:/{ print \" \" \$1; }" /etc/group - done + /usr/bin/id -Gnz | xargs -0n1 echo " " echo csih_warning "This usually means you're running this script from a non-admin" csih_warning "desktop session, or in a non-elevated shell under UAC control." @@ -615,32 +652,6 @@ echo warning_cnt=0 -# Check for ${SYSCONFDIR} directory -csih_make_dir "${SYSCONFDIR}" "Cannot create global configuration files." -if ! /usr/bin/chmod 775 "${SYSCONFDIR}" >/dev/null 2>&1 -then - csih_warning "Can't set permissions on ${SYSCONFDIR}!" - let ++warning_cnt -fi -if ! /usr/bin/setfacl -m u:system:rwx "${SYSCONFDIR}" >/dev/null 2>&1 -then - csih_warning "Can't set extended permissions on ${SYSCONFDIR}!" - let ++warning_cnt -fi - -# Check for /var/log directory -csih_make_dir "${LOCALSTATEDIR}/log" "Cannot create log directory." -if ! /usr/bin/chmod 775 "${LOCALSTATEDIR}/log" >/dev/null 2>&1 -then - csih_warning "Can't set permissions on ${LOCALSTATEDIR}/log!" - let ++warning_cnt -fi -if ! /usr/bin/setfacl -m u:system:rwx "${LOCALSTATEDIR}/log" >/dev/null 2>&1 -then - csih_warning "Can't set extended permissions on ${LOCALSTATEDIR}/log!" - let ++warning_cnt -fi - # Create /var/log/lastlog if not already exists if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ] then @@ -665,13 +676,9 @@ then csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!" let ++warning_cnt fi -if ! /usr/bin/setfacl -m u:system:rwx "${LOCALSTATEDIR}/empty" >/dev/null 2>&1 -then - csih_warning "Can't set extended permissions on ${LOCALSTATEDIR}/empty!" - let ++warning_cnt -fi # generate missing host keys +csih_inform "Generating missing SSH host keys" /usr/bin/ssh-keygen -A || let warning_cnt+=$? # handle ssh_config @@ -690,10 +697,11 @@ fi csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1 then - /usr/bin/grep -q UsePrivilegeSeparation ${SYSCONFDIR}/sshd_config && privsep_configured=yes + sshd_config_configured=yes fi +sshd_strictmodes || let warning_cnt+=$? sshd_privsep || let warning_cnt+=$? - +sshd_config_tweak || let warning_cnt+=$? update_services_file || let warning_cnt+=$? update_inetd_conf || let warning_cnt+=$? install_service || let warning_cnt+=$? diff --git a/crypto/openssh/contrib/cygwin/ssh-user-config b/crypto/openssh/contrib/cygwin/ssh-user-config index 8708b7a..33dc0cb 100644 --- a/crypto/openssh/contrib/cygwin/ssh-user-config +++ b/crypto/openssh/contrib/cygwin/ssh-user-config @@ -1,6 +1,6 @@ #!/bin/bash # -# ssh-user-config, Copyright 2000-2008 Red Hat Inc. +# ssh-user-config, Copyright 2000-2014 Red Hat Inc. # # This file is part of the Cygwin port of OpenSSH. # @@ -75,19 +75,18 @@ readonly -f create_identity # pwdhome # ====================================================================== check_user_homedir() { - local uid=$(id -u) - pwdhome=$(awk -F: '{ if ( $3 == '${uid}' ) print $6; }' < ${SYSCONFDIR}/passwd) + pwdhome=$(getent passwd $UID | awk -F: '{ print $6; }') if [ "X${pwdhome}" = "X" ] then csih_error_multi \ - "There is no home directory set for you in ${SYSCONFDIR}/passwd." \ + "There is no home directory set for you in the account database." \ 'Setting $HOME is not sufficient!' fi if [ ! -d "${pwdhome}" ] then csih_error_multi \ - "${pwdhome} is set in ${SYSCONFDIR}/passwd as your home directory" \ + "${pwdhome} is set in the account database as your home directory" \ 'but it is not a valid directory. Cannot create user identity files.' fi @@ -96,7 +95,7 @@ check_user_homedir() { if [ "X${pwdhome}" = "X/" ] then # But first raise a warning! - csih_warning "Your home directory in ${SYSCONFDIR}/passwd is set to root (/). This is not recommended!" + csih_warning "Your home directory in the account database is set to root (/). This is not recommended!" if csih_request "Would you like to proceed anyway?" then pwdhome='' @@ -106,7 +105,7 @@ check_user_homedir() { fi fi - if [ -d "${pwdhome}" -a csih_is_nt -a -n "`chmod -c g-w,o-w "${pwdhome}"`" ] + if [ -d "${pwdhome}" -a -n "`chmod -c g-w,o-w "${pwdhome}"`" ] then echo csih_warning 'group and other have been revoked write permission to your home' @@ -149,9 +148,10 @@ readonly -f check_user_dot_ssh_dir # pwdhome -- check_user_homedir() # ====================================================================== fix_authorized_keys_perms() { - if [ csih_is_nt -a -e "${pwdhome}/.ssh/authorized_keys" ] + if [ -e "${pwdhome}/.ssh/authorized_keys" ] then - if ! setfacl -m "u::rw-,g::---,o::---" "${pwdhome}/.ssh/authorized_keys" + setfacl -b "${pwdhome}/.ssh/authorized_keys" 2>/dev/null || echo -n + if ! chmod u-x,g-wx,o-wx "${pwdhome}/.ssh/authorized_keys" then csih_warning "Setting correct permissions to ${pwdhome}/.ssh/authorized_keys" csih_warning "failed. Please care for the correct permissions. The minimum requirement" @@ -243,15 +243,6 @@ done # Action! # ====================================================================== -# Check passwd file -if [ ! -f ${SYSCONFDIR}/passwd ] -then - csih_error_multi \ - "${SYSCONFDIR}/passwd is nonexistant. Please generate an ${SYSCONFDIR}/passwd file" \ - 'first using mkpasswd. Check if it contains an entry for you and' \ - 'please care for the home directory in your entry as well.' -fi - check_user_homedir check_user_dot_ssh_dir create_identity id_rsa rsa "SSH2 RSA" diff --git a/crypto/openssh/contrib/redhat/openssh.spec b/crypto/openssh/contrib/redhat/openssh.spec index 96401c6..4c55227 100644 --- a/crypto/openssh/contrib/redhat/openssh.spec +++ b/crypto/openssh/contrib/redhat/openssh.spec @@ -1,4 +1,4 @@ -%define ver 6.6p1 +%define ver 7.1p2 %define rel 1 # OpenSSH privilege separation requires a user & group ID @@ -86,7 +86,7 @@ PreReq: initscripts >= 5.00 %else Requires: initscripts >= 5.20 %endif -BuildRequires: perl, openssl-devel, tcp_wrappers +BuildRequires: perl, openssl-devel BuildRequires: /bin/login %if ! %{build6x} BuildPreReq: glibc-devel, pam @@ -192,7 +192,6 @@ echo K5DIR=$K5DIR --sysconfdir=%{_sysconfdir}/ssh \ --libexecdir=%{_libexecdir}/openssh \ --datadir=%{_datadir}/openssh \ - --with-tcp-wrappers \ --with-rsh=%{_bindir}/rsh \ --with-default-path=/usr/local/bin:/bin:/usr/bin \ --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ diff --git a/crypto/openssh/contrib/suse/openssh.spec b/crypto/openssh/contrib/suse/openssh.spec index 0515d6d..3ee5268 100644 --- a/crypto/openssh/contrib/suse/openssh.spec +++ b/crypto/openssh/contrib/suse/openssh.spec @@ -13,7 +13,7 @@ Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh -Version: 6.6p1 +Version: 7.1p2 URL: http://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz @@ -28,11 +28,9 @@ Provides: ssh # (Build[ing] Prereq[uisites] only work for RPM 2.95 and newer.) # building prerequisites -- stuff for # OpenSSL (openssl-devel), -# TCP Wrappers (tcpd-devel), # and Gnome (glibdev, gtkdev, and gnlibsd) # BuildPrereq: openssl -BuildPrereq: tcpd-devel BuildPrereq: zlib-devel #BuildPrereq: glibdev #BuildPrereq: gtkdev @@ -140,7 +138,6 @@ CFLAGS="$RPM_OPT_FLAGS" \ --mandir=%{_mandir} \ --with-privsep-path=/var/lib/empty \ --with-pam \ - --with-tcp-wrappers \ --libexecdir=%{_libdir}/ssh make diff --git a/crypto/openssh/deattack.c b/crypto/openssh/deattack.c index 1b37e4d..e76481a 100644 --- a/crypto/openssh/deattack.c +++ b/crypto/openssh/deattack.c @@ -1,4 +1,4 @@ -/* $OpenBSD: deattack.c,v 1.30 2006/09/16 19:53:37 djm Exp $ */ +/* $OpenBSD: deattack.c,v 1.32 2015/01/20 23:14:00 deraadt Exp $ */ /* * Cryptographic attack detector for ssh - source code * @@ -20,16 +20,13 @@ #include "includes.h" -#include - #include #include -#include +#include -#include "xmalloc.h" #include "deattack.h" -#include "log.h" #include "crc32.h" +#include "sshbuf.h" #include "misc.h" /* @@ -66,7 +63,7 @@ /* Hash function (Input keys are cipher results) */ -#define HASH(x) get_u32(x) +#define HASH(x) PEEK_U32(x) #define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE)) @@ -79,10 +76,10 @@ crc_update(u_int32_t *a, u_int32_t b) /* detect if a block is used in a particular pattern */ static int -check_crc(u_char *S, u_char *buf, u_int32_t len) +check_crc(const u_char *S, const u_char *buf, u_int32_t len) { u_int32_t crc; - u_char *c; + const u_char *c; crc = 0; for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) { @@ -94,36 +91,44 @@ check_crc(u_char *S, u_char *buf, u_int32_t len) crc_update(&crc, 0); } } - return (crc == 0); + return crc == 0; } +void +deattack_init(struct deattack_ctx *dctx) +{ + bzero(dctx, sizeof(*dctx)); + dctx->n = HASH_MINSIZE / HASH_ENTRYSIZE; +} /* Detect a crc32 compensation attack on a packet */ int -detect_attack(u_char *buf, u_int32_t len) +detect_attack(struct deattack_ctx *dctx, const u_char *buf, u_int32_t len) { - static u_int16_t *h = (u_int16_t *) NULL; - static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE; - u_int32_t i, j; - u_int32_t l, same; - u_char *c; - u_char *d; + u_int32_t i, j, l, same; + u_int16_t *tmp; + const u_char *c, *d; if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) || - len % SSH_BLOCKSIZE != 0) { - fatal("detect_attack: bad length %d", len); - } - for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2) + len % SSH_BLOCKSIZE != 0) + return DEATTACK_ERROR; + for (l = dctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2) ; - if (h == NULL) { - debug("Installing crc compensation attack detector."); - h = (u_int16_t *) xcalloc(l, HASH_ENTRYSIZE); - n = l; + if (dctx->h == NULL) { + if ((dctx->h = calloc(l, HASH_ENTRYSIZE)) == NULL) + return DEATTACK_ERROR; + dctx->n = l; } else { - if (l > n) { - h = (u_int16_t *)xrealloc(h, l, HASH_ENTRYSIZE); - n = l; + if (l > dctx->n) { + if ((tmp = reallocarray(dctx->h, l, HASH_ENTRYSIZE)) + == NULL) { + free(dctx->h); + dctx->h = NULL; + return DEATTACK_ERROR; + } + dctx->h = tmp; + dctx->n = l; } } @@ -132,29 +137,29 @@ detect_attack(u_char *buf, u_int32_t len) for (d = buf; d < c; d += SSH_BLOCKSIZE) { if (!CMP(c, d)) { if ((check_crc(c, buf, len))) - return (DEATTACK_DETECTED); + return DEATTACK_DETECTED; else break; } } } - return (DEATTACK_OK); + return DEATTACK_OK; } - memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE); + memset(dctx->h, HASH_UNUSEDCHAR, dctx->n * HASH_ENTRYSIZE); for (c = buf, same = j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) { - for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED; - i = (i + 1) & (n - 1)) { - if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) { + for (i = HASH(c) & (dctx->n - 1); dctx->h[i] != HASH_UNUSED; + i = (i + 1) & (dctx->n - 1)) { + if (!CMP(c, buf + dctx->h[i] * SSH_BLOCKSIZE)) { if (++same > MAX_IDENTICAL) - return (DEATTACK_DOS_DETECTED); + return DEATTACK_DOS_DETECTED; if (check_crc(c, buf, len)) - return (DEATTACK_DETECTED); + return DEATTACK_DETECTED; else break; } } - h[i] = j; + dctx->h[i] = j; } - return (DEATTACK_OK); + return DEATTACK_OK; } diff --git a/crypto/openssh/deattack.h b/crypto/openssh/deattack.h index 0316fb2..ce67a30 100644 --- a/crypto/openssh/deattack.h +++ b/crypto/openssh/deattack.h @@ -1,4 +1,4 @@ -/* $OpenBSD: deattack.h,v 1.10 2006/09/16 19:53:37 djm Exp $ */ +/* $OpenBSD: deattack.h,v 1.11 2015/01/19 19:52:16 markus Exp $ */ /* * Cryptographic attack detector for ssh - Header file @@ -26,6 +26,13 @@ #define DEATTACK_OK 0 #define DEATTACK_DETECTED 1 #define DEATTACK_DOS_DETECTED 2 +#define DEATTACK_ERROR 3 -int detect_attack(u_char *, u_int32_t); +struct deattack_ctx { + u_int16_t *h; + u_int32_t n; +}; + +void deattack_init(struct deattack_ctx *); +int detect_attack(struct deattack_ctx *, const u_char *, u_int32_t); #endif diff --git a/crypto/openssh/defines.h b/crypto/openssh/defines.h index 354d5b6..fa0ccba 100644 --- a/crypto/openssh/defines.h +++ b/crypto/openssh/defines.h @@ -25,7 +25,7 @@ #ifndef _DEFINES_H #define _DEFINES_H -/* $Id: defines.h,v 1.176 2014/01/17 13:12:38 dtucker Exp $ */ +/* $Id: defines.h,v 1.183 2014/09/02 19:33:26 djm Exp $ */ /* Constants */ @@ -105,6 +105,17 @@ enum # endif /* PATH_MAX */ #endif /* MAXPATHLEN */ +#ifndef HOST_NAME_MAX +# include "netdb.h" /* for MAXHOSTNAMELEN */ +# if defined(_POSIX_HOST_NAME_MAX) +# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX +# elif defined(MAXHOSTNAMELEN) +# define HOST_NAME_MAX MAXHOSTNAMELEN +# else +# define HOST_NAME_MAX 255 +# endif +#endif /* HOST_NAME_MAX */ + #if defined(HAVE_DECL_MAXSYMLINKS) && HAVE_DECL_MAXSYMLINKS == 0 # define MAXSYMLINKS 5 #endif @@ -405,7 +416,7 @@ struct winsize { /* user may have set a different path */ #if defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) -# undef _PATH_MAILDIR MAILDIR +# undef _PATH_MAILDIR #endif /* defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) */ #ifdef MAIL_DIRECTORY @@ -586,6 +597,12 @@ struct winsize { # undef HAVE_GAI_STRERROR #endif +#if defined(HAVE_GETADDRINFO) +# if defined(HAVE_DECL_AI_NUMERICSERV) && HAVE_DECL_AI_NUMERICSERV == 0 +# define AI_NUMERICSERV 0 +# endif +#endif + #if defined(BROKEN_UPDWTMPX) && defined(HAVE_UPDWTMPX) # undef HAVE_UPDWTMPX #endif @@ -603,10 +620,6 @@ struct winsize { # define memmove(s1, s2, n) bcopy((s2), (s1), (n)) #endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ -#if defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) -# define USE_VHANGUP -#endif /* defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) */ - #ifndef GETPGRP_VOID # include # define getpgrp() getpgrp(0) @@ -809,14 +822,6 @@ struct winsize { # define SSH_IOBUFSZ 8192 #endif -#ifndef _NSIG -# ifdef NSIG -# define _NSIG NSIG -# else -# define _NSIG 128 -# endif -#endif - /* * Platforms that have arc4random_uniform() and not arc4random_stir() * shouldn't need the latter. @@ -826,4 +831,23 @@ struct winsize { # define arc4random_stir() #endif +#ifndef HAVE_VA_COPY +# ifdef HAVE___VA_COPY +# define va_copy(dest, src) __va_copy(dest, src) +# else +# define va_copy(dest, src) (dest) = (src) +# endif +#endif + +#ifndef __predict_true +# if defined(__GNUC__) && \ + ((__GNUC__ > (2)) || (__GNUC__ == (2) && __GNUC_MINOR__ >= (96))) +# define __predict_true(exp) __builtin_expect(((exp) != 0), 1) +# define __predict_false(exp) __builtin_expect(((exp) != 0), 0) +# else +# define __predict_true(exp) ((exp) != 0) +# define __predict_false(exp) ((exp) != 0) +# endif /* gcc version */ +#endif /* __predict_true */ + #endif /* _DEFINES_H */ diff --git a/crypto/openssh/dh.c b/crypto/openssh/dh.c index 3331cda..4c639ac 100644 --- a/crypto/openssh/dh.c +++ b/crypto/openssh/dh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh.c,v 1.53 2013/11/21 00:45:44 djm Exp $ */ +/* $OpenBSD: dh.c,v 1.57 2015/05/27 23:39:18 dtucker Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * @@ -25,7 +25,7 @@ #include "includes.h" -#include +#include /* MIN */ #include #include @@ -34,11 +34,13 @@ #include #include #include +#include #include "dh.h" #include "pathnames.h" #include "log.h" #include "misc.h" +#include "ssherr.h" static int parse_prime(int linenum, char *line, struct dhgroup *dhg) @@ -107,10 +109,11 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) goto fail; } - if ((dhg->g = BN_new()) == NULL) - fatal("parse_prime: BN_new failed"); - if ((dhg->p = BN_new()) == NULL) - fatal("parse_prime: BN_new failed"); + if ((dhg->g = BN_new()) == NULL || + (dhg->p = BN_new()) == NULL) { + error("parse_prime: BN_new failed"); + goto fail; + } if (BN_hex2bn(&dhg->g, gen) == 0) { error("moduli:%d: could not parse generator value", linenum); goto fail; @@ -128,7 +131,6 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) error("moduli:%d: generator is invalid", linenum); goto fail; } - return 1; fail: @@ -137,7 +139,6 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) if (dhg->p != NULL) BN_clear_free(dhg->p); dhg->g = dhg->p = NULL; - error("Bad prime description in line %d", linenum); return 0; } @@ -154,7 +155,7 @@ choose_dh(int min, int wantbits, int max) (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) { logit("WARNING: %s does not exist, using fixed modulus", _PATH_DH_MODULI); - return (dh_new_group14()); + return (dh_new_group_fallback(max)); } linenum = 0; @@ -182,7 +183,7 @@ choose_dh(int min, int wantbits, int max) if (bestcount == 0) { fclose(f); logit("WARNING: no suitable primes in %s", _PATH_DH_PRIMES); - return (dh_new_group14()); + return (dh_new_group_fallback(max)); } linenum = 0; @@ -200,9 +201,11 @@ choose_dh(int min, int wantbits, int max) break; } fclose(f); - if (linenum != which+1) - fatal("WARNING: line %d disappeared in %s, giving up", + if (linenum != which+1) { + logit("WARNING: line %d disappeared in %s, giving up", which, _PATH_DH_PRIMES); + return (dh_new_group_fallback(max)); + } return (dh_new_group(dhg.g, dhg.p)); } @@ -251,22 +254,22 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) return 0; } -void +int dh_gen_key(DH *dh, int need) { int pbits; - if (need <= 0) - fatal("%s: need <= 0", __func__); - if (dh->p == NULL) - fatal("%s: dh->p == NULL", __func__); - if ((pbits = BN_num_bits(dh->p)) <= 0) - fatal("%s: bits(p) <= 0", __func__); + if (need < 0 || dh->p == NULL || + (pbits = BN_num_bits(dh->p)) <= 0 || + need > INT_MAX / 2 || 2 * need > pbits) + return SSH_ERR_INVALID_ARGUMENT; dh->length = MIN(need * 2, pbits - 1); - if (DH_generate_key(dh) == 0) - fatal("%s: key generation failed", __func__); - if (!dh_pub_is_valid(dh, dh->pub_key)) - fatal("%s: generated invalid key", __func__); + if (DH_generate_key(dh) == 0 || + !dh_pub_is_valid(dh, dh->pub_key)) { + BN_clear_free(dh->priv_key); + return SSH_ERR_LIBCRYPTO_ERROR; + } + return 0; } DH * @@ -275,13 +278,12 @@ dh_new_group_asc(const char *gen, const char *modulus) DH *dh; if ((dh = DH_new()) == NULL) - fatal("dh_new_group_asc: DH_new"); - - if (BN_hex2bn(&dh->p, modulus) == 0) - fatal("BN_hex2bn p"); - if (BN_hex2bn(&dh->g, gen) == 0) - fatal("BN_hex2bn g"); - + return NULL; + if (BN_hex2bn(&dh->p, modulus) == 0 || + BN_hex2bn(&dh->g, gen) == 0) { + DH_free(dh); + return NULL; + } return (dh); } @@ -296,7 +298,7 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus) DH *dh; if ((dh = DH_new()) == NULL) - fatal("dh_new_group: DH_new"); + return NULL; dh->p = modulus; dh->g = gen; @@ -337,6 +339,45 @@ dh_new_group14(void) } /* + * 4k bit fallback group used by DH-GEX if moduli file cannot be read. + * Source: MODP group 16 from RFC3526. + */ +DH * +dh_new_group_fallback(int max) +{ + static char *gen = "2", *group16 = + "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" + "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" + "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D" + "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" + "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" + "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" + "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" + "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" + "15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64" + "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7" + "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B" + "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C" + "BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31" + "43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7" + "88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA" + "2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6" + "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED" + "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9" + "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199" + "FFFFFFFF" "FFFFFFFF"; + + if (max < 4096) { + debug3("requested max size %d, using 2k bit group 14", max); + return dh_new_group14(); + } + debug3("using 4k bit group 16"); + return (dh_new_group_asc(gen, group16)); +} + +/* * Estimates the group order for a Diffie-Hellman group that has an * attack complexity approximately the same as O(2**bits). * Values from NIST Special Publication 800-57: Recommendation for Key @@ -344,7 +385,7 @@ dh_new_group14(void) * from RFC4419 section 3. */ -int +u_int dh_estimate(int bits) { if (bits <= 112) diff --git a/crypto/openssh/dh.h b/crypto/openssh/dh.h index 48f7b68..6546953 100644 --- a/crypto/openssh/dh.h +++ b/crypto/openssh/dh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dh.h,v 1.11 2013/10/08 11:42:13 dtucker Exp $ */ +/* $OpenBSD: dh.h,v 1.13 2015/05/27 23:39:18 dtucker Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. @@ -37,11 +37,12 @@ DH *dh_new_group_asc(const char *, const char *); DH *dh_new_group(BIGNUM *, BIGNUM *); DH *dh_new_group1(void); DH *dh_new_group14(void); +DH *dh_new_group_fallback(int); -void dh_gen_key(DH *, int); +int dh_gen_key(DH *, int); int dh_pub_is_valid(DH *, BIGNUM *); -int dh_estimate(int); +u_int dh_estimate(int); /* Min and max values from RFC4419. */ #define DH_GRP_MIN 1024 diff --git a/crypto/openssh/digest-libc.c b/crypto/openssh/digest-libc.c index 9377c77..40db002 100644 --- a/crypto/openssh/digest-libc.c +++ b/crypto/openssh/digest-libc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-libc.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: digest-libc.c,v 1.5 2015/05/05 02:48:17 jsg Exp $ */ /* * Copyright (c) 2013 Damien Miller * Copyright (c) 2014 Markus Friedl. All rights reserved. @@ -18,17 +18,22 @@ #include "includes.h" +#ifndef WITH_OPENSSL + #include #include #include #include +#if 0 #include #include #include #include +#endif -#include "buffer.h" +#include "ssherr.h" +#include "sshbuf.h" #include "digest.h" typedef void md_init_fn(void *mdctx); @@ -88,30 +93,30 @@ const struct ssh_digest digests[SSH_DIGEST_MAX] = { "SHA256", SHA256_BLOCK_LENGTH, SHA256_DIGEST_LENGTH, - sizeof(SHA2_CTX), - (md_init_fn *) SHA256Init, - (md_update_fn *) SHA256Update, - (md_final_fn *) SHA256Final + sizeof(SHA256_CTX), + (md_init_fn *) SHA256_Init, + (md_update_fn *) SHA256_Update, + (md_final_fn *) SHA256_Final }, { SSH_DIGEST_SHA384, "SHA384", SHA384_BLOCK_LENGTH, SHA384_DIGEST_LENGTH, - sizeof(SHA2_CTX), - (md_init_fn *) SHA384Init, - (md_update_fn *) SHA384Update, - (md_final_fn *) SHA384Final + sizeof(SHA384_CTX), + (md_init_fn *) SHA384_Init, + (md_update_fn *) SHA384_Update, + (md_final_fn *) SHA384_Final }, { SSH_DIGEST_SHA512, "SHA512", SHA512_BLOCK_LENGTH, SHA512_DIGEST_LENGTH, - sizeof(SHA2_CTX), - (md_init_fn *) SHA512Init, - (md_update_fn *) SHA512Update, - (md_final_fn *) SHA512Final + sizeof(SHA512_CTX), + (md_init_fn *) SHA512_Init, + (md_update_fn *) SHA512_Update, + (md_final_fn *) SHA512_Final } }; @@ -125,6 +130,26 @@ ssh_digest_by_alg(int alg) return &(digests[alg]); } +int +ssh_digest_alg_by_name(const char *name) +{ + int alg; + + for (alg = 0; alg < SSH_DIGEST_MAX; alg++) { + if (strcasecmp(name, digests[alg].name) == 0) + return digests[alg].id; + } + return -1; +} + +const char * +ssh_digest_alg_name(int alg) +{ + const struct ssh_digest *digest = ssh_digest_by_alg(alg); + + return digest == NULL ? NULL : digest->name; +} + size_t ssh_digest_bytes(int alg) { @@ -164,7 +189,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) const struct ssh_digest *digest = ssh_digest_by_alg(from->alg); if (digest == NULL || from->alg != to->alg) - return -1; + return SSH_ERR_INVALID_ARGUMENT; memcpy(to->mdctx, from->mdctx, digest->ctx_len); return 0; } @@ -175,15 +200,15 @@ ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); if (digest == NULL) - return -1; + return SSH_ERR_INVALID_ARGUMENT; digest->md_update(ctx->mdctx, m, mlen); return 0; } int -ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b) +ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b) { - return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b)); + return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b)); } int @@ -192,11 +217,11 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); if (digest == NULL) - return -1; + return SSH_ERR_INVALID_ARGUMENT; if (dlen > UINT_MAX) - return -1; + return SSH_ERR_INVALID_ARGUMENT; if (dlen < digest->digest_len) /* No truncation allowed */ - return -1; + return SSH_ERR_INVALID_ARGUMENT; digest->md_final(d, ctx->mdctx); return 0; } @@ -223,16 +248,17 @@ ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) struct ssh_digest_ctx *ctx = ssh_digest_start(alg); if (ctx == NULL) - return -1; + return SSH_ERR_INVALID_ARGUMENT; if (ssh_digest_update(ctx, m, mlen) != 0 || ssh_digest_final(ctx, d, dlen) != 0) - return -1; + return SSH_ERR_INVALID_ARGUMENT; ssh_digest_free(ctx); return 0; } int -ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) +ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) { - return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen); + return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen); } +#endif /* !WITH_OPENSSL */ diff --git a/crypto/openssh/digest-openssl.c b/crypto/openssh/digest-openssl.c index 863d37d..13b63c2 100644 --- a/crypto/openssh/digest-openssl.c +++ b/crypto/openssh/digest-openssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-openssl.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: digest-openssl.c,v 1.5 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -17,6 +17,8 @@ #include "includes.h" +#ifdef WITH_OPENSSL + #include #include #include @@ -26,8 +28,18 @@ #include "openbsd-compat/openssl-compat.h" -#include "buffer.h" +#include "sshbuf.h" #include "digest.h" +#include "ssherr.h" + +#ifndef HAVE_EVP_RIPEMD160 +# define EVP_ripemd160 NULL +#endif /* HAVE_EVP_RIPEMD160 */ +#ifndef HAVE_EVP_SHA256 +# define EVP_sha256 NULL +# define EVP_sha384 NULL +# define EVP_sha512 NULL +#endif /* HAVE_EVP_SHA256 */ struct ssh_digest_ctx { int alg; @@ -46,11 +58,9 @@ const struct ssh_digest digests[] = { { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, { SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 }, { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, -#ifdef HAVE_EVP_SHA256 /* XXX replace with local if missing */ { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, -#endif { -1, NULL, 0, NULL }, }; @@ -61,9 +71,31 @@ ssh_digest_by_alg(int alg) return NULL; if (digests[alg].id != alg) /* sanity */ return NULL; + if (digests[alg].mdfunc == NULL) + return NULL; return &(digests[alg]); } +int +ssh_digest_alg_by_name(const char *name) +{ + int alg; + + for (alg = 0; digests[alg].id != -1; alg++) { + if (strcasecmp(name, digests[alg].name) == 0) + return digests[alg].id; + } + return -1; +} + +const char * +ssh_digest_alg_name(int alg) +{ + const struct ssh_digest *digest = ssh_digest_by_alg(alg); + + return digest == NULL ? NULL : digest->name; +} + size_t ssh_digest_bytes(int alg) { @@ -98,9 +130,11 @@ ssh_digest_start(int alg) int ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) { + if (from->alg != to->alg) + return SSH_ERR_INVALID_ARGUMENT; /* we have bcopy-style order while openssl has memcpy-style */ if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx)) - return -1; + return SSH_ERR_LIBCRYPTO_ERROR; return 0; } @@ -108,14 +142,14 @@ int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) { if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) - return -1; + return SSH_ERR_LIBCRYPTO_ERROR; return 0; } int -ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b) +ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b) { - return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b)); + return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b)); } int @@ -125,13 +159,13 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) u_int l = dlen; if (dlen > UINT_MAX) - return -1; + return SSH_ERR_INVALID_ARGUMENT; if (dlen < digest->digest_len) /* No truncation allowed */ - return -1; + return SSH_ERR_INVALID_ARGUMENT; if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1) - return -1; + return SSH_ERR_LIBCRYPTO_ERROR; if (l != digest->digest_len) /* sanity */ - return -1; + return SSH_ERR_INTERNAL_ERROR; return 0; } @@ -148,19 +182,24 @@ ssh_digest_free(struct ssh_digest_ctx *ctx) int ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) { - struct ssh_digest_ctx *ctx = ssh_digest_start(alg); - - if (ctx == NULL) - return -1; - if (ssh_digest_update(ctx, m, mlen) != 0 || - ssh_digest_final(ctx, d, dlen) != 0) - return -1; - ssh_digest_free(ctx); + const struct ssh_digest *digest = ssh_digest_by_alg(alg); + u_int mdlen; + + if (digest == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if (dlen > UINT_MAX) + return SSH_ERR_INVALID_ARGUMENT; + if (dlen < digest->digest_len) + return SSH_ERR_INVALID_ARGUMENT; + mdlen = dlen; + if (!EVP_Digest(m, mlen, d, &mdlen, digest->mdfunc(), NULL)) + return SSH_ERR_LIBCRYPTO_ERROR; return 0; } int -ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) +ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) { - return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen); + return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen); } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/digest.h b/crypto/openssh/digest.h index 0fb207f..3fe0734 100644 --- a/crypto/openssh/digest.h +++ b/crypto/openssh/digest.h @@ -1,4 +1,4 @@ -/* $OpenBSD: digest.h,v 1.2 2014/01/27 18:58:14 markus Exp $ */ +/* $OpenBSD: digest.h,v 1.7 2014/12/21 22:27:56 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -30,8 +30,15 @@ #define SSH_DIGEST_SHA512 5 #define SSH_DIGEST_MAX 6 +struct sshbuf; struct ssh_digest_ctx; +/* Looks up a digest algorithm by name */ +int ssh_digest_alg_by_name(const char *name); + +/* Returns the algorithm name for a digest identifier */ +const char *ssh_digest_alg_name(int alg); + /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ size_t ssh_digest_bytes(int alg); @@ -47,14 +54,15 @@ int ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) __attribute__((__bounded__(__buffer__, 2, 3))) __attribute__((__bounded__(__buffer__, 4, 5))); -int ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) +int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen) __attribute__((__bounded__(__buffer__, 3, 4))); /* Update API */ struct ssh_digest_ctx *ssh_digest_start(int alg); int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) __attribute__((__bounded__(__buffer__, 2, 3))); -int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b); +int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, + const struct sshbuf *b); int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) __attribute__((__bounded__(__buffer__, 2, 3))); void ssh_digest_free(struct ssh_digest_ctx *ctx); diff --git a/crypto/openssh/dispatch.c b/crypto/openssh/dispatch.c index 64bb809..aac933e 100644 --- a/crypto/openssh/dispatch.c +++ b/crypto/openssh/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.22 2008/10/31 15:05:34 stevesk Exp $ */ +/* $OpenBSD: dispatch.c,v 1.27 2015/05/01 07:10:01 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -36,69 +36,107 @@ #include "dispatch.h" #include "packet.h" #include "compat.h" +#include "ssherr.h" -#define DISPATCH_MAX 255 - -dispatch_fn *dispatch[DISPATCH_MAX]; - -void -dispatch_protocol_error(int type, u_int32_t seq, void *ctxt) +int +dispatch_protocol_error(int type, u_int32_t seq, void *ctx) { + struct ssh *ssh = active_state; /* XXX */ + int r; + logit("dispatch_protocol_error: type %d seq %u", type, seq); if (!compat20) fatal("protocol error"); - packet_start(SSH2_MSG_UNIMPLEMENTED); - packet_put_int(seq); - packet_send(); - packet_write_wait(); + if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || + (r = sshpkt_put_u32(ssh, seq)) != 0 || + (r = sshpkt_send(ssh)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + sshpkt_fatal(ssh, __func__, r); + return 0; } -void -dispatch_protocol_ignore(int type, u_int32_t seq, void *ctxt) + +int +dispatch_protocol_ignore(int type, u_int32_t seq, void *ssh) { logit("dispatch_protocol_ignore: type %d seq %u", type, seq); + return 0; } + void -dispatch_init(dispatch_fn *dflt) +ssh_dispatch_init(struct ssh *ssh, dispatch_fn *dflt) { u_int i; for (i = 0; i < DISPATCH_MAX; i++) - dispatch[i] = dflt; + ssh->dispatch[i] = dflt; } + void -dispatch_range(u_int from, u_int to, dispatch_fn *fn) +ssh_dispatch_range(struct ssh *ssh, u_int from, u_int to, dispatch_fn *fn) { u_int i; for (i = from; i <= to; i++) { if (i >= DISPATCH_MAX) break; - dispatch[i] = fn; + ssh->dispatch[i] = fn; } } + void -dispatch_set(int type, dispatch_fn *fn) +ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn) { - dispatch[type] = fn; + ssh->dispatch[type] = fn; } -void -dispatch_run(int mode, volatile sig_atomic_t *done, void *ctxt) + +int +ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, + void *ctxt) { - for (;;) { - int type; - u_int32_t seqnr; + int r; + u_char type; + u_int32_t seqnr; + for (;;) { if (mode == DISPATCH_BLOCK) { - type = packet_read_seqnr(&seqnr); + r = ssh_packet_read_seqnr(ssh, &type, &seqnr); + if (r != 0) + return r; } else { - type = packet_read_poll_seqnr(&seqnr); + r = ssh_packet_read_poll_seqnr(ssh, &type, &seqnr); + if (r != 0) + return r; if (type == SSH_MSG_NONE) - return; + return 0; + } + if (type > 0 && type < DISPATCH_MAX && + ssh->dispatch[type] != NULL) { + if (ssh->dispatch_skip_packets) { + debug2("skipped packet (type %u)", type); + ssh->dispatch_skip_packets--; + continue; + } + /* XXX 'ssh' will replace 'ctxt' later */ + r = (*ssh->dispatch[type])(type, seqnr, ctxt); + if (r != 0) + return r; + } else { + r = sshpkt_disconnect(ssh, + "protocol error: rcvd type %d", type); + if (r != 0) + return r; + return SSH_ERR_DISCONNECTED; } - if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL) - (*dispatch[type])(type, seqnr, ctxt); - else - packet_disconnect("protocol error: rcvd type %d", type); if (done != NULL && *done) - return; + return 0; } } + +void +ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done, + void *ctxt) +{ + int r; + + if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0) + sshpkt_fatal(ssh, __func__, r); +} diff --git a/crypto/openssh/dispatch.h b/crypto/openssh/dispatch.h index 3e3d1a1..cd51dbc 100644 --- a/crypto/openssh/dispatch.h +++ b/crypto/openssh/dispatch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.h,v 1.11 2006/04/20 09:27:09 djm Exp $ */ +/* $OpenBSD: dispatch.h,v 1.12 2015/01/19 20:07:45 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -24,18 +24,35 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#ifndef DISPATCH_H +#define DISPATCH_H + +#define DISPATCH_MAX 255 enum { DISPATCH_BLOCK, DISPATCH_NONBLOCK }; -typedef void dispatch_fn(int, u_int32_t, void *); +struct ssh; + +typedef int dispatch_fn(int, u_int32_t, void *); + +int dispatch_protocol_error(int, u_int32_t, void *); +int dispatch_protocol_ignore(int, u_int32_t, void *); +void ssh_dispatch_init(struct ssh *, dispatch_fn *); +void ssh_dispatch_set(struct ssh *, int, dispatch_fn *); +void ssh_dispatch_range(struct ssh *, u_int, u_int, dispatch_fn *); +int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *, void *); +void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *); + +#define dispatch_init(dflt) \ + ssh_dispatch_init(active_state, (dflt)) +#define dispatch_range(from, to, fn) \ + ssh_dispatch_range(active_state, (from), (to), (fn)) +#define dispatch_set(type, fn) \ + ssh_dispatch_set(active_state, (type), (fn)) +#define dispatch_run(mode, done, ctxt) \ + ssh_dispatch_run_fatal(active_state, (mode), (done), (ctxt)) -void dispatch_init(dispatch_fn *); -void dispatch_set(int, dispatch_fn *); -void dispatch_range(u_int, u_int, dispatch_fn *); -void dispatch_run(int, volatile sig_atomic_t *, void *); -void dispatch_protocol_error(int, u_int32_t, void *); -void dispatch_protocol_ignore(int, u_int32_t, void *); +#endif diff --git a/crypto/openssh/dns.c b/crypto/openssh/dns.c index 630b97a..e813afe 100644 --- a/crypto/openssh/dns.c +++ b/crypto/openssh/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.29 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: dns.c,v 1.35 2015/08/20 22:32:42 deraadt Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -34,11 +34,15 @@ #include #include #include +#include +#include #include "xmalloc.h" -#include "key.h" +#include "sshkey.h" +#include "ssherr.h" #include "dns.h" #include "log.h" +#include "digest.h" static const char *errset_text[] = { "success", /* 0 ERRSET_SUCCESS */ @@ -75,10 +79,10 @@ dns_result_totext(unsigned int res) */ static int dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, - u_char **digest, u_int *digest_len, Key *key) + u_char **digest, size_t *digest_len, struct sshkey *key) { - int success = 0; - enum fp_type fp_type = 0; + int r, success = 0; + int fp_alg = -1; switch (key->type) { case KEY_RSA: @@ -96,6 +100,11 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, if (!*digest_type) *digest_type = SSHFP_HASH_SHA256; break; + case KEY_ED25519: + *algorithm = SSHFP_KEY_ED25519; + if (!*digest_type) + *digest_type = SSHFP_HASH_SHA256; + break; default: *algorithm = SSHFP_KEY_RESERVED; /* 0 */ *digest_type = SSHFP_HASH_RESERVED; /* 0 */ @@ -103,19 +112,20 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, switch (*digest_type) { case SSHFP_HASH_SHA1: - fp_type = SSH_FP_SHA1; + fp_alg = SSH_DIGEST_SHA1; break; case SSHFP_HASH_SHA256: - fp_type = SSH_FP_SHA256; + fp_alg = SSH_DIGEST_SHA256; break; default: *digest_type = SSHFP_HASH_RESERVED; /* 0 */ } if (*algorithm && *digest_type) { - *digest = key_fingerprint_raw(key, fp_type, digest_len); - if (*digest == NULL) - fatal("dns_read_key: null from key_fingerprint_raw()"); + if ((r = sshkey_fingerprint_raw(key, fp_alg, digest, + digest_len)) != 0) + fatal("%s: sshkey_fingerprint_raw: %s", __func__, + ssh_err(r)); success = 1; } else { *digest = NULL; @@ -131,7 +141,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, */ static int dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type, - u_char **digest, u_int *digest_len, u_char *rdata, int rdata_len) + u_char **digest, size_t *digest_len, u_char *rdata, int rdata_len) { int success = 0; @@ -144,7 +154,7 @@ dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type, *digest_len = rdata_len - 2; if (*digest_len > 0) { - *digest = (u_char *) xmalloc(*digest_len); + *digest = xmalloc(*digest_len); memcpy(*digest, rdata + 2, *digest_len); } else { *digest = (u_char *)xstrdup(""); @@ -192,7 +202,7 @@ is_numeric_hostname(const char *hostname) */ int verify_host_key_dns(const char *hostname, struct sockaddr *address, - Key *hostkey, int *flags) + struct sshkey *hostkey, int *flags) { u_int counter; int result; @@ -201,12 +211,12 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, u_int8_t hostkey_algorithm; u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED; u_char *hostkey_digest; - u_int hostkey_digest_len; + size_t hostkey_digest_len; u_int8_t dnskey_algorithm; u_int8_t dnskey_digest_type; u_char *dnskey_digest; - u_int dnskey_digest_len; + size_t dnskey_digest_len; *flags = 0; @@ -284,7 +294,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, free(dnskey_digest); } - free(hostkey_digest); /* from key_fingerprint_raw() */ + free(hostkey_digest); /* from sshkey_fingerprint_raw() */ freerrset(fingerprints); if (*flags & DNS_VERIFY_FOUND) @@ -302,13 +312,13 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, * Export the fingerprint of a key as a DNS resource record */ int -export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) +export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic) { u_int8_t rdata_pubkey_algorithm = 0; u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED; u_int8_t dtype; u_char *rdata_digest; - u_int i, rdata_digest_len; + size_t i, rdata_digest_len; int success = 0; for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) { @@ -316,7 +326,7 @@ export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type, &rdata_digest, &rdata_digest_len, key)) { if (generic) { - fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", + fprintf(f, "%s IN TYPE%d \\# %zu %02x %02x ", hostname, DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len, rdata_pubkey_algorithm, rdata_digest_type); @@ -327,7 +337,7 @@ export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) for (i = 0; i < rdata_digest_len; i++) fprintf(f, "%02x", rdata_digest[i]); fprintf(f, "\n"); - free(rdata_digest); /* from key_fingerprint_raw() */ + free(rdata_digest); /* from sshkey_fingerprint_raw() */ success = 1; } } diff --git a/crypto/openssh/dns.h b/crypto/openssh/dns.h index d5f4281..30e2b19 100644 --- a/crypto/openssh/dns.h +++ b/crypto/openssh/dns.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.h,v 1.12 2012/05/23 03:28:28 djm Exp $ */ +/* $OpenBSD: dns.h,v 1.15 2015/05/08 06:45:13 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -32,7 +32,8 @@ enum sshfp_types { SSHFP_KEY_RESERVED = 0, SSHFP_KEY_RSA = 1, SSHFP_KEY_DSA = 2, - SSHFP_KEY_ECDSA = 3 + SSHFP_KEY_ECDSA = 3, + SSHFP_KEY_ED25519 = 4 }; enum sshfp_hashes { @@ -49,7 +50,8 @@ enum sshfp_hashes { #define DNS_VERIFY_MATCH 0x00000002 #define DNS_VERIFY_SECURE 0x00000004 -int verify_host_key_dns(const char *, struct sockaddr *, Key *, int *); -int export_dns_rr(const char *, Key *, FILE *, int); +int verify_host_key_dns(const char *, struct sockaddr *, + struct sshkey *, int *); +int export_dns_rr(const char *, struct sshkey *, FILE *, int); #endif /* DNS_H */ diff --git a/crypto/openssh/entropy.c b/crypto/openssh/entropy.c index 2d483b3..9305f89 100644 --- a/crypto/openssh/entropy.c +++ b/crypto/openssh/entropy.c @@ -24,6 +24,8 @@ #include "includes.h" +#ifdef WITH_OPENSSL + #include #include #ifdef HAVE_SYS_UN_H @@ -43,6 +45,8 @@ #include #include +#include "openbsd-compat/openssl-compat.h" + #include "ssh.h" #include "misc.h" #include "xmalloc.h" @@ -209,16 +213,7 @@ seed_rng(void) #ifndef OPENSSL_PRNG_ONLY unsigned char buf[RANDOM_SEED_SIZE]; #endif - /* - * OpenSSL version numbers: MNNFFPPS: major minor fix patch status - * We match major, minor, fix and status (not patch) for <1.0.0. - * After that, we acceptable compatible fix versions (so we - * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed - * within a patch series. - */ - u_long version_mask = SSLeay() >= 0x1000000f ? ~0xffff0L : ~0xff0L; - if (((SSLeay() ^ OPENSSL_VERSION_NUMBER) & version_mask) || - (SSLeay() >> 12) < (OPENSSL_VERSION_NUMBER >> 12)) + if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, SSLeay())) fatal("OpenSSL version mismatch. Built against %lx, you " "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); @@ -237,3 +232,13 @@ seed_rng(void) if (RAND_status() != 1) fatal("PRNG is not seeded"); } + +#else /* WITH_OPENSSL */ + +/* Handled in arc4random() */ +void +seed_rng(void) +{ +} + +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/ge25519.h b/crypto/openssh/ge25519.h index 64f63c6..a097637 100644 --- a/crypto/openssh/ge25519.h +++ b/crypto/openssh/ge25519.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ge25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */ +/* $OpenBSD: ge25519.h,v 1.4 2015/02/16 18:26:26 miod Exp $ */ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, @@ -28,7 +28,7 @@ typedef struct fe25519 t; } ge25519; -const ge25519 ge25519_base; +extern const ge25519 ge25519_base; int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]); diff --git a/crypto/openssh/groupaccess.c b/crypto/openssh/groupaccess.c index 1eab10b..2518c84 100644 --- a/crypto/openssh/groupaccess.c +++ b/crypto/openssh/groupaccess.c @@ -1,4 +1,4 @@ -/* $OpenBSD: groupaccess.c,v 1.14 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: groupaccess.c,v 1.16 2015/05/04 06:10:48 djm Exp $ */ /* * Copyright (c) 2001 Kevin Steves. All rights reserved. * @@ -26,13 +26,13 @@ #include "includes.h" #include -#include #include #include #include #include #include +#include #include "xmalloc.h" #include "groupaccess.h" @@ -97,11 +97,9 @@ int ga_match_pattern_list(const char *group_pattern) { int i, found = 0; - size_t len = strlen(group_pattern); for (i = 0; i < ngroups; i++) { - switch (match_pattern_list(groups_byname[i], - group_pattern, len, 0)) { + switch (match_pattern_list(groups_byname[i], group_pattern, 0)) { case -1: return 0; /* Negated match wins */ case 0: diff --git a/crypto/openssh/gss-genr.c b/crypto/openssh/gss-genr.c index b39281b..d617d60 100644 --- a/crypto/openssh/gss-genr.c +++ b/crypto/openssh/gss-genr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-genr.c,v 1.22 2013/11/08 00:39:15 djm Exp $ */ +/* $OpenBSD: gss-genr.c,v 1.23 2015/01/20 23:14:00 deraadt Exp $ */ /* * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. @@ -31,8 +31,10 @@ #include #include +#include #include #include +#include #include #include "xmalloc.h" diff --git a/crypto/openssh/gss-serv-krb5.c b/crypto/openssh/gss-serv-krb5.c index 759fa10..795992d 100644 --- a/crypto/openssh/gss-serv-krb5.c +++ b/crypto/openssh/gss-serv-krb5.c @@ -39,6 +39,7 @@ #include "hostfile.h" #include "auth.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "buffer.h" diff --git a/crypto/openssh/gss-serv.c b/crypto/openssh/gss-serv.c index e61b37b..53993d6 100644 --- a/crypto/openssh/gss-serv.c +++ b/crypto/openssh/gss-serv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-serv.c,v 1.26 2014/02/26 20:28:44 djm Exp $ */ +/* $OpenBSD: gss-serv.c,v 1.29 2015/05/22 03:50:02 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -29,7 +29,6 @@ #ifdef GSSAPI #include -#include #include #include @@ -45,9 +44,12 @@ #include "channels.h" #include "session.h" #include "misc.h" +#include "servconf.h" #include "ssh-gss.h" +extern ServerOptions options; + static ssh_gssapi_client gssapi_client = { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; @@ -97,28 +99,35 @@ static OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx) { OM_uint32 status; - char lname[MAXHOSTNAMELEN]; + char lname[NI_MAXHOST]; gss_OID_set oidset; - gss_create_empty_oid_set(&status, &oidset); - gss_add_oid_set_member(&status, ctx->oid, &oidset); + if (options.gss_strict_acceptor) { + gss_create_empty_oid_set(&status, &oidset); + gss_add_oid_set_member(&status, ctx->oid, &oidset); - if (gethostname(lname, MAXHOSTNAMELEN)) { - gss_release_oid_set(&status, &oidset); - return (-1); - } + if (gethostname(lname, MAXHOSTNAMELEN)) { + gss_release_oid_set(&status, &oidset); + return (-1); + } + + if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { + gss_release_oid_set(&status, &oidset); + return (ctx->major); + } + + if ((ctx->major = gss_acquire_cred(&ctx->minor, + ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, + NULL, NULL))) + ssh_gssapi_error(ctx); - if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { gss_release_oid_set(&status, &oidset); return (ctx->major); + } else { + ctx->name = GSS_C_NO_NAME; + ctx->creds = GSS_C_NO_CREDENTIAL; } - - if ((ctx->major = gss_acquire_cred(&ctx->minor, - ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) - ssh_gssapi_error(ctx); - - gss_release_oid_set(&status, &oidset); - return (ctx->major); + return GSS_S_COMPLETE; } /* Privileged */ diff --git a/crypto/openssh/hmac.c b/crypto/openssh/hmac.c index 99317b0..1c87964 100644 --- a/crypto/openssh/hmac.c +++ b/crypto/openssh/hmac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hmac.c,v 1.10 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: hmac.c,v 1.12 2015/03/24 20:03:44 markus Exp $ */ /* * Copyright (c) 2014 Markus Friedl. All rights reserved. * @@ -20,7 +20,7 @@ #include #include -#include "buffer.h" +#include "sshbuf.h" #include "digest.h" #include "hmac.h" @@ -96,7 +96,7 @@ ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen) } int -ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b) +ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const struct sshbuf *b) { return ssh_digest_update_buffer(ctx->digest, b); } @@ -154,7 +154,7 @@ hmac_test(void *key, size_t klen, void *m, size_t mlen, u_char *e, size_t elen) if (memcmp(e, digest, elen)) { for (i = 0; i < elen; i++) - printf("[%zd] %2.2x %2.2x\n", i, e[i], digest[i]); + printf("[%zu] %2.2x %2.2x\n", i, e[i], digest[i]); printf("mismatch\n"); } else printf("ok\n"); diff --git a/crypto/openssh/hmac.h b/crypto/openssh/hmac.h index 2374a69..42b33d0 100644 --- a/crypto/openssh/hmac.h +++ b/crypto/openssh/hmac.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hmac.h,v 1.6 2014/01/27 18:58:14 markus Exp $ */ +/* $OpenBSD: hmac.h,v 1.9 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2014 Markus Friedl. All rights reserved. * @@ -21,6 +21,7 @@ /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ size_t ssh_hmac_bytes(int alg); +struct sshbuf; struct ssh_hmac_ctx; struct ssh_hmac_ctx *ssh_hmac_start(int alg); @@ -29,7 +30,7 @@ int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen) __attribute__((__bounded__(__buffer__, 2, 3))); int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen) __attribute__((__bounded__(__buffer__, 2, 3))); -int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b); +int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const struct sshbuf *b); int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen) __attribute__((__bounded__(__buffer__, 2, 3))); void ssh_hmac_free(struct ssh_hmac_ctx *ctx); diff --git a/crypto/openssh/hostfile.c b/crypto/openssh/hostfile.c index 8bc9540..2850a47 100644 --- a/crypto/openssh/hostfile.c +++ b/crypto/openssh/hostfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.c,v 1.55 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: hostfile.c,v 1.66 2015/05/04 06:10:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -39,21 +39,26 @@ #include "includes.h" #include +#include #include +#include #include #include #include #include #include +#include +#include #include "xmalloc.h" #include "match.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "log.h" #include "misc.h" +#include "ssherr.h" #include "digest.h" #include "hmac.h" @@ -62,6 +67,8 @@ struct hostkeys { u_int num_entries; }; +/* XXX hmac is too easy to dictionary attack; use bcrypt? */ + static int extract_salt(const char *s, u_int l, u_char *salt, size_t salt_len) { @@ -154,15 +161,16 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len) */ int -hostfile_read_key(char **cpp, int *bitsp, Key *ret) +hostfile_read_key(char **cpp, u_int *bitsp, struct sshkey *ret) { char *cp; + int r; /* Skip leading whitespace. */ for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) ; - if (key_read(ret, &cp) != 1) + if ((r = sshkey_read(ret, &cp)) != 0) return 0; /* Skip trailing whitespace. */ @@ -171,26 +179,8 @@ hostfile_read_key(char **cpp, int *bitsp, Key *ret) /* Return results. */ *cpp = cp; - if (bitsp != NULL) { - if ((*bitsp = key_size(ret)) <= 0) - return 0; - } - return 1; -} - -static int -hostfile_check_key(int bits, const Key *key, const char *host, - const char *filename, u_long linenum) -{ - if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL) - return 1; - if (bits != BN_num_bits(key->rsa->n)) { - logit("Warning: %s, line %lu: keysize mismatch for host %s: " - "actual %d vs. announced %d.", - filename, linenum, host, BN_num_bits(key->rsa->n), bits); - logit("Warning: replace %d with %d in %s, line %lu.", - bits, BN_num_bits(key->rsa->n), filename, linenum); - } + if (bitsp != NULL) + *bitsp = sshkey_size(ret); return 1; } @@ -238,91 +228,66 @@ init_hostkeys(void) return ret; } -void -load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path) -{ - FILE *f; - char line[8192]; - u_long linenum = 0, num_loaded = 0; - char *cp, *cp2, *hashed_host; - HostkeyMarker marker; - Key *key; - int kbits; - - if ((f = fopen(path, "r")) == NULL) - return; - debug3("%s: loading entries for host \"%.100s\" from file \"%s\"", - __func__, host, path); - while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) { - cp = line; - - /* Skip any leading whitespace, comments and empty lines. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '#' || *cp == '\n') - continue; - - if ((marker = check_markers(&cp)) == MRK_ERROR) { - verbose("%s: invalid marker at %s:%lu", - __func__, path, linenum); - continue; - } - - /* Find the end of the host name portion. */ - for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) - ; +struct load_callback_ctx { + const char *host; + u_long num_loaded; + struct hostkeys *hostkeys; +}; - /* Check if the host name matches. */ - if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) { - if (*cp != HASH_DELIM) - continue; - hashed_host = host_hash(host, cp, (u_int) (cp2 - cp)); - if (hashed_host == NULL) { - debug("Invalid hashed host line %lu of %s", - linenum, path); - continue; - } - if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0) - continue; - } +static int +record_hostkey(struct hostkey_foreach_line *l, void *_ctx) +{ + struct load_callback_ctx *ctx = (struct load_callback_ctx *)_ctx; + struct hostkeys *hostkeys = ctx->hostkeys; + struct hostkey_entry *tmp; + + if (l->status == HKF_STATUS_INVALID) { + /* XXX make this verbose() in the future */ + debug("%s:%ld: parse error in hostkeys file", + l->path, l->linenum); + return 0; + } - /* Got a match. Skip host name. */ - cp = cp2; + debug3("%s: found %skey type %s in file %s:%lu", __func__, + l->marker == MRK_NONE ? "" : + (l->marker == MRK_CA ? "ca " : "revoked "), + sshkey_type(l->key), l->path, l->linenum); + if ((tmp = reallocarray(hostkeys->entries, + hostkeys->num_entries + 1, sizeof(*hostkeys->entries))) == NULL) + return SSH_ERR_ALLOC_FAIL; + hostkeys->entries = tmp; + hostkeys->entries[hostkeys->num_entries].host = xstrdup(ctx->host); + hostkeys->entries[hostkeys->num_entries].file = xstrdup(l->path); + hostkeys->entries[hostkeys->num_entries].line = l->linenum; + hostkeys->entries[hostkeys->num_entries].key = l->key; + l->key = NULL; /* steal it */ + hostkeys->entries[hostkeys->num_entries].marker = l->marker; + hostkeys->num_entries++; + ctx->num_loaded++; - /* - * Extract the key from the line. This will skip any leading - * whitespace. Ignore badly formatted lines. - */ - key = key_new(KEY_UNSPEC); - if (!hostfile_read_key(&cp, &kbits, key)) { - key_free(key); - key = key_new(KEY_RSA1); - if (!hostfile_read_key(&cp, &kbits, key)) { - key_free(key); - continue; - } - } - if (!hostfile_check_key(kbits, key, host, path, linenum)) - continue; + return 0; +} - debug3("%s: found %skey type %s in file %s:%lu", __func__, - marker == MRK_NONE ? "" : - (marker == MRK_CA ? "ca " : "revoked "), - key_type(key), path, linenum); - hostkeys->entries = xrealloc(hostkeys->entries, - hostkeys->num_entries + 1, sizeof(*hostkeys->entries)); - hostkeys->entries[hostkeys->num_entries].host = xstrdup(host); - hostkeys->entries[hostkeys->num_entries].file = xstrdup(path); - hostkeys->entries[hostkeys->num_entries].line = linenum; - hostkeys->entries[hostkeys->num_entries].key = key; - hostkeys->entries[hostkeys->num_entries].marker = marker; - hostkeys->num_entries++; - num_loaded++; +void +load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path) +{ + int r; + struct load_callback_ctx ctx; + + ctx.host = host; + ctx.num_loaded = 0; + ctx.hostkeys = hostkeys; + + if ((r = hostkeys_foreach(path, record_hostkey, &ctx, host, NULL, + HKF_WANT_MATCH|HKF_WANT_PARSE_KEY)) != 0) { + if (r != SSH_ERR_SYSTEM_ERROR && errno != ENOENT) + debug("%s: hostkeys_foreach failed for %s: %s", + __func__, path, ssh_err(r)); } - debug3("%s: loaded %lu keys", __func__, num_loaded); - fclose(f); - return; -} + if (ctx.num_loaded != 0) + debug3("%s: loaded %lu keys from %s", __func__, + ctx.num_loaded, host); +} void free_hostkeys(struct hostkeys *hostkeys) @@ -332,7 +297,7 @@ free_hostkeys(struct hostkeys *hostkeys) for (i = 0; i < hostkeys->num_entries; i++) { free(hostkeys->entries[i].host); free(hostkeys->entries[i].file); - key_free(hostkeys->entries[i].key); + sshkey_free(hostkeys->entries[i].key); explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries)); } free(hostkeys->entries); @@ -341,18 +306,18 @@ free_hostkeys(struct hostkeys *hostkeys) } static int -check_key_not_revoked(struct hostkeys *hostkeys, Key *k) +check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k) { - int is_cert = key_is_cert(k); + int is_cert = sshkey_is_cert(k); u_int i; for (i = 0; i < hostkeys->num_entries; i++) { if (hostkeys->entries[i].marker != MRK_REVOKE) continue; - if (key_equal_public(k, hostkeys->entries[i].key)) + if (sshkey_equal_public(k, hostkeys->entries[i].key)) return -1; if (is_cert && - key_equal_public(k->cert->signature_key, + sshkey_equal_public(k->cert->signature_key, hostkeys->entries[i].key)) return -1; } @@ -376,11 +341,11 @@ check_key_not_revoked(struct hostkeys *hostkeys, Key *k) */ static HostStatus check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, - Key *k, int keytype, const struct hostkey_entry **found) + struct sshkey *k, int keytype, const struct hostkey_entry **found) { u_int i; HostStatus end_return = HOST_NEW; - int want_cert = key_is_cert(k); + int want_cert = sshkey_is_cert(k); HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE; int proto = (k ? k->type : keytype) == KEY_RSA1 ? 1 : 2; @@ -404,7 +369,7 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, break; } if (want_cert) { - if (key_equal_public(k->cert->signature_key, + if (sshkey_equal_public(k->cert->signature_key, hostkeys->entries[i].key)) { /* A matching CA exists */ end_return = HOST_OK; @@ -413,7 +378,7 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, break; } } else { - if (key_equal(k, hostkeys->entries[i].key)) { + if (sshkey_equal(k, hostkeys->entries[i].key)) { end_return = HOST_OK; if (found != NULL) *found = hostkeys->entries + i; @@ -432,9 +397,9 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, } return end_return; } - + HostStatus -check_key_in_hostkeys(struct hostkeys *hostkeys, Key *key, +check_key_in_hostkeys(struct hostkeys *hostkeys, struct sshkey *key, const struct hostkey_entry **found) { if (key == NULL) @@ -450,40 +415,438 @@ lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype, found) == HOST_FOUND); } +static int +write_host_entry(FILE *f, const char *host, const char *ip, + const struct sshkey *key, int store_hash) +{ + int r, success = 0; + char *hashed_host = NULL; + + if (store_hash) { + if ((hashed_host = host_hash(host, NULL, 0)) == NULL) { + error("%s: host_hash failed", __func__); + return 0; + } + fprintf(f, "%s ", hashed_host); + } else if (ip != NULL) + fprintf(f, "%s,%s ", host, ip); + else + fprintf(f, "%s ", host); + + if ((r = sshkey_write(key, f)) == 0) + success = 1; + else + error("%s: sshkey_write failed: %s", __func__, ssh_err(r)); + fputc('\n', f); + return success; +} + /* * Appends an entry to the host file. Returns false if the entry could not * be appended. */ - int -add_host_to_hostfile(const char *filename, const char *host, const Key *key, - int store_hash) +add_host_to_hostfile(const char *filename, const char *host, + const struct sshkey *key, int store_hash) { FILE *f; - int success = 0; - char *hashed_host = NULL; + int success; if (key == NULL) return 1; /* XXX ? */ f = fopen(filename, "a"); if (!f) return 0; + success = write_host_entry(f, host, NULL, key, store_hash); + fclose(f); + return success; +} - if (store_hash) { - if ((hashed_host = host_hash(host, NULL, 0)) == NULL) { - error("add_host_to_hostfile: host_hash failed"); - fclose(f); +struct host_delete_ctx { + FILE *out; + int quiet; + const char *host; + int *skip_keys; /* XXX split for host/ip? might want to ensure both */ + struct sshkey * const *keys; + size_t nkeys; + int modified; +}; + +static int +host_delete(struct hostkey_foreach_line *l, void *_ctx) +{ + struct host_delete_ctx *ctx = (struct host_delete_ctx *)_ctx; + int loglevel = ctx->quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE; + size_t i; + + if (l->status == HKF_STATUS_MATCHED) { + if (l->marker != MRK_NONE) { + /* Don't remove CA and revocation lines */ + fprintf(ctx->out, "%s\n", l->line); return 0; } + + /* XXX might need a knob for this later */ + /* Don't remove RSA1 keys */ + if (l->key->type == KEY_RSA1) { + fprintf(ctx->out, "%s\n", l->line); + return 0; + } + + /* + * If this line contains one of the keys that we will be + * adding later, then don't change it and mark the key for + * skipping. + */ + for (i = 0; i < ctx->nkeys; i++) { + if (sshkey_equal(ctx->keys[i], l->key)) { + ctx->skip_keys[i] = 1; + fprintf(ctx->out, "%s\n", l->line); + debug3("%s: %s key already at %s:%ld", __func__, + sshkey_type(l->key), l->path, l->linenum); + return 0; + } + } + + /* + * Hostname matches and has no CA/revoke marker, delete it + * by *not* writing the line to ctx->out. + */ + do_log2(loglevel, "%s%s%s:%ld: Removed %s key for host %s", + ctx->quiet ? __func__ : "", ctx->quiet ? ": " : "", + l->path, l->linenum, sshkey_type(l->key), ctx->host); + ctx->modified = 1; + return 0; + } + /* Retain non-matching hosts and invalid lines when deleting */ + if (l->status == HKF_STATUS_INVALID) { + do_log2(loglevel, "%s%s%s:%ld: invalid known_hosts entry", + ctx->quiet ? __func__ : "", ctx->quiet ? ": " : "", + l->path, l->linenum); } - fprintf(f, "%s ", store_hash ? hashed_host : host); + fprintf(ctx->out, "%s\n", l->line); + return 0; +} - if (key_write(key, f)) { - success = 1; +int +hostfile_replace_entries(const char *filename, const char *host, const char *ip, + struct sshkey **keys, size_t nkeys, int store_hash, int quiet, int hash_alg) +{ + int r, fd, oerrno = 0; + int loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE; + struct host_delete_ctx ctx; + char *fp, *temp = NULL, *back = NULL; + mode_t omask; + size_t i; + + omask = umask(077); + + memset(&ctx, 0, sizeof(ctx)); + ctx.host = host; + ctx.quiet = quiet; + if ((ctx.skip_keys = calloc(nkeys, sizeof(*ctx.skip_keys))) == NULL) + return SSH_ERR_ALLOC_FAIL; + ctx.keys = keys; + ctx.nkeys = nkeys; + ctx.modified = 0; + + /* + * Prepare temporary file for in-place deletion. + */ + if ((r = asprintf(&temp, "%s.XXXXXXXXXXX", filename)) < 0 || + (r = asprintf(&back, "%s.old", filename)) < 0) { + r = SSH_ERR_ALLOC_FAIL; + goto fail; + } + + if ((fd = mkstemp(temp)) == -1) { + oerrno = errno; + error("%s: mkstemp: %s", __func__, strerror(oerrno)); + r = SSH_ERR_SYSTEM_ERROR; + goto fail; + } + if ((ctx.out = fdopen(fd, "w")) == NULL) { + oerrno = errno; + close(fd); + error("%s: fdopen: %s", __func__, strerror(oerrno)); + r = SSH_ERR_SYSTEM_ERROR; + goto fail; + } + + /* Remove all entries for the specified host from the file */ + if ((r = hostkeys_foreach(filename, host_delete, &ctx, host, ip, + HKF_WANT_PARSE_KEY)) != 0) { + error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r)); + goto fail; + } + + /* Add the requested keys */ + for (i = 0; i < nkeys; i++) { + if (ctx.skip_keys[i]) + continue; + if ((fp = sshkey_fingerprint(keys[i], hash_alg, + SSH_FP_DEFAULT)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto fail; + } + do_log2(loglevel, "%s%sAdding new key for %s to %s: %s %s", + quiet ? __func__ : "", quiet ? ": " : "", host, filename, + sshkey_ssh_name(keys[i]), fp); + free(fp); + if (!write_host_entry(ctx.out, host, ip, keys[i], store_hash)) { + r = SSH_ERR_INTERNAL_ERROR; + goto fail; + } + ctx.modified = 1; + } + fclose(ctx.out); + ctx.out = NULL; + + if (ctx.modified) { + /* Backup the original file and replace it with the temporary */ + if (unlink(back) == -1 && errno != ENOENT) { + oerrno = errno; + error("%s: unlink %.100s: %s", __func__, + back, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto fail; + } + if (link(filename, back) == -1) { + oerrno = errno; + error("%s: link %.100s to %.100s: %s", __func__, + filename, back, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto fail; + } + if (rename(temp, filename) == -1) { + oerrno = errno; + error("%s: rename \"%s\" to \"%s\": %s", __func__, + temp, filename, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto fail; + } } else { - error("add_host_to_hostfile: saving key in %s failed", filename); + /* No changes made; just delete the temporary file */ + if (unlink(temp) != 0) + error("%s: unlink \"%s\": %s", __func__, + temp, strerror(errno)); + } + + /* success */ + r = 0; + fail: + if (temp != NULL && r != 0) + unlink(temp); + free(temp); + free(back); + if (ctx.out != NULL) + fclose(ctx.out); + free(ctx.skip_keys); + umask(omask); + if (r == SSH_ERR_SYSTEM_ERROR) + errno = oerrno; + return r; +} + +static int +match_maybe_hashed(const char *host, const char *names, int *was_hashed) +{ + int hashed = *names == HASH_DELIM; + const char *hashed_host; + size_t nlen = strlen(names); + + if (was_hashed != NULL) + *was_hashed = hashed; + if (hashed) { + if ((hashed_host = host_hash(host, names, nlen)) == NULL) + return -1; + return nlen == strlen(hashed_host) && + strncmp(hashed_host, names, nlen) == 0; } - fprintf(f, "\n"); + return match_hostname(host, names) == 1; +} + +int +hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, + const char *host, const char *ip, u_int options) +{ + FILE *f; + char line[8192], oline[8192], ktype[128]; + u_long linenum = 0; + char *cp, *cp2; + u_int kbits; + int hashed; + int s, r = 0; + struct hostkey_foreach_line lineinfo; + size_t l; + + memset(&lineinfo, 0, sizeof(lineinfo)); + if (host == NULL && (options & HKF_WANT_MATCH) != 0) + return SSH_ERR_INVALID_ARGUMENT; + if ((f = fopen(path, "r")) == NULL) + return SSH_ERR_SYSTEM_ERROR; + + debug3("%s: reading file \"%s\"", __func__, path); + while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) { + line[strcspn(line, "\n")] = '\0'; + strlcpy(oline, line, sizeof(oline)); + + sshkey_free(lineinfo.key); + memset(&lineinfo, 0, sizeof(lineinfo)); + lineinfo.path = path; + lineinfo.linenum = linenum; + lineinfo.line = oline; + lineinfo.marker = MRK_NONE; + lineinfo.status = HKF_STATUS_OK; + lineinfo.keytype = KEY_UNSPEC; + + /* Skip any leading whitespace, comments and empty lines. */ + for (cp = line; *cp == ' ' || *cp == '\t'; cp++) + ; + if (!*cp || *cp == '#' || *cp == '\n') { + if ((options & HKF_WANT_MATCH) == 0) { + lineinfo.status = HKF_STATUS_COMMENT; + if ((r = callback(&lineinfo, ctx)) != 0) + break; + } + continue; + } + + if ((lineinfo.marker = check_markers(&cp)) == MRK_ERROR) { + verbose("%s: invalid marker at %s:%lu", + __func__, path, linenum); + if ((options & HKF_WANT_MATCH) == 0) + goto bad; + continue; + } + + /* Find the end of the host name portion. */ + for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) + ; + lineinfo.hosts = cp; + *cp2++ = '\0'; + + /* Check if the host name matches. */ + if (host != NULL) { + if ((s = match_maybe_hashed(host, lineinfo.hosts, + &hashed)) == -1) { + debug2("%s: %s:%ld: bad host hash \"%.32s\"", + __func__, path, linenum, lineinfo.hosts); + goto bad; + } + if (s == 1) { + lineinfo.status = HKF_STATUS_MATCHED; + lineinfo.match |= HKF_MATCH_HOST | + (hashed ? HKF_MATCH_HOST_HASHED : 0); + } + /* Try matching IP address if supplied */ + if (ip != NULL) { + if ((s = match_maybe_hashed(ip, lineinfo.hosts, + &hashed)) == -1) { + debug2("%s: %s:%ld: bad ip hash " + "\"%.32s\"", __func__, path, + linenum, lineinfo.hosts); + goto bad; + } + if (s == 1) { + lineinfo.status = HKF_STATUS_MATCHED; + lineinfo.match |= HKF_MATCH_IP | + (hashed ? HKF_MATCH_IP_HASHED : 0); + } + } + /* + * Skip this line if host matching requested and + * neither host nor address matched. + */ + if ((options & HKF_WANT_MATCH) != 0 && + lineinfo.status != HKF_STATUS_MATCHED) + continue; + } + + /* Got a match. Skip host name and any following whitespace */ + for (; *cp2 == ' ' || *cp2 == '\t'; cp2++) + ; + if (*cp2 == '\0' || *cp2 == '#') { + debug2("%s:%ld: truncated before key type", + path, linenum); + goto bad; + } + lineinfo.rawkey = cp = cp2; + + if ((options & HKF_WANT_PARSE_KEY) != 0) { + /* + * Extract the key from the line. This will skip + * any leading whitespace. Ignore badly formatted + * lines. + */ + if ((lineinfo.key = sshkey_new(KEY_UNSPEC)) == NULL) { + error("%s: sshkey_new failed", __func__); + r = SSH_ERR_ALLOC_FAIL; + break; + } + if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) { +#ifdef WITH_SSH1 + sshkey_free(lineinfo.key); + lineinfo.key = sshkey_new(KEY_RSA1); + if (lineinfo.key == NULL) { + error("%s: sshkey_new fail", __func__); + r = SSH_ERR_ALLOC_FAIL; + break; + } + if (!hostfile_read_key(&cp, &kbits, + lineinfo.key)) + goto bad; +#else + goto bad; +#endif + } + lineinfo.keytype = lineinfo.key->type; + lineinfo.comment = cp; + } else { + /* Extract and parse key type */ + l = strcspn(lineinfo.rawkey, " \t"); + if (l <= 1 || l >= sizeof(ktype) || + lineinfo.rawkey[l] == '\0') + goto bad; + memcpy(ktype, lineinfo.rawkey, l); + ktype[l] = '\0'; + lineinfo.keytype = sshkey_type_from_name(ktype); + + /* + * Assume RSA1 if the first component is a short + * decimal number. + */ + if (lineinfo.keytype == KEY_UNSPEC && l < 8 && + strspn(ktype, "0123456789") == l) + lineinfo.keytype = KEY_RSA1; + + /* + * Check that something other than whitespace follows + * the key type. This won't catch all corruption, but + * it does catch trivial truncation. + */ + cp2 += l; /* Skip past key type */ + for (; *cp2 == ' ' || *cp2 == '\t'; cp2++) + ; + if (*cp2 == '\0' || *cp2 == '#') { + debug2("%s:%ld: truncated after key type", + path, linenum); + lineinfo.keytype = KEY_UNSPEC; + } + if (lineinfo.keytype == KEY_UNSPEC) { + bad: + sshkey_free(lineinfo.key); + lineinfo.key = NULL; + lineinfo.status = HKF_STATUS_INVALID; + if ((r = callback(&lineinfo, ctx)) != 0) + break; + continue; + } + } + if ((r = callback(&lineinfo, ctx)) != 0) + break; + } + sshkey_free(lineinfo.key); fclose(f); - return success; + return r; } diff --git a/crypto/openssh/hostfile.h b/crypto/openssh/hostfile.h index 679c034..bd21043 100644 --- a/crypto/openssh/hostfile.h +++ b/crypto/openssh/hostfile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.h,v 1.20 2013/07/12 00:19:58 djm Exp $ */ +/* $OpenBSD: hostfile.h,v 1.24 2015/02/16 22:08:57 djm Exp $ */ /* * Author: Tatu Ylonen @@ -26,7 +26,7 @@ struct hostkey_entry { char *host; char *file; u_long line; - Key *key; + struct sshkey *key; HostkeyMarker marker; }; struct hostkeys; @@ -35,13 +35,18 @@ struct hostkeys *init_hostkeys(void); void load_hostkeys(struct hostkeys *, const char *, const char *); void free_hostkeys(struct hostkeys *); -HostStatus check_key_in_hostkeys(struct hostkeys *, Key *, +HostStatus check_key_in_hostkeys(struct hostkeys *, struct sshkey *, const struct hostkey_entry **); int lookup_key_in_hostkeys_by_type(struct hostkeys *, int, const struct hostkey_entry **); -int hostfile_read_key(char **, int *, Key *); -int add_host_to_hostfile(const char *, const char *, const Key *, int); +int hostfile_read_key(char **, u_int *, struct sshkey *); +int add_host_to_hostfile(const char *, const char *, + const struct sshkey *, int); + +int hostfile_replace_entries(const char *filename, + const char *host, const char *ip, struct sshkey **keys, size_t nkeys, + int store_hash, int quiet, int hash_alg); #define HASH_MAGIC "|1|" #define HASH_DELIM '|' @@ -51,4 +56,53 @@ int add_host_to_hostfile(const char *, const char *, const Key *, int); char *host_hash(const char *, const char *, u_int); +/* + * Iterate through a hostkeys file, optionally parsing keys and matching + * hostnames. Allows access to the raw keyfile lines to allow + * streaming edits to the file to take place. + */ +#define HKF_WANT_MATCH (1) /* return only matching hosts/addrs */ +#define HKF_WANT_PARSE_KEY (1<<1) /* need key parsed */ + +#define HKF_STATUS_OK 0 /* Line parsed, didn't match host */ +#define HKF_STATUS_INVALID 1 /* line had parse error */ +#define HKF_STATUS_COMMENT 2 /* valid line contained no key */ +#define HKF_STATUS_MATCHED 3 /* hostname or IP matched */ + +#define HKF_MATCH_HOST (1) /* hostname matched */ +#define HKF_MATCH_IP (1<<1) /* address matched */ +#define HKF_MATCH_HOST_HASHED (1<<2) /* hostname was hashed */ +#define HKF_MATCH_IP_HASHED (1<<3) /* address was hashed */ +/* XXX HKF_MATCH_KEY_TYPE? */ + +/* + * The callback function receives this as an argument for each matching + * hostkey line. The callback may "steal" the 'key' field by setting it to NULL. + * If a parse error occurred, then "hosts" and subsequent options may be NULL. + */ +struct hostkey_foreach_line { + const char *path; /* Path of file */ + u_long linenum; /* Line number */ + u_int status; /* One of HKF_STATUS_* */ + u_int match; /* Zero or more of HKF_MATCH_* OR'd together */ + char *line; /* Entire key line; mutable by callback */ + int marker; /* CA/revocation markers; indicated by MRK_* value */ + const char *hosts; /* Raw hosts text, may be hashed or list multiple */ + const char *rawkey; /* Text of key and any comment following it */ + int keytype; /* Type of key; KEY_UNSPEC for invalid/comment lines */ + struct sshkey *key; /* Key, if parsed ok and HKF_WANT_MATCH_HOST set */ + const char *comment; /* Any comment following the key */ +}; + +/* + * Callback fires for each line (or matching line if a HKF_WANT_* option + * is set). The foreach loop will terminate if the callback returns a non- + * zero exit status. + */ +typedef int hostkeys_foreach_fn(struct hostkey_foreach_line *l, void *ctx); + +/* Iterate over a hostkeys file */ +int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, + const char *host, const char *ip, u_int options); + #endif diff --git a/crypto/openssh/includes.h b/crypto/openssh/includes.h index 07bcd89..2893a54 100644 --- a/crypto/openssh/includes.h +++ b/crypto/openssh/includes.h @@ -23,10 +23,11 @@ #endif #include +#include #include /* For CMSG_* */ #ifdef HAVE_LIMITS_H -# include /* For PATH_MAX */ +# include /* For PATH_MAX, _POSIX_HOST_NAME_MAX */ #endif #ifdef HAVE_BSTRING_H # include @@ -166,7 +167,9 @@ # endif #endif +#ifdef WITH_OPENSSL #include /* For OPENSSL_VERSION_NUMBER */ +#endif #include "defines.h" diff --git a/crypto/openssh/kex.c b/crypto/openssh/kex.c index 74e2b86..b777b7d 100644 --- a/crypto/openssh/kex.c +++ b/crypto/openssh/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.98 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.109 2015/07/30 00:01:34 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -25,7 +25,7 @@ #include "includes.h" -#include +#include /* MAX roundup */ #include #include @@ -33,22 +33,26 @@ #include #include +#ifdef WITH_OPENSSL #include +#endif -#include "xmalloc.h" #include "ssh2.h" -#include "buffer.h" #include "packet.h" #include "compat.h" #include "cipher.h" -#include "key.h" +#include "sshkey.h" #include "kex.h" #include "log.h" #include "mac.h" #include "match.h" +#include "misc.h" #include "dispatch.h" #include "monitor.h" #include "roaming.h" + +#include "ssherr.h" +#include "sshbuf.h" #include "digest.h" #if OPENSSL_VERSION_NUMBER >= 0x00907000L @@ -60,22 +64,23 @@ extern const EVP_MD *evp_ssh_sha256(void); #endif /* prototype */ -static void kex_kexinit_finish(Kex *); -static void kex_choose_conf(Kex *); +static int kex_choose_conf(struct ssh *); +static int kex_input_newkeys(int, u_int32_t, void *); struct kexalg { char *name; - int type; + u_int type; int ec_nid; int hash_alg; }; static const struct kexalg kexalgs[] = { +#ifdef WITH_OPENSSL { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, #ifdef HAVE_EVP_SHA256 { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, -#endif +#endif /* HAVE_EVP_SHA256 */ #ifdef OPENSSL_HAS_ECC { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, @@ -84,19 +89,19 @@ static const struct kexalg kexalgs[] = { # ifdef OPENSSL_HAS_NISTP521 { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, SSH_DIGEST_SHA512 }, -# endif -#endif - { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, -#ifdef HAVE_EVP_SHA256 +# endif /* OPENSSL_HAS_NISTP521 */ +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ +#if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, -#endif +#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ { NULL, -1, -1, -1}, }; char * kex_alg_list(char sep) { - char *ret = NULL; + char *ret = NULL, *tmp; size_t nlen, rlen = 0; const struct kexalg *k; @@ -104,7 +109,11 @@ kex_alg_list(char sep) if (ret != NULL) ret[rlen++] = sep; nlen = strlen(k->name); - ret = xrealloc(ret, 1, rlen + nlen + 2); + if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { + free(ret); + return NULL; + } + ret = tmp; memcpy(ret + rlen, k->name, nlen + 1); rlen += nlen; } @@ -131,7 +140,8 @@ kex_names_valid(const char *names) if (names == NULL || strcmp(names, "") == 0) return 0; - s = cp = xstrdup(names); + if ((s = cp = strdup(names)) == NULL) + return 0; for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (kex_alg_by_name(p) == NULL) { @@ -145,158 +155,255 @@ kex_names_valid(const char *names) return 1; } +/* + * Concatenate algorithm names, avoiding duplicates in the process. + * Caller must free returned string. + */ +char * +kex_names_cat(const char *a, const char *b) +{ + char *ret = NULL, *tmp = NULL, *cp, *p; + size_t len; + + if (a == NULL || *a == '\0') + return NULL; + if (b == NULL || *b == '\0') + return strdup(a); + if (strlen(b) > 1024*1024) + return NULL; + len = strlen(a) + strlen(b) + 2; + if ((tmp = cp = strdup(b)) == NULL || + (ret = calloc(1, len)) == NULL) { + free(tmp); + return NULL; + } + strlcpy(ret, a, len); + for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { + if (match_list(ret, p, NULL) != NULL) + continue; /* Algorithm already present */ + if (strlcat(ret, ",", len) >= len || + strlcat(ret, p, len) >= len) { + free(tmp); + free(ret); + return NULL; /* Shouldn't happen */ + } + } + free(tmp); + return ret; +} + +/* + * Assemble a list of algorithms from a default list and a string from a + * configuration file. The user-provided string may begin with '+' to + * indicate that it should be appended to the default. + */ +int +kex_assemble_names(const char *def, char **list) +{ + char *ret; + + if (list == NULL || *list == NULL || **list == '\0') { + *list = strdup(def); + return 0; + } + if (**list != '+') { + return 0; + } + + if ((ret = kex_names_cat(def, *list + 1)) == NULL) + return SSH_ERR_ALLOC_FAIL; + free(*list); + *list = ret; + return 0; +} + /* put algorithm proposal into buffer */ -static void -kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) +int +kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) { u_int i; + int r; + + sshbuf_reset(b); - buffer_clear(b); /* * add a dummy cookie, the cookie will be overwritten by * kex_send_kexinit(), each time a kexinit is set */ - for (i = 0; i < KEX_COOKIE_LEN; i++) - buffer_put_char(b, 0); - for (i = 0; i < PROPOSAL_MAX; i++) - buffer_put_cstring(b, proposal[i]); - buffer_put_char(b, 0); /* first_kex_packet_follows */ - buffer_put_int(b, 0); /* uint32 reserved */ + for (i = 0; i < KEX_COOKIE_LEN; i++) { + if ((r = sshbuf_put_u8(b, 0)) != 0) + return r; + } + for (i = 0; i < PROPOSAL_MAX; i++) { + if ((r = sshbuf_put_cstring(b, proposal[i])) != 0) + return r; + } + if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */ + (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */ + return r; + return 0; } /* parse buffer and return algorithm proposal */ -static char ** -kex_buf2prop(Buffer *raw, int *first_kex_follows) +int +kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp) { - Buffer b; + struct sshbuf *b = NULL; + u_char v; u_int i; - char **proposal; - - proposal = xcalloc(PROPOSAL_MAX, sizeof(char *)); - - buffer_init(&b); - buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); - /* skip cookie */ - for (i = 0; i < KEX_COOKIE_LEN; i++) - buffer_get_char(&b); + char **proposal = NULL; + int r; + + *propp = NULL; + if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((b = sshbuf_fromb(raw)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */ + goto out; /* extract kex init proposal strings */ for (i = 0; i < PROPOSAL_MAX; i++) { - proposal[i] = buffer_get_cstring(&b,NULL); + if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) + goto out; debug2("kex_parse_kexinit: %s", proposal[i]); } /* first kex follows / reserved */ - i = buffer_get_char(&b); + if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ + (r = sshbuf_get_u32(b, &i)) != 0) /* reserved */ + goto out; if (first_kex_follows != NULL) - *first_kex_follows = i; - debug2("kex_parse_kexinit: first_kex_follows %d ", i); - i = buffer_get_int(&b); - debug2("kex_parse_kexinit: reserved %u ", i); - buffer_free(&b); - return proposal; + *first_kex_follows = v; + debug2("first_kex_follows %d ", v); + debug2("reserved %u ", i); + r = 0; + *propp = proposal; + out: + if (r != 0 && proposal != NULL) + kex_prop_free(proposal); + sshbuf_free(b); + return r; } -static void +void kex_prop_free(char **proposal) { u_int i; + if (proposal == NULL) + return; for (i = 0; i < PROPOSAL_MAX; i++) free(proposal[i]); free(proposal); } /* ARGSUSED */ -static void +static int kex_protocol_error(int type, u_int32_t seq, void *ctxt) { error("Hm, kex protocol error: type %d seq %u", type, seq); + return 0; } static void -kex_reset_dispatch(void) +kex_reset_dispatch(struct ssh *ssh) { - dispatch_range(SSH2_MSG_TRANSPORT_MIN, + ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN, SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); - dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); + ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); } -void -kex_finish(Kex *kex) +int +kex_send_newkeys(struct ssh *ssh) { - kex_reset_dispatch(); + int r; - packet_start(SSH2_MSG_NEWKEYS); - packet_send(); - /* packet_write_wait(); */ + kex_reset_dispatch(ssh); + if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; debug("SSH2_MSG_NEWKEYS sent"); - debug("expecting SSH2_MSG_NEWKEYS"); - packet_read_expect(SSH2_MSG_NEWKEYS); - packet_check_eom(); - debug("SSH2_MSG_NEWKEYS received"); + ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); + return 0; +} + +static int +kex_input_newkeys(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + int r; + debug("SSH2_MSG_NEWKEYS received"); + ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error); + if ((r = sshpkt_get_end(ssh)) != 0) + return r; kex->done = 1; - buffer_clear(&kex->peer); - /* buffer_clear(&kex->my); */ + sshbuf_reset(kex->peer); + /* sshbuf_reset(kex->my); */ kex->flags &= ~KEX_INIT_SENT; free(kex->name); kex->name = NULL; + return 0; } -void -kex_send_kexinit(Kex *kex) +int +kex_send_kexinit(struct ssh *ssh) { - u_int32_t rnd = 0; u_char *cookie; - u_int i; + struct kex *kex = ssh->kex; + int r; - if (kex == NULL) { - error("kex_send_kexinit: no kex, cannot rekey"); - return; - } - if (kex->flags & KEX_INIT_SENT) { - debug("KEX_INIT_SENT"); - return; - } + if (kex == NULL) + return SSH_ERR_INTERNAL_ERROR; + if (kex->flags & KEX_INIT_SENT) + return 0; kex->done = 0; /* generate a random cookie */ - if (buffer_len(&kex->my) < KEX_COOKIE_LEN) - fatal("kex_send_kexinit: kex proposal too short"); - cookie = buffer_ptr(&kex->my); - for (i = 0; i < KEX_COOKIE_LEN; i++) { - if (i % 4 == 0) - rnd = arc4random(); - cookie[i] = rnd; - rnd >>= 8; - } - packet_start(SSH2_MSG_KEXINIT); - packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my)); - packet_send(); + if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) + return SSH_ERR_INVALID_FORMAT; + if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) + return SSH_ERR_INTERNAL_ERROR; + arc4random_buf(cookie, KEX_COOKIE_LEN); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 || + (r = sshpkt_putb(ssh, kex->my)) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; debug("SSH2_MSG_KEXINIT sent"); kex->flags |= KEX_INIT_SENT; + return 0; } /* ARGSUSED */ -void +int kex_input_kexinit(int type, u_int32_t seq, void *ctxt) { - char *ptr; - u_int i, dlen; - Kex *kex = (Kex *)ctxt; + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + const u_char *ptr; + u_int i; + size_t dlen; + int r; debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) - fatal("kex_input_kexinit: no kex, cannot rekey"); + return SSH_ERR_INVALID_ARGUMENT; - ptr = packet_get_raw(&dlen); - buffer_append(&kex->peer, ptr, dlen); + ptr = sshpkt_ptr(ssh, &dlen); + if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) + return r; /* discard packet */ for (i = 0; i < KEX_COOKIE_LEN; i++) - packet_get_char(); + if ((r = sshpkt_get_u8(ssh, NULL)) != 0) + return r; for (i = 0; i < PROPOSAL_MAX; i++) - free(packet_get_string(NULL)); + if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) + return r; /* * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported * KEX method has the server move first, but a server might be using @@ -307,55 +414,130 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt) * for cases where the server *doesn't* go first. I guess we should * ignore it when it is set for these cases, which is what we do now. */ - (void) packet_get_char(); /* first_kex_follows */ - (void) packet_get_int(); /* reserved */ - packet_check_eom(); + if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */ + (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */ + (r = sshpkt_get_end(ssh)) != 0) + return r; - kex_kexinit_finish(kex); + if (!(kex->flags & KEX_INIT_SENT)) + if ((r = kex_send_kexinit(ssh)) != 0) + return r; + if ((r = kex_choose_conf(ssh)) != 0) + return r; + + if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) + return (kex->kex[kex->kex_type])(ssh); + + return SSH_ERR_INTERNAL_ERROR; } -Kex * -kex_setup(char *proposal[PROPOSAL_MAX]) +int +kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp) { - Kex *kex; - - kex = xcalloc(1, sizeof(*kex)); - buffer_init(&kex->peer); - buffer_init(&kex->my); - kex_prop2buf(&kex->my, proposal); + struct kex *kex; + int r; + + *kexp = NULL; + if ((kex = calloc(1, sizeof(*kex))) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((kex->peer = sshbuf_new()) == NULL || + (kex->my = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = kex_prop2buf(kex->my, proposal)) != 0) + goto out; kex->done = 0; + kex_reset_dispatch(ssh); + r = 0; + *kexp = kex; + out: + if (r != 0) + kex_free(kex); + return r; +} - kex_send_kexinit(kex); /* we start */ - kex_reset_dispatch(); - - return kex; +void +kex_free_newkeys(struct newkeys *newkeys) +{ + if (newkeys == NULL) + return; + if (newkeys->enc.key) { + explicit_bzero(newkeys->enc.key, newkeys->enc.key_len); + free(newkeys->enc.key); + newkeys->enc.key = NULL; + } + if (newkeys->enc.iv) { + explicit_bzero(newkeys->enc.iv, newkeys->enc.block_size); + free(newkeys->enc.iv); + newkeys->enc.iv = NULL; + } + free(newkeys->enc.name); + explicit_bzero(&newkeys->enc, sizeof(newkeys->enc)); + free(newkeys->comp.name); + explicit_bzero(&newkeys->comp, sizeof(newkeys->comp)); + mac_clear(&newkeys->mac); + if (newkeys->mac.key) { + explicit_bzero(newkeys->mac.key, newkeys->mac.key_len); + free(newkeys->mac.key); + newkeys->mac.key = NULL; + } + free(newkeys->mac.name); + explicit_bzero(&newkeys->mac, sizeof(newkeys->mac)); + explicit_bzero(newkeys, sizeof(*newkeys)); + free(newkeys); } -static void -kex_kexinit_finish(Kex *kex) +void +kex_free(struct kex *kex) { - if (!(kex->flags & KEX_INIT_SENT)) - kex_send_kexinit(kex); + u_int mode; - kex_choose_conf(kex); +#ifdef WITH_OPENSSL + if (kex->dh) + DH_free(kex->dh); +#ifdef OPENSSL_HAS_ECC + if (kex->ec_client_key) + EC_KEY_free(kex->ec_client_key); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + for (mode = 0; mode < MODE_MAX; mode++) { + kex_free_newkeys(kex->newkeys[mode]); + kex->newkeys[mode] = NULL; + } + sshbuf_free(kex->peer); + sshbuf_free(kex->my); + free(kex->session_id); + free(kex->client_version_string); + free(kex->server_version_string); + free(kex->failed_choice); + free(kex); +} - if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && - kex->kex[kex->kex_type] != NULL) { - (kex->kex[kex->kex_type])(kex); - } else { - fatal("Unsupported key exchange %d", kex->kex_type); +int +kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) +{ + int r; + + if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) + return r; + if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */ + kex_free(ssh->kex); + ssh->kex = NULL; + return r; } + return 0; } -static void -choose_enc(Enc *enc, char *client, char *server) +static int +choose_enc(struct sshenc *enc, char *client, char *server) { char *name = match_list(client, server, NULL); + if (name == NULL) - fatal("no matching cipher found: client %s server %s", - client, server); + return SSH_ERR_NO_CIPHER_ALG_MATCH; if ((enc->cipher = cipher_by_name(name)) == NULL) - fatal("matching cipher is not supported: %s", name); + return SSH_ERR_INTERNAL_ERROR; enc->name = name; enc->enabled = 0; enc->iv = NULL; @@ -363,31 +545,34 @@ choose_enc(Enc *enc, char *client, char *server) enc->key = NULL; enc->key_len = cipher_keylen(enc->cipher); enc->block_size = cipher_blocksize(enc->cipher); + return 0; } -static void -choose_mac(Mac *mac, char *client, char *server) +static int +choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) { char *name = match_list(client, server, NULL); + if (name == NULL) - fatal("no matching mac found: client %s server %s", - client, server); + return SSH_ERR_NO_MAC_ALG_MATCH; if (mac_setup(mac, name) < 0) - fatal("unsupported mac %s", name); + return SSH_ERR_INTERNAL_ERROR; /* truncate the key */ - if (datafellows & SSH_BUG_HMAC) + if (ssh->compat & SSH_BUG_HMAC) mac->key_len = 16; mac->name = name; mac->key = NULL; mac->enabled = 0; + return 0; } -static void -choose_comp(Comp *comp, char *client, char *server) +static int +choose_comp(struct sshcomp *comp, char *client, char *server) { char *name = match_list(client, server, NULL); + if (name == NULL) - fatal("no matching comp found: client %s server %s", client, server); + return SSH_ERR_NO_COMPRESS_ALG_MATCH; if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; } else if (strcmp(name, "zlib") == 0) { @@ -395,36 +580,42 @@ choose_comp(Comp *comp, char *client, char *server) } else if (strcmp(name, "none") == 0) { comp->type = COMP_NONE; } else { - fatal("unsupported comp %s", name); + return SSH_ERR_INTERNAL_ERROR; } comp->name = name; + return 0; } -static void -choose_kex(Kex *k, char *client, char *server) +static int +choose_kex(struct kex *k, char *client, char *server) { const struct kexalg *kexalg; k->name = match_list(client, server, NULL); + if (k->name == NULL) - fatal("Unable to negotiate a key exchange method"); + return SSH_ERR_NO_KEX_ALG_MATCH; if ((kexalg = kex_alg_by_name(k->name)) == NULL) - fatal("unsupported kex alg %s", k->name); + return SSH_ERR_INTERNAL_ERROR; k->kex_type = kexalg->type; k->hash_alg = kexalg->hash_alg; k->ec_nid = kexalg->ec_nid; + return 0; } -static void -choose_hostkeyalg(Kex *k, char *client, char *server) +static int +choose_hostkeyalg(struct kex *k, char *client, char *server) { char *hostkeyalg = match_list(client, server, NULL); + if (hostkeyalg == NULL) - fatal("no hostkey alg"); - k->hostkey_type = key_type_from_name(hostkeyalg); + return SSH_ERR_NO_HOSTKEY_ALG_MATCH; + k->hostkey_type = sshkey_type_from_name(hostkeyalg); if (k->hostkey_type == KEY_UNSPEC) - fatal("bad hostkey alg '%s'", hostkeyalg); + return SSH_ERR_INTERNAL_ERROR; + k->hostkey_nid = sshkey_ecdsa_nid_from_name(hostkeyalg); free(hostkeyalg); + return 0; } static int @@ -451,18 +642,20 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) return (1); } -static void -kex_choose_conf(Kex *kex) +static int +kex_choose_conf(struct ssh *ssh) { - Newkeys *newkeys; - char **my, **peer; + struct kex *kex = ssh->kex; + struct newkeys *newkeys; + char **my = NULL, **peer = NULL; char **cprop, **sprop; int nenc, nmac, ncomp; u_int mode, ctos, need, dh_need, authlen; - int first_kex_follows, type; + int r, first_kex_follows; - my = kex_buf2prop(&kex->my, NULL); - peer = kex_buf2prop(&kex->peer, &first_kex_follows); + if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0 || + (r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0) + goto out; if (kex->server) { cprop=peer; @@ -474,8 +667,9 @@ kex_choose_conf(Kex *kex) /* Check whether server offers roaming */ if (!kex->server) { - char *roaming; - roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); + char *roaming = match_list(KEX_RESUME, + peer[PROPOSAL_KEX_ALGS], NULL); + if (roaming) { kex->roaming = 1; free(roaming); @@ -484,28 +678,55 @@ kex_choose_conf(Kex *kex) /* Algorithm Negotiation */ for (mode = 0; mode < MODE_MAX; mode++) { - newkeys = xcalloc(1, sizeof(*newkeys)); + if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } kex->newkeys[mode] = newkeys; ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; - choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]); - /* ignore mac for authenticated encryption */ + if ((r = choose_enc(&newkeys->enc, cprop[nenc], + sprop[nenc])) != 0) { + kex->failed_choice = peer[nenc]; + peer[nenc] = NULL; + goto out; + } authlen = cipher_authlen(newkeys->enc.cipher); - if (authlen == 0) - choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); - choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); + /* ignore mac for authenticated encryption */ + if (authlen == 0 && + (r = choose_mac(ssh, &newkeys->mac, cprop[nmac], + sprop[nmac])) != 0) { + kex->failed_choice = peer[nmac]; + peer[nmac] = NULL; + goto out; + } + if ((r = choose_comp(&newkeys->comp, cprop[ncomp], + sprop[ncomp])) != 0) { + kex->failed_choice = peer[ncomp]; + peer[ncomp] = NULL; + goto out; + } debug("kex: %s %s %s %s", ctos ? "client->server" : "server->client", newkeys->enc.name, authlen == 0 ? newkeys->mac.name : "", newkeys->comp.name); } - choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); - choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], - sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); + if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], + sprop[PROPOSAL_KEX_ALGS])) != 0) { + kex->failed_choice = peer[PROPOSAL_KEX_ALGS]; + peer[PROPOSAL_KEX_ALGS] = NULL; + goto out; + } + if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], + sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) { + kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS]; + peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL; + goto out; + } need = dh_need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; @@ -524,45 +745,47 @@ kex_choose_conf(Kex *kex) /* ignore the next message if the proposals do not match */ if (first_kex_follows && !proposals_match(my, peer) && - !(datafellows & SSH_BUG_FIRSTKEX)) { - type = packet_read(); - debug2("skipping next packet (type %u)", type); - } - + !(ssh->compat & SSH_BUG_FIRSTKEX)) + ssh->dispatch_skip_packets = 1; + r = 0; + out: kex_prop_free(my); kex_prop_free(peer); + return r; } -static u_char * -derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, - const u_char *shared_secret, u_int slen) +static int +derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, + const struct sshbuf *shared_secret, u_char **keyp) { - Buffer b; - struct ssh_digest_ctx *hashctx; + struct kex *kex = ssh->kex; + struct ssh_digest_ctx *hashctx = NULL; char c = id; u_int have; size_t mdsz; u_char *digest; + int r; if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) - fatal("bad kex md size %zu", mdsz); - digest = xmalloc(roundup(need, mdsz)); - - buffer_init(&b); - buffer_append(&b, shared_secret, slen); + return SSH_ERR_INVALID_ARGUMENT; + if ((digest = calloc(1, roundup(need, mdsz))) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } /* K1 = HASH(K || H || "A" || session_id) */ - if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) - fatal("%s: ssh_digest_start failed", __func__); - if (ssh_digest_update_buffer(hashctx, &b) != 0 || + if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || + ssh_digest_update_buffer(hashctx, shared_secret) != 0 || ssh_digest_update(hashctx, hash, hashlen) != 0 || ssh_digest_update(hashctx, &c, 1) != 0 || ssh_digest_update(hashctx, kex->session_id, - kex->session_id_len) != 0) - fatal("%s: ssh_digest_update failed", __func__); - if (ssh_digest_final(hashctx, digest, mdsz) != 0) - fatal("%s: ssh_digest_final failed", __func__); + kex->session_id_len) != 0 || + ssh_digest_final(hashctx, digest, mdsz) != 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } ssh_digest_free(hashctx); + hashctx = NULL; /* * expand key: @@ -570,120 +793,123 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, * Key = K1 || K2 || ... || Kn */ for (have = mdsz; need > have; have += mdsz) { - if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) - fatal("%s: ssh_digest_start failed", __func__); - if (ssh_digest_update_buffer(hashctx, &b) != 0 || + if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || + ssh_digest_update_buffer(hashctx, shared_secret) != 0 || ssh_digest_update(hashctx, hash, hashlen) != 0 || - ssh_digest_update(hashctx, digest, have) != 0) - fatal("%s: ssh_digest_update failed", __func__); - if (ssh_digest_final(hashctx, digest + have, mdsz) != 0) - fatal("%s: ssh_digest_final failed", __func__); + ssh_digest_update(hashctx, digest, have) != 0 || + ssh_digest_final(hashctx, digest + have, mdsz) != 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } ssh_digest_free(hashctx); + hashctx = NULL; } - buffer_free(&b); #ifdef DEBUG_KEX fprintf(stderr, "key '%c'== ", c); dump_digest("key", digest, need); #endif - return digest; + *keyp = digest; + digest = NULL; + r = 0; + out: + if (digest) + free(digest); + ssh_digest_free(hashctx); + return r; } -Newkeys *current_keys[MODE_MAX]; - #define NKEYS 6 -void -kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, - const u_char *shared_secret, u_int slen) +int +kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen, + const struct sshbuf *shared_secret) { + struct kex *kex = ssh->kex; u_char *keys[NKEYS]; - u_int i, mode, ctos; + u_int i, j, mode, ctos; + int r; for (i = 0; i < NKEYS; i++) { - keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, - shared_secret, slen); + if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen, + shared_secret, &keys[i])) != 0) { + for (j = 0; j < i; j++) + free(keys[j]); + return r; + } } - - debug2("kex_derive_keys"); for (mode = 0; mode < MODE_MAX; mode++) { - current_keys[mode] = kex->newkeys[mode]; - kex->newkeys[mode] = NULL; ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); - current_keys[mode]->enc.iv = keys[ctos ? 0 : 1]; - current_keys[mode]->enc.key = keys[ctos ? 2 : 3]; - current_keys[mode]->mac.key = keys[ctos ? 4 : 5]; + kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1]; + kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; + kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; } + return 0; } -void -kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) -{ - Buffer shared_secret; - - buffer_init(&shared_secret); - buffer_put_bignum2(&shared_secret, secret); - kex_derive_keys(kex, hash, hashlen, - buffer_ptr(&shared_secret), buffer_len(&shared_secret)); - buffer_free(&shared_secret); -} - -Newkeys * -kex_get_newkeys(int mode) +#ifdef WITH_OPENSSL +int +kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen, + const BIGNUM *secret) { - Newkeys *ret; - - ret = current_keys[mode]; - current_keys[mode] = NULL; - return ret; + struct sshbuf *shared_secret; + int r; + + if ((shared_secret = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0) + r = kex_derive_keys(ssh, hash, hashlen, shared_secret); + sshbuf_free(shared_secret); + return r; } +#endif -void +#ifdef WITH_SSH1 +int derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, u_int8_t cookie[8], u_int8_t id[16]) { - u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; - int len; - struct ssh_digest_ctx *hashctx; - - if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) - fatal("%s: ssh_digest_start", __func__); - - len = BN_num_bytes(host_modulus); - if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) - fatal("%s: bad host modulus (len %d)", __func__, len); - BN_bn2bin(host_modulus, nbuf); - if (ssh_digest_update(hashctx, nbuf, len) != 0) - fatal("%s: ssh_digest_update failed", __func__); - - len = BN_num_bytes(server_modulus); - if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) - fatal("%s: bad server modulus (len %d)", __func__, len); - BN_bn2bin(server_modulus, nbuf); - if (ssh_digest_update(hashctx, nbuf, len) != 0 || - ssh_digest_update(hashctx, cookie, 8) != 0) - fatal("%s: ssh_digest_update failed", __func__); - if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) - fatal("%s: ssh_digest_final failed", __func__); + u_int8_t hbuf[2048], sbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; + struct ssh_digest_ctx *hashctx = NULL; + size_t hlen, slen; + int r; + + hlen = BN_num_bytes(host_modulus); + slen = BN_num_bytes(server_modulus); + if (hlen < (512 / 8) || (u_int)hlen > sizeof(hbuf) || + slen < (512 / 8) || (u_int)slen > sizeof(sbuf)) + return SSH_ERR_KEY_BITS_MISMATCH; + if (BN_bn2bin(host_modulus, hbuf) <= 0 || + BN_bn2bin(server_modulus, sbuf) <= 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (ssh_digest_update(hashctx, hbuf, hlen) != 0 || + ssh_digest_update(hashctx, sbuf, slen) != 0 || + ssh_digest_update(hashctx, cookie, 8) != 0 || + ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); - - explicit_bzero(nbuf, sizeof(nbuf)); + r = 0; + out: + ssh_digest_free(hashctx); + explicit_bzero(hbuf, sizeof(hbuf)); + explicit_bzero(sbuf, sizeof(sbuf)); explicit_bzero(obuf, sizeof(obuf)); + return r; } +#endif #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(char *msg, u_char *digest, int len) { - int i; - fprintf(stderr, "%s\n", msg); - for (i = 0; i < len; i++) { - fprintf(stderr, "%02x", digest[i]); - if (i%32 == 31) - fprintf(stderr, "\n"); - else if (i%8 == 7) - fprintf(stderr, " "); - } - fprintf(stderr, "\n"); + sshbuf_dump_data(digest, len, stderr); } #endif diff --git a/crypto/openssh/kex.h b/crypto/openssh/kex.h index c85680e..d71b532 100644 --- a/crypto/openssh/kex.h +++ b/crypto/openssh/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.62 2014/01/27 18:58:14 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.73 2015/07/30 00:01:34 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -26,13 +26,28 @@ #ifndef KEX_H #define KEX_H -#include -#include -#include -#ifdef OPENSSL_HAS_ECC -#include +#include "mac.h" +#include "buffer.h" /* XXX for typedef */ +#include "key.h" /* XXX for typedef */ + +#ifdef WITH_LEAKMALLOC +#include "leakmalloc.h" #endif +#ifdef WITH_OPENSSL +# ifdef OPENSSL_HAS_ECC +# include +# else /* OPENSSL_HAS_ECC */ +# define EC_KEY void +# define EC_GROUP void +# define EC_POINT void +# endif /* OPENSSL_HAS_ECC */ +#else /* WITH_OPENSSL */ +# define EC_KEY void +# define EC_GROUP void +# define EC_POINT void +#endif /* WITH_OPENSSL */ + #define KEX_COOKIE_LEN 16 #define KEX_DH1 "diffie-hellman-group1-sha1" @@ -49,6 +64,8 @@ #define COMP_ZLIB 1 #define COMP_DELAYED 2 +#define CURVE25519_SIZE 32 + enum kex_init_proposals { PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, @@ -81,15 +98,9 @@ enum kex_exchange { #define KEX_INIT_SENT 0x0001 -typedef struct Kex Kex; -typedef struct Mac Mac; -typedef struct Comp Comp; -typedef struct Enc Enc; -typedef struct Newkeys Newkeys; - -struct Enc { +struct sshenc { char *name; - const Cipher *cipher; + const struct sshcipher *cipher; int enabled; u_int key_len; u_int iv_len; @@ -97,108 +108,123 @@ struct Enc { u_char *key; u_char *iv; }; -struct Mac { - char *name; - int enabled; - u_int mac_len; - u_char *key; - u_int key_len; - int type; - int etm; /* Encrypt-then-MAC */ - struct ssh_hmac_ctx *hmac_ctx; - struct umac_ctx *umac_ctx; -}; -struct Comp { - int type; +struct sshcomp { + u_int type; int enabled; char *name; }; -struct Newkeys { - Enc enc; - Mac mac; - Comp comp; +struct newkeys { + struct sshenc enc; + struct sshmac mac; + struct sshcomp comp; }; -struct Kex { + +struct ssh; + +struct kex { u_char *session_id; - u_int session_id_len; - Newkeys *newkeys[MODE_MAX]; + size_t session_id_len; + struct newkeys *newkeys[MODE_MAX]; u_int we_need; u_int dh_need; int server; char *name; int hostkey_type; - int kex_type; + int hostkey_nid; + u_int kex_type; int roaming; - Buffer my; - Buffer peer; + struct sshbuf *my; + struct sshbuf *peer; sig_atomic_t done; - int flags; + u_int flags; int hash_alg; int ec_nid; char *client_version_string; char *server_version_string; - int (*verify_host_key)(Key *); - Key *(*load_host_public_key)(int); - Key *(*load_host_private_key)(int); - int (*host_key_index)(Key *); - void (*sign)(Key *, Key *, u_char **, u_int *, u_char *, u_int); - void (*kex[KEX_MAX])(Kex *); + char *failed_choice; + int (*verify_host_key)(struct sshkey *, struct ssh *); + struct sshkey *(*load_host_public_key)(int, int, struct ssh *); + struct sshkey *(*load_host_private_key)(int, int, struct ssh *); + int (*host_key_index)(struct sshkey *, int, struct ssh *); + int (*sign)(struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, u_int); + int (*kex[KEX_MAX])(struct ssh *); + /* kex specific state */ + DH *dh; /* DH */ + u_int min, max, nbits; /* GEX */ + EC_KEY *ec_client_key; /* ECDH */ + const EC_GROUP *ec_group; /* ECDH */ + u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 */ + u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ }; int kex_names_valid(const char *); char *kex_alg_list(char); - -Kex *kex_setup(char *[PROPOSAL_MAX]); -void kex_finish(Kex *); - -void kex_send_kexinit(Kex *); -void kex_input_kexinit(int, u_int32_t, void *); -void kex_derive_keys(Kex *, u_char *, u_int, const u_char *, u_int); -void kex_derive_keys_bn(Kex *, u_char *, u_int, const BIGNUM *); - -Newkeys *kex_get_newkeys(int); - -void kexdh_client(Kex *); -void kexdh_server(Kex *); -void kexgex_client(Kex *); -void kexgex_server(Kex *); -void kexecdh_client(Kex *); -void kexecdh_server(Kex *); -void kexc25519_client(Kex *); -void kexc25519_server(Kex *); - -void -kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, - BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); -void -kexgex_hash(int, char *, char *, char *, int, char *, - int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, - BIGNUM *, BIGNUM *, u_char **, u_int *); -#ifdef OPENSSL_HAS_ECC -void -kex_ecdh_hash(int, const EC_GROUP *, char *, char *, char *, int, - char *, int, u_char *, int, const EC_POINT *, const EC_POINT *, - const BIGNUM *, u_char **, u_int *); -#endif -void -kex_c25519_hash(int, char *, char *, char *, int, - char *, int, u_char *, int, const u_char *, const u_char *, - const u_char *, u_int, u_char **, u_int *); - -#define CURVE25519_SIZE 32 -void kexc25519_keygen(u_char[CURVE25519_SIZE], u_char[CURVE25519_SIZE]) +char *kex_names_cat(const char *, const char *); +int kex_assemble_names(const char *, char **); + +int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **); +int kex_setup(struct ssh *, char *[PROPOSAL_MAX]); +void kex_free_newkeys(struct newkeys *); +void kex_free(struct kex *); + +int kex_buf2prop(struct sshbuf *, int *, char ***); +int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]); +void kex_prop_free(char **); + +int kex_send_kexinit(struct ssh *); +int kex_input_kexinit(int, u_int32_t, void *); +int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); +int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *); +int kex_send_newkeys(struct ssh *); + +int kexdh_client(struct ssh *); +int kexdh_server(struct ssh *); +int kexgex_client(struct ssh *); +int kexgex_server(struct ssh *); +int kexecdh_client(struct ssh *); +int kexecdh_server(struct ssh *); +int kexc25519_client(struct ssh *); +int kexc25519_server(struct ssh *); + +int kex_dh_hash(const char *, const char *, + const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, + const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); + +int kexgex_hash(int, const char *, const char *, + const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, + int, int, int, + const BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, + u_char *, size_t *); + +int kex_ecdh_hash(int, const EC_GROUP *, const char *, const char *, + const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, + const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *); + +int kex_c25519_hash(int, const char *, const char *, const char *, size_t, + const char *, size_t, const u_char *, size_t, const u_char *, const u_char *, + const u_char *, size_t, u_char *, size_t *); + +void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -void kexc25519_shared_key(const u_char key[CURVE25519_SIZE], - const u_char pub[CURVE25519_SIZE], Buffer *out) +int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], struct sshbuf *out) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -void +int derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(char *, u_char *, int); #endif +#if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC) +# undef EC_KEY +# undef EC_GROUP +# undef EC_POINT +#endif + #endif diff --git a/crypto/openssh/kexc25519.c b/crypto/openssh/kexc25519.c index ee79b43..8d8cd4a 100644 --- a/crypto/openssh/kexc25519.c +++ b/crypto/openssh/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.5 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.9 2015/03/26 07:00:04 djm Exp $ */ /* * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -35,13 +35,14 @@ #include #include -#include "buffer.h" +#include "sshbuf.h" #include "ssh2.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" #include "kex.h" #include "log.h" #include "digest.h" +#include "ssherr.h" extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE]) @@ -58,65 +59,75 @@ kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) crypto_scalarmult_curve25519(pub, key, basepoint); } -void +int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], - const u_char pub[CURVE25519_SIZE], Buffer *out) + const u_char pub[CURVE25519_SIZE], struct sshbuf *out) { u_char shared_key[CURVE25519_SIZE]; + int r; + + /* Check for all-zero public key */ + explicit_bzero(shared_key, CURVE25519_SIZE); + if (timingsafe_bcmp(pub, shared_key, CURVE25519_SIZE) == 0) + return SSH_ERR_KEY_INVALID_EC_VALUE; crypto_scalarmult_curve25519(shared_key, key, pub); #ifdef DEBUG_KEXECDH dump_digest("shared secret", shared_key, CURVE25519_SIZE); #endif - buffer_clear(out); - buffer_put_bignum2_from_string(out, shared_key, CURVE25519_SIZE); + sshbuf_reset(out); + r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE); explicit_bzero(shared_key, CURVE25519_SIZE); + return r; } -void +int kex_c25519_hash( int hash_alg, - char *client_version_string, - char *server_version_string, - char *ckexinit, int ckexinitlen, - char *skexinit, int skexinitlen, - u_char *serverhostkeyblob, int sbloblen, + const char *client_version_string, + const char *server_version_string, + const char *ckexinit, size_t ckexinitlen, + const char *skexinit, size_t skexinitlen, + const u_char *serverhostkeyblob, size_t sbloblen, const u_char client_dh_pub[CURVE25519_SIZE], const u_char server_dh_pub[CURVE25519_SIZE], - const u_char *shared_secret, u_int secretlen, - u_char **hash, u_int *hashlen) + const u_char *shared_secret, size_t secretlen, + u_char *hash, size_t *hashlen) { - Buffer b; - static u_char digest[SSH_DIGEST_MAX_LENGTH]; - - buffer_init(&b); - buffer_put_cstring(&b, client_version_string); - buffer_put_cstring(&b, server_version_string); - - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - buffer_put_int(&b, ckexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, ckexinit, ckexinitlen); - buffer_put_int(&b, skexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, skexinit, skexinitlen); - - buffer_put_string(&b, serverhostkeyblob, sbloblen); - buffer_put_string(&b, client_dh_pub, CURVE25519_SIZE); - buffer_put_string(&b, server_dh_pub, CURVE25519_SIZE); - buffer_append(&b, shared_secret, secretlen); - + struct sshbuf *b; + int r; + + if (*hashlen < ssh_digest_bytes(hash_alg)) + return SSH_ERR_INVALID_ARGUMENT; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 || + (r = sshbuf_put_cstring(b, server_version_string)) < 0 || + /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ + (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || + (r = sshbuf_put(b, ckexinit, ckexinitlen)) < 0 || + (r = sshbuf_put_u32(b, skexinitlen+1)) < 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || + (r = sshbuf_put(b, skexinit, skexinitlen)) < 0 || + (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) < 0 || + (r = sshbuf_put_string(b, client_dh_pub, CURVE25519_SIZE)) < 0 || + (r = sshbuf_put_string(b, server_dh_pub, CURVE25519_SIZE)) < 0 || + (r = sshbuf_put(b, shared_secret, secretlen)) < 0) { + sshbuf_free(b); + return r; + } #ifdef DEBUG_KEX - buffer_dump(&b); + sshbuf_dump(b, stderr); #endif - if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) - fatal("%s: digest_buffer failed", __func__); - - buffer_free(&b); - + if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { + sshbuf_free(b); + return SSH_ERR_LIBCRYPTO_ERROR; + } + sshbuf_free(b); + *hashlen = ssh_digest_bytes(hash_alg); #ifdef DEBUG_KEX - dump_digest("hash", digest, ssh_digest_bytes(hash_alg)); + dump_digest("hash", hash, *hashlen); #endif - *hash = digest; - *hashlen = ssh_digest_bytes(hash_alg); + return 0; } diff --git a/crypto/openssh/kexc25519c.c b/crypto/openssh/kexc25519c.c index a80678a..b7ef65d 100644 --- a/crypto/openssh/kexc25519c.c +++ b/crypto/openssh/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.4 2014/01/12 08:13:13 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.7 2015/01/26 06:10:03 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -33,97 +33,138 @@ #include #include -#include "xmalloc.h" -#include "buffer.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" #include "kex.h" #include "log.h" #include "packet.h" #include "ssh2.h" +#include "sshbuf.h" +#include "digest.h" +#include "ssherr.h" -void -kexc25519_client(Kex *kex) -{ - Key *server_host_key; - u_char client_key[CURVE25519_SIZE]; - u_char client_pubkey[CURVE25519_SIZE]; - u_char *server_pubkey = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *hash; - u_int slen, sbloblen, hashlen; - Buffer shared_secret; - - kexc25519_keygen(client_key, client_pubkey); +static int +input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt); - packet_start(SSH2_MSG_KEX_ECDH_INIT); - packet_put_string(client_pubkey, sizeof(client_pubkey)); - packet_send(); - debug("sending SSH2_MSG_KEX_ECDH_INIT"); +int +kexc25519_client(struct ssh *ssh) +{ + struct kex *kex = ssh->kex; + int r; + kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey); #ifdef DEBUG_KEXECDH - dump_digest("client private key:", client_key, sizeof(client_key)); + dump_digest("client private key:", kex->c25519_client_key, + sizeof(kex->c25519_client_key)); #endif + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || + (r = sshpkt_put_string(ssh, kex->c25519_client_pubkey, + sizeof(kex->c25519_client_pubkey))) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); - packet_read_expect(SSH2_MSG_KEX_ECDH_REPLY); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_c25519_reply); + return 0; +} + +static int +input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + struct sshkey *server_host_key = NULL; + struct sshbuf *shared_secret = NULL; + u_char *server_pubkey = NULL; + u_char *server_host_key_blob = NULL, *signature = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, pklen, sbloblen, hashlen; + int r; + + if (kex->verify_host_key == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } /* hostkey */ - server_host_key_blob = packet_get_string(&sbloblen); - server_host_key = key_from_blob(server_host_key_blob, sbloblen); - if (server_host_key == NULL) - fatal("cannot decode server_host_key_blob"); - if (server_host_key->type != kex->hostkey_type) - fatal("type mismatch for decoded server_host_key_blob"); - if (kex->verify_host_key == NULL) - fatal("cannot verify server_host_key"); - if (kex->verify_host_key(server_host_key) == -1) - fatal("server_host_key verification failed"); + if ((r = sshpkt_get_string(ssh, &server_host_key_blob, + &sbloblen)) != 0 || + (r = sshkey_from_blob(server_host_key_blob, sbloblen, + &server_host_key)) != 0) + goto out; + if (server_host_key->type != kex->hostkey_type || + (kex->hostkey_type == KEY_ECDSA && + server_host_key->ecdsa_nid != kex->hostkey_nid)) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + if (kex->verify_host_key(server_host_key, ssh) == -1) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } /* Q_S, server public key */ - server_pubkey = packet_get_string(&slen); - if (slen != CURVE25519_SIZE) - fatal("Incorrect size for server Curve25519 pubkey: %d", slen); + /* signed H */ + if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 || + (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; + if (pklen != CURVE25519_SIZE) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } #ifdef DEBUG_KEXECDH dump_digest("server public key:", server_pubkey, CURVE25519_SIZE); #endif - /* signed H */ - signature = packet_get_string(&slen); - packet_check_eom(); - - buffer_init(&shared_secret); - kexc25519_shared_key(client_key, server_pubkey, &shared_secret); + if ((shared_secret = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = kexc25519_shared_key(kex->c25519_client_key, server_pubkey, + shared_secret)) < 0) + goto out; /* calc and verify H */ - kex_c25519_hash( + hashlen = sizeof(hash); + if ((r = kex_c25519_hash( kex->hash_alg, kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->my), buffer_len(&kex->my), - buffer_ptr(&kex->peer), buffer_len(&kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, - client_pubkey, + kex->c25519_client_pubkey, server_pubkey, - buffer_ptr(&shared_secret), buffer_len(&shared_secret), - &hash, &hashlen - ); - free(server_host_key_blob); - free(server_pubkey); - if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) - fatal("key_verify failed for server_host_key"); - key_free(server_host_key); - free(signature); + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + hash, &hashlen)) < 0) + goto out; + + if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, + ssh->compat)) != 0) + goto out; /* save session id */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; - kex->session_id = xmalloc(kex->session_id_len); + kex->session_id = malloc(kex->session_id_len); + if (kex->session_id == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(kex->session_id, hash, kex->session_id_len); } - kex_derive_keys(kex, hash, hashlen, - buffer_ptr(&shared_secret), buffer_len(&shared_secret)); - buffer_free(&shared_secret); - kex_finish(kex); + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); +out: + explicit_bzero(hash, sizeof(hash)); + explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); + free(server_host_key_blob); + free(server_pubkey); + free(signature); + sshkey_free(server_host_key); + sshbuf_free(shared_secret); + return r; } diff --git a/crypto/openssh/kexc25519s.c b/crypto/openssh/kexc25519s.c index 2b8e8ef..2402725 100644 --- a/crypto/openssh/kexc25519s.c +++ b/crypto/openssh/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.4 2014/01/12 08:13:13 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.9 2015/04/27 00:37:53 dtucker Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -27,100 +27,133 @@ #include "includes.h" #include +#include #include #include -#include "xmalloc.h" -#include "buffer.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" +#include "digest.h" #include "kex.h" #include "log.h" #include "packet.h" #include "ssh2.h" +#include "sshbuf.h" +#include "ssherr.h" -void -kexc25519_server(Kex *kex) +static int input_kex_c25519_init(int, u_int32_t, void *); + +int +kexc25519_server(struct ssh *ssh) +{ + debug("expecting SSH2_MSG_KEX_ECDH_INIT"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_c25519_init); + return 0; +} + +static int +input_kex_c25519_init(int type, u_int32_t seq, void *ctxt) { - Key *server_host_private, *server_host_public; + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + struct sshkey *server_host_private, *server_host_public; + struct sshbuf *shared_secret = NULL; u_char *server_host_key_blob = NULL, *signature = NULL; u_char server_key[CURVE25519_SIZE]; u_char *client_pubkey = NULL; u_char server_pubkey[CURVE25519_SIZE]; - u_char *hash; - u_int slen, sbloblen, hashlen; - Buffer shared_secret; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, pklen, sbloblen, hashlen; + int r; /* generate private key */ kexc25519_keygen(server_key, server_pubkey); #ifdef DEBUG_KEXECDH dump_digest("server private key:", server_key, sizeof(server_key)); #endif - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) - fatal("Cannot load hostkey"); - server_host_public = kex->load_host_public_key(kex->hostkey_type); - if (server_host_public == NULL) - fatal("Unsupported hostkey type %d", kex->hostkey_type); - server_host_private = kex->load_host_private_key(kex->hostkey_type); - - debug("expecting SSH2_MSG_KEX_ECDH_INIT"); - packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); - client_pubkey = packet_get_string(&slen); - if (slen != CURVE25519_SIZE) - fatal("Incorrect size for server Curve25519 pubkey: %d", slen); - packet_check_eom(); + kex->load_host_private_key == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + server_host_public = kex->load_host_public_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + server_host_private = kex->load_host_private_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + if (server_host_public == NULL) { + r = SSH_ERR_NO_HOSTKEY_LOADED; + goto out; + } + if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; + if (pklen != CURVE25519_SIZE) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } #ifdef DEBUG_KEXECDH dump_digest("client public key:", client_pubkey, CURVE25519_SIZE); #endif - buffer_init(&shared_secret); - kexc25519_shared_key(server_key, client_pubkey, &shared_secret); + if ((shared_secret = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = kexc25519_shared_key(server_key, client_pubkey, + shared_secret)) < 0) + goto out; /* calc H */ - key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); - kex_c25519_hash( + if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, + &sbloblen)) != 0) + goto out; + hashlen = sizeof(hash); + if ((r = kex_c25519_hash( kex->hash_alg, kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - buffer_ptr(&kex->my), buffer_len(&kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, client_pubkey, server_pubkey, - buffer_ptr(&shared_secret), buffer_len(&shared_secret), - &hash, &hashlen - ); + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + hash, &hashlen)) < 0) + goto out; /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; - kex->session_id = xmalloc(kex->session_id_len); + kex->session_id = malloc(kex->session_id_len); + if (kex->session_id == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ - kex->sign(server_host_private, server_host_public, &signature, &slen, - hash, hashlen); - - /* destroy_sensitive_data(); */ + if ((r = kex->sign(server_host_private, server_host_public, + &signature, &slen, hash, hashlen, ssh->compat)) < 0) + goto out; /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ - packet_start(SSH2_MSG_KEX_ECDH_REPLY); - packet_put_string(server_host_key_blob, sbloblen); - packet_put_string(server_pubkey, sizeof(server_pubkey)); - packet_put_string(signature, slen); - packet_send(); - - free(signature); + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || + (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || + (r = sshpkt_put_string(ssh, server_pubkey, sizeof(server_pubkey))) != 0 || + (r = sshpkt_put_string(ssh, signature, slen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); +out: + explicit_bzero(hash, sizeof(hash)); + explicit_bzero(server_key, sizeof(server_key)); free(server_host_key_blob); - /* have keys, free server key */ + free(signature); free(client_pubkey); - - kex_derive_keys(kex, hash, hashlen, - buffer_ptr(&shared_secret), buffer_len(&shared_secret)); - buffer_free(&shared_secret); - kex_finish(kex); + sshbuf_free(shared_secret); + return r; } diff --git a/crypto/openssh/kexdh.c b/crypto/openssh/kexdh.c index e7cdadc..feea669 100644 --- a/crypto/openssh/kexdh.c +++ b/crypto/openssh/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.24 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.25 2015/01/19 20:16:15 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -25,63 +25,69 @@ #include "includes.h" +#ifdef WITH_OPENSSL + #include #include #include -#include "buffer.h" #include "ssh2.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" #include "kex.h" +#include "ssherr.h" +#include "sshbuf.h" #include "digest.h" -#include "log.h" -void +int kex_dh_hash( - char *client_version_string, - char *server_version_string, - char *ckexinit, int ckexinitlen, - char *skexinit, int skexinitlen, - u_char *serverhostkeyblob, int sbloblen, - BIGNUM *client_dh_pub, - BIGNUM *server_dh_pub, - BIGNUM *shared_secret, - u_char **hash, u_int *hashlen) + const char *client_version_string, + const char *server_version_string, + const u_char *ckexinit, size_t ckexinitlen, + const u_char *skexinit, size_t skexinitlen, + const u_char *serverhostkeyblob, size_t sbloblen, + const BIGNUM *client_dh_pub, + const BIGNUM *server_dh_pub, + const BIGNUM *shared_secret, + u_char *hash, size_t *hashlen) { - Buffer b; - static u_char digest[SSH_DIGEST_MAX_LENGTH]; - - buffer_init(&b); - buffer_put_cstring(&b, client_version_string); - buffer_put_cstring(&b, server_version_string); - - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - buffer_put_int(&b, ckexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, ckexinit, ckexinitlen); - buffer_put_int(&b, skexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, skexinit, skexinitlen); - - buffer_put_string(&b, serverhostkeyblob, sbloblen); - buffer_put_bignum2(&b, client_dh_pub); - buffer_put_bignum2(&b, server_dh_pub); - buffer_put_bignum2(&b, shared_secret); + struct sshbuf *b; + int r; + if (*hashlen < ssh_digest_bytes(SSH_DIGEST_SHA1)) + return SSH_ERR_INVALID_ARGUMENT; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || + (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ + (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || + (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || + (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || + (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || + (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || + (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { + sshbuf_free(b); + return r; + } #ifdef DEBUG_KEX - buffer_dump(&b); + sshbuf_dump(b, stderr); #endif - if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, digest, sizeof(digest)) != 0) - fatal("%s: ssh_digest_buffer failed", __func__); - - buffer_free(&b); - + if (ssh_digest_buffer(SSH_DIGEST_SHA1, b, hash, *hashlen) != 0) { + sshbuf_free(b); + return SSH_ERR_LIBCRYPTO_ERROR; + } + sshbuf_free(b); + *hashlen = ssh_digest_bytes(SSH_DIGEST_SHA1); #ifdef DEBUG_KEX - dump_digest("hash", digest, ssh_digest_bytes(SSH_DIGEST_SHA1)); + dump_digest("hash", hash, *hashlen); #endif - *hash = digest; - *hashlen = ssh_digest_bytes(SSH_DIGEST_SHA1); + return 0; } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/kexdhc.c b/crypto/openssh/kexdhc.c index f7a19fc..af259f1 100644 --- a/crypto/openssh/kexdhc.c +++ b/crypto/openssh/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.15 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.18 2015/01/26 06:10:03 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -25,6 +25,8 @@ #include "includes.h" +#ifdef WITH_OPENSSL + #include #include @@ -34,128 +36,177 @@ #include #include -#include "xmalloc.h" -#include "buffer.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" +#include "digest.h" #include "kex.h" #include "log.h" #include "packet.h" #include "dh.h" #include "ssh2.h" +#include "dispatch.h" +#include "compat.h" +#include "ssherr.h" +#include "sshbuf.h" + +static int input_kex_dh(int, u_int32_t, void *); -void -kexdh_client(Kex *kex) +int +kexdh_client(struct ssh *ssh) { - BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; - DH *dh; - Key *server_host_key; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *kbuf, *hash; - u_int klen, slen, sbloblen, hashlen; - int kout; + struct kex *kex = ssh->kex; + int r; /* generate and send 'e', client DH public key */ switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: - dh = dh_new_group1(); + kex->dh = dh_new_group1(); break; case KEX_DH_GRP14_SHA1: - dh = dh_new_group14(); + kex->dh = dh_new_group14(); break; default: - fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if (kex->dh == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } - dh_gen_key(dh, kex->we_need * 8); - packet_start(SSH2_MSG_KEXDH_INIT); - packet_put_bignum2(dh->pub_key); - packet_send(); - debug("sending SSH2_MSG_KEXDH_INIT"); + if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || + (r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || + (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; #ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, dh); + DHparams_print_fp(stderr, kex->dh); fprintf(stderr, "pub= "); - BN_print_fp(stderr, dh->pub_key); + BN_print_fp(stderr, kex->dh->pub_key); fprintf(stderr, "\n"); #endif - debug("expecting SSH2_MSG_KEXDH_REPLY"); - packet_read_expect(SSH2_MSG_KEXDH_REPLY); + ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh); + r = 0; + out: + return r; +} +static int +input_kex_dh(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; + struct sshkey *server_host_key = NULL; + u_char *kbuf = NULL, *server_host_key_blob = NULL, *signature = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t klen = 0, slen, sbloblen, hashlen; + int kout, r; + + if (kex->verify_host_key == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } /* key, cert */ - server_host_key_blob = packet_get_string(&sbloblen); - server_host_key = key_from_blob(server_host_key_blob, sbloblen); - if (server_host_key == NULL) - fatal("cannot decode server_host_key_blob"); - if (server_host_key->type != kex->hostkey_type) - fatal("type mismatch for decoded server_host_key_blob"); - if (kex->verify_host_key == NULL) - fatal("cannot verify server_host_key"); - if (kex->verify_host_key(server_host_key) == -1) - fatal("server_host_key verification failed"); - + if ((r = sshpkt_get_string(ssh, &server_host_key_blob, + &sbloblen)) != 0 || + (r = sshkey_from_blob(server_host_key_blob, sbloblen, + &server_host_key)) != 0) + goto out; + if (server_host_key->type != kex->hostkey_type || + (kex->hostkey_type == KEY_ECDSA && + server_host_key->ecdsa_nid != kex->hostkey_nid)) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + if (kex->verify_host_key(server_host_key, ssh) == -1) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } /* DH parameter f, server public DH key */ - if ((dh_server_pub = BN_new()) == NULL) - fatal("dh_server_pub == NULL"); - packet_get_bignum2(dh_server_pub); - + if ((dh_server_pub = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* signed H */ + if ((r = sshpkt_get_bignum2(ssh, dh_server_pub)) != 0 || + (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; #ifdef DEBUG_KEXDH fprintf(stderr, "dh_server_pub= "); BN_print_fp(stderr, dh_server_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_server_pub)); #endif + if (!dh_pub_is_valid(kex->dh, dh_server_pub)) { + sshpkt_disconnect(ssh, "bad server public DH value"); + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } - /* signed H */ - signature = packet_get_string(&slen); - packet_check_eom(); - - if (!dh_pub_is_valid(dh, dh_server_pub)) - packet_disconnect("bad server public DH value"); - - klen = DH_size(dh); - kbuf = xmalloc(klen); - if ((kout = DH_compute_key(kbuf, dh_server_pub, dh)) < 0) - fatal("DH_compute_key: failed"); + klen = DH_size(kex->dh); + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 || + BN_bin2bn(kbuf, kout, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif - if ((shared_secret = BN_new()) == NULL) - fatal("kexdh_client: BN_new failed"); - if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) - fatal("kexdh_client: BN_bin2bn failed"); - explicit_bzero(kbuf, klen); - free(kbuf); /* calc and verify H */ - kex_dh_hash( + hashlen = sizeof(hash); + if ((r = kex_dh_hash( kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->my), buffer_len(&kex->my), - buffer_ptr(&kex->peer), buffer_len(&kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, - dh->pub_key, + kex->dh->pub_key, dh_server_pub, shared_secret, - &hash, &hashlen - ); - free(server_host_key_blob); - BN_clear_free(dh_server_pub); - DH_free(dh); + hash, &hashlen)) != 0) + goto out; - if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) - fatal("key_verify failed for server_host_key"); - key_free(server_host_key); - free(signature); + if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, + ssh->compat)) != 0) + goto out; /* save session id */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; - kex->session_id = xmalloc(kex->session_id_len); + kex->session_id = malloc(kex->session_id_len); + if (kex->session_id == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(kex->session_id, hash, kex->session_id_len); } - kex_derive_keys_bn(kex, hash, hashlen, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); + if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + out: + explicit_bzero(hash, sizeof(hash)); + DH_free(kex->dh); + kex->dh = NULL; + if (dh_server_pub) + BN_clear_free(dh_server_pub); + if (kbuf) { + explicit_bzero(kbuf, klen); + free(kbuf); + } + if (shared_secret) + BN_clear_free(shared_secret); + sshkey_free(server_host_key); + free(server_host_key_blob); + free(signature); + return r; } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/kexdhs.c b/crypto/openssh/kexdhs.c index c3011f7..de7c05b 100644 --- a/crypto/openssh/kexdhs.c +++ b/crypto/openssh/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.18 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.22 2015/01/26 06:10:03 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -25,6 +25,8 @@ #include "includes.h" +#ifdef WITH_OPENSSL + #include #include @@ -33,55 +35,89 @@ #include -#include "xmalloc.h" -#include "buffer.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" +#include "digest.h" #include "kex.h" #include "log.h" #include "packet.h" #include "dh.h" #include "ssh2.h" -void -kexdh_server(Kex *kex) +#include "dispatch.h" +#include "compat.h" +#include "ssherr.h" +#include "sshbuf.h" + +static int input_kex_dh_init(int, u_int32_t, void *); + +int +kexdh_server(struct ssh *ssh) { - BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; - DH *dh; - Key *server_host_public, *server_host_private; - u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; - u_int sbloblen, klen, hashlen, slen; - int kout; + struct kex *kex = ssh->kex; + int r; /* generate server DH public key */ switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: - dh = dh_new_group1(); + kex->dh = dh_new_group1(); break; case KEX_DH_GRP14_SHA1: - dh = dh_new_group14(); + kex->dh = dh_new_group14(); break; default: - fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if (kex->dh == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } - dh_gen_key(dh, kex->we_need * 8); + if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) + goto out; debug("expecting SSH2_MSG_KEXDH_INIT"); - packet_read_expect(SSH2_MSG_KEXDH_INIT); + ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init); + r = 0; + out: + return r; +} + +int +input_kex_dh_init(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; + struct sshkey *server_host_public, *server_host_private; + u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t sbloblen, slen; + size_t klen = 0, hashlen; + int kout, r; if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) - fatal("Cannot load hostkey"); - server_host_public = kex->load_host_public_key(kex->hostkey_type); - if (server_host_public == NULL) - fatal("Unsupported hostkey type %d", kex->hostkey_type); - server_host_private = kex->load_host_private_key(kex->hostkey_type); + kex->load_host_private_key == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + server_host_public = kex->load_host_public_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + server_host_private = kex->load_host_private_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + if (server_host_public == NULL) { + r = SSH_ERR_NO_HOSTKEY_LOADED; + goto out; + } /* key, cert */ - if ((dh_client_pub = BN_new()) == NULL) - fatal("dh_client_pub == NULL"); - packet_get_bignum2(dh_client_pub); - packet_check_eom(); + if ((dh_client_pub = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); @@ -91,70 +127,90 @@ kexdh_server(Kex *kex) #endif #ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, dh); + DHparams_print_fp(stderr, kex->dh); fprintf(stderr, "pub= "); - BN_print_fp(stderr, dh->pub_key); + BN_print_fp(stderr, kex->dh->pub_key); fprintf(stderr, "\n"); #endif - if (!dh_pub_is_valid(dh, dh_client_pub)) - packet_disconnect("bad client public DH value"); + if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { + sshpkt_disconnect(ssh, "bad client public DH value"); + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } - klen = DH_size(dh); - kbuf = xmalloc(klen); - if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0) - fatal("DH_compute_key: failed"); + klen = DH_size(kex->dh); + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || + BN_bin2bn(kbuf, kout, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif - if ((shared_secret = BN_new()) == NULL) - fatal("kexdh_server: BN_new failed"); - if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) - fatal("kexdh_server: BN_bin2bn failed"); - explicit_bzero(kbuf, klen); - free(kbuf); - - key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); - + if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, + &sbloblen)) != 0) + goto out; /* calc H */ - kex_dh_hash( + hashlen = sizeof(hash); + if ((r = kex_dh_hash( kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - buffer_ptr(&kex->my), buffer_len(&kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, dh_client_pub, - dh->pub_key, + kex->dh->pub_key, shared_secret, - &hash, &hashlen - ); - BN_clear_free(dh_client_pub); + hash, &hashlen)) != 0) + goto out; /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; - kex->session_id = xmalloc(kex->session_id_len); + kex->session_id = malloc(kex->session_id_len); + if (kex->session_id == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ - kex->sign(server_host_private, server_host_public, &signature, &slen, - hash, hashlen); + if ((r = kex->sign(server_host_private, server_host_public, + &signature, &slen, hash, hashlen, ssh->compat)) < 0) + goto out; /* destroy_sensitive_data(); */ /* send server hostkey, DH pubkey 'f' and singed H */ - packet_start(SSH2_MSG_KEXDH_REPLY); - packet_put_string(server_host_key_blob, sbloblen); - packet_put_bignum2(dh->pub_key); /* f */ - packet_put_string(signature, slen); - packet_send(); - - free(signature); + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 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_string(ssh, signature, slen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + + if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + out: + explicit_bzero(hash, sizeof(hash)); + DH_free(kex->dh); + kex->dh = NULL; + if (dh_client_pub) + BN_clear_free(dh_client_pub); + if (kbuf) { + explicit_bzero(kbuf, klen); + free(kbuf); + } + if (shared_secret) + BN_clear_free(shared_secret); free(server_host_key_blob); - /* have keys, free DH */ - DH_free(dh); - - kex_derive_keys_bn(kex, hash, hashlen, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); + free(signature); + return r; } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/kexecdh.c b/crypto/openssh/kexecdh.c index c52c5e2..2a4fec6 100644 --- a/crypto/openssh/kexecdh.c +++ b/crypto/openssh/kexecdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdh.c,v 1.5 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -26,7 +26,7 @@ #include "includes.h" -#ifdef OPENSSL_HAS_ECC +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) #include @@ -38,60 +38,63 @@ #include #include -#include "buffer.h" #include "ssh2.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" #include "kex.h" -#include "log.h" +#include "sshbuf.h" #include "digest.h" +#include "ssherr.h" -void +int kex_ecdh_hash( int hash_alg, const EC_GROUP *ec_group, - char *client_version_string, - char *server_version_string, - char *ckexinit, int ckexinitlen, - char *skexinit, int skexinitlen, - u_char *serverhostkeyblob, int sbloblen, + const char *client_version_string, + const char *server_version_string, + const u_char *ckexinit, size_t ckexinitlen, + const u_char *skexinit, size_t skexinitlen, + const u_char *serverhostkeyblob, size_t sbloblen, const EC_POINT *client_dh_pub, const EC_POINT *server_dh_pub, const BIGNUM *shared_secret, - u_char **hash, u_int *hashlen) + u_char *hash, size_t *hashlen) { - Buffer b; - static u_char digest[SSH_DIGEST_MAX_LENGTH]; - - buffer_init(&b); - buffer_put_cstring(&b, client_version_string); - buffer_put_cstring(&b, server_version_string); - - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - buffer_put_int(&b, ckexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, ckexinit, ckexinitlen); - buffer_put_int(&b, skexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, skexinit, skexinitlen); - - buffer_put_string(&b, serverhostkeyblob, sbloblen); - buffer_put_ecpoint(&b, ec_group, client_dh_pub); - buffer_put_ecpoint(&b, ec_group, server_dh_pub); - buffer_put_bignum2(&b, shared_secret); + struct sshbuf *b; + int r; + if (*hashlen < ssh_digest_bytes(hash_alg)) + return SSH_ERR_INVALID_ARGUMENT; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || + (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ + (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || + (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || + (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || + (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 || + (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 || + (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { + sshbuf_free(b); + return r; + } #ifdef DEBUG_KEX - buffer_dump(&b); + sshbuf_dump(b, stderr); #endif - if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) - fatal("%s: ssh_digest_buffer failed", __func__); - - buffer_free(&b); - + if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { + sshbuf_free(b); + return SSH_ERR_LIBCRYPTO_ERROR; + } + sshbuf_free(b); + *hashlen = ssh_digest_bytes(hash_alg); #ifdef DEBUG_KEX - dump_digest("hash", digest, ssh_digest_bytes(hash_alg)); + dump_digest("hash", hash, *hashlen); #endif - *hash = digest; - *hashlen = ssh_digest_bytes(hash_alg); + return 0; } -#endif /* OPENSSL_HAS_ECC */ +#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ diff --git a/crypto/openssh/kexecdhc.c b/crypto/openssh/kexecdhc.c index 2f7629c..90220ce 100644 --- a/crypto/openssh/kexecdhc.c +++ b/crypto/openssh/kexecdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhc.c,v 1.7 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: kexecdhc.c,v 1.10 2015/01/26 06:10:03 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -26,140 +26,203 @@ #include "includes.h" +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + #include #include #include #include -#include "xmalloc.h" -#include "buffer.h" -#include "key.h" +#include + +#include "sshkey.h" #include "cipher.h" +#include "digest.h" #include "kex.h" #include "log.h" #include "packet.h" #include "dh.h" #include "ssh2.h" +#include "dispatch.h" +#include "compat.h" +#include "ssherr.h" +#include "sshbuf.h" -#ifdef OPENSSL_HAS_ECC - -#include +static int input_kex_ecdh_reply(int, u_int32_t, void *); -void -kexecdh_client(Kex *kex) +int +kexecdh_client(struct ssh *ssh) { - EC_KEY *client_key; - EC_POINT *server_public; + struct kex *kex = ssh->kex; + EC_KEY *client_key = NULL; const EC_GROUP *group; - BIGNUM *shared_secret; - Key *server_host_key; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *kbuf, *hash; - u_int klen, slen, sbloblen, hashlen; + const EC_POINT *public_key; + int r; - if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) - fatal("%s: EC_KEY_new_by_curve_name failed", __func__); - if (EC_KEY_generate_key(client_key) != 1) - fatal("%s: EC_KEY_generate_key failed", __func__); + if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_KEY_generate_key(client_key) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } group = EC_KEY_get0_group(client_key); + public_key = EC_KEY_get0_public_key(client_key); - packet_start(SSH2_MSG_KEX_ECDH_INIT); - packet_put_ecpoint(group, EC_KEY_get0_public_key(client_key)); - packet_send(); + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || + (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; debug("sending SSH2_MSG_KEX_ECDH_INIT"); #ifdef DEBUG_KEXECDH fputs("client private key:\n", stderr); - key_dump_ec_key(client_key); + sshkey_dump_ec_key(client_key); #endif + kex->ec_client_key = client_key; + kex->ec_group = group; + client_key = NULL; /* owned by the kex */ debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); - packet_read_expect(SSH2_MSG_KEX_ECDH_REPLY); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_ecdh_reply); + r = 0; + out: + if (client_key) + EC_KEY_free(client_key); + return r; +} + +static int +input_kex_ecdh_reply(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + const EC_GROUP *group; + EC_POINT *server_public = NULL; + EC_KEY *client_key; + BIGNUM *shared_secret = NULL; + struct sshkey *server_host_key = NULL; + u_char *server_host_key_blob = NULL, *signature = NULL; + u_char *kbuf = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, sbloblen; + size_t klen = 0, hashlen; + int r; + + if (kex->verify_host_key == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + group = kex->ec_group; + client_key = kex->ec_client_key; /* hostkey */ - server_host_key_blob = packet_get_string(&sbloblen); - server_host_key = key_from_blob(server_host_key_blob, sbloblen); - if (server_host_key == NULL) - fatal("cannot decode server_host_key_blob"); - if (server_host_key->type != kex->hostkey_type) - fatal("type mismatch for decoded server_host_key_blob"); - if (kex->verify_host_key == NULL) - fatal("cannot verify server_host_key"); - if (kex->verify_host_key(server_host_key) == -1) - fatal("server_host_key verification failed"); + if ((r = sshpkt_get_string(ssh, &server_host_key_blob, + &sbloblen)) != 0 || + (r = sshkey_from_blob(server_host_key_blob, sbloblen, + &server_host_key)) != 0) + goto out; + if (server_host_key->type != kex->hostkey_type || + (kex->hostkey_type == KEY_ECDSA && + server_host_key->ecdsa_nid != kex->hostkey_nid)) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + if (kex->verify_host_key(server_host_key, ssh) == -1) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } /* Q_S, server public key */ - if ((server_public = EC_POINT_new(group)) == NULL) - fatal("%s: EC_POINT_new failed", __func__); - packet_get_ecpoint(group, server_public); - - if (key_ec_validate_public(group, server_public) != 0) - fatal("%s: invalid server public key", __func__); + /* signed H */ + if ((server_public = EC_POINT_new(group)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 || + (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; #ifdef DEBUG_KEXECDH fputs("server public key:\n", stderr); - key_dump_ec_point(group, server_public); + sshkey_dump_ec_point(group, server_public); #endif - - /* signed H */ - signature = packet_get_string(&slen); - packet_check_eom(); + if (sshkey_ec_validate_public(group, server_public) != 0) { + sshpkt_disconnect(ssh, "invalid server public key"); + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } klen = (EC_GROUP_get_degree(group) + 7) / 8; - kbuf = xmalloc(klen); + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } if (ECDH_compute_key(kbuf, klen, server_public, - client_key, NULL) != (int)klen) - fatal("%s: ECDH_compute_key failed", __func__); + client_key, NULL) != (int)klen || + BN_bin2bn(kbuf, klen, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } #ifdef DEBUG_KEXECDH dump_digest("shared secret", kbuf, klen); #endif - if ((shared_secret = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - if (BN_bin2bn(kbuf, klen, shared_secret) == NULL) - fatal("%s: BN_bin2bn failed", __func__); - explicit_bzero(kbuf, klen); - free(kbuf); - /* calc and verify H */ - kex_ecdh_hash( + hashlen = sizeof(hash); + if ((r = kex_ecdh_hash( kex->hash_alg, group, kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->my), buffer_len(&kex->my), - buffer_ptr(&kex->peer), buffer_len(&kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, EC_KEY_get0_public_key(client_key), server_public, shared_secret, - &hash, &hashlen - ); - free(server_host_key_blob); - EC_POINT_clear_free(server_public); - EC_KEY_free(client_key); + hash, &hashlen)) != 0) + goto out; - if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) - fatal("key_verify failed for server_host_key"); - key_free(server_host_key); - free(signature); + if ((r = sshkey_verify(server_host_key, signature, slen, hash, + hashlen, ssh->compat)) != 0) + goto out; /* save session id */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; - kex->session_id = xmalloc(kex->session_id_len); + kex->session_id = malloc(kex->session_id_len); + if (kex->session_id == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(kex->session_id, hash, kex->session_id_len); } - kex_derive_keys_bn(kex, hash, hashlen, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); -} -#else /* OPENSSL_HAS_ECC */ -void -kexecdh_client(Kex *kex) -{ - fatal("ECC support is not enabled"); + if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + out: + explicit_bzero(hash, sizeof(hash)); + if (kex->ec_client_key) { + EC_KEY_free(kex->ec_client_key); + kex->ec_client_key = NULL; + } + if (server_public) + EC_POINT_clear_free(server_public); + if (kbuf) { + explicit_bzero(kbuf, klen); + free(kbuf); + } + if (shared_secret) + BN_clear_free(shared_secret); + sshkey_free(server_host_key); + free(server_host_key_blob); + free(signature); + return r; } -#endif /* OPENSSL_HAS_ECC */ +#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ + diff --git a/crypto/openssh/kexecdhs.c b/crypto/openssh/kexecdhs.c index 2700b72..0adb80e 100644 --- a/crypto/openssh/kexecdhs.c +++ b/crypto/openssh/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.10 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.14 2015/01/26 06:10:03 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -26,136 +26,183 @@ #include "includes.h" +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + #include #include #include -#include "xmalloc.h" -#include "buffer.h" -#include "key.h" +#include + +#include "sshkey.h" #include "cipher.h" +#include "digest.h" #include "kex.h" #include "log.h" #include "packet.h" #include "ssh2.h" -#ifdef OPENSSL_HAS_ECC +#include "dispatch.h" +#include "compat.h" +#include "ssherr.h" +#include "sshbuf.h" -#include +static int input_kex_ecdh_init(int, u_int32_t, void *); + +int +kexecdh_server(struct ssh *ssh) +{ + debug("expecting SSH2_MSG_KEX_ECDH_INIT"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_ecdh_init); + return 0; +} -void -kexecdh_server(Kex *kex) +static int +input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt) { + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; EC_POINT *client_public; - EC_KEY *server_key; + EC_KEY *server_key = NULL; const EC_GROUP *group; - BIGNUM *shared_secret; - Key *server_host_private, *server_host_public; + const EC_POINT *public_key; + BIGNUM *shared_secret = NULL; + struct sshkey *server_host_private, *server_host_public; u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *kbuf, *hash; - u_int klen, slen, sbloblen, hashlen; - - if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) - fatal("%s: EC_KEY_new_by_curve_name failed", __func__); - if (EC_KEY_generate_key(server_key) != 1) - fatal("%s: EC_KEY_generate_key failed", __func__); + u_char *kbuf = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, sbloblen; + size_t klen = 0, hashlen; + int r; + + if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_KEY_generate_key(server_key) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } group = EC_KEY_get0_group(server_key); #ifdef DEBUG_KEXECDH fputs("server private key:\n", stderr); - key_dump_ec_key(server_key); + sshkey_dump_ec_key(server_key); #endif if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) - fatal("Cannot load hostkey"); - server_host_public = kex->load_host_public_key(kex->hostkey_type); - if (server_host_public == NULL) - fatal("Unsupported hostkey type %d", kex->hostkey_type); - server_host_private = kex->load_host_private_key(kex->hostkey_type); - - debug("expecting SSH2_MSG_KEX_ECDH_INIT"); - packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); - if ((client_public = EC_POINT_new(group)) == NULL) - fatal("%s: EC_POINT_new failed", __func__); - packet_get_ecpoint(group, client_public); - packet_check_eom(); - - if (key_ec_validate_public(group, client_public) != 0) - fatal("%s: invalid client public key", __func__); + kex->load_host_private_key == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + server_host_public = kex->load_host_public_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + server_host_private = kex->load_host_private_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + if (server_host_public == NULL) { + r = SSH_ERR_NO_HOSTKEY_LOADED; + goto out; + } + if ((client_public = EC_POINT_new(group)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; #ifdef DEBUG_KEXECDH fputs("client public key:\n", stderr); - key_dump_ec_point(group, client_public); + sshkey_dump_ec_point(group, client_public); #endif + if (sshkey_ec_validate_public(group, client_public) != 0) { + sshpkt_disconnect(ssh, "invalid client public key"); + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } /* Calculate shared_secret */ klen = (EC_GROUP_get_degree(group) + 7) / 8; - kbuf = xmalloc(klen); + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } if (ECDH_compute_key(kbuf, klen, client_public, - server_key, NULL) != (int)klen) - fatal("%s: ECDH_compute_key failed", __func__); + server_key, NULL) != (int)klen || + BN_bin2bn(kbuf, klen, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } -#ifdef DEBUG_KEXDH +#ifdef DEBUG_KEXECDH dump_digest("shared secret", kbuf, klen); #endif - if ((shared_secret = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - if (BN_bin2bn(kbuf, klen, shared_secret) == NULL) - fatal("%s: BN_bin2bn failed", __func__); - explicit_bzero(kbuf, klen); - free(kbuf); - /* calc H */ - key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); - kex_ecdh_hash( + if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, + &sbloblen)) != 0) + goto out; + hashlen = sizeof(hash); + if ((r = kex_ecdh_hash( kex->hash_alg, group, kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - buffer_ptr(&kex->my), buffer_len(&kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, client_public, EC_KEY_get0_public_key(server_key), shared_secret, - &hash, &hashlen - ); - EC_POINT_clear_free(client_public); + hash, &hashlen)) != 0) + goto out; /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; - kex->session_id = xmalloc(kex->session_id_len); + kex->session_id = malloc(kex->session_id_len); + if (kex->session_id == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ - kex->sign(server_host_private, server_host_public, &signature, &slen, - hash, hashlen); + if ((r = kex->sign(server_host_private, server_host_public, + &signature, &slen, hash, hashlen, ssh->compat)) < 0) + goto out; /* destroy_sensitive_data(); */ + public_key = EC_KEY_get0_public_key(server_key); /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ - packet_start(SSH2_MSG_KEX_ECDH_REPLY); - packet_put_string(server_host_key_blob, sbloblen); - packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key)); - packet_put_string(signature, slen); - packet_send(); - - free(signature); + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || + (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || + (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || + (r = sshpkt_put_string(ssh, signature, slen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + + if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + out: + explicit_bzero(hash, sizeof(hash)); + if (kex->ec_client_key) { + EC_KEY_free(kex->ec_client_key); + kex->ec_client_key = NULL; + } + if (server_key) + EC_KEY_free(server_key); + if (kbuf) { + explicit_bzero(kbuf, klen); + free(kbuf); + } + if (shared_secret) + BN_clear_free(shared_secret); free(server_host_key_blob); - /* have keys, free server key */ - EC_KEY_free(server_key); - - kex_derive_keys_bn(kex, hash, hashlen, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); -} -#else /* OPENSSL_HAS_ECC */ -void -kexecdh_server(Kex *kex) -{ - fatal("ECC support is not enabled"); + free(signature); + return r; } -#endif /* OPENSSL_HAS_ECC */ +#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ + diff --git a/crypto/openssh/kexgex.c b/crypto/openssh/kexgex.c index c2e6bc1..8b0d833 100644 --- a/crypto/openssh/kexgex.c +++ b/crypto/openssh/kexgex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgex.c,v 1.28 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexgex.c,v 1.29 2015/01/19 20:16:15 markus Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -26,73 +26,77 @@ #include "includes.h" +#ifdef WITH_OPENSSL + #include #include #include -#include "buffer.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" #include "kex.h" #include "ssh2.h" +#include "ssherr.h" +#include "sshbuf.h" #include "digest.h" -#include "log.h" -void +int kexgex_hash( int hash_alg, - char *client_version_string, - char *server_version_string, - char *ckexinit, int ckexinitlen, - char *skexinit, int skexinitlen, - u_char *serverhostkeyblob, int sbloblen, - int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen, - BIGNUM *client_dh_pub, - BIGNUM *server_dh_pub, - BIGNUM *shared_secret, - u_char **hash, u_int *hashlen) + const char *client_version_string, + const char *server_version_string, + const u_char *ckexinit, size_t ckexinitlen, + const u_char *skexinit, size_t skexinitlen, + const u_char *serverhostkeyblob, size_t sbloblen, + int min, int wantbits, int max, + const BIGNUM *prime, + const BIGNUM *gen, + const BIGNUM *client_dh_pub, + const BIGNUM *server_dh_pub, + const BIGNUM *shared_secret, + u_char *hash, size_t *hashlen) { - Buffer b; - static u_char digest[SSH_DIGEST_MAX_LENGTH]; - - buffer_init(&b); - buffer_put_cstring(&b, client_version_string); - buffer_put_cstring(&b, server_version_string); - - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - buffer_put_int(&b, ckexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, ckexinit, ckexinitlen); - buffer_put_int(&b, skexinitlen+1); - buffer_put_char(&b, SSH2_MSG_KEXINIT); - buffer_append(&b, skexinit, skexinitlen); + struct sshbuf *b; + int r; - buffer_put_string(&b, serverhostkeyblob, sbloblen); - if (min == -1 || max == -1) - buffer_put_int(&b, wantbits); - else { - buffer_put_int(&b, min); - buffer_put_int(&b, wantbits); - buffer_put_int(&b, max); + if (*hashlen < ssh_digest_bytes(SSH_DIGEST_SHA1)) + return SSH_ERR_INVALID_ARGUMENT; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || + (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ + (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || + (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || + (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || + (min != -1 && (r = sshbuf_put_u32(b, min)) != 0) || + (r = sshbuf_put_u32(b, wantbits)) != 0 || + (max != -1 && (r = sshbuf_put_u32(b, max)) != 0) || + (r = sshbuf_put_bignum2(b, prime)) != 0 || + (r = sshbuf_put_bignum2(b, gen)) != 0 || + (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || + (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || + (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { + sshbuf_free(b); + return r; } - buffer_put_bignum2(&b, prime); - buffer_put_bignum2(&b, gen); - buffer_put_bignum2(&b, client_dh_pub); - buffer_put_bignum2(&b, server_dh_pub); - buffer_put_bignum2(&b, shared_secret); - #ifdef DEBUG_KEXDH - buffer_dump(&b); -#endif - if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) - fatal("%s: ssh_digest_buffer failed", __func__); - - buffer_free(&b); - -#ifdef DEBUG_KEX - dump_digest("hash", digest, ssh_digest_bytes(hash_alg)); + sshbuf_dump(b, stderr); #endif - *hash = digest; + if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { + sshbuf_free(b); + return SSH_ERR_LIBCRYPTO_ERROR; + } + sshbuf_free(b); *hashlen = ssh_digest_bytes(hash_alg); +#ifdef DEBUG_KEXDH + dump_digest("hash", hash, *hashlen); +#endif + return 0; } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/kexgexc.c b/crypto/openssh/kexgexc.c index 355b7ba..71ff133 100644 --- a/crypto/openssh/kexgexc.c +++ b/crypto/openssh/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.17 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.22 2015/05/26 23:23:40 dtucker Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -26,6 +26,9 @@ #include "includes.h" +#ifdef WITH_OPENSSL + +#include #include #include @@ -35,173 +38,235 @@ #include #include -#include "xmalloc.h" -#include "buffer.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" +#include "digest.h" #include "kex.h" #include "log.h" #include "packet.h" #include "dh.h" #include "ssh2.h" #include "compat.h" +#include "dispatch.h" +#include "ssherr.h" +#include "sshbuf.h" + +static int input_kex_dh_gex_group(int, u_int32_t, void *); +static int input_kex_dh_gex_reply(int, u_int32_t, void *); -void -kexgex_client(Kex *kex) +int +kexgex_client(struct ssh *ssh) { - BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; - BIGNUM *p = NULL, *g = NULL; - Key *server_host_key; - u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; - u_int klen, slen, sbloblen, hashlen; - int kout; - int min, max, nbits; - DH *dh; + struct kex *kex = ssh->kex; + int r; + u_int nbits; nbits = dh_estimate(kex->dh_need * 8); - if (datafellows & SSH_OLD_DHGEX) { - /* Old GEX request */ - packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD); - packet_put_int(nbits); - min = DH_GRP_MIN; - max = DH_GRP_MAX; - - debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", nbits); - } else { - /* New GEX request */ - min = DH_GRP_MIN; - max = DH_GRP_MAX; - packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST); - packet_put_int(min); - packet_put_int(nbits); - packet_put_int(max); - - debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent", - min, nbits, max); - } + kex->min = DH_GRP_MIN; + kex->max = DH_GRP_MAX; + kex->nbits = nbits; + if (datafellows & SSH_BUG_DHGEX_LARGE) + kex->nbits = MIN(kex->nbits, 4096); + /* New GEX request */ + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 || + (r = sshpkt_put_u32(ssh, kex->min)) != 0 || + (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || + (r = sshpkt_put_u32(ssh, kex->max)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent", + kex->min, kex->nbits, kex->max); #ifdef DEBUG_KEXDH fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", - min, nbits, max); + kex->min, kex->nbits, kex->max); #endif - packet_send(); - - debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); - packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, + &input_kex_dh_gex_group); + r = 0; + out: + return r; +} - if ((p = BN_new()) == NULL) - fatal("BN_new"); - packet_get_bignum2(p); - if ((g = BN_new()) == NULL) - fatal("BN_new"); - packet_get_bignum2(g); - packet_check_eom(); +static int +input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + BIGNUM *p = NULL, *g = NULL; + int r, bits; - if (BN_num_bits(p) < min || BN_num_bits(p) > max) - fatal("DH_GEX group out of range: %d !< %d !< %d", - min, BN_num_bits(p), max); + debug("got SSH2_MSG_KEX_DH_GEX_GROUP"); - dh = dh_new_group(g, p); - dh_gen_key(dh, kex->we_need * 8); + if ((p = BN_new()) == NULL || + (g = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshpkt_get_bignum2(ssh, p)) != 0 || + (r = sshpkt_get_bignum2(ssh, g)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; + if ((bits = BN_num_bits(p)) < 0 || + (u_int)bits < kex->min || (u_int)bits > kex->max) { + r = SSH_ERR_DH_GEX_OUT_OF_RANGE; + goto out; + } + if ((kex->dh = dh_new_group(g, p)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + p = g = NULL; /* belong to kex->dh now */ + /* generate and send 'e', client DH public key */ + if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || + (r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || + (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); #ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, dh); + DHparams_print_fp(stderr, kex->dh); fprintf(stderr, "pub= "); - BN_print_fp(stderr, dh->pub_key); + BN_print_fp(stderr, kex->dh->pub_key); fprintf(stderr, "\n"); #endif + 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); + r = 0; +out: + if (p) + BN_clear_free(p); + if (g) + BN_clear_free(g); + return r; +} - debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); - /* generate and send 'e', client DH public key */ - packet_start(SSH2_MSG_KEX_DH_GEX_INIT); - packet_put_bignum2(dh->pub_key); - packet_send(); - - debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); - packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY); +static int +input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; + struct sshkey *server_host_key = NULL; + u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t klen = 0, slen, sbloblen, hashlen; + int kout, r; + debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); + if (kex->verify_host_key == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } /* key, cert */ - server_host_key_blob = packet_get_string(&sbloblen); - server_host_key = key_from_blob(server_host_key_blob, sbloblen); - if (server_host_key == NULL) - fatal("cannot decode server_host_key_blob"); - if (server_host_key->type != kex->hostkey_type) - fatal("type mismatch for decoded server_host_key_blob"); - if (kex->verify_host_key == NULL) - fatal("cannot verify server_host_key"); - if (kex->verify_host_key(server_host_key) == -1) - fatal("server_host_key verification failed"); - + if ((r = sshpkt_get_string(ssh, &server_host_key_blob, + &sbloblen)) != 0 || + (r = sshkey_from_blob(server_host_key_blob, sbloblen, + &server_host_key)) != 0) + goto out; + if (server_host_key->type != kex->hostkey_type) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + if (server_host_key->type != kex->hostkey_type || + (kex->hostkey_type == KEY_ECDSA && + server_host_key->ecdsa_nid != kex->hostkey_nid)) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + if (kex->verify_host_key(server_host_key, ssh) == -1) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } /* DH parameter f, server public DH key */ - if ((dh_server_pub = BN_new()) == NULL) - fatal("dh_server_pub == NULL"); - packet_get_bignum2(dh_server_pub); - + if ((dh_server_pub = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* signed H */ + if ((r = sshpkt_get_bignum2(ssh, dh_server_pub)) != 0 || + (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; #ifdef DEBUG_KEXDH fprintf(stderr, "dh_server_pub= "); BN_print_fp(stderr, dh_server_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_server_pub)); #endif + if (!dh_pub_is_valid(kex->dh, dh_server_pub)) { + sshpkt_disconnect(ssh, "bad server public DH value"); + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } - /* signed H */ - signature = packet_get_string(&slen); - packet_check_eom(); - - if (!dh_pub_is_valid(dh, dh_server_pub)) - packet_disconnect("bad server public DH value"); - - klen = DH_size(dh); - kbuf = xmalloc(klen); - if ((kout = DH_compute_key(kbuf, dh_server_pub, dh)) < 0) - fatal("DH_compute_key: failed"); + klen = DH_size(kex->dh); + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 || + BN_bin2bn(kbuf, kout, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif - if ((shared_secret = BN_new()) == NULL) - fatal("kexgex_client: BN_new failed"); - if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) - fatal("kexgex_client: BN_bin2bn failed"); - explicit_bzero(kbuf, klen); - free(kbuf); - - if (datafellows & SSH_OLD_DHGEX) - min = max = -1; + if (ssh->compat & SSH_OLD_DHGEX) + kex->min = kex->max = -1; /* calc and verify H */ - kexgex_hash( + hashlen = sizeof(hash); + if ((r = kexgex_hash( kex->hash_alg, kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->my), buffer_len(&kex->my), - buffer_ptr(&kex->peer), buffer_len(&kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, - min, nbits, max, - dh->p, dh->g, - dh->pub_key, + kex->min, kex->nbits, kex->max, + kex->dh->p, kex->dh->g, + kex->dh->pub_key, dh_server_pub, shared_secret, - &hash, &hashlen - ); - - /* have keys, free DH */ - DH_free(dh); - free(server_host_key_blob); - BN_clear_free(dh_server_pub); + hash, &hashlen)) != 0) + goto out; - if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) - fatal("key_verify failed for server_host_key"); - key_free(server_host_key); - free(signature); + if ((r = sshkey_verify(server_host_key, signature, slen, hash, + hashlen, ssh->compat)) != 0) + goto out; /* save session id */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; - kex->session_id = xmalloc(kex->session_id_len); + kex->session_id = malloc(kex->session_id_len); + if (kex->session_id == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(kex->session_id, hash, kex->session_id_len); } - kex_derive_keys_bn(kex, hash, hashlen, shared_secret); - BN_clear_free(shared_secret); - kex_finish(kex); + if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + out: + explicit_bzero(hash, sizeof(hash)); + DH_free(kex->dh); + kex->dh = NULL; + if (dh_server_pub) + BN_clear_free(dh_server_pub); + if (kbuf) { + explicit_bzero(kbuf, klen); + free(kbuf); + } + if (shared_secret) + BN_clear_free(shared_secret); + sshkey_free(server_host_key); + free(server_host_key_blob); + free(signature); + return r; } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/kexgexs.c b/crypto/openssh/kexgexs.c index 770ad28..ff6c687 100644 --- a/crypto/openssh/kexgexs.c +++ b/crypto/openssh/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.19 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.25 2015/04/13 02:04:08 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -26,7 +26,9 @@ #include "includes.h" -#include +#ifdef WITH_OPENSSL + +#include /* MIN MAX */ #include #include @@ -35,10 +37,9 @@ #include -#include "xmalloc.h" -#include "buffer.h" -#include "key.h" +#include "sshkey.h" #include "cipher.h" +#include "digest.h" #include "kex.h" #include "log.h" #include "packet.h" @@ -49,79 +50,110 @@ #include "ssh-gss.h" #endif #include "monitor_wrap.h" +#include "dispatch.h" +#include "ssherr.h" +#include "sshbuf.h" + +static int input_kex_dh_gex_request(int, u_int32_t, void *); +static int input_kex_dh_gex_init(int, u_int32_t, void *); -void -kexgex_server(Kex *kex) +int +kexgex_server(struct ssh *ssh) { - BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; - Key *server_host_public, *server_host_private; - DH *dh; - u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; - u_int sbloblen, klen, slen, hashlen; - int omin = -1, min = -1, omax = -1, max = -1, onbits = -1, nbits = -1; - int type, kout; + ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST, + &input_kex_dh_gex_request); + debug("expecting SSH2_MSG_KEX_DH_GEX_REQUEST"); + return 0; +} - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) - fatal("Cannot load hostkey"); - server_host_public = kex->load_host_public_key(kex->hostkey_type); - if (server_host_public == NULL) - fatal("Unsupported hostkey type %d", kex->hostkey_type); - server_host_private = kex->load_host_private_key(kex->hostkey_type); - - type = packet_read(); - switch (type) { - case SSH2_MSG_KEX_DH_GEX_REQUEST: - debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); - omin = min = packet_get_int(); - onbits = nbits = packet_get_int(); - omax = max = packet_get_int(); - min = MAX(DH_GRP_MIN, min); - max = MIN(DH_GRP_MAX, max); - nbits = MAX(DH_GRP_MIN, nbits); - nbits = MIN(DH_GRP_MAX, nbits); - break; - case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: - debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received"); - onbits = nbits = packet_get_int(); - /* unused for old GEX */ - omin = min = DH_GRP_MIN; - omax = max = DH_GRP_MAX; - break; - default: - fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type); +static int +input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + int r; + u_int min = 0, max = 0, nbits = 0; + + debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); + if ((r = sshpkt_get_u32(ssh, &min)) != 0 || + (r = sshpkt_get_u32(ssh, &nbits)) != 0 || + (r = sshpkt_get_u32(ssh, &max)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; + kex->nbits = nbits; + kex->min = min; + kex->max = max; + min = MAX(DH_GRP_MIN, min); + max = MIN(DH_GRP_MAX, max); + nbits = MAX(DH_GRP_MIN, nbits); + nbits = MIN(DH_GRP_MAX, nbits); + + if (kex->max < kex->min || kex->nbits < kex->min || + kex->max < kex->nbits) { + r = SSH_ERR_DH_GEX_OUT_OF_RANGE; + goto out; } - packet_check_eom(); - - if (omax < omin || onbits < omin || omax < onbits) - fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", - omin, onbits, omax); /* Contact privileged parent */ - dh = PRIVSEP(choose_dh(min, nbits, max)); - if (dh == NULL) - packet_disconnect("Protocol error: no matching DH grp found"); - + kex->dh = PRIVSEP(choose_dh(min, nbits, max)); + if (kex->dh == NULL) { + sshpkt_disconnect(ssh, "no matching DH grp found"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); - packet_start(SSH2_MSG_KEX_DH_GEX_GROUP); - packet_put_bignum2(dh->p); - packet_put_bignum2(dh->g); - packet_send(); - - /* flush */ - packet_write_wait(); + 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, kex->dh->g)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; /* Compute our exchange value in parallel with the client */ - dh_gen_key(dh, kex->we_need * 8); + if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) + goto out; debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); - packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init); + r = 0; + out: + return r; +} + +static int +input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; + struct sshkey *server_host_public, *server_host_private; + u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t sbloblen, slen; + size_t klen = 0, hashlen; + int kout, r; + + if (kex->load_host_public_key == NULL || + kex->load_host_private_key == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + server_host_public = kex->load_host_public_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + server_host_private = kex->load_host_private_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + if (server_host_public == NULL) { + r = SSH_ERR_NO_HOSTKEY_LOADED; + goto out; + } /* key, cert */ - if ((dh_client_pub = BN_new()) == NULL) - fatal("dh_client_pub == NULL"); - packet_get_bignum2(dh_client_pub); - packet_check_eom(); + if ((dh_client_pub = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); @@ -131,78 +163,92 @@ kexgex_server(Kex *kex) #endif #ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, dh); + DHparams_print_fp(stderr, kex->dh); fprintf(stderr, "pub= "); - BN_print_fp(stderr, dh->pub_key); + BN_print_fp(stderr, kex->dh->pub_key); fprintf(stderr, "\n"); #endif - if (!dh_pub_is_valid(dh, dh_client_pub)) - packet_disconnect("bad client public DH value"); + if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { + sshpkt_disconnect(ssh, "bad client public DH value"); + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } - klen = DH_size(dh); - kbuf = xmalloc(klen); - if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0) - fatal("DH_compute_key: failed"); + klen = DH_size(kex->dh); + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || + BN_bin2bn(kbuf, kout, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif - if ((shared_secret = BN_new()) == NULL) - fatal("kexgex_server: BN_new failed"); - if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) - fatal("kexgex_server: BN_bin2bn failed"); - explicit_bzero(kbuf, klen); - free(kbuf); - - key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); - - if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) - omin = min = omax = max = -1; - + if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, + &sbloblen)) != 0) + goto out; /* calc H */ - kexgex_hash( + hashlen = sizeof(hash); + if ((r = kexgex_hash( kex->hash_alg, kex->client_version_string, kex->server_version_string, - buffer_ptr(&kex->peer), buffer_len(&kex->peer), - buffer_ptr(&kex->my), buffer_len(&kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, - omin, onbits, omax, - dh->p, dh->g, + kex->min, kex->nbits, kex->max, + kex->dh->p, kex->dh->g, dh_client_pub, - dh->pub_key, + kex->dh->pub_key, shared_secret, - &hash, &hashlen - ); - BN_clear_free(dh_client_pub); + hash, &hashlen)) != 0) + goto out; /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; - kex->session_id = xmalloc(kex->session_id_len); + kex->session_id = malloc(kex->session_id_len); + if (kex->session_id == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ - kex->sign(server_host_private, server_host_public, &signature, &slen, - hash, hashlen); + if ((r = kex->sign(server_host_private, server_host_public, + &signature, &slen, hash, hashlen, ssh->compat)) < 0) + goto out; /* destroy_sensitive_data(); */ /* send server hostkey, DH pubkey 'f' and singed H */ - debug("SSH2_MSG_KEX_DH_GEX_REPLY sent"); - packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); - packet_put_string(server_host_key_blob, sbloblen); - packet_put_bignum2(dh->pub_key); /* f */ - packet_put_string(signature, slen); - packet_send(); - - free(signature); + 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_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ + (r = sshpkt_put_string(ssh, signature, slen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + + if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + out: + DH_free(kex->dh); + kex->dh = NULL; + if (dh_client_pub) + BN_clear_free(dh_client_pub); + if (kbuf) { + explicit_bzero(kbuf, klen); + free(kbuf); + } + if (shared_secret) + BN_clear_free(shared_secret); free(server_host_key_blob); - /* have keys, free DH */ - DH_free(dh); - - kex_derive_keys_bn(kex, hash, hashlen, shared_secret); - BN_clear_free(shared_secret); - - kex_finish(kex); + free(signature); + return r; } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/key.c b/crypto/openssh/key.c index 168e1b7..0ba98b6 100644 --- a/crypto/openssh/key.c +++ b/crypto/openssh/key.c @@ -1,2089 +1,224 @@ -/* $OpenBSD: key.c,v 1.116 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: key.c,v 1.128 2015/07/03 03:43:18 djm Exp $ */ /* - * read_bignum(): - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2008 Alexander von Gernler. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * placed in the public domain */ #include "includes.h" -#include #include - -#include "crypto_api.h" - -#include -#include - +#include #include #include -#include +#include -#include "xmalloc.h" +#define SSH_KEY_NO_DEFINE #include "key.h" -#include "rsa.h" -#include "uuencode.h" -#include "buffer.h" -#include "log.h" -#include "misc.h" -#include "ssh2.h" -#include "digest.h" - -static int to_blob(const Key *, u_char **, u_int *, int); -static Key *key_from_blob2(const u_char *, u_int, int); - -static struct KeyCert * -cert_new(void) -{ - struct KeyCert *cert; - - cert = xcalloc(1, sizeof(*cert)); - buffer_init(&cert->certblob); - buffer_init(&cert->critical); - buffer_init(&cert->extensions); - cert->key_id = NULL; - cert->principals = NULL; - cert->signature_key = NULL; - return cert; -} - -Key * -key_new(int type) -{ - Key *k; - RSA *rsa; - DSA *dsa; - k = xcalloc(1, sizeof(*k)); - k->type = type; - k->ecdsa = NULL; - k->ecdsa_nid = -1; - k->dsa = NULL; - k->rsa = NULL; - k->cert = NULL; - k->ed25519_sk = NULL; - k->ed25519_pk = NULL; - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - if ((rsa = RSA_new()) == NULL) - fatal("key_new: RSA_new failed"); - if ((rsa->n = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((rsa->e = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - k->rsa = rsa; - break; - case KEY_DSA: - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - if ((dsa = DSA_new()) == NULL) - fatal("key_new: DSA_new failed"); - if ((dsa->p = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->q = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->g = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->pub_key = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - k->dsa = dsa; - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - case KEY_ECDSA_CERT: - /* Cannot do anything until we know the group */ - break; -#endif - case KEY_ED25519: - case KEY_ED25519_CERT: - /* no need to prealloc */ - break; - case KEY_UNSPEC: - break; - default: - fatal("key_new: bad key type %d", k->type); - break; - } - if (key_is_cert(k)) - k->cert = cert_new(); - - return k; -} +#include "compat.h" +#include "sshkey.h" +#include "ssherr.h" +#include "log.h" +#include "authfile.h" void key_add_private(Key *k) { - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - if ((k->rsa->d = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->iqmp = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->q = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->p = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->dmq1 = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->dmp1 = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - break; - case KEY_DSA: - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - if ((k->dsa->priv_key = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - break; - case KEY_ECDSA: - case KEY_ECDSA_CERT: - /* Cannot do anything until we know the group */ - break; - case KEY_ED25519: - case KEY_ED25519_CERT: - /* no need to prealloc */ - break; - case KEY_UNSPEC: - break; - default: - break; - } + int r; + + if ((r = sshkey_add_private(k)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); } Key * key_new_private(int type) { - Key *k = key_new(type); - - key_add_private(k); - return k; -} - -static void -cert_free(struct KeyCert *cert) -{ - u_int i; - - buffer_free(&cert->certblob); - buffer_free(&cert->critical); - buffer_free(&cert->extensions); - free(cert->key_id); - for (i = 0; i < cert->nprincipals; i++) - free(cert->principals[i]); - free(cert->principals); - if (cert->signature_key != NULL) - key_free(cert->signature_key); - free(cert); -} - -void -key_free(Key *k) -{ - if (k == NULL) - fatal("key_free: key is NULL"); - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - if (k->rsa != NULL) - RSA_free(k->rsa); - k->rsa = NULL; - break; - case KEY_DSA: - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - if (k->dsa != NULL) - DSA_free(k->dsa); - k->dsa = NULL; - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - case KEY_ECDSA_CERT: - if (k->ecdsa != NULL) - EC_KEY_free(k->ecdsa); - k->ecdsa = NULL; - break; -#endif - case KEY_ED25519: - case KEY_ED25519_CERT: - if (k->ed25519_pk) { - explicit_bzero(k->ed25519_pk, ED25519_PK_SZ); - free(k->ed25519_pk); - k->ed25519_pk = NULL; - } - if (k->ed25519_sk) { - explicit_bzero(k->ed25519_sk, ED25519_SK_SZ); - free(k->ed25519_sk); - k->ed25519_sk = NULL; - } - break; - case KEY_UNSPEC: - break; - default: - fatal("key_free: bad key type %d", k->type); - break; - } - if (key_is_cert(k)) { - if (k->cert != NULL) - cert_free(k->cert); - k->cert = NULL; - } - - free(k); -} - -static int -cert_compare(struct KeyCert *a, struct KeyCert *b) -{ - if (a == NULL && b == NULL) - return 1; - if (a == NULL || b == NULL) - return 0; - if (buffer_len(&a->certblob) != buffer_len(&b->certblob)) - return 0; - if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob), - buffer_len(&a->certblob)) != 0) - return 0; - return 1; -} - -/* - * Compare public portions of key only, allowing comparisons between - * certificates and plain keys too. - */ -int -key_equal_public(const Key *a, const Key *b) -{ -#ifdef OPENSSL_HAS_ECC - BN_CTX *bnctx; -#endif - - if (a == NULL || b == NULL || - key_type_plain(a->type) != key_type_plain(b->type)) - return 0; - - switch (a->type) { - case KEY_RSA1: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - case KEY_RSA: - return a->rsa != NULL && b->rsa != NULL && - BN_cmp(a->rsa->e, b->rsa->e) == 0 && - BN_cmp(a->rsa->n, b->rsa->n) == 0; - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - case KEY_DSA: - return a->dsa != NULL && b->dsa != NULL && - BN_cmp(a->dsa->p, b->dsa->p) == 0 && - BN_cmp(a->dsa->q, b->dsa->q) == 0 && - BN_cmp(a->dsa->g, b->dsa->g) == 0 && - BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: - case KEY_ECDSA: - if (a->ecdsa == NULL || b->ecdsa == NULL || - EC_KEY_get0_public_key(a->ecdsa) == NULL || - EC_KEY_get0_public_key(b->ecdsa) == NULL) - return 0; - if ((bnctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new failed", __func__); - if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa), - EC_KEY_get0_group(b->ecdsa), bnctx) != 0 || - EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa), - EC_KEY_get0_public_key(a->ecdsa), - EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) { - BN_CTX_free(bnctx); - return 0; - } - BN_CTX_free(bnctx); - return 1; -#endif /* OPENSSL_HAS_ECC */ - case KEY_ED25519: - case KEY_ED25519_CERT: - return a->ed25519_pk != NULL && b->ed25519_pk != NULL && - memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0; - default: - fatal("key_equal: bad key type %d", a->type); - } - /* NOTREACHED */ -} - -int -key_equal(const Key *a, const Key *b) -{ - if (a == NULL || b == NULL || a->type != b->type) - return 0; - if (key_is_cert(a)) { - if (!cert_compare(a->cert, b->cert)) - return 0; - } - return key_equal_public(a, b); -} - -u_char* -key_fingerprint_raw(const Key *k, enum fp_type dgst_type, - u_int *dgst_raw_length) -{ - u_char *blob = NULL; - u_char *retval = NULL; - u_int len = 0; - int nlen, elen, hash_alg = -1; - - *dgst_raw_length = 0; - - /* XXX switch to DIGEST_* directly? */ - switch (dgst_type) { - case SSH_FP_MD5: - hash_alg = SSH_DIGEST_MD5; - break; - case SSH_FP_SHA1: - hash_alg = SSH_DIGEST_SHA1; - break; - case SSH_FP_SHA256: - hash_alg = SSH_DIGEST_SHA256; - break; - default: - fatal("%s: bad digest type %d", __func__, dgst_type); - } - switch (k->type) { - case KEY_RSA1: - nlen = BN_num_bytes(k->rsa->n); - elen = BN_num_bytes(k->rsa->e); - len = nlen + elen; - blob = xmalloc(len); - BN_bn2bin(k->rsa->n, blob); - BN_bn2bin(k->rsa->e, blob + nlen); - break; - case KEY_DSA: - case KEY_ECDSA: - case KEY_RSA: - case KEY_ED25519: - key_to_blob(k, &blob, &len); - break; - case KEY_DSA_CERT_V00: - case KEY_RSA_CERT_V00: - case KEY_DSA_CERT: - case KEY_ECDSA_CERT: - case KEY_RSA_CERT: - case KEY_ED25519_CERT: - /* We want a fingerprint of the _key_ not of the cert */ - to_blob(k, &blob, &len, 1); - break; - case KEY_UNSPEC: - return retval; - default: - fatal("%s: bad key type %d", __func__, k->type); - break; - } - if (blob != NULL) { - retval = xmalloc(SSH_DIGEST_MAX_LENGTH); - if ((ssh_digest_memory(hash_alg, blob, len, - retval, SSH_DIGEST_MAX_LENGTH)) != 0) - fatal("%s: digest_memory failed", __func__); - explicit_bzero(blob, len); - free(blob); - *dgst_raw_length = ssh_digest_bytes(hash_alg); - } else { - fatal("%s: blob is null", __func__); - } - return retval; -} - -static char * -key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len) -{ - char *retval; - u_int i; - - retval = xcalloc(1, dgst_raw_len * 3 + 1); - for (i = 0; i < dgst_raw_len; i++) { - char hex[4]; - snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); - strlcat(retval, hex, dgst_raw_len * 3 + 1); - } - - /* Remove the trailing ':' character */ - retval[(dgst_raw_len * 3) - 1] = '\0'; - return retval; -} - -static char * -key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len) -{ - char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; - char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', - 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; - u_int i, j = 0, rounds, seed = 1; - char *retval; - - rounds = (dgst_raw_len / 2) + 1; - retval = xcalloc((rounds * 6), sizeof(char)); - retval[j++] = 'x'; - for (i = 0; i < rounds; i++) { - u_int idx0, idx1, idx2, idx3, idx4; - if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { - idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + - seed) % 6; - idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; - idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + - (seed / 6)) % 6; - retval[j++] = vowels[idx0]; - retval[j++] = consonants[idx1]; - retval[j++] = vowels[idx2]; - if ((i + 1) < rounds) { - idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; - idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; - retval[j++] = consonants[idx3]; - retval[j++] = '-'; - retval[j++] = consonants[idx4]; - seed = ((seed * 5) + - ((((u_int)(dgst_raw[2 * i])) * 7) + - ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; - } - } else { - idx0 = seed % 6; - idx1 = 16; - idx2 = seed / 6; - retval[j++] = vowels[idx0]; - retval[j++] = consonants[idx1]; - retval[j++] = vowels[idx2]; - } - } - retval[j++] = 'x'; - retval[j++] = '\0'; - return retval; -} - -/* - * Draw an ASCII-Art representing the fingerprint so human brain can - * profit from its built-in pattern recognition ability. - * This technique is called "random art" and can be found in some - * scientific publications like this original paper: - * - * "Hash Visualization: a New Technique to improve Real-World Security", - * Perrig A. and Song D., 1999, International Workshop on Cryptographic - * Techniques and E-Commerce (CrypTEC '99) - * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf - * - * The subject came up in a talk by Dan Kaminsky, too. - * - * If you see the picture is different, the key is different. - * If the picture looks the same, you still know nothing. - * - * The algorithm used here is a worm crawling over a discrete plane, - * leaving a trace (augmenting the field) everywhere it goes. - * Movement is taken from dgst_raw 2bit-wise. Bumping into walls - * makes the respective movement vector be ignored for this turn. - * Graphs are not unambiguous, because circles in graphs can be - * walked in either direction. - */ - -/* - * Field sizes for the random art. Have to be odd, so the starting point - * can be in the exact middle of the picture, and FLDBASE should be >=8 . - * Else pictures would be too dense, and drawing the frame would - * fail, too, because the key type would not fit in anymore. - */ -#define FLDBASE 8 -#define FLDSIZE_Y (FLDBASE + 1) -#define FLDSIZE_X (FLDBASE * 2 + 1) -static char * -key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) -{ - /* - * Chars to be used after each other every time the worm - * intersects with itself. Matter of taste. - */ - char *augmentation_string = " .o+=*BOX@%&#/^SE"; - char *retval, *p; - u_char field[FLDSIZE_X][FLDSIZE_Y]; - u_int i, b; - int x, y; - size_t len = strlen(augmentation_string) - 1; - - retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2)); - - /* initialize field */ - memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); - x = FLDSIZE_X / 2; - y = FLDSIZE_Y / 2; - - /* process raw key */ - for (i = 0; i < dgst_raw_len; i++) { - int input; - /* each byte conveys four 2-bit move commands */ - input = dgst_raw[i]; - for (b = 0; b < 4; b++) { - /* evaluate 2 bit, rest is shifted later */ - x += (input & 0x1) ? 1 : -1; - y += (input & 0x2) ? 1 : -1; - - /* assure we are still in bounds */ - x = MAX(x, 0); - y = MAX(y, 0); - x = MIN(x, FLDSIZE_X - 1); - y = MIN(y, FLDSIZE_Y - 1); - - /* augment the field */ - if (field[x][y] < len - 2) - field[x][y]++; - input = input >> 2; - } - } - - /* mark starting point and end point*/ - field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; - field[x][y] = len; - - /* fill in retval */ - snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k)); - p = strchr(retval, '\0'); - - /* output upper border */ - for (i = p - retval - 1; i < FLDSIZE_X; i++) - *p++ = '-'; - *p++ = '+'; - *p++ = '\n'; - - /* output content */ - for (y = 0; y < FLDSIZE_Y; y++) { - *p++ = '|'; - for (x = 0; x < FLDSIZE_X; x++) - *p++ = augmentation_string[MIN(field[x][y], len)]; - *p++ = '|'; - *p++ = '\n'; - } - - /* output lower border */ - *p++ = '+'; - for (i = 0; i < FLDSIZE_X; i++) - *p++ = '-'; - *p++ = '+'; - - return retval; -} - -char * -key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) -{ - char *retval = NULL; - u_char *dgst_raw; - u_int dgst_raw_len; - - dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); - if (!dgst_raw) - fatal("key_fingerprint: null from key_fingerprint_raw()"); - switch (dgst_rep) { - case SSH_FP_HEX: - retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); - break; - case SSH_FP_BUBBLEBABBLE: - retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); - break; - case SSH_FP_RANDOMART: - retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k); - break; - default: - fatal("key_fingerprint: bad digest representation %d", - dgst_rep); - break; - } - explicit_bzero(dgst_raw, dgst_raw_len); - free(dgst_raw); - return retval; -} - -/* - * Reads a multiple-precision integer in decimal from the buffer, and advances - * the pointer. The integer must already be initialized. This function is - * permitted to modify the buffer. This leaves *cpp to point just beyond the - * last processed (and maybe modified) character. Note that this may modify - * the buffer containing the number. - */ -static int -read_bignum(char **cpp, BIGNUM * value) -{ - char *cp = *cpp; - int old; + Key *ret = NULL; - /* Skip any leading whitespace. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - - /* Check that it begins with a decimal digit. */ - if (*cp < '0' || *cp > '9') - return 0; - - /* Save starting position. */ - *cpp = cp; - - /* Move forward until all decimal digits skipped. */ - for (; *cp >= '0' && *cp <= '9'; cp++) - ; - - /* Save the old terminating character, and replace it by \0. */ - old = *cp; - *cp = 0; - - /* Parse the number. */ - if (BN_dec2bn(&value, *cpp) == 0) - return 0; - - /* Restore old terminating character. */ - *cp = old; - - /* Move beyond the number and return success. */ - *cpp = cp; - return 1; -} - -static int -write_bignum(FILE *f, BIGNUM *num) -{ - char *buf = BN_bn2dec(num); - if (buf == NULL) { - error("write_bignum: BN_bn2dec() failed"); - return 0; - } - fprintf(f, " %s", buf); - OPENSSL_free(buf); - return 1; + if ((ret = sshkey_new_private(type)) == NULL) + fatal("%s: failed", __func__); + return ret; } -/* returns 1 ok, -1 error */ int key_read(Key *ret, char **cpp) { - Key *k; - int success = -1; - char *cp, *space; - int len, n, type; - u_int bits; - u_char *blob; -#ifdef OPENSSL_HAS_ECC - int curve_nid = -1; -#endif - - cp = *cpp; - - switch (ret->type) { - case KEY_RSA1: - /* Get number of bits. */ - if (*cp < '0' || *cp > '9') - return -1; /* Bad bit count... */ - for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) - bits = 10 * bits + *cp - '0'; - if (bits == 0) - return -1; - *cpp = cp; - /* Get public exponent, public modulus. */ - if (!read_bignum(cpp, ret->rsa->e)) - return -1; - if (!read_bignum(cpp, ret->rsa->n)) - return -1; - /* validate the claimed number of bits */ - if ((u_int)BN_num_bits(ret->rsa->n) != bits) { - verbose("key_read: claimed key size %d does not match " - "actual %d", bits, BN_num_bits(ret->rsa->n)); - return -1; - } - success = 1; - break; - case KEY_UNSPEC: - case KEY_RSA: - case KEY_DSA: - case KEY_ECDSA: - case KEY_ED25519: - case KEY_DSA_CERT_V00: - case KEY_RSA_CERT_V00: - case KEY_DSA_CERT: - case KEY_ECDSA_CERT: - case KEY_RSA_CERT: - case KEY_ED25519_CERT: - space = strchr(cp, ' '); - if (space == NULL) { - debug3("key_read: missing whitespace"); - return -1; - } - *space = '\0'; - type = key_type_from_name(cp); -#ifdef OPENSSL_HAS_ECC - if (key_type_plain(type) == KEY_ECDSA && - (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) { - debug("key_read: invalid curve"); - return -1; - } -#endif - *space = ' '; - if (type == KEY_UNSPEC) { - debug3("key_read: missing keytype"); - return -1; - } - cp = space+1; - if (*cp == '\0') { - debug3("key_read: short string"); - return -1; - } - if (ret->type == KEY_UNSPEC) { - ret->type = type; - } else if (ret->type != type) { - /* is a key, but different type */ - debug3("key_read: type mismatch"); - return -1; - } - len = 2*strlen(cp); - blob = xmalloc(len); - n = uudecode(cp, blob, len); - if (n < 0) { - error("key_read: uudecode %s failed", cp); - free(blob); - return -1; - } - k = key_from_blob(blob, (u_int)n); - free(blob); - if (k == NULL) { - error("key_read: key_from_blob %s failed", cp); - return -1; - } - if (k->type != type) { - error("key_read: type mismatch: encoding error"); - key_free(k); - return -1; - } -#ifdef OPENSSL_HAS_ECC - if (key_type_plain(type) == KEY_ECDSA && - curve_nid != k->ecdsa_nid) { - error("key_read: type mismatch: EC curve mismatch"); - key_free(k); - return -1; - } -#endif -/*XXXX*/ - if (key_is_cert(ret)) { - if (!key_is_cert(k)) { - error("key_read: loaded key is not a cert"); - key_free(k); - return -1; - } - if (ret->cert != NULL) - cert_free(ret->cert); - ret->cert = k->cert; - k->cert = NULL; - } - if (key_type_plain(ret->type) == KEY_RSA) { - if (ret->rsa != NULL) - RSA_free(ret->rsa); - ret->rsa = k->rsa; - k->rsa = NULL; -#ifdef DEBUG_PK - RSA_print_fp(stderr, ret->rsa, 8); -#endif - } - if (key_type_plain(ret->type) == KEY_DSA) { - if (ret->dsa != NULL) - DSA_free(ret->dsa); - ret->dsa = k->dsa; - k->dsa = NULL; -#ifdef DEBUG_PK - DSA_print_fp(stderr, ret->dsa, 8); -#endif - } -#ifdef OPENSSL_HAS_ECC - if (key_type_plain(ret->type) == KEY_ECDSA) { - if (ret->ecdsa != NULL) - EC_KEY_free(ret->ecdsa); - ret->ecdsa = k->ecdsa; - ret->ecdsa_nid = k->ecdsa_nid; - k->ecdsa = NULL; - k->ecdsa_nid = -1; -#ifdef DEBUG_PK - key_dump_ec_key(ret->ecdsa); -#endif - } -#endif - if (key_type_plain(ret->type) == KEY_ED25519) { - free(ret->ed25519_pk); - ret->ed25519_pk = k->ed25519_pk; - k->ed25519_pk = NULL; -#ifdef DEBUG_PK - /* XXX */ -#endif - } - success = 1; -/*XXXX*/ - key_free(k); - if (success != 1) - break; - /* advance cp: skip whitespace and data */ - while (*cp == ' ' || *cp == '\t') - cp++; - while (*cp != '\0' && *cp != ' ' && *cp != '\t') - cp++; - *cpp = cp; - break; - default: - fatal("key_read: bad key type: %d", ret->type); - break; - } - return success; + return sshkey_read(ret, cpp) == 0 ? 1 : -1; } int key_write(const Key *key, FILE *f) { - int n, success = 0; - u_int len, bits = 0; - u_char *blob; - char *uu; - - if (key_is_cert(key)) { - if (key->cert == NULL) { - error("%s: no cert data", __func__); - return 0; - } - if (buffer_len(&key->cert->certblob) == 0) { - error("%s: no signed certificate blob", __func__); - return 0; - } - } - - switch (key->type) { - case KEY_RSA1: - if (key->rsa == NULL) - return 0; - /* size of modulus 'n' */ - bits = BN_num_bits(key->rsa->n); - fprintf(f, "%u", bits); - if (write_bignum(f, key->rsa->e) && - write_bignum(f, key->rsa->n)) - return 1; - error("key_write: failed for RSA key"); - return 0; - case KEY_DSA: - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - if (key->dsa == NULL) - return 0; - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - case KEY_ECDSA_CERT: - if (key->ecdsa == NULL) - return 0; - break; -#endif - case KEY_ED25519: - case KEY_ED25519_CERT: - if (key->ed25519_pk == NULL) - return 0; - break; - case KEY_RSA: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - if (key->rsa == NULL) - return 0; - break; - default: - return 0; - } - - key_to_blob(key, &blob, &len); - uu = xmalloc(2*len); - n = uuencode(blob, len, uu, 2*len); - if (n > 0) { - fprintf(f, "%s %s", key_ssh_name(key), uu); - success = 1; - } - free(blob); - free(uu); - - return success; -} - -const char * -key_cert_type(const Key *k) -{ - switch (k->cert->type) { - case SSH2_CERT_TYPE_USER: - return "user"; - case SSH2_CERT_TYPE_HOST: - return "host"; - default: - return "unknown"; - } -} - -struct keytype { - char *name; - char *shortname; - int type; - int nid; - int cert; -}; -static const struct keytype keytypes[] = { - { NULL, "RSA1", KEY_RSA1, 0, 0 }, - { "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, - { "ssh-dss", "DSA", KEY_DSA, 0, 0 }, - { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 }, -#ifdef OPENSSL_HAS_ECC - { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, - { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, -# ifdef OPENSSL_HAS_NISTP521 - { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, -# endif -#endif /* OPENSSL_HAS_ECC */ - { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 }, - { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 }, -#ifdef OPENSSL_HAS_ECC - { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", - KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 }, - { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", - KEY_ECDSA_CERT, NID_secp384r1, 1 }, -# ifdef OPENSSL_HAS_NISTP521 - { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", - KEY_ECDSA_CERT, NID_secp521r1, 1 }, -# endif -#endif /* OPENSSL_HAS_ECC */ - { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00", - KEY_RSA_CERT_V00, 0, 1 }, - { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", - KEY_DSA_CERT_V00, 0, 1 }, - { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", - KEY_ED25519_CERT, 0, 1 }, - { NULL, NULL, -1, -1, 0 } -}; - -const char * -key_type(const Key *k) -{ - const struct keytype *kt; - - for (kt = keytypes; kt->type != -1; kt++) { - if (kt->type == k->type) - return kt->shortname; - } - return "unknown"; -} - -static const char * -key_ssh_name_from_type_nid(int type, int nid) -{ - const struct keytype *kt; - - for (kt = keytypes; kt->type != -1; kt++) { - if (kt->type == type && (kt->nid == 0 || kt->nid == nid)) - return kt->name; - } - return "ssh-unknown"; -} - -const char * -key_ssh_name(const Key *k) -{ - return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid); -} - -const char * -key_ssh_name_plain(const Key *k) -{ - return key_ssh_name_from_type_nid(key_type_plain(k->type), - k->ecdsa_nid); -} - -int -key_type_from_name(char *name) -{ - const struct keytype *kt; - - for (kt = keytypes; kt->type != -1; kt++) { - /* Only allow shortname matches for plain key types */ - if ((kt->name != NULL && strcmp(name, kt->name) == 0) || - (!kt->cert && strcasecmp(kt->shortname, name) == 0)) - return kt->type; - } - debug2("key_type_from_name: unknown key type '%s'", name); - return KEY_UNSPEC; -} - -int -key_ecdsa_nid_from_name(const char *name) -{ - const struct keytype *kt; - - for (kt = keytypes; kt->type != -1; kt++) { - if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) - continue; - if (kt->name != NULL && strcmp(name, kt->name) == 0) - return kt->nid; - } - debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name); - return -1; -} - -char * -key_alg_list(int certs_only, int plain_only) -{ - char *ret = NULL; - size_t nlen, rlen = 0; - const struct keytype *kt; - - for (kt = keytypes; kt->type != -1; kt++) { - if (kt->name == NULL) - continue; - if ((certs_only && !kt->cert) || (plain_only && kt->cert)) - continue; - if (ret != NULL) - ret[rlen++] = '\n'; - nlen = strlen(kt->name); - ret = xrealloc(ret, 1, rlen + nlen + 2); - memcpy(ret + rlen, kt->name, nlen + 1); - rlen += nlen; - } - return ret; -} - -int -key_type_is_cert(int type) -{ - const struct keytype *kt; - - for (kt = keytypes; kt->type != -1; kt++) { - if (kt->type == type) - return kt->cert; - } - return 0; -} - -static int -key_type_is_valid_ca(int type) -{ - switch (type) { - case KEY_RSA: - case KEY_DSA: - case KEY_ECDSA: - case KEY_ED25519: - return 1; - default: - return 0; - } -} - -u_int -key_size(const Key *k) -{ - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - return BN_num_bits(k->rsa->n); - case KEY_DSA: - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - return BN_num_bits(k->dsa->p); - case KEY_ED25519: - return 256; /* XXX */ -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - case KEY_ECDSA_CERT: - return key_curve_nid_to_bits(k->ecdsa_nid); -#endif - } - return 0; -} - -static RSA * -rsa_generate_private_key(u_int bits) -{ - RSA *private = RSA_new(); - BIGNUM *f4 = BN_new(); - - if (private == NULL) - fatal("%s: RSA_new failed", __func__); - if (f4 == NULL) - fatal("%s: BN_new failed", __func__); - if (!BN_set_word(f4, RSA_F4)) - fatal("%s: BN_new failed", __func__); - if (!RSA_generate_key_ex(private, bits, f4, NULL)) - fatal("%s: key generation failed.", __func__); - BN_free(f4); - return private; -} - -static DSA* -dsa_generate_private_key(u_int bits) -{ - DSA *private = DSA_new(); - - if (private == NULL) - fatal("%s: DSA_new failed", __func__); - if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, - NULL, NULL)) - fatal("%s: DSA_generate_parameters failed", __func__); - if (!DSA_generate_key(private)) - fatal("%s: DSA_generate_key failed.", __func__); - return private; -} - -int -key_ecdsa_bits_to_nid(int bits) -{ - switch (bits) { -#ifdef OPENSSL_HAS_ECC - case 256: - return NID_X9_62_prime256v1; - case 384: - return NID_secp384r1; -# ifdef OPENSSL_HAS_NISTP521 - case 521: - return NID_secp521r1; -# endif -#endif - default: - return -1; - } -} - -#ifdef OPENSSL_HAS_ECC -int -key_ecdsa_key_to_nid(EC_KEY *k) -{ - EC_GROUP *eg; - int nids[] = { - NID_X9_62_prime256v1, - NID_secp384r1, -# ifdef OPENSSL_HAS_NISTP521 - NID_secp521r1, -# endif - -1 - }; - int nid; - u_int i; - BN_CTX *bnctx; - const EC_GROUP *g = EC_KEY_get0_group(k); - - /* - * The group may be stored in a ASN.1 encoded private key in one of two - * ways: as a "named group", which is reconstituted by ASN.1 object ID - * or explicit group parameters encoded into the key blob. Only the - * "named group" case sets the group NID for us, but we can figure - * it out for the other case by comparing against all the groups that - * are supported. - */ - if ((nid = EC_GROUP_get_curve_name(g)) > 0) - return nid; - if ((bnctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new() failed", __func__); - for (i = 0; nids[i] != -1; i++) { - if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) - fatal("%s: EC_GROUP_new_by_curve_name failed", - __func__); - if (EC_GROUP_cmp(g, eg, bnctx) == 0) - break; - EC_GROUP_free(eg); - } - BN_CTX_free(bnctx); - debug3("%s: nid = %d", __func__, nids[i]); - if (nids[i] != -1) { - /* Use the group with the NID attached */ - EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE); - if (EC_KEY_set_group(k, eg) != 1) - fatal("%s: EC_KEY_set_group", __func__); - } - return nids[i]; + return sshkey_write(key, f) == 0 ? 1 : 0; } -static EC_KEY* -ecdsa_generate_private_key(u_int bits, int *nid) -{ - EC_KEY *private; - - if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1) - fatal("%s: invalid key length", __func__); - if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) - fatal("%s: EC_KEY_new_by_curve_name failed", __func__); - if (EC_KEY_generate_key(private) != 1) - fatal("%s: EC_KEY_generate_key failed", __func__); - EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); - return private; -} -#endif /* OPENSSL_HAS_ECC */ - Key * key_generate(int type, u_int bits) { - Key *k = key_new(KEY_UNSPEC); - switch (type) { - case KEY_DSA: - k->dsa = dsa_generate_private_key(bits); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid); - break; -#endif - case KEY_RSA: - case KEY_RSA1: - k->rsa = rsa_generate_private_key(bits); - break; - case KEY_ED25519: - k->ed25519_pk = xmalloc(ED25519_PK_SZ); - k->ed25519_sk = xmalloc(ED25519_SK_SZ); - crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); - break; - case KEY_RSA_CERT_V00: - case KEY_DSA_CERT_V00: - case KEY_RSA_CERT: - case KEY_DSA_CERT: - fatal("key_generate: cert keys cannot be generated directly"); - default: - fatal("key_generate: unknown type %d", type); - } - k->type = type; - return k; + int r; + Key *ret = NULL; + + if ((r = sshkey_generate(type, bits, &ret)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + return ret; } void -key_cert_copy(const Key *from_key, struct Key *to_key) +key_cert_copy(const Key *from_key, Key *to_key) { - u_int i; - const struct KeyCert *from; - struct KeyCert *to; - - if (to_key->cert != NULL) { - cert_free(to_key->cert); - to_key->cert = NULL; - } - - if ((from = from_key->cert) == NULL) - return; - - to = to_key->cert = cert_new(); - - buffer_append(&to->certblob, buffer_ptr(&from->certblob), - buffer_len(&from->certblob)); + int r; - buffer_append(&to->critical, - buffer_ptr(&from->critical), buffer_len(&from->critical)); - buffer_append(&to->extensions, - buffer_ptr(&from->extensions), buffer_len(&from->extensions)); - - to->serial = from->serial; - to->type = from->type; - to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id); - to->valid_after = from->valid_after; - to->valid_before = from->valid_before; - to->signature_key = from->signature_key == NULL ? - NULL : key_from_private(from->signature_key); - - to->nprincipals = from->nprincipals; - if (to->nprincipals > CERT_MAX_PRINCIPALS) - fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)", - __func__, to->nprincipals, CERT_MAX_PRINCIPALS); - if (to->nprincipals > 0) { - to->principals = xcalloc(from->nprincipals, - sizeof(*to->principals)); - for (i = 0; i < to->nprincipals; i++) - to->principals[i] = xstrdup(from->principals[i]); - } + if ((r = sshkey_cert_copy(from_key, to_key)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); } Key * key_from_private(const Key *k) { - Key *n = NULL; - switch (k->type) { - case KEY_DSA: - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - n = key_new(k->type); - if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || - (BN_copy(n->dsa->q, k->dsa->q) == NULL) || - (BN_copy(n->dsa->g, k->dsa->g) == NULL) || - (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) - fatal("key_from_private: BN_copy failed"); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - case KEY_ECDSA_CERT: - n = key_new(k->type); - n->ecdsa_nid = k->ecdsa_nid; - if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) - fatal("%s: EC_KEY_new_by_curve_name failed", __func__); - if (EC_KEY_set_public_key(n->ecdsa, - EC_KEY_get0_public_key(k->ecdsa)) != 1) - fatal("%s: EC_KEY_set_public_key failed", __func__); - break; -#endif - case KEY_RSA: - case KEY_RSA1: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - n = key_new(k->type); - if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || - (BN_copy(n->rsa->e, k->rsa->e) == NULL)) - fatal("key_from_private: BN_copy failed"); - break; - case KEY_ED25519: - case KEY_ED25519_CERT: - n = key_new(k->type); - if (k->ed25519_pk != NULL) { - n->ed25519_pk = xmalloc(ED25519_PK_SZ); - memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); - } - break; - default: - fatal("key_from_private: unknown type %d", k->type); - break; - } - if (key_is_cert(k)) - key_cert_copy(k, n); - return n; -} - -int -key_names_valid2(const char *names) -{ - char *s, *cp, *p; - - if (names == NULL || strcmp(names, "") == 0) - return 0; - s = cp = xstrdup(names); - for ((p = strsep(&cp, ",")); p && *p != '\0'; - (p = strsep(&cp, ","))) { - switch (key_type_from_name(p)) { - case KEY_RSA1: - case KEY_UNSPEC: - free(s); - return 0; - } - } - debug3("key names ok: [%s]", names); - free(s); - return 1; -} - -static int -cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) -{ - u_char *principals, *critical, *exts, *sig_key, *sig; - u_int signed_len, plen, clen, sklen, slen, kidlen, elen; - Buffer tmp; - char *principal; - int ret = -1; - int v00 = key->type == KEY_DSA_CERT_V00 || - key->type == KEY_RSA_CERT_V00; - - buffer_init(&tmp); - - /* Copy the entire key blob for verification and later serialisation */ - buffer_append(&key->cert->certblob, blob, blen); - - elen = 0; /* Not touched for v00 certs */ - principals = exts = critical = sig_key = sig = NULL; - if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) || - buffer_get_int_ret(&key->cert->type, b) != 0 || - (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL || - (principals = buffer_get_string_ret(b, &plen)) == NULL || - buffer_get_int64_ret(&key->cert->valid_after, b) != 0 || - buffer_get_int64_ret(&key->cert->valid_before, b) != 0 || - (critical = buffer_get_string_ret(b, &clen)) == NULL || - (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) || - (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */ - buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */ - (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) { - error("%s: parse error", __func__); - goto out; - } - - /* Signature is left in the buffer so we can calculate this length */ - signed_len = buffer_len(&key->cert->certblob) - buffer_len(b); - - if ((sig = buffer_get_string_ret(b, &slen)) == NULL) { - error("%s: parse error", __func__); - goto out; - } - - if (key->cert->type != SSH2_CERT_TYPE_USER && - key->cert->type != SSH2_CERT_TYPE_HOST) { - error("Unknown certificate type %u", key->cert->type); - goto out; - } - - buffer_append(&tmp, principals, plen); - while (buffer_len(&tmp) > 0) { - if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) { - error("%s: Too many principals", __func__); - goto out; - } - if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) { - error("%s: Principals data invalid", __func__); - goto out; - } - key->cert->principals = xrealloc(key->cert->principals, - key->cert->nprincipals + 1, sizeof(*key->cert->principals)); - key->cert->principals[key->cert->nprincipals++] = principal; - } - - buffer_clear(&tmp); - - buffer_append(&key->cert->critical, critical, clen); - buffer_append(&tmp, critical, clen); - /* validate structure */ - while (buffer_len(&tmp) != 0) { - if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL || - buffer_get_string_ptr_ret(&tmp, NULL) == NULL) { - error("%s: critical option data invalid", __func__); - goto out; - } - } - buffer_clear(&tmp); - - buffer_append(&key->cert->extensions, exts, elen); - buffer_append(&tmp, exts, elen); - /* validate structure */ - while (buffer_len(&tmp) != 0) { - if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL || - buffer_get_string_ptr_ret(&tmp, NULL) == NULL) { - error("%s: extension data invalid", __func__); - goto out; - } - } - buffer_clear(&tmp); - - if ((key->cert->signature_key = key_from_blob2(sig_key, sklen, 0)) - == NULL) { - error("%s: Signature key invalid", __func__); - goto out; - } - if (!key_type_is_valid_ca(key->cert->signature_key->type)) { - error("%s: Invalid signature key type %s (%d)", __func__, - key_type(key->cert->signature_key), - key->cert->signature_key->type); - goto out; - } - - switch (key_verify(key->cert->signature_key, sig, slen, - buffer_ptr(&key->cert->certblob), signed_len)) { - case 1: - ret = 0; - break; /* Good signature */ - case 0: - error("%s: Invalid signature on certificate", __func__); - goto out; - case -1: - error("%s: Certificate signature verification failed", - __func__); - goto out; - } + int r; + Key *ret = NULL; - out: - buffer_free(&tmp); - free(principals); - free(critical); - free(exts); - free(sig_key); - free(sig); + if ((r = sshkey_from_private(k, &ret)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); return ret; } -static Key * -key_from_blob2(const u_char *blob, u_int blen, int allow_cert) +static void +fatal_on_fatal_errors(int r, const char *func, int extra_fatal) { - Buffer b; - int rlen, type; - u_int len; - char *ktype = NULL, *curve = NULL; - u_char *pk = NULL; - Key *key = NULL; -#ifdef OPENSSL_HAS_ECC - EC_POINT *q = NULL; - int nid = -1; -#endif - -#ifdef DEBUG_PK - dump_base64(stderr, blob, blen); -#endif - buffer_init(&b); - buffer_append(&b, blob, blen); - if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) { - error("key_from_blob: can't read key type"); - goto out; - } - - type = key_type_from_name(ktype); -#ifdef OPENSSL_HAS_ECC - if (key_type_plain(type) == KEY_ECDSA) - nid = key_ecdsa_nid_from_name(ktype); -#endif - if (!allow_cert && key_type_is_cert(type)) { - error("key_from_blob: certificate not allowed in this context"); - goto out; - } - switch (type) { - case KEY_RSA_CERT: - (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ - /* FALLTHROUGH */ - case KEY_RSA: - case KEY_RSA_CERT_V00: - key = key_new(type); - if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || - buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { - error("key_from_blob: can't read rsa key"); - badkey: - key_free(key); - key = NULL; - goto out; - } -#ifdef DEBUG_PK - RSA_print_fp(stderr, key->rsa, 8); -#endif - break; - case KEY_DSA_CERT: - (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ - /* FALLTHROUGH */ - case KEY_DSA: - case KEY_DSA_CERT_V00: - key = key_new(type); - if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->g) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) { - error("key_from_blob: can't read dsa key"); - goto badkey; - } -#ifdef DEBUG_PK - DSA_print_fp(stderr, key->dsa, 8); -#endif - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: - (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ - /* FALLTHROUGH */ - case KEY_ECDSA: - key = key_new(type); - key->ecdsa_nid = nid; - if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) { - error("key_from_blob: can't read ecdsa curve"); - goto badkey; - } - if (key->ecdsa_nid != key_curve_name_to_nid(curve)) { - error("key_from_blob: ecdsa curve doesn't match type"); - goto badkey; - } - if (key->ecdsa != NULL) - EC_KEY_free(key->ecdsa); - if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) - == NULL) - fatal("key_from_blob: EC_KEY_new_by_curve_name failed"); - if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) - fatal("key_from_blob: EC_POINT_new failed"); - if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa), - q) == -1) { - error("key_from_blob: can't read ecdsa key point"); - goto badkey; - } - if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa), - q) != 0) - goto badkey; - if (EC_KEY_set_public_key(key->ecdsa, q) != 1) - fatal("key_from_blob: EC_KEY_set_public_key failed"); -#ifdef DEBUG_PK - key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); -#endif - break; -#endif /* OPENSSL_HAS_ECC */ - case KEY_ED25519_CERT: - (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ - /* FALLTHROUGH */ - case KEY_ED25519: - if ((pk = buffer_get_string_ret(&b, &len)) == NULL) { - error("key_from_blob: can't read ed25519 key"); - goto badkey; - } - if (len != ED25519_PK_SZ) { - error("key_from_blob: ed25519 len %d != %d", - len, ED25519_PK_SZ); - goto badkey; - } - key = key_new(type); - key->ed25519_pk = pk; - pk = NULL; - break; - case KEY_UNSPEC: - key = key_new(type); - break; - default: - error("key_from_blob: cannot handle type %s", ktype); - goto out; - } - if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) { - error("key_from_blob: can't parse cert data"); - goto badkey; - } - rlen = buffer_len(&b); - if (key != NULL && rlen != 0) - error("key_from_blob: remaining bytes in key blob %d", rlen); - out: - free(ktype); - free(curve); - free(pk); -#ifdef OPENSSL_HAS_ECC - if (q != NULL) - EC_POINT_free(q); -#endif - buffer_free(&b); - return key; + if (r == SSH_ERR_INTERNAL_ERROR || + r == SSH_ERR_ALLOC_FAIL || + (extra_fatal != 0 && r == extra_fatal)) + fatal("%s: %s", func, ssh_err(r)); } Key * key_from_blob(const u_char *blob, u_int blen) { - return key_from_blob2(blob, blen, 1); + int r; + Key *ret = NULL; + + if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) { + fatal_on_fatal_errors(r, __func__, 0); + error("%s: %s", __func__, ssh_err(r)); + return NULL; + } + return ret; } -static int -to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain) +int +key_to_blob(const Key *key, u_char **blobp, u_int *lenp) { - Buffer b; - int len, type; + u_char *blob; + size_t blen; + int r; if (blobp != NULL) *blobp = NULL; if (lenp != NULL) *lenp = 0; - if (key == NULL) { - error("key_to_blob: key == NULL"); - return 0; - } - buffer_init(&b); - type = force_plain ? key_type_plain(key->type) : key->type; - switch (type) { - case KEY_DSA_CERT_V00: - case KEY_RSA_CERT_V00: - case KEY_DSA_CERT: - case KEY_ECDSA_CERT: - case KEY_RSA_CERT: - case KEY_ED25519_CERT: - /* Use the existing blob */ - buffer_append(&b, buffer_ptr(&key->cert->certblob), - buffer_len(&key->cert->certblob)); - break; - case KEY_DSA: - buffer_put_cstring(&b, - key_ssh_name_from_type_nid(type, key->ecdsa_nid)); - buffer_put_bignum2(&b, key->dsa->p); - buffer_put_bignum2(&b, key->dsa->q); - buffer_put_bignum2(&b, key->dsa->g); - buffer_put_bignum2(&b, key->dsa->pub_key); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - buffer_put_cstring(&b, - key_ssh_name_from_type_nid(type, key->ecdsa_nid)); - buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid)); - buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa), - EC_KEY_get0_public_key(key->ecdsa)); - break; -#endif - case KEY_RSA: - buffer_put_cstring(&b, - key_ssh_name_from_type_nid(type, key->ecdsa_nid)); - buffer_put_bignum2(&b, key->rsa->e); - buffer_put_bignum2(&b, key->rsa->n); - break; - case KEY_ED25519: - buffer_put_cstring(&b, - key_ssh_name_from_type_nid(type, key->ecdsa_nid)); - buffer_put_string(&b, key->ed25519_pk, ED25519_PK_SZ); - break; - default: - error("key_to_blob: unsupported key type %d", key->type); - buffer_free(&b); + if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { + fatal_on_fatal_errors(r, __func__, 0); + error("%s: %s", __func__, ssh_err(r)); return 0; } - len = buffer_len(&b); + if (blen > INT_MAX) + fatal("%s: giant len %zu", __func__, blen); + if (blobp != NULL) + *blobp = blob; if (lenp != NULL) - *lenp = len; - if (blobp != NULL) { - *blobp = xmalloc(len); - memcpy(*blobp, buffer_ptr(&b), len); - } - explicit_bzero(buffer_ptr(&b), len); - buffer_free(&b); - return len; + *lenp = blen; + return blen; } int -key_to_blob(const Key *key, u_char **blobp, u_int *lenp) -{ - return to_blob(key, blobp, lenp, 0); -} - -int -key_sign( - const Key *key, - u_char **sigp, u_int *lenp, +key_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { - switch (key->type) { - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - case KEY_DSA: - return ssh_dss_sign(key, sigp, lenp, data, datalen); -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: - case KEY_ECDSA: - return ssh_ecdsa_sign(key, sigp, lenp, data, datalen); -#endif - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - case KEY_RSA: - return ssh_rsa_sign(key, sigp, lenp, data, datalen); - case KEY_ED25519: - case KEY_ED25519_CERT: - return ssh_ed25519_sign(key, sigp, lenp, data, datalen); - default: - error("key_sign: invalid key type %d", key->type); + int r; + u_char *sig; + size_t siglen; + + if (sigp != NULL) + *sigp = NULL; + if (lenp != NULL) + *lenp = 0; + if ((r = sshkey_sign(key, &sig, &siglen, + data, datalen, datafellows)) != 0) { + fatal_on_fatal_errors(r, __func__, 0); + error("%s: %s", __func__, ssh_err(r)); return -1; } + if (siglen > INT_MAX) + fatal("%s: giant len %zu", __func__, siglen); + if (sigp != NULL) + *sigp = sig; + if (lenp != NULL) + *lenp = siglen; + return 0; } -/* - * key_verify returns 1 for a correct signature, 0 for an incorrect signature - * and -1 on error. - */ int -key_verify( - const Key *key, - const u_char *signature, u_int signaturelen, +key_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { - if (signaturelen == 0) - return -1; + int r; - switch (key->type) { - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - case KEY_DSA: - return ssh_dss_verify(key, signature, signaturelen, data, datalen); -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: - case KEY_ECDSA: - return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen); -#endif - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - case KEY_RSA: - return ssh_rsa_verify(key, signature, signaturelen, data, datalen); - case KEY_ED25519: - case KEY_ED25519_CERT: - return ssh_ed25519_verify(key, signature, signaturelen, data, datalen); - default: - error("key_verify: invalid key type %d", key->type); - return -1; + if ((r = sshkey_verify(key, signature, signaturelen, + data, datalen, datafellows)) != 0) { + fatal_on_fatal_errors(r, __func__, 0); + error("%s: %s", __func__, ssh_err(r)); + return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1; } + return 1; } -/* Converts a private to a public key */ Key * key_demote(const Key *k) { - Key *pk; - - pk = xcalloc(1, sizeof(*pk)); - pk->type = k->type; - pk->flags = k->flags; - pk->ecdsa_nid = k->ecdsa_nid; - pk->dsa = NULL; - pk->ecdsa = NULL; - pk->rsa = NULL; - pk->ed25519_pk = NULL; - pk->ed25519_sk = NULL; - - switch (k->type) { - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - key_cert_copy(k, pk); - /* FALLTHROUGH */ - case KEY_RSA1: - case KEY_RSA: - if ((pk->rsa = RSA_new()) == NULL) - fatal("key_demote: RSA_new failed"); - if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) - fatal("key_demote: BN_dup failed"); - break; - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - key_cert_copy(k, pk); - /* FALLTHROUGH */ - case KEY_DSA: - if ((pk->dsa = DSA_new()) == NULL) - fatal("key_demote: DSA_new failed"); - if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) - fatal("key_demote: BN_dup failed"); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: - key_cert_copy(k, pk); - /* FALLTHROUGH */ - case KEY_ECDSA: - if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL) - fatal("key_demote: EC_KEY_new_by_curve_name failed"); - if (EC_KEY_set_public_key(pk->ecdsa, - EC_KEY_get0_public_key(k->ecdsa)) != 1) - fatal("key_demote: EC_KEY_set_public_key failed"); - break; -#endif - case KEY_ED25519_CERT: - key_cert_copy(k, pk); - /* FALLTHROUGH */ - case KEY_ED25519: - if (k->ed25519_pk != NULL) { - pk->ed25519_pk = xmalloc(ED25519_PK_SZ); - memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); - } - break; - default: - fatal("key_demote: bad key type %d", k->type); - break; - } - - return (pk); -} + int r; + Key *ret = NULL; -int -key_is_cert(const Key *k) -{ - if (k == NULL) - return 0; - return key_type_is_cert(k->type); + if ((r = sshkey_demote(k, &ret)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + return ret; } -/* Return the cert-less equivalent to a certified key type */ int -key_type_plain(int type) +key_to_certified(Key *k) { - switch (type) { - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - return KEY_RSA; - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - return KEY_DSA; - case KEY_ECDSA_CERT: - return KEY_ECDSA; - case KEY_ED25519_CERT: - return KEY_ED25519; - default: - return type; - } -} + int r; -/* Convert a plain key to their _CERT equivalent */ -int -key_to_certified(Key *k, int legacy) -{ - switch (k->type) { - case KEY_RSA: - k->cert = cert_new(); - k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT; - return 0; - case KEY_DSA: - k->cert = cert_new(); - k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT; - return 0; - case KEY_ECDSA: - if (legacy) - fatal("%s: legacy ECDSA certificates are not supported", - __func__); - k->cert = cert_new(); - k->type = KEY_ECDSA_CERT; - return 0; - case KEY_ED25519: - if (legacy) - fatal("%s: legacy ED25519 certificates are not " - "supported", __func__); - k->cert = cert_new(); - k->type = KEY_ED25519_CERT; - return 0; - default: - error("%s: key has incorrect type %s", __func__, key_type(k)); + if ((r = sshkey_to_certified(k)) != 0) { + fatal_on_fatal_errors(r, __func__, 0); + error("%s: %s", __func__, ssh_err(r)); return -1; } + return 0; } -/* Convert a certificate to its raw key equivalent */ int key_drop_cert(Key *k) { - if (!key_type_is_cert(k->type)) { - error("%s: key has incorrect type %s", __func__, key_type(k)); + int r; + + if ((r = sshkey_drop_cert(k)) != 0) { + fatal_on_fatal_errors(r, __func__, 0); + error("%s: %s", __func__, ssh_err(r)); return -1; } - cert_free(k->cert); - k->cert = NULL; - k->type = key_type_plain(k->type); return 0; } -/* Sign a certified key, (re-)generating the signed certblob. */ int key_certify(Key *k, Key *ca) { - Buffer principals; - u_char *ca_blob, *sig_blob, nonce[32]; - u_int i, ca_len, sig_len; - - if (k->cert == NULL) { - error("%s: key lacks cert info", __func__); - return -1; - } - - if (!key_is_cert(k)) { - error("%s: certificate has unknown type %d", __func__, - k->cert->type); - return -1; - } - - if (!key_type_is_valid_ca(ca->type)) { - error("%s: CA key has unsupported type %s", __func__, - key_type(ca)); - return -1; - } - - key_to_blob(ca, &ca_blob, &ca_len); - - buffer_clear(&k->cert->certblob); - buffer_put_cstring(&k->cert->certblob, key_ssh_name(k)); - - /* -v01 certs put nonce first */ - arc4random_buf(&nonce, sizeof(nonce)); - if (!key_cert_is_legacy(k)) - buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); + int r; - /* XXX this substantially duplicates to_blob(); refactor */ - switch (k->type) { - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - buffer_put_bignum2(&k->cert->certblob, k->dsa->p); - buffer_put_bignum2(&k->cert->certblob, k->dsa->q); - buffer_put_bignum2(&k->cert->certblob, k->dsa->g); - buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: - buffer_put_cstring(&k->cert->certblob, - key_curve_nid_to_name(k->ecdsa_nid)); - buffer_put_ecpoint(&k->cert->certblob, - EC_KEY_get0_group(k->ecdsa), - EC_KEY_get0_public_key(k->ecdsa)); - break; -#endif - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - buffer_put_bignum2(&k->cert->certblob, k->rsa->e); - buffer_put_bignum2(&k->cert->certblob, k->rsa->n); - break; - case KEY_ED25519_CERT: - buffer_put_string(&k->cert->certblob, - k->ed25519_pk, ED25519_PK_SZ); - break; - default: - error("%s: key has incorrect type %s", __func__, key_type(k)); - buffer_clear(&k->cert->certblob); - free(ca_blob); + if ((r = sshkey_certify(k, ca)) != 0) { + fatal_on_fatal_errors(r, __func__, 0); + error("%s: %s", __func__, ssh_err(r)); return -1; } - - /* -v01 certs have a serial number next */ - if (!key_cert_is_legacy(k)) - buffer_put_int64(&k->cert->certblob, k->cert->serial); - - buffer_put_int(&k->cert->certblob, k->cert->type); - buffer_put_cstring(&k->cert->certblob, k->cert->key_id); - - buffer_init(&principals); - for (i = 0; i < k->cert->nprincipals; i++) - buffer_put_cstring(&principals, k->cert->principals[i]); - buffer_put_string(&k->cert->certblob, buffer_ptr(&principals), - buffer_len(&principals)); - buffer_free(&principals); - - buffer_put_int64(&k->cert->certblob, k->cert->valid_after); - buffer_put_int64(&k->cert->certblob, k->cert->valid_before); - buffer_put_string(&k->cert->certblob, - buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical)); - - /* -v01 certs have non-critical options here */ - if (!key_cert_is_legacy(k)) { - buffer_put_string(&k->cert->certblob, - buffer_ptr(&k->cert->extensions), - buffer_len(&k->cert->extensions)); - } - - /* -v00 certs put the nonce at the end */ - if (key_cert_is_legacy(k)) - buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); - - buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ - buffer_put_string(&k->cert->certblob, ca_blob, ca_len); - free(ca_blob); - - /* Sign the whole mess */ - if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob), - buffer_len(&k->cert->certblob)) != 0) { - error("%s: signature operation failed", __func__); - buffer_clear(&k->cert->certblob); - return -1; - } - /* Append signature and we are done */ - buffer_put_string(&k->cert->certblob, sig_blob, sig_len); - free(sig_blob); - return 0; } @@ -2091,535 +226,201 @@ int key_cert_check_authority(const Key *k, int want_host, int require_principal, const char *name, const char **reason) { - u_int i, principal_matches; - time_t now = time(NULL); + int r; - if (want_host) { - if (k->cert->type != SSH2_CERT_TYPE_HOST) { - *reason = "Certificate invalid: not a host certificate"; - return -1; - } - } else { - if (k->cert->type != SSH2_CERT_TYPE_USER) { - *reason = "Certificate invalid: not a user certificate"; - return -1; - } - } - if (now < 0) { - error("%s: system clock lies before epoch", __func__); - *reason = "Certificate invalid: not yet valid"; + if ((r = sshkey_cert_check_authority(k, want_host, require_principal, + name, reason)) != 0) { + fatal_on_fatal_errors(r, __func__, 0); + error("%s: %s", __func__, ssh_err(r)); return -1; } - if ((u_int64_t)now < k->cert->valid_after) { - *reason = "Certificate invalid: not yet valid"; - return -1; - } - if ((u_int64_t)now >= k->cert->valid_before) { - *reason = "Certificate invalid: expired"; - return -1; - } - if (k->cert->nprincipals == 0) { - if (require_principal) { - *reason = "Certificate lacks principal list"; - return -1; - } - } else if (name != NULL) { - principal_matches = 0; - for (i = 0; i < k->cert->nprincipals; i++) { - if (strcmp(name, k->cert->principals[i]) == 0) { - principal_matches = 1; - break; - } - } - if (!principal_matches) { - *reason = "Certificate invalid: name is not a listed " - "principal"; - return -1; - } - } return 0; } +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) int -key_cert_is_legacy(const Key *k) +key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) { - switch (k->type) { - case KEY_DSA_CERT_V00: - case KEY_RSA_CERT_V00: - return 1; - default: - return 0; + int r; + + if ((r = sshkey_ec_validate_public(group, public)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + error("%s: %s", __func__, ssh_err(r)); + return -1; } + return 0; } -/* XXX: these are really begging for a table-driven approach */ int -key_curve_name_to_nid(const char *name) +key_ec_validate_private(const EC_KEY *key) { -#ifdef OPENSSL_HAS_ECC - if (strcmp(name, "nistp256") == 0) - return NID_X9_62_prime256v1; - else if (strcmp(name, "nistp384") == 0) - return NID_secp384r1; -# ifdef OPENSSL_HAS_NISTP521 - else if (strcmp(name, "nistp521") == 0) - return NID_secp521r1; -# endif -#endif - - debug("%s: unsupported EC curve name \"%.100s\"", __func__, name); - return -1; -} + int r; -u_int -key_curve_nid_to_bits(int nid) -{ - switch (nid) { -#ifdef OPENSSL_HAS_ECC - case NID_X9_62_prime256v1: - return 256; - case NID_secp384r1: - return 384; -# ifdef OPENSSL_HAS_NISTP521 - case NID_secp521r1: - return 521; -# endif -#endif - default: - error("%s: unsupported EC curve nid %d", __func__, nid); - return 0; + if ((r = sshkey_ec_validate_private(key)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + error("%s: %s", __func__, ssh_err(r)); + return -1; } + return 0; } +#endif /* WITH_OPENSSL */ -const char * -key_curve_nid_to_name(int nid) -{ -#ifdef OPENSSL_HAS_ECC - if (nid == NID_X9_62_prime256v1) - return "nistp256"; - else if (nid == NID_secp384r1) - return "nistp384"; -# ifdef OPENSSL_HAS_NISTP521 - else if (nid == NID_secp521r1) - return "nistp521"; -# endif -#endif - error("%s: unsupported EC curve nid %d", __func__, nid); - return NULL; -} - -#ifdef OPENSSL_HAS_ECC -int -key_ec_nid_to_hash_alg(int nid) +void +key_private_serialize(const Key *key, struct sshbuf *b) { - int kbits = key_curve_nid_to_bits(nid); + int r; - if (kbits == 0) - fatal("%s: invalid nid %d", __func__, nid); - /* RFC5656 section 6.2.1 */ - if (kbits <= 256) - return SSH_DIGEST_SHA256; - else if (kbits <= 384) - return SSH_DIGEST_SHA384; - else - return SSH_DIGEST_SHA512; + if ((r = sshkey_private_serialize(key, b)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); } -int -key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) +Key * +key_private_deserialize(struct sshbuf *blob) { - BN_CTX *bnctx; - EC_POINT *nq = NULL; - BIGNUM *order, *x, *y, *tmp; - int ret = -1; - - if ((bnctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new failed", __func__); - BN_CTX_start(bnctx); + int r; + Key *ret = NULL; - /* - * We shouldn't ever hit this case because bignum_get_ecpoint() - * refuses to load GF2m points. - */ - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_prime_field) { - error("%s: group is not a prime field", __func__); - goto out; - } - - /* Q != infinity */ - if (EC_POINT_is_at_infinity(group, public)) { - error("%s: received degenerate public key (infinity)", - __func__); - goto out; + if ((r = sshkey_private_deserialize(blob, &ret)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + error("%s: %s", __func__, ssh_err(r)); + return NULL; } + return ret; +} - if ((x = BN_CTX_get(bnctx)) == NULL || - (y = BN_CTX_get(bnctx)) == NULL || - (order = BN_CTX_get(bnctx)) == NULL || - (tmp = BN_CTX_get(bnctx)) == NULL) - fatal("%s: BN_CTX_get failed", __func__); +/* authfile.c */ - /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ - if (EC_GROUP_get_order(group, order, bnctx) != 1) - fatal("%s: EC_GROUP_get_order failed", __func__); - if (EC_POINT_get_affine_coordinates_GFp(group, public, - x, y, bnctx) != 1) - fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__); - if (BN_num_bits(x) <= BN_num_bits(order) / 2) { - error("%s: public key x coordinate too small: " - "bits(x) = %d, bits(order)/2 = %d", __func__, - BN_num_bits(x), BN_num_bits(order) / 2); - goto out; - } - if (BN_num_bits(y) <= BN_num_bits(order) / 2) { - error("%s: public key y coordinate too small: " - "bits(y) = %d, bits(order)/2 = %d", __func__, - BN_num_bits(x), BN_num_bits(order) / 2); - goto out; - } - - /* nQ == infinity (n == order of subgroup) */ - if ((nq = EC_POINT_new(group)) == NULL) - fatal("%s: BN_CTX_tmp failed", __func__); - if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) - fatal("%s: EC_GROUP_mul failed", __func__); - if (EC_POINT_is_at_infinity(group, nq) != 1) { - error("%s: received degenerate public key (nQ != infinity)", - __func__); - goto out; - } +int +key_save_private(Key *key, const char *filename, const char *passphrase, + const char *comment, int force_new_format, const char *new_format_cipher, + int new_format_rounds) +{ + int r; - /* x < order - 1, y < order - 1 */ - if (!BN_sub(tmp, order, BN_value_one())) - fatal("%s: BN_sub failed", __func__); - if (BN_cmp(x, tmp) >= 0) { - error("%s: public key x coordinate >= group order - 1", - __func__); - goto out; - } - if (BN_cmp(y, tmp) >= 0) { - error("%s: public key y coordinate >= group order - 1", - __func__); - goto out; + if ((r = sshkey_save_private(key, filename, passphrase, comment, + force_new_format, new_format_cipher, new_format_rounds)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + error("%s: %s", __func__, ssh_err(r)); + return 0; } - ret = 0; - out: - BN_CTX_free(bnctx); - EC_POINT_free(nq); - return ret; + return 1; } int -key_ec_validate_private(const EC_KEY *key) +key_load_file(int fd, const char *filename, struct sshbuf *blob) { - BN_CTX *bnctx; - BIGNUM *order, *tmp; - int ret = -1; - - if ((bnctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new failed", __func__); - BN_CTX_start(bnctx); + int r; - if ((order = BN_CTX_get(bnctx)) == NULL || - (tmp = BN_CTX_get(bnctx)) == NULL) - fatal("%s: BN_CTX_get failed", __func__); - - /* log2(private) > log2(order)/2 */ - if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) - fatal("%s: EC_GROUP_get_order failed", __func__); - if (BN_num_bits(EC_KEY_get0_private_key(key)) <= - BN_num_bits(order) / 2) { - error("%s: private key too small: " - "bits(y) = %d, bits(order)/2 = %d", __func__, - BN_num_bits(EC_KEY_get0_private_key(key)), - BN_num_bits(order) / 2); - goto out; + if ((r = sshkey_load_file(fd, blob)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + error("%s: %s", __func__, ssh_err(r)); + return 0; } + return 1; +} - /* private < order - 1 */ - if (!BN_sub(tmp, order, BN_value_one())) - fatal("%s: BN_sub failed", __func__); - if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) { - error("%s: private key >= group order - 1", __func__); - goto out; +Key * +key_load_cert(const char *filename) +{ + int r; + Key *ret = NULL; + + if ((r = sshkey_load_cert(filename, &ret)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + /* Old authfile.c ignored all file errors. */ + if (r == SSH_ERR_SYSTEM_ERROR) + debug("%s: %s", __func__, ssh_err(r)); + else + error("%s: %s", __func__, ssh_err(r)); + return NULL; } - ret = 0; - out: - BN_CTX_free(bnctx); return ret; -} -#if defined(DEBUG_KEXECDH) || defined(DEBUG_PK) -void -key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) -{ - BIGNUM *x, *y; - BN_CTX *bnctx; +} - if (point == NULL) { - fputs("point=(NULL)\n", stderr); - return; +Key * +key_load_public(const char *filename, char **commentp) +{ + int r; + Key *ret = NULL; + + if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + /* Old authfile.c ignored all file errors. */ + if (r == SSH_ERR_SYSTEM_ERROR) + debug("%s: %s", __func__, ssh_err(r)); + else + error("%s: %s", __func__, ssh_err(r)); + return NULL; } - if ((bnctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new failed", __func__); - BN_CTX_start(bnctx); - if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL) - fatal("%s: BN_CTX_get failed", __func__); - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_prime_field) - fatal("%s: group is not a prime field", __func__); - if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1) - fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__); - fputs("x=", stderr); - BN_print_fp(stderr, x); - fputs("\ny=", stderr); - BN_print_fp(stderr, y); - fputs("\n", stderr); - BN_CTX_free(bnctx); + return ret; } -void -key_dump_ec_key(const EC_KEY *key) -{ - const BIGNUM *exponent; - - key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key)); - fputs("exponent=", stderr); - if ((exponent = EC_KEY_get0_private_key(key)) == NULL) - fputs("(NULL)", stderr); - else - BN_print_fp(stderr, EC_KEY_get0_private_key(key)); - fputs("\n", stderr); +Key * +key_load_private(const char *path, const char *passphrase, + char **commentp) +{ + int r; + Key *ret = NULL; + + if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + /* Old authfile.c ignored all file errors. */ + if (r == SSH_ERR_SYSTEM_ERROR || + r == SSH_ERR_KEY_WRONG_PASSPHRASE) + debug("%s: %s", __func__, ssh_err(r)); + else + error("%s: %s", __func__, ssh_err(r)); + return NULL; + } + return ret; } -#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */ -#endif /* OPENSSL_HAS_ECC */ -void -key_private_serialize(const Key *key, Buffer *b) -{ - buffer_put_cstring(b, key_ssh_name(key)); - switch (key->type) { - case KEY_RSA: - buffer_put_bignum2(b, key->rsa->n); - buffer_put_bignum2(b, key->rsa->e); - buffer_put_bignum2(b, key->rsa->d); - buffer_put_bignum2(b, key->rsa->iqmp); - buffer_put_bignum2(b, key->rsa->p); - buffer_put_bignum2(b, key->rsa->q); - break; - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) - fatal("%s: no cert/certblob", __func__); - buffer_put_string(b, buffer_ptr(&key->cert->certblob), - buffer_len(&key->cert->certblob)); - buffer_put_bignum2(b, key->rsa->d); - buffer_put_bignum2(b, key->rsa->iqmp); - buffer_put_bignum2(b, key->rsa->p); - buffer_put_bignum2(b, key->rsa->q); - break; - case KEY_DSA: - buffer_put_bignum2(b, key->dsa->p); - buffer_put_bignum2(b, key->dsa->q); - buffer_put_bignum2(b, key->dsa->g); - buffer_put_bignum2(b, key->dsa->pub_key); - buffer_put_bignum2(b, key->dsa->priv_key); - break; - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) - fatal("%s: no cert/certblob", __func__); - buffer_put_string(b, buffer_ptr(&key->cert->certblob), - buffer_len(&key->cert->certblob)); - buffer_put_bignum2(b, key->dsa->priv_key); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid)); - buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa), - EC_KEY_get0_public_key(key->ecdsa)); - buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); - break; - case KEY_ECDSA_CERT: - if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) - fatal("%s: no cert/certblob", __func__); - buffer_put_string(b, buffer_ptr(&key->cert->certblob), - buffer_len(&key->cert->certblob)); - buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); - break; -#endif /* OPENSSL_HAS_ECC */ - case KEY_ED25519: - buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ); - buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ); - break; - case KEY_ED25519_CERT: - if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) - fatal("%s: no cert/certblob", __func__); - buffer_put_string(b, buffer_ptr(&key->cert->certblob), - buffer_len(&key->cert->certblob)); - buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ); - buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ); - break; +Key * +key_load_private_cert(int type, const char *filename, const char *passphrase, + int *perm_ok) +{ + int r; + Key *ret = NULL; + + if ((r = sshkey_load_private_cert(type, filename, passphrase, + &ret, perm_ok)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + /* Old authfile.c ignored all file errors. */ + if (r == SSH_ERR_SYSTEM_ERROR || + r == SSH_ERR_KEY_WRONG_PASSPHRASE) + debug("%s: %s", __func__, ssh_err(r)); + else + error("%s: %s", __func__, ssh_err(r)); + return NULL; } + return ret; } Key * -key_private_deserialize(Buffer *blob) -{ - char *type_name; - Key *k = NULL; - u_char *cert; - u_int len, pklen, sklen; - int type; -#ifdef OPENSSL_HAS_ECC - char *curve; - BIGNUM *exponent; - EC_POINT *q; -#endif - - type_name = buffer_get_string(blob, NULL); - type = key_type_from_name(type_name); - switch (type) { - case KEY_DSA: - k = key_new_private(type); - buffer_get_bignum2(blob, k->dsa->p); - buffer_get_bignum2(blob, k->dsa->q); - buffer_get_bignum2(blob, k->dsa->g); - buffer_get_bignum2(blob, k->dsa->pub_key); - buffer_get_bignum2(blob, k->dsa->priv_key); - break; - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - cert = buffer_get_string(blob, &len); - if ((k = key_from_blob(cert, len)) == NULL) - fatal("Certificate parse failed"); - free(cert); - key_add_private(k); - buffer_get_bignum2(blob, k->dsa->priv_key); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - k = key_new_private(type); - k->ecdsa_nid = key_ecdsa_nid_from_name(type_name); - curve = buffer_get_string(blob, NULL); - if (k->ecdsa_nid != key_curve_name_to_nid(curve)) - fatal("%s: curve names mismatch", __func__); - free(curve); - k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); - if (k->ecdsa == NULL) - fatal("%s: EC_KEY_new_by_curve_name failed", - __func__); - q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa)); - if (q == NULL) - fatal("%s: BN_new failed", __func__); - if ((exponent = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - buffer_get_ecpoint(blob, - EC_KEY_get0_group(k->ecdsa), q); - buffer_get_bignum2(blob, exponent); - if (EC_KEY_set_public_key(k->ecdsa, q) != 1) - fatal("%s: EC_KEY_set_public_key failed", - __func__); - if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) - fatal("%s: EC_KEY_set_private_key failed", - __func__); - if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), - EC_KEY_get0_public_key(k->ecdsa)) != 0) - fatal("%s: bad ECDSA public key", __func__); - if (key_ec_validate_private(k->ecdsa) != 0) - fatal("%s: bad ECDSA private key", __func__); - BN_clear_free(exponent); - EC_POINT_free(q); - break; - case KEY_ECDSA_CERT: - cert = buffer_get_string(blob, &len); - if ((k = key_from_blob(cert, len)) == NULL) - fatal("Certificate parse failed"); - free(cert); - key_add_private(k); - if ((exponent = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - buffer_get_bignum2(blob, exponent); - if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) - fatal("%s: EC_KEY_set_private_key failed", - __func__); - if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), - EC_KEY_get0_public_key(k->ecdsa)) != 0 || - key_ec_validate_private(k->ecdsa) != 0) - fatal("%s: bad ECDSA key", __func__); - BN_clear_free(exponent); - break; -#endif - case KEY_RSA: - k = key_new_private(type); - buffer_get_bignum2(blob, k->rsa->n); - buffer_get_bignum2(blob, k->rsa->e); - buffer_get_bignum2(blob, k->rsa->d); - buffer_get_bignum2(blob, k->rsa->iqmp); - buffer_get_bignum2(blob, k->rsa->p); - buffer_get_bignum2(blob, k->rsa->q); - - /* Generate additional parameters */ - rsa_generate_additional_parameters(k->rsa); - break; - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - cert = buffer_get_string(blob, &len); - if ((k = key_from_blob(cert, len)) == NULL) - fatal("Certificate parse failed"); - free(cert); - key_add_private(k); - buffer_get_bignum2(blob, k->rsa->d); - buffer_get_bignum2(blob, k->rsa->iqmp); - buffer_get_bignum2(blob, k->rsa->p); - buffer_get_bignum2(blob, k->rsa->q); - break; - case KEY_ED25519: - k = key_new_private(type); - k->ed25519_pk = buffer_get_string(blob, &pklen); - k->ed25519_sk = buffer_get_string(blob, &sklen); - if (pklen != ED25519_PK_SZ) - fatal("%s: ed25519 pklen %d != %d", - __func__, pklen, ED25519_PK_SZ); - if (sklen != ED25519_SK_SZ) - fatal("%s: ed25519 sklen %d != %d", - __func__, sklen, ED25519_SK_SZ); - break; - case KEY_ED25519_CERT: - cert = buffer_get_string(blob, &len); - if ((k = key_from_blob(cert, len)) == NULL) - fatal("Certificate parse failed"); - free(cert); - key_add_private(k); - k->ed25519_pk = buffer_get_string(blob, &pklen); - k->ed25519_sk = buffer_get_string(blob, &sklen); - if (pklen != ED25519_PK_SZ) - fatal("%s: ed25519 pklen %d != %d", - __func__, pklen, ED25519_PK_SZ); - if (sklen != ED25519_SK_SZ) - fatal("%s: ed25519 sklen %d != %d", - __func__, sklen, ED25519_SK_SZ); - break; - default: - free(type_name); - buffer_clear(blob); +key_load_private_type(int type, const char *filename, const char *passphrase, + char **commentp, int *perm_ok) +{ + int r; + Key *ret = NULL; + + if ((r = sshkey_load_private_type(type, filename, passphrase, + &ret, commentp, perm_ok)) != 0) { + fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); + /* Old authfile.c ignored all file errors. */ + if (r == SSH_ERR_SYSTEM_ERROR || + (r == SSH_ERR_KEY_WRONG_PASSPHRASE)) + debug("%s: %s", __func__, ssh_err(r)); + else + error("%s: %s", __func__, ssh_err(r)); return NULL; } - free(type_name); + return ret; +} - /* enable blinding */ - switch (k->type) { - case KEY_RSA: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: - case KEY_RSA1: - if (RSA_blinding_on(k->rsa, NULL) != 1) { - error("%s: RSA_blinding_on failed", __func__); - key_free(k); - return NULL; - } - break; - } - return k; +int +key_perm_ok(int fd, const char *filename) +{ + return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0; } + diff --git a/crypto/openssh/key.h b/crypto/openssh/key.h index d8ad13d..903bdf6 100644 --- a/crypto/openssh/key.h +++ b/crypto/openssh/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.41 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: key.h,v 1.48 2015/07/03 03:43:18 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -26,141 +26,79 @@ #ifndef KEY_H #define KEY_H -#include "buffer.h" -#include -#include -#ifdef OPENSSL_HAS_ECC -#include +#include "sshkey.h" + +typedef struct sshkey Key; + +#define types sshkey_types +#define fp_type sshkey_fp_type +#define fp_rep sshkey_fp_rep + +#ifndef SSH_KEY_NO_DEFINE +#define key_new sshkey_new +#define key_free sshkey_free +#define key_equal_public sshkey_equal_public +#define key_equal sshkey_equal +#define key_type sshkey_type +#define key_cert_type sshkey_cert_type +#define key_ssh_name sshkey_ssh_name +#define key_ssh_name_plain sshkey_ssh_name_plain +#define key_type_from_name sshkey_type_from_name +#define key_ecdsa_nid_from_name sshkey_ecdsa_nid_from_name +#define key_type_is_cert sshkey_type_is_cert +#define key_size sshkey_size +#define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid +#define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid +#define key_is_cert sshkey_is_cert +#define key_type_plain sshkey_type_plain +#define key_curve_name_to_nid sshkey_curve_name_to_nid +#define key_curve_nid_to_bits sshkey_curve_nid_to_bits +#define key_curve_nid_to_name sshkey_curve_nid_to_name +#define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg +#define key_dump_ec_point sshkey_dump_ec_point +#define key_dump_ec_key sshkey_dump_ec_key #endif -typedef struct Key Key; -enum types { - KEY_RSA1, - KEY_RSA, - KEY_DSA, - KEY_ECDSA, - KEY_ED25519, - KEY_RSA_CERT, - KEY_DSA_CERT, - KEY_ECDSA_CERT, - KEY_ED25519_CERT, - KEY_RSA_CERT_V00, - KEY_DSA_CERT_V00, - KEY_UNSPEC -}; -enum fp_type { - SSH_FP_SHA1, - SSH_FP_MD5, - SSH_FP_SHA256 -}; -enum fp_rep { - SSH_FP_HEX, - SSH_FP_BUBBLEBABBLE, - SSH_FP_RANDOMART -}; - -/* key is stored in external hardware */ -#define KEY_FLAG_EXT 0x0001 - -#define CERT_MAX_PRINCIPALS 256 -struct KeyCert { - Buffer certblob; /* Kept around for use on wire */ - u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */ - u_int64_t serial; - char *key_id; - u_int nprincipals; - char **principals; - u_int64_t valid_after, valid_before; - Buffer critical; - Buffer extensions; - Key *signature_key; -}; - -struct Key { - int type; - int flags; - RSA *rsa; - DSA *dsa; - int ecdsa_nid; /* NID of curve */ -#ifdef OPENSSL_HAS_ECC - EC_KEY *ecdsa; -#else - void *ecdsa; -#endif - struct KeyCert *cert; - u_char *ed25519_sk; - u_char *ed25519_pk; -}; - -#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES -#define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES - -Key *key_new(int); -void key_add_private(Key *); -Key *key_new_private(int); -void key_free(Key *); -Key *key_demote(const Key *); -int key_equal_public(const Key *, const Key *); -int key_equal(const Key *, const Key *); -char *key_fingerprint(const Key *, enum fp_type, enum fp_rep); -u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); -const char *key_type(const Key *); -const char *key_cert_type(const Key *); -int key_write(const Key *, FILE *); -int key_read(Key *, char **); -u_int key_size(const Key *); +void key_add_private(Key *); +Key *key_new_private(int); +void key_free(Key *); +Key *key_demote(const Key *); +int key_write(const Key *, FILE *); +int key_read(Key *, char **); Key *key_generate(int, u_int); Key *key_from_private(const Key *); -int key_type_from_name(char *); -int key_is_cert(const Key *); -int key_type_is_cert(int); -int key_type_plain(int); -int key_to_certified(Key *, int); +int key_to_certified(Key *); int key_drop_cert(Key *); int key_certify(Key *, Key *); -void key_cert_copy(const Key *, struct Key *); +void key_cert_copy(const Key *, Key *); int key_cert_check_authority(const Key *, int, int, const char *, const char **); -int key_cert_is_legacy(const Key *); +char *key_alg_list(int, int); -int key_ecdsa_nid_from_name(const char *); -int key_curve_name_to_nid(const char *); -const char *key_curve_nid_to_name(int); -u_int key_curve_nid_to_bits(int); -int key_ecdsa_bits_to_nid(int); -#ifdef OPENSSL_HAS_ECC -int key_ecdsa_key_to_nid(EC_KEY *); -int key_ec_nid_to_hash_alg(int nid); -int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); -int key_ec_validate_private(const EC_KEY *); -#endif -char *key_alg_list(int, int); +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) +int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); +int key_ec_validate_private(const EC_KEY *); +#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ -Key *key_from_blob(const u_char *, u_int); -int key_to_blob(const Key *, u_char **, u_int *); -const char *key_ssh_name(const Key *); -const char *key_ssh_name_plain(const Key *); -int key_names_valid2(const char *); +Key *key_from_blob(const u_char *, u_int); +int key_to_blob(const Key *, u_char **, u_int *); int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); -int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int); -int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int); -int ssh_ecdsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); -int ssh_ecdsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); -int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); -int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); -int ssh_ed25519_sign(const Key *, u_char **, u_int *, const u_char *, u_int); -int ssh_ed25519_verify(const Key *, const u_char *, u_int, const u_char *, u_int); - -#if defined(OPENSSL_HAS_ECC) && (defined(DEBUG_KEXECDH) || defined(DEBUG_PK)) -void key_dump_ec_point(const EC_GROUP *, const EC_POINT *); -void key_dump_ec_key(const EC_KEY *); -#endif - -void key_private_serialize(const Key *, Buffer *); -Key *key_private_deserialize(Buffer *); +void key_private_serialize(const Key *, struct sshbuf *); +Key *key_private_deserialize(struct sshbuf *); + +/* authfile.c */ +int key_save_private(Key *, const char *, const char *, const char *, + int, const char *, int); +int key_load_file(int, const char *, struct sshbuf *); +Key *key_load_cert(const char *); +Key *key_load_public(const char *, char **); +Key *key_load_private(const char *, const char *, char **); +Key *key_load_private_cert(int, const char *, const char *, int *); +Key *key_load_private_type(int, const char *, const char *, char **, int *); +int key_perm_ok(int, const char *); #endif diff --git a/crypto/openssh/krl.c b/crypto/openssh/krl.c index 3b4cded..4075df8 100644 --- a/crypto/openssh/krl.c +++ b/crypto/openssh/krl.c @@ -14,12 +14,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.c,v 1.14 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: krl.c,v 1.33 2015/07/03 03:43:18 djm Exp $ */ #include "includes.h" +#include /* MIN */ #include -#include #include #include @@ -30,12 +30,14 @@ #include #include -#include "buffer.h" -#include "key.h" +#include "sshbuf.h" +#include "ssherr.h" +#include "sshkey.h" #include "authfile.h" #include "misc.h" #include "log.h" -#include "xmalloc.h" +#include "digest.h" +#include "bitmap.h" #include "krl.h" @@ -72,7 +74,7 @@ RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp); /* Tree of blobs (used for keys and fingerprints) */ struct revoked_blob { u_char *blob; - u_int len; + size_t len; RB_ENTRY(revoked_blob) tree_entry; }; static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b); @@ -81,7 +83,7 @@ RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp); /* Tracks revoked certs for a single CA */ struct revoked_certs { - Key *ca_key; + struct sshkey *ca_key; struct revoked_serial_tree revoked_serials; struct revoked_key_id_tree revoked_key_ids; TAILQ_ENTRY(revoked_certs) entry; @@ -154,8 +156,7 @@ revoked_certs_free(struct revoked_certs *rc) free(rki->key_id); free(rki); } - if (rc->ca_key != NULL) - key_free(rc->ca_key); + sshkey_free(rc->ca_key); } void @@ -190,12 +191,13 @@ ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version) krl->krl_version = version; } -void +int ssh_krl_set_comment(struct ssh_krl *krl, const char *comment) { free(krl->comment); if ((krl->comment = strdup(comment)) == NULL) - fatal("%s: strdup", __func__); + return SSH_ERR_ALLOC_FAIL; + return 0; } /* @@ -203,14 +205,16 @@ ssh_krl_set_comment(struct ssh_krl *krl, const char *comment) * create a new one in the tree if one did not exist already. */ static int -revoked_certs_for_ca_key(struct ssh_krl *krl, const Key *ca_key, +revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key, struct revoked_certs **rcp, int allow_create) { struct revoked_certs *rc; + int r; *rcp = NULL; TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { - if (key_equal(rc->ca_key, ca_key)) { + if ((ca_key == NULL && rc->ca_key == NULL) || + sshkey_equal(rc->ca_key, ca_key)) { *rcp = rc; return 0; } @@ -219,15 +223,18 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const Key *ca_key, return 0; /* If this CA doesn't exist in the list then add it now */ if ((rc = calloc(1, sizeof(*rc))) == NULL) - return -1; - if ((rc->ca_key = key_from_private(ca_key)) == NULL) { + return SSH_ERR_ALLOC_FAIL; + if (ca_key == NULL) + rc->ca_key = NULL; + else if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) { free(rc); - return -1; + return r; } RB_INIT(&rc->revoked_serials); RB_INIT(&rc->revoked_key_ids); TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry); - debug3("%s: new CA %s", __func__, key_type(ca_key)); + KRL_DBG(("%s: new CA %s", __func__, + ca_key == NULL ? "*" : sshkey_type(ca_key))); *rcp = rc; return 0; } @@ -245,14 +252,14 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) if (ers == NULL || serial_cmp(ers, &rs) != 0) { /* No entry matches. Just insert */ if ((irs = malloc(sizeof(rs))) == NULL) - return -1; + return SSH_ERR_ALLOC_FAIL; memcpy(irs, &rs, sizeof(*irs)); ers = RB_INSERT(revoked_serial_tree, rt, irs); if (ers != NULL) { KRL_DBG(("%s: bad: ers != NULL", __func__)); /* Shouldn't happen */ free(irs); - return -1; + return SSH_ERR_INTERNAL_ERROR; } ers = irs; } else { @@ -267,6 +274,7 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) if (ers->hi < hi) ers->hi = hi; } + /* * The inserted or revised range might overlap or abut adjacent ones; * coalesce as necessary. @@ -305,40 +313,42 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) } int -ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key, +ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const struct sshkey *ca_key, u_int64_t serial) { return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial); } int -ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key, - u_int64_t lo, u_int64_t hi) +ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, + const struct sshkey *ca_key, u_int64_t lo, u_int64_t hi) { struct revoked_certs *rc; + int r; if (lo > hi || lo == 0) - return -1; - if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0) - return -1; + return SSH_ERR_INVALID_ARGUMENT; + if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0) + return r; return insert_serial_range(&rc->revoked_serials, lo, hi); } int -ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key, +ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const struct sshkey *ca_key, const char *key_id) { struct revoked_key_id *rki, *erki; struct revoked_certs *rc; + int r; - if (revoked_certs_for_ca_key(krl, ca_key, &rc, 1) != 0) - return -1; + if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0) + return r; - debug3("%s: revoke %s", __func__, key_id); + KRL_DBG(("%s: revoke %s", __func__, key_id)); if ((rki = calloc(1, sizeof(*rki))) == NULL || (rki->key_id = strdup(key_id)) == NULL) { free(rki); - fatal("%s: strdup", __func__); + return SSH_ERR_ALLOC_FAIL; } erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki); if (erki != NULL) { @@ -350,33 +360,32 @@ ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key, /* Convert "key" to a public key blob without any certificate information */ static int -plain_key_blob(const Key *key, u_char **blob, u_int *blen) +plain_key_blob(const struct sshkey *key, u_char **blob, size_t *blen) { - Key *kcopy; + struct sshkey *kcopy; int r; - if ((kcopy = key_from_private(key)) == NULL) - return -1; - if (key_is_cert(kcopy)) { - if (key_drop_cert(kcopy) != 0) { - error("%s: key_drop_cert", __func__); - key_free(kcopy); - return -1; + if ((r = sshkey_from_private(key, &kcopy)) != 0) + return r; + if (sshkey_is_cert(kcopy)) { + if ((r = sshkey_drop_cert(kcopy)) != 0) { + sshkey_free(kcopy); + return r; } } - r = key_to_blob(kcopy, blob, blen); - free(kcopy); - return r == 0 ? -1 : 0; + r = sshkey_to_blob(kcopy, blob, blen); + sshkey_free(kcopy); + return r; } /* Revoke a key blob. Ownership of blob is transferred to the tree */ static int -revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, u_int len) +revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, size_t len) { struct revoked_blob *rb, *erb; if ((rb = calloc(1, sizeof(*rb))) == NULL) - return -1; + return SSH_ERR_ALLOC_FAIL; rb->blob = blob; rb->len = len; erb = RB_INSERT(revoked_blob_tree, rbt, rb); @@ -388,36 +397,39 @@ revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, u_int len) } int -ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key) +ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key) { u_char *blob; - u_int len; + size_t len; + int r; - debug3("%s: revoke type %s", __func__, key_type(key)); - if (plain_key_blob(key, &blob, &len) != 0) - return -1; + debug3("%s: revoke type %s", __func__, sshkey_type(key)); + if ((r = plain_key_blob(key, &blob, &len)) != 0) + return r; return revoke_blob(&krl->revoked_keys, blob, len); } int -ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key) +ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key) { u_char *blob; - u_int len; + size_t len; + int r; - debug3("%s: revoke type %s by sha1", __func__, key_type(key)); - if ((blob = key_fingerprint_raw(key, SSH_FP_SHA1, &len)) == NULL) - return -1; + debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key)); + if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1, + &blob, &len)) != 0) + return r; return revoke_blob(&krl->revoked_sha1s, blob, len); } int -ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key) +ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key) { - if (!key_is_cert(key)) + if (!sshkey_is_cert(key)) return ssh_krl_revoke_key_sha1(krl, key); - if (key_cert_is_legacy(key) || key->cert->serial == 0) { + if (key->cert->serial == 0) { return ssh_krl_revoke_cert_by_key_id(krl, key->cert->signature_key, key->cert->key_id); @@ -429,8 +441,8 @@ ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key) } /* - * Select a copact next section type to emit in a KRL based on the - * current section type, the run length of contiguous revoked serial + * Select the most compact section type to emit next in a KRL based on + * the current section type, the run length of contiguous revoked serial * numbers and the gaps from the last and to the next revoked serial. * Applies a mostly-accurate bit cost model to select the section type * that will minimise the size of the resultant KRL. @@ -500,50 +512,69 @@ choose_next_state(int current_state, u_int64_t contig, int final, *force_new_section = 1; cost = cost_bitmap_restart; } - debug3("%s: contig %llu last_gap %llu next_gap %llu final %d, costs:" + KRL_DBG(("%s: contig %llu last_gap %llu next_gap %llu final %d, costs:" "list %llu range %llu bitmap %llu new bitmap %llu, " "selected 0x%02x%s", __func__, (long long unsigned)contig, (long long unsigned)last_gap, (long long unsigned)next_gap, final, (long long unsigned)cost_list, (long long unsigned)cost_range, (long long unsigned)cost_bitmap, (long long unsigned)cost_bitmap_restart, new_state, - *force_new_section ? " restart" : ""); + *force_new_section ? " restart" : "")); return new_state; } +static int +put_bitmap(struct sshbuf *buf, struct bitmap *bitmap) +{ + size_t len; + u_char *blob; + int r; + + len = bitmap_nbytes(bitmap); + if ((blob = malloc(len)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (bitmap_to_string(bitmap, blob, len) != 0) { + free(blob); + return SSH_ERR_INTERNAL_ERROR; + } + r = sshbuf_put_bignum2_bytes(buf, blob, len); + free(blob); + return r; +} + /* Generate a KRL_SECTION_CERTIFICATES KRL section */ static int -revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) +revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) { - int final, force_new_sect, r = -1; + int final, force_new_sect, r = SSH_ERR_INTERNAL_ERROR; u_int64_t i, contig, gap, last = 0, bitmap_start = 0; struct revoked_serial *rs, *nrs; struct revoked_key_id *rki; int next_state, state = 0; - Buffer sect; - u_char *kblob = NULL; - u_int klen; - BIGNUM *bitmap = NULL; - - /* Prepare CA scope key blob if we have one supplied */ - if (key_to_blob(rc->ca_key, &kblob, &klen) == 0) - return -1; + struct sshbuf *sect; + struct bitmap *bitmap = NULL; - buffer_init(§); + if ((sect = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; - /* Store the header */ - buffer_put_string(buf, kblob, klen); - buffer_put_string(buf, NULL, 0); /* Reserved */ - - free(kblob); + /* Store the header: optional CA scope key, reserved */ + if (rc->ca_key == NULL) { + if ((r = sshbuf_put_string(buf, NULL, 0)) != 0) + goto out; + } else { + if ((r = sshkey_puts(rc->ca_key, buf)) != 0) + goto out; + } + if ((r = sshbuf_put_string(buf, NULL, 0)) != 0) + goto out; /* Store the revoked serials. */ for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials); rs != NULL; rs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs)) { - debug3("%s: serial %llu:%llu state 0x%02x", __func__, + KRL_DBG(("%s: serial %llu:%llu state 0x%02x", __func__, (long long unsigned)rs->lo, (long long unsigned)rs->hi, - state); + state)); /* Check contiguous length and gap to next section (if any) */ nrs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs); @@ -561,36 +592,43 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) */ if (state != 0 && (force_new_sect || next_state != state || state == KRL_SECTION_CERT_SERIAL_RANGE)) { - debug3("%s: finish state 0x%02x", __func__, state); + KRL_DBG(("%s: finish state 0x%02x", __func__, state)); switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: case KRL_SECTION_CERT_SERIAL_RANGE: break; case KRL_SECTION_CERT_SERIAL_BITMAP: - buffer_put_bignum2(§, bitmap); - BN_free(bitmap); + if ((r = put_bitmap(sect, bitmap)) != 0) + goto out; + bitmap_free(bitmap); bitmap = NULL; break; } - buffer_put_char(buf, state); - buffer_put_string(buf, - buffer_ptr(§), buffer_len(§)); + if ((r = sshbuf_put_u8(buf, state)) != 0 || + (r = sshbuf_put_stringb(buf, sect)) != 0) + goto out; + sshbuf_reset(sect); } /* If we are starting a new section then prepare it now */ if (next_state != state || force_new_sect) { - debug3("%s: start state 0x%02x", __func__, next_state); + KRL_DBG(("%s: start state 0x%02x", __func__, + next_state)); state = next_state; - buffer_clear(§); + sshbuf_reset(sect); switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: case KRL_SECTION_CERT_SERIAL_RANGE: break; case KRL_SECTION_CERT_SERIAL_BITMAP: - if ((bitmap = BN_new()) == NULL) + if ((bitmap = bitmap_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; goto out; + } bitmap_start = rs->lo; - buffer_put_int64(§, bitmap_start); + if ((r = sshbuf_put_u64(sect, + bitmap_start)) != 0) + goto out; break; } } @@ -598,12 +636,15 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) /* Perform section-specific processing */ switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: - for (i = 0; i < contig; i++) - buffer_put_int64(§, rs->lo + i); + for (i = 0; i < contig; i++) { + if ((r = sshbuf_put_u64(sect, rs->lo + i)) != 0) + goto out; + } break; case KRL_SECTION_CERT_SERIAL_RANGE: - buffer_put_int64(§, rs->lo); - buffer_put_int64(§, rs->hi); + if ((r = sshbuf_put_u64(sect, rs->lo)) != 0 || + (r = sshbuf_put_u64(sect, rs->hi)) != 0) + goto out; break; case KRL_SECTION_CERT_SERIAL_BITMAP: if (rs->lo - bitmap_start > INT_MAX) { @@ -611,9 +652,11 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) goto out; } for (i = 0; i < contig; i++) { - if (BN_set_bit(bitmap, - rs->lo + i - bitmap_start) != 1) + if (bitmap_set_bit(bitmap, + rs->lo + i - bitmap_start) != 0) { + r = SSH_ERR_ALLOC_FAIL; goto out; + } } break; } @@ -621,119 +664,125 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf) } /* Flush the remaining section, if any */ if (state != 0) { - debug3("%s: serial final flush for state 0x%02x", - __func__, state); + KRL_DBG(("%s: serial final flush for state 0x%02x", + __func__, state)); switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: case KRL_SECTION_CERT_SERIAL_RANGE: break; case KRL_SECTION_CERT_SERIAL_BITMAP: - buffer_put_bignum2(§, bitmap); - BN_free(bitmap); + if ((r = put_bitmap(sect, bitmap)) != 0) + goto out; + bitmap_free(bitmap); bitmap = NULL; break; } - buffer_put_char(buf, state); - buffer_put_string(buf, - buffer_ptr(§), buffer_len(§)); + if ((r = sshbuf_put_u8(buf, state)) != 0 || + (r = sshbuf_put_stringb(buf, sect)) != 0) + goto out; } - debug3("%s: serial done ", __func__); + KRL_DBG(("%s: serial done ", __func__)); /* Now output a section for any revocations by key ID */ - buffer_clear(§); + sshbuf_reset(sect); RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) { - debug3("%s: key ID %s", __func__, rki->key_id); - buffer_put_cstring(§, rki->key_id); + KRL_DBG(("%s: key ID %s", __func__, rki->key_id)); + if ((r = sshbuf_put_cstring(sect, rki->key_id)) != 0) + goto out; } - if (buffer_len(§) != 0) { - buffer_put_char(buf, KRL_SECTION_CERT_KEY_ID); - buffer_put_string(buf, buffer_ptr(§), - buffer_len(§)); + if (sshbuf_len(sect) != 0) { + if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERT_KEY_ID)) != 0 || + (r = sshbuf_put_stringb(buf, sect)) != 0) + goto out; } r = 0; out: - if (bitmap != NULL) - BN_free(bitmap); - buffer_free(§); + bitmap_free(bitmap); + sshbuf_free(sect); return r; } int -ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys, - u_int nsign_keys) +ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, + const struct sshkey **sign_keys, u_int nsign_keys) { - int r = -1; + int r = SSH_ERR_INTERNAL_ERROR; struct revoked_certs *rc; struct revoked_blob *rb; - Buffer sect; - u_char *kblob = NULL, *sblob = NULL; - u_int klen, slen, i; + struct sshbuf *sect; + u_char *sblob = NULL; + size_t slen, i; if (krl->generated_date == 0) krl->generated_date = time(NULL); - buffer_init(§); + if ((sect = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; /* Store the header */ - buffer_append(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1); - buffer_put_int(buf, KRL_FORMAT_VERSION); - buffer_put_int64(buf, krl->krl_version); - buffer_put_int64(buf, krl->generated_date); - buffer_put_int64(buf, krl->flags); - buffer_put_string(buf, NULL, 0); - buffer_put_cstring(buf, krl->comment ? krl->comment : ""); + if ((r = sshbuf_put(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1)) != 0 || + (r = sshbuf_put_u32(buf, KRL_FORMAT_VERSION)) != 0 || + (r = sshbuf_put_u64(buf, krl->krl_version)) != 0 || + (r = sshbuf_put_u64(buf, krl->generated_date) != 0) || + (r = sshbuf_put_u64(buf, krl->flags)) != 0 || + (r = sshbuf_put_string(buf, NULL, 0)) != 0 || + (r = sshbuf_put_cstring(buf, krl->comment)) != 0) + goto out; /* Store sections for revoked certificates */ TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { - if (revoked_certs_generate(rc, §) != 0) + sshbuf_reset(sect); + if ((r = revoked_certs_generate(rc, sect)) != 0) + goto out; + if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERTIFICATES)) != 0 || + (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; - buffer_put_char(buf, KRL_SECTION_CERTIFICATES); - buffer_put_string(buf, buffer_ptr(§), - buffer_len(§)); } /* Finally, output sections for revocations by public key/hash */ - buffer_clear(§); + sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { - debug3("%s: key len %u ", __func__, rb->len); - buffer_put_string(§, rb->blob, rb->len); + KRL_DBG(("%s: key len %zu ", __func__, rb->len)); + if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0) + goto out; } - if (buffer_len(§) != 0) { - buffer_put_char(buf, KRL_SECTION_EXPLICIT_KEY); - buffer_put_string(buf, buffer_ptr(§), - buffer_len(§)); + if (sshbuf_len(sect) != 0) { + if ((r = sshbuf_put_u8(buf, KRL_SECTION_EXPLICIT_KEY)) != 0 || + (r = sshbuf_put_stringb(buf, sect)) != 0) + goto out; } - buffer_clear(§); + sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) { - debug3("%s: hash len %u ", __func__, rb->len); - buffer_put_string(§, rb->blob, rb->len); + KRL_DBG(("%s: hash len %zu ", __func__, rb->len)); + if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0) + goto out; } - if (buffer_len(§) != 0) { - buffer_put_char(buf, KRL_SECTION_FINGERPRINT_SHA1); - buffer_put_string(buf, buffer_ptr(§), - buffer_len(§)); + if (sshbuf_len(sect) != 0) { + if ((r = sshbuf_put_u8(buf, + KRL_SECTION_FINGERPRINT_SHA1)) != 0 || + (r = sshbuf_put_stringb(buf, sect)) != 0) + goto out; } for (i = 0; i < nsign_keys; i++) { - if (key_to_blob(sign_keys[i], &kblob, &klen) == 0) + KRL_DBG(("%s: signature key %s", __func__, + sshkey_ssh_name(sign_keys[i]))); + if ((r = sshbuf_put_u8(buf, KRL_SECTION_SIGNATURE)) != 0 || + (r = sshkey_puts(sign_keys[i], buf)) != 0) goto out; - debug3("%s: signature key len %u", __func__, klen); - buffer_put_char(buf, KRL_SECTION_SIGNATURE); - buffer_put_string(buf, kblob, klen); - - if (key_sign(sign_keys[i], &sblob, &slen, - buffer_ptr(buf), buffer_len(buf)) == -1) + if ((r = sshkey_sign(sign_keys[i], &sblob, &slen, + sshbuf_ptr(buf), sshbuf_len(buf), 0)) != 0) + goto out; + KRL_DBG(("%s: signature sig len %zu", __func__, slen)); + if ((r = sshbuf_put_string(buf, sblob, slen)) != 0) goto out; - debug3("%s: signature sig len %u", __func__, slen); - buffer_put_string(buf, sblob, slen); } r = 0; out: - free(kblob); free(sblob); - buffer_free(§); + sshbuf_free(sect); return r; } @@ -745,192 +794,178 @@ format_timestamp(u_int64_t timestamp, char *ts, size_t nts) t = timestamp; tm = localtime(&t); - *ts = '\0'; - strftime(ts, nts, "%Y%m%dT%H%M%S", tm); + if (tm == NULL) + strlcpy(ts, "", nts); + else { + *ts = '\0'; + strftime(ts, nts, "%Y%m%dT%H%M%S", tm); + } } static int -parse_revoked_certs(Buffer *buf, struct ssh_krl *krl) +parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl) { - int ret = -1, nbits; - u_char type, *blob; - u_int blen; - Buffer subsect; + int r = SSH_ERR_INTERNAL_ERROR; + u_char type; + const u_char *blob; + size_t blen, nbits; + struct sshbuf *subsect = NULL; u_int64_t serial, serial_lo, serial_hi; - BIGNUM *bitmap = NULL; + struct bitmap *bitmap = NULL; char *key_id = NULL; - Key *ca_key = NULL; + struct sshkey *ca_key = NULL; - buffer_init(&subsect); + if ((subsect = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; - if ((blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL || - buffer_get_string_ptr_ret(buf, NULL) == NULL) { /* reserved */ - error("%s: buffer error", __func__); + /* Header: key, reserved */ + if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 || + (r = sshbuf_skip_string(buf)) != 0) goto out; - } - if ((ca_key = key_from_blob(blob, blen)) == NULL) + if (blen != 0 && (r = sshkey_from_blob(blob, blen, &ca_key)) != 0) goto out; - while (buffer_len(buf) > 0) { - if (buffer_get_char_ret(&type, buf) != 0 || - (blob = buffer_get_string_ptr_ret(buf, &blen)) == NULL) { - error("%s: buffer error", __func__); - goto out; + while (sshbuf_len(buf) > 0) { + if (subsect != NULL) { + sshbuf_free(subsect); + subsect = NULL; } - buffer_clear(&subsect); - buffer_append(&subsect, blob, blen); - debug3("%s: subsection type 0x%02x", __func__, type); - /* buffer_dump(&subsect); */ + if ((r = sshbuf_get_u8(buf, &type)) != 0 || + (r = sshbuf_froms(buf, &subsect)) != 0) + goto out; + KRL_DBG(("%s: subsection type 0x%02x", __func__, type)); + /* sshbuf_dump(subsect, stderr); */ switch (type) { case KRL_SECTION_CERT_SERIAL_LIST: - while (buffer_len(&subsect) > 0) { - if (buffer_get_int64_ret(&serial, - &subsect) != 0) { - error("%s: buffer error", __func__); + while (sshbuf_len(subsect) > 0) { + if ((r = sshbuf_get_u64(subsect, &serial)) != 0) goto out; - } - if (ssh_krl_revoke_cert_by_serial(krl, ca_key, - serial) != 0) { - error("%s: update failed", __func__); + if ((r = ssh_krl_revoke_cert_by_serial(krl, + ca_key, serial)) != 0) goto out; - } } break; case KRL_SECTION_CERT_SERIAL_RANGE: - if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 || - buffer_get_int64_ret(&serial_hi, &subsect) != 0) { - error("%s: buffer error", __func__); + if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 || + (r = sshbuf_get_u64(subsect, &serial_hi)) != 0) goto out; - } - if (ssh_krl_revoke_cert_by_serial_range(krl, ca_key, - serial_lo, serial_hi) != 0) { - error("%s: update failed", __func__); + if ((r = ssh_krl_revoke_cert_by_serial_range(krl, + ca_key, serial_lo, serial_hi)) != 0) goto out; - } break; case KRL_SECTION_CERT_SERIAL_BITMAP: - if ((bitmap = BN_new()) == NULL) { - error("%s: BN_new", __func__); + if ((bitmap = bitmap_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; goto out; } - if (buffer_get_int64_ret(&serial_lo, &subsect) != 0 || - buffer_get_bignum2_ret(&subsect, bitmap) != 0) { - error("%s: buffer error", __func__); + if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 || + (r = sshbuf_get_bignum2_bytes_direct(subsect, + &blob, &blen)) != 0) goto out; - } - if ((nbits = BN_num_bits(bitmap)) < 0) { - error("%s: bitmap bits < 0", __func__); + if (bitmap_from_string(bitmap, blob, blen) != 0) { + r = SSH_ERR_INVALID_FORMAT; goto out; } - for (serial = 0; serial < (u_int)nbits; serial++) { + nbits = bitmap_nbits(bitmap); + for (serial = 0; serial < (u_int64_t)nbits; serial++) { if (serial > 0 && serial_lo + serial == 0) { error("%s: bitmap wraps u64", __func__); + r = SSH_ERR_INVALID_FORMAT; goto out; } - if (!BN_is_bit_set(bitmap, serial)) + if (!bitmap_test_bit(bitmap, serial)) continue; - if (ssh_krl_revoke_cert_by_serial(krl, ca_key, - serial_lo + serial) != 0) { - error("%s: update failed", __func__); + if ((r = ssh_krl_revoke_cert_by_serial(krl, + ca_key, serial_lo + serial)) != 0) goto out; - } } - BN_free(bitmap); + bitmap_free(bitmap); bitmap = NULL; break; case KRL_SECTION_CERT_KEY_ID: - while (buffer_len(&subsect) > 0) { - if ((key_id = buffer_get_cstring_ret(&subsect, - NULL)) == NULL) { - error("%s: buffer error", __func__); + while (sshbuf_len(subsect) > 0) { + if ((r = sshbuf_get_cstring(subsect, + &key_id, NULL)) != 0) goto out; - } - if (ssh_krl_revoke_cert_by_key_id(krl, ca_key, - key_id) != 0) { - error("%s: update failed", __func__); + if ((r = ssh_krl_revoke_cert_by_key_id(krl, + ca_key, key_id)) != 0) goto out; - } free(key_id); key_id = NULL; } break; default: error("Unsupported KRL certificate section %u", type); + r = SSH_ERR_INVALID_FORMAT; goto out; } - if (buffer_len(&subsect) > 0) { + if (sshbuf_len(subsect) > 0) { error("KRL certificate section contains unparsed data"); + r = SSH_ERR_INVALID_FORMAT; goto out; } } - ret = 0; + r = 0; out: - if (ca_key != NULL) - key_free(ca_key); if (bitmap != NULL) - BN_free(bitmap); + bitmap_free(bitmap); free(key_id); - buffer_free(&subsect); - return ret; + sshkey_free(ca_key); + sshbuf_free(subsect); + return r; } /* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */ int -ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, - const Key **sign_ca_keys, u_int nsign_ca_keys) +ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, + const struct sshkey **sign_ca_keys, size_t nsign_ca_keys) { - Buffer copy, sect; - struct ssh_krl *krl; + struct sshbuf *copy = NULL, *sect = NULL; + struct ssh_krl *krl = NULL; char timestamp[64]; - int ret = -1, r, sig_seen; - Key *key = NULL, **ca_used = NULL; - u_char type, *blob, *rdata = NULL; - u_int i, j, sig_off, sects_off, rlen, blen, format_version, nca_used; + int r = SSH_ERR_INTERNAL_ERROR, sig_seen; + struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used; + u_char type, *rdata = NULL; + const u_char *blob; + size_t i, j, sig_off, sects_off, rlen, blen, nca_used; + u_int format_version; nca_used = 0; *krlp = NULL; - if (buffer_len(buf) < sizeof(KRL_MAGIC) - 1 || - memcmp(buffer_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) { + if (sshbuf_len(buf) < sizeof(KRL_MAGIC) - 1 || + memcmp(sshbuf_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) { debug3("%s: not a KRL", __func__); - /* - * Return success but a NULL *krlp here to signal that the - * file might be a simple list of keys. - */ - return 0; + return SSH_ERR_KRL_BAD_MAGIC; } /* Take a copy of the KRL buffer so we can verify its signature later */ - buffer_init(©); - buffer_append(©, buffer_ptr(buf), buffer_len(buf)); - - buffer_init(§); - buffer_consume(©, sizeof(KRL_MAGIC) - 1); + if ((copy = sshbuf_fromb(buf)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_consume(copy, sizeof(KRL_MAGIC) - 1)) != 0) + goto out; if ((krl = ssh_krl_init()) == NULL) { error("%s: alloc failed", __func__); goto out; } - if (buffer_get_int_ret(&format_version, ©) != 0) { - error("%s: KRL truncated", __func__); + if ((r = sshbuf_get_u32(copy, &format_version)) != 0) goto out; - } if (format_version != KRL_FORMAT_VERSION) { - error("%s: KRL unsupported format version %u", - __func__, format_version); + r = SSH_ERR_INVALID_FORMAT; goto out; } - if (buffer_get_int64_ret(&krl->krl_version, ©) != 0 || - buffer_get_int64_ret(&krl->generated_date, ©) != 0 || - buffer_get_int64_ret(&krl->flags, ©) != 0 || - buffer_get_string_ptr_ret(©, NULL) == NULL || /* reserved */ - (krl->comment = buffer_get_cstring_ret(©, NULL)) == NULL) { - error("%s: buffer error", __func__); + if ((r = sshbuf_get_u64(copy, &krl->krl_version)) != 0 || + (r = sshbuf_get_u64(copy, &krl->generated_date)) != 0 || + (r = sshbuf_get_u64(copy, &krl->flags)) != 0 || + (r = sshbuf_skip_string(copy)) != 0 || + (r = sshbuf_get_cstring(copy, &krl->comment, NULL)) != 0) goto out; - } format_timestamp(krl->generated_date, timestamp, sizeof(timestamp)); debug("KRL version %llu generated at %s%s%s", @@ -942,18 +977,22 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, * detailed parsing of data whose provenance is unverified. */ sig_seen = 0; - sects_off = buffer_len(buf) - buffer_len(©); - while (buffer_len(©) > 0) { - if (buffer_get_char_ret(&type, ©) != 0 || - (blob = buffer_get_string_ptr_ret(©, &blen)) == NULL) { - error("%s: buffer error", __func__); + if (sshbuf_len(buf) < sshbuf_len(copy)) { + /* Shouldn't happen */ + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + sects_off = sshbuf_len(buf) - sshbuf_len(copy); + while (sshbuf_len(copy) > 0) { + if ((r = sshbuf_get_u8(copy, &type)) != 0 || + (r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0) goto out; - } - debug3("%s: first pass, section 0x%02x", __func__, type); + KRL_DBG(("%s: first pass, section 0x%02x", __func__, type)); if (type != KRL_SECTION_SIGNATURE) { if (sig_seen) { error("KRL contains non-signature section " "after signature"); + r = SSH_ERR_INVALID_FORMAT; goto out; } /* Not interested for now. */ @@ -961,94 +1000,114 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, } sig_seen = 1; /* First string component is the signing key */ - if ((key = key_from_blob(blob, blen)) == NULL) { - error("%s: invalid signature key", __func__); + if ((r = sshkey_from_blob(blob, blen, &key)) != 0) { + r = SSH_ERR_INVALID_FORMAT; goto out; } - sig_off = buffer_len(buf) - buffer_len(©); + if (sshbuf_len(buf) < sshbuf_len(copy)) { + /* Shouldn't happen */ + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + sig_off = sshbuf_len(buf) - sshbuf_len(copy); /* Second string component is the signature itself */ - if ((blob = buffer_get_string_ptr_ret(©, &blen)) == NULL) { - error("%s: buffer error", __func__); + if ((r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0) { + r = SSH_ERR_INVALID_FORMAT; goto out; } /* Check signature over entire KRL up to this point */ - if (key_verify(key, blob, blen, - buffer_ptr(buf), buffer_len(buf) - sig_off) != 1) { - error("bad signaure on KRL"); + if ((r = sshkey_verify(key, blob, blen, + sshbuf_ptr(buf), sshbuf_len(buf) - sig_off, 0)) != 0) goto out; - } /* Check if this key has already signed this KRL */ for (i = 0; i < nca_used; i++) { - if (key_equal(ca_used[i], key)) { + if (sshkey_equal(ca_used[i], key)) { error("KRL signed more than once with " "the same key"); + r = SSH_ERR_INVALID_FORMAT; goto out; } } /* Record keys used to sign the KRL */ - ca_used = xrealloc(ca_used, nca_used + 1, sizeof(*ca_used)); + tmp_ca_used = reallocarray(ca_used, nca_used + 1, + sizeof(*ca_used)); + if (tmp_ca_used == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + ca_used = tmp_ca_used; ca_used[nca_used++] = key; key = NULL; break; } + if (sshbuf_len(copy) != 0) { + /* Shouldn't happen */ + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + /* * 2nd pass: parse and load the KRL, skipping the header to the point * where the section start. */ - buffer_append(©, (u_char*)buffer_ptr(buf) + sects_off, - buffer_len(buf) - sects_off); - while (buffer_len(©) > 0) { - if (buffer_get_char_ret(&type, ©) != 0 || - (blob = buffer_get_string_ptr_ret(©, &blen)) == NULL) { - error("%s: buffer error", __func__); - goto out; + sshbuf_free(copy); + if ((copy = sshbuf_fromb(buf)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_consume(copy, sects_off)) != 0) + goto out; + while (sshbuf_len(copy) > 0) { + if (sect != NULL) { + sshbuf_free(sect); + sect = NULL; } - debug3("%s: second pass, section 0x%02x", __func__, type); - buffer_clear(§); - buffer_append(§, blob, blen); + if ((r = sshbuf_get_u8(copy, &type)) != 0 || + (r = sshbuf_froms(copy, §)) != 0) + goto out; + KRL_DBG(("%s: second pass, section 0x%02x", __func__, type)); switch (type) { case KRL_SECTION_CERTIFICATES: - if ((r = parse_revoked_certs(§, krl)) != 0) + if ((r = parse_revoked_certs(sect, krl)) != 0) goto out; break; case KRL_SECTION_EXPLICIT_KEY: case KRL_SECTION_FINGERPRINT_SHA1: - while (buffer_len(§) > 0) { - if ((rdata = buffer_get_string_ret(§, - &rlen)) == NULL) { - error("%s: buffer error", __func__); + while (sshbuf_len(sect) > 0) { + if ((r = sshbuf_get_string(sect, + &rdata, &rlen)) != 0) goto out; - } if (type == KRL_SECTION_FINGERPRINT_SHA1 && rlen != 20) { error("%s: bad SHA1 length", __func__); + r = SSH_ERR_INVALID_FORMAT; goto out; } - if (revoke_blob( + if ((r = revoke_blob( type == KRL_SECTION_EXPLICIT_KEY ? &krl->revoked_keys : &krl->revoked_sha1s, - rdata, rlen) != 0) + rdata, rlen)) != 0) goto out; - rdata = NULL; /* revoke_blob frees blob */ + rdata = NULL; /* revoke_blob frees rdata */ } break; case KRL_SECTION_SIGNATURE: /* Handled above, but still need to stay in synch */ - buffer_clear(§); - if ((blob = buffer_get_string_ptr_ret(©, - &blen)) == NULL) { - error("%s: buffer error", __func__); + sshbuf_reset(sect); + sect = NULL; + if ((r = sshbuf_skip_string(copy)) != 0) goto out; - } break; default: error("Unsupported KRL section %u", type); + r = SSH_ERR_INVALID_FORMAT; goto out; } - if (buffer_len(§) > 0) { + if (sshbuf_len(sect) > 0) { error("KRL section contains unparsed data"); + r = SSH_ERR_INVALID_FORMAT; goto out; } } @@ -1059,12 +1118,13 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, if (ssh_krl_check_key(krl, ca_used[i]) == 0) sig_seen = 1; else { - key_free(ca_used[i]); + sshkey_free(ca_used[i]); ca_used[i] = NULL; } } if (nca_used && !sig_seen) { error("All keys used to sign KRL were revoked"); + r = SSH_ERR_KEY_REVOKED; goto out; } @@ -1075,163 +1135,169 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, for (j = 0; j < nca_used; j++) { if (ca_used[j] == NULL) continue; - if (key_equal(ca_used[j], sign_ca_keys[i])) { + if (sshkey_equal(ca_used[j], sign_ca_keys[i])) { sig_seen = 1; break; } } } if (!sig_seen) { + r = SSH_ERR_SIGNATURE_INVALID; error("KRL not signed with any trusted key"); goto out; } } *krlp = krl; - ret = 0; + r = 0; out: - if (ret != 0) + if (r != 0) ssh_krl_free(krl); - for (i = 0; i < nca_used; i++) { - if (ca_used[i] != NULL) - key_free(ca_used[i]); - } + for (i = 0; i < nca_used; i++) + sshkey_free(ca_used[i]); free(ca_used); free(rdata); - if (key != NULL) - key_free(key); - buffer_free(©); - buffer_free(§); - return ret; + sshkey_free(key); + sshbuf_free(copy); + sshbuf_free(sect); + return r; } -/* Checks whether a given key/cert is revoked. Does not check its CA */ +/* Checks certificate serial number and key ID revocation */ static int -is_key_revoked(struct ssh_krl *krl, const Key *key) +is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc) { - struct revoked_blob rb, *erb; struct revoked_serial rs, *ers; struct revoked_key_id rki, *erki; + + /* Check revocation by cert key ID */ + memset(&rki, 0, sizeof(rki)); + rki.key_id = key->cert->key_id; + erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki); + if (erki != NULL) { + KRL_DBG(("%s: revoked by key ID", __func__)); + return SSH_ERR_KEY_REVOKED; + } + + /* + * Zero serials numbers are ignored (it's the default when the + * CA doesn't specify one). + */ + if (key->cert->serial == 0) + return 0; + + memset(&rs, 0, sizeof(rs)); + rs.lo = rs.hi = key->cert->serial; + ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs); + if (ers != NULL) { + KRL_DBG(("%s: revoked serial %llu matched %llu:%llu", __func__, + key->cert->serial, ers->lo, ers->hi)); + return SSH_ERR_KEY_REVOKED; + } + return 0; +} + +/* Checks whether a given key/cert is revoked. Does not check its CA */ +static int +is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) +{ + struct revoked_blob rb, *erb; struct revoked_certs *rc; + int r; /* Check explicitly revoked hashes first */ memset(&rb, 0, sizeof(rb)); - if ((rb.blob = key_fingerprint_raw(key, SSH_FP_SHA1, &rb.len)) == NULL) - return -1; + if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1, + &rb.blob, &rb.len)) != 0) + return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); free(rb.blob); if (erb != NULL) { - debug("%s: revoked by key SHA1", __func__); - return -1; + KRL_DBG(("%s: revoked by key SHA1", __func__)); + return SSH_ERR_KEY_REVOKED; } /* Next, explicit keys */ memset(&rb, 0, sizeof(rb)); - if (plain_key_blob(key, &rb.blob, &rb.len) != 0) - return -1; + if ((r = plain_key_blob(key, &rb.blob, &rb.len)) != 0) + return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); free(rb.blob); if (erb != NULL) { - debug("%s: revoked by explicit key", __func__); - return -1; + KRL_DBG(("%s: revoked by explicit key", __func__)); + return SSH_ERR_KEY_REVOKED; } - if (!key_is_cert(key)) + if (!sshkey_is_cert(key)) return 0; - /* Check cert revocation */ - if (revoked_certs_for_ca_key(krl, key->cert->signature_key, - &rc, 0) != 0) - return -1; - if (rc == NULL) - return 0; /* No entry for this CA */ - - /* Check revocation by cert key ID */ - memset(&rki, 0, sizeof(rki)); - rki.key_id = key->cert->key_id; - erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki); - if (erki != NULL) { - debug("%s: revoked by key ID", __func__); - return -1; + /* Check cert revocation for the specified CA */ + if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key, + &rc, 0)) != 0) + return r; + if (rc != NULL) { + if ((r = is_cert_revoked(key, rc)) != 0) + return r; } - - /* - * Legacy cert formats lack serial numbers. Zero serials numbers - * are ignored (it's the default when the CA doesn't specify one). - */ - if (key_cert_is_legacy(key) || key->cert->serial == 0) - return 0; - - memset(&rs, 0, sizeof(rs)); - rs.lo = rs.hi = key->cert->serial; - ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs); - if (ers != NULL) { - KRL_DBG(("%s: %llu matched %llu:%llu", __func__, - key->cert->serial, ers->lo, ers->hi)); - debug("%s: revoked by serial", __func__); - return -1; + /* Check cert revocation for the wildcard CA */ + if ((r = revoked_certs_for_ca_key(krl, NULL, &rc, 0)) != 0) + return r; + if (rc != NULL) { + if ((r = is_cert_revoked(key, rc)) != 0) + return r; } - KRL_DBG(("%s: %llu no match", __func__, key->cert->serial)); + KRL_DBG(("%s: %llu no match", __func__, key->cert->serial)); return 0; } int -ssh_krl_check_key(struct ssh_krl *krl, const Key *key) +ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key) { int r; - debug2("%s: checking key", __func__); + KRL_DBG(("%s: checking key", __func__)); if ((r = is_key_revoked(krl, key)) != 0) return r; - if (key_is_cert(key)) { + if (sshkey_is_cert(key)) { debug2("%s: checking CA key", __func__); if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0) return r; } - debug3("%s: key okay", __func__); + KRL_DBG(("%s: key okay", __func__)); return 0; } -/* Returns 0 on success, -1 on error or key revoked, -2 if path is not a KRL */ int -ssh_krl_file_contains_key(const char *path, const Key *key) +ssh_krl_file_contains_key(const char *path, const struct sshkey *key) { - Buffer krlbuf; - struct ssh_krl *krl; - int revoked, fd; + struct sshbuf *krlbuf = NULL; + struct ssh_krl *krl = NULL; + int oerrno = 0, r, fd; if (path == NULL) return 0; + if ((krlbuf = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; if ((fd = open(path, O_RDONLY)) == -1) { - error("open %s: %s", path, strerror(errno)); - error("Revoked keys file not accessible - refusing public key " - "authentication"); - return -1; - } - buffer_init(&krlbuf); - if (!key_load_file(fd, path, &krlbuf)) { - close(fd); - buffer_free(&krlbuf); - error("Revoked keys file not readable - refusing public key " - "authentication"); - return -1; - } - close(fd); - if (ssh_krl_from_blob(&krlbuf, &krl, NULL, 0) != 0) { - buffer_free(&krlbuf); - error("Invalid KRL, refusing public key " - "authentication"); - return -1; + r = SSH_ERR_SYSTEM_ERROR; + oerrno = errno; + goto out; } - buffer_free(&krlbuf); - if (krl == NULL) { - debug3("%s: %s is not a KRL file", __func__, path); - return -2; + if ((r = sshkey_load_file(fd, krlbuf)) != 0) { + oerrno = errno; + goto out; } + if ((r = ssh_krl_from_blob(krlbuf, &krl, NULL, 0)) != 0) + goto out; debug2("%s: checking KRL %s", __func__, path); - revoked = ssh_krl_check_key(krl, key) != 0; + r = ssh_krl_check_key(krl, key); + out: + close(fd); + sshbuf_free(krlbuf); ssh_krl_free(krl); - return revoked ? -1 : 0; + if (r != 0) + errno = oerrno; + return r; } diff --git a/crypto/openssh/krl.h b/crypto/openssh/krl.h index 2c43f5b..4e12bef 100644 --- a/crypto/openssh/krl.h +++ b/crypto/openssh/krl.h @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.h,v 1.2 2013/01/18 00:24:58 djm Exp $ */ +/* $OpenBSD: krl.h,v 1.4 2015/01/13 19:06:49 djm Exp $ */ #ifndef _KRL_H #define _KRL_H @@ -36,28 +36,30 @@ #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 #define KRL_SECTION_CERT_KEY_ID 0x23 +struct sshkey; +struct sshbuf; struct ssh_krl; struct ssh_krl *ssh_krl_init(void); void ssh_krl_free(struct ssh_krl *krl); void ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version); -void ssh_krl_set_sign_key(struct ssh_krl *krl, const Key *sign_key); -void ssh_krl_set_comment(struct ssh_krl *krl, const char *comment); -int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const Key *ca_key, - u_int64_t serial); -int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, const Key *ca_key, - u_int64_t lo, u_int64_t hi); -int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const Key *ca_key, - const char *key_id); -int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key); -int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const Key *key); -int ssh_krl_revoke_key(struct ssh_krl *krl, const Key *key); -int ssh_krl_to_blob(struct ssh_krl *krl, Buffer *buf, const Key **sign_keys, - u_int nsign_keys); -int ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp, - const Key **sign_ca_keys, u_int nsign_ca_keys); -int ssh_krl_check_key(struct ssh_krl *krl, const Key *key); -int ssh_krl_file_contains_key(const char *path, const Key *key); +void ssh_krl_set_sign_key(struct ssh_krl *krl, const struct sshkey *sign_key); +int ssh_krl_set_comment(struct ssh_krl *krl, const char *comment); +int ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, + const struct sshkey *ca_key, u_int64_t serial); +int ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl, + const struct sshkey *ca_key, u_int64_t lo, u_int64_t hi); +int ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, + const struct sshkey *ca_key, const char *key_id); +int ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key); +int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key); +int ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key); +int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, + const struct sshkey **sign_keys, u_int nsign_keys); +int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, + const struct sshkey **sign_ca_keys, size_t nsign_ca_keys); +int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key); +int ssh_krl_file_contains_key(const char *path, const struct sshkey *key); #endif /* _KRL_H */ diff --git a/crypto/openssh/log.c b/crypto/openssh/log.c index 32e1d2e..ad12930 100644 --- a/crypto/openssh/log.c +++ b/crypto/openssh/log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.45 2013/05/16 09:08:41 dtucker Exp $ */ +/* $OpenBSD: log.c,v 1.46 2015/07/08 19:04:21 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -50,7 +50,6 @@ # include #endif -#include "xmalloc.h" #include "log.h" static LogLevel log_level = SYSLOG_LEVEL_INFO; diff --git a/crypto/openssh/loginrec.c b/crypto/openssh/loginrec.c index 4219b9a..94ae81d 100644 --- a/crypto/openssh/loginrec.c +++ b/crypto/openssh/loginrec.c @@ -787,12 +787,12 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx) /* this is just a 128-bit IPv6 address */ if (li->hostaddr.sa.sa_family == AF_INET6) { sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa); - memcpy(ut->ut_addr_v6, sa6->sin6_addr.s6_addr, 16); + memcpy(utx->ut_addr_v6, sa6->sin6_addr.s6_addr, 16); if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { - ut->ut_addr_v6[0] = ut->ut_addr_v6[3]; - ut->ut_addr_v6[1] = 0; - ut->ut_addr_v6[2] = 0; - ut->ut_addr_v6[3] = 0; + utx->ut_addr_v6[0] = utx->ut_addr_v6[3]; + utx->ut_addr_v6[1] = 0; + utx->ut_addr_v6[2] = 0; + utx->ut_addr_v6[3] = 0; } } # endif diff --git a/crypto/openssh/mac.c b/crypto/openssh/mac.c index 0977572..f63fbff 100644 --- a/crypto/openssh/mac.c +++ b/crypto/openssh/mac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mac.c,v 1.28 2014/02/07 06:55:54 djm Exp $ */ +/* $OpenBSD: mac.c,v 1.32 2015/01/15 18:32:54 naddy Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -27,22 +27,16 @@ #include -#include #include -#include - -#include "xmalloc.h" -#include "log.h" -#include "cipher.h" -#include "buffer.h" -#include "key.h" -#include "kex.h" -#include "mac.h" -#include "misc.h" +#include #include "digest.h" #include "hmac.h" #include "umac.h" +#include "mac.h" +#include "misc.h" +#include "ssherr.h" +#include "sshbuf.h" #include "openbsd-compat/openssl-compat.h" @@ -95,7 +89,7 @@ static const struct macalg macs[] = { char * mac_alg_list(char sep) { - char *ret = NULL; + char *ret = NULL, *tmp; size_t nlen, rlen = 0; const struct macalg *m; @@ -103,20 +97,24 @@ mac_alg_list(char sep) if (ret != NULL) ret[rlen++] = sep; nlen = strlen(m->name); - ret = xrealloc(ret, 1, rlen + nlen + 2); + if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { + free(ret); + return NULL; + } + ret = tmp; memcpy(ret + rlen, m->name, nlen + 1); rlen += nlen; } return ret; } -static void -mac_setup_by_alg(Mac *mac, const struct macalg *macalg) +static int +mac_setup_by_alg(struct sshmac *mac, const struct macalg *macalg) { mac->type = macalg->type; if (mac->type == SSH_DIGEST) { if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL) - fatal("ssh_hmac_start(alg=%d) failed", macalg->alg); + return SSH_ERR_ALLOC_FAIL; mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg); } else { mac->mac_len = macalg->len / 8; @@ -126,60 +124,61 @@ mac_setup_by_alg(Mac *mac, const struct macalg *macalg) if (macalg->truncatebits != 0) mac->mac_len = macalg->truncatebits / 8; mac->etm = macalg->etm; + return 0; } int -mac_setup(Mac *mac, char *name) +mac_setup(struct sshmac *mac, char *name) { const struct macalg *m; for (m = macs; m->name != NULL; m++) { if (strcmp(name, m->name) != 0) continue; - if (mac != NULL) { - mac_setup_by_alg(mac, m); - debug2("mac_setup: setup %s", name); - } - return (0); + if (mac != NULL) + return mac_setup_by_alg(mac, m); + return 0; } - debug2("mac_setup: unknown %s", name); - return (-1); + return SSH_ERR_INVALID_ARGUMENT; } int -mac_init(Mac *mac) +mac_init(struct sshmac *mac) { if (mac->key == NULL) - fatal("%s: no key", __func__); + return SSH_ERR_INVALID_ARGUMENT; switch (mac->type) { case SSH_DIGEST: if (mac->hmac_ctx == NULL || ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0) - return -1; + return SSH_ERR_INVALID_ARGUMENT; return 0; case SSH_UMAC: - mac->umac_ctx = umac_new(mac->key); + if ((mac->umac_ctx = umac_new(mac->key)) == NULL) + return SSH_ERR_ALLOC_FAIL; return 0; case SSH_UMAC128: - mac->umac_ctx = umac128_new(mac->key); + if ((mac->umac_ctx = umac128_new(mac->key)) == NULL) + return SSH_ERR_ALLOC_FAIL; return 0; default: - return -1; + return SSH_ERR_INVALID_ARGUMENT; } } -u_char * -mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) +int +mac_compute(struct sshmac *mac, u_int32_t seqno, const u_char *data, int datalen, + u_char *digest, size_t dlen) { static union { - u_char m[EVP_MAX_MD_SIZE]; + u_char m[SSH_DIGEST_MAX_LENGTH]; u_int64_t for_align; } u; - u_char b[4], nonce[8]; + u_char b[4]; + u_char nonce[8]; if (mac->mac_len > sizeof(u)) - fatal("mac_compute: mac too long %u %zu", - mac->mac_len, sizeof(u)); + return SSH_ERR_INTERNAL_ERROR; switch (mac->type) { case SSH_DIGEST: @@ -189,10 +188,10 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 || ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 || ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0) - fatal("ssh_hmac failed"); + return SSH_ERR_LIBCRYPTO_ERROR; break; case SSH_UMAC: - put_u64(nonce, seqno); + POKE_U64(nonce, seqno); umac_update(mac->umac_ctx, data, datalen); umac_final(mac->umac_ctx, u.m, nonce); break; @@ -202,13 +201,18 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) umac128_final(mac->umac_ctx, u.m, nonce); break; default: - fatal("mac_compute: unknown MAC type"); + return SSH_ERR_INVALID_ARGUMENT; } - return (u.m); + if (digest != NULL) { + if (dlen > mac->mac_len) + dlen = mac->mac_len; + memcpy(digest, u.m, dlen); + } + return 0; } void -mac_clear(Mac *mac) +mac_clear(struct sshmac *mac) { if (mac->type == SSH_UMAC) { if (mac->umac_ctx != NULL) @@ -230,17 +234,16 @@ mac_valid(const char *names) char *maclist, *cp, *p; if (names == NULL || strcmp(names, "") == 0) - return (0); - maclist = cp = xstrdup(names); + return 0; + if ((maclist = cp = strdup(names)) == NULL) + return 0; for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0'; (p = strsep(&cp, MAC_SEP))) { if (mac_setup(NULL, p) < 0) { - debug("bad mac %s [%s]", p, names); free(maclist); - return (0); + return 0; } } - debug3("macs ok: [%s]", names); free(maclist); - return (1); + return 1; } diff --git a/crypto/openssh/mac.h b/crypto/openssh/mac.h index fbe18c4..e5f6b84 100644 --- a/crypto/openssh/mac.h +++ b/crypto/openssh/mac.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mac.h,v 1.8 2013/11/07 11:58:27 dtucker Exp $ */ +/* $OpenBSD: mac.h,v 1.9 2015/01/13 19:31:40 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -23,9 +23,29 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef SSHMAC_H +#define SSHMAC_H + +#include + +struct sshmac { + char *name; + int enabled; + u_int mac_len; + u_char *key; + u_int key_len; + int type; + int etm; /* Encrypt-then-MAC */ + struct ssh_hmac_ctx *hmac_ctx; + struct umac_ctx *umac_ctx; +}; + int mac_valid(const char *); char *mac_alg_list(char); -int mac_setup(Mac *, char *); -int mac_init(Mac *); -u_char *mac_compute(Mac *, u_int32_t, u_char *, int); -void mac_clear(Mac *); +int mac_setup(struct sshmac *, char *); +int mac_init(struct sshmac *); +int mac_compute(struct sshmac *, u_int32_t, const u_char *, int, + u_char *, size_t); +void mac_clear(struct sshmac *); + +#endif /* SSHMAC_H */ diff --git a/crypto/openssh/match.c b/crypto/openssh/match.c index c35e328..913b6ba 100644 --- a/crypto/openssh/match.c +++ b/crypto/openssh/match.c @@ -1,4 +1,4 @@ -/* $OpenBSD: match.c,v 1.29 2013/11/20 20:54:10 deraadt Exp $ */ +/* $OpenBSD: match.c,v 1.30 2015/05/04 06:10:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -115,15 +115,13 @@ match_pattern(const char *s, const char *pattern) * indicate negation). Returns -1 if negation matches, 1 if there is * a positive match, 0 if there is no match at all. */ - int -match_pattern_list(const char *string, const char *pattern, u_int len, - int dolower) +match_pattern_list(const char *string, const char *pattern, int dolower) { char sub[1024]; int negated; int got_positive; - u_int i, subi; + u_int i, subi, len = strlen(pattern); got_positive = 0; for (i = 0; i < len;) { @@ -177,9 +175,9 @@ match_pattern_list(const char *string, const char *pattern, u_int len, * a positive match, 0 if there is no match at all. */ int -match_hostname(const char *host, const char *pattern, u_int len) +match_hostname(const char *host, const char *pattern) { - return match_pattern_list(host, pattern, len, 1); + return match_pattern_list(host, pattern, 1); } /* @@ -200,7 +198,7 @@ match_host_and_ip(const char *host, const char *ipaddr, return 0; /* negative hostname match */ - if ((mhost = match_hostname(host, patterns, strlen(patterns))) == -1) + if ((mhost = match_hostname(host, patterns)) == -1) return 0; /* no match at all */ if (mhost == 0 && mip == 0) diff --git a/crypto/openssh/match.h b/crypto/openssh/match.h index 3d7f70f..db97ca8 100644 --- a/crypto/openssh/match.h +++ b/crypto/openssh/match.h @@ -1,4 +1,4 @@ -/* $OpenBSD: match.h,v 1.15 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: match.h,v 1.16 2015/05/04 06:10:48 djm Exp $ */ /* * Author: Tatu Ylonen @@ -15,8 +15,8 @@ #define MATCH_H int match_pattern(const char *, const char *); -int match_pattern_list(const char *, const char *, u_int, int); -int match_hostname(const char *, const char *, u_int); +int match_pattern_list(const char *, const char *, int); +int match_hostname(const char *, const char *); int match_host_and_ip(const char *, const char *, const char *); int match_user(const char *, const char *, const char *, const char *); char *match_list(const char *, const char *, u_int *); diff --git a/crypto/openssh/misc.c b/crypto/openssh/misc.c index e4c8c32..ddd2b2d 100644 --- a/crypto/openssh/misc.c +++ b/crypto/openssh/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.92 2013/10/14 23:28:23 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.97 2015/04/24 01:36:00 deraadt Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -29,8 +29,9 @@ #include #include #include -#include +#include +#include #include #include #include @@ -471,7 +472,7 @@ addargs(arglist *args, char *fmt, ...) } else if (args->num+2 >= nalloc) nalloc *= 2; - args->list = xrealloc(args->list, nalloc, sizeof(char *)); + args->list = xreallocarray(args->list, nalloc, sizeof(char *)); args->nalloc = nalloc; args->list[args->num++] = cp; args->list[args->num] = NULL; @@ -550,7 +551,7 @@ tilde_expand_filename(const char *filename, uid_t uid) if (path != NULL) filename = path + 1; - if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= MAXPATHLEN) + if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) fatal("tilde_expand_filename: Path too long"); return (ret); @@ -788,6 +789,20 @@ get_u32(const void *vp) return (v); } +u_int32_t +get_u32_le(const void *vp) +{ + const u_char *p = (const u_char *)vp; + u_int32_t v; + + v = (u_int32_t)p[0]; + v |= (u_int32_t)p[1] << 8; + v |= (u_int32_t)p[2] << 16; + v |= (u_int32_t)p[3] << 24; + + return (v); +} + u_int16_t get_u16(const void *vp) { @@ -826,6 +841,16 @@ put_u32(void *vp, u_int32_t v) p[3] = (u_char)v & 0xff; } +void +put_u32_le(void *vp, u_int32_t v) +{ + u_char *p = (u_char *)vp; + + p[0] = (u_char)v & 0xff; + p[1] = (u_char)(v >> 8) & 0xff; + p[2] = (u_char)(v >> 16) & 0xff; + p[3] = (u_char)(v >> 24) & 0xff; +} void put_u16(void *vp, u_int16_t v) @@ -858,17 +883,24 @@ ms_to_timeval(struct timeval *tv, int ms) time_t monotime(void) { -#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) +#if defined(HAVE_CLOCK_GETTIME) && \ + (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME)) struct timespec ts; static int gettime_failed = 0; if (!gettime_failed) { +#if defined(CLOCK_BOOTTIME) + if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) + return (ts.tv_sec); +#endif +#if defined(CLOCK_MONOTONIC) if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) return (ts.tv_sec); +#endif debug3("clock_gettime: %s", strerror(errno)); gettime_failed = 1; } -#endif +#endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */ return time(NULL); } @@ -1025,6 +1057,53 @@ lowercase(char *s) for (; *s; s++) *s = tolower((u_char)*s); } + +int +unix_listener(const char *path, int backlog, int unlink_first) +{ + struct sockaddr_un sunaddr; + int saved_errno, sock; + + memset(&sunaddr, 0, sizeof(sunaddr)); + sunaddr.sun_family = AF_UNIX; + if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { + error("%s: \"%s\" too long for Unix domain socket", __func__, + path); + errno = ENAMETOOLONG; + return -1; + } + + sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + saved_errno = errno; + error("socket: %.100s", strerror(errno)); + errno = saved_errno; + return -1; + } + if (unlink_first == 1) { + if (unlink(path) != 0 && errno != ENOENT) + error("unlink(%s): %.100s", path, strerror(errno)); + } + if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { + saved_errno = errno; + error("bind: %.100s", strerror(errno)); + close(sock); + error("%s: cannot bind to path: %s", __func__, path); + errno = saved_errno; + return -1; + } + if (listen(sock, backlog) < 0) { + saved_errno = errno; + error("listen: %.100s", strerror(errno)); + close(sock); + unlink(path); + error("%s: cannot listen on path: %s", __func__, path); + errno = saved_errno; + return -1; + } + return sock; +} + void sock_set_v6only(int s) { diff --git a/crypto/openssh/misc.h b/crypto/openssh/misc.h index d4df619..374c33c 100644 --- a/crypto/openssh/misc.h +++ b/crypto/openssh/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.50 2013/10/14 23:28:23 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.54 2014/07/15 15:54:14 millert Exp $ */ /* * Author: Tatu Ylonen @@ -15,6 +15,25 @@ #ifndef _MISC_H #define _MISC_H +/* Data structure for representing a forwarding request. */ +struct Forward { + char *listen_host; /* Host (address) to listen on. */ + int listen_port; /* Port to forward. */ + char *listen_path; /* Path to bind domain socket. */ + char *connect_host; /* Host to connect. */ + int connect_port; /* Port to connect on connect_host. */ + char *connect_path; /* Path to connect domain socket. */ + int allocated_port; /* Dynamically allocated listen port */ + int handle; /* Handle for dynamic listen ports */ +}; + +/* Common server and client forwarding options. */ +struct ForwardOptions { + int gateway_ports; /* Allow remote connects to forwarded ports. */ + mode_t streamlocal_bind_mask; /* umask for streamlocal binds */ + int streamlocal_bind_unlink; /* unlink socket before bind */ +}; + /* misc.c */ char *chop(char *); @@ -37,6 +56,7 @@ void ms_subtract_diff(struct timeval *, int *); void ms_to_timeval(struct timeval *, int); time_t monotime(void); void lowercase(char *s); +int unix_listener(const char *, int, int); void sock_set_v6only(int); @@ -68,6 +88,9 @@ int tun_open(int, int); #define SSH_TUNID_ERR (SSH_TUNID_ANY - 1) #define SSH_TUNID_MAX (SSH_TUNID_ANY - 2) +/* Fake port to indicate that host field is really a path. */ +#define PORT_STREAMLOCAL -2 + /* Functions to extract or store big-endian words of various sizes */ u_int64_t get_u64(const void *) __attribute__((__bounded__( __minbytes__, 1, 8))); @@ -82,6 +105,12 @@ void put_u32(void *, u_int32_t) void put_u16(void *, u_int16_t) __attribute__((__bounded__( __minbytes__, 1, 2))); +/* Little-endian store/load, used by umac.c */ +u_int32_t get_u32_le(const void *) + __attribute__((__bounded__(__minbytes__, 1, 4))); +void put_u32_le(void *, u_int32_t) + __attribute__((__bounded__(__minbytes__, 1, 4))); + struct bwlimit { size_t buflen; u_int64_t rate, thresh, lamt; diff --git a/crypto/openssh/moduli b/crypto/openssh/moduli index dff3c24..426a58f 100644 --- a/crypto/openssh/moduli +++ b/crypto/openssh/moduli @@ -1,276 +1,268 @@ -# $OpenBSD: moduli,v 1.12 2015/05/22 02:45:42 dtucker Exp $ +# $OpenBSD: moduli,v 1.14 2015/07/22 02:34:59 dtucker Exp $ # Time Type Tests Tries Size Generator Modulus -20150520233853 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA2AC62AF -20150520233854 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA2BCC50F -20150520233854 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA2C241F3 -20150520233855 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA2DDF347 -20150520233856 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA2E3FDBB -20150520233857 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3006603 -20150520233858 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA31D9C37 -20150520233859 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA333355B -20150520233900 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3428B23 -20150520233902 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA37C9A43 -20150520233903 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA384B367 -20150520233903 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3903453 -20150520233904 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3946C77 -20150520233904 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA39F6A9B -20150520233904 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3A0E88B -20150520233905 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3A37763 -20150520233906 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3BBDD57 -20150520233906 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3BDCDD7 -20150520233906 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3BF5D73 -20150520233907 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3C9BB83 -20150520233908 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3E5ADCF -20150520233909 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA3F82077 -20150520233910 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA406944F -20150520233910 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA40F7457 -20150520233912 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA438733B -20150520233913 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA44707FB -20150520233914 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA4588A2B -20150520233916 2 6 100 1023 2 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA48CC01B -20150520233917 2 6 100 1023 5 DB662973FB21C0B7BF21AB46AFD3E2002AE70C92DE6B9AEAFECF7B0A96D7ACB024B7C29DB18E70CB945FA54C7773519BC7161648AFE4939058AC40ECDBBD3636F5BF45863117E955007C9D0F9333BB4EF62F7C9F6298AB79A309C734F3CF201C61EBC3926ADD4E80968A65D9F60535164ACE7A7BFEDC1022002BB2BBA4960077 -20150520234251 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A740BE2123 -20150520234255 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A740D85877 -20150520234257 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A740E6494B -20150520234301 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A741120F9B -20150520234303 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7411EAC5B -20150520234304 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7412579DB -20150520234311 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74167053B -20150520234312 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74169B303 -20150520234318 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A741A3D69F -20150520234322 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A741C07E23 -20150520234330 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7420B48E3 -20150520234331 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74215059B -20150520234336 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74240BD03 -20150520234338 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7424D70BB -20150520234341 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7425C6CE3 -20150520234342 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74264FA9B -20150520234343 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7426BB34B -20150520234346 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74285D9E3 -20150520234347 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A742878293 -20150520234348 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74288D143 -20150520234356 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A742D55BF3 -20150520234401 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A742FC8227 -20150520234410 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7436032EB -20150520234411 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74361377F -20150520234415 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7437CCCFB -20150520234418 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A743902C1F -20150520234420 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7439EE5DB -20150520234422 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A743AE19BF -20150520234430 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7440152AB -20150520234432 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7440C2F63 -20150520234434 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7441FBDEB -20150520234436 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7442C98DF -20150520234437 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A744319703 -20150520234438 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A74433E927 -20150520234444 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A7446DF46F -20150520234450 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A744A3488B -20150520234455 2 6 100 1535 2 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A744CDAACB -20150520234459 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A744E9D8FF -20150520234504 2 6 100 1535 5 F8F4A446A6C7196643612A6C5CC26A47E491FB737740D68BBEBF0130F7AAADC59075781FB1723B644C0ADCE548C02E726DE5233C484FB4481F3EF3ED0585A0D687B2E0A6987AD2BC910754FC1A1E06B87710CFF0BC2E9868BA15BA20C103D3DCA6B65D8D0182B277F7CAE61D83A785BDD0B3CE471B4B8FAB224438D7A6772130167110AFD1FF584861996117F67B41CF3D2D5FAB020F2EB7F53E299AACF98797AEB6BAC3F0BB892DB4E4F8CDDE28C112C73EB556D0C381C6B9CC78A745196237 -20150520235007 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031E9A9C5F7 -20150520235015 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031E9CBB21F -20150520235039 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EA2E9623 -20150520235043 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EA33E3DF -20150520235057 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EA68038B -20150520235114 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EAAB0717 -20150520235122 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EAC2A7FB -20150520235125 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EAC82DD3 -20150520235154 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EB40583F -20150520235214 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EB94F247 -20150520235218 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EB9DF49F -20150520235239 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EBF7BE27 -20150520235244 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EC0B4F4F -20150520235250 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EC21070F -20150520235256 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EC36541F -20150520235307 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EC5FE22B -20150520235322 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031ECA1FB57 -20150520235331 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031ECC3C823 -20150520235349 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031ED035187 -20150520235400 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031ED2F07DB -20150520235407 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031ED4620CF -20150520235422 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031ED86D39F -20150520235424 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031ED86E683 -20150520235427 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031ED8C3073 -20150520235443 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EDCB1F63 -20150520235450 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EDE00B77 -20150520235452 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EDE42247 -20150520235458 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EDF8F493 -20150520235503 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EE04D69F -20150520235508 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EE14B92B -20150520235510 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EE167933 -20150520235517 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EE2DC63B -20150520235527 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EE52259F -20150520235539 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EE829247 -20150520235557 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EED044BF -20150520235608 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EEFD34CF -20150520235614 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EF0F709F -20150520235616 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EF12110B -20150520235622 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EF25FE1F -20150520235637 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EF6BF4D3 -20150520235654 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EFAF28BF -20150520235701 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EFBFB8BB -20150520235704 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EFC7A62F -20150520235710 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031EFD79323 -20150520235725 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F0158F1F -20150520235728 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F01A9E6B -20150520235743 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F055798B -20150520235752 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F0730BC3 -20150520235757 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F08283FF -20150520235825 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F0F451E3 -20150520235830 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F0FDEFB7 -20150520235901 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F1828ECF -20150521000008 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F185D7BF -20150521000011 2 6 100 2047 2 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F18C58FB -20150521000014 2 6 100 2047 5 F7360753237CF1837003CDFE89D99C8149BE6C4B4CCD9D09D834FF137878C452FB4FAB5CA51BE6619BC6FEC4184FA9A96D21FDE83505B67262EEA4870FD709F4DD3A2EC36E5746ED80D762467E794FE524992EAC42D2F0F391A63E027F24411B231D25AEFE60C9329CE8FFB61A8A123C74F6755211C8CFD59915CE0DE28579B66CB426D111F90B19A5BD83AB8C2CAB09FB1F09509B029883BD154B82418B4F3A9EE4564E5F344D5B911C10829C1E975817EB2DFF49F34D95277897A7198C9C4921037B8AA091C380663A6D5260F98FA784565DE2D977C50A1079B485F4BE63B4E3D6A63FD8DD59704116A41CB1C7C2AAA449071BFBAFB0F867FCC031F191F757 -20150521000841 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CC7F06BB -20150521001025 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CD1057AB -20150521001131 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CD717D6F -20150521001248 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CDDA85F7 -20150521001453 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CE8959BF -20150521001510 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CE98227B -20150521001623 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CEF967BF -20150521001651 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CF18156B -20150521001758 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CF717197 -20150521001924 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622CFE1507B -20150521002244 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D0F75427 -20150521002509 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D1BD2823 -20150521002808 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D2B4950F -20150521002846 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D2E6D6D7 -20150521003203 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D3F5D0D3 -20150521003322 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D45851E3 -20150521003430 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D4AEE517 -20150521003629 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D5538E0B -20150521003714 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D58BAFCF -20150521003722 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D5916FC7 -20150521003739 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D5A378F7 -20150521004506 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D82B5113 -20150521004613 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D880CB43 -20150521004753 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D909305B -20150521004802 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D90DBDC3 -20150521005025 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D9CBF44F -20150521005051 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622D9E89DA7 -20150521005252 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622DA8BA403 -20150521005347 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622DAD07F73 -20150521005825 2 6 100 3071 2 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622DC5CE5A3 -20150521005858 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622DC84A597 -20150521010014 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622DCE62957 -20150521010219 2 6 100 3071 5 E0C2D7F7B6E4C69A3B6632FC77BED88CAC663CE39D91DDF017816529795F33B591F80F445BE16F8FB51D11861682154B904AE2282FA0462EB6C508FD7B7AEC551A6C630FE9CC7E17E660377558E4F841CD77AABD81E6A0988823047B3A00C2E50C33035987D6EA42C65FD776051F5D43045848D4385FB37482DC9E5133D1B75E34CC81C2B87C9530F5229FF2154604A286C2E257D3A89CF330AEDBA16288E852277C5D7C6AA947B4510625312DF982A30A4D75679F707EB325CD4DF65C7A58154C6C05E28545DE69673B3EA9CCD41529A7CCEB49A3392D23E9AB083148DD956F8CA9B8CDD76496FF95B5782EE888C40EF1201EB3A52CAE1A635BBF82CD479B38DABD6DEE7A2844F8C614215B04CEBDD41039C2DC2D1CF00AFC78C0363E548FAE1DE8A7B535CC41CED767BE05F300F50C59307061ADE1CAA4614F8FEFAECE8F8C5DB3F425B348A206B0E95703EEA8785768CDB53972422C75B58A7AEA2AD9E2546EA991466E6AFE1FA157D75D3F6616DB715D10CCD6B71C73051FE622DD9517D7 -20150521011229 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F951FEB83 -20150521011834 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F960399B7 -20150521012438 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F96EE7973 -20150521014010 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F99453213 -20150521015607 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F9B549727 -20150521015640 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F9B600A7B -20150521020946 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F9D5299DF -20150521021536 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F9E2793D3 -20150521022706 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877F9FE131CB -20150521023922 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FA1BAC073 -20150521025234 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FA3BC9483 -20150521025424 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FA3FB3513 -20150521032445 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FA87E0FAB -20150521032932 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FA929F00F -20150521032947 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FA92B272B -20150521033245 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FA9953D0B -20150521034828 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FABDD4AEF -20150521035044 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FAC298C7F -20150521035111 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FAC31F17B -20150521035749 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FAD250357 -20150521040009 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FAD788A73 -20150521040220 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FADC5F173 -20150521040316 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FADDFFC03 -20150521041042 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FAEEBDEB3 -20150521041443 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FAF7AD7BB -20150521041831 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FB007D653 -20150521041928 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FB025C91B -20150521042301 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FB0A4C143 -20150521042631 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FB12009F7 -20150521042740 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FB145360F -20150521043358 2 6 100 4095 2 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FB22FAE93 -20150521044013 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FB31527AF -20150521044543 2 6 100 4095 5 C8BCE52E2AE7AE1EC20056B2D0764047C92392C9DF75C3A57EB8AF1062A809E6EA975D9910AA5C55833CC47D4DA76E92BF63FEBB289E5FE2ED729429DE9567D0A489FA27B41810066B96602B2E555B34628A37C4CE04984D15C36F1EAD09081D2CB2147D5F0B7E8BCF0774FFCF5F649E0CB797DD23D0801C153B6B8480828CF165C7ED3181F316F371C6EC0B6EF6B8CBE36E5A4E8C070854668AF07FE6C73C3EB817CD0E8C7F264546A1B0402AC0FCEBA5032EBA2323769CC401D262971F4B44FC1151EC4F6E761709FD6ABDC84D9C36046811F54DC86D293D16D235DC712BF7346CDAC005AE5C0DCD96480C9BD0CF7C4BD50026553E27F957B6640BA6A87C6642FF3D97A3E63DA468276E3A22C0C3F2A1CFFB4F190D5E23700BB468EA31FD3EB87B44B51BDABDB0667FCFB618CECFB2BC440A5F2E237E93A6DFF96AB3561AF5EE1BDA21720129FF2123F7038C70B4CADF1BC70B2EF5EBC264E1E3B2A4B3780D4A11507D03A498A556A923B0EFAF90D024341A47818F03D5ADD961086C2573DABF02C4E2F303817D323E1D8D88EFBE3F5E0D6688593C65254907745CA6176C8ED7D6B830875A0BA8FFEEB1882742A4553E4E55A93A7AD4F3224B7BFA03E29C77DB0FCCE0E37E6D3A64C5555ED9555FA1E2C34EC04DA3B6E0AAA7BF64879BC4724859FE806E7DC49A5394AD3D01492F05AE69CF10C67B18BDFF8E877FB3DDFBB7 -20150521004745 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F52665F2B -20150521003352 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F57C7B577 -20150521005557 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F591BBC57 -20150521014228 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F5BDF5CE7 -20150521015455 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F5C9CFD1F -20150521001701 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F5CF6FF9B -20150521002558 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F5D7C4FE3 -20150521003319 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F5DE41DFB -20150521003721 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F5E1B5FAF -20150521010943 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F600B866F -20150521014141 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F61F01EC3 -20150521010312 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F65EAB753 -20150521002914 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F69FD9357 -20150521011058 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F6C6B8513 -20150521013628 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F6DE7D9EF -20150521015040 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F6EB0C897 -20150521001307 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F6F15473B -20150521012712 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F7377044B -20150521005218 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F7767DEA3 -20150521003512 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F7C5546F7 -20150521005420 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F7D68EDC3 -20150521011347 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F7E859CF3 -20150521002429 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F819A93E7 -20150521004826 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F88D91A57 -20150521010541 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F89D29B9F -20150521012418 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F8ADC38F7 -20150521015506 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F8C91980B -20150521004000 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F8E369B97 -20150521005659 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F8F2B1BEB -20150521010328 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F8F7DD1D3 -20150521011152 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F8FF052BB -20150521001457 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F92940463 -20150521011129 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F95C47DCB -20150521013515 2 6 100 6143 2 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F9710A103 -20150521013841 2 6 100 6143 5 D9F2DC4F4AB3E451AB7781730AE26AE5AB1927A8F93D05C7765C4F23947CBAD218690437DDE587137100CA657CB902597743E8B05CB9B821A48E081C451227F5E42404534A28EE1D0A52FA903FBB15B79139D130420B8C7BD2477CDF0C06CF4C9943DF76A74C3B503B2229A5628E13983B0426A10FD164A720488DE3A1639D004B694ADB5216C21F481519865529CE6E3C9C8B89AC00FBF2B4C1F0B0033AC2A5072A157B5D4346950917B055227557FF1EB5F0873D75E648BEE4B6F88D4B228CB89C7602E34F85BF86DDBD09CA39993C73FF59B0310754F0D24740316F7D8D21D67EC65C8715B7130EBC8E19EB712990BBB30D650ACB0B7864B632ABBC2AEE7221393A5C74B043568043480DB41821A0CE1E6D271456C2FDC243D39868FB0D7BDA3FAD5894F7DCBBC5751B77B3DF99F6E8A5BD7A5B82F594E3E0CA2BBF7DA74312227B323652E6856B597326206CAFF2380C23CF94B8CD3EAA56BE60F8C372887CD37A62FC6F5FD467ED96E7CD9C285E75C2C353E520DFB3F39FE7B8E35FFB485B1B043F52321675EDF4848266997D059810F71D21E9DB3E3AB1BCE3713DB67155F41B7C21939B285AB63DBF1770228E4EE36314310D89200F132E8ECF2968CDA0E57DBBCE589E4DDBAD009994A817032EFA52F0659A319FBD813901BF5847EC2D7979CBA5870F3DA25BE09673952628E1EA70C82EC0BE67B402E48DF85C5983516BBEEAB811D1ECAB02928D4087B826139D073501149D47B3339CDA763840E4492661FFEF96C81C816B862EEE820019CD83C93BF9DFF8EC8C59331780D5D86B164EC12BBE59F4C9E62FD7819A941D10AFE32179B2361A17618FA84864F58C09AECB817E67BC352371BB7D7F8209E4EB9002013A585092D4721B1CB464A8480CC76173989144EF51692E373E9CCEAC9807EF190D6BBDD3BB0D16CA87DC6A54890D6F074ABD83E3CF077F2F592C0745BE15D7D6871552BB6139E5CF70D684C6D1D0C4516733E0639BBEC847313BE3D1D923B6A5FAF43A5341DD8C0779881BEB92736BA4F18BD6CDC1FC922B3809ED244748101A6C7E30DDE0C232FA3F9733A497 -20150521041810 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7BE934407F -20150521070624 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7BEEB1E407 -20150521051555 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7BF50EEEC3 -20150521061258 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C00AF225F -20150521034225 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C058D5963 -20150521035956 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C0616723F -20150521054248 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C12F16C3F -20150521060112 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C1379EA23 -20150521023340 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C165F2773 -20150521043505 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C1A3EC717 -20150521024626 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C202ABED3 -20150521064303 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C27790087 -20150521060604 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C2F9DF583 -20150521062143 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C3003EEAB -20150521044311 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C363D0A77 -20150521053731 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C37D6EFCF -20150521065640 2 6 100 7679 5 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C3A20A2DF -20150521044717 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C3F622E8B -20150521065426 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C430ED7CB -20150521023632 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C445E575B -20150521032945 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C45EEE643 -20150521054538 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C49FB77CB -20150521024620 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C4D86D0FB -20150521042108 2 6 100 7679 2 D67DA234F46097F7EE3B230456E7C895BCA86395DF43D60D9D587C64EA4525FBCAD22442143068578CE8ECC8280B2D81F747B484AA668FFCDBEB067EB824B42E5FA1A40BC08EE8CC4A064298CB31C36340951EC7A006878C79C80068196180DA31E1DEF79A72B2D059203DDE461485D1B9783AF79E981CDAEF88589D8343E5B52D96FE90EA13194AFAF7459B17B80971720357ABD09CFE992966FFC1C239821C910F55D69E44277E5DE9841F4E5B2D25D6A265D321059B762F7D6AC5F0E260DEEB628D32940002B219B354486CC5BBF6390F19899EA5E145A28487029DF0517564A81FA10FA60AFA04CE77794775392829DB636E7F5EE00868D5027A6BA75CA922CEF3CA78683D14AB2E58439789033ACF441236F5E3C7849E3662B5123304F82D0061EA9C18EA1676A736FFD628AE982CCEAB8979568C43FB34207E0DEC7D8A6AA391846C910F77771ECF2D0531A234D3798BC1B1433091A895E23A77792F4BE403D526F1D260A3627F2E80E863A204A774F58D7DE2C5C4A7E463A46BC436F0B7AF07179EC334D31073BF035FD94454ECD54146473F786EA15A1CEBB3B9C0D282195AD612D33B31F5528DAB5231CB17A3DE9AB5C8BD7BF8F773C255845BC9B70A1E53A50E5AEA801FFE604A2B2C1FBE86A2A883632E7AE75ADA007FB6AB1AA529DE3151CAA8D1D07FA19EFF5679398340E720CF2CFC4E1AEDD73C44983CC8E610DD419AE2E88206573837D6E44018D9498B62F9C0B8EA7741450FC7DBFF7C546D3CBCBA5B9123577FD5531880A18F1275F9181A922803D8F03512C58B5FBBC41CE8095EDD920A3E36CEB6EDB56900E6CEC2928288909D61B3B426EBC54F0A69C261A848B358C3A8E332567B9FFC1A7A07E9414BB1F75DE0795CF87632F5D6A87A246FD4E98E70489F779FE99C5BC4DB24BFA860C3551888FC721CDBC6AB5783B02BEF893E0984B6FDB5142A1AFD3277FE8F36B87849BC00B3FB3ADAFE4EDAE4839B83894C27FEF93514D7E3FFB7A30E99C6875D96C582E81D45FB463DC37B8791FC28A759301FC2F9879960C82BC7C427382A41B9AEFAC0051A2C653E55A47B48860CDA32812A192C1508A6C012C7E4BBAB1619B7926549FD8CE27928618F035BE31D56CBC9586D88E00DA69341F6F01554E205344E49E8871CCF80F9FF5CB54479AFA66806DD02FAFEE7D43572B3AA22742635FE65BFC8004960DC679FC7F8C0E5B50B3CE1E446B7A5E189BB9AAFA06FEC472D6E67EA4905373A01A2B662F534131405FBAB9BBAE892F0C265439EA1ABC91B186B5AC1E53A0C786607B1069BC026359955CFD614D7F80DF416A08AB18991A0398A83DF3CF2D65D7C505E524B -20150521041835 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354CD3703FA7 -20150521051726 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354CD4CEF96F -20150521074626 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354CD86439C3 -20150521082439 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354CD947F7F3 -20150521012012 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354CE0694343 -20150521073153 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354CE93D436F -20150521094433 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354CEC4EE993 -20150521074128 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354CFA190CE3 -20150521014004 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D0235296F -20150521014736 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D025961EB -20150521065737 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D0961218F -20150521043653 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D163706C7 -20150521085322 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D1BC6858F -20150521093922 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D1CC27FE3 -20150521120407 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D1FE2874F -20150521124157 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D20A8A19B -20150521035417 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D24E0665B -20150521062806 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D2828F7AB -20150521074218 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D29B42017 -20150521114937 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D2F027D3F -20150521073847 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D3905A9FF -20150521024512 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D41DB2FFB -20150521024827 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D41E2852F -20150521042402 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D43D9B0E3 -20150521083756 2 6 100 8191 5 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D491D852F -20150521113241 2 6 100 8191 2 D7182545CB6AFDA1CCF5BB87F606DDD1CD25D4BAF110D7CCCC0BC78929189C09DC69308FBF76A16338AB8351B974081AEFE6F68B9DD0B3F661ED84DAF8736BF328122D00A803AD05DDB334CF5C98B2670F0B2ED0E2FA602CE2F6157A2A8E649A546957CE4F723C84B6AC46D64C5B329304181F2B70F48D15181C38777F4E18BB0344F5DAE703CC3A46B670713A7B99E536D30F92D1E5E683F2C5540105F425E01234968D1A63E0220A02721183E30302F029E4D0E0664E30329B730D99D03E53D67793F31BBA6C4274FB2ACA9181655B766246C598E4CD402737B682232B8534BE43A790ED6C04EF8047E1796048099B65EF415375D87BC7A01CB6086C9E23B667D22F52F5F44D6960601C15515D14F7D6A6BF6D7F6B1D834866ADF9FCFA1CDE00EF04C05591B05D4752471F124406D034BC8E6D71E03880BD3E7A77FD22E7D90B90A491E528EDE2E4B6FCF7C638883A4CDE80AF2C839569A4FB641C7B8948200DB0F51CA9B2613966C51F026A007D0696D14A4E4897556C7BB0E60A407B7B8C57643F278A47CC8089E24D38BAC1350A0E6D19FE540A773B8E90A6312D4B038C643B03ADDC741BDD3012F7714863BB63688E6145D47A6F40D15D6485E5AC278E229EA800FE705FEBEB2183CEF7C55DB952B627D4890B45441B3D4CF03BF0D132A7042C24447518B14956C11703131981CD69D7B6BA2A9F8C62057FE3A4319D17739DE0BBDAC9600E4809CD856E5F41C580863D93C251F0A31BA1CBCCAA499FEB79184E165C436A3B2FA9791C4526B47B0D1F6FE3BDE2730421E5DCA10483D91AA873ABD1236674EBE3A0D134C685CCE9D632280AE11C0D9CF7275517C1F14BCB81F2B23860D86F5028B21DF85868972EDF70A0704B3853EB1B16970834C661BC65693D38368DDB0D6E781DD2F52AE279913304601F5709E1C4B1A12B0FFDA93369001186FE8716027667F4B816E927A9977D3030CE211F4BE8B6F48836EABF4D8457FC5CFE39DF5BE96146D3B8C5BA11C3D75D252B0C190DEA5757049DE6BA89249166D60163ADDD38EAE171B53D44E135973AA05293AA7407693AE5478F480A3BE97BACBD8C7DE6EDF39EFB8BDDF8B0A2169228FD98A863C450129C8BA561A1D0F29C4EC75060A27E028E1321BCF7ADCB34B2C2B037E2C6B705F74002E0C844092025A630CFB2105F04D40135794DDF30C7E19187AE2AB8E6296C9EACFF43279F0ABE6E1150ABC2C3C8A6C4B95A7AA18CFBF953BF7662C16A0FE26D9EE7CF62BA16AA87B06373082E7551F42B8BE57BE19A50B059DC652BA46157FB7CC29AC1BF2834E668443637F87B2B12FD338706D69935D2C6348CF72F568B89B66345BF42209AA6D898F4388A54B4CFFD735EAF987CD6B738B401A14FACDAC97F63529118ED56DFB7DAC4967FFA252D185DBC29652E3F62A45D6BF990FB354D4CAD7D8B +20150522025931 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAD18DA1F +20150522025936 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAD3763B3 +20150522025942 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAD702B8B +20150522025943 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAD77C283 +20150522025947 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAD96C25B +20150522025953 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DADD9B3DB +20150522025956 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DADE84F07 +20150522025957 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DADEC1DB3 +20150522030001 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE0E297F +20150522030004 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE2A1E23 +20150522030005 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE2ADE53 +20150522030008 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE47B9F7 +20150522030009 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE4E1343 +20150522030014 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE715CBB +20150522030016 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE7BC9EF +20150522030018 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE84579B +20150522030019 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAE8A564B +20150522030023 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAEAF7AD7 +20150522030025 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAEB9DC53 +20150522030027 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAECD976F +20150522030034 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF07F063 +20150522030034 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF08ACBB +20150522030037 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF192C07 +20150522030039 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF241333 +20150522030040 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF255B3B +20150522030044 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF3DEC37 +20150522030048 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF60F05B +20150522030049 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF6255DF +20150522030055 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAF8EE01F +20150522030059 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAFAD237B +20150522030104 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAFD13587 +20150522030105 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAFD2BE6F +20150522030108 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAFECF32F +20150522030112 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DAFFDEED7 +20150522030115 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB01CAA63 +20150522030116 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB01F3647 +20150522030119 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB034B30F +20150522030122 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB04822EF +20150522030124 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB0528867 +20150522030131 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB08D3CAB +20150522030136 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB0B10C6F +20150522030138 2 6 100 1535 5 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB0C688A7 +20150522030140 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB0CCDF9B +20150522030141 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB0CFD81B +20150522030145 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB0F59763 +20150522030148 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB10339FB +20150522030149 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB10E3ACB +20150522030150 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB11127F3 +20150522030159 2 6 100 1535 2 F4EE15F22E5F49997A027769656DF0240598C9470C7D67A7D7DA2777883C1C243A6F3D04E1CFA6A0350B165ECABE89A684C11ABB7E5B93B54FD6EAC85BBA9F23C6306E485BB9AC5515ABC739CE9B1A79F7DEF6D00B643856DB903E23E7F985EDCAFF867FE15498E7EF6A91057DE337A9AAEDE941C934E65243AC7888A33C78FB2490BBA2BA06F18ECC51DE9AA54BADD061CC5BE1EA060CC3217CA11E26772BD088898D2882CB49A9FF40168E49AE6A90EE1F61132E1B6E4E7F99797DB15B8BDB +20150522030634 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8ADB54257 +20150522030715 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8AE6EF847 +20150522030737 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8AEC5D76B +20150522030739 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8AECB604F +20150522030742 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8AECF538B +20150522030756 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8AF04851B +20150522030828 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8AF867683 +20150522030905 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B01F7E27 +20150522030909 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B02AFB8F +20150522030918 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B048739F +20150522030930 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B07661CB +20150522030938 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B091EC43 +20150522030955 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B0D50D0F +20150522031007 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B1023673 +20150522031015 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B119500F +20150522031036 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B177EE9F +20150522031056 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B1D0030B +20150522031103 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B1ECC193 +20150522031125 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B24C9CF7 +20150522031136 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B2774773 +20150522031208 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B2FC9617 +20150522031220 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B32FE6CF +20150522031228 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B345AC93 +20150522031248 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B392E18F +20150522031256 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B3B32FCF +20150522031300 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B3BF5B2B +20150522031311 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B3E840CB +20150522031316 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B3F5F9D7 +20150522031334 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B439F28B +20150522031337 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B44025D3 +20150522031339 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B442AC0B +20150522031353 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B4788613 +20150522031356 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B47F8FDB +20150522031401 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B48EAEFB +20150522031407 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B4A1CE0B +20150522031420 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B4D73D93 +20150522031425 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B4E9937F +20150522031428 2 6 100 2047 5 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B4EFD4BF +20150522031436 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B507149B +20150522031452 2 6 100 2047 2 DB36277B45EA5615C782C08BF6A290A3D61E6B9690E4A147042113FC1BFC0AEEC5FB0FF82FC1FEA86E273F667EC387FEF3421FFFC617A70C34B1987986C6B35C715713914AB75932A3D1942ECC0F324D81BF00D59916B3BFDC7BA432AF5C5DFCF30BF4A2C80B8CA52A9B80E989D3A852BD81A8BD3ADC97497F43C6F0A90882D9CFA165CF1F735C96428BF9BC32A58B71CF1D4FD48A6D2C616E91BB6E07C5CB0DF0C59DAF79D659C6E53007843497BBEE5B341D27DE2E2543B8DFEB4DDAE6328EAD441C3F36509C1FA689FE494B0426ADCAF9E567A1C5A3301689C5CCC55EC4002FAA5D254C2F3C0F8636BEA7019D1CD212B74EE4F273E0B9997720E8B54A3243 +20150522032348 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF98368C951B +20150522033023 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9838C4B4F7 +20150522033224 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9839729F67 +20150522033330 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9839CF938B +20150522033506 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983A5AA27B +20150522033539 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983A849987 +20150522033610 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983AAC8A5F +20150522033839 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983B7F9067 +20150522033952 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983BE385D7 +20150522034001 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983BEA4367 +20150522034055 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983C305BC3 +20150522034123 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983C516EB3 +20150522034146 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983C6D1017 +20150522034241 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983CB6A553 +20150522034528 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983DA8F54F +20150522034544 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983DB92AEB +20150522034719 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983E32A87B +20150522034748 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983E589F5B +20150522035227 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF983FE4EA2B +20150522035328 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9840340683 +20150522035522 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9840D77183 +20150522035721 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF98417632BF +20150522035808 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9841B795AB +20150522035847 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9841E9F357 +20150522040046 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9842863803 +20150522040057 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF98428F98CF +20150522040128 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9842B68EA3 +20150522040136 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9842BA209B +20150522040232 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF984303E883 +20150522040546 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9844117EF3 +20150522040607 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9844276407 +20150522040733 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF984499981B +20150522040850 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF984502ECCF +20150522041059 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9845BB3AD7 +20150522041141 2 6 100 3071 5 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF9845F34747 +20150522041538 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF98473F522B +20150522041645 2 6 100 3071 2 E409DD3E1471472B9A1A2C64FDDC0EB822C4485590288E209141916DF6C51125FCF17ED5F4226F63928FD7E9C60DEC3B0A82C6DF10C33E0CDA2E200004C3B89C7BD872CF9572374C7590F8960C97E1A995319ECABF60C00DAC39A8A4A4196638FB338F47445310F2424518C4ED9C789D17D591DF7B2CB11FC320AD7C84376EF838077C5C81BBEE2BDF38F8716E94F756919654AD5BC8FDF9CD644F0B1F604DFB7CF28B8AD55576458DB547348E74101FA39ADD0D5675E2BA2FA074C2BEC53DCA68A1F49E3F5EBBE9069C7BB20A0ED4217C8D8FE99DC3DDAC05172EB056C6173306F604B90079CEAD87AA170EA89E38C07128067C48695040F766131E9E8459FB71ED94BE176C9F827BBAB219E1BD7A4C7ED9FE7FF62E844B0915C9ACD5B17FDE866EC34C44C348C23CC303D6E7AFDC55AAAC007BF3C67280C13C9801D2D8E0739680257CE5CEBD5CA0CF24D2CA6A354D5D132A72D2ABB2E50D257B5A6DAA038683C1A433861204570824D0734402498259C171BB58DA074D22B1DF98479B35EB +20150522043157 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379177A90103 +20150522044043 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379178F7604B +20150522044434 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917986809B +20150522044641 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379179D34D9F +20150522045152 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917A93F48B +20150522045648 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917B4FEA03 +20150522051224 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917DA8111B +20150522051844 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917E9226DB +20150522052054 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917EDC16FB +20150522052204 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917F0058A7 +20150522052248 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917F16842F +20150522052650 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917FA2234F +20150522052821 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37917FD2EA1B +20150522054416 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F3791823EE827 +20150522054652 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379182978693 +20150522054912 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379182E6E57B +20150522054941 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379182F0448B +20150522055008 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379182FA0E27 +20150522060835 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379185801F93 +20150522062202 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379187943813 +20150522062512 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F3791880945B7 +20150522063933 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918A32FF83 +20150522064222 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918A910AB3 +20150522064452 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918AE83E73 +20150522065035 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918BBA1623 +20150522065634 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918C920633 +20150522070134 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918D471AAB +20150522070306 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918D7B1063 +20150522070332 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918D838D0B +20150522070807 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918E2B8B67 +20150522071420 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918F0C3653 +20150522071508 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918F1EFFFB +20150522071555 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918F35E697 +20150522071903 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37918FA47DEB +20150522074443 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F37919363872B +20150522075339 2 6 100 4095 2 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379194BA4383 +20150522080128 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F379195DB3C5F +20150522080506 2 6 100 4095 5 DDE41D7021F9DF8240D0BD8E14CE1E374A4FFDD073767E84C8C347B6F832731277F9D333B8BC7CD96ED164DF5C6F26E46E4BAF0AA7C87B26CE3E11042C1BDDF76095E50D7772E5DC0C48EBA0E41EC92EAFA655DA1B6C614E1F0F9AD815BD7505AA9B8A265D13956B5A26141EE812404DE13B821C9B7BCA9982B8CF7D862F8E8A373FEFEE4AE46EC2122519A2AD896ED18CAECEF314D1B98C83358B6E9D2F3BC58C1688F162E3CF1FF58E57E7B9E14BB37C9C9E9692E57C42937141C226E84C35B42DED9055A7F366A61C3CB4899B499278ED4C729CC1DE54827E882290F9FC13F7F1488F897698EA62A99468D6F3ED0561816C39B8279154FC7A8E453CCC4EB1ABC777A397B694E1B9866C2495489F94721A3351B252D05FE6C7857929B34C19A8EB42ABED88FA370DABCA83A245DC35CFB399824D127507AD540054C647F61C6BD11CAFC3FE5277A1014DF6B538BC8BFE009315BCD60E020DAB840B8A4219EBA4E349680BC7CA3A9BC36164A3D36E325C530B178747814F575899126B307EB63F910DDE0F09E5056B2F9F7E230A42C11DDD34A9B23A64090C2FF9C7F3DD696E6828613E74A64CFC4046ECFA997BE84981430D8A7F8AEC63001E50AF9F556567A0065A9A013A66A2737CEEE468D6A15002358AC648D862B0618E6DD6A98BBBE9E68174D9C9FE4568BB2D12083CF6892B6B8D58307944955A987F3791965094C7 +20150522083733 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C514C4F88F +20150522093608 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C517A26827 +20150522094040 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C517D03757 +20150522095314 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C518686A8B +20150522101845 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C519A641F3 +20150522103233 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C51A4A87B7 +20150522111208 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C51C3A7B9B +20150522120305 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C51EB16CF7 +20150522122813 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C51FE5C353 +20150522132032 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5226F04CB +20150522141054 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C524EBC207 +20150522153656 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C529553A9F +20150522154114 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5298632F7 +20150522154826 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C529DCC5D7 +20150522163842 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C52C78C8C3 +20150522165625 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C52D5A1C27 +20150522172408 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C52EBD88E3 +20150522173745 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C52F69630B +20150522184340 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5327AFF1B +20150522190348 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5336CDC63 +20150522200705 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5366C1207 +20150522201200 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5369D0A6B +20150522202855 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5375B287F +20150522204401 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5380EDB4B +20150522205115 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5385D084B +20150522210056 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C538CEBB3B +20150522212110 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C539B27FE3 +20150522215602 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C53B4E825B +20150522222840 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C53CD37713 +20150522224719 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C53DAAAE07 +20150523005800 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C543D2802B +20150523110456 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C549CAF02F +20150523111755 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C54A5BCB0B +20150523135850 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C551C0E2B7 +20150523140345 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C551F4D6B3 +20150523153045 2 6 100 6143 2 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C5561141EB +20150523170349 2 6 100 6143 5 E49C8871D7F1191BFDDF2C21369599F9E9F57F502A68C5AA4B87527B218B90EB8F33F3D6B4E379A17BA18BDDA81F2DE8B15EABBF424BDEF329D792093D88EB5536D5F165F767F08AD2220E0005162BB37BE7F45B2574F2BE5BFE4262623C8895A803F747E3BCB0DD396DED524EE1E9B9EEE82C741A1F8ACA2E6DB05CC1FE8C2A7DC50F1F019FD74FC6FFBF38ADA2D36A7CC8DB2C7961C154A74BF0086C173AC7A22B266BBE9974459A7EFDC2F0CDB2F9E288527FD356017FDE01AE17A954561197E18E4AADAF0643860328FC9A2D8A5073348DAD615ADF1AE4AD5BA1630437AB4F7948FCB3D33CD225AA6661DD2AAFFE774CA01F0BF8A2DB168D8FFF3A223E3A60B039E9ABAE8E4B6A37B7E8F77A3EC2D1714B79DEC2ED2BCFB39A4FAAB8913D421099623BCD1DE50B419173236D91E09CFCF544161EB4CA8A45295D812708E349D2118EFA3EDC0F86D3300A80C36D77CEE41441F84BBE663413378F2CAA58F6915B5B3CD799541AD5CCC74B76A59555EDC3B6ABD77318E0A9E6450277DF93A882C6F3D2E13E3BBE361BBB2813A2A269324D7FD2D9437AD065CF3CE698BE08857E5E22800CDBC0235AEB364301AF3170C24B8A68B7B038499F788040E86376DA7DB517751F4FC6D1D3E1C3FE8DDA27B69D1281A18D6D2DC92C2E471A4B577F789E5D397C68B738DBEA06FF55AC1D1C177E3A51D136055E379CF68C27DBB6D66771D9ADFD846CBFF9EFF5B0BDC9EA16A8817243451A93545D19DCFB3DE1E50936A62CD98379ED37C13BE8D71DE48E4115DD309E67F676B0CE88B60BDCD0CAB98878A17E67E20723DE50DB3599485E25687005AB55407632E12AD919498F562D2871A55FEDB76F113D1E92AD5E4D342B45611D9F844BED39B36E5225147D3F6BFEC6C6CA88C423ED62781E29EA9A9418500E7419922E51210FA767153619573EEB19609C77212D6A9724295FBF0A1915F33074D5225E9BD0C6105DA28F1B0E5F43EECBE67B18D5FE74FE60CF87800C623B13FD6152CA913F91ABC5113FF0CCFE362C30DF8F369E08DE8D57222DDF659AE2458C7B4225AE583E178328C55A59DCDF +20150523191201 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB470CDA3203 +20150523215157 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB4711A72AAB +20150523231527 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB47141BE273 +20150523235422 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB47153C4A8F +20150524010823 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB47174C4663 +20150524013736 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB471810100B +20150524040115 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB471BEA9823 +20150524051719 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB471DEF42C3 +20150524055417 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB471EE81B27 +20150524104925 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB4726B43323 +20150524105636 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB4726DBBBDF +20150524130121 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB472A1294AB +20150524163025 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB472FBAE453 +20150524163715 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB472FE1144B +20150524173410 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB47315B458F +20150524181655 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB473268D4BB +20150524223625 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB473917D17B +20150525001303 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB473B95BAC3 +20150525011252 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB473D16F0B3 +20150525020522 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB473E60DDB7 +20150525061910 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB4744D20B9F +20150525092924 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB47499CAF77 +20150525124039 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB474E6A2CEB +20150525132602 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB474F854D7B +20150525170642 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB4755495933 +20150525201019 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB4759D07FB7 +20150525223942 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB475D6E1C07 +20150525230547 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB475E0B3487 +20150525234905 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB475F115D93 +20150526002510 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB475FE94D13 +20150526014857 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB4761E82A83 +20150526045853 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB47667CBC4F +20150605090211 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB476DA5F0B7 +20150605145212 2 6 100 7679 5 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB4776229827 +20150605174343 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB477A770453 +20150605182015 2 6 100 7679 2 F829F98FA9F017F2B534A1ADF10BFE7F46E24D09A1EA89D3BB00CC679F6CDF5107A8AAF6F1AC8581E5D52174BA79E05DC2D61FE0B3F10B52520086FF4BE33841858D569DEFF006D6145E062E37CB2A225BAC5207DBC87BBCBE31A12678F8BD3E64FAFD7DA004CA67EED97A92C511BBDB5CAE7D563758EA45BD2280A91209C417093F079E901E48C80702D0B5420C21A571B133299B590EB3ADD67CB1538D85F03C2EBF2A0E1B64C3CCB55CAE257C3939E2A48DDB50B557BFCFFA891EA55D2CE29ADF58D94887170E2EF8EEA14D83117793B2EBEBAA5DAF26F118C53F3F50EF50ACF4BE634C4714F05F198D0A10C91C789C08F9CE84CE238FDFAA6368A1D971450D3A05B279DC0DB0BE57E7B36ED42FC2DE0989CBF4881F59E1C3EB80C8BFA7A9B4493246AB0977F26E368179D4269DF732C935A7901E34042CEBA93FA7B5F2BE7765D1568F83A82D0A556F973DEE714AE348EC6EE73D06E5746D7CA7A2172053350FF03E2B2483F6F5CC20CE2FD44CF81187EE3A28073C4360432BA958FC71C6B4609208610001B762042C20951BB46D484A4D018134E581BAD41EABE16721DB572B76921A6FDA278B4DBCD6E479D89D8F076A3DF39BBF6A81A1529BBDB06A75792E3CC2AE7047533465FB0C4BB6F0B16A2FB13B5812E5AFA8BC06184CB8620700602A9F3D1194EC7F98FF6858CFB26161FA3903301F7F54E8946C688B91631BF8B2452255F7EA8BC66FA9CB2D12BFE8437330956902B5D04469F45AEBEF0CC2F49791EE958B7FC791ACC0BC6A0DAAA8BFB2A5EB49628051F42A0CF1FA0EA33E9EFC8DED03407EA35D1D6E7F09D278793C9E446F99E3A9D6EB93A07FFFA8A16CA1417D776A3DC2D621F3D49A7DED7FC3274228EA72E2BECFBB071B8F1EEC99F04E62DBE9D6F781B3E4078EE28596222A387E87FC7213BB49AFDB79E549B5533877A8FAAD0A86F34AB36B26A48E544F5175EA498E57E6CC8B72924F2DC0B4C4A6364E667B11E49AEF39CE132086650954863BA4BB734A8A13945901802072BF924A6B38BC81E10E3EB74330411F10E259D58C9C4C5F1B4F40E85F11D12D0A5D4F896E24ABBD91E80EBCF0446B189705C133E113699D589068FD67D1993917B9349D380BAAAC594824051275D3AFA8BD3434AAB6C30CC9B6E687AD41A20DBDB890D36571726BCDA2B7051E1BC227480C83F2352A9DF08EBCDEF39936BC26553279246E536F26FFBB65176F4FE67B21658DF22C344A260B4AA8A09F354ECF50B8505F2F6AE4F99F6549CA139B730DC3618E6B5B70966A4276848266CBF23F0FEE469EAF298932EFBBA50E719BFF2259504A6D23938DAD104016FA91EB477B32F0B3 +20150526114135 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE95C238093 +20150526114600 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE95C32EEF7 +20150526134901 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE95F067BA3 +20150526153127 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE96179B9CB +20150526164245 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE96332D5AF +20150526174513 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9649A719B +20150527035812 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE97262B7F7 +20150527075726 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE977B43343 +20150527112120 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE97C1F6EA7 +20150528010450 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE98E4FBCCB +20150528020450 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE98F884B93 +20150528024708 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE990692277 +20150605205801 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE994DC793F +20150606012116 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE99A681C6B +20150606055158 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9A0264EE7 +20150606071549 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9A1DB0223 +20150606132241 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9A644DC6B +20150606164856 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9AAAAEE73 +20150606183208 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9ACEEACDB +20150607015742 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9B6ADF38F +20150607022317 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9B733A2AB +20150607051100 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9BAB79D47 +20150607064815 2 6 100 8191 5 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9BCBC8A17 +20150607120629 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9C355FA5B +20150607121012 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9C3600A83 +20150607123508 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9C3DCB093 +20150607144400 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9C680E5AB +20150607145646 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9C6BC5BC3 +20150607201140 2 6 100 8191 2 C64DCFC087E26CA2C02394329FAB07FECC446B77A6190D0FFB4326006E0F6D755C35C82228750F80F466E5E6C6FD70A6D4398BBF24C8B4D4B27A38125ADA4D087A7051B2FFCDF675AB1AD9A3A4EE3071B75A8DBEDD879C1B4D396FDF862B2C192B5EB832FA23EAA10DFE795435545882854A0F3BEB476B865E6ED98E43E49950F2FDB00A0E177FAAA3162AE6F513DAFC9A55676C0BC5B87A1C79F98C1A93035F3B39BB24C2C398DA1AADCC16EBB918407579D24ADB3826725E2B4BE73129F28181BD3A1CFCA78712592F8C58E8AF3BA7D7DFFB538AA2476467AC75BFD4C884949C58A0BC8D820E0AE5E0280E083401D239F63649845FEB53444126D137B3A80D4EBF5839263C302FFC3CA5F653B2D93C4AC474D489ADC4E1379BB7FD72950B57EF30FF579917AC9999B4136C030FDCB6121E6F7222227206EBA69DEA5E7DDC7F4718E24E3E4D6D17A81F18E0D376292ED3BB744C66B9ED4BC90F6A04E953B952F794F01372FA88558228C70C97C01D5350EDEE0BEBC99BBD696AE2EFAAB1A0767DCAB15C52821B3243388CE729957668B385A050651F38702C5301A92180A8B84FDF30A74A23E34D9690EEC35A4B644B97DD1558933D7D3DAFF826C942882E223C79EEAE9835F972C273139C396E519D124B6ABBE233548EE1B00B87F7791611DF2E47343368D333C071E231F82914AAE51CEAE790410A6D11D6B82067A9847C945E0BB32310F8370C81636FF68BE65137C3FA912E4C1147F49946C198E1E15E04B8FC7AFFC8465A182E81976C5ED5C2D07F3F6AA25ED27FAC527D6126213BCABC49E102D35AF81E2A694AF0EF83DF6A687E8F3DEEC076BE08A7CD1A3B81C4997136880DB4E7E37B56082F10702F0BB646C7C8A760E297E2A39129BC4A3D0EFB9C3FA2611F5E545F2DC52E013FC49353553F46DEBB59817E18B701689B7A755E609A1B521D72DAE5CBCCE7059E8DA977C97CC87ED8118A2A0011B5ECCCB53785EBDD8986B0A3B36538BBCF4C27DCA06A4B35A9F9920439A35445A0703B34269EB2652999D041912810C06C5742B2AC9B23522D6A2AA3F38A699170B90EAE64509BBD00306C6AFB78AF35EE0D0B504500D5A2AECC0170C2B97620B4796CF538B6D867297F8EC1B08B2F4AFD3534FD9775200BAC298A216AA2553964B7A259D738C84A4035A2BAD35F2AA67CA197D9BB0658ABAB4AF6261C74F18D3D98A5B22C24476FAA8DB9F4FF2621CA01F27C8AB6157F6A1E7F0900CB3F2EEE44D77AAEDC77F24B0E2288340E9A371ACB021407C3E089F61FF0F8469EC9FDFC53892B47CDD0E63748DFE8F814AF7755E6B08491B0CBF8A3A847A922798D28FC72CC9AF8F9299D7B59E1AD1054A98488DB158D471A2D66053FD017238A9B9114393CB4BFD48B8FAABF7E4139E62F533CCCFDD9189E2FFBBB8E488B25B13B17BBEDE9CD3C4A03 diff --git a/crypto/openssh/moduli.0 b/crypto/openssh/moduli.0 deleted file mode 100644 index 7d678b4..0000000 --- a/crypto/openssh/moduli.0 +++ /dev/null @@ -1,74 +0,0 @@ -MODULI(5) OpenBSD Programmer's Manual MODULI(5) - -NAME - moduli - Diffie-Hellman moduli - -DESCRIPTION - The /etc/moduli file contains prime numbers and generators for use by - sshd(8) in the Diffie-Hellman Group Exchange key exchange method. - - New moduli may be generated with ssh-keygen(1) using a two-step process. - An initial candidate generation pass, using ssh-keygen -G, calculates - numbers that are likely to be useful. A second primality testing pass, - using ssh-keygen -T, provides a high degree of assurance that the numbers - are prime and are safe for use in Diffie-Hellman operations by sshd(8). - This moduli format is used as the output from each pass. - - The file consists of newline-separated records, one per modulus, - containing seven space-separated fields. These fields are as follows: - - timestamp The time that the modulus was last processed as - YYYYMMDDHHMMSS. - - type Decimal number specifying the internal structure of - the prime modulus. Supported types are: - - 0 Unknown, not tested. - 2 "Safe" prime; (p-1)/2 is also prime. - 4 Sophie Germain; 2p+1 is also prime. - - Moduli candidates initially produced by ssh-keygen(1) - are Sophie Germain primes (type 4). Further primality - testing with ssh-keygen(1) produces safe prime moduli - (type 2) that are ready for use in sshd(8). Other - types are not used by OpenSSH. - - tests Decimal number indicating the type of primality tests - that the number has been subjected to represented as a - bitmask of the following values: - - 0x00 Not tested. - 0x01 Composite number - not prime. - 0x02 Sieve of Eratosthenes. - 0x04 Probabilistic Miller-Rabin primality tests. - - The ssh-keygen(1) moduli candidate generation uses the - Sieve of Eratosthenes (flag 0x02). Subsequent - ssh-keygen(1) primality tests are Miller-Rabin tests - (flag 0x04). - - trials Decimal number indicating the number of primality - trials that have been performed on the modulus. - - size Decimal number indicating the size of the prime in - bits. - - generator The recommended generator for use with this modulus - (hexadecimal). - - modulus The modulus itself in hexadecimal. - - When performing Diffie-Hellman Group Exchange, sshd(8) first estimates - the size of the modulus required to produce enough Diffie-Hellman output - to sufficiently key the selected symmetric cipher. sshd(8) then randomly - selects a modulus from /etc/moduli that best meets the size requirement. - -SEE ALSO - ssh-keygen(1), sshd(8) - -STANDARDS - M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for - the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006, - 2006. - -OpenBSD 5.5 September 26, 2012 OpenBSD 5.5 diff --git a/crypto/openssh/moduli.c b/crypto/openssh/moduli.c index bb4dd7b..ed1bdc9 100644 --- a/crypto/openssh/moduli.c +++ b/crypto/openssh/moduli.c @@ -1,4 +1,4 @@ -/* $OpenBSD: moduli.c,v 1.28 2013/10/24 00:49:49 dtucker Exp $ */ +/* $OpenBSD: moduli.c,v 1.30 2015/01/20 23:14:00 deraadt Exp $ */ /* * Copyright 1994 Phil Karn * Copyright 1996-1998, 2003 William Allen Simpson @@ -39,7 +39,9 @@ #include "includes.h" -#include +#ifdef WITH_OPENSSL + +#include /* MAX */ #include #include @@ -52,6 +54,7 @@ #include #include #include +#include #include "xmalloc.h" #include "dh.h" @@ -447,11 +450,11 @@ static void write_checkpoint(char *cpfile, u_int32_t lineno) { FILE *fp; - char tmp[MAXPATHLEN]; + char tmp[PATH_MAX]; int r; r = snprintf(tmp, sizeof(tmp), "%s.XXXXXXXXXX", cpfile); - if (r == -1 || r >= MAXPATHLEN) { + if (r == -1 || r >= PATH_MAX) { logit("write_checkpoint: temp pathname too long"); return; } @@ -461,6 +464,7 @@ write_checkpoint(char *cpfile, u_int32_t lineno) } if ((fp = fdopen(r, "w")) == NULL) { logit("write_checkpoint: fdopen: %s", strerror(errno)); + unlink(tmp); close(r); return; } @@ -801,3 +805,5 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, return (res); } + +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/monitor.c b/crypto/openssh/monitor.c index af63490..a914209 100644 --- a/crypto/openssh/monitor.c +++ b/crypto/openssh/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.131 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.150 2015/06/22 23:42:16 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -28,7 +28,6 @@ #include "includes.h" #include -#include #include #include "openbsd-compat/sys-tree.h" #include @@ -40,9 +39,13 @@ #endif #include #include -#include +#ifdef HAVE_STDINT_H +#include +#endif #include #include +#include +#include #include #ifdef HAVE_POLL_H #include @@ -56,7 +59,9 @@ #include #endif +#ifdef WITH_OPENSSL #include +#endif #include "openbsd-compat/sys-queue.h" #include "atomicio.h" @@ -84,6 +89,7 @@ #include "sshlogin.h" #include "canohost.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "monitor.h" #include "monitor_mm.h" @@ -92,11 +98,12 @@ #endif #include "monitor_wrap.h" #include "monitor_fdpass.h" -#include "misc.h" #include "compat.h" #include "ssh2.h" #include "roaming.h" #include "authfd.h" +#include "match.h" +#include "ssherr.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; @@ -105,38 +112,13 @@ static Gssctxt *gsscontext = NULL; /* Imports */ extern ServerOptions options; extern u_int utmp_len; -extern Newkeys *current_keys[]; -extern z_stream incoming_stream; -extern z_stream outgoing_stream; extern u_char session_id[]; extern Buffer auth_debug; extern int auth_debug_init; extern Buffer loginmsg; /* State exported from the child */ - -struct { - z_stream incoming; - z_stream outgoing; - u_char *keyin; - u_int keyinlen; - u_char *keyout; - u_int keyoutlen; - u_char *ivin; - u_int ivinlen; - u_char *ivout; - u_int ivoutlen; - u_char *ssh1key; - u_int ssh1keylen; - int ssh1cipher; - int ssh1protoflags; - u_char *input; - u_int ilen; - u_char *output; - u_int olen; - u_int64_t sent_bytes; - u_int64_t recv_bytes; -} child_state; +static struct sshbuf *child_state; /* Functions on the monitor that answer unprivileged requests */ @@ -185,7 +167,10 @@ int mm_answer_audit_command(int, Buffer *); static int monitor_read_log(struct monitor *); static Authctxt *authctxt; + +#ifdef WITH_SSH1 static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ +#endif /* local state for key verify */ static u_char *key_blob = NULL; @@ -215,7 +200,9 @@ struct mon_table { #define MON_PERMIT 0x1000 /* Request is permitted */ struct mon_table mon_dispatch_proto20[] = { +#ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, +#endif {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, @@ -252,7 +239,9 @@ struct mon_table mon_dispatch_proto20[] = { }; struct mon_table mon_dispatch_postauth20[] = { +#ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, +#endif {MONITOR_REQ_SIGN, 0, mm_answer_sign}, {MONITOR_REQ_PTY, 0, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, @@ -265,6 +254,7 @@ struct mon_table mon_dispatch_postauth20[] = { }; struct mon_table mon_dispatch_proto15[] = { +#ifdef WITH_SSH1 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, @@ -292,10 +282,12 @@ struct mon_table mon_dispatch_proto15[] = { #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, #endif +#endif /* WITH_SSH1 */ {0, 0, NULL} }; struct mon_table mon_dispatch_postauth15[] = { +#ifdef WITH_SSH1 {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, @@ -303,6 +295,7 @@ struct mon_table mon_dispatch_postauth15[] = { {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, #endif +#endif /* WITH_SSH1 */ {0, 0, NULL} }; @@ -411,7 +404,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { auth_log(authctxt, authenticated, partial, auth_method, auth_submethod); - if (!authenticated) + if (!partial && !authenticated) authctxt->failures++; } } @@ -457,6 +450,9 @@ monitor_child_postauth(struct monitor *pmonitor) signal(SIGHUP, &monitor_child_handler); signal(SIGTERM, &monitor_child_handler); signal(SIGINT, &monitor_child_handler); +#ifdef SIGXFSZ + signal(SIGXFSZ, SIG_IGN); +#endif if (compat20) { mon_dispatch = mon_dispatch_postauth20; @@ -487,6 +483,27 @@ monitor_sync(struct monitor *pmonitor) } } +/* Allocation functions for zlib */ +static void * +mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) +{ + size_t len = (size_t) size * ncount; + void *address; + + if (len == 0 || ncount > SIZE_MAX / size) + fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); + + address = mm_malloc(mm, len); + + return (address); +} + +static void +mm_zfree(struct mm_master *mm, void *address) +{ + mm_free(mm, address); +} + static int monitor_read_log(struct monitor *pmonitor) { @@ -630,6 +647,7 @@ monitor_reset_key_state(void) hostbased_chost = NULL; } +#ifdef WITH_OPENSSL int mm_answer_moduli(int sock, Buffer *m) { @@ -664,29 +682,62 @@ mm_answer_moduli(int sock, Buffer *m) mm_request_send(sock, MONITOR_ANS_MODULI, m); return (0); } - -extern AuthenticationConnection *auth_conn; +#endif int mm_answer_sign(int sock, Buffer *m) { - Key *key; + struct ssh *ssh = active_state; /* XXX */ + extern int auth_sock; /* XXX move to state struct? */ + struct sshkey *key; + struct sshbuf *sigbuf; u_char *p; u_char *signature; - u_int siglen, datlen; - int keyid; + size_t datlen, siglen; + int r, keyid, is_proof = 0; + const char proof_req[] = "hostkeys-prove-00@openssh.com"; debug3("%s", __func__); - keyid = buffer_get_int(m); - p = buffer_get_string(m, &datlen); + if ((r = sshbuf_get_u32(m, &keyid)) != 0 || + (r = sshbuf_get_string(m, &p, &datlen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), * SHA384 (48 bytes) and SHA512 (64 bytes). + * + * Otherwise, verify the signature request is for a hostkey + * proof. + * + * XXX perform similar check for KEX signature requests too? + * it's not trivial, since what is signed is the hash, rather + * than the full kex structure... */ - if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) - fatal("%s: data length incorrect: %u", __func__, datlen); + if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) { + /* + * Construct expected hostkey proof and compare it to what + * the client sent us. + */ + if (session_id2_len == 0) /* hostkeys is never first */ + fatal("%s: bad data length: %zu", __func__, datlen); + if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) + fatal("%s: no hostkey for index %d", __func__, keyid); + if ((sigbuf = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || + (r = sshbuf_put_string(sigbuf, session_id2, + session_id2_len) != 0) || + (r = sshkey_puts(key, sigbuf)) != 0) + fatal("%s: couldn't prepare private key " + "proof buffer: %s", __func__, ssh_err(r)); + if (datlen != sshbuf_len(sigbuf) || + memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) + fatal("%s: bad data length: %zu, hostkey proof len %zu", + __func__, datlen, sshbuf_len(sigbuf)); + sshbuf_free(sigbuf); + is_proof = 1; + } /* save session id, it will be passed on the first call */ if (session_id2_len == 0) { @@ -696,20 +747,26 @@ mm_answer_sign(int sock, Buffer *m) } if ((key = get_hostkey_by_index(keyid)) != NULL) { - if (key_sign(key, &signature, &siglen, p, datlen) < 0) - fatal("%s: key_sign failed", __func__); - } else if ((key = get_hostkey_public_by_index(keyid)) != NULL && - auth_conn != NULL) { - if (ssh_agent_sign(auth_conn, key, &signature, &siglen, p, - datlen) < 0) - fatal("%s: ssh_agent_sign failed", __func__); + if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, + datafellows)) != 0) + fatal("%s: sshkey_sign failed: %s", + __func__, ssh_err(r)); + } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && + auth_sock > 0) { + if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, + p, datlen, datafellows)) != 0) { + fatal("%s: ssh_agent_sign failed: %s", + __func__, ssh_err(r)); + } } else fatal("%s: no hostkey from index %d", __func__, keyid); - debug3("%s: signature %p(%u)", __func__, signature, siglen); + debug3("%s: %s signature %p(%zu)", __func__, + is_proof ? "KEX" : "hostkey proof", signature, siglen); - buffer_clear(m); - buffer_put_string(m, signature, siglen); + sshbuf_reset(m); + if ((r = sshbuf_put_string(m, signature, siglen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(p); free(signature); @@ -1128,7 +1185,7 @@ mm_answer_keyallowed(int sock, Buffer *m) Key *key; char *cuser, *chost; u_char *blob; - u_int bloblen; + u_int bloblen, pubkey_auth_attempt; enum mm_keytype type = 0; int allowed = 0; @@ -1138,6 +1195,7 @@ mm_answer_keyallowed(int sock, Buffer *m) cuser = buffer_get_string(m, NULL); chost = buffer_get_string(m, NULL); blob = buffer_get_string(m, &bloblen); + pubkey_auth_attempt = buffer_get_int(m); key = key_from_blob(blob, bloblen); @@ -1148,17 +1206,29 @@ mm_answer_keyallowed(int sock, Buffer *m) debug3("%s: key_from_blob: %p", __func__, key); if (key != NULL && authctxt->valid) { + /* These should not make it past the privsep child */ + if (key_type_plain(key->type) == KEY_RSA && + (datafellows & SSH_BUG_RSASIGMD5) != 0) + fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); + switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && - user_key_allowed(authctxt->pw, key); + !auth2_userkey_already_used(authctxt, key) && + match_pattern_list(sshkey_ssh_name(key), + options.pubkey_key_types, 0) == 1 && + user_key_allowed(authctxt->pw, key, + pubkey_auth_attempt); pubkey_auth_info(authctxt, key, NULL); auth_method = "publickey"; - if (options.pubkey_authentication && allowed != 1) + if (options.pubkey_authentication && + (!pubkey_auth_attempt || allowed != 1)) auth_clear_options(); break; case MM_HOSTKEY: allowed = options.hostbased_authentication && + match_pattern_list(sshkey_ssh_name(key), + options.hostbased_key_types, 0) == 1 && hostbased_key_allowed(authctxt->pw, cuser, chost, key); pubkey_auth_info(authctxt, key, @@ -1166,6 +1236,7 @@ mm_answer_keyallowed(int sock, Buffer *m) cuser, chost); auth_method = "hostbased"; break; +#ifdef WITH_SSH1 case MM_RSAHOSTKEY: key->type = KEY_RSA1; /* XXX */ allowed = options.rhosts_rsa_authentication && @@ -1175,6 +1246,7 @@ mm_answer_keyallowed(int sock, Buffer *m) auth_clear_options(); auth_method = "rsa"; break; +#endif default: fatal("%s: unknown key type %d", __func__, type); break; @@ -1376,7 +1448,12 @@ mm_answer_keyverify(int sock, Buffer *m) debug3("%s: key %p signature %s", __func__, key, (verified == 1) ? "verified" : "unverified"); - key_free(key); + /* If auth was successful then record key to ensure it isn't reused */ + if (verified == 1) + auth2_record_userkey(authctxt, key); + else + key_free(key); + free(blob); free(signature); free(data); @@ -1398,6 +1475,9 @@ mm_record_login(Session *s, struct passwd *pw) socklen_t fromlen; struct sockaddr_storage from; + if (options.use_login) + return; + /* * Get IP address of client. If the connection is not a socket, let * the address be 0.0.0.0. @@ -1511,6 +1591,7 @@ mm_answer_pty_cleanup(int sock, Buffer *m) return (0); } +#ifdef WITH_SSH1 int mm_answer_sesskey(int sock, Buffer *m) { @@ -1688,6 +1769,7 @@ mm_answer_rsa_response(int sock, Buffer *m) return (success); } +#endif int mm_answer_term(int sock, Buffer *req) @@ -1760,101 +1842,40 @@ mm_answer_audit_command(int socket, Buffer *m) void monitor_apply_keystate(struct monitor *pmonitor) { - if (compat20) { - set_newkeys(MODE_IN); - set_newkeys(MODE_OUT); - } else { - packet_set_protocol_flags(child_state.ssh1protoflags); - packet_set_encryption_key(child_state.ssh1key, - child_state.ssh1keylen, child_state.ssh1cipher); - free(child_state.ssh1key); - } - - /* for rc4 and other stateful ciphers */ - packet_set_keycontext(MODE_OUT, child_state.keyout); - free(child_state.keyout); - packet_set_keycontext(MODE_IN, child_state.keyin); - free(child_state.keyin); - - if (!compat20) { - packet_set_iv(MODE_OUT, child_state.ivout); - free(child_state.ivout); - packet_set_iv(MODE_IN, child_state.ivin); - free(child_state.ivin); + struct ssh *ssh = active_state; /* XXX */ + struct kex *kex; + int r; + + debug3("%s: packet_set_state", __func__); + if ((r = ssh_packet_set_state(ssh, child_state)) != 0) + fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); + sshbuf_free(child_state); + child_state = NULL; + + if ((kex = ssh->kex) != 0) { + /* XXX set callbacks */ +#ifdef WITH_OPENSSL + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; +# ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kexecdh_server; +# endif +#endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->load_host_public_key=&get_hostkey_public_by_type; + kex->load_host_private_key=&get_hostkey_private_by_type; + kex->host_key_index=&get_hostkey_index; + kex->sign = sshd_hostkey_sign; } - memcpy(&incoming_stream, &child_state.incoming, - sizeof(incoming_stream)); - memcpy(&outgoing_stream, &child_state.outgoing, - sizeof(outgoing_stream)); - /* Update with new address */ - if (options.compression) - mm_init_compression(pmonitor->m_zlib); - - if (options.rekey_limit || options.rekey_interval) - packet_set_rekey_limits((u_int32_t)options.rekey_limit, - (time_t)options.rekey_interval); - - /* Network I/O buffers */ - /* XXX inefficient for large buffers, need: buffer_init_from_string */ - buffer_clear(packet_get_input()); - buffer_append(packet_get_input(), child_state.input, child_state.ilen); - explicit_bzero(child_state.input, child_state.ilen); - free(child_state.input); - - buffer_clear(packet_get_output()); - buffer_append(packet_get_output(), child_state.output, - child_state.olen); - explicit_bzero(child_state.output, child_state.olen); - free(child_state.output); - - /* Roaming */ - if (compat20) - roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes); -} - -static Kex * -mm_get_kex(Buffer *m) -{ - Kex *kex; - void *blob; - u_int bloblen; - - kex = xcalloc(1, sizeof(*kex)); - kex->session_id = buffer_get_string(m, &kex->session_id_len); - if (session_id2 == NULL || - kex->session_id_len != session_id2_len || - timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0) - fatal("mm_get_get: internal error: bad session id"); - kex->we_need = buffer_get_int(m); - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; - kex->kex[KEX_C25519_SHA256] = kexc25519_server; - kex->server = 1; - kex->hostkey_type = buffer_get_int(m); - kex->kex_type = buffer_get_int(m); - blob = buffer_get_string(m, &bloblen); - buffer_init(&kex->my); - buffer_append(&kex->my, blob, bloblen); - free(blob); - blob = buffer_get_string(m, &bloblen); - buffer_init(&kex->peer); - buffer_append(&kex->peer, blob, bloblen); - free(blob); - kex->done = 1; - kex->flags = buffer_get_int(m); - kex->client_version_string = buffer_get_string(m, NULL); - kex->server_version_string = buffer_get_string(m, NULL); - kex->load_host_public_key=&get_hostkey_public_by_type; - kex->load_host_private_key=&get_hostkey_private_by_type; - kex->host_key_index=&get_hostkey_index; - kex->sign = sshd_hostkey_sign; - - return (kex); + if (options.compression) { + ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib, + (ssh_packet_comp_alloc_func *)mm_zalloc, + (ssh_packet_comp_free_func *)mm_zfree); + } } /* This function requries careful sanity checking */ @@ -1862,117 +1883,15 @@ mm_get_kex(Buffer *m) void mm_get_keystate(struct monitor *pmonitor) { - Buffer m; - u_char *blob, *p; - u_int bloblen, plen; - u_int32_t seqnr, packets; - u_int64_t blocks, bytes; - debug3("%s: Waiting for new keys", __func__); - buffer_init(&m); - mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); - if (!compat20) { - child_state.ssh1protoflags = buffer_get_int(&m); - child_state.ssh1cipher = buffer_get_int(&m); - child_state.ssh1key = buffer_get_string(&m, - &child_state.ssh1keylen); - child_state.ivout = buffer_get_string(&m, - &child_state.ivoutlen); - child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); - goto skip; - } else { - /* Get the Kex for rekeying */ - *pmonitor->m_pkex = mm_get_kex(&m); - } - - blob = buffer_get_string(&m, &bloblen); - current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); - free(blob); - - debug3("%s: Waiting for second key", __func__); - blob = buffer_get_string(&m, &bloblen); - current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); - free(blob); - - /* Now get sequence numbers for the packets */ - seqnr = buffer_get_int(&m); - blocks = buffer_get_int64(&m); - packets = buffer_get_int(&m); - bytes = buffer_get_int64(&m); - packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes); - seqnr = buffer_get_int(&m); - blocks = buffer_get_int64(&m); - packets = buffer_get_int(&m); - bytes = buffer_get_int64(&m); - packet_set_state(MODE_IN, seqnr, blocks, packets, bytes); - - skip: - /* Get the key context */ - child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); - child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); - - debug3("%s: Getting compression state", __func__); - /* Get compression state */ - p = buffer_get_string(&m, &plen); - if (plen != sizeof(child_state.outgoing)) - fatal("%s: bad request size", __func__); - memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); - free(p); - - p = buffer_get_string(&m, &plen); - if (plen != sizeof(child_state.incoming)) - fatal("%s: bad request size", __func__); - memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); - free(p); - - /* Network I/O buffers */ - debug3("%s: Getting Network I/O buffers", __func__); - child_state.input = buffer_get_string(&m, &child_state.ilen); - child_state.output = buffer_get_string(&m, &child_state.olen); - - /* Roaming */ - if (compat20) { - child_state.sent_bytes = buffer_get_int64(&m); - child_state.recv_bytes = buffer_get_int64(&m); - } - - buffer_free(&m); -} - - -/* Allocation functions for zlib */ -void * -mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) -{ - size_t len = (size_t) size * ncount; - void *address; - - if (len == 0 || ncount > SIZE_T_MAX / size) - fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size); - - address = mm_malloc(mm, len); - - return (address); + if ((child_state = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, + child_state); + debug3("%s: GOT new keys", __func__); } -void -mm_zfree(struct mm_master *mm, void *address) -{ - mm_free(mm, address); -} - -void -mm_init_compression(struct mm_master *mm) -{ - outgoing_stream.zalloc = (alloc_func)mm_zalloc; - outgoing_stream.zfree = (free_func)mm_zfree; - outgoing_stream.opaque = mm; - - incoming_stream.zalloc = (alloc_func)mm_zalloc; - incoming_stream.zfree = (free_func)mm_zfree; - incoming_stream.opaque = mm; -} /* XXX */ @@ -2009,6 +1928,7 @@ monitor_openfds(struct monitor *mon, int do_logfds) struct monitor * monitor_init(void) { + struct ssh *ssh = active_state; /* XXX */ struct monitor *mon; mon = xcalloc(1, sizeof(*mon)); @@ -2021,7 +1941,9 @@ monitor_init(void) mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); /* Compression needs to share state across borders */ - mm_init_compression(mon->m_zlib); + ssh_packet_set_compress_hooks(ssh, mon->m_zlib, + (ssh_packet_comp_alloc_func *)mm_zalloc, + (ssh_packet_comp_free_func *)mm_zfree); } return mon; diff --git a/crypto/openssh/monitor.h b/crypto/openssh/monitor.h index 5bc41b5..93b8b66 100644 --- a/crypto/openssh/monitor.h +++ b/crypto/openssh/monitor.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.h,v 1.18 2014/01/29 06:18:35 djm Exp $ */ +/* $OpenBSD: monitor.h,v 1.19 2015/01/19 19:52:16 markus Exp $ */ /* * Copyright 2002 Niels Provos @@ -75,7 +75,7 @@ struct monitor { int m_log_sendfd; struct mm_master *m_zback; struct mm_master *m_zlib; - struct Kex **m_pkex; + struct kex **m_pkex; pid_t m_pid; }; diff --git a/crypto/openssh/monitor_fdpass.c b/crypto/openssh/monitor_fdpass.c index 7eb6f5c..2ddd807 100644 --- a/crypto/openssh/monitor_fdpass.c +++ b/crypto/openssh/monitor_fdpass.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_fdpass.c,v 1.19 2010/01/12 00:58:25 djm Exp $ */ +/* $OpenBSD: monitor_fdpass.c,v 1.20 2015/02/25 23:05:47 djm Exp $ */ /* * Copyright 2001 Niels Provos * All rights reserved. @@ -34,12 +34,17 @@ #endif #include -#ifdef HAVE_POLL_H -#include -#endif #include #include +#ifdef HAVE_POLL_H +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif +#endif + #include "log.h" #include "monitor_fdpass.h" @@ -65,6 +70,7 @@ mm_send_fd(int sock, int fd) msg.msg_accrights = (caddr_t)&fd; msg.msg_accrightslen = sizeof(fd); #else + memset(&cmsgbuf, 0, sizeof(cmsgbuf)); msg.msg_control = (caddr_t)&cmsgbuf.buf; msg.msg_controllen = sizeof(cmsgbuf.buf); cmsg = CMSG_FIRSTHDR(&msg); @@ -131,6 +137,7 @@ mm_receive_fd(int sock) msg.msg_accrights = (caddr_t)&fd; msg.msg_accrightslen = sizeof(fd); #else + memset(&cmsgbuf, 0, sizeof(cmsgbuf)); msg.msg_control = &cmsgbuf.buf; msg.msg_controllen = sizeof(cmsgbuf.buf); #endif diff --git a/crypto/openssh/monitor_mm.c b/crypto/openssh/monitor_mm.c index 0ba0658..aa47b2e 100644 --- a/crypto/openssh/monitor_mm.c +++ b/crypto/openssh/monitor_mm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_mm.c,v 1.19 2014/01/04 17:50:55 tedu Exp $ */ +/* $OpenBSD: monitor_mm.c,v 1.21 2015/02/06 23:21:59 millert Exp $ */ /* * Copyright 2002 Niels Provos * All rights reserved. @@ -30,12 +30,14 @@ #ifdef HAVE_SYS_MMAN_H #include #endif -#include #include "openbsd-compat/sys-tree.h" #include #include #include +#ifdef HAVE_STDINT_H +#include +#endif #include #include @@ -176,7 +178,7 @@ mm_malloc(struct mm_master *mm, size_t size) if (size == 0) fatal("mm_malloc: try to allocate 0 space"); - if (size > SIZE_T_MAX - MM_MINSIZE + 1) + if (size > SIZE_MAX - MM_MINSIZE + 1) fatal("mm_malloc: size too big"); size = ((size + (MM_MINSIZE - 1)) / MM_MINSIZE) * MM_MINSIZE; diff --git a/crypto/openssh/monitor_wrap.c b/crypto/openssh/monitor_wrap.c index b2bc8dd..eac421b 100644 --- a/crypto/openssh/monitor_wrap.c +++ b/crypto/openssh/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.79 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.85 2015/05/01 03:23:51 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -38,14 +38,18 @@ #include #include +#ifdef WITH_OPENSSL #include #include #include +#endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" +#ifdef WITH_OPENSSL #include "dh.h" +#endif #include "buffer.h" #include "key.h" #include "cipher.h" @@ -78,6 +82,8 @@ #include "servconf.h" #include "roaming.h" +#include "ssherr.h" + /* Imports */ extern int compat20; extern z_stream incoming_stream; @@ -174,6 +180,7 @@ mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m) rtype, type); } +#ifdef WITH_OPENSSL DH * mm_choose_dh(int min, int nbits, int max) { @@ -207,17 +214,19 @@ mm_choose_dh(int min, int nbits, int max) return (dh_new_group(g, p)); } +#endif int -mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) +mm_key_sign(Key *key, u_char **sigp, u_int *lenp, + const u_char *data, u_int datalen) { - Kex *kex = *pmonitor->m_pkex; + struct kex *kex = *pmonitor->m_pkex; Buffer m; debug3("%s entering", __func__); buffer_init(&m); - buffer_put_int(&m, kex->host_key_index(key)); + buffer_put_int(&m, kex->host_key_index(key, 0, active_state)); buffer_put_string(&m, data, datalen); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); @@ -362,16 +371,17 @@ mm_auth_password(Authctxt *authctxt, char *password) } int -mm_user_key_allowed(struct passwd *pw, Key *key) +mm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt) { - return (mm_key_allowed(MM_USERKEY, NULL, NULL, key)); + return (mm_key_allowed(MM_USERKEY, NULL, NULL, key, + pubkey_auth_attempt)); } int mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host, Key *key) { - return (mm_key_allowed(MM_HOSTKEY, user, host, key)); + return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0)); } int @@ -381,13 +391,14 @@ mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user, int ret; key->type = KEY_RSA; /* XXX hack for key_to_blob */ - ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key); + ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key, 0); key->type = KEY_RSA1; return (ret); } int -mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key) +mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key, + int pubkey_auth_attempt) { Buffer m; u_char *blob; @@ -405,6 +416,7 @@ mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key) buffer_put_cstring(&m, user ? user : ""); buffer_put_cstring(&m, host ? host : ""); buffer_put_string(&m, blob, len); + buffer_put_int(&m, pubkey_auth_attempt); free(blob); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m); @@ -462,239 +474,21 @@ mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) return (verified); } -/* Export key state after authentication */ -Newkeys * -mm_newkeys_from_blob(u_char *blob, int blen) -{ - Buffer b; - u_int len; - Newkeys *newkey = NULL; - Enc *enc; - Mac *mac; - Comp *comp; - - debug3("%s: %p(%d)", __func__, blob, blen); -#ifdef DEBUG_PK - dump_base64(stderr, blob, blen); -#endif - buffer_init(&b); - buffer_append(&b, blob, blen); - - newkey = xcalloc(1, sizeof(*newkey)); - enc = &newkey->enc; - mac = &newkey->mac; - comp = &newkey->comp; - - /* Enc structure */ - enc->name = buffer_get_string(&b, NULL); - buffer_get(&b, &enc->cipher, sizeof(enc->cipher)); - enc->enabled = buffer_get_int(&b); - enc->block_size = buffer_get_int(&b); - enc->key = buffer_get_string(&b, &enc->key_len); - enc->iv = buffer_get_string(&b, &enc->iv_len); - - if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher) - fatal("%s: bad cipher name %s or pointer %p", __func__, - enc->name, enc->cipher); - - /* Mac structure */ - if (cipher_authlen(enc->cipher) == 0) { - mac->name = buffer_get_string(&b, NULL); - if (mac->name == NULL || mac_setup(mac, mac->name) == -1) - fatal("%s: can not setup mac %s", __func__, mac->name); - mac->enabled = buffer_get_int(&b); - mac->key = buffer_get_string(&b, &len); - if (len > mac->key_len) - fatal("%s: bad mac key length: %u > %d", __func__, len, - mac->key_len); - mac->key_len = len; - } - - /* Comp structure */ - comp->type = buffer_get_int(&b); - comp->enabled = buffer_get_int(&b); - comp->name = buffer_get_string(&b, NULL); - - len = buffer_len(&b); - if (len != 0) - error("newkeys_from_blob: remaining bytes in blob %u", len); - buffer_free(&b); - return (newkey); -} - -int -mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp) -{ - Buffer b; - int len; - Enc *enc; - Mac *mac; - Comp *comp; - Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode); - - debug3("%s: converting %p", __func__, newkey); - - if (newkey == NULL) { - error("%s: newkey == NULL", __func__); - return 0; - } - enc = &newkey->enc; - mac = &newkey->mac; - comp = &newkey->comp; - - buffer_init(&b); - /* Enc structure */ - buffer_put_cstring(&b, enc->name); - /* The cipher struct is constant and shared, you export pointer */ - buffer_append(&b, &enc->cipher, sizeof(enc->cipher)); - buffer_put_int(&b, enc->enabled); - buffer_put_int(&b, enc->block_size); - buffer_put_string(&b, enc->key, enc->key_len); - packet_get_keyiv(mode, enc->iv, enc->iv_len); - buffer_put_string(&b, enc->iv, enc->iv_len); - - /* Mac structure */ - if (cipher_authlen(enc->cipher) == 0) { - buffer_put_cstring(&b, mac->name); - buffer_put_int(&b, mac->enabled); - buffer_put_string(&b, mac->key, mac->key_len); - } - - /* Comp structure */ - buffer_put_int(&b, comp->type); - buffer_put_int(&b, comp->enabled); - buffer_put_cstring(&b, comp->name); - - len = buffer_len(&b); - if (lenp != NULL) - *lenp = len; - if (blobp != NULL) { - *blobp = xmalloc(len); - memcpy(*blobp, buffer_ptr(&b), len); - } - explicit_bzero(buffer_ptr(&b), len); - buffer_free(&b); - return len; -} - -static void -mm_send_kex(Buffer *m, Kex *kex) -{ - buffer_put_string(m, kex->session_id, kex->session_id_len); - buffer_put_int(m, kex->we_need); - buffer_put_int(m, kex->hostkey_type); - buffer_put_int(m, kex->kex_type); - buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my)); - buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer)); - buffer_put_int(m, kex->flags); - buffer_put_cstring(m, kex->client_version_string); - buffer_put_cstring(m, kex->server_version_string); -} - void mm_send_keystate(struct monitor *monitor) { - Buffer m, *input, *output; - u_char *blob, *p; - u_int bloblen, plen; - u_int32_t seqnr, packets; - u_int64_t blocks, bytes; - - buffer_init(&m); - - if (!compat20) { - u_char iv[24]; - u_char *key; - u_int ivlen, keylen; - - buffer_put_int(&m, packet_get_protocol_flags()); - - buffer_put_int(&m, packet_get_ssh1_cipher()); - - debug3("%s: Sending ssh1 KEY+IV", __func__); - keylen = packet_get_encryption_key(NULL); - key = xmalloc(keylen+1); /* add 1 if keylen == 0 */ - keylen = packet_get_encryption_key(key); - buffer_put_string(&m, key, keylen); - explicit_bzero(key, keylen); - free(key); - - ivlen = packet_get_keyiv_len(MODE_OUT); - packet_get_keyiv(MODE_OUT, iv, ivlen); - buffer_put_string(&m, iv, ivlen); - ivlen = packet_get_keyiv_len(MODE_IN); - packet_get_keyiv(MODE_IN, iv, ivlen); - buffer_put_string(&m, iv, ivlen); - goto skip; - } else { - /* Kex for rekeying */ - mm_send_kex(&m, *monitor->m_pkex); - } - - debug3("%s: Sending new keys: %p %p", - __func__, packet_get_newkeys(MODE_OUT), - packet_get_newkeys(MODE_IN)); - - /* Keys from Kex */ - if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen)) - fatal("%s: conversion of newkeys failed", __func__); - - buffer_put_string(&m, blob, bloblen); - free(blob); - - if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) - fatal("%s: conversion of newkeys failed", __func__); - - buffer_put_string(&m, blob, bloblen); - free(blob); - - packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes); - buffer_put_int(&m, seqnr); - buffer_put_int64(&m, blocks); - buffer_put_int(&m, packets); - buffer_put_int64(&m, bytes); - packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes); - buffer_put_int(&m, seqnr); - buffer_put_int64(&m, blocks); - buffer_put_int(&m, packets); - buffer_put_int64(&m, bytes); - - debug3("%s: New keys have been sent", __func__); - skip: - /* More key context */ - plen = packet_get_keycontext(MODE_OUT, NULL); - p = xmalloc(plen+1); - packet_get_keycontext(MODE_OUT, p); - buffer_put_string(&m, p, plen); - free(p); - - plen = packet_get_keycontext(MODE_IN, NULL); - p = xmalloc(plen+1); - packet_get_keycontext(MODE_IN, p); - buffer_put_string(&m, p, plen); - free(p); - - /* Compression state */ - debug3("%s: Sending compression state", __func__); - buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream)); - buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream)); - - /* Network I/O buffers */ - input = (Buffer *)packet_get_input(); - output = (Buffer *)packet_get_output(); - buffer_put_string(&m, buffer_ptr(input), buffer_len(input)); - buffer_put_string(&m, buffer_ptr(output), buffer_len(output)); - - /* Roaming */ - if (compat20) { - buffer_put_int64(&m, get_sent_bytes()); - buffer_put_int64(&m, get_recv_bytes()); - } - - mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); + struct ssh *ssh = active_state; /* XXX */ + struct sshbuf *m; + int r; + + if ((m = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = ssh_packet_get_state(ssh, m)) != 0) + fatal("%s: get_state failed: %s", + __func__, ssh_err(r)); + mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m); debug3("%s: Finished sending state", __func__); - - buffer_free(&m); + sshbuf_free(m); } int @@ -911,6 +705,7 @@ mm_terminate(void) buffer_free(&m); } +#ifdef WITH_SSH1 int mm_ssh1_session_key(BIGNUM *num) { @@ -930,6 +725,7 @@ mm_ssh1_session_key(BIGNUM *num) return (rsafail); } +#endif static void mm_chall_setup(char **name, char **infotxt, u_int *numprompts, @@ -1077,6 +873,7 @@ mm_ssh1_session_id(u_char session_id[16]) buffer_free(&m); } +#ifdef WITH_SSH1 int mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) { @@ -1172,6 +969,7 @@ mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) return (success); } +#endif #ifdef SSH_AUDIT_EVENTS void diff --git a/crypto/openssh/monitor_wrap.h b/crypto/openssh/monitor_wrap.h index 18c2501..de4a08f 100644 --- a/crypto/openssh/monitor_wrap.h +++ b/crypto/openssh/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.24 2014/01/29 06:18:35 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.27 2015/05/01 03:23:51 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -40,13 +40,13 @@ struct Authctxt; void mm_log_handler(LogLevel, const char *, void *); int mm_is_monitor(void); DH *mm_choose_dh(int, int, int); -int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); +int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_int); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(const char *); char *mm_auth2_read_banner(void); int mm_auth_password(struct Authctxt *, char *); -int mm_key_allowed(enum mm_keytype, char *, char *, Key *); -int mm_user_key_allowed(struct passwd *, Key *); +int mm_key_allowed(enum mm_keytype, char *, char *, Key *, int); +int mm_user_key_allowed(struct passwd *, Key *, int); int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *); int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); @@ -87,7 +87,7 @@ void mm_ssh1_session_id(u_char *); int mm_ssh1_session_key(BIGNUM *); /* Key export functions */ -struct Newkeys *mm_newkeys_from_blob(u_char *, int); +struct newkeys *mm_newkeys_from_blob(u_char *, int); int mm_newkeys_to_blob(int, u_char **, u_int *); void monitor_apply_keystate(struct monitor *); @@ -103,9 +103,6 @@ int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); int mm_skey_respond(void *, u_int, char **); /* zlib allocation hooks */ - -void *mm_zalloc(struct mm_master *, u_int, u_int); -void mm_zfree(struct mm_master *, void *); void mm_init_compression(struct mm_master *); #endif /* _MM_WRAP_H_ */ diff --git a/crypto/openssh/msg.c b/crypto/openssh/msg.c index cd5f98c..5a7b8ca 100644 --- a/crypto/openssh/msg.c +++ b/crypto/openssh/msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msg.c,v 1.15 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: msg.c,v 1.16 2015/01/15 09:40:00 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -34,17 +34,18 @@ #include #include -#include "buffer.h" +#include "sshbuf.h" +#include "ssherr.h" #include "log.h" #include "atomicio.h" #include "msg.h" #include "misc.h" int -ssh_msg_send(int fd, u_char type, Buffer *m) +ssh_msg_send(int fd, u_char type, struct sshbuf *m) { u_char buf[5]; - u_int mlen = buffer_len(m); + u_int mlen = sshbuf_len(m); debug3("ssh_msg_send: type %u", (unsigned int)type & 0xff); @@ -54,7 +55,7 @@ ssh_msg_send(int fd, u_char type, Buffer *m) error("ssh_msg_send: write"); return (-1); } - if (atomicio(vwrite, fd, buffer_ptr(m), mlen) != mlen) { + if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(m), mlen) != mlen) { error("ssh_msg_send: write"); return (-1); } @@ -62,10 +63,11 @@ ssh_msg_send(int fd, u_char type, Buffer *m) } int -ssh_msg_recv(int fd, Buffer *m) +ssh_msg_recv(int fd, struct sshbuf *m) { - u_char buf[4]; + u_char buf[4], *p; u_int msg_len; + int r; debug3("ssh_msg_recv entering"); @@ -79,9 +81,12 @@ ssh_msg_recv(int fd, Buffer *m) error("ssh_msg_recv: read: bad msg_len %u", msg_len); return (-1); } - buffer_clear(m); - buffer_append_space(m, msg_len); - if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) { + sshbuf_reset(m); + if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) { + error("%s: buffer error: %s", __func__, ssh_err(r)); + return -1; + } + if (atomicio(read, fd, p, msg_len) != msg_len) { error("ssh_msg_recv: read: %s", strerror(errno)); return (-1); } diff --git a/crypto/openssh/msg.h b/crypto/openssh/msg.h index b0cb9b5..dfb3424 100644 --- a/crypto/openssh/msg.h +++ b/crypto/openssh/msg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: msg.h,v 1.4 2006/03/25 22:22:43 djm Exp $ */ +/* $OpenBSD: msg.h,v 1.5 2015/01/15 09:40:00 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -25,7 +25,8 @@ #ifndef SSH_MSG_H #define SSH_MSG_H -int ssh_msg_send(int, u_char, Buffer *); -int ssh_msg_recv(int, Buffer *); +struct sshbuf; +int ssh_msg_send(int, u_char, struct sshbuf *); +int ssh_msg_recv(int, struct sshbuf *); #endif diff --git a/crypto/openssh/mux.c b/crypto/openssh/mux.c index 4ebb033..1ab9339 100644 --- a/crypto/openssh/mux.c +++ b/crypto/openssh/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.44 2013/07/12 00:19:58 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.54 2015/08/19 23:18:26 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -34,7 +34,6 @@ __RCSID("$FreeBSD$"); #include -#include #include #include #include @@ -106,6 +105,11 @@ struct mux_session_confirm_ctx { u_int rid; }; +/* Context for stdio fwd open confirmation callback */ +struct mux_stdio_confirm_ctx { + u_int rid; +}; + /* Context for global channel callback */ struct mux_channel_confirm_ctx { u_int cid; /* channel id */ @@ -158,6 +162,7 @@ struct mux_master_state { #define MUX_FWD_DYNAMIC 3 static void mux_session_confirm(int, int, void *); +static void mux_stdio_confirm(int, int, void *); static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); @@ -346,7 +351,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) free(cp); continue; } - cctx->env = xrealloc(cctx->env, env_len + 2, + cctx->env = xreallocarray(cctx->env, env_len + 2, sizeof(*cctx->env)); cctx->env[env_len++] = cp; cctx->env[env_len] = NULL; @@ -510,29 +515,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r) } static char * -format_forward(u_int ftype, Forward *fwd) +format_forward(u_int ftype, struct Forward *fwd) { char *ret; switch (ftype) { case MUX_FWD_LOCAL: xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", + (fwd->listen_path != NULL) ? fwd->listen_path : (fwd->listen_host == NULL) ? - (options.gateway_ports ? "*" : "LOCALHOST") : + (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : fwd->listen_host, fwd->listen_port, + (fwd->connect_path != NULL) ? fwd->connect_path : fwd->connect_host, fwd->connect_port); break; case MUX_FWD_DYNAMIC: xasprintf(&ret, "dynamic forward %.200s:%d -> *", (fwd->listen_host == NULL) ? - (options.gateway_ports ? "*" : "LOCALHOST") : + (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : fwd->listen_host, fwd->listen_port); break; case MUX_FWD_REMOTE: xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", + (fwd->listen_path != NULL) ? fwd->listen_path : (fwd->listen_host == NULL) ? "LOCALHOST" : fwd->listen_host, fwd->listen_port, + (fwd->connect_path != NULL) ? fwd->connect_path : fwd->connect_host, fwd->connect_port); break; default: @@ -552,14 +561,18 @@ compare_host(const char *a, const char *b) } static int -compare_forward(Forward *a, Forward *b) +compare_forward(struct Forward *a, struct Forward *b) { if (!compare_host(a->listen_host, b->listen_host)) return 0; + if (!compare_host(a->listen_path, b->listen_path)) + return 0; if (a->listen_port != b->listen_port) return 0; if (!compare_host(a->connect_host, b->connect_host)) return 0; + if (!compare_host(a->connect_path, b->connect_path)) + return 0; if (a->connect_port != b->connect_port) return 0; @@ -571,7 +584,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) { struct mux_channel_confirm_ctx *fctx = ctxt; char *failmsg = NULL; - Forward *rfwd; + struct Forward *rfwd; Channel *c; Buffer out; @@ -581,18 +594,21 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) return; } buffer_init(&out); - if (fctx->fid >= options.num_remote_forwards) { + if (fctx->fid >= options.num_remote_forwards || + (options.remote_forwards[fctx->fid].connect_path == NULL && + options.remote_forwards[fctx->fid].connect_host == NULL)) { xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid); goto fail; } rfwd = &options.remote_forwards[fctx->fid]; debug("%s: %s for: listen %d, connect %s:%d", __func__, type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", - rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); + rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : + rfwd->connect_host, rfwd->connect_port); if (type == SSH2_MSG_REQUEST_SUCCESS) { if (rfwd->listen_port == 0) { rfwd->allocated_port = packet_get_int(); - logit("Allocated port %u for mux remote forward" + debug("Allocated port %u for mux remote forward" " to %s:%d", rfwd->allocated_port, rfwd->connect_host, rfwd->connect_port); buffer_put_int(&out, MUX_S_REMOTE_PORT); @@ -608,8 +624,23 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) } else { if (rfwd->listen_port == 0) channel_update_permitted_opens(rfwd->handle, -1); - xasprintf(&failmsg, "remote port forwarding failed for " - "listen port %d", rfwd->listen_port); + if (rfwd->listen_path != NULL) + xasprintf(&failmsg, "remote port forwarding failed for " + "listen path %s", rfwd->listen_path); + else + xasprintf(&failmsg, "remote port forwarding failed for " + "listen port %d", rfwd->listen_port); + + debug2("%s: clearing registered forwarding for listen %d, " + "connect %s:%d", __func__, rfwd->listen_port, + rfwd->connect_path ? rfwd->connect_path : + rfwd->connect_host, rfwd->connect_port); + + free(rfwd->listen_host); + free(rfwd->listen_path); + free(rfwd->connect_host); + free(rfwd->connect_path); + memset(rfwd, 0, sizeof(*rfwd)); } fail: error("%s: %s", __func__, failmsg); @@ -628,35 +659,48 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) static int process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) { - Forward fwd; + struct Forward fwd; char *fwd_desc = NULL; + char *listen_addr, *connect_addr; u_int ftype; u_int lport, cport; int i, ret = 0, freefwd = 1; memset(&fwd, 0, sizeof(fwd)); + /* XXX - lport/cport check redundant */ if (buffer_get_int_ret(&ftype, m) != 0 || - (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || + (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || buffer_get_int_ret(&lport, m) != 0 || - (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || + (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || buffer_get_int_ret(&cport, m) != 0 || - lport > 65535 || cport > 65535) { + (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || + (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { error("%s: malformed message", __func__); ret = -1; goto out; } - fwd.listen_port = lport; - fwd.connect_port = cport; - if (*fwd.listen_host == '\0') { - free(fwd.listen_host); - fwd.listen_host = NULL; + if (*listen_addr == '\0') { + free(listen_addr); + listen_addr = NULL; } - if (*fwd.connect_host == '\0') { - free(fwd.connect_host); - fwd.connect_host = NULL; + if (*connect_addr == '\0') { + free(connect_addr); + connect_addr = NULL; } + memset(&fwd, 0, sizeof(fwd)); + fwd.listen_port = lport; + if (fwd.listen_port == PORT_STREAMLOCAL) + fwd.listen_path = listen_addr; + else + fwd.listen_host = listen_addr; + fwd.connect_port = cport; + if (fwd.connect_port == PORT_STREAMLOCAL) + fwd.connect_path = connect_addr; + else + fwd.connect_host = connect_addr; + debug2("%s: channel %d: request %s", __func__, c->self, (fwd_desc = format_forward(ftype, &fwd))); @@ -664,25 +708,30 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) ftype != MUX_FWD_DYNAMIC) { logit("%s: invalid forwarding type %u", __func__, ftype); invalid: - free(fwd.listen_host); - free(fwd.connect_host); + free(listen_addr); + free(connect_addr); buffer_put_int(r, MUX_S_FAILURE); buffer_put_int(r, rid); buffer_put_cstring(r, "Invalid forwarding request"); return 0; } - if (fwd.listen_port >= 65536) { + if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { + logit("%s: streamlocal and dynamic forwards " + "are mutually exclusive", __func__); + goto invalid; + } + if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) { logit("%s: invalid listen port %u", __func__, fwd.listen_port); goto invalid; } - if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC && - ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { + if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) + || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { logit("%s: invalid connect port %u", __func__, fwd.connect_port); goto invalid; } - if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { + if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { logit("%s: missing connect host", __func__); goto invalid; } @@ -733,9 +782,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { - if (!channel_setup_local_fwd_listener(fwd.listen_host, - fwd.listen_port, fwd.connect_host, fwd.connect_port, - options.gateway_ports)) { + if (!channel_setup_local_fwd_listener(&fwd, + &options.fwd_opts)) { fail: logit("slave-requested %s failed", fwd_desc); buffer_put_int(r, MUX_S_FAILURE); @@ -748,8 +796,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } else { struct mux_channel_confirm_ctx *fctx; - fwd.handle = channel_request_remote_forwarding(fwd.listen_host, - fwd.listen_port, fwd.connect_host, fwd.connect_port); + fwd.handle = channel_request_remote_forwarding(&fwd); if (fwd.handle < 0) goto fail; add_remote_forward(&options, &fwd); @@ -770,7 +817,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) free(fwd_desc); if (freefwd) { free(fwd.listen_host); + free(fwd.listen_path); free(fwd.connect_host); + free(fwd.connect_path); } return ret; } @@ -778,37 +827,49 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) static int process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) { - Forward fwd, *found_fwd; + struct Forward fwd, *found_fwd; char *fwd_desc = NULL; const char *error_reason = NULL; + char *listen_addr = NULL, *connect_addr = NULL; u_int ftype; - int i, listen_port, ret = 0; + int i, ret = 0; u_int lport, cport; memset(&fwd, 0, sizeof(fwd)); if (buffer_get_int_ret(&ftype, m) != 0 || - (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || + (listen_addr = buffer_get_string_ret(m, NULL)) == NULL || buffer_get_int_ret(&lport, m) != 0 || - (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || + (connect_addr = buffer_get_string_ret(m, NULL)) == NULL || buffer_get_int_ret(&cport, m) != 0 || - lport > 65535 || cport > 65535) { + (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || + (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { error("%s: malformed message", __func__); ret = -1; goto out; } - fwd.listen_port = lport; - fwd.connect_port = cport; - if (*fwd.listen_host == '\0') { - free(fwd.listen_host); - fwd.listen_host = NULL; + if (*listen_addr == '\0') { + free(listen_addr); + listen_addr = NULL; } - if (*fwd.connect_host == '\0') { - free(fwd.connect_host); - fwd.connect_host = NULL; + if (*connect_addr == '\0') { + free(connect_addr); + connect_addr = NULL; } + memset(&fwd, 0, sizeof(fwd)); + fwd.listen_port = lport; + if (fwd.listen_port == PORT_STREAMLOCAL) + fwd.listen_path = listen_addr; + else + fwd.listen_host = listen_addr; + fwd.connect_port = cport; + if (fwd.connect_port == PORT_STREAMLOCAL) + fwd.connect_path = connect_addr; + else + fwd.connect_host = connect_addr; + debug2("%s: channel %d: request cancel %s", __func__, c->self, (fwd_desc = format_forward(ftype, &fwd))); @@ -843,18 +904,14 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) * This shouldn't fail unless we confused the host/port * between options.remote_forwards and permitted_opens. * However, for dynamic allocated listen ports we need - * to lookup the actual listen port. + * to use the actual listen port. */ - listen_port = (fwd.listen_port == 0) ? - found_fwd->allocated_port : fwd.listen_port; - if (channel_request_rforward_cancel(fwd.listen_host, - listen_port) == -1) + if (channel_request_rforward_cancel(found_fwd) == -1) error_reason = "port not in permitted opens"; } else { /* local and dynamic forwards */ /* Ditto */ - if (channel_cancel_lport_listener(fwd.listen_host, - fwd.listen_port, fwd.connect_port, - options.gateway_ports) == -1) + if (channel_cancel_lport_listener(&fwd, fwd.connect_port, + &options.fwd_opts) == -1) error_reason = "port not found"; } @@ -863,8 +920,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) buffer_put_int(r, rid); free(found_fwd->listen_host); + free(found_fwd->listen_path); free(found_fwd->connect_host); + free(found_fwd->connect_path); found_fwd->listen_host = found_fwd->connect_host = NULL; + found_fwd->listen_path = found_fwd->connect_path = NULL; found_fwd->listen_port = found_fwd->connect_port = 0; } else { buffer_put_int(r, MUX_S_FAILURE); @@ -873,8 +933,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } out: free(fwd_desc); - free(fwd.listen_host); - free(fwd.connect_host); + free(listen_addr); + free(connect_addr); return ret; } @@ -886,6 +946,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) char *reserved, *chost; u_int cport, i, j; int new_fd[2]; + struct mux_stdio_confirm_ctx *cctx; chost = reserved = NULL; if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || @@ -965,15 +1026,60 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); - /* prepare reply */ - /* XXX defer until channel confirmed */ - buffer_put_int(r, MUX_S_SESSION_OPENED); - buffer_put_int(r, rid); - buffer_put_int(r, nc->self); + cctx = xcalloc(1, sizeof(*cctx)); + cctx->rid = rid; + channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx); + c->mux_pause = 1; /* stop handling messages until open_confirm done */ + /* reply is deferred, sent by mux_session_confirm */ return 0; } +/* Callback on open confirmation in mux master for a mux stdio fwd session. */ +static void +mux_stdio_confirm(int id, int success, void *arg) +{ + struct mux_stdio_confirm_ctx *cctx = arg; + Channel *c, *cc; + Buffer reply; + + if (cctx == NULL) + fatal("%s: cctx == NULL", __func__); + if ((c = channel_by_id(id)) == NULL) + fatal("%s: no channel for id %d", __func__, id); + if ((cc = channel_by_id(c->ctl_chan)) == NULL) + fatal("%s: channel %d lacks control channel %d", __func__, + id, c->ctl_chan); + + if (!success) { + debug3("%s: sending failure reply", __func__); + /* prepare reply */ + buffer_init(&reply); + buffer_put_int(&reply, MUX_S_FAILURE); + buffer_put_int(&reply, cctx->rid); + buffer_put_cstring(&reply, "Session open refused by peer"); + goto done; + } + + debug3("%s: sending success reply", __func__); + /* prepare reply */ + buffer_init(&reply); + buffer_put_int(&reply, MUX_S_SESSION_OPENED); + buffer_put_int(&reply, cctx->rid); + buffer_put_int(&reply, c->self); + + done: + /* Send reply */ + buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); + buffer_free(&reply); + + if (cc->mux_pause <= 0) + fatal("%s: mux_pause %d", __func__, cc->mux_pause); + cc->mux_pause = 0; /* start processing messages again */ + c->open_confirm_ctx = NULL; + free(cctx); +} + static int process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) { @@ -1013,7 +1119,7 @@ mux_master_read_cb(Channel *c) { struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; Buffer in, out; - void *ptr; + const u_char *ptr; u_int type, rid, have, i; int ret = -1; @@ -1136,12 +1242,11 @@ mux_tty_alloc_failed(Channel *c) void muxserver_listen(void) { - struct sockaddr_un addr; - socklen_t sun_len; mode_t old_umask; char *orig_control_path = options.control_path; char rbuf[16+1]; u_int i, r; + int oerrno; if (options.control_path == NULL || options.control_master == SSHCTL_MASTER_NO) @@ -1166,24 +1271,12 @@ muxserver_listen(void) xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); debug3("%s: temporary control path %s", __func__, options.control_path); - memset(&addr, '\0', sizeof(addr)); - addr.sun_family = AF_UNIX; - sun_len = offsetof(struct sockaddr_un, sun_path) + - strlen(options.control_path) + 1; - - if (strlcpy(addr.sun_path, options.control_path, - sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) { - error("ControlPath \"%s\" too long for Unix domain socket", - options.control_path); - goto disable_mux_master; - } - - if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) - fatal("%s socket(): %s", __func__, strerror(errno)); - old_umask = umask(0177); - if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) { - if (errno == EINVAL || errno == EADDRINUSE) { + muxserver_sock = unix_listener(options.control_path, 64, 0); + oerrno = errno; + umask(old_umask); + if (muxserver_sock < 0) { + if (oerrno == EINVAL || oerrno == EADDRINUSE) { error("ControlSocket %s already exists, " "disabling multiplexing", options.control_path); disable_mux_master: @@ -1196,13 +1289,11 @@ muxserver_listen(void) options.control_path = NULL; options.control_master = SSHCTL_MASTER_NO; return; - } else - fatal("%s bind(): %s", __func__, strerror(errno)); + } else { + /* unix_listener() logs the error */ + cleanup_exit(255); + } } - umask(old_umask); - - if (listen(muxserver_sock, 64) == -1) - fatal("%s listen(): %s", __func__, strerror(errno)); /* Now atomically "move" the mux socket into position */ if (link(options.control_path, orig_control_path) != 0) { @@ -1432,7 +1523,7 @@ mux_client_read_packet(int fd, Buffer *m) { Buffer queue; u_int need, have; - void *ptr; + const u_char *ptr; int oerrno; buffer_init(&queue); @@ -1596,7 +1687,7 @@ mux_client_request_terminate(int fd) } static int -mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) +mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) { Buffer m; char *e, *fwd_desc; @@ -1611,11 +1702,20 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); buffer_put_int(&m, muxclient_request_id); buffer_put_int(&m, ftype); - buffer_put_cstring(&m, - fwd->listen_host == NULL ? "" : fwd->listen_host); + if (fwd->listen_path != NULL) { + buffer_put_cstring(&m, fwd->listen_path); + } else { + buffer_put_cstring(&m, + fwd->listen_host == NULL ? "" : + (*fwd->listen_host == '\0' ? "*" : fwd->listen_host)); + } buffer_put_int(&m, fwd->listen_port); - buffer_put_cstring(&m, - fwd->connect_host == NULL ? "" : fwd->connect_host); + if (fwd->connect_path != NULL) { + buffer_put_cstring(&m, fwd->connect_path); + } else { + buffer_put_cstring(&m, + fwd->connect_host == NULL ? "" : fwd->connect_host); + } buffer_put_int(&m, fwd->connect_port); if (mux_client_write_packet(fd, &m) != 0) @@ -1640,7 +1740,7 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) if (cancel_flag) fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__); fwd->allocated_port = buffer_get_int(&m); - logit("Allocated port %u for remote forward to %s:%d", + verbose("Allocated port %u for remote forward to %s:%d", fwd->allocated_port, fwd->connect_host ? fwd->connect_host : "", fwd->connect_port); @@ -1925,7 +2025,7 @@ mux_client_request_stdio_fwd(int fd) case MUX_S_FAILURE: e = buffer_get_string(&m, NULL); buffer_free(&m); - fatal("%s: stdio forwarding request failed: %s", __func__, e); + fatal("Stdio forwarding request failed: %s", e); default: buffer_free(&m); error("%s: unexpected response from master 0x%08x", diff --git a/crypto/openssh/myproposal.h b/crypto/openssh/myproposal.h index 89479e6..83fc943 100644 --- a/crypto/openssh/myproposal.h +++ b/crypto/openssh/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.35 2013/12/06 13:39:49 markus Exp $ */ +/* $OpenBSD: myproposal.h,v 1.47 2015/07/10 06:21:53 markus Exp $ */ /* $FreeBSD$ */ /* @@ -62,7 +62,7 @@ #ifdef OPENSSL_HAVE_EVPGCM # define AESGCM_CIPHER_MODES \ - "aes128-gcm@openssh.com,aes256-gcm@openssh.com," + ",aes128-gcm@openssh.com,aes256-gcm@openssh.com" #else # define AESGCM_CIPHER_MODES #endif @@ -70,32 +70,37 @@ #ifdef HAVE_EVP_SHA256 # define KEX_SHA256_METHODS \ "diffie-hellman-group-exchange-sha256," -#define KEX_CURVE25519_METHODS \ - "curve25519-sha256@libssh.org," #define SHA2_HMAC_MODES \ "hmac-sha2-256," \ "hmac-sha2-512," #else # define KEX_SHA256_METHODS -# define KEX_CURVE25519_METHODS # define SHA2_HMAC_MODES #endif -# define KEX_DEFAULT_KEX \ +#ifdef WITH_OPENSSL +# ifdef HAVE_EVP_SHA256 +# define KEX_CURVE25519_METHODS "curve25519-sha256@libssh.org," +# else +# define KEX_CURVE25519_METHODS "" +# endif +#define KEX_COMMON_KEX \ KEX_CURVE25519_METHODS \ KEX_ECDH_METHODS \ - KEX_SHA256_METHODS \ + KEX_SHA256_METHODS + +#define KEX_SERVER_KEX KEX_COMMON_KEX \ + "diffie-hellman-group14-sha1" \ + +#define KEX_CLIENT_KEX KEX_COMMON_KEX \ "diffie-hellman-group-exchange-sha1," \ - "diffie-hellman-group14-sha1," \ - "diffie-hellman-group1-sha1" + "diffie-hellman-group14-sha1" #define KEX_DEFAULT_PK_ALG \ HOSTKEY_ECDSA_CERT_METHODS \ "ssh-ed25519-cert-v01@openssh.com," \ "ssh-rsa-cert-v01@openssh.com," \ "ssh-dss-cert-v01@openssh.com," \ - "ssh-rsa-cert-v00@openssh.com," \ - "ssh-dss-cert-v00@openssh.com," \ HOSTKEY_ECDSA_METHODS \ "ssh-ed25519," \ "ssh-rsa," \ @@ -103,47 +108,91 @@ /* the actual algorithms */ -#define KEX_DEFAULT_ENCRYPT \ - "aes128-ctr,aes192-ctr,aes256-ctr," \ - "arcfour256,arcfour128," \ - AESGCM_CIPHER_MODES \ +#define KEX_SERVER_ENCRYPT \ "chacha20-poly1305@openssh.com," \ + "aes128-ctr,aes192-ctr,aes256-ctr" \ + AESGCM_CIPHER_MODES + +#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT "," \ + "arcfour256,arcfour128," \ "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" -#define KEX_DEFAULT_MAC \ - "hmac-md5-etm@openssh.com," \ - "hmac-sha1-etm@openssh.com," \ +#define KEX_SERVER_MAC \ "umac-64-etm@openssh.com," \ "umac-128-etm@openssh.com," \ "hmac-sha2-256-etm@openssh.com," \ "hmac-sha2-512-etm@openssh.com," \ + "hmac-sha1-etm@openssh.com," \ + "umac-64@openssh.com," \ + "umac-128@openssh.com," \ + "hmac-sha2-256," \ + "hmac-sha2-512," \ + "hmac-sha1" + +#define KEX_CLIENT_MAC KEX_SERVER_MAC "," \ + "hmac-md5-etm@openssh.com," \ "hmac-ripemd160-etm@openssh.com," \ "hmac-sha1-96-etm@openssh.com," \ "hmac-md5-96-etm@openssh.com," \ "hmac-md5," \ - "hmac-sha1," \ - "umac-64@openssh.com," \ - "umac-128@openssh.com," \ - SHA2_HMAC_MODES \ "hmac-ripemd160," \ "hmac-ripemd160@openssh.com," \ "hmac-sha1-96," \ "hmac-md5-96" +#else + +#define KEX_SERVER_KEX \ + "curve25519-sha256@libssh.org" +#define KEX_DEFAULT_PK_ALG \ + "ssh-ed25519-cert-v01@openssh.com," \ + "ssh-ed25519" +#define KEX_SERVER_ENCRYPT \ + "chacha20-poly1305@openssh.com," \ + "aes128-ctr,aes192-ctr,aes256-ctr" +#define KEX_SERVER_MAC \ + "umac-64-etm@openssh.com," \ + "umac-128-etm@openssh.com," \ + "hmac-sha2-256-etm@openssh.com," \ + "hmac-sha2-512-etm@openssh.com," \ + "hmac-sha1-etm@openssh.com," \ + "umac-64@openssh.com," \ + "umac-128@openssh.com," \ + "hmac-sha2-256," \ + "hmac-sha2-512," \ + "hmac-sha1" + +#define KEX_CLIENT_KEX KEX_SERVER_KEX +#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT +#define KEX_CLIENT_MAC KEX_SERVER_MAC + +#endif /* WITH_OPENSSL */ + #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" #define KEX_DEFAULT_LANG "" +#define KEX_CLIENT \ + KEX_CLIENT_KEX, \ + KEX_DEFAULT_PK_ALG, \ + KEX_CLIENT_ENCRYPT, \ + KEX_CLIENT_ENCRYPT, \ + KEX_CLIENT_MAC, \ + KEX_CLIENT_MAC, \ + KEX_DEFAULT_COMP, \ + KEX_DEFAULT_COMP, \ + KEX_DEFAULT_LANG, \ + KEX_DEFAULT_LANG -static char *myproposal[PROPOSAL_MAX] = { - KEX_DEFAULT_KEX, - KEX_DEFAULT_PK_ALG, - KEX_DEFAULT_ENCRYPT, - KEX_DEFAULT_ENCRYPT, - KEX_DEFAULT_MAC, - KEX_DEFAULT_MAC, - KEX_DEFAULT_COMP, - KEX_DEFAULT_COMP, - KEX_DEFAULT_LANG, +#define KEX_SERVER \ + KEX_SERVER_KEX, \ + KEX_DEFAULT_PK_ALG, \ + KEX_SERVER_ENCRYPT, \ + KEX_SERVER_ENCRYPT, \ + KEX_SERVER_MAC, \ + KEX_SERVER_MAC, \ + KEX_DEFAULT_COMP, \ + KEX_DEFAULT_COMP, \ + KEX_DEFAULT_LANG, \ KEX_DEFAULT_LANG -}; + diff --git a/crypto/openssh/opacket.c b/crypto/openssh/opacket.c new file mode 100644 index 0000000..b9160d5 --- /dev/null +++ b/crypto/openssh/opacket.c @@ -0,0 +1,349 @@ +/* Written by Markus Friedl. Placed in the public domain. */ + +#include "includes.h" + +#include "ssherr.h" +#include "packet.h" +#include "log.h" + +struct ssh *active_state, *backup_state; + +/* Map old to new API */ + +void +ssh_packet_start(struct ssh *ssh, u_char type) +{ + int r; + + if ((r = sshpkt_start(ssh, type)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +void +ssh_packet_put_char(struct ssh *ssh, int value) +{ + u_char ch = value; + int r; + + if ((r = sshpkt_put_u8(ssh, ch)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +void +ssh_packet_put_int(struct ssh *ssh, u_int value) +{ + int r; + + if ((r = sshpkt_put_u32(ssh, value)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +void +ssh_packet_put_int64(struct ssh *ssh, u_int64_t value) +{ + int r; + + if ((r = sshpkt_put_u64(ssh, value)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +void +ssh_packet_put_string(struct ssh *ssh, const void *buf, u_int len) +{ + int r; + + if ((r = sshpkt_put_string(ssh, buf, len)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +void +ssh_packet_put_cstring(struct ssh *ssh, const char *str) +{ + int r; + + if ((r = sshpkt_put_cstring(ssh, str)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +void +ssh_packet_put_raw(struct ssh *ssh, const void *buf, u_int len) +{ + int r; + + if ((r = sshpkt_put(ssh, buf, len)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +#ifdef WITH_SSH1 +void +ssh_packet_put_bignum(struct ssh *ssh, BIGNUM * value) +{ + int r; + + if ((r = sshpkt_put_bignum1(ssh, value)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} +#endif + +#ifdef WITH_OPENSSL +void +ssh_packet_put_bignum2(struct ssh *ssh, BIGNUM * value) +{ + int r; + + if ((r = sshpkt_put_bignum2(ssh, value)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +# ifdef OPENSSL_HAS_ECC +void +ssh_packet_put_ecpoint(struct ssh *ssh, const EC_GROUP *curve, + const EC_POINT *point) +{ + int r; + + if ((r = sshpkt_put_ec(ssh, point, curve)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} +# endif +#endif /* WITH_OPENSSL */ + +void +ssh_packet_send(struct ssh *ssh) +{ + int r; + + if ((r = sshpkt_send(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +u_int +ssh_packet_get_char(struct ssh *ssh) +{ + u_char ch; + int r; + + if ((r = sshpkt_get_u8(ssh, &ch)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + return ch; +} + +u_int +ssh_packet_get_int(struct ssh *ssh) +{ + u_int val; + int r; + + if ((r = sshpkt_get_u32(ssh, &val)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + return val; +} + +u_int64_t +ssh_packet_get_int64(struct ssh *ssh) +{ + u_int64_t val; + int r; + + if ((r = sshpkt_get_u64(ssh, &val)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + return val; +} + +#ifdef WITH_SSH1 +void +ssh_packet_get_bignum(struct ssh *ssh, BIGNUM * value) +{ + int r; + + if ((r = sshpkt_get_bignum1(ssh, value)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} +#endif + +#ifdef WITH_OPENSSL +void +ssh_packet_get_bignum2(struct ssh *ssh, BIGNUM * value) +{ + int r; + + if ((r = sshpkt_get_bignum2(ssh, value)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +# ifdef OPENSSL_HAS_ECC +void +ssh_packet_get_ecpoint(struct ssh *ssh, const EC_GROUP *curve, EC_POINT *point) +{ + int r; + + if ((r = sshpkt_get_ec(ssh, point, curve)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} +# endif +#endif /* WITH_OPENSSL */ + +void * +ssh_packet_get_string(struct ssh *ssh, u_int *length_ptr) +{ + int r; + size_t len; + u_char *val; + + if ((r = sshpkt_get_string(ssh, &val, &len)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + if (length_ptr != NULL) + *length_ptr = (u_int)len; + return val; +} + +const void * +ssh_packet_get_string_ptr(struct ssh *ssh, u_int *length_ptr) +{ + int r; + size_t len; + const u_char *val; + + if ((r = sshpkt_get_string_direct(ssh, &val, &len)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + if (length_ptr != NULL) + *length_ptr = (u_int)len; + return val; +} + +char * +ssh_packet_get_cstring(struct ssh *ssh, u_int *length_ptr) +{ + int r; + size_t len; + char *val; + + if ((r = sshpkt_get_cstring(ssh, &val, &len)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + if (length_ptr != NULL) + *length_ptr = (u_int)len; + return val; +} + +/* Old API, that had to be reimplemented */ + +void +packet_set_connection(int fd_in, int fd_out) +{ + active_state = ssh_packet_set_connection(active_state, fd_in, fd_out); + if (active_state == NULL) + fatal("%s: ssh_packet_set_connection failed", __func__); +} + +void +packet_backup_state(void) +{ + ssh_packet_backup_state(active_state, backup_state); +} + +void +packet_restore_state(void) +{ + ssh_packet_restore_state(active_state, backup_state); +} + +u_int +packet_get_char(void) +{ + return (ssh_packet_get_char(active_state)); +} + +u_int +packet_get_int(void) +{ + return (ssh_packet_get_int(active_state)); +} + +int +packet_read_seqnr(u_int32_t *seqnr) +{ + u_char type; + int r; + + if ((r = ssh_packet_read_seqnr(active_state, &type, seqnr)) != 0) + sshpkt_fatal(active_state, __func__, r); + return type; +} + +int +packet_read_poll_seqnr(u_int32_t *seqnr) +{ + u_char type; + int r; + + if ((r = ssh_packet_read_poll_seqnr(active_state, &type, seqnr))) + sshpkt_fatal(active_state, __func__, r); + return type; +} + +void +packet_close(void) +{ + ssh_packet_close(active_state); + active_state = NULL; +} + +void +packet_process_incoming(const char *buf, u_int len) +{ + int r; + + if ((r = ssh_packet_process_incoming(active_state, buf, len)) != 0) + sshpkt_fatal(active_state, __func__, r); +} + +void +packet_write_wait(void) +{ + int r; + + if ((r = ssh_packet_write_wait(active_state)) != 0) + sshpkt_fatal(active_state, __func__, r); +} + +void +packet_write_poll(void) +{ + int r; + + if ((r = ssh_packet_write_poll(active_state)) != 0) + sshpkt_fatal(active_state, __func__, r); +} + +void +packet_read_expect(int expected_type) +{ + int r; + + if ((r = ssh_packet_read_expect(active_state, expected_type)) != 0) + sshpkt_fatal(active_state, __func__, r); +} + +void +packet_disconnect(const char *fmt, ...) +{ + char buf[1024]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + ssh_packet_disconnect(active_state, "%s", buf); +} + +void +packet_send_debug(const char *fmt, ...) +{ + char buf[1024]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + ssh_packet_send_debug(active_state, "%s", buf); +} diff --git a/crypto/openssh/opacket.h b/crypto/openssh/opacket.h new file mode 100644 index 0000000..a0a60e5 --- /dev/null +++ b/crypto/openssh/opacket.h @@ -0,0 +1,168 @@ +#ifndef _OPACKET_H +/* Written by Markus Friedl. Placed in the public domain. */ + +/* Map old to new API */ +void ssh_packet_start(struct ssh *, u_char); +void ssh_packet_put_char(struct ssh *, int ch); +void ssh_packet_put_int(struct ssh *, u_int value); +void ssh_packet_put_int64(struct ssh *, u_int64_t value); +void ssh_packet_put_bignum(struct ssh *, BIGNUM * value); +void ssh_packet_put_bignum2(struct ssh *, BIGNUM * value); +void ssh_packet_put_ecpoint(struct ssh *, const EC_GROUP *, const EC_POINT *); +void ssh_packet_put_string(struct ssh *, const void *buf, u_int len); +void ssh_packet_put_cstring(struct ssh *, const char *str); +void ssh_packet_put_raw(struct ssh *, const void *buf, u_int len); +void ssh_packet_send(struct ssh *); + +u_int ssh_packet_get_char(struct ssh *); +u_int ssh_packet_get_int(struct ssh *); +u_int64_t ssh_packet_get_int64(struct ssh *); +void ssh_packet_get_bignum(struct ssh *, BIGNUM * value); +void ssh_packet_get_bignum2(struct ssh *, BIGNUM * value); +void ssh_packet_get_ecpoint(struct ssh *, const EC_GROUP *, EC_POINT *); +void *ssh_packet_get_string(struct ssh *, u_int *length_ptr); +char *ssh_packet_get_cstring(struct ssh *, u_int *length_ptr); + +/* don't allow remaining bytes after the end of the message */ +#define ssh_packet_check_eom(ssh) \ +do { \ + int _len = ssh_packet_remaining(ssh); \ + if (_len > 0) { \ + logit("Packet integrity error (%d bytes remaining) at %s:%d", \ + _len ,__FILE__, __LINE__); \ + ssh_packet_disconnect(ssh, \ + "Packet integrity error."); \ + } \ +} while (0) + +/* old API */ +void packet_close(void); +u_int packet_get_char(void); +u_int packet_get_int(void); +void packet_backup_state(void); +void packet_restore_state(void); +void packet_set_connection(int, int); +int packet_read_seqnr(u_int32_t *); +int packet_read_poll_seqnr(u_int32_t *); +void packet_process_incoming(const char *buf, u_int len); +void packet_write_wait(void); +void packet_write_poll(void); +void packet_read_expect(int expected_type); +#define packet_set_timeout(timeout, count) \ + ssh_packet_set_timeout(active_state, (timeout), (count)) +#define packet_connection_is_on_socket() \ + ssh_packet_connection_is_on_socket(active_state) +#define packet_set_nonblocking() \ + ssh_packet_set_nonblocking(active_state) +#define packet_get_connection_in() \ + ssh_packet_get_connection_in(active_state) +#define packet_get_connection_out() \ + ssh_packet_get_connection_out(active_state) +#define packet_set_protocol_flags(protocol_flags) \ + ssh_packet_set_protocol_flags(active_state, (protocol_flags)) +#define packet_get_protocol_flags() \ + ssh_packet_get_protocol_flags(active_state) +#define packet_start_compression(level) \ + ssh_packet_start_compression(active_state, (level)) +#define packet_set_encryption_key(key, keylen, number) \ + ssh_packet_set_encryption_key(active_state, (key), (keylen), (number)) +#define packet_start(type) \ + ssh_packet_start(active_state, (type)) +#define packet_put_char(value) \ + ssh_packet_put_char(active_state, (value)) +#define packet_put_int(value) \ + ssh_packet_put_int(active_state, (value)) +#define packet_put_int64(value) \ + ssh_packet_put_int64(active_state, (value)) +#define packet_put_string( buf, len) \ + ssh_packet_put_string(active_state, (buf), (len)) +#define packet_put_cstring(str) \ + ssh_packet_put_cstring(active_state, (str)) +#define packet_put_raw(buf, len) \ + ssh_packet_put_raw(active_state, (buf), (len)) +#define packet_put_bignum(value) \ + ssh_packet_put_bignum(active_state, (value)) +#define packet_put_bignum2(value) \ + ssh_packet_put_bignum2(active_state, (value)) +#define packet_send() \ + ssh_packet_send(active_state) +#define packet_read() \ + ssh_packet_read(active_state) +#define packet_get_int64() \ + ssh_packet_get_int64(active_state) +#define packet_get_bignum(value) \ + ssh_packet_get_bignum(active_state, (value)) +#define packet_get_bignum2(value) \ + ssh_packet_get_bignum2(active_state, (value)) +#define packet_remaining() \ + ssh_packet_remaining(active_state) +#define packet_get_string(length_ptr) \ + ssh_packet_get_string(active_state, (length_ptr)) +#define packet_get_string_ptr(length_ptr) \ + ssh_packet_get_string_ptr(active_state, (length_ptr)) +#define packet_get_cstring(length_ptr) \ + ssh_packet_get_cstring(active_state, (length_ptr)) +void packet_send_debug(const char *, ...) + __attribute__((format(printf, 1, 2))); +void packet_disconnect(const char *, ...) + __attribute__((format(printf, 1, 2))) + __attribute__((noreturn)); +#define packet_have_data_to_write() \ + ssh_packet_have_data_to_write(active_state) +#define packet_not_very_much_data_to_write() \ + ssh_packet_not_very_much_data_to_write(active_state) +#define packet_set_interactive(interactive, qos_interactive, qos_bulk) \ + ssh_packet_set_interactive(active_state, (interactive), (qos_interactive), (qos_bulk)) +#define packet_is_interactive() \ + ssh_packet_is_interactive(active_state) +#define packet_set_maxsize(s) \ + ssh_packet_set_maxsize(active_state, (s)) +#define packet_inc_alive_timeouts() \ + ssh_packet_inc_alive_timeouts(active_state) +#define packet_set_alive_timeouts(ka) \ + ssh_packet_set_alive_timeouts(active_state, (ka)) +#define packet_get_maxsize() \ + ssh_packet_get_maxsize(active_state) +#define packet_add_padding(pad) \ + sshpkt_add_padding(active_state, (pad)) +#define packet_send_ignore(nbytes) \ + ssh_packet_send_ignore(active_state, (nbytes)) +#define packet_need_rekeying() \ + ssh_packet_need_rekeying(active_state) +#define packet_set_server() \ + ssh_packet_set_server(active_state) +#define packet_set_authenticated() \ + ssh_packet_set_authenticated(active_state) +#define packet_get_input() \ + ssh_packet_get_input(active_state) +#define packet_get_output() \ + ssh_packet_get_output(active_state) +#define packet_set_compress_hooks(ctx, allocfunc, freefunc) \ + ssh_packet_set_compress_hooks(active_state, ctx, \ + allocfunc, freefunc); +#define packet_check_eom() \ + ssh_packet_check_eom(active_state) +#define set_newkeys(mode) \ + ssh_set_newkeys(active_state, (mode)) +#define packet_get_state(m) \ + ssh_packet_get_state(active_state, m) +#define packet_set_state(m) \ + ssh_packet_set_state(active_state, m) +#if 0 +#define get_remote_ipaddr() \ + ssh_remote_ipaddr(active_state) +#endif +#define packet_get_raw(lenp) \ + sshpkt_ptr(active_state, lenp) +#define packet_get_ecpoint(c,p) \ + ssh_packet_get_ecpoint(active_state, c, p) +#define packet_put_ecpoint(c,p) \ + ssh_packet_put_ecpoint(active_state, c, p) +#define packet_get_rekey_timeout() \ + ssh_packet_get_rekey_timeout(active_state) +#define packet_set_rekey_limits(x,y) \ + ssh_packet_set_rekey_limits(active_state, x, y) +#define packet_get_bytes(x,y) \ + ssh_packet_get_bytes(active_state, x, y) + +#endif /* _OPACKET_H */ diff --git a/crypto/openssh/openbsd-compat/.cvsignore b/crypto/openssh/openbsd-compat/.cvsignore new file mode 100644 index 0000000..f3c7a7c --- /dev/null +++ b/crypto/openssh/openbsd-compat/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/crypto/openssh/openbsd-compat/Makefile.in b/crypto/openssh/openbsd-compat/Makefile.in index 6ecfb93..3c5e3b7 100644 --- a/crypto/openssh/openbsd-compat/Makefile.in +++ b/crypto/openssh/openbsd-compat/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.55 2014/02/04 00:37:50 djm Exp $ +# $Id: Makefile.in,v 1.56 2014/09/30 23:43:08 djm Exp $ sysconfdir=@sysconfdir@ piddir=@piddir@ @@ -16,9 +16,9 @@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ LDFLAGS=-L. @LDFLAGS@ -OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o +OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o -COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o +COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o kludge-fd_set.o PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o diff --git a/crypto/openssh/openbsd-compat/arc4random.c b/crypto/openssh/openbsd-compat/arc4random.c index eac073c..046f57e 100644 --- a/crypto/openssh/openbsd-compat/arc4random.c +++ b/crypto/openssh/openbsd-compat/arc4random.c @@ -26,15 +26,19 @@ #include "includes.h" +#include + +#include #include #include #include -#include #ifndef HAVE_ARC4RANDOM +#ifdef WITH_OPENSSL #include #include +#endif #include "log.h" @@ -73,21 +77,51 @@ _rs_init(u_char *buf, size_t n) chacha_ivsetup(&rs, buf + KEYSZ); } +#ifndef WITH_OPENSSL +#define SSH_RANDOM_DEV "/dev/urandom" +/* XXX use getrandom() if supported on Linux */ +static void +getrnd(u_char *s, size_t len) +{ + int fd; + ssize_t r; + size_t o = 0; + + if ((fd = open(SSH_RANDOM_DEV, O_RDONLY)) == -1) + fatal("Couldn't open %s: %s", SSH_RANDOM_DEV, strerror(errno)); + while (o < len) { + r = read(fd, s + o, len - o); + if (r < 0) { + if (errno == EAGAIN || errno == EINTR || + errno == EWOULDBLOCK) + continue; + fatal("read %s: %s", SSH_RANDOM_DEV, strerror(errno)); + } + o += r; + } + close(fd); +} +#endif + static void _rs_stir(void) { u_char rnd[KEYSZ + IVSZ]; +#ifdef WITH_OPENSSL if (RAND_bytes(rnd, sizeof(rnd)) <= 0) fatal("Couldn't obtain random bytes (error %ld)", ERR_get_error()); +#else + getrnd(rnd, sizeof(rnd)); +#endif if (!rs_initialized) { rs_initialized = 1; _rs_init(rnd, sizeof(rnd)); } else _rs_rekey(rnd, sizeof(rnd)); - memset(rnd, 0, sizeof(rnd)); + explicit_bzero(rnd, sizeof(rnd)); /* invalidate rs_buf */ rs_have = 0; @@ -229,7 +263,7 @@ arc4random_buf(void *_buf, size_t n) buf[i] = r & 0xff; r >>= 8; } - i = r = 0; + explicit_bzero(&r, sizeof(r)); } #endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ diff --git a/crypto/openssh/openbsd-compat/bcrypt_pbkdf.c b/crypto/openssh/openbsd-compat/bcrypt_pbkdf.c index 91b6ba0..0a07f9a 100644 --- a/crypto/openssh/openbsd-compat/bcrypt_pbkdf.c +++ b/crypto/openssh/openbsd-compat/bcrypt_pbkdf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bcrypt_pbkdf.c,v 1.4 2013/07/29 00:55:53 tedu Exp $ */ +/* $OpenBSD: bcrypt_pbkdf.c,v 1.13 2015/01/12 03:20:04 tedu Exp $ */ /* * Copyright (c) 2013 Ted Unangst * @@ -32,8 +32,13 @@ #endif #include "crypto_api.h" +#ifdef SHA512_DIGEST_LENGTH +# undef SHA512_DIGEST_LENGTH +#endif #define SHA512_DIGEST_LENGTH crypto_hash_sha512_BYTES +#define MINIMUM(a,b) (((a) < (b)) ? (a) : (b)) + /* * pkcs #5 pbkdf2 implementation using the "bcrypt" hash * @@ -51,15 +56,15 @@ * * One modification from official pbkdf2. Instead of outputting key material * linearly, we mix it. pbkdf2 has a known weakness where if one uses it to - * generate (i.e.) 512 bits of key material for use as two 256 bit keys, an - * attacker can merely run once through the outer loop below, but the user + * generate (e.g.) 512 bits of key material for use as two 256 bit keys, an + * attacker can merely run once through the outer loop, but the user * always runs it twice. Shuffling output bytes requires computing the * entirety of the key material to assemble any subkey. This is something a * wise caller could do; we just do it for you. */ -#define BCRYPT_BLOCKS 8 -#define BCRYPT_HASHSIZE (BCRYPT_BLOCKS * 4) +#define BCRYPT_WORDS 8 +#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4) static void bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out) @@ -67,7 +72,7 @@ bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out) blf_ctx state; u_int8_t ciphertext[BCRYPT_HASHSIZE] = "OxychromaticBlowfishSwatDynamite"; - uint32_t cdata[BCRYPT_BLOCKS]; + uint32_t cdata[BCRYPT_WORDS]; int i; uint16_t j; size_t shalen = SHA512_DIGEST_LENGTH; @@ -82,14 +87,14 @@ bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out) /* encryption */ j = 0; - for (i = 0; i < BCRYPT_BLOCKS; i++) + for (i = 0; i < BCRYPT_WORDS; i++) cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext), &j); for (i = 0; i < 64; i++) blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t)); /* copy out */ - for (i = 0; i < BCRYPT_BLOCKS; i++) { + for (i = 0; i < BCRYPT_WORDS; i++) { out[4 * i + 3] = (cdata[i] >> 24) & 0xff; out[4 * i + 2] = (cdata[i] >> 16) & 0xff; out[4 * i + 1] = (cdata[i] >> 8) & 0xff; @@ -97,9 +102,9 @@ bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out) } /* zap */ - memset(ciphertext, 0, sizeof(ciphertext)); - memset(cdata, 0, sizeof(cdata)); - memset(&state, 0, sizeof(state)); + explicit_bzero(ciphertext, sizeof(ciphertext)); + explicit_bzero(cdata, sizeof(cdata)); + explicit_bzero(&state, sizeof(state)); } int @@ -113,6 +118,7 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const u_int8_t *salt, size_t salt u_int8_t *countsalt; size_t i, j, amt, stride; uint32_t count; + size_t origkeylen = keylen; /* nothing crazy */ if (rounds < 1) @@ -152,17 +158,20 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const u_int8_t *salt, size_t salt } /* - * pbkdf2 deviation: ouput the key material non-linearly. + * pbkdf2 deviation: output the key material non-linearly. */ - amt = MIN(amt, keylen); - for (i = 0; i < amt; i++) - key[i * stride + (count - 1)] = out[i]; - keylen -= amt; + amt = MINIMUM(amt, keylen); + for (i = 0; i < amt; i++) { + size_t dest = i * stride + (count - 1); + if (dest >= origkeylen) + break; + key[dest] = out[i]; + } + keylen -= i; } /* zap */ - memset(out, 0, sizeof(out)); - memset(countsalt, 0, saltlen + 4); + explicit_bzero(out, sizeof(out)); free(countsalt); return 0; diff --git a/crypto/openssh/openbsd-compat/bsd-cygwin_util.c b/crypto/openssh/openbsd-compat/bsd-cygwin_util.c index 267e77a..8672ccf 100644 --- a/crypto/openssh/openbsd-compat/bsd-cygwin_util.c +++ b/crypto/openssh/openbsd-compat/bsd-cygwin_util.c @@ -57,6 +57,22 @@ check_ntsec(const char *filename) return (pathconf(filename, _PC_POSIX_PERMISSIONS)); } +const char * +cygwin_ssh_privsep_user() +{ + static char cyg_privsep_user[DNLEN + UNLEN + 2]; + + if (!cyg_privsep_user[0]) + { +#ifdef CW_CYGNAME_FROM_WINNAME + if (cygwin_internal (CW_CYGNAME_FROM_WINNAME, "sshd", cyg_privsep_user, + sizeof cyg_privsep_user) != 0) +#endif + strlcpy(cyg_privsep_user, "sshd", sizeof(cyg_privsep_user)); + } + return cyg_privsep_user; +} + #define NL(x) x, (sizeof (x) - 1) #define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0])) diff --git a/crypto/openssh/openbsd-compat/bsd-cygwin_util.h b/crypto/openssh/openbsd-compat/bsd-cygwin_util.h index 1177366..79cb2a1 100644 --- a/crypto/openssh/openbsd-compat/bsd-cygwin_util.h +++ b/crypto/openssh/openbsd-compat/bsd-cygwin_util.h @@ -1,4 +1,4 @@ -/* $Id: bsd-cygwin_util.h,v 1.17 2014/01/18 10:04:00 dtucker Exp $ */ +/* $Id: bsd-cygwin_util.h,v 1.18 2014/05/27 04:34:43 djm Exp $ */ /* * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen @@ -39,6 +39,8 @@ /* Avoid including windows headers. */ typedef void *HANDLE; #define INVALID_HANDLE_VALUE ((HANDLE) -1) +#define DNLEN 16 +#define UNLEN 256 /* Cygwin functions for which declarations are only available when including windows headers, so we have to define them here explicitely. */ @@ -48,6 +50,8 @@ extern void cygwin_set_impersonation_token (const HANDLE); #include #include +#define CYGWIN_SSH_PRIVSEP_USER (cygwin_ssh_privsep_user()) +const char *cygwin_ssh_privsep_user(); int binary_open(const char *, int , ...); int check_ntsec(const char *); diff --git a/crypto/openssh/openbsd-compat/bsd-misc.c b/crypto/openssh/openbsd-compat/bsd-misc.c index 65e8003..f7be415 100644 --- a/crypto/openssh/openbsd-compat/bsd-misc.c +++ b/crypto/openssh/openbsd-compat/bsd-misc.c @@ -31,8 +31,6 @@ #include #include -#include "xmalloc.h" - #ifndef HAVE___PROGNAME char *__progname; #endif @@ -43,13 +41,12 @@ char *__progname; */ char *ssh_get_progname(char *argv0) { + char *p, *q; #ifdef HAVE___PROGNAME extern char *__progname; - return xstrdup(__progname); + p = __progname; #else - char *p; - if (argv0 == NULL) return ("unknown"); /* XXX */ p = strrchr(argv0, '/'); @@ -57,9 +54,12 @@ char *ssh_get_progname(char *argv0) p = argv0; else p++; - - return (xstrdup(p)); #endif + if ((q = strdup(p)) == NULL) { + perror("strdup"); + exit(1); + } + return q; } #ifndef HAVE_SETLOGIN diff --git a/crypto/openssh/openbsd-compat/bsd-misc.h b/crypto/openssh/openbsd-compat/bsd-misc.h index e4fa805..ff347a2 100644 --- a/crypto/openssh/openbsd-compat/bsd-misc.h +++ b/crypto/openssh/openbsd-compat/bsd-misc.h @@ -111,7 +111,7 @@ pid_t getpgid(pid_t); #endif #ifndef HAVE_ENDGRENT -# define endgrent() do { } while (0) +# define endgrent() do { } while(0) #endif #ifndef HAVE_KRB5_GET_ERROR_MESSAGE diff --git a/crypto/openssh/openbsd-compat/bsd-snprintf.c b/crypto/openssh/openbsd-compat/bsd-snprintf.c index 975991e..23a6359 100644 --- a/crypto/openssh/openbsd-compat/bsd-snprintf.c +++ b/crypto/openssh/openbsd-compat/bsd-snprintf.c @@ -538,7 +538,7 @@ fmtstr(char *buffer, size_t *currlen, size_t maxlen, } while (*value && (cnt < max)) { DOPR_OUTCH(buffer, *currlen, maxlen, *value); - *value++; + value++; ++cnt; } while ((padlen < 0) && (cnt < max)) { @@ -553,7 +553,7 @@ fmtstr(char *buffer, size_t *currlen, size_t maxlen, static int fmtint(char *buffer, size_t *currlen, size_t maxlen, - LLONG value, int base, int min, int max, int flags) + intmax_t value, int base, int min, int max, int flags) { int signvalue = 0; unsigned LLONG uvalue; diff --git a/crypto/openssh/openbsd-compat/explicit_bzero.c b/crypto/openssh/openbsd-compat/explicit_bzero.c index b106741..3c85a48 100644 --- a/crypto/openssh/openbsd-compat/explicit_bzero.c +++ b/crypto/openssh/openbsd-compat/explicit_bzero.c @@ -7,14 +7,34 @@ #include "includes.h" +/* + * explicit_bzero - don't let the compiler optimize away bzero + */ + #ifndef HAVE_EXPLICIT_BZERO +#ifdef HAVE_MEMSET_S + +void +explicit_bzero(void *p, size_t n) +{ + (void)memset_s(p, n, 0, n); +} + +#else /* HAVE_MEMSET_S */ + /* - * explicit_bzero - don't let the compiler optimize away bzero + * Indirect bzero through a volatile pointer to hopefully avoid + * dead-store optimisation eliminating the call. */ +static void (* volatile ssh_bzero)(void *, size_t) = bzero; + void explicit_bzero(void *p, size_t n) { - bzero(p, n); + ssh_bzero(p, n); } -#endif + +#endif /* HAVE_MEMSET_S */ + +#endif /* HAVE_EXPLICIT_BZERO */ diff --git a/crypto/openssh/openbsd-compat/fake-rfc2553.h b/crypto/openssh/openbsd-compat/fake-rfc2553.h index 3e9090f..6426f7b 100644 --- a/crypto/openssh/openbsd-compat/fake-rfc2553.h +++ b/crypto/openssh/openbsd-compat/fake-rfc2553.h @@ -109,6 +109,9 @@ struct sockaddr_in6 { #ifndef AI_NUMERICHOST # define AI_NUMERICHOST (1<<2) #endif +#ifndef AI_NUMERICSERV +# define AI_NUMERICSERV (1<<3) +#endif #ifndef NI_MAXSERV # define NI_MAXSERV 32 diff --git a/crypto/openssh/openbsd-compat/getrrsetbyname-ldns.c b/crypto/openssh/openbsd-compat/getrrsetbyname-ldns.c index 343720f..4647b62 100644 --- a/crypto/openssh/openbsd-compat/getrrsetbyname-ldns.c +++ b/crypto/openssh/openbsd-compat/getrrsetbyname-ldns.c @@ -69,7 +69,7 @@ getrrsetbyname(const char *hostname, unsigned int rdclass, struct rrsetinfo *rrset = NULL; struct rdatainfo *rdata; size_t len; - ldns_resolver *ldns_res; + ldns_resolver *ldns_res = NULL; ldns_rdf *domain = NULL; ldns_pkt *pkt = NULL; ldns_rr_list *rrsigs = NULL, *rrdata = NULL; diff --git a/crypto/openssh/openbsd-compat/kludge-fd_set.c b/crypto/openssh/openbsd-compat/kludge-fd_set.c new file mode 100644 index 0000000..6c2ffb6 --- /dev/null +++ b/crypto/openssh/openbsd-compat/kludge-fd_set.c @@ -0,0 +1,28 @@ +/* Placed in the public domain. */ + +/* + * _FORTIFY_SOURCE includes a misguided check for FD_SET(n)/FD_ISSET(b) + * where n > FD_SETSIZE. This breaks OpenSSH and other programs that + * explicitly allocate fd_sets. To avoid this, we wrap FD_SET in a + * function compiled without _FORTIFY_SOURCE. + */ + +#include "config.h" + +#if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE) +# include +# if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) +# undef _FORTIFY_SOURCE +# undef __USE_FORTIFY_LEVEL +# include +void kludge_FD_SET(int n, fd_set *set) { + FD_SET(n, set); +} +int kludge_FD_ISSET(int n, fd_set *set) { + return FD_ISSET(n, set); +} +# endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */ +# endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */ +#endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */ + diff --git a/crypto/openssh/openbsd-compat/md5.c b/crypto/openssh/openbsd-compat/md5.c new file mode 100644 index 0000000..195ab51 --- /dev/null +++ b/crypto/openssh/openbsd-compat/md5.c @@ -0,0 +1,251 @@ +/* $OpenBSD: md5.c,v 1.9 2014/01/08 06:14:57 tedu Exp $ */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#include "includes.h" + +#ifndef WITH_OPENSSL + +#include +#include +#include "md5.h" + +#define PUT_64BIT_LE(cp, value) do { \ + (cp)[7] = (value) >> 56; \ + (cp)[6] = (value) >> 48; \ + (cp)[5] = (value) >> 40; \ + (cp)[4] = (value) >> 32; \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +#define PUT_32BIT_LE(cp, value) do { \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +static u_int8_t PADDING[MD5_BLOCK_LENGTH] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +MD5Init(MD5_CTX *ctx) +{ + ctx->count = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xefcdab89; + ctx->state[2] = 0x98badcfe; + ctx->state[3] = 0x10325476; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len) +{ + size_t have, need; + + /* Check how many bytes we already have and how many more we need. */ + have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); + need = MD5_BLOCK_LENGTH - have; + + /* Update bitcount */ + ctx->count += (u_int64_t)len << 3; + + if (len >= need) { + if (have != 0) { + memcpy(ctx->buffer + have, input, need); + MD5Transform(ctx->state, ctx->buffer); + input += need; + len -= need; + have = 0; + } + + /* Process data in MD5_BLOCK_LENGTH-byte chunks. */ + while (len >= MD5_BLOCK_LENGTH) { + MD5Transform(ctx->state, input); + input += MD5_BLOCK_LENGTH; + len -= MD5_BLOCK_LENGTH; + } + } + + /* Handle any remaining bytes of data. */ + if (len != 0) + memcpy(ctx->buffer + have, input, len); +} + +/* + * Pad pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +MD5Pad(MD5_CTX *ctx) +{ + u_int8_t count[8]; + size_t padlen; + + /* Convert count to 8 bytes in little endian order. */ + PUT_64BIT_LE(count, ctx->count); + + /* Pad out to 56 mod 64. */ + padlen = MD5_BLOCK_LENGTH - + ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); + if (padlen < 1 + 8) + padlen += MD5_BLOCK_LENGTH; + MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ + MD5Update(ctx, count, 8); +} + +/* + * Final wrapup--call MD5Pad, fill in digest and zero out ctx. + */ +void +MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) +{ + int i; + + MD5Pad(ctx); + for (i = 0; i < 4; i++) + PUT_32BIT_LE(digest + i * 4, ctx->state[i]); + memset(ctx, 0, sizeof(*ctx)); +} + + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH]) +{ + u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4]; + +#if BYTE_ORDER == LITTLE_ENDIAN + memcpy(in, block, sizeof(in)); +#else + for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) { + in[a] = (u_int32_t)( + (u_int32_t)(block[a * 4 + 0]) | + (u_int32_t)(block[a * 4 + 1]) << 8 | + (u_int32_t)(block[a * 4 + 2]) << 16 | + (u_int32_t)(block[a * 4 + 3]) << 24); + } +#endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21); + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} +#endif /* !WITH_OPENSSL */ diff --git a/crypto/openssh/openbsd-compat/md5.h b/crypto/openssh/openbsd-compat/md5.h new file mode 100644 index 0000000..c83c19d --- /dev/null +++ b/crypto/openssh/openbsd-compat/md5.h @@ -0,0 +1,51 @@ +/* $OpenBSD: md5.h,v 1.17 2012/12/05 23:19:57 deraadt Exp $ */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + */ + +#ifndef _MD5_H_ +#define _MD5_H_ + +#ifndef WITH_OPENSSL + +#define MD5_BLOCK_LENGTH 64 +#define MD5_DIGEST_LENGTH 16 +#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) + +typedef struct MD5Context { + u_int32_t state[4]; /* state */ + u_int64_t count; /* number of bits, mod 2^64 */ + u_int8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */ +} MD5_CTX; + +void MD5Init(MD5_CTX *); +void MD5Update(MD5_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void MD5Pad(MD5_CTX *); +void MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *) + __attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH))); +void MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH]) + __attribute__((__bounded__(__minbytes__,1,4))) + __attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH))); +char *MD5End(MD5_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); +char *MD5File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); +char *MD5FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); +char *MD5Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH))); + +#endif /* !WITH_OPENSSL */ + +#endif /* _MD5_H_ */ diff --git a/crypto/openssh/openbsd-compat/openbsd-compat.h b/crypto/openssh/openbsd-compat/openbsd-compat.h index bc9888e..1ff7114 100644 --- a/crypto/openssh/openbsd-compat/openbsd-compat.h +++ b/crypto/openssh/openbsd-compat/openbsd-compat.h @@ -1,4 +1,4 @@ -/* $Id: openbsd-compat.h,v 1.61 2014/02/04 00:18:23 djm Exp $ */ +/* $Id: openbsd-compat.h,v 1.62 2014/09/30 23:43:08 djm Exp $ */ /* * Copyright (c) 1999-2003 Damien Miller. All rights reserved. @@ -43,7 +43,10 @@ #include "readpassphrase.h" #include "vis.h" #include "getrrsetbyname.h" +#include "sha1.h" #include "sha2.h" +#include "rmd160.h" +#include "md5.h" #include "blf.h" #ifndef HAVE_BASENAME @@ -62,9 +65,21 @@ void closefrom(int); char *getcwd(char *pt, size_t size); #endif +#ifndef HAVE_REALLOCARRAY +void *reallocarray(void *, size_t, size_t); +#endif + #if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) +/* + * glibc's FORTIFY_SOURCE can redefine this and prevent us picking up the + * compat version. + */ +# ifdef BROKEN_REALPATH +# define realpath(x, y) _ssh_compat_realpath(x, y) +# endif + char *realpath(const char *path, char *resolved); -#endif +#endif #ifndef HAVE_RRESVPORT_AF int rresvport_af(int *alport, sa_family_t af); @@ -214,7 +229,7 @@ long long strtonum(const char *, long long, long long, const char **); /* multibyte character support */ #ifndef HAVE_MBLEN -# define mblen(x, y) 1 +# define mblen(x, y) (1) #endif #if !defined(HAVE_VASPRINTF) || !defined(HAVE_VSNPRINTF) @@ -268,4 +283,20 @@ char *shadow_pw(struct passwd *pw); #include "port-tun.h" #include "port-uw.h" +/* _FORTIFY_SOURCE breaks FD_ISSET(n)/FD_SET(n) for n > FD_SETSIZE. Avoid. */ +#if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE) +# include +# if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ) +# if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) +# include /* Ensure include guard is defined */ +# undef FD_SET +# undef FD_ISSET +# define FD_SET(n, set) kludge_FD_SET(n, set) +# define FD_ISSET(n, set) kludge_FD_ISSET(n, set) +void kludge_FD_SET(int, fd_set *); +int kludge_FD_ISSET(int, fd_set *); +# endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */ +# endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */ +#endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */ + #endif /* _OPENBSD_COMPAT_H */ diff --git a/crypto/openssh/openbsd-compat/openssl-compat.c b/crypto/openssh/openbsd-compat/openssl-compat.c index 885c121..63a660c 100644 --- a/crypto/openssh/openbsd-compat/openssl-compat.c +++ b/crypto/openssh/openbsd-compat/openssl-compat.c @@ -1,4 +1,4 @@ -/* $Id: openssl-compat.c,v 1.17 2014/02/13 05:38:33 dtucker Exp $ */ +/* $Id: openssl-compat.c,v 1.19 2014/07/02 05:28:07 djm Exp $ */ /* * Copyright (c) 2005 Darren Tucker @@ -16,8 +16,11 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS #include "includes.h" +#ifdef WITH_OPENSSL + #include #include @@ -26,147 +29,44 @@ # include #endif -#ifndef HAVE_RSA_GET_DEFAULT_METHOD -# include -#endif - #include "log.h" -#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS #include "openssl-compat.h" -#ifdef SSH_OLD_EVP -int -ssh_EVP_CipherInit(EVP_CIPHER_CTX *evp, const EVP_CIPHER *type, - unsigned char *key, unsigned char *iv, int enc) -{ - EVP_CipherInit(evp, type, key, iv, enc); - return 1; -} - -int -ssh_EVP_Cipher(EVP_CIPHER_CTX *evp, char *dst, char *src, int len) -{ - EVP_Cipher(evp, dst, src, len); - return 1; -} - -int -ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *evp) -{ - EVP_CIPHER_CTX_cleanup(evp); - return 1; -} -#endif - -#ifndef HAVE_EVP_DIGESTINIT_EX -int -EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, void *engine) -{ - if (engine != NULL) - fatal("%s: ENGINE is not supported", __func__); -# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID - EVP_DigestInit(ctx, md); - return 1; -# else - return EVP_DigestInit(ctx, md); -# endif -} -#endif - -#ifndef HAVE_EVP_DIGESTFINAL_EX -int -EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s) -{ -# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID - EVP_DigestFinal(ctx, md, s); - return 1; -# else - return EVP_DigestFinal(ctx, md, s); -# endif -} -#endif - -#ifdef OPENSSL_EVP_DIGESTUPDATE_VOID -int -ssh_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt) -{ - EVP_DigestUpdate(ctx, d, cnt); - return 1; -} -#endif - -#ifndef HAVE_EVP_MD_CTX_COPY_EX -int -EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) -{ - return EVP_MD_CTX_copy(out, in); -} -#endif - -#ifndef HAVE_BN_IS_PRIME_EX -int -BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, void *cb) -{ - if (cb != NULL) - fatal("%s: callback args not supported", __func__); - return BN_is_prime(p, nchecks, NULL, ctx, NULL); -} -#endif - -#ifndef HAVE_RSA_GENERATE_KEY_EX -int -RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *bn_e, void *cb) -{ - RSA *new_rsa, tmp_rsa; - unsigned long e; - - if (cb != NULL) - fatal("%s: callback args not supported", __func__); - e = BN_get_word(bn_e); - if (e == 0xffffffffL) - fatal("%s: value of e too large", __func__); - new_rsa = RSA_generate_key(bits, e, NULL, NULL); - if (new_rsa == NULL) - return 0; - /* swap rsa/new_rsa then free new_rsa */ - tmp_rsa = *rsa; - *rsa = *new_rsa; - *new_rsa = tmp_rsa; - RSA_free(new_rsa); - return 1; -} -#endif +/* + * OpenSSL version numbers: MNNFFPPS: major minor fix patch status + * We match major, minor, fix and status (not patch) for <1.0.0. + * After that, we acceptable compatible fix versions (so we + * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed + * within a patch series. + */ -#ifndef HAVE_DSA_GENERATE_PARAMETERS_EX int -DSA_generate_parameters_ex(DSA *dsa, int bits, const unsigned char *seed, - int seed_len, int *counter_ret, unsigned long *h_ret, void *cb) +ssh_compatible_openssl(long headerver, long libver) { - DSA *new_dsa, tmp_dsa; - - if (cb != NULL) - fatal("%s: callback args not supported", __func__); - new_dsa = DSA_generate_parameters(bits, (unsigned char *)seed, seed_len, - counter_ret, h_ret, NULL, NULL); - if (new_dsa == NULL) - return 0; - /* swap dsa/new_dsa then free new_dsa */ - tmp_dsa = *dsa; - *dsa = *new_dsa; - *new_dsa = tmp_dsa; - DSA_free(new_dsa); - return 1; + long mask, hfix, lfix; + + /* exact match is always OK */ + if (headerver == libver) + return 1; + + /* for versions < 1.0.0, major,minor,fix,status must match */ + if (headerver < 0x1000000f) { + mask = 0xfffff00fL; /* major,minor,fix,status */ + return (headerver & mask) == (libver & mask); + } + + /* + * For versions >= 1.0.0, major,minor,status must match and library + * fix version must be equal to or newer than the header. + */ + mask = 0xfff0000fL; /* major,minor,status */ + hfix = (headerver & 0x000ff000) >> 12; + lfix = (libver & 0x000ff000) >> 12; + if ( (headerver & mask) == (libver & mask) && lfix >= hfix) + return 1; + return 0; } -#endif - -#ifndef HAVE_RSA_GET_DEFAULT_METHOD -RSA_METHOD * -RSA_get_default_method(void) -{ - return RSA_PKCS1_SSLeay(); -} -#endif #ifdef USE_OPENSSL_ENGINE void @@ -180,3 +80,5 @@ ssh_OpenSSL_add_all_algorithms(void) OPENSSL_config(NULL); } #endif + +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/openbsd-compat/openssl-compat.h b/crypto/openssh/openbsd-compat/openssl-compat.h index 276b970..8917551 100644 --- a/crypto/openssh/openbsd-compat/openssl-compat.h +++ b/crypto/openssh/openbsd-compat/openssl-compat.h @@ -1,4 +1,4 @@ -/* $Id: openssl-compat.h,v 1.26 2014/02/13 05:38:33 dtucker Exp $ */ +/* $Id: openssl-compat.h,v 1.31 2014/08/29 18:18:29 djm Exp $ */ /* * Copyright (c) 2005 Darren Tucker @@ -16,28 +16,21 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef _OPENSSL_COMPAT_H +#define _OPENSSL_COMPAT_H + #include "includes.h" +#ifdef WITH_OPENSSL + #include #include #include #include -/* Only in 0.9.8 */ -#ifndef OPENSSL_DSA_MAX_MODULUS_BITS -# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 -#endif -#ifndef OPENSSL_RSA_MAX_MODULUS_BITS -# define OPENSSL_RSA_MAX_MODULUS_BITS 16384 -#endif - -/* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */ -#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f) -# define OPENSSL_free(x) Free(x) -#endif +int ssh_compatible_openssl(long, long); -#if OPENSSL_VERSION_NUMBER < 0x00906000L -# define SSH_OLD_EVP -# define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data) +#if (OPENSSL_VERSION_NUMBER <= 0x0090805fL) +# error OpenSSL 0.9.8f or greater is required #endif #if OPENSSL_VERSION_NUMBER < 0x10000001L @@ -46,27 +39,17 @@ # define LIBCRYPTO_EVP_INL_TYPE size_t #endif -#if (OPENSSL_VERSION_NUMBER < 0x00907000L) || defined(OPENSSL_LOBOTOMISED_AES) -# define USE_BUILTIN_RIJNDAEL +#ifndef OPENSSL_RSA_MAX_MODULUS_BITS +# define OPENSSL_RSA_MAX_MODULUS_BITS 16384 #endif - -#ifdef USE_BUILTIN_RIJNDAEL -# include "rijndael.h" -# define AES_KEY rijndael_ctx -# define AES_BLOCK_SIZE 16 -# define AES_encrypt(a, b, c) rijndael_encrypt(c, a, b) -# define AES_set_encrypt_key(a, b, c) rijndael_set_key(c, (char *)a, b, 1) -# define EVP_aes_128_cbc evp_rijndael -# define EVP_aes_192_cbc evp_rijndael -# define EVP_aes_256_cbc evp_rijndael -const EVP_CIPHER *evp_rijndael(void); -void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); +#ifndef OPENSSL_DSA_MAX_MODULUS_BITS +# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 #endif #ifndef OPENSSL_HAVE_EVPCTR -#define EVP_aes_128_ctr evp_aes_128_ctr -#define EVP_aes_192_ctr evp_aes_128_ctr -#define EVP_aes_256_ctr evp_aes_128_ctr +# define EVP_aes_128_ctr evp_aes_128_ctr +# define EVP_aes_192_ctr evp_aes_128_ctr +# define EVP_aes_256_ctr evp_aes_128_ctr const EVP_CIPHER *evp_aes_128_ctr(void); void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); #endif @@ -88,26 +71,9 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); # endif #endif -#if OPENSSL_VERSION_NUMBER < 0x00907000L -#define EVP_X_STATE(evp) &(evp).c -#define EVP_X_STATE_LEN(evp) sizeof((evp).c) -#else -#define EVP_X_STATE(evp) (evp).cipher_data -#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size -#endif - -/* OpenSSL 0.9.8e returns cipher key len not context key len */ -#if (OPENSSL_VERSION_NUMBER == 0x0090805fL) -# define EVP_CIPHER_CTX_key_length(c) ((c)->key_len) -#endif - -#ifndef HAVE_RSA_GET_DEFAULT_METHOD -RSA_METHOD *RSA_get_default_method(void); -#endif - /* * We overload some of the OpenSSL crypto functions with ssh_* equivalents - * which cater for older and/or less featureful OpenSSL version. + * to automatically handle OpenSSL engine initialisation. * * In order for the compat library to call the real functions, it must * define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and @@ -115,19 +81,6 @@ RSA_METHOD *RSA_get_default_method(void); */ #ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS -# ifdef SSH_OLD_EVP -# ifdef EVP_Cipher -# undef EVP_Cipher -# endif -# define EVP_CipherInit(a,b,c,d,e) ssh_EVP_CipherInit((a),(b),(c),(d),(e)) -# define EVP_Cipher(a,b,c,d) ssh_EVP_Cipher((a),(b),(c),(d)) -# define EVP_CIPHER_CTX_cleanup(a) ssh_EVP_CIPHER_CTX_cleanup((a)) -# endif /* SSH_OLD_EVP */ - -# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID -# define EVP_DigestUpdate(a,b,c) ssh_EVP_DigestUpdate((a),(b),(c)) -# endif - # ifdef USE_OPENSSL_ENGINE # ifdef OpenSSL_add_all_algorithms # undef OpenSSL_add_all_algorithms @@ -135,48 +88,9 @@ RSA_METHOD *RSA_get_default_method(void); # define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms() # endif -# ifndef HAVE_BN_IS_PRIME_EX -int BN_is_prime_ex(const BIGNUM *, int, BN_CTX *, void *); -# endif - -# ifndef HAVE_DSA_GENERATE_PARAMETERS_EX -int DSA_generate_parameters_ex(DSA *, int, const unsigned char *, int, int *, - unsigned long *, void *); -# endif - -# ifndef HAVE_RSA_GENERATE_KEY_EX -int RSA_generate_key_ex(RSA *, int, BIGNUM *, void *); -# endif - -# ifndef HAVE_EVP_DIGESTINIT_EX -int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, void *); -# endif - -# ifndef HAVE_EVP_DISESTFINAL_EX -int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *); -# endif - -# ifndef EVP_MD_CTX_COPY_EX -int EVP_MD_CTX_copy_ex(EVP_MD_CTX *, const EVP_MD_CTX *); -# endif - -int ssh_EVP_CipherInit(EVP_CIPHER_CTX *, const EVP_CIPHER *, unsigned char *, - unsigned char *, int); -int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int); -int ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *); void ssh_OpenSSL_add_all_algorithms(void); -# ifndef HAVE_HMAC_CTX_INIT -# define HMAC_CTX_init(a) -# endif - -# ifndef HAVE_EVP_MD_CTX_INIT -# define EVP_MD_CTX_init(a) -# endif - -# ifndef HAVE_EVP_MD_CTX_CLEANUP -# define EVP_MD_CTX_cleanup(a) -# endif - #endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */ +#endif /* WITH_OPENSSL */ +#endif /* _OPENSSL_COMPAT_H */ diff --git a/crypto/openssh/openbsd-compat/port-linux.c b/crypto/openssh/openbsd-compat/port-linux.c index 4637a7a3..f36999d 100644 --- a/crypto/openssh/openbsd-compat/port-linux.c +++ b/crypto/openssh/openbsd-compat/port-linux.c @@ -278,7 +278,7 @@ oom_adjust_setup(void) verbose("error writing %s: %s", oom_adj_path, strerror(errno)); else - verbose("Set %s from %d to %d", + debug("Set %s from %d to %d", oom_adj_path, oom_adj_save, value); } fclose(fp); @@ -302,7 +302,7 @@ oom_adjust_restore(void) if (fprintf(fp, "%d\n", oom_adj_save) <= 0) verbose("error writing %s: %s", oom_adj_path, strerror(errno)); else - verbose("Set %s to %d", oom_adj_path, oom_adj_save); + debug("Set %s to %d", oom_adj_path, oom_adj_save); fclose(fp); return; diff --git a/crypto/openssh/openbsd-compat/port-tun.c b/crypto/openssh/openbsd-compat/port-tun.c index 0d756f7..49e7b4d 100644 --- a/crypto/openssh/openbsd-compat/port-tun.c +++ b/crypto/openssh/openbsd-compat/port-tun.c @@ -32,8 +32,9 @@ #include "openbsd-compat/sys-queue.h" #include "log.h" #include "misc.h" -#include "buffer.h" +#include "sshbuf.h" #include "channels.h" +#include "ssherr.h" /* * This is the portable version of the SSH tunnel forwarding, it @@ -210,6 +211,7 @@ sys_tun_infilter(struct Channel *c, char *buf, int len) #endif u_int32_t *af; char *ptr = buf; + int r; #if defined(SSH_TUN_PREPEND_AF) if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af))) @@ -242,7 +244,8 @@ sys_tun_infilter(struct Channel *c, char *buf, int len) *af = htonl(OPENBSD_AF_INET); #endif - buffer_put_string(&c->input, ptr, len); + if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); return (0); } @@ -251,8 +254,14 @@ sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen) { u_char *buf; u_int32_t *af; - - *data = buffer_get_string(&c->output, dlen); + int r; + size_t xxx_dlen; + + /* XXX new API is incompatible with this signature. */ + if ((r = sshbuf_get_string(&c->output, data, &xxx_dlen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (dlen != NULL) + *dlen = xxx_dlen; if (*dlen < sizeof(*af)) return (NULL); buf = *data; diff --git a/crypto/openssh/openbsd-compat/port-uw.c b/crypto/openssh/openbsd-compat/port-uw.c index b1fbfa2..db24dbb 100644 --- a/crypto/openssh/openbsd-compat/port-uw.c +++ b/crypto/openssh/openbsd-compat/port-uw.c @@ -42,6 +42,7 @@ #include "key.h" #include "auth-options.h" #include "log.h" +#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ #include "servconf.h" #include "hostfile.h" #include "auth.h" diff --git a/crypto/openssh/openbsd-compat/readpassphrase.c b/crypto/openssh/openbsd-compat/readpassphrase.c index 62b6d0d..d63cdf2 100644 --- a/crypto/openssh/openbsd-compat/readpassphrase.c +++ b/crypto/openssh/openbsd-compat/readpassphrase.c @@ -46,6 +46,14 @@ # define _POSIX_VDISABLE VDISABLE #endif +#ifndef _NSIG +# ifdef NSIG +# define _NSIG NSIG +# else +# define _NSIG 128 +# endif +#endif + static volatile sig_atomic_t signo[_NSIG]; static void handler(int); diff --git a/crypto/openssh/openbsd-compat/reallocarray.c b/crypto/openssh/openbsd-compat/reallocarray.c new file mode 100644 index 0000000..1a52acc --- /dev/null +++ b/crypto/openssh/openbsd-compat/reallocarray.c @@ -0,0 +1,46 @@ +/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */ +/* + * Copyright (c) 2008 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/reallocarray.c */ + +#include "includes.h" +#ifndef HAVE_REALLOCARRAY + +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +} +#endif /* HAVE_REALLOCARRAY */ diff --git a/crypto/openssh/openbsd-compat/realpath.c b/crypto/openssh/openbsd-compat/realpath.c index b6120d0..ba4cea9 100644 --- a/crypto/openssh/openbsd-compat/realpath.c +++ b/crypto/openssh/openbsd-compat/realpath.c @@ -33,11 +33,13 @@ #if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) +#include #include #include #include #include +#include #include #include @@ -90,7 +92,7 @@ realpath(const char *path, char resolved[PATH_MAX]) */ p = strchr(left, '/'); s = p ? p : left + left_len; - if (s - left >= sizeof(next_token)) { + if (s - left >= (ptrdiff_t)sizeof(next_token)) { errno = ENAMETOOLONG; return (NULL); } @@ -169,7 +171,8 @@ realpath(const char *path, char resolved[PATH_MAX]) */ if (p != NULL) { if (symlink[slen - 1] != '/') { - if (slen + 1 >= sizeof(symlink)) { + if (slen + 1 >= + (ptrdiff_t)sizeof(symlink)) { errno = ENAMETOOLONG; return (NULL); } diff --git a/crypto/openssh/openbsd-compat/regress/.cvsignore b/crypto/openssh/openbsd-compat/regress/.cvsignore new file mode 100644 index 0000000..33074f4 --- /dev/null +++ b/crypto/openssh/openbsd-compat/regress/.cvsignore @@ -0,0 +1,6 @@ +Makefile +snprintftest +strduptest +strtonumtest +closefromtest +opensslvertest diff --git a/crypto/openssh/openbsd-compat/regress/Makefile.in b/crypto/openssh/openbsd-compat/regress/Makefile.in index bcf214b..dabdb09 100644 --- a/crypto/openssh/openbsd-compat/regress/Makefile.in +++ b/crypto/openssh/openbsd-compat/regress/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.4 2006/08/19 09:12:14 dtucker Exp $ +# $Id: Makefile.in,v 1.5 2014/06/17 13:06:08 dtucker Exp $ sysconfdir=@sysconfdir@ piddir=@piddir@ @@ -16,11 +16,11 @@ LIBS=@LIBS@ LDFLAGS=@LDFLAGS@ $(LIBCOMPAT) TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \ - strtonumtest$(EXEEXT) + strtonumtest$(EXEEXT) opensslvertest$(EXEEXT) all: t-exec ${OTHERTESTS} -%$(EXEEXT): %.c +%$(EXEEXT): %.c $(LIBCOMPAT) $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBS) t-exec: $(TESTPROGS) diff --git a/crypto/openssh/openbsd-compat/regress/opensslvertest.c b/crypto/openssh/openbsd-compat/regress/opensslvertest.c new file mode 100644 index 0000000..5d019b5 --- /dev/null +++ b/crypto/openssh/openbsd-compat/regress/opensslvertest.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014 Darren Tucker + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +int ssh_compatible_openssl(long, long); + +struct version_test { + long headerver; + long libver; + int result; +} version_tests[] = { + /* built with 0.9.8b release headers */ + { 0x0090802fL, 0x0090802fL, 1}, /* exact match */ + { 0x0090802fL, 0x0090804fL, 1}, /* newer library fix version: ok */ + { 0x0090802fL, 0x0090801fL, 1}, /* older library fix version: ok */ + { 0x0090802fL, 0x0090702fL, 0}, /* older library minor version: NO */ + { 0x0090802fL, 0x0090902fL, 0}, /* newer library minor version: NO */ + { 0x0090802fL, 0x0080802fL, 0}, /* older library major version: NO */ + { 0x0090802fL, 0x1000100fL, 0}, /* newer library major version: NO */ + + /* built with 1.0.1b release headers */ + { 0x1000101fL, 0x1000101fL, 1},/* exact match */ + { 0x1000101fL, 0x1000102fL, 1}, /* newer library patch version: ok */ + { 0x1000101fL, 0x1000100fL, 1}, /* older library patch version: ok */ + { 0x1000101fL, 0x1000201fL, 1}, /* newer library fix version: ok */ + { 0x1000101fL, 0x1000001fL, 0}, /* older library fix version: NO */ + { 0x1000101fL, 0x1010101fL, 0}, /* newer library minor version: NO */ + { 0x1000101fL, 0x0000101fL, 0}, /* older library major version: NO */ + { 0x1000101fL, 0x2000101fL, 0}, /* newer library major version: NO */ +}; + +void +fail(long hver, long lver, int result) +{ + fprintf(stderr, "opensslver: header %lx library %lx != %d \n", hver, lver, result); + exit(1); +} + +int +main(void) +{ + unsigned int i; + int res; + long hver, lver; + + for (i = 0; i < sizeof(version_tests) / sizeof(version_tests[0]); i++) { + hver = version_tests[i].headerver; + lver = version_tests[i].libver; + res = version_tests[i].result; + if (ssh_compatible_openssl(hver, lver) != res) + fail(hver, lver, res); + } + exit(0); +} diff --git a/crypto/openssh/openbsd-compat/rmd160.c b/crypto/openssh/openbsd-compat/rmd160.c new file mode 100644 index 0000000..e915141 --- /dev/null +++ b/crypto/openssh/openbsd-compat/rmd160.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Preneel, Bosselaers, Dobbertin, "The Cryptographic Hash Function RIPEMD-160", + * RSA Laboratories, CryptoBytes, Volume 3, Number 2, Autumn 1997, + * ftp://ftp.rsasecurity.com/pub/cryptobytes/crypto3n2.pdf + */ + +#include "includes.h" + +#ifndef WITH_OPENSSL + +#include +#ifdef HAVE_ENDIAN_H +#include +#endif +#include +#include + +#define PUT_64BIT_LE(cp, value) do { \ + (cp)[7] = (value) >> 56; \ + (cp)[6] = (value) >> 48; \ + (cp)[5] = (value) >> 40; \ + (cp)[4] = (value) >> 32; \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +#define PUT_32BIT_LE(cp, value) do { \ + (cp)[3] = (value) >> 24; \ + (cp)[2] = (value) >> 16; \ + (cp)[1] = (value) >> 8; \ + (cp)[0] = (value); } while (0) + +#define H0 0x67452301U +#define H1 0xEFCDAB89U +#define H2 0x98BADCFEU +#define H3 0x10325476U +#define H4 0xC3D2E1F0U + +#define K0 0x00000000U +#define K1 0x5A827999U +#define K2 0x6ED9EBA1U +#define K3 0x8F1BBCDCU +#define K4 0xA953FD4EU + +#define KK0 0x50A28BE6U +#define KK1 0x5C4DD124U +#define KK2 0x6D703EF3U +#define KK3 0x7A6D76E9U +#define KK4 0x00000000U + +/* rotate x left n bits. */ +#define ROL(n, x) (((x) << (n)) | ((x) >> (32-(n)))) + +#define F0(x, y, z) ((x) ^ (y) ^ (z)) +#define F1(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define F2(x, y, z) (((x) | (~y)) ^ (z)) +#define F3(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define F4(x, y, z) ((x) ^ ((y) | (~z))) + +#define R(a, b, c, d, e, Fj, Kj, sj, rj) \ + do { \ + a = ROL(sj, a + Fj(b,c,d) + X(rj) + Kj) + e; \ + c = ROL(10, c); \ + } while(0) + +#define X(i) x[i] + +static u_int8_t PADDING[RMD160_BLOCK_LENGTH] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void +RMD160Init(RMD160_CTX *ctx) +{ + ctx->count = 0; + ctx->state[0] = H0; + ctx->state[1] = H1; + ctx->state[2] = H2; + ctx->state[3] = H3; + ctx->state[4] = H4; +} + +void +RMD160Update(RMD160_CTX *ctx, const u_int8_t *input, size_t len) +{ + size_t have, off, need; + + have = (ctx->count / 8) % RMD160_BLOCK_LENGTH; + need = RMD160_BLOCK_LENGTH - have; + ctx->count += 8 * len; + off = 0; + + if (len >= need) { + if (have) { + memcpy(ctx->buffer + have, input, need); + RMD160Transform(ctx->state, ctx->buffer); + off = need; + have = 0; + } + /* now the buffer is empty */ + while (off + RMD160_BLOCK_LENGTH <= len) { + RMD160Transform(ctx->state, input+off); + off += RMD160_BLOCK_LENGTH; + } + } + if (off < len) + memcpy(ctx->buffer + have, input+off, len-off); +} + +void +RMD160Pad(RMD160_CTX *ctx) +{ + u_int8_t size[8]; + size_t padlen; + + PUT_64BIT_LE(size, ctx->count); + + /* + * pad to RMD160_BLOCK_LENGTH byte blocks, at least one byte from + * PADDING plus 8 bytes for the size + */ + padlen = RMD160_BLOCK_LENGTH - ((ctx->count / 8) % RMD160_BLOCK_LENGTH); + if (padlen < 1 + 8) + padlen += RMD160_BLOCK_LENGTH; + RMD160Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ + RMD160Update(ctx, size, 8); +} + +void +RMD160Final(u_int8_t digest[RMD160_DIGEST_LENGTH], RMD160_CTX *ctx) +{ + int i; + + RMD160Pad(ctx); + for (i = 0; i < 5; i++) + PUT_32BIT_LE(digest + i*4, ctx->state[i]); + memset(ctx, 0, sizeof (*ctx)); +} + +void +RMD160Transform(u_int32_t state[5], const u_int8_t block[RMD160_BLOCK_LENGTH]) +{ + u_int32_t a, b, c, d, e, aa, bb, cc, dd, ee, t, x[16]; + +#if BYTE_ORDER == LITTLE_ENDIAN + memcpy(x, block, RMD160_BLOCK_LENGTH); +#else + int i; + + for (i = 0; i < 16; i++) + x[i] = (u_int32_t)( + (u_int32_t)(block[i*4 + 0]) | + (u_int32_t)(block[i*4 + 1]) << 8 | + (u_int32_t)(block[i*4 + 2]) << 16 | + (u_int32_t)(block[i*4 + 3]) << 24); +#endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* Round 1 */ + R(a, b, c, d, e, F0, K0, 11, 0); + R(e, a, b, c, d, F0, K0, 14, 1); + R(d, e, a, b, c, F0, K0, 15, 2); + R(c, d, e, a, b, F0, K0, 12, 3); + R(b, c, d, e, a, F0, K0, 5, 4); + R(a, b, c, d, e, F0, K0, 8, 5); + R(e, a, b, c, d, F0, K0, 7, 6); + R(d, e, a, b, c, F0, K0, 9, 7); + R(c, d, e, a, b, F0, K0, 11, 8); + R(b, c, d, e, a, F0, K0, 13, 9); + R(a, b, c, d, e, F0, K0, 14, 10); + R(e, a, b, c, d, F0, K0, 15, 11); + R(d, e, a, b, c, F0, K0, 6, 12); + R(c, d, e, a, b, F0, K0, 7, 13); + R(b, c, d, e, a, F0, K0, 9, 14); + R(a, b, c, d, e, F0, K0, 8, 15); /* #15 */ + /* Round 2 */ + R(e, a, b, c, d, F1, K1, 7, 7); + R(d, e, a, b, c, F1, K1, 6, 4); + R(c, d, e, a, b, F1, K1, 8, 13); + R(b, c, d, e, a, F1, K1, 13, 1); + R(a, b, c, d, e, F1, K1, 11, 10); + R(e, a, b, c, d, F1, K1, 9, 6); + R(d, e, a, b, c, F1, K1, 7, 15); + R(c, d, e, a, b, F1, K1, 15, 3); + R(b, c, d, e, a, F1, K1, 7, 12); + R(a, b, c, d, e, F1, K1, 12, 0); + R(e, a, b, c, d, F1, K1, 15, 9); + R(d, e, a, b, c, F1, K1, 9, 5); + R(c, d, e, a, b, F1, K1, 11, 2); + R(b, c, d, e, a, F1, K1, 7, 14); + R(a, b, c, d, e, F1, K1, 13, 11); + R(e, a, b, c, d, F1, K1, 12, 8); /* #31 */ + /* Round 3 */ + R(d, e, a, b, c, F2, K2, 11, 3); + R(c, d, e, a, b, F2, K2, 13, 10); + R(b, c, d, e, a, F2, K2, 6, 14); + R(a, b, c, d, e, F2, K2, 7, 4); + R(e, a, b, c, d, F2, K2, 14, 9); + R(d, e, a, b, c, F2, K2, 9, 15); + R(c, d, e, a, b, F2, K2, 13, 8); + R(b, c, d, e, a, F2, K2, 15, 1); + R(a, b, c, d, e, F2, K2, 14, 2); + R(e, a, b, c, d, F2, K2, 8, 7); + R(d, e, a, b, c, F2, K2, 13, 0); + R(c, d, e, a, b, F2, K2, 6, 6); + R(b, c, d, e, a, F2, K2, 5, 13); + R(a, b, c, d, e, F2, K2, 12, 11); + R(e, a, b, c, d, F2, K2, 7, 5); + R(d, e, a, b, c, F2, K2, 5, 12); /* #47 */ + /* Round 4 */ + R(c, d, e, a, b, F3, K3, 11, 1); + R(b, c, d, e, a, F3, K3, 12, 9); + R(a, b, c, d, e, F3, K3, 14, 11); + R(e, a, b, c, d, F3, K3, 15, 10); + R(d, e, a, b, c, F3, K3, 14, 0); + R(c, d, e, a, b, F3, K3, 15, 8); + R(b, c, d, e, a, F3, K3, 9, 12); + R(a, b, c, d, e, F3, K3, 8, 4); + R(e, a, b, c, d, F3, K3, 9, 13); + R(d, e, a, b, c, F3, K3, 14, 3); + R(c, d, e, a, b, F3, K3, 5, 7); + R(b, c, d, e, a, F3, K3, 6, 15); + R(a, b, c, d, e, F3, K3, 8, 14); + R(e, a, b, c, d, F3, K3, 6, 5); + R(d, e, a, b, c, F3, K3, 5, 6); + R(c, d, e, a, b, F3, K3, 12, 2); /* #63 */ + /* Round 5 */ + R(b, c, d, e, a, F4, K4, 9, 4); + R(a, b, c, d, e, F4, K4, 15, 0); + R(e, a, b, c, d, F4, K4, 5, 5); + R(d, e, a, b, c, F4, K4, 11, 9); + R(c, d, e, a, b, F4, K4, 6, 7); + R(b, c, d, e, a, F4, K4, 8, 12); + R(a, b, c, d, e, F4, K4, 13, 2); + R(e, a, b, c, d, F4, K4, 12, 10); + R(d, e, a, b, c, F4, K4, 5, 14); + R(c, d, e, a, b, F4, K4, 12, 1); + R(b, c, d, e, a, F4, K4, 13, 3); + R(a, b, c, d, e, F4, K4, 14, 8); + R(e, a, b, c, d, F4, K4, 11, 11); + R(d, e, a, b, c, F4, K4, 8, 6); + R(c, d, e, a, b, F4, K4, 5, 15); + R(b, c, d, e, a, F4, K4, 6, 13); /* #79 */ + + aa = a ; bb = b; cc = c; dd = d; ee = e; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* Parallel round 1 */ + R(a, b, c, d, e, F4, KK0, 8, 5); + R(e, a, b, c, d, F4, KK0, 9, 14); + R(d, e, a, b, c, F4, KK0, 9, 7); + R(c, d, e, a, b, F4, KK0, 11, 0); + R(b, c, d, e, a, F4, KK0, 13, 9); + R(a, b, c, d, e, F4, KK0, 15, 2); + R(e, a, b, c, d, F4, KK0, 15, 11); + R(d, e, a, b, c, F4, KK0, 5, 4); + R(c, d, e, a, b, F4, KK0, 7, 13); + R(b, c, d, e, a, F4, KK0, 7, 6); + R(a, b, c, d, e, F4, KK0, 8, 15); + R(e, a, b, c, d, F4, KK0, 11, 8); + R(d, e, a, b, c, F4, KK0, 14, 1); + R(c, d, e, a, b, F4, KK0, 14, 10); + R(b, c, d, e, a, F4, KK0, 12, 3); + R(a, b, c, d, e, F4, KK0, 6, 12); /* #15 */ + /* Parallel round 2 */ + R(e, a, b, c, d, F3, KK1, 9, 6); + R(d, e, a, b, c, F3, KK1, 13, 11); + R(c, d, e, a, b, F3, KK1, 15, 3); + R(b, c, d, e, a, F3, KK1, 7, 7); + R(a, b, c, d, e, F3, KK1, 12, 0); + R(e, a, b, c, d, F3, KK1, 8, 13); + R(d, e, a, b, c, F3, KK1, 9, 5); + R(c, d, e, a, b, F3, KK1, 11, 10); + R(b, c, d, e, a, F3, KK1, 7, 14); + R(a, b, c, d, e, F3, KK1, 7, 15); + R(e, a, b, c, d, F3, KK1, 12, 8); + R(d, e, a, b, c, F3, KK1, 7, 12); + R(c, d, e, a, b, F3, KK1, 6, 4); + R(b, c, d, e, a, F3, KK1, 15, 9); + R(a, b, c, d, e, F3, KK1, 13, 1); + R(e, a, b, c, d, F3, KK1, 11, 2); /* #31 */ + /* Parallel round 3 */ + R(d, e, a, b, c, F2, KK2, 9, 15); + R(c, d, e, a, b, F2, KK2, 7, 5); + R(b, c, d, e, a, F2, KK2, 15, 1); + R(a, b, c, d, e, F2, KK2, 11, 3); + R(e, a, b, c, d, F2, KK2, 8, 7); + R(d, e, a, b, c, F2, KK2, 6, 14); + R(c, d, e, a, b, F2, KK2, 6, 6); + R(b, c, d, e, a, F2, KK2, 14, 9); + R(a, b, c, d, e, F2, KK2, 12, 11); + R(e, a, b, c, d, F2, KK2, 13, 8); + R(d, e, a, b, c, F2, KK2, 5, 12); + R(c, d, e, a, b, F2, KK2, 14, 2); + R(b, c, d, e, a, F2, KK2, 13, 10); + R(a, b, c, d, e, F2, KK2, 13, 0); + R(e, a, b, c, d, F2, KK2, 7, 4); + R(d, e, a, b, c, F2, KK2, 5, 13); /* #47 */ + /* Parallel round 4 */ + R(c, d, e, a, b, F1, KK3, 15, 8); + R(b, c, d, e, a, F1, KK3, 5, 6); + R(a, b, c, d, e, F1, KK3, 8, 4); + R(e, a, b, c, d, F1, KK3, 11, 1); + R(d, e, a, b, c, F1, KK3, 14, 3); + R(c, d, e, a, b, F1, KK3, 14, 11); + R(b, c, d, e, a, F1, KK3, 6, 15); + R(a, b, c, d, e, F1, KK3, 14, 0); + R(e, a, b, c, d, F1, KK3, 6, 5); + R(d, e, a, b, c, F1, KK3, 9, 12); + R(c, d, e, a, b, F1, KK3, 12, 2); + R(b, c, d, e, a, F1, KK3, 9, 13); + R(a, b, c, d, e, F1, KK3, 12, 9); + R(e, a, b, c, d, F1, KK3, 5, 7); + R(d, e, a, b, c, F1, KK3, 15, 10); + R(c, d, e, a, b, F1, KK3, 8, 14); /* #63 */ + /* Parallel round 5 */ + R(b, c, d, e, a, F0, KK4, 8, 12); + R(a, b, c, d, e, F0, KK4, 5, 15); + R(e, a, b, c, d, F0, KK4, 12, 10); + R(d, e, a, b, c, F0, KK4, 9, 4); + R(c, d, e, a, b, F0, KK4, 12, 1); + R(b, c, d, e, a, F0, KK4, 5, 5); + R(a, b, c, d, e, F0, KK4, 14, 8); + R(e, a, b, c, d, F0, KK4, 6, 7); + R(d, e, a, b, c, F0, KK4, 8, 6); + R(c, d, e, a, b, F0, KK4, 13, 2); + R(b, c, d, e, a, F0, KK4, 6, 13); + R(a, b, c, d, e, F0, KK4, 5, 14); + R(e, a, b, c, d, F0, KK4, 15, 0); + R(d, e, a, b, c, F0, KK4, 13, 3); + R(c, d, e, a, b, F0, KK4, 11, 9); + R(b, c, d, e, a, F0, KK4, 11, 11); /* #79 */ + + t = state[1] + cc + d; + state[1] = state[2] + dd + e; + state[2] = state[3] + ee + a; + state[3] = state[4] + aa + b; + state[4] = state[0] + bb + c; + state[0] = t; +} + +#endif /* !WITH_OPENSSL */ diff --git a/crypto/openssh/openbsd-compat/rmd160.h b/crypto/openssh/openbsd-compat/rmd160.h new file mode 100644 index 0000000..99c1dcd --- /dev/null +++ b/crypto/openssh/openbsd-compat/rmd160.h @@ -0,0 +1,61 @@ +/* $OpenBSD: rmd160.h,v 1.17 2012/12/05 23:19:57 deraadt Exp $ */ +/* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _RMD160_H +#define _RMD160_H + +#ifndef WITH_OPENSSL + +#define RMD160_BLOCK_LENGTH 64 +#define RMD160_DIGEST_LENGTH 20 +#define RMD160_DIGEST_STRING_LENGTH (RMD160_DIGEST_LENGTH * 2 + 1) + +/* RMD160 context. */ +typedef struct RMD160Context { + u_int32_t state[5]; /* state */ + u_int64_t count; /* number of bits, mod 2^64 */ + u_int8_t buffer[RMD160_BLOCK_LENGTH]; /* input buffer */ +} RMD160_CTX; + +void RMD160Init(RMD160_CTX *); +void RMD160Transform(u_int32_t [5], const u_int8_t [RMD160_BLOCK_LENGTH]) + __attribute__((__bounded__(__minbytes__,1,5))) + __attribute__((__bounded__(__minbytes__,2,RMD160_BLOCK_LENGTH))); +void RMD160Update(RMD160_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void RMD160Pad(RMD160_CTX *); +void RMD160Final(u_int8_t [RMD160_DIGEST_LENGTH], RMD160_CTX *) + __attribute__((__bounded__(__minbytes__,1,RMD160_DIGEST_LENGTH))); +char *RMD160End(RMD160_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); +char *RMD160File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); +char *RMD160FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); +char *RMD160Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,RMD160_DIGEST_STRING_LENGTH))); + +#endif /* !WITH_OPENSSL */ +#endif /* _RMD160_H */ diff --git a/crypto/openssh/openbsd-compat/sha1.c b/crypto/openssh/openbsd-compat/sha1.c new file mode 100644 index 0000000..4b5381f --- /dev/null +++ b/crypto/openssh/openbsd-compat/sha1.c @@ -0,0 +1,177 @@ +/* $OpenBSD: sha1.c,v 1.23 2014/01/08 06:14:57 tedu Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +#include "includes.h" + +#ifndef WITH_OPENSSL + +#include +#include + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* + * blk0() and blk() perform the initial expand. + * I got the idea of expanding during the round function from SSLeay + */ +#if BYTE_ORDER == LITTLE_ENDIAN +# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +# define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 + */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +typedef union { + u_int8_t c[64]; + u_int32_t l[16]; +} CHAR64LONG16; + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ +void +SHA1Transform(u_int32_t state[5], const u_int8_t buffer[SHA1_BLOCK_LENGTH]) +{ + u_int32_t a, b, c, d, e; + u_int8_t workspace[SHA1_BLOCK_LENGTH]; + CHAR64LONG16 *block = (CHAR64LONG16 *)workspace; + + (void)memcpy(block, buffer, SHA1_BLOCK_LENGTH); + + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* + * SHA1Init - Initialize new context + */ +void +SHA1Init(SHA1_CTX *context) +{ + + /* SHA1 initialization constants */ + context->count = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; +} + + +/* + * Run your data through this. + */ +void +SHA1Update(SHA1_CTX *context, const u_int8_t *data, size_t len) +{ + size_t i, j; + + j = (size_t)((context->count >> 3) & 63); + context->count += (len << 3); + if ((j + len) > 63) { + (void)memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) + SHA1Transform(context->state, (u_int8_t *)&data[i]); + j = 0; + } else { + i = 0; + } + (void)memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* + * Add padding and return the message digest. + */ +void +SHA1Pad(SHA1_CTX *context) +{ + u_int8_t finalcount[8]; + u_int i; + + for (i = 0; i < 8; i++) { + finalcount[i] = (u_int8_t)((context->count >> + ((7 - (i & 7)) * 8)) & 255); /* Endian independent */ + } + SHA1Update(context, (u_int8_t *)"\200", 1); + while ((context->count & 504) != 448) + SHA1Update(context, (u_int8_t *)"\0", 1); + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ +} + +void +SHA1Final(u_int8_t digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) +{ + u_int i; + + SHA1Pad(context); + for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { + digest[i] = (u_int8_t) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + memset(context, 0, sizeof(*context)); +} +#endif /* !WITH_OPENSSL */ diff --git a/crypto/openssh/openbsd-compat/sha1.h b/crypto/openssh/openbsd-compat/sha1.h new file mode 100644 index 0000000..327d94c --- /dev/null +++ b/crypto/openssh/openbsd-compat/sha1.h @@ -0,0 +1,58 @@ +/* $OpenBSD: sha1.h,v 1.24 2012/12/05 23:19:57 deraadt Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +#ifndef _SHA1_H +#define _SHA1_H + +#ifndef WITH_OPENSSL + +#define SHA1_BLOCK_LENGTH 64 +#define SHA1_DIGEST_LENGTH 20 +#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1) + +typedef struct { + u_int32_t state[5]; + u_int64_t count; + u_int8_t buffer[SHA1_BLOCK_LENGTH]; +} SHA1_CTX; + +void SHA1Init(SHA1_CTX *); +void SHA1Pad(SHA1_CTX *); +void SHA1Transform(u_int32_t [5], const u_int8_t [SHA1_BLOCK_LENGTH]) + __attribute__((__bounded__(__minbytes__,1,5))) + __attribute__((__bounded__(__minbytes__,2,SHA1_BLOCK_LENGTH))); +void SHA1Update(SHA1_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA1Final(u_int8_t [SHA1_DIGEST_LENGTH], SHA1_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA1_DIGEST_LENGTH))); +char *SHA1End(SHA1_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); +char *SHA1File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); +char *SHA1FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA1_DIGEST_STRING_LENGTH))); +char *SHA1Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA1_DIGEST_STRING_LENGTH))); + +#define HTONDIGEST(x) do { \ + x[0] = htonl(x[0]); \ + x[1] = htonl(x[1]); \ + x[2] = htonl(x[2]); \ + x[3] = htonl(x[3]); \ + x[4] = htonl(x[4]); } while (0) + +#define NTOHDIGEST(x) do { \ + x[0] = ntohl(x[0]); \ + x[1] = ntohl(x[1]); \ + x[2] = ntohl(x[2]); \ + x[3] = ntohl(x[3]); \ + x[4] = ntohl(x[4]); } while (0) + +#endif /* !WITH_OPENSSL */ +#endif /* _SHA1_H */ diff --git a/crypto/openssh/openbsd-compat/sha2.c b/crypto/openssh/openbsd-compat/sha2.c index f5bf74d..737935d 100644 --- a/crypto/openssh/openbsd-compat/sha2.c +++ b/crypto/openssh/openbsd-compat/sha2.c @@ -38,13 +38,18 @@ #include "includes.h" -#include +#ifdef WITH_OPENSSL +# include +# if !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L) +# define _NEED_SHA2 1 +# endif +#else +# define _NEED_SHA2 1 +#endif + +#if defined(_NEED_SHA2) && !defined(HAVE_SHA256_UPDATE) -#if !defined(HAVE_EVP_SHA256) && !defined(HAVE_SHA256_UPDATE) && \ - (OPENSSL_VERSION_NUMBER >= 0x00907000L) -#include #include -#include "sha2.h" /* * UNROLLED TRANSFORM LOOP NOTE: @@ -838,7 +843,6 @@ SHA512_Final(u_int8_t digest[SHA512_DIGEST_LENGTH], SHA512_CTX *context) } -#if 0 /*** SHA-384: *********************************************************/ void SHA384_Init(SHA384_CTX *context) @@ -851,9 +855,29 @@ SHA384_Init(SHA384_CTX *context) context->bitcount[0] = context->bitcount[1] = 0; } +#if 0 __weak_alias(SHA384_Transform, SHA512_Transform); __weak_alias(SHA384_Update, SHA512_Update); __weak_alias(SHA384_Pad, SHA512_Pad); +#endif + +void +SHA384_Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH]) +{ + return SHA512_Transform(state, data); +} + +void +SHA384_Update(SHA512_CTX *context, const u_int8_t *data, size_t len) +{ + SHA512_Update(context, data, len); +} + +void +SHA384_Pad(SHA512_CTX *context) +{ + SHA512_Pad(context); +} void SHA384_Final(u_int8_t digest[SHA384_DIGEST_LENGTH], SHA384_CTX *context) @@ -876,7 +900,5 @@ SHA384_Final(u_int8_t digest[SHA384_DIGEST_LENGTH], SHA384_CTX *context) /* Zero out state data */ memset(context, 0, sizeof(*context)); } -#endif -#endif /* !defined(HAVE_EVP_SHA256) && !defined(HAVE_SHA256_UPDATE) && \ - (OPENSSL_VERSION_NUMBER >= 0x00907000L) */ +#endif /* defined(_NEED_SHA2) && !defined(HAVE_SHA256_UPDATE) */ diff --git a/crypto/openssh/openbsd-compat/sha2.h b/crypto/openssh/openbsd-compat/sha2.h index 73e94f1..c8bfc3c 100644 --- a/crypto/openssh/openbsd-compat/sha2.h +++ b/crypto/openssh/openbsd-compat/sha2.h @@ -41,10 +41,16 @@ #include "includes.h" -#include +#ifdef WITH_OPENSSL +# include +# if !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L) +# define _NEED_SHA2 1 +# endif +#else +# define _NEED_SHA2 1 +#endif -#if !defined(HAVE_EVP_SHA256) && !defined(HAVE_SHA256_UPDATE) && \ - (OPENSSL_VERSION_NUMBER >= 0x00907000L) +#if defined(_NEED_SHA2) && !defined(HAVE_SHA256_UPDATE) /*** SHA-256/384/512 Various Length Definitions ***********************/ #define SHA256_BLOCK_LENGTH 64 @@ -70,9 +76,7 @@ typedef struct _SHA512_CTX { u_int8_t buffer[SHA512_BLOCK_LENGTH]; } SHA512_CTX; -#if 0 typedef SHA512_CTX SHA384_CTX; -#endif void SHA256_Init(SHA256_CTX *); void SHA256_Transform(u_int32_t state[8], const u_int8_t [SHA256_BLOCK_LENGTH]); @@ -91,7 +95,6 @@ char *SHA256_Data(const u_int8_t *, size_t, char *) __attribute__((__bounded__(__string__,1,2))) __attribute__((__bounded__(__minbytes__,3,SHA256_DIGEST_STRING_LENGTH))); -#if 0 void SHA384_Init(SHA384_CTX *); void SHA384_Transform(u_int64_t state[8], const u_int8_t [SHA384_BLOCK_LENGTH]); void SHA384_Update(SHA384_CTX *, const u_int8_t *, size_t) @@ -108,7 +111,6 @@ char *SHA384_FileChunk(const char *, char *, off_t, off_t) char *SHA384_Data(const u_int8_t *, size_t, char *) __attribute__((__bounded__(__string__,1,2))) __attribute__((__bounded__(__minbytes__,3,SHA384_DIGEST_STRING_LENGTH))); -#endif /* 0 */ void SHA512_Init(SHA512_CTX *); void SHA512_Transform(u_int64_t state[8], const u_int8_t [SHA512_BLOCK_LENGTH]); @@ -127,7 +129,6 @@ char *SHA512_Data(const u_int8_t *, size_t, char *) __attribute__((__bounded__(__string__,1,2))) __attribute__((__bounded__(__minbytes__,3,SHA512_DIGEST_STRING_LENGTH))); -#endif /* !defined(HAVE_EVP_SHA256) && !defined(HAVE_SHA256_UPDATE) && \ - (OPENSSL_VERSION_NUMBER >= 0x00907000L) */ +#endif /* defined(_NEED_SHA2) && !defined(HAVE_SHA256_UPDATE) */ #endif /* _SSHSHA2_H */ diff --git a/crypto/openssh/openbsd-compat/xcrypt.c b/crypto/openssh/openbsd-compat/xcrypt.c index c8aea46..8577cbd 100644 --- a/crypto/openssh/openbsd-compat/xcrypt.c +++ b/crypto/openssh/openbsd-compat/xcrypt.c @@ -57,7 +57,7 @@ # include "md5crypt.h" # endif -# if !defined(HAVE_CRYPT) && defined(HAVE_DES_CRYPT) +# if defined(WITH_OPENSSL) && !defined(HAVE_CRYPT) && defined(HAVE_DES_CRYPT) # include # define crypt DES_crypt # endif diff --git a/crypto/openssh/opensshd.init.in b/crypto/openssh/opensshd.init.in index 0db60ca..517345b 100755 --- a/crypto/openssh/opensshd.init.in +++ b/crypto/openssh/opensshd.init.in @@ -21,6 +21,7 @@ HOST_KEY_RSA1=$sysconfdir/ssh_host_key HOST_KEY_DSA=$sysconfdir/ssh_host_dsa_key HOST_KEY_RSA=$sysconfdir/ssh_host_rsa_key @COMMENT_OUT_ECC@HOST_KEY_ECDSA=$sysconfdir/ssh_host_ecdsa_key +HOST_KEY_ED25519=$sysconfdir/ssh_host_ed25519_key checkkeys() { @@ -36,6 +37,9 @@ checkkeys() { @COMMENT_OUT_ECC@ if [ ! -f $HOST_KEY_ECDSA ]; then @COMMENT_OUT_ECC@ ${SSH_KEYGEN} -t ecdsa -f ${HOST_KEY_ECDSA} -N "" @COMMENT_OUT_ECC@ fi + if [ ! -f $HOST_KEY_ED25519 ]; then + ${SSH_KEYGEN} -t ed25519 -f ${HOST_KEY_ED25519} -N "" + fi } stop_service() { diff --git a/crypto/openssh/packet.c b/crypto/openssh/packet.c index ff70e60..8c1498c 100644 --- a/crypto/openssh/packet.c +++ b/crypto/openssh/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.192 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.214 2015/08/20 22:32:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -40,9 +40,9 @@ #include "includes.h" __RCSID("$FreeBSD$"); +#include /* MIN roundup */ #include #include "openbsd-compat/sys-queue.h" -#include #include #ifdef HAVE_SYS_TIME_H # include @@ -58,28 +58,35 @@ __RCSID("$FreeBSD$"); #include #include #include +#include #include #include +#include + +#include "buffer.h" /* typedefs XXX */ +#include "key.h" /* typedefs XXX */ + #include "xmalloc.h" -#include "buffer.h" -#include "packet.h" #include "crc32.h" -#include "compress.h" #include "deattack.h" -#include "channels.h" #include "compat.h" #include "ssh1.h" #include "ssh2.h" #include "cipher.h" -#include "key.h" +#include "sshkey.h" #include "kex.h" +#include "digest.h" #include "mac.h" #include "log.h" #include "canohost.h" #include "misc.h" +#include "channels.h" #include "ssh.h" +#include "packet.h" #include "roaming.h" +#include "ssherr.h" +#include "sshbuf.h" #ifdef PACKET_DEBUG #define DBG(x) x @@ -99,7 +106,7 @@ struct packet_state { struct packet { TAILQ_ENTRY(packet) next; u_char type; - Buffer payload; + struct sshbuf *payload; }; struct session_state { @@ -116,26 +123,33 @@ struct session_state { u_int remote_protocol_flags; /* Encryption context for receiving data. Only used for decryption. */ - CipherContext receive_context; + struct sshcipher_ctx receive_context; /* Encryption context for sending data. Only used for encryption. */ - CipherContext send_context; + struct sshcipher_ctx send_context; /* Buffer for raw input data from the socket. */ - Buffer input; + struct sshbuf *input; /* Buffer for raw output data going to the socket. */ - Buffer output; + struct sshbuf *output; /* Buffer for the partial outgoing packet being constructed. */ - Buffer outgoing_packet; + struct sshbuf *outgoing_packet; /* Buffer for the incoming packet currently being processed. */ - Buffer incoming_packet; + struct sshbuf *incoming_packet; /* Scratch buffer for packet compression/decompression. */ - Buffer compression_buffer; - int compression_buffer_ready; + struct sshbuf *compression_buffer; + + /* Incoming/outgoing compression dictionaries */ + z_stream compression_in_stream; + z_stream compression_out_stream; + int compression_in_started; + int compression_out_started; + int compression_in_failures; + int compression_out_failures; /* * Flag indicating whether packet compression/decompression is @@ -164,7 +178,7 @@ struct session_state { int packet_timeout_ms; /* Session key information for Encryption and MAC */ - Newkeys *newkeys[MODE_MAX]; + struct newkeys *newkeys[MODE_MAX]; struct packet_state p_read, p_send; /* Volume-based rekeying */ @@ -172,7 +186,7 @@ struct session_state { u_int32_t rekey_limit; /* Time-based rekeying */ - time_t rekey_interval; /* how often in seconds */ + u_int32_t rekey_interval; /* how often in seconds */ time_t rekey_time; /* time of last rekeying */ /* Session key for protocol v1 */ @@ -184,7 +198,7 @@ struct session_state { /* XXX discard incoming data after MAC error */ u_int packet_discard; - Mac *packet_discard_mac; + struct sshmac *packet_discard_mac; /* Used in packet_read_poll2() */ u_int packlen; @@ -198,119 +212,178 @@ struct session_state { /* Used in packet_set_maxsize */ int set_maxsize_called; - TAILQ_HEAD(, packet) outgoing; -}; + /* One-off warning about weak ciphers */ + int cipher_warning_done; -static struct session_state *active_state, *backup_state; + /* SSH1 CRC compensation attack detector */ + struct deattack_ctx deattack; -static struct session_state * -alloc_session_state(void) -{ - struct session_state *s = xcalloc(1, sizeof(*s)); + TAILQ_HEAD(, packet) outgoing; +}; - s->connection_in = -1; - s->connection_out = -1; - s->max_packet_size = 32768; - s->packet_timeout_ms = -1; - return s; +struct ssh * +ssh_alloc_session_state(void) +{ + struct ssh *ssh = NULL; + struct session_state *state = NULL; + + if ((ssh = calloc(1, sizeof(*ssh))) == NULL || + (state = calloc(1, sizeof(*state))) == NULL || + (state->input = sshbuf_new()) == NULL || + (state->output = sshbuf_new()) == NULL || + (state->outgoing_packet = sshbuf_new()) == NULL || + (state->incoming_packet = sshbuf_new()) == NULL) + goto fail; + TAILQ_INIT(&state->outgoing); + TAILQ_INIT(&ssh->private_keys); + TAILQ_INIT(&ssh->public_keys); + state->connection_in = -1; + state->connection_out = -1; + state->max_packet_size = 32768; + state->packet_timeout_ms = -1; + state->p_send.packets = state->p_read.packets = 0; + state->initialized = 1; + /* + * ssh_packet_send2() needs to queue packets until + * we've done the initial key exchange. + */ + state->rekeying = 1; + ssh->state = state; + return ssh; + fail: + if (state) { + sshbuf_free(state->input); + sshbuf_free(state->output); + sshbuf_free(state->incoming_packet); + sshbuf_free(state->outgoing_packet); + free(state); + } + free(ssh); + return NULL; } /* * Sets the descriptors used for communication. Disables encryption until * packet_set_encryption_key is called. */ -void -packet_set_connection(int fd_in, int fd_out) -{ - const Cipher *none = cipher_by_name("none"); - - if (none == NULL) - fatal("packet_set_connection: cannot load cipher 'none'"); - if (active_state == NULL) - active_state = alloc_session_state(); - active_state->connection_in = fd_in; - active_state->connection_out = fd_out; - cipher_init(&active_state->send_context, none, (const u_char *)"", - 0, NULL, 0, CIPHER_ENCRYPT); - cipher_init(&active_state->receive_context, none, (const u_char *)"", - 0, NULL, 0, CIPHER_DECRYPT); - active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL; - if (!active_state->initialized) { - active_state->initialized = 1; - buffer_init(&active_state->input); - buffer_init(&active_state->output); - buffer_init(&active_state->outgoing_packet); - buffer_init(&active_state->incoming_packet); - TAILQ_INIT(&active_state->outgoing); - active_state->p_send.packets = active_state->p_read.packets = 0; +struct ssh * +ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) +{ + struct session_state *state; + const struct sshcipher *none = cipher_by_name("none"); + int r; + + if (none == NULL) { + error("%s: cannot load cipher 'none'", __func__); + return NULL; + } + if (ssh == NULL) + ssh = ssh_alloc_session_state(); + if (ssh == NULL) { + error("%s: cound not allocate state", __func__); + return NULL; } + state = ssh->state; + state->connection_in = fd_in; + state->connection_out = fd_out; + if ((r = cipher_init(&state->send_context, none, + (const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 || + (r = cipher_init(&state->receive_context, none, + (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) { + error("%s: cipher_init failed: %s", __func__, ssh_err(r)); + free(ssh); + return NULL; + } + state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL; + deattack_init(&state->deattack); + /* + * Cache the IP address of the remote connection for use in error + * messages that might be generated after the connection has closed. + */ + (void)ssh_remote_ipaddr(ssh); + return ssh; } void -packet_set_timeout(int timeout, int count) +ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count) { + struct session_state *state = ssh->state; + if (timeout <= 0 || count <= 0) { - active_state->packet_timeout_ms = -1; + state->packet_timeout_ms = -1; return; } if ((INT_MAX / 1000) / count < timeout) - active_state->packet_timeout_ms = INT_MAX; + state->packet_timeout_ms = INT_MAX; else - active_state->packet_timeout_ms = timeout * count * 1000; + state->packet_timeout_ms = timeout * count * 1000; } -static void -packet_stop_discard(void) +int +ssh_packet_stop_discard(struct ssh *ssh) { - if (active_state->packet_discard_mac) { + struct session_state *state = ssh->state; + int r; + + if (state->packet_discard_mac) { char buf[1024]; - + memset(buf, 'a', sizeof(buf)); - while (buffer_len(&active_state->incoming_packet) < + while (sshbuf_len(state->incoming_packet) < PACKET_MAX_SIZE) - buffer_append(&active_state->incoming_packet, buf, - sizeof(buf)); - (void) mac_compute(active_state->packet_discard_mac, - active_state->p_read.seqnr, - buffer_ptr(&active_state->incoming_packet), - PACKET_MAX_SIZE); - } - logit("Finished discarding for %.200s", get_remote_ipaddr()); - cleanup_exit(255); + if ((r = sshbuf_put(state->incoming_packet, buf, + sizeof(buf))) != 0) + return r; + (void) mac_compute(state->packet_discard_mac, + state->p_read.seqnr, + sshbuf_ptr(state->incoming_packet), PACKET_MAX_SIZE, + NULL, 0); + } + logit("Finished discarding for %.200s", ssh_remote_ipaddr(ssh)); + return SSH_ERR_MAC_INVALID; } -static void -packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard) +static int +ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc, + struct sshmac *mac, u_int packet_length, u_int discard) { - if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) - packet_disconnect("Packet corrupt"); + struct session_state *state = ssh->state; + int r; + + if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) { + if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0) + return r; + return SSH_ERR_MAC_INVALID; + } if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) - active_state->packet_discard_mac = mac; - if (buffer_len(&active_state->input) >= discard) - packet_stop_discard(); - active_state->packet_discard = discard - - buffer_len(&active_state->input); + state->packet_discard_mac = mac; + if (sshbuf_len(state->input) >= discard && + (r = ssh_packet_stop_discard(ssh)) != 0) + return r; + state->packet_discard = discard - sshbuf_len(state->input); + return 0; } /* Returns 1 if remote host is connected via socket, 0 if not. */ int -packet_connection_is_on_socket(void) +ssh_packet_connection_is_on_socket(struct ssh *ssh) { + struct session_state *state = ssh->state; struct sockaddr_storage from, to; socklen_t fromlen, tolen; /* filedescriptors in and out are the same, so it's a socket */ - if (active_state->connection_in == active_state->connection_out) + if (state->connection_in == state->connection_out) return 1; fromlen = sizeof(from); memset(&from, 0, sizeof(from)); - if (getpeername(active_state->connection_in, (struct sockaddr *)&from, + if (getpeername(state->connection_in, (struct sockaddr *)&from, &fromlen) < 0) return 0; tolen = sizeof(to); memset(&to, 0, sizeof(to)); - if (getpeername(active_state->connection_out, (struct sockaddr *)&to, + if (getpeername(state->connection_out, (struct sockaddr *)&to, &tolen) < 0) return 0; if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) @@ -320,123 +393,23 @@ packet_connection_is_on_socket(void) return 1; } -/* - * Exports an IV from the CipherContext required to export the key - * state back from the unprivileged child to the privileged parent - * process. - */ - -void -packet_get_keyiv(int mode, u_char *iv, u_int len) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &active_state->send_context; - else - cc = &active_state->receive_context; - - cipher_get_keyiv(cc, iv, len); -} - -int -packet_get_keycontext(int mode, u_char *dat) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &active_state->send_context; - else - cc = &active_state->receive_context; - - return (cipher_get_keycontext(cc, dat)); -} - -void -packet_set_keycontext(int mode, u_char *dat) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &active_state->send_context; - else - cc = &active_state->receive_context; - - cipher_set_keycontext(cc, dat); -} - -int -packet_get_keyiv_len(int mode) -{ - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &active_state->send_context; - else - cc = &active_state->receive_context; - - return (cipher_get_keyiv_len(cc)); -} - void -packet_set_iv(int mode, u_char *dat) +ssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes) { - CipherContext *cc; - - if (mode == MODE_OUT) - cc = &active_state->send_context; - else - cc = &active_state->receive_context; - - cipher_set_keyiv(cc, dat); + if (ibytes) + *ibytes = ssh->state->p_read.bytes; + if (obytes) + *obytes = ssh->state->p_send.bytes; } int -packet_get_ssh1_cipher(void) -{ - return (cipher_get_number(active_state->receive_context.cipher)); -} - -void -packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, - u_int32_t *packets, u_int64_t *bytes) -{ - struct packet_state *state; - - state = (mode == MODE_IN) ? - &active_state->p_read : &active_state->p_send; - if (seqnr) - *seqnr = state->seqnr; - if (blocks) - *blocks = state->blocks; - if (packets) - *packets = state->packets; - if (bytes) - *bytes = state->bytes; -} - -void -packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets, - u_int64_t bytes) -{ - struct packet_state *state; - - state = (mode == MODE_IN) ? - &active_state->p_read : &active_state->p_send; - state->seqnr = seqnr; - state->blocks = blocks; - state->packets = packets; - state->bytes = bytes; -} - -static int -packet_connection_af(void) +ssh_packet_connection_af(struct ssh *ssh) { struct sockaddr_storage to; socklen_t tolen = sizeof(to); memset(&to, 0, sizeof(to)); - if (getsockname(active_state->connection_out, (struct sockaddr *)&to, + if (getsockname(ssh->state->connection_out, (struct sockaddr *)&to, &tolen) < 0) return 0; #ifdef IPV4_IN_IPV6 @@ -450,72 +423,125 @@ packet_connection_af(void) /* Sets the connection into non-blocking mode. */ void -packet_set_nonblocking(void) +ssh_packet_set_nonblocking(struct ssh *ssh) { /* Set the socket into non-blocking mode. */ - set_nonblock(active_state->connection_in); + set_nonblock(ssh->state->connection_in); - if (active_state->connection_out != active_state->connection_in) - set_nonblock(active_state->connection_out); + if (ssh->state->connection_out != ssh->state->connection_in) + set_nonblock(ssh->state->connection_out); } /* Returns the socket used for reading. */ int -packet_get_connection_in(void) +ssh_packet_get_connection_in(struct ssh *ssh) { - return active_state->connection_in; + return ssh->state->connection_in; } /* Returns the descriptor used for writing. */ int -packet_get_connection_out(void) +ssh_packet_get_connection_out(struct ssh *ssh) { - return active_state->connection_out; + return ssh->state->connection_out; +} + +/* + * Returns the IP-address of the remote host as a string. The returned + * string must not be freed. + */ + +const char * +ssh_remote_ipaddr(struct ssh *ssh) +{ + /* Check whether we have cached the ipaddr. */ + if (ssh->remote_ipaddr == NULL) + ssh->remote_ipaddr = ssh_packet_connection_is_on_socket(ssh) ? + get_peer_ipaddr(ssh->state->connection_in) : + strdup("UNKNOWN"); + if (ssh->remote_ipaddr == NULL) + return "UNKNOWN"; + return ssh->remote_ipaddr; } /* Closes the connection and clears and frees internal data structures. */ void -packet_close(void) +ssh_packet_close(struct ssh *ssh) { - if (!active_state->initialized) + struct session_state *state = ssh->state; + int r; + u_int mode; + + if (!state->initialized) return; - active_state->initialized = 0; - if (active_state->connection_in == active_state->connection_out) { - shutdown(active_state->connection_out, SHUT_RDWR); - close(active_state->connection_out); + state->initialized = 0; + if (state->connection_in == state->connection_out) { + shutdown(state->connection_out, SHUT_RDWR); + close(state->connection_out); } else { - close(active_state->connection_in); - close(active_state->connection_out); + close(state->connection_in); + close(state->connection_out); + } + sshbuf_free(state->input); + sshbuf_free(state->output); + sshbuf_free(state->outgoing_packet); + sshbuf_free(state->incoming_packet); + for (mode = 0; mode < MODE_MAX; mode++) + kex_free_newkeys(state->newkeys[mode]); + if (state->compression_buffer) { + sshbuf_free(state->compression_buffer); + if (state->compression_out_started) { + z_streamp stream = &state->compression_out_stream; + debug("compress outgoing: " + "raw data %llu, compressed %llu, factor %.2f", + (unsigned long long)stream->total_in, + (unsigned long long)stream->total_out, + stream->total_in == 0 ? 0.0 : + (double) stream->total_out / stream->total_in); + if (state->compression_out_failures == 0) + deflateEnd(stream); + } + if (state->compression_in_started) { + z_streamp stream = &state->compression_out_stream; + debug("compress incoming: " + "raw data %llu, compressed %llu, factor %.2f", + (unsigned long long)stream->total_out, + (unsigned long long)stream->total_in, + stream->total_out == 0 ? 0.0 : + (double) stream->total_in / stream->total_out); + if (state->compression_in_failures == 0) + inflateEnd(stream); + } } - buffer_free(&active_state->input); - buffer_free(&active_state->output); - buffer_free(&active_state->outgoing_packet); - buffer_free(&active_state->incoming_packet); - if (active_state->compression_buffer_ready) { - buffer_free(&active_state->compression_buffer); - buffer_compress_uninit(); + if ((r = cipher_cleanup(&state->send_context)) != 0) + error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); + if ((r = cipher_cleanup(&state->receive_context)) != 0) + error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); + if (ssh->remote_ipaddr) { + free(ssh->remote_ipaddr); + ssh->remote_ipaddr = NULL; } - cipher_cleanup(&active_state->send_context); - cipher_cleanup(&active_state->receive_context); + free(ssh->state); + ssh->state = NULL; } /* Sets remote side protocol flags. */ void -packet_set_protocol_flags(u_int protocol_flags) +ssh_packet_set_protocol_flags(struct ssh *ssh, u_int protocol_flags) { - active_state->remote_protocol_flags = protocol_flags; + ssh->state->remote_protocol_flags = protocol_flags; } /* Returns the remote protocol flags set earlier by the above function. */ u_int -packet_get_protocol_flags(void) +ssh_packet_get_protocol_flags(struct ssh *ssh) { - return active_state->remote_protocol_flags; + return ssh->state->remote_protocol_flags; } /* @@ -523,247 +549,405 @@ packet_get_protocol_flags(void) * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */ -static void -packet_init_compression(void) +static int +ssh_packet_init_compression(struct ssh *ssh) { - if (active_state->compression_buffer_ready == 1) - return; - active_state->compression_buffer_ready = 1; - buffer_init(&active_state->compression_buffer); + if (!ssh->state->compression_buffer && + ((ssh->state->compression_buffer = sshbuf_new()) == NULL)) + return SSH_ERR_ALLOC_FAIL; + return 0; } -void -packet_start_compression(int level) -{ - if (active_state->packet_compression && !compat20) - fatal("Compression already enabled."); - active_state->packet_compression = 1; - packet_init_compression(); - buffer_compress_init_send(level); - buffer_compress_init_recv(); +static int +start_compression_out(struct ssh *ssh, int level) +{ + if (level < 1 || level > 9) + return SSH_ERR_INVALID_ARGUMENT; + debug("Enabling compression at level %d.", level); + if (ssh->state->compression_out_started == 1) + deflateEnd(&ssh->state->compression_out_stream); + switch (deflateInit(&ssh->state->compression_out_stream, level)) { + case Z_OK: + ssh->state->compression_out_started = 1; + break; + case Z_MEM_ERROR: + return SSH_ERR_ALLOC_FAIL; + default: + return SSH_ERR_INTERNAL_ERROR; + } + return 0; } -/* - * Causes any further packets to be encrypted using the given key. The same - * key is used for both sending and reception. However, both directions are - * encrypted independently of each other. - */ - -void -packet_set_encryption_key(const u_char *key, u_int keylen, int number) +static int +start_compression_in(struct ssh *ssh) { - const Cipher *cipher = cipher_by_number(number); - - if (cipher == NULL) - fatal("packet_set_encryption_key: unknown cipher number %d", number); - if (keylen < 20) - fatal("packet_set_encryption_key: keylen too small: %d", keylen); - if (keylen > SSH_SESSION_KEY_LENGTH) - fatal("packet_set_encryption_key: keylen too big: %d", keylen); - memcpy(active_state->ssh1_key, key, keylen); - active_state->ssh1_keylen = keylen; - cipher_init(&active_state->send_context, cipher, key, keylen, NULL, - 0, CIPHER_ENCRYPT); - cipher_init(&active_state->receive_context, cipher, key, keylen, NULL, - 0, CIPHER_DECRYPT); + if (ssh->state->compression_in_started == 1) + inflateEnd(&ssh->state->compression_in_stream); + switch (inflateInit(&ssh->state->compression_in_stream)) { + case Z_OK: + ssh->state->compression_in_started = 1; + break; + case Z_MEM_ERROR: + return SSH_ERR_ALLOC_FAIL; + default: + return SSH_ERR_INTERNAL_ERROR; + } + return 0; } -u_int -packet_get_encryption_key(u_char *key) +int +ssh_packet_start_compression(struct ssh *ssh, int level) { - if (key == NULL) - return (active_state->ssh1_keylen); - memcpy(key, active_state->ssh1_key, active_state->ssh1_keylen); - return (active_state->ssh1_keylen); + int r; + + if (ssh->state->packet_compression && !compat20) + return SSH_ERR_INTERNAL_ERROR; + ssh->state->packet_compression = 1; + if ((r = ssh_packet_init_compression(ssh)) != 0 || + (r = start_compression_in(ssh)) != 0 || + (r = start_compression_out(ssh, level)) != 0) + return r; + return 0; } -/* Start constructing a packet to send. */ -void -packet_start(u_char type) +/* XXX remove need for separate compression buffer */ +static int +compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) { - u_char buf[9]; - int len; + u_char buf[4096]; + int r, status; - DBG(debug("packet_start[%d]", type)); - len = compat20 ? 6 : 9; - memset(buf, 0, len - 1); - buf[len - 1] = type; - buffer_clear(&active_state->outgoing_packet); - buffer_append(&active_state->outgoing_packet, buf, len); -} + if (ssh->state->compression_out_started != 1) + return SSH_ERR_INTERNAL_ERROR; -/* Append payload. */ -void -packet_put_char(int value) -{ - char ch = value; + /* This case is not handled below. */ + if (sshbuf_len(in) == 0) + return 0; - buffer_append(&active_state->outgoing_packet, &ch, 1); + /* Input is the contents of the input buffer. */ + if ((ssh->state->compression_out_stream.next_in = + sshbuf_mutable_ptr(in)) == NULL) + return SSH_ERR_INTERNAL_ERROR; + ssh->state->compression_out_stream.avail_in = sshbuf_len(in); + + /* Loop compressing until deflate() returns with avail_out != 0. */ + do { + /* Set up fixed-size output buffer. */ + ssh->state->compression_out_stream.next_out = buf; + ssh->state->compression_out_stream.avail_out = sizeof(buf); + + /* Compress as much data into the buffer as possible. */ + status = deflate(&ssh->state->compression_out_stream, + Z_PARTIAL_FLUSH); + switch (status) { + case Z_MEM_ERROR: + return SSH_ERR_ALLOC_FAIL; + case Z_OK: + /* Append compressed data to output_buffer. */ + if ((r = sshbuf_put(out, buf, sizeof(buf) - + ssh->state->compression_out_stream.avail_out)) != 0) + return r; + break; + case Z_STREAM_ERROR: + default: + ssh->state->compression_out_failures++; + return SSH_ERR_INVALID_FORMAT; + } + } while (ssh->state->compression_out_stream.avail_out == 0); + return 0; } -void -packet_put_int(u_int value) +static int +uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) { - buffer_put_int(&active_state->outgoing_packet, value); -} + u_char buf[4096]; + int r, status; -void -packet_put_int64(u_int64_t value) -{ - buffer_put_int64(&active_state->outgoing_packet, value); -} + if (ssh->state->compression_in_started != 1) + return SSH_ERR_INTERNAL_ERROR; -void -packet_put_string(const void *buf, u_int len) -{ - buffer_put_string(&active_state->outgoing_packet, buf, len); -} + if ((ssh->state->compression_in_stream.next_in = + sshbuf_mutable_ptr(in)) == NULL) + return SSH_ERR_INTERNAL_ERROR; + ssh->state->compression_in_stream.avail_in = sshbuf_len(in); -void -packet_put_cstring(const char *str) -{ - buffer_put_cstring(&active_state->outgoing_packet, str); + for (;;) { + /* Set up fixed-size output buffer. */ + ssh->state->compression_in_stream.next_out = buf; + ssh->state->compression_in_stream.avail_out = sizeof(buf); + + status = inflate(&ssh->state->compression_in_stream, + Z_PARTIAL_FLUSH); + switch (status) { + case Z_OK: + if ((r = sshbuf_put(out, buf, sizeof(buf) - + ssh->state->compression_in_stream.avail_out)) != 0) + return r; + break; + case Z_BUF_ERROR: + /* + * Comments in zlib.h say that we should keep calling + * inflate() until we get an error. This appears to + * be the error that we get. + */ + return 0; + case Z_DATA_ERROR: + return SSH_ERR_INVALID_FORMAT; + case Z_MEM_ERROR: + return SSH_ERR_ALLOC_FAIL; + case Z_STREAM_ERROR: + default: + ssh->state->compression_in_failures++; + return SSH_ERR_INTERNAL_ERROR; + } + } + /* NOTREACHED */ } -void -packet_put_raw(const void *buf, u_int len) -{ - buffer_append(&active_state->outgoing_packet, buf, len); +/* Serialise compression state into a blob for privsep */ +static int +ssh_packet_get_compress_state(struct sshbuf *m, struct ssh *ssh) +{ + struct session_state *state = ssh->state; + struct sshbuf *b; + int r; + + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (state->compression_in_started) { + if ((r = sshbuf_put_string(b, &state->compression_in_stream, + sizeof(state->compression_in_stream))) != 0) + goto out; + } else if ((r = sshbuf_put_string(b, NULL, 0)) != 0) + goto out; + if (state->compression_out_started) { + if ((r = sshbuf_put_string(b, &state->compression_out_stream, + sizeof(state->compression_out_stream))) != 0) + goto out; + } else if ((r = sshbuf_put_string(b, NULL, 0)) != 0) + goto out; + r = sshbuf_put_stringb(m, b); + out: + sshbuf_free(b); + return r; +} + +/* Deserialise compression state from a blob for privsep */ +static int +ssh_packet_set_compress_state(struct ssh *ssh, struct sshbuf *m) +{ + struct session_state *state = ssh->state; + struct sshbuf *b = NULL; + int r; + const u_char *inblob, *outblob; + size_t inl, outl; + + if ((r = sshbuf_froms(m, &b)) != 0) + goto out; + if ((r = sshbuf_get_string_direct(b, &inblob, &inl)) != 0 || + (r = sshbuf_get_string_direct(b, &outblob, &outl)) != 0) + goto out; + if (inl == 0) + state->compression_in_started = 0; + else if (inl != sizeof(state->compression_in_stream)) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } else { + state->compression_in_started = 1; + memcpy(&state->compression_in_stream, inblob, inl); + } + if (outl == 0) + state->compression_out_started = 0; + else if (outl != sizeof(state->compression_out_stream)) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } else { + state->compression_out_started = 1; + memcpy(&state->compression_out_stream, outblob, outl); + } + r = 0; + out: + sshbuf_free(b); + return r; } void -packet_put_bignum(BIGNUM * value) +ssh_packet_set_compress_hooks(struct ssh *ssh, void *ctx, + void *(*allocfunc)(void *, u_int, u_int), + void (*freefunc)(void *, void *)) { - buffer_put_bignum(&active_state->outgoing_packet, value); + ssh->state->compression_out_stream.zalloc = (alloc_func)allocfunc; + ssh->state->compression_out_stream.zfree = (free_func)freefunc; + ssh->state->compression_out_stream.opaque = ctx; + ssh->state->compression_in_stream.zalloc = (alloc_func)allocfunc; + ssh->state->compression_in_stream.zfree = (free_func)freefunc; + ssh->state->compression_in_stream.opaque = ctx; } -void -packet_put_bignum2(BIGNUM * value) -{ - buffer_put_bignum2(&active_state->outgoing_packet, value); -} +/* + * Causes any further packets to be encrypted using the given key. The same + * key is used for both sending and reception. However, both directions are + * encrypted independently of each other. + */ -#ifdef OPENSSL_HAS_ECC void -packet_put_ecpoint(const EC_GROUP *curve, const EC_POINT *point) +ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, int number) { - buffer_put_ecpoint(&active_state->outgoing_packet, curve, point); +#ifndef WITH_SSH1 + fatal("no SSH protocol 1 support"); +#else /* WITH_SSH1 */ + struct session_state *state = ssh->state; + const struct sshcipher *cipher = cipher_by_number(number); + int r; + const char *wmsg; + + if (cipher == NULL) + fatal("%s: unknown cipher number %d", __func__, number); + if (keylen < 20) + fatal("%s: keylen too small: %d", __func__, keylen); + if (keylen > SSH_SESSION_KEY_LENGTH) + fatal("%s: keylen too big: %d", __func__, keylen); + memcpy(state->ssh1_key, key, keylen); + state->ssh1_keylen = keylen; + if ((r = cipher_init(&state->send_context, cipher, key, keylen, + NULL, 0, CIPHER_ENCRYPT)) != 0 || + (r = cipher_init(&state->receive_context, cipher, key, keylen, + NULL, 0, CIPHER_DECRYPT) != 0)) + fatal("%s: cipher_init failed: %s", __func__, ssh_err(r)); + if (!state->cipher_warning_done && + ((wmsg = cipher_warning_message(&state->send_context)) != NULL || + (wmsg = cipher_warning_message(&state->send_context)) != NULL)) { + error("Warning: %s", wmsg); + state->cipher_warning_done = 1; + } +#endif /* WITH_SSH1 */ } -#endif /* * Finalizes and sends the packet. If the encryption key has been set, * encrypts the packet before sending. */ -static void -packet_send1(void) +int +ssh_packet_send1(struct ssh *ssh) { + struct session_state *state = ssh->state; u_char buf[8], *cp; - int i, padding, len; + int r, padding, len; u_int checksum; - u_int32_t rnd = 0; /* * If using packet compression, compress the payload of the outgoing * packet. */ - if (active_state->packet_compression) { - buffer_clear(&active_state->compression_buffer); + if (state->packet_compression) { + sshbuf_reset(state->compression_buffer); /* Skip padding. */ - buffer_consume(&active_state->outgoing_packet, 8); + if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0) + goto out; /* padding */ - buffer_append(&active_state->compression_buffer, - "\0\0\0\0\0\0\0\0", 8); - buffer_compress(&active_state->outgoing_packet, - &active_state->compression_buffer); - buffer_clear(&active_state->outgoing_packet); - buffer_append(&active_state->outgoing_packet, - buffer_ptr(&active_state->compression_buffer), - buffer_len(&active_state->compression_buffer)); + if ((r = sshbuf_put(state->compression_buffer, + "\0\0\0\0\0\0\0\0", 8)) != 0) + goto out; + if ((r = compress_buffer(ssh, state->outgoing_packet, + state->compression_buffer)) != 0) + goto out; + sshbuf_reset(state->outgoing_packet); + if ((r = sshbuf_putb(state->outgoing_packet, + state->compression_buffer)) != 0) + goto out; } /* Compute packet length without padding (add checksum, remove padding). */ - len = buffer_len(&active_state->outgoing_packet) + 4 - 8; + len = sshbuf_len(state->outgoing_packet) + 4 - 8; /* Insert padding. Initialized to zero in packet_start1() */ padding = 8 - len % 8; - if (!active_state->send_context.plaintext) { - cp = buffer_ptr(&active_state->outgoing_packet); - for (i = 0; i < padding; i++) { - if (i % 4 == 0) - rnd = arc4random(); - cp[7 - i] = rnd & 0xff; - rnd >>= 8; + if (!state->send_context.plaintext) { + cp = sshbuf_mutable_ptr(state->outgoing_packet); + if (cp == NULL) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; } + arc4random_buf(cp + 8 - padding, padding); } - buffer_consume(&active_state->outgoing_packet, 8 - padding); + if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0) + goto out; /* Add check bytes. */ - checksum = ssh_crc32(buffer_ptr(&active_state->outgoing_packet), - buffer_len(&active_state->outgoing_packet)); - put_u32(buf, checksum); - buffer_append(&active_state->outgoing_packet, buf, 4); + checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet), + sshbuf_len(state->outgoing_packet)); + POKE_U32(buf, checksum); + if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0) + goto out; #ifdef PACKET_DEBUG fprintf(stderr, "packet_send plain: "); - buffer_dump(&active_state->outgoing_packet); + sshbuf_dump(state->outgoing_packet, stderr); #endif /* Append to output. */ - put_u32(buf, len); - buffer_append(&active_state->output, buf, 4); - cp = buffer_append_space(&active_state->output, - buffer_len(&active_state->outgoing_packet)); - if (cipher_crypt(&active_state->send_context, 0, cp, - buffer_ptr(&active_state->outgoing_packet), - buffer_len(&active_state->outgoing_packet), 0, 0) != 0) - fatal("%s: cipher_crypt failed", __func__); + POKE_U32(buf, len); + if ((r = sshbuf_put(state->output, buf, 4)) != 0) + goto out; + if ((r = sshbuf_reserve(state->output, + sshbuf_len(state->outgoing_packet), &cp)) != 0) + goto out; + if ((r = cipher_crypt(&state->send_context, 0, cp, + sshbuf_ptr(state->outgoing_packet), + sshbuf_len(state->outgoing_packet), 0, 0)) != 0) + goto out; #ifdef PACKET_DEBUG fprintf(stderr, "encrypted: "); - buffer_dump(&active_state->output); + sshbuf_dump(state->output, stderr); #endif - active_state->p_send.packets++; - active_state->p_send.bytes += len + - buffer_len(&active_state->outgoing_packet); - buffer_clear(&active_state->outgoing_packet); + state->p_send.packets++; + state->p_send.bytes += len + + sshbuf_len(state->outgoing_packet); + sshbuf_reset(state->outgoing_packet); /* * Note that the packet is now only buffered in output. It won't be - * actually sent until packet_write_wait or packet_write_poll is - * called. + * actually sent until ssh_packet_write_wait or ssh_packet_write_poll + * is called. */ + r = 0; + out: + return r; } -void -set_newkeys(int mode) +int +ssh_set_newkeys(struct ssh *ssh, int mode) { - Enc *enc; - Mac *mac; - Comp *comp; - CipherContext *cc; + struct session_state *state = ssh->state; + struct sshenc *enc; + struct sshmac *mac; + struct sshcomp *comp; + struct sshcipher_ctx *cc; u_int64_t *max_blocks; - int crypt_type; + const char *wmsg; + int r, crypt_type; debug2("set_newkeys: mode %d", mode); if (mode == MODE_OUT) { - cc = &active_state->send_context; + cc = &state->send_context; crypt_type = CIPHER_ENCRYPT; - active_state->p_send.packets = active_state->p_send.blocks = 0; - max_blocks = &active_state->max_blocks_out; + state->p_send.packets = state->p_send.blocks = 0; + max_blocks = &state->max_blocks_out; } else { - cc = &active_state->receive_context; + cc = &state->receive_context; crypt_type = CIPHER_DECRYPT; - active_state->p_read.packets = active_state->p_read.blocks = 0; - max_blocks = &active_state->max_blocks_in; + state->p_read.packets = state->p_read.blocks = 0; + max_blocks = &state->max_blocks_in; } - if (active_state->newkeys[mode] != NULL) { + if (state->newkeys[mode] != NULL) { debug("set_newkeys: rekeying"); - cipher_cleanup(cc); - enc = &active_state->newkeys[mode]->enc; - mac = &active_state->newkeys[mode]->mac; - comp = &active_state->newkeys[mode]->comp; + if ((r = cipher_cleanup(cc)) != 0) + return r; + enc = &state->newkeys[mode]->enc; + mac = &state->newkeys[mode]->mac; + comp = &state->newkeys[mode]->comp; mac_clear(mac); explicit_bzero(enc->iv, enc->iv_len); explicit_bzero(enc->key, enc->key_len); @@ -774,31 +958,45 @@ set_newkeys(int mode) free(mac->name); free(mac->key); free(comp->name); - free(active_state->newkeys[mode]); - } - active_state->newkeys[mode] = kex_get_newkeys(mode); - if (active_state->newkeys[mode] == NULL) - fatal("newkeys: no keys for mode %d", mode); - enc = &active_state->newkeys[mode]->enc; - mac = &active_state->newkeys[mode]->mac; - comp = &active_state->newkeys[mode]->comp; - if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0) - mac->enabled = 1; + free(state->newkeys[mode]); + } + /* move newkeys from kex to state */ + if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL) + return SSH_ERR_INTERNAL_ERROR; + ssh->kex->newkeys[mode] = NULL; + enc = &state->newkeys[mode]->enc; + mac = &state->newkeys[mode]->mac; + comp = &state->newkeys[mode]->comp; + if (cipher_authlen(enc->cipher) == 0) { + if ((r = mac_init(mac)) != 0) + return r; + } + mac->enabled = 1; DBG(debug("cipher_init_context: %d", mode)); - cipher_init(cc, enc->cipher, enc->key, enc->key_len, - enc->iv, enc->iv_len, crypt_type); + if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len, + enc->iv, enc->iv_len, crypt_type)) != 0) + return r; + if (!state->cipher_warning_done && + (wmsg = cipher_warning_message(cc)) != NULL) { + error("Warning: %s", wmsg); + state->cipher_warning_done = 1; + } /* Deleting the keys does not gain extra security */ /* explicit_bzero(enc->iv, enc->block_size); explicit_bzero(enc->key, enc->key_len); explicit_bzero(mac->key, mac->key_len); */ if ((comp->type == COMP_ZLIB || (comp->type == COMP_DELAYED && - active_state->after_authentication)) && comp->enabled == 0) { - packet_init_compression(); - if (mode == MODE_OUT) - buffer_compress_init_send(6); - else - buffer_compress_init_recv(); + state->after_authentication)) && comp->enabled == 0) { + if ((r = ssh_packet_init_compression(ssh)) < 0) + return r; + if (mode == MODE_OUT) { + if ((r = start_compression_out(ssh, 6)) != 0) + return r; + } else { + if ((r = start_compression_in(ssh)) != 0) + return r; + } comp->enabled = 1; } /* @@ -809,9 +1007,10 @@ set_newkeys(int mode) *max_blocks = (u_int64_t)1 << (enc->block_size*2); else *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; - if (active_state->rekey_limit) + if (state->rekey_limit) *max_blocks = MIN(*max_blocks, - active_state->rekey_limit / enc->block_size); + state->rekey_limit / enc->block_size); + return 0; } /* @@ -819,52 +1018,59 @@ set_newkeys(int mode) * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. */ -static void -packet_enable_delayed_compress(void) +static int +ssh_packet_enable_delayed_compress(struct ssh *ssh) { - Comp *comp = NULL; - int mode; + struct session_state *state = ssh->state; + struct sshcomp *comp = NULL; + int r, mode; /* * Remember that we are past the authentication step, so rekeying * with COMP_DELAYED will turn on compression immediately. */ - active_state->after_authentication = 1; + state->after_authentication = 1; for (mode = 0; mode < MODE_MAX; mode++) { /* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ - if (active_state->newkeys[mode] == NULL) + if (state->newkeys[mode] == NULL) continue; - comp = &active_state->newkeys[mode]->comp; + comp = &state->newkeys[mode]->comp; if (comp && !comp->enabled && comp->type == COMP_DELAYED) { - packet_init_compression(); - if (mode == MODE_OUT) - buffer_compress_init_send(6); - else - buffer_compress_init_recv(); + if ((r = ssh_packet_init_compression(ssh)) != 0) + return r; + if (mode == MODE_OUT) { + if ((r = start_compression_out(ssh, 6)) != 0) + return r; + } else { + if ((r = start_compression_in(ssh)) != 0) + return r; + } comp->enabled = 1; } } + return 0; } /* * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) */ -static void -packet_send2_wrapped(void) +int +ssh_packet_send2_wrapped(struct ssh *ssh) { - u_char type, *cp, *macbuf = NULL; + struct session_state *state = ssh->state; + u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; u_char padlen, pad = 0; - u_int i, len, authlen = 0, aadlen = 0; - u_int32_t rnd = 0; - Enc *enc = NULL; - Mac *mac = NULL; - Comp *comp = NULL; - int block_size; - - if (active_state->newkeys[MODE_OUT] != NULL) { - enc = &active_state->newkeys[MODE_OUT]->enc; - mac = &active_state->newkeys[MODE_OUT]->mac; - comp = &active_state->newkeys[MODE_OUT]->comp; + u_int authlen = 0, aadlen = 0; + u_int len; + struct sshenc *enc = NULL; + struct sshmac *mac = NULL; + struct sshcomp *comp = NULL; + int r, block_size; + + if (state->newkeys[MODE_OUT] != NULL) { + enc = &state->newkeys[MODE_OUT]->enc; + mac = &state->newkeys[MODE_OUT]->mac; + comp = &state->newkeys[MODE_OUT]->comp; /* disable mac for authenticated encryption */ if ((authlen = cipher_authlen(enc->cipher)) != 0) mac = NULL; @@ -872,32 +1078,34 @@ packet_send2_wrapped(void) block_size = enc ? enc->block_size : 8; aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; - cp = buffer_ptr(&active_state->outgoing_packet); - type = cp[5]; + type = (sshbuf_ptr(state->outgoing_packet))[5]; #ifdef PACKET_DEBUG fprintf(stderr, "plain: "); - buffer_dump(&active_state->outgoing_packet); + sshbuf_dump(state->outgoing_packet, stderr); #endif if (comp && comp->enabled) { - len = buffer_len(&active_state->outgoing_packet); + len = sshbuf_len(state->outgoing_packet); /* skip header, compress only payload */ - buffer_consume(&active_state->outgoing_packet, 5); - buffer_clear(&active_state->compression_buffer); - buffer_compress(&active_state->outgoing_packet, - &active_state->compression_buffer); - buffer_clear(&active_state->outgoing_packet); - buffer_append(&active_state->outgoing_packet, "\0\0\0\0\0", 5); - buffer_append(&active_state->outgoing_packet, - buffer_ptr(&active_state->compression_buffer), - buffer_len(&active_state->compression_buffer)); - DBG(debug("compression: raw %d compressed %d", len, - buffer_len(&active_state->outgoing_packet))); + if ((r = sshbuf_consume(state->outgoing_packet, 5)) != 0) + goto out; + sshbuf_reset(state->compression_buffer); + if ((r = compress_buffer(ssh, state->outgoing_packet, + state->compression_buffer)) != 0) + goto out; + sshbuf_reset(state->outgoing_packet); + if ((r = sshbuf_put(state->outgoing_packet, + "\0\0\0\0\0", 5)) != 0 || + (r = sshbuf_putb(state->outgoing_packet, + state->compression_buffer)) != 0) + goto out; + DBG(debug("compression: raw %d compressed %zd", len, + sshbuf_len(state->outgoing_packet))); } /* sizeof (packet_len + pad_len + payload) */ - len = buffer_len(&active_state->outgoing_packet); + len = sshbuf_len(state->outgoing_packet); /* * calc size of padding, alloc space, get random data, @@ -907,139 +1115,145 @@ packet_send2_wrapped(void) padlen = block_size - (len % block_size); if (padlen < 4) padlen += block_size; - if (active_state->extra_pad) { + if (state->extra_pad) { /* will wrap if extra_pad+padlen > 255 */ - active_state->extra_pad = - roundup(active_state->extra_pad, block_size); - pad = active_state->extra_pad - - ((len + padlen) % active_state->extra_pad); - debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", - pad, len, padlen, active_state->extra_pad); + state->extra_pad = + roundup(state->extra_pad, block_size); + pad = state->extra_pad - + ((len + padlen) % state->extra_pad); + DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)", + __func__, pad, len, padlen, state->extra_pad)); padlen += pad; - active_state->extra_pad = 0; + state->extra_pad = 0; } - cp = buffer_append_space(&active_state->outgoing_packet, padlen); - if (enc && !active_state->send_context.plaintext) { + if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0) + goto out; + if (enc && !state->send_context.plaintext) { /* random padding */ - for (i = 0; i < padlen; i++) { - if (i % 4 == 0) - rnd = arc4random(); - cp[i] = rnd & 0xff; - rnd >>= 8; - } + arc4random_buf(cp, padlen); } else { /* clear padding */ explicit_bzero(cp, padlen); } /* sizeof (packet_len + pad_len + payload + padding) */ - len = buffer_len(&active_state->outgoing_packet); - cp = buffer_ptr(&active_state->outgoing_packet); + len = sshbuf_len(state->outgoing_packet); + cp = sshbuf_mutable_ptr(state->outgoing_packet); + if (cp == NULL) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } /* packet_length includes payload, padding and padding length field */ - put_u32(cp, len - 4); + POKE_U32(cp, len - 4); cp[4] = padlen; DBG(debug("send: len %d (includes padlen %d, aadlen %d)", len, padlen, aadlen)); /* compute MAC over seqnr and packet(length fields, payload, padding) */ if (mac && mac->enabled && !mac->etm) { - macbuf = mac_compute(mac, active_state->p_send.seqnr, - buffer_ptr(&active_state->outgoing_packet), len); - DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr)); + if ((r = mac_compute(mac, state->p_send.seqnr, + sshbuf_ptr(state->outgoing_packet), len, + macbuf, sizeof(macbuf))) != 0) + goto out; + DBG(debug("done calc MAC out #%d", state->p_send.seqnr)); } /* encrypt packet and append to output buffer. */ - cp = buffer_append_space(&active_state->output, len + authlen); - if (cipher_crypt(&active_state->send_context, active_state->p_send.seqnr, - cp, buffer_ptr(&active_state->outgoing_packet), - len - aadlen, aadlen, authlen) != 0) - fatal("%s: cipher_crypt failed", __func__); + if ((r = sshbuf_reserve(state->output, + sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0) + goto out; + if ((r = cipher_crypt(&state->send_context, state->p_send.seqnr, cp, + sshbuf_ptr(state->outgoing_packet), + len - aadlen, aadlen, authlen)) != 0) + goto out; /* append unencrypted MAC */ if (mac && mac->enabled) { if (mac->etm) { /* EtM: compute mac over aadlen + cipher text */ - macbuf = mac_compute(mac, - active_state->p_send.seqnr, cp, len); + if ((r = mac_compute(mac, state->p_send.seqnr, + cp, len, macbuf, sizeof(macbuf))) != 0) + goto out; DBG(debug("done calc MAC(EtM) out #%d", - active_state->p_send.seqnr)); + state->p_send.seqnr)); } - buffer_append(&active_state->output, macbuf, mac->mac_len); + if ((r = sshbuf_put(state->output, macbuf, mac->mac_len)) != 0) + goto out; } #ifdef PACKET_DEBUG fprintf(stderr, "encrypted: "); - buffer_dump(&active_state->output); + sshbuf_dump(state->output, stderr); #endif /* increment sequence number for outgoing packets */ - if (++active_state->p_send.seqnr == 0) + if (++state->p_send.seqnr == 0) logit("outgoing seqnr wraps around"); - if (++active_state->p_send.packets == 0) - if (!(datafellows & SSH_BUG_NOREKEY)) - fatal("XXX too many packets with same key"); - active_state->p_send.blocks += len / block_size; - active_state->p_send.bytes += len; - buffer_clear(&active_state->outgoing_packet); + if (++state->p_send.packets == 0) + if (!(ssh->compat & SSH_BUG_NOREKEY)) + return SSH_ERR_NEED_REKEY; + state->p_send.blocks += len / block_size; + state->p_send.bytes += len; + sshbuf_reset(state->outgoing_packet); if (type == SSH2_MSG_NEWKEYS) - set_newkeys(MODE_OUT); - else if (type == SSH2_MSG_USERAUTH_SUCCESS && active_state->server_side) - packet_enable_delayed_compress(); + r = ssh_set_newkeys(ssh, MODE_OUT); + else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side) + r = ssh_packet_enable_delayed_compress(ssh); + else + r = 0; + out: + return r; } -static void -packet_send2(void) +int +ssh_packet_send2(struct ssh *ssh) { + struct session_state *state = ssh->state; struct packet *p; - u_char type, *cp; + u_char type; + int r; - cp = buffer_ptr(&active_state->outgoing_packet); - type = cp[5]; + type = sshbuf_ptr(state->outgoing_packet)[5]; /* during rekeying we can only send key exchange messages */ - if (active_state->rekeying) { + if (state->rekeying) { if ((type < SSH2_MSG_TRANSPORT_MIN) || (type > SSH2_MSG_TRANSPORT_MAX) || (type == SSH2_MSG_SERVICE_REQUEST) || (type == SSH2_MSG_SERVICE_ACCEPT)) { debug("enqueue packet: %u", type); - p = xcalloc(1, sizeof(*p)); + p = calloc(1, sizeof(*p)); + if (p == NULL) + return SSH_ERR_ALLOC_FAIL; p->type = type; - memcpy(&p->payload, &active_state->outgoing_packet, - sizeof(Buffer)); - buffer_init(&active_state->outgoing_packet); - TAILQ_INSERT_TAIL(&active_state->outgoing, p, next); - return; + p->payload = state->outgoing_packet; + TAILQ_INSERT_TAIL(&state->outgoing, p, next); + state->outgoing_packet = sshbuf_new(); + if (state->outgoing_packet == NULL) + return SSH_ERR_ALLOC_FAIL; + return 0; } } /* rekeying starts with sending KEXINIT */ if (type == SSH2_MSG_KEXINIT) - active_state->rekeying = 1; + state->rekeying = 1; - packet_send2_wrapped(); + if ((r = ssh_packet_send2_wrapped(ssh)) != 0) + return r; /* after a NEWKEYS message we can send the complete queue */ if (type == SSH2_MSG_NEWKEYS) { - active_state->rekeying = 0; - active_state->rekey_time = monotime(); - while ((p = TAILQ_FIRST(&active_state->outgoing))) { + state->rekeying = 0; + state->rekey_time = monotime(); + while ((p = TAILQ_FIRST(&state->outgoing))) { type = p->type; debug("dequeue packet: %u", type); - buffer_free(&active_state->outgoing_packet); - memcpy(&active_state->outgoing_packet, &p->payload, - sizeof(Buffer)); - TAILQ_REMOVE(&active_state->outgoing, p, next); + sshbuf_free(state->outgoing_packet); + state->outgoing_packet = p->payload; + TAILQ_REMOVE(&state->outgoing, p, next); free(p); - packet_send2_wrapped(); + if ((r = ssh_packet_send2_wrapped(ssh)) != 0) + return r; } } -} - -void -packet_send(void) -{ - if (compat20) - packet_send2(); - else - packet_send1(); - DBG(debug("packet_send done")); + return 0; } /* @@ -1049,95 +1263,111 @@ packet_send(void) */ int -packet_read_seqnr(u_int32_t *seqnr_p) +ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) { - int type, len, ret, cont, ms_remain = 0; + struct session_state *state = ssh->state; + int len, r, ms_remain, cont; fd_set *setp; char buf[8192]; struct timeval timeout, start, *timeoutp = NULL; DBG(debug("packet_read()")); - setp = (fd_set *)xcalloc(howmany(active_state->connection_in + 1, + setp = calloc(howmany(state->connection_in + 1, NFDBITS), sizeof(fd_mask)); + if (setp == NULL) + return SSH_ERR_ALLOC_FAIL; - /* Since we are blocking, ensure that all written packets have been sent. */ - packet_write_wait(); + /* + * Since we are blocking, ensure that all written packets have + * been sent. + */ + if ((r = ssh_packet_write_wait(ssh)) != 0) + goto out; /* Stay in the loop until we have received a complete packet. */ for (;;) { /* Try to read a packet from the buffer. */ - type = packet_read_poll_seqnr(seqnr_p); + r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); + if (r != 0) + break; if (!compat20 && ( - type == SSH_SMSG_SUCCESS - || type == SSH_SMSG_FAILURE - || type == SSH_CMSG_EOF - || type == SSH_CMSG_EXIT_CONFIRMATION)) - packet_check_eom(); + *typep == SSH_SMSG_SUCCESS + || *typep == SSH_SMSG_FAILURE + || *typep == SSH_CMSG_EOF + || *typep == SSH_CMSG_EXIT_CONFIRMATION)) + if ((r = sshpkt_get_end(ssh)) != 0) + break; /* If we got a packet, return it. */ - if (type != SSH_MSG_NONE) { - free(setp); - return type; - } + if (*typep != SSH_MSG_NONE) + break; /* * Otherwise, wait for some data to arrive, add it to the * buffer, and try again. */ - memset(setp, 0, howmany(active_state->connection_in + 1, + memset(setp, 0, howmany(state->connection_in + 1, NFDBITS) * sizeof(fd_mask)); - FD_SET(active_state->connection_in, setp); + FD_SET(state->connection_in, setp); - if (active_state->packet_timeout_ms > 0) { - ms_remain = active_state->packet_timeout_ms; + if (state->packet_timeout_ms > 0) { + ms_remain = state->packet_timeout_ms; timeoutp = &timeout; } /* Wait for some data to arrive. */ for (;;) { - if (active_state->packet_timeout_ms != -1) { + if (state->packet_timeout_ms != -1) { ms_to_timeval(&timeout, ms_remain); gettimeofday(&start, NULL); } - if ((ret = select(active_state->connection_in + 1, setp, + if ((r = select(state->connection_in + 1, setp, NULL, NULL, timeoutp)) >= 0) break; if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) break; - if (active_state->packet_timeout_ms == -1) + if (state->packet_timeout_ms == -1) continue; ms_subtract_diff(&start, &ms_remain); if (ms_remain <= 0) { - ret = 0; + r = 0; break; } } - if (ret == 0) { - logit("Connection to %.200s timed out while " - "waiting to read", get_remote_ipaddr()); - cleanup_exit(255); - } + if (r == 0) + return SSH_ERR_CONN_TIMEOUT; /* Read data from the socket. */ do { cont = 0; - len = roaming_read(active_state->connection_in, buf, + len = roaming_read(state->connection_in, buf, sizeof(buf), &cont); } while (len == 0 && cont); if (len == 0) { - logit("Connection closed by %.200s", get_remote_ipaddr()); - cleanup_exit(255); + r = SSH_ERR_CONN_CLOSED; + goto out; } - if (len < 0) - fatal("Read from socket failed: %.100s", strerror(errno)); + if (len < 0) { + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + /* Append it to the buffer. */ - packet_process_incoming(buf, len); + if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0) + goto out; } - /* NOTREACHED */ + out: + free(setp); + return r; } int -packet_read(void) +ssh_packet_read(struct ssh *ssh) { - return packet_read_seqnr(NULL); + u_char type; + int r; + + if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + return type; } /* @@ -1145,15 +1375,22 @@ packet_read(void) * that given, and gives a fatal error and exits if there is a mismatch. */ -void -packet_read_expect(int expected_type) +int +ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) { - int type; + int r; + u_char type; - type = packet_read(); - if (type != expected_type) - packet_disconnect("Protocol error: expected packet type %d, got %d", - expected_type, type); + if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) + return r; + if (type != expected_type) { + if ((r = sshpkt_disconnect(ssh, + "Protocol error: expected packet type %d, got %d", + expected_type, type)) != 0) + return r; + return SSH_ERR_PROTOCOL_ERROR; + } + return 0; } /* Checks if a full packet is available in the data received so far via @@ -1165,115 +1402,165 @@ packet_read_expect(int expected_type) * to higher levels. */ -static int -packet_read_poll1(void) +int +ssh_packet_read_poll1(struct ssh *ssh, u_char *typep) { + struct session_state *state = ssh->state; u_int len, padded_len; - u_char *cp, type; + const char *emsg; + const u_char *cp; + u_char *p; u_int checksum, stored_checksum; + int r; + + *typep = SSH_MSG_NONE; /* Check if input size is less than minimum packet size. */ - if (buffer_len(&active_state->input) < 4 + 8) - return SSH_MSG_NONE; + if (sshbuf_len(state->input) < 4 + 8) + return 0; /* Get length of incoming packet. */ - cp = buffer_ptr(&active_state->input); - len = get_u32(cp); - if (len < 1 + 2 + 2 || len > 256 * 1024) - packet_disconnect("Bad packet length %u.", len); + len = PEEK_U32(sshbuf_ptr(state->input)); + if (len < 1 + 2 + 2 || len > 256 * 1024) { + if ((r = sshpkt_disconnect(ssh, "Bad packet length %u", + len)) != 0) + return r; + return SSH_ERR_CONN_CORRUPT; + } padded_len = (len + 8) & ~7; /* Check if the packet has been entirely received. */ - if (buffer_len(&active_state->input) < 4 + padded_len) - return SSH_MSG_NONE; + if (sshbuf_len(state->input) < 4 + padded_len) + return 0; /* The entire packet is in buffer. */ /* Consume packet length. */ - buffer_consume(&active_state->input, 4); + if ((r = sshbuf_consume(state->input, 4)) != 0) + goto out; /* * Cryptographic attack detector for ssh * (C)1998 CORE-SDI, Buenos Aires Argentina * Ariel Futoransky(futo@core-sdi.com) */ - if (!active_state->receive_context.plaintext) { - switch (detect_attack(buffer_ptr(&active_state->input), - padded_len)) { + if (!state->receive_context.plaintext) { + emsg = NULL; + switch (detect_attack(&state->deattack, + sshbuf_ptr(state->input), padded_len)) { + case DEATTACK_OK: + break; case DEATTACK_DETECTED: - packet_disconnect("crc32 compensation attack: " - "network attack detected"); + emsg = "crc32 compensation attack detected"; + break; case DEATTACK_DOS_DETECTED: - packet_disconnect("deattack denial of " - "service detected"); + emsg = "deattack denial of service detected"; + break; + default: + emsg = "deattack error"; + break; + } + if (emsg != NULL) { + error("%s", emsg); + if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + return r; + return SSH_ERR_CONN_CORRUPT; } } /* Decrypt data to incoming_packet. */ - buffer_clear(&active_state->incoming_packet); - cp = buffer_append_space(&active_state->incoming_packet, padded_len); - if (cipher_crypt(&active_state->receive_context, 0, cp, - buffer_ptr(&active_state->input), padded_len, 0, 0) != 0) - fatal("%s: cipher_crypt failed", __func__); + sshbuf_reset(state->incoming_packet); + if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0) + goto out; + if ((r = cipher_crypt(&state->receive_context, 0, p, + sshbuf_ptr(state->input), padded_len, 0, 0)) != 0) + goto out; - buffer_consume(&active_state->input, padded_len); + if ((r = sshbuf_consume(state->input, padded_len)) != 0) + goto out; #ifdef PACKET_DEBUG fprintf(stderr, "read_poll plain: "); - buffer_dump(&active_state->incoming_packet); + sshbuf_dump(state->incoming_packet, stderr); #endif /* Compute packet checksum. */ - checksum = ssh_crc32(buffer_ptr(&active_state->incoming_packet), - buffer_len(&active_state->incoming_packet) - 4); + checksum = ssh_crc32(sshbuf_ptr(state->incoming_packet), + sshbuf_len(state->incoming_packet) - 4); /* Skip padding. */ - buffer_consume(&active_state->incoming_packet, 8 - len % 8); + if ((r = sshbuf_consume(state->incoming_packet, 8 - len % 8)) != 0) + goto out; /* Test check bytes. */ - if (len != buffer_len(&active_state->incoming_packet)) - packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", - len, buffer_len(&active_state->incoming_packet)); - - cp = (u_char *)buffer_ptr(&active_state->incoming_packet) + len - 4; - stored_checksum = get_u32(cp); - if (checksum != stored_checksum) - packet_disconnect("Corrupted check bytes on input."); - buffer_consume_end(&active_state->incoming_packet, 4); - - if (active_state->packet_compression) { - buffer_clear(&active_state->compression_buffer); - buffer_uncompress(&active_state->incoming_packet, - &active_state->compression_buffer); - buffer_clear(&active_state->incoming_packet); - buffer_append(&active_state->incoming_packet, - buffer_ptr(&active_state->compression_buffer), - buffer_len(&active_state->compression_buffer)); - } - active_state->p_read.packets++; - active_state->p_read.bytes += padded_len + 4; - type = buffer_get_char(&active_state->incoming_packet); - if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) - packet_disconnect("Invalid ssh1 packet type: %d", type); - return type; + if (len != sshbuf_len(state->incoming_packet)) { + error("%s: len %d != sshbuf_len %zd", __func__, + len, sshbuf_len(state->incoming_packet)); + if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + return r; + return SSH_ERR_CONN_CORRUPT; + } + + cp = sshbuf_ptr(state->incoming_packet) + len - 4; + stored_checksum = PEEK_U32(cp); + if (checksum != stored_checksum) { + error("Corrupted check bytes on input"); + if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + return r; + return SSH_ERR_CONN_CORRUPT; + } + if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0) + goto out; + + if (state->packet_compression) { + sshbuf_reset(state->compression_buffer); + if ((r = uncompress_buffer(ssh, state->incoming_packet, + state->compression_buffer)) != 0) + goto out; + sshbuf_reset(state->incoming_packet); + if ((r = sshbuf_putb(state->incoming_packet, + state->compression_buffer)) != 0) + goto out; + } + state->p_read.packets++; + state->p_read.bytes += padded_len + 4; + if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) + goto out; + if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) { + error("Invalid ssh1 packet type: %d", *typep); + if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + return r; + return SSH_ERR_PROTOCOL_ERROR; + } + r = 0; + out: + return r; } -static int -packet_read_poll2(u_int32_t *seqnr_p) +int +ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) { + struct session_state *state = ssh->state; u_int padlen, need; - u_char *macbuf = NULL, *cp, type; - u_int maclen, authlen = 0, aadlen = 0, block_size; - Enc *enc = NULL; - Mac *mac = NULL; - Comp *comp = NULL; - - if (active_state->packet_discard) - return SSH_MSG_NONE; - - if (active_state->newkeys[MODE_IN] != NULL) { - enc = &active_state->newkeys[MODE_IN]->enc; - mac = &active_state->newkeys[MODE_IN]->mac; - comp = &active_state->newkeys[MODE_IN]->comp; + u_char *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; + u_int maclen, aadlen = 0, authlen = 0, block_size; + struct sshenc *enc = NULL; + struct sshmac *mac = NULL; + struct sshcomp *comp = NULL; + int r; + + *typep = SSH_MSG_NONE; + + if (state->packet_discard) + return 0; + + if (state->newkeys[MODE_IN] != NULL) { + enc = &state->newkeys[MODE_IN]->enc; + mac = &state->newkeys[MODE_IN]->mac; + comp = &state->newkeys[MODE_IN]->comp; /* disable mac for authenticated encryption */ if ((authlen = cipher_authlen(enc->cipher)) != 0) mac = NULL; @@ -1282,69 +1569,72 @@ packet_read_poll2(u_int32_t *seqnr_p) block_size = enc ? enc->block_size : 8; aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; - if (aadlen && active_state->packlen == 0) { - if (cipher_get_length(&active_state->receive_context, - &active_state->packlen, - active_state->p_read.seqnr, - buffer_ptr(&active_state->input), - buffer_len(&active_state->input)) != 0) - return SSH_MSG_NONE; - if (active_state->packlen < 1 + 4 || - active_state->packlen > PACKET_MAX_SIZE) { + if (aadlen && state->packlen == 0) { + if (cipher_get_length(&state->receive_context, + &state->packlen, state->p_read.seqnr, + sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0) + return 0; + if (state->packlen < 1 + 4 || + state->packlen > PACKET_MAX_SIZE) { #ifdef PACKET_DEBUG - buffer_dump(&active_state->input); + sshbuf_dump(state->input, stderr); #endif - logit("Bad packet length %u.", active_state->packlen); - packet_disconnect("Packet corrupt"); + logit("Bad packet length %u.", state->packlen); + if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0) + return r; + return SSH_ERR_CONN_CORRUPT; } - buffer_clear(&active_state->incoming_packet); - } else if (active_state->packlen == 0) { + sshbuf_reset(state->incoming_packet); + } else if (state->packlen == 0) { /* * check if input size is less than the cipher block size, * decrypt first block and extract length of incoming packet */ - if (buffer_len(&active_state->input) < block_size) - return SSH_MSG_NONE; - buffer_clear(&active_state->incoming_packet); - cp = buffer_append_space(&active_state->incoming_packet, - block_size); - if (cipher_crypt(&active_state->receive_context, - active_state->p_read.seqnr, cp, - buffer_ptr(&active_state->input), block_size, 0, 0) != 0) - fatal("Decryption integrity check failed"); - cp = buffer_ptr(&active_state->incoming_packet); - active_state->packlen = get_u32(cp); - if (active_state->packlen < 1 + 4 || - active_state->packlen > PACKET_MAX_SIZE) { + if (sshbuf_len(state->input) < block_size) + return 0; + sshbuf_reset(state->incoming_packet); + if ((r = sshbuf_reserve(state->incoming_packet, block_size, + &cp)) != 0) + goto out; + if ((r = cipher_crypt(&state->receive_context, + state->p_send.seqnr, cp, sshbuf_ptr(state->input), + block_size, 0, 0)) != 0) + goto out; + state->packlen = PEEK_U32(sshbuf_ptr(state->incoming_packet)); + if (state->packlen < 1 + 4 || + state->packlen > PACKET_MAX_SIZE) { #ifdef PACKET_DEBUG - buffer_dump(&active_state->incoming_packet); + fprintf(stderr, "input: \n"); + sshbuf_dump(state->input, stderr); + fprintf(stderr, "incoming_packet: \n"); + sshbuf_dump(state->incoming_packet, stderr); #endif - logit("Bad packet length %u.", active_state->packlen); - packet_start_discard(enc, mac, active_state->packlen, - PACKET_MAX_SIZE); - return SSH_MSG_NONE; + logit("Bad packet length %u.", state->packlen); + return ssh_packet_start_discard(ssh, enc, mac, + state->packlen, PACKET_MAX_SIZE); } - buffer_consume(&active_state->input, block_size); + if ((r = sshbuf_consume(state->input, block_size)) != 0) + goto out; } - DBG(debug("input: packet len %u", active_state->packlen+4)); + DBG(debug("input: packet len %u", state->packlen+4)); + if (aadlen) { /* only the payload is encrypted */ - need = active_state->packlen; + need = state->packlen; } else { /* * the payload size and the payload are encrypted, but we * have a partial packet of block_size bytes */ - need = 4 + active_state->packlen - block_size; + need = 4 + state->packlen - block_size; } DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d," " aadlen %d", block_size, need, maclen, authlen, aadlen)); if (need % block_size != 0) { logit("padding error: need %d block %d mod %d", need, block_size, need % block_size); - packet_start_discard(enc, mac, active_state->packlen, - PACKET_MAX_SIZE - block_size); - return SSH_MSG_NONE; + return ssh_packet_start_discard(ssh, enc, mac, + state->packlen, PACKET_MAX_SIZE - block_size); } /* * check if the entire packet has been received and @@ -1354,167 +1644,197 @@ packet_read_poll2(u_int32_t *seqnr_p) * 'authlen' bytes of authentication tag or * 'maclen' bytes of message authentication code. */ - if (buffer_len(&active_state->input) < aadlen + need + authlen + maclen) - return SSH_MSG_NONE; + if (sshbuf_len(state->input) < aadlen + need + authlen + maclen) + return 0; #ifdef PACKET_DEBUG fprintf(stderr, "read_poll enc/full: "); - buffer_dump(&active_state->input); + sshbuf_dump(state->input, stderr); #endif /* EtM: compute mac over encrypted input */ - if (mac && mac->enabled && mac->etm) - macbuf = mac_compute(mac, active_state->p_read.seqnr, - buffer_ptr(&active_state->input), aadlen + need); - cp = buffer_append_space(&active_state->incoming_packet, aadlen + need); - if (cipher_crypt(&active_state->receive_context, - active_state->p_read.seqnr, cp, - buffer_ptr(&active_state->input), need, aadlen, authlen) != 0) - fatal("Decryption integrity check failed"); - buffer_consume(&active_state->input, aadlen + need + authlen); + if (mac && mac->enabled && mac->etm) { + if ((r = mac_compute(mac, state->p_read.seqnr, + sshbuf_ptr(state->input), aadlen + need, + macbuf, sizeof(macbuf))) != 0) + goto out; + } + if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, + &cp)) != 0) + goto out; + if ((r = cipher_crypt(&state->receive_context, state->p_read.seqnr, cp, + sshbuf_ptr(state->input), need, aadlen, authlen)) != 0) + goto out; + if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) + goto out; /* * compute MAC over seqnr and packet, * increment sequence number for incoming packet */ if (mac && mac->enabled) { if (!mac->etm) - macbuf = mac_compute(mac, active_state->p_read.seqnr, - buffer_ptr(&active_state->incoming_packet), - buffer_len(&active_state->incoming_packet)); - if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input), + if ((r = mac_compute(mac, state->p_read.seqnr, + sshbuf_ptr(state->incoming_packet), + sshbuf_len(state->incoming_packet), + macbuf, sizeof(macbuf))) != 0) + goto out; + if (timingsafe_bcmp(macbuf, sshbuf_ptr(state->input), mac->mac_len) != 0) { logit("Corrupted MAC on input."); if (need > PACKET_MAX_SIZE) - fatal("internal error need %d", need); - packet_start_discard(enc, mac, active_state->packlen, - PACKET_MAX_SIZE - need); - return SSH_MSG_NONE; + return SSH_ERR_INTERNAL_ERROR; + return ssh_packet_start_discard(ssh, enc, mac, + state->packlen, PACKET_MAX_SIZE - need); } - - DBG(debug("MAC #%d ok", active_state->p_read.seqnr)); - buffer_consume(&active_state->input, mac->mac_len); + + DBG(debug("MAC #%d ok", state->p_read.seqnr)); + if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) + goto out; } - /* XXX now it's safe to use fatal/packet_disconnect */ if (seqnr_p != NULL) - *seqnr_p = active_state->p_read.seqnr; - if (++active_state->p_read.seqnr == 0) + *seqnr_p = state->p_read.seqnr; + if (++state->p_read.seqnr == 0) logit("incoming seqnr wraps around"); - if (++active_state->p_read.packets == 0) - if (!(datafellows & SSH_BUG_NOREKEY)) - fatal("XXX too many packets with same key"); - active_state->p_read.blocks += (active_state->packlen + 4) / block_size; - active_state->p_read.bytes += active_state->packlen + 4; + if (++state->p_read.packets == 0) + if (!(ssh->compat & SSH_BUG_NOREKEY)) + return SSH_ERR_NEED_REKEY; + state->p_read.blocks += (state->packlen + 4) / block_size; + state->p_read.bytes += state->packlen + 4; /* get padlen */ - cp = buffer_ptr(&active_state->incoming_packet); - padlen = cp[4]; + padlen = sshbuf_ptr(state->incoming_packet)[4]; DBG(debug("input: padlen %d", padlen)); - if (padlen < 4) - packet_disconnect("Corrupted padlen %d on input.", padlen); + if (padlen < 4) { + if ((r = sshpkt_disconnect(ssh, + "Corrupted padlen %d on input.", padlen)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + return r; + return SSH_ERR_CONN_CORRUPT; + } /* skip packet size + padlen, discard padding */ - buffer_consume(&active_state->incoming_packet, 4 + 1); - buffer_consume_end(&active_state->incoming_packet, padlen); + if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 || + ((r = sshbuf_consume_end(state->incoming_packet, padlen)) != 0)) + goto out; - DBG(debug("input: len before de-compress %d", - buffer_len(&active_state->incoming_packet))); + DBG(debug("input: len before de-compress %zd", + sshbuf_len(state->incoming_packet))); if (comp && comp->enabled) { - buffer_clear(&active_state->compression_buffer); - buffer_uncompress(&active_state->incoming_packet, - &active_state->compression_buffer); - buffer_clear(&active_state->incoming_packet); - buffer_append(&active_state->incoming_packet, - buffer_ptr(&active_state->compression_buffer), - buffer_len(&active_state->compression_buffer)); - DBG(debug("input: len after de-compress %d", - buffer_len(&active_state->incoming_packet))); + sshbuf_reset(state->compression_buffer); + if ((r = uncompress_buffer(ssh, state->incoming_packet, + state->compression_buffer)) != 0) + goto out; + sshbuf_reset(state->incoming_packet); + if ((r = sshbuf_putb(state->incoming_packet, + state->compression_buffer)) != 0) + goto out; + DBG(debug("input: len after de-compress %zd", + sshbuf_len(state->incoming_packet))); } /* * get packet type, implies consume. * return length of payload (without type field) */ - type = buffer_get_char(&active_state->incoming_packet); - if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN) - packet_disconnect("Invalid ssh2 packet type: %d", type); - if (type == SSH2_MSG_NEWKEYS) - set_newkeys(MODE_IN); - else if (type == SSH2_MSG_USERAUTH_SUCCESS && - !active_state->server_side) - packet_enable_delayed_compress(); + if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) + goto out; + if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) { + if ((r = sshpkt_disconnect(ssh, + "Invalid ssh2 packet type: %d", *typep)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + return r; + return SSH_ERR_PROTOCOL_ERROR; + } + if (*typep == SSH2_MSG_NEWKEYS) + r = ssh_set_newkeys(ssh, MODE_IN); + else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side) + r = ssh_packet_enable_delayed_compress(ssh); + else + r = 0; #ifdef PACKET_DEBUG - fprintf(stderr, "read/plain[%d]:\r\n", type); - buffer_dump(&active_state->incoming_packet); + fprintf(stderr, "read/plain[%d]:\r\n", *typep); + sshbuf_dump(state->incoming_packet, stderr); #endif /* reset for next packet */ - active_state->packlen = 0; - return type; + state->packlen = 0; + out: + return r; } int -packet_read_poll_seqnr(u_int32_t *seqnr_p) +ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) { + struct session_state *state = ssh->state; u_int reason, seqnr; - u_char type; - char *msg; + int r; + u_char *msg; for (;;) { + msg = NULL; if (compat20) { - type = packet_read_poll2(seqnr_p); - if (type) { - active_state->keep_alive_timeouts = 0; - DBG(debug("received packet type %d", type)); + r = ssh_packet_read_poll2(ssh, typep, seqnr_p); + if (r != 0) + return r; + if (*typep) { + state->keep_alive_timeouts = 0; + DBG(debug("received packet type %d", *typep)); } - switch (type) { + switch (*typep) { case SSH2_MSG_IGNORE: debug3("Received SSH2_MSG_IGNORE"); break; case SSH2_MSG_DEBUG: - packet_get_char(); - msg = packet_get_string(NULL); + if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || + (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || + (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { + if (msg) + free(msg); + return r; + } debug("Remote: %.900s", msg); free(msg); - msg = packet_get_string(NULL); - free(msg); break; case SSH2_MSG_DISCONNECT: - reason = packet_get_int(); - msg = packet_get_string(NULL); + if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || + (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) + return r; /* Ignore normal client exit notifications */ - do_log2(active_state->server_side && + do_log2(ssh->state->server_side && reason == SSH2_DISCONNECT_BY_APPLICATION ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, "Received disconnect from %s: %u: %.400s", - get_remote_ipaddr(), reason, msg); + ssh_remote_ipaddr(ssh), reason, msg); free(msg); - cleanup_exit(255); - break; + return SSH_ERR_DISCONNECTED; case SSH2_MSG_UNIMPLEMENTED: - seqnr = packet_get_int(); + if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) + return r; debug("Received SSH2_MSG_UNIMPLEMENTED for %u", seqnr); break; default: - return type; + return 0; } } else { - type = packet_read_poll1(); - switch (type) { + r = ssh_packet_read_poll1(ssh, typep); + switch (*typep) { case SSH_MSG_NONE: return SSH_MSG_NONE; case SSH_MSG_IGNORE: break; case SSH_MSG_DEBUG: - msg = packet_get_string(NULL); + if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) + return r; debug("Remote: %.900s", msg); free(msg); break; case SSH_MSG_DISCONNECT: - msg = packet_get_string(NULL); + if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) + return r; logit("Received disconnect from %s: %.400s", - get_remote_ipaddr(), msg); - cleanup_exit(255); - break; + ssh_remote_ipaddr(ssh), msg); + free(msg); + return SSH_ERR_DISCONNECTED; default: - DBG(debug("received packet type %d", type)); - return type; + DBG(debug("received packet type %d", *typep)); + return 0; } } } @@ -1525,111 +1845,31 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) * together with packet_read_poll. */ -void -packet_process_incoming(const char *buf, u_int len) +int +ssh_packet_process_incoming(struct ssh *ssh, const char *buf, u_int len) { - if (active_state->packet_discard) { - active_state->keep_alive_timeouts = 0; /* ?? */ - if (len >= active_state->packet_discard) - packet_stop_discard(); - active_state->packet_discard -= len; - return; + struct session_state *state = ssh->state; + int r; + + if (state->packet_discard) { + state->keep_alive_timeouts = 0; /* ?? */ + if (len >= state->packet_discard) { + if ((r = ssh_packet_stop_discard(ssh)) != 0) + return r; + } + state->packet_discard -= len; + return 0; } - buffer_append(&active_state->input, buf, len); -} + if ((r = sshbuf_put(ssh->state->input, buf, len)) != 0) + return r; -/* Returns a character from the packet. */ + return 0; +} -u_int -packet_get_char(void) +int +ssh_packet_remaining(struct ssh *ssh) { - char ch; - - buffer_get(&active_state->incoming_packet, &ch, 1); - return (u_char) ch; -} - -/* Returns an integer from the packet data. */ - -u_int -packet_get_int(void) -{ - return buffer_get_int(&active_state->incoming_packet); -} - -/* Returns an 64 bit integer from the packet data. */ - -u_int64_t -packet_get_int64(void) -{ - return buffer_get_int64(&active_state->incoming_packet); -} - -/* - * Returns an arbitrary precision integer from the packet data. The integer - * must have been initialized before this call. - */ - -void -packet_get_bignum(BIGNUM * value) -{ - buffer_get_bignum(&active_state->incoming_packet, value); -} - -void -packet_get_bignum2(BIGNUM * value) -{ - buffer_get_bignum2(&active_state->incoming_packet, value); -} - -#ifdef OPENSSL_HAS_ECC -void -packet_get_ecpoint(const EC_GROUP *curve, EC_POINT *point) -{ - buffer_get_ecpoint(&active_state->incoming_packet, curve, point); -} -#endif - -void * -packet_get_raw(u_int *length_ptr) -{ - u_int bytes = buffer_len(&active_state->incoming_packet); - - if (length_ptr != NULL) - *length_ptr = bytes; - return buffer_ptr(&active_state->incoming_packet); -} - -int -packet_remaining(void) -{ - return buffer_len(&active_state->incoming_packet); -} - -/* - * Returns a string from the packet data. The string is allocated using - * xmalloc; it is the responsibility of the calling program to free it when - * no longer needed. The length_ptr argument may be NULL, or point to an - * integer into which the length of the string is stored. - */ - -void * -packet_get_string(u_int *length_ptr) -{ - return buffer_get_string(&active_state->incoming_packet, length_ptr); -} - -void * -packet_get_string_ptr(u_int *length_ptr) -{ - return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr); -} - -/* Ensures the returned string has no embedded \0 characters in it. */ -char * -packet_get_cstring(u_int *length_ptr) -{ - return buffer_get_cstring(&active_state->incoming_packet, length_ptr); + return sshbuf_len(ssh->state->incoming_packet); } /* @@ -1638,16 +1878,16 @@ packet_get_cstring(u_int *length_ptr) * message is printed immediately, but only if the client is being executed * in verbose mode. These messages are primarily intended to ease debugging * authentication problems. The length of the formatted message must not - * exceed 1024 bytes. This will automatically call packet_write_wait. + * exceed 1024 bytes. This will automatically call ssh_packet_write_wait. */ - void -packet_send_debug(const char *fmt,...) +ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...) { char buf[1024]; va_list args; + int r; - if (compat20 && (datafellows & SSH_BUG_DEBUG)) + if (compat20 && (ssh->compat & SSH_BUG_DEBUG)) return; va_start(args, fmt); @@ -1655,16 +1895,62 @@ packet_send_debug(const char *fmt,...) va_end(args); if (compat20) { - packet_start(SSH2_MSG_DEBUG); - packet_put_char(0); /* bool: always display */ - packet_put_cstring(buf); - packet_put_cstring(""); + if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || + (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ + (r = sshpkt_put_cstring(ssh, buf)) != 0 || + (r = sshpkt_put_cstring(ssh, "")) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); } else { - packet_start(SSH_MSG_DEBUG); - packet_put_cstring(buf); + if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 || + (r = sshpkt_put_cstring(ssh, buf)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + } + if ((r = ssh_packet_write_wait(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); +} + +/* + * Pretty-print connection-terminating errors and exit. + */ +void +sshpkt_fatal(struct ssh *ssh, const char *tag, int r) +{ + switch (r) { + case SSH_ERR_CONN_CLOSED: + logit("Connection closed by %.200s", ssh_remote_ipaddr(ssh)); + cleanup_exit(255); + case SSH_ERR_CONN_TIMEOUT: + logit("Connection to %.200s timed out", ssh_remote_ipaddr(ssh)); + cleanup_exit(255); + case SSH_ERR_DISCONNECTED: + logit("Disconnected from %.200s", + ssh_remote_ipaddr(ssh)); + cleanup_exit(255); + case SSH_ERR_SYSTEM_ERROR: + if (errno == ECONNRESET) { + logit("Connection reset by %.200s", + ssh_remote_ipaddr(ssh)); + cleanup_exit(255); + } + /* FALLTHROUGH */ + case SSH_ERR_NO_CIPHER_ALG_MATCH: + case SSH_ERR_NO_MAC_ALG_MATCH: + case SSH_ERR_NO_COMPRESS_ALG_MATCH: + case SSH_ERR_NO_KEX_ALG_MATCH: + case SSH_ERR_NO_HOSTKEY_ALG_MATCH: + if (ssh && ssh->kex && ssh->kex->failed_choice) { + fatal("Unable to negotiate with %.200s: %s. " + "Their offer: %s", ssh_remote_ipaddr(ssh), + ssh_err(r), ssh->kex->failed_choice); + } + /* FALLTHROUGH */ + default: + fatal("%s%sConnection to %.200s: %s", + tag != NULL ? tag : "", tag != NULL ? ": " : "", + ssh_remote_ipaddr(ssh), ssh_err(r)); } - packet_send(); - packet_write_wait(); } /* @@ -1673,13 +1959,13 @@ packet_send_debug(const char *fmt,...) * should not contain a newline. The length of the formatted message must * not exceed 1024 bytes. */ - void -packet_disconnect(const char *fmt,...) +ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...) { char buf[1024]; va_list args; static int disconnecting = 0; + int r; if (disconnecting) /* Guard against recursive invocations. */ fatal("packet_disconnect called recursively."); @@ -1696,87 +1982,88 @@ packet_disconnect(const char *fmt,...) /* Display the error locally */ logit("Disconnecting: %.100s", buf); - /* Send the disconnect message to the other side, and wait for it to get sent. */ - if (compat20) { - packet_start(SSH2_MSG_DISCONNECT); - packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); - packet_put_cstring(buf); - packet_put_cstring(""); - } else { - packet_start(SSH_MSG_DISCONNECT); - packet_put_cstring(buf); - } - packet_send(); - packet_write_wait(); + /* + * Send the disconnect message to the other side, and wait + * for it to get sent. + */ + if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0) + sshpkt_fatal(ssh, __func__, r); - /* Stop listening for connections. */ - channel_close_all(); + if ((r = ssh_packet_write_wait(ssh)) != 0) + sshpkt_fatal(ssh, __func__, r); /* Close the connection. */ - packet_close(); + ssh_packet_close(ssh); cleanup_exit(255); } -/* Checks if there is any buffered output, and tries to write some of the output. */ - -void -packet_write_poll(void) +/* + * Checks if there is any buffered output, and tries to write some of + * the output. + */ +int +ssh_packet_write_poll(struct ssh *ssh) { - int len = buffer_len(&active_state->output); - int cont; + struct session_state *state = ssh->state; + int len = sshbuf_len(state->output); + int cont, r; if (len > 0) { cont = 0; - len = roaming_write(active_state->connection_out, - buffer_ptr(&active_state->output), len, &cont); + len = roaming_write(state->connection_out, + sshbuf_ptr(state->output), len, &cont); if (len == -1) { if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) - return; - fatal("Write failed: %.100s", strerror(errno)); + return 0; + return SSH_ERR_SYSTEM_ERROR; } if (len == 0 && !cont) - fatal("Write connection closed"); - buffer_consume(&active_state->output, len); + return SSH_ERR_CONN_CLOSED; + if ((r = sshbuf_consume(state->output, len)) != 0) + return r; } + return 0; } /* * Calls packet_write_poll repeatedly until all pending output data has been * written. */ - -void -packet_write_wait(void) +int +ssh_packet_write_wait(struct ssh *ssh) { fd_set *setp; - int ret, ms_remain = 0; + int ret, r, ms_remain = 0; struct timeval start, timeout, *timeoutp = NULL; + struct session_state *state = ssh->state; - setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1, + setp = calloc(howmany(state->connection_out + 1, NFDBITS), sizeof(fd_mask)); - packet_write_poll(); - while (packet_have_data_to_write()) { - memset(setp, 0, howmany(active_state->connection_out + 1, + if (setp == NULL) + return SSH_ERR_ALLOC_FAIL; + ssh_packet_write_poll(ssh); + while (ssh_packet_have_data_to_write(ssh)) { + memset(setp, 0, howmany(state->connection_out + 1, NFDBITS) * sizeof(fd_mask)); - FD_SET(active_state->connection_out, setp); + FD_SET(state->connection_out, setp); - if (active_state->packet_timeout_ms > 0) { - ms_remain = active_state->packet_timeout_ms; + if (state->packet_timeout_ms > 0) { + ms_remain = state->packet_timeout_ms; timeoutp = &timeout; } for (;;) { - if (active_state->packet_timeout_ms != -1) { + if (state->packet_timeout_ms != -1) { ms_to_timeval(&timeout, ms_remain); gettimeofday(&start, NULL); } - if ((ret = select(active_state->connection_out + 1, + if ((ret = select(state->connection_out + 1, NULL, setp, NULL, timeoutp)) >= 0) break; if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) break; - if (active_state->packet_timeout_ms == -1) + if (state->packet_timeout_ms == -1) continue; ms_subtract_diff(&start, &ms_remain); if (ms_remain <= 0) { @@ -1785,45 +2072,48 @@ packet_write_wait(void) } } if (ret == 0) { - logit("Connection to %.200s timed out while " - "waiting to write", get_remote_ipaddr()); - cleanup_exit(255); + free(setp); + return SSH_ERR_CONN_TIMEOUT; + } + if ((r = ssh_packet_write_poll(ssh)) != 0) { + free(setp); + return r; } - packet_write_poll(); } free(setp); + return 0; } /* Returns true if there is buffered data to write to the connection. */ int -packet_have_data_to_write(void) +ssh_packet_have_data_to_write(struct ssh *ssh) { - return buffer_len(&active_state->output) != 0; + return sshbuf_len(ssh->state->output) != 0; } /* Returns true if there is not too much data to write to the connection. */ int -packet_not_very_much_data_to_write(void) +ssh_packet_not_very_much_data_to_write(struct ssh *ssh) { - if (active_state->interactive_mode) - return buffer_len(&active_state->output) < 16384; + if (ssh->state->interactive_mode) + return sshbuf_len(ssh->state->output) < 16384; else - return buffer_len(&active_state->output) < 128 * 1024; + return sshbuf_len(ssh->state->output) < 128 * 1024; } -static void -packet_set_tos(int tos) +void +ssh_packet_set_tos(struct ssh *ssh, int tos) { #ifndef IP_TOS_IS_BROKEN - if (!packet_connection_is_on_socket()) + if (!ssh_packet_connection_is_on_socket(ssh)) return; - switch (packet_connection_af()) { + switch (ssh_packet_connection_af(ssh)) { # ifdef IP_TOS case AF_INET: debug3("%s: set IP_TOS 0x%02x", __func__, tos); - if (setsockopt(active_state->connection_in, + if (setsockopt(ssh->state->connection_in, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) error("setsockopt IP_TOS %d: %.100s:", tos, strerror(errno)); @@ -1832,7 +2122,7 @@ packet_set_tos(int tos) # ifdef IPV6_TCLASS case AF_INET6: debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos); - if (setsockopt(active_state->connection_in, + if (setsockopt(ssh->state->connection_in, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0) error("setsockopt IPV6_TCLASS %d: %.100s:", tos, strerror(errno)); @@ -1845,71 +2135,69 @@ packet_set_tos(int tos) /* Informs that the current session is interactive. Sets IP flags for that. */ void -packet_set_interactive(int interactive, int qos_interactive, int qos_bulk) +ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk) { - if (active_state->set_interactive_called) + struct session_state *state = ssh->state; + + if (state->set_interactive_called) return; - active_state->set_interactive_called = 1; + state->set_interactive_called = 1; /* Record that we are in interactive mode. */ - active_state->interactive_mode = interactive; + state->interactive_mode = interactive; /* Only set socket options if using a socket. */ - if (!packet_connection_is_on_socket()) + if (!ssh_packet_connection_is_on_socket(ssh)) return; - set_nodelay(active_state->connection_in); - packet_set_tos(interactive ? qos_interactive : qos_bulk); + set_nodelay(state->connection_in); + ssh_packet_set_tos(ssh, interactive ? qos_interactive : + qos_bulk); } /* Returns true if the current connection is interactive. */ int -packet_is_interactive(void) +ssh_packet_is_interactive(struct ssh *ssh) { - return active_state->interactive_mode; + return ssh->state->interactive_mode; } int -packet_set_maxsize(u_int s) +ssh_packet_set_maxsize(struct ssh *ssh, u_int s) { - if (active_state->set_maxsize_called) { + struct session_state *state = ssh->state; + + if (state->set_maxsize_called) { logit("packet_set_maxsize: called twice: old %d new %d", - active_state->max_packet_size, s); + state->max_packet_size, s); return -1; } if (s < 4 * 1024 || s > 1024 * 1024) { logit("packet_set_maxsize: bad size %d", s); return -1; } - active_state->set_maxsize_called = 1; + state->set_maxsize_called = 1; debug("packet_set_maxsize: setting to %d", s); - active_state->max_packet_size = s; + state->max_packet_size = s; return s; } int -packet_inc_alive_timeouts(void) +ssh_packet_inc_alive_timeouts(struct ssh *ssh) { - return ++active_state->keep_alive_timeouts; + return ++ssh->state->keep_alive_timeouts; } void -packet_set_alive_timeouts(int ka) +ssh_packet_set_alive_timeouts(struct ssh *ssh, int ka) { - active_state->keep_alive_timeouts = ka; + ssh->state->keep_alive_timeouts = ka; } u_int -packet_get_maxsize(void) +ssh_packet_get_maxsize(struct ssh *ssh) { - return active_state->max_packet_size; -} - -/* roundup current message to pad bytes */ -void -packet_add_padding(u_char pad) -{ - active_state->extra_pad = pad; + return ssh->state->max_packet_size; } /* @@ -1924,135 +2212,718 @@ packet_add_padding(u_char pad) * protection measure against advanced traffic analysis techniques. */ void -packet_send_ignore(int nbytes) +ssh_packet_send_ignore(struct ssh *ssh, int nbytes) { u_int32_t rnd = 0; - int i; + int r, i; - packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); - packet_put_int(nbytes); + if ((r = sshpkt_start(ssh, compat20 ? + SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 || + (r = sshpkt_put_u32(ssh, nbytes)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); for (i = 0; i < nbytes; i++) { if (i % 4 == 0) rnd = arc4random(); - packet_put_char((u_char)rnd & 0xff); + if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); rnd >>= 8; } } #define MAX_PACKETS (1U<<31) int -packet_need_rekeying(void) +ssh_packet_need_rekeying(struct ssh *ssh) { - if (datafellows & SSH_BUG_NOREKEY) + struct session_state *state = ssh->state; + + if (ssh->compat & SSH_BUG_NOREKEY) return 0; return - (active_state->p_send.packets > MAX_PACKETS) || - (active_state->p_read.packets > MAX_PACKETS) || - (active_state->max_blocks_out && - (active_state->p_send.blocks > active_state->max_blocks_out)) || - (active_state->max_blocks_in && - (active_state->p_read.blocks > active_state->max_blocks_in)) || - (active_state->rekey_interval != 0 && active_state->rekey_time + - active_state->rekey_interval <= monotime()); + (state->p_send.packets > MAX_PACKETS) || + (state->p_read.packets > MAX_PACKETS) || + (state->max_blocks_out && + (state->p_send.blocks > state->max_blocks_out)) || + (state->max_blocks_in && + (state->p_read.blocks > state->max_blocks_in)) || + (state->rekey_interval != 0 && state->rekey_time + + state->rekey_interval <= monotime()); } void -packet_set_rekey_limits(u_int32_t bytes, time_t seconds) +ssh_packet_set_rekey_limits(struct ssh *ssh, u_int32_t bytes, time_t seconds) { debug3("rekey after %lld bytes, %d seconds", (long long)bytes, (int)seconds); - active_state->rekey_limit = bytes; - active_state->rekey_interval = seconds; - /* - * We set the time here so that in post-auth privsep slave we count - * from the completion of the authentication. - */ - active_state->rekey_time = monotime(); + ssh->state->rekey_limit = bytes; + ssh->state->rekey_interval = seconds; } time_t -packet_get_rekey_timeout(void) +ssh_packet_get_rekey_timeout(struct ssh *ssh) { time_t seconds; - seconds = active_state->rekey_time + active_state->rekey_interval - + seconds = ssh->state->rekey_time + ssh->state->rekey_interval - monotime(); return (seconds <= 0 ? 1 : seconds); } void -packet_set_server(void) +ssh_packet_set_server(struct ssh *ssh) { - active_state->server_side = 1; + ssh->state->server_side = 1; } void -packet_set_authenticated(void) +ssh_packet_set_authenticated(struct ssh *ssh) { - active_state->after_authentication = 1; + ssh->state->after_authentication = 1; } void * -packet_get_input(void) +ssh_packet_get_input(struct ssh *ssh) { - return (void *)&active_state->input; + return (void *)ssh->state->input; } void * -packet_get_output(void) +ssh_packet_get_output(struct ssh *ssh) { - return (void *)&active_state->output; -} - -void * -packet_get_newkeys(int mode) -{ - return (void *)active_state->newkeys[mode]; + return (void *)ssh->state->output; } +/* XXX TODO update roaming to new API (does not work anyway) */ /* * Save the state for the real connection, and use a separate state when * resuming a suspended connection. */ void -packet_backup_state(void) +ssh_packet_backup_state(struct ssh *ssh, + struct ssh *backup_state) { - struct session_state *tmp; + struct ssh *tmp; - close(active_state->connection_in); - active_state->connection_in = -1; - close(active_state->connection_out); - active_state->connection_out = -1; + close(ssh->state->connection_in); + ssh->state->connection_in = -1; + close(ssh->state->connection_out); + ssh->state->connection_out = -1; if (backup_state) tmp = backup_state; else - tmp = alloc_session_state(); - backup_state = active_state; - active_state = tmp; + tmp = ssh_alloc_session_state(); + backup_state = ssh; + ssh = tmp; } +/* XXX FIXME FIXME FIXME */ /* * Swap in the old state when resuming a connecion. */ void -packet_restore_state(void) +ssh_packet_restore_state(struct ssh *ssh, + struct ssh *backup_state) { - struct session_state *tmp; - void *buf; + struct ssh *tmp; u_int len; + int r; tmp = backup_state; - backup_state = active_state; - active_state = tmp; - active_state->connection_in = backup_state->connection_in; - backup_state->connection_in = -1; - active_state->connection_out = backup_state->connection_out; - backup_state->connection_out = -1; - len = buffer_len(&backup_state->input); + backup_state = ssh; + ssh = tmp; + ssh->state->connection_in = backup_state->state->connection_in; + backup_state->state->connection_in = -1; + ssh->state->connection_out = backup_state->state->connection_out; + backup_state->state->connection_out = -1; + len = sshbuf_len(backup_state->state->input); if (len > 0) { - buf = buffer_ptr(&backup_state->input); - buffer_append(&active_state->input, buf, len); - buffer_clear(&backup_state->input); + if ((r = sshbuf_putb(ssh->state->input, + backup_state->state->input)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + sshbuf_reset(backup_state->state->input); add_recv_bytes(len); } } + +/* Reset after_authentication and reset compression in post-auth privsep */ +static int +ssh_packet_set_postauth(struct ssh *ssh) +{ + struct sshcomp *comp; + int r, mode; + + debug("%s: called", __func__); + /* This was set in net child, but is not visible in user child */ + ssh->state->after_authentication = 1; + ssh->state->rekeying = 0; + for (mode = 0; mode < MODE_MAX; mode++) { + if (ssh->state->newkeys[mode] == NULL) + continue; + comp = &ssh->state->newkeys[mode]->comp; + if (comp && comp->enabled && + (r = ssh_packet_init_compression(ssh)) != 0) + return r; + } + return 0; +} + +/* Packet state (de-)serialization for privsep */ + +/* turn kex into a blob for packet state serialization */ +static int +kex_to_blob(struct sshbuf *m, struct kex *kex) +{ + int r; + + if ((r = sshbuf_put_string(m, kex->session_id, + kex->session_id_len)) != 0 || + (r = sshbuf_put_u32(m, kex->we_need)) != 0 || + (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || + (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || + (r = sshbuf_put_stringb(m, kex->my)) != 0 || + (r = sshbuf_put_stringb(m, kex->peer)) != 0 || + (r = sshbuf_put_u32(m, kex->flags)) != 0 || + (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || + (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) + return r; + return 0; +} + +/* turn key exchange results into a blob for packet state serialization */ +static int +newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode) +{ + struct sshbuf *b; + struct sshcipher_ctx *cc; + struct sshcomp *comp; + struct sshenc *enc; + struct sshmac *mac; + struct newkeys *newkey; + int r; + + if ((newkey = ssh->state->newkeys[mode]) == NULL) + return SSH_ERR_INTERNAL_ERROR; + enc = &newkey->enc; + mac = &newkey->mac; + comp = &newkey->comp; + cc = (mode == MODE_OUT) ? &ssh->state->send_context : + &ssh->state->receive_context; + if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0) + return r; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + /* The cipher struct is constant and shared, you export pointer */ + if ((r = sshbuf_put_cstring(b, enc->name)) != 0 || + (r = sshbuf_put(b, &enc->cipher, sizeof(enc->cipher))) != 0 || + (r = sshbuf_put_u32(b, enc->enabled)) != 0 || + (r = sshbuf_put_u32(b, enc->block_size)) != 0 || + (r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 || + (r = sshbuf_put_string(b, enc->iv, enc->iv_len)) != 0) + goto out; + if (cipher_authlen(enc->cipher) == 0) { + if ((r = sshbuf_put_cstring(b, mac->name)) != 0 || + (r = sshbuf_put_u32(b, mac->enabled)) != 0 || + (r = sshbuf_put_string(b, mac->key, mac->key_len)) != 0) + goto out; + } + if ((r = sshbuf_put_u32(b, comp->type)) != 0 || + (r = sshbuf_put_u32(b, comp->enabled)) != 0 || + (r = sshbuf_put_cstring(b, comp->name)) != 0) + goto out; + r = sshbuf_put_stringb(m, b); + out: + if (b != NULL) + sshbuf_free(b); + return r; +} + +/* serialize packet state into a blob */ +int +ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) +{ + struct session_state *state = ssh->state; + u_char *p; + size_t slen, rlen; + int r, ssh1cipher; + + if (!compat20) { + ssh1cipher = cipher_get_number(state->receive_context.cipher); + slen = cipher_get_keyiv_len(&state->send_context); + rlen = cipher_get_keyiv_len(&state->receive_context); + if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 || + (r = sshbuf_put_u32(m, ssh1cipher)) != 0 || + (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 || + (r = sshbuf_put_u32(m, slen)) != 0 || + (r = sshbuf_reserve(m, slen, &p)) != 0 || + (r = cipher_get_keyiv(&state->send_context, p, slen)) != 0 || + (r = sshbuf_put_u32(m, rlen)) != 0 || + (r = sshbuf_reserve(m, rlen, &p)) != 0 || + (r = cipher_get_keyiv(&state->receive_context, p, rlen)) != 0) + return r; + } else { + if ((r = kex_to_blob(m, ssh->kex)) != 0 || + (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || + (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || + (r = sshbuf_put_u32(m, state->rekey_limit)) != 0 || + (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || + (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || + (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || + (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || + (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || + (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || + (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || + (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || + (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0) + return r; + } + + slen = cipher_get_keycontext(&state->send_context, NULL); + rlen = cipher_get_keycontext(&state->receive_context, NULL); + if ((r = sshbuf_put_u32(m, slen)) != 0 || + (r = sshbuf_reserve(m, slen, &p)) != 0) + return r; + if (cipher_get_keycontext(&state->send_context, p) != (int)slen) + return SSH_ERR_INTERNAL_ERROR; + if ((r = sshbuf_put_u32(m, rlen)) != 0 || + (r = sshbuf_reserve(m, rlen, &p)) != 0) + return r; + if (cipher_get_keycontext(&state->receive_context, p) != (int)rlen) + return SSH_ERR_INTERNAL_ERROR; + + if ((r = ssh_packet_get_compress_state(m, ssh)) != 0 || + (r = sshbuf_put_stringb(m, state->input)) != 0 || + (r = sshbuf_put_stringb(m, state->output)) != 0) + return r; + + if (compat20) { + if ((r = sshbuf_put_u64(m, get_sent_bytes())) != 0 || + (r = sshbuf_put_u64(m, get_recv_bytes())) != 0) + return r; + } + return 0; +} + +/* restore key exchange results from blob for packet state de-serialization */ +static int +newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) +{ + struct sshbuf *b = NULL; + struct sshcomp *comp; + struct sshenc *enc; + struct sshmac *mac; + struct newkeys *newkey = NULL; + size_t keylen, ivlen, maclen; + int r; + + if ((newkey = calloc(1, sizeof(*newkey))) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_froms(m, &b)) != 0) + goto out; +#ifdef DEBUG_PK + sshbuf_dump(b, stderr); +#endif + enc = &newkey->enc; + mac = &newkey->mac; + comp = &newkey->comp; + + if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 || + (r = sshbuf_get(b, &enc->cipher, sizeof(enc->cipher))) != 0 || + (r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 || + (r = sshbuf_get_u32(b, &enc->block_size)) != 0 || + (r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 || + (r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0) + goto out; + if (cipher_authlen(enc->cipher) == 0) { + if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0) + goto out; + if ((r = mac_setup(mac, mac->name)) != 0) + goto out; + if ((r = sshbuf_get_u32(b, (u_int *)&mac->enabled)) != 0 || + (r = sshbuf_get_string(b, &mac->key, &maclen)) != 0) + goto out; + if (maclen > mac->key_len) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + mac->key_len = maclen; + } + if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || + (r = sshbuf_get_u32(b, (u_int *)&comp->enabled)) != 0 || + (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) + goto out; + if (enc->name == NULL || + cipher_by_name(enc->name) != enc->cipher) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(b) != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + enc->key_len = keylen; + enc->iv_len = ivlen; + ssh->kex->newkeys[mode] = newkey; + newkey = NULL; + r = 0; + out: + if (newkey != NULL) + free(newkey); + if (b != NULL) + sshbuf_free(b); + return r; +} + +/* restore kex from blob for packet state de-serialization */ +static int +kex_from_blob(struct sshbuf *m, struct kex **kexp) +{ + struct kex *kex; + int r; + + if ((kex = calloc(1, sizeof(struct kex))) == NULL || + (kex->my = sshbuf_new()) == NULL || + (kex->peer = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || + (r = sshbuf_get_u32(m, &kex->we_need)) != 0 || + (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || + (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || + (r = sshbuf_get_stringb(m, kex->my)) != 0 || + (r = sshbuf_get_stringb(m, kex->peer)) != 0 || + (r = sshbuf_get_u32(m, &kex->flags)) != 0 || + (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || + (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) + goto out; + kex->server = 1; + kex->done = 1; + r = 0; + out: + if (r != 0 || kexp == NULL) { + if (kex != NULL) { + if (kex->my != NULL) + sshbuf_free(kex->my); + if (kex->peer != NULL) + sshbuf_free(kex->peer); + free(kex); + } + if (kexp != NULL) + *kexp = NULL; + } else { + *kexp = kex; + } + return r; +} + +/* + * Restore packet state from content of blob 'm' (de-serialization). + * Note that 'm' will be partially consumed on parsing or any other errors. + */ +int +ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) +{ + struct session_state *state = ssh->state; + const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output; + size_t ssh1keylen, rlen, slen, ilen, olen; + int r; + u_int ssh1cipher = 0; + u_int64_t sent_bytes = 0, recv_bytes = 0; + + if (!compat20) { + if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 || + (r = sshbuf_get_u32(m, &ssh1cipher)) != 0 || + (r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 || + (r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 || + (r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0) + return r; + if (ssh1cipher > INT_MAX) + return SSH_ERR_KEY_UNKNOWN_CIPHER; + ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen, + (int)ssh1cipher); + if (cipher_get_keyiv_len(&state->send_context) != (int)slen || + cipher_get_keyiv_len(&state->receive_context) != (int)rlen) + return SSH_ERR_INVALID_FORMAT; + if ((r = cipher_set_keyiv(&state->send_context, ivout)) != 0 || + (r = cipher_set_keyiv(&state->receive_context, ivin)) != 0) + return r; + } else { + if ((r = kex_from_blob(m, &ssh->kex)) != 0 || + (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || + (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || + (r = sshbuf_get_u32(m, &state->rekey_limit)) != 0 || + (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || + (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || + (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || + (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || + (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || + (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || + (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || + (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || + (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) + return r; + /* + * We set the time here so that in post-auth privsep slave we + * count from the completion of the authentication. + */ + state->rekey_time = monotime(); + /* XXX ssh_set_newkeys overrides p_read.packets? XXX */ + if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || + (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) + return r; + } + if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || + (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) + return r; + if (cipher_get_keycontext(&state->send_context, NULL) != (int)slen || + cipher_get_keycontext(&state->receive_context, NULL) != (int)rlen) + return SSH_ERR_INVALID_FORMAT; + cipher_set_keycontext(&state->send_context, keyout); + cipher_set_keycontext(&state->receive_context, keyin); + + if ((r = ssh_packet_set_compress_state(ssh, m)) != 0 || + (r = ssh_packet_set_postauth(ssh)) != 0) + return r; + + sshbuf_reset(state->input); + sshbuf_reset(state->output); + if ((r = sshbuf_get_string_direct(m, &input, &ilen)) != 0 || + (r = sshbuf_get_string_direct(m, &output, &olen)) != 0 || + (r = sshbuf_put(state->input, input, ilen)) != 0 || + (r = sshbuf_put(state->output, output, olen)) != 0) + return r; + + if (compat20) { + if ((r = sshbuf_get_u64(m, &sent_bytes)) != 0 || + (r = sshbuf_get_u64(m, &recv_bytes)) != 0) + return r; + roam_set_bytes(sent_bytes, recv_bytes); + } + if (sshbuf_len(m)) + return SSH_ERR_INVALID_FORMAT; + debug3("%s: done", __func__); + return 0; +} + +/* NEW API */ + +/* put data to the outgoing packet */ + +int +sshpkt_put(struct ssh *ssh, const void *v, size_t len) +{ + return sshbuf_put(ssh->state->outgoing_packet, v, len); +} + +int +sshpkt_putb(struct ssh *ssh, const struct sshbuf *b) +{ + return sshbuf_putb(ssh->state->outgoing_packet, b); +} + +int +sshpkt_put_u8(struct ssh *ssh, u_char val) +{ + return sshbuf_put_u8(ssh->state->outgoing_packet, val); +} + +int +sshpkt_put_u32(struct ssh *ssh, u_int32_t val) +{ + return sshbuf_put_u32(ssh->state->outgoing_packet, val); +} + +int +sshpkt_put_u64(struct ssh *ssh, u_int64_t val) +{ + return sshbuf_put_u64(ssh->state->outgoing_packet, val); +} + +int +sshpkt_put_string(struct ssh *ssh, const void *v, size_t len) +{ + return sshbuf_put_string(ssh->state->outgoing_packet, v, len); +} + +int +sshpkt_put_cstring(struct ssh *ssh, const void *v) +{ + return sshbuf_put_cstring(ssh->state->outgoing_packet, v); +} + +int +sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v) +{ + return sshbuf_put_stringb(ssh->state->outgoing_packet, v); +} + +#ifdef WITH_OPENSSL +#ifdef OPENSSL_HAS_ECC +int +sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g) +{ + return sshbuf_put_ec(ssh->state->outgoing_packet, v, g); +} +#endif /* OPENSSL_HAS_ECC */ + +#ifdef WITH_SSH1 +int +sshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v) +{ + return sshbuf_put_bignum1(ssh->state->outgoing_packet, v); +} +#endif /* WITH_SSH1 */ + +int +sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v) +{ + return sshbuf_put_bignum2(ssh->state->outgoing_packet, v); +} +#endif /* WITH_OPENSSL */ + +/* fetch data from the incoming packet */ + +int +sshpkt_get(struct ssh *ssh, void *valp, size_t len) +{ + return sshbuf_get(ssh->state->incoming_packet, valp, len); +} + +int +sshpkt_get_u8(struct ssh *ssh, u_char *valp) +{ + return sshbuf_get_u8(ssh->state->incoming_packet, valp); +} + +int +sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp) +{ + return sshbuf_get_u32(ssh->state->incoming_packet, valp); +} + +int +sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp) +{ + return sshbuf_get_u64(ssh->state->incoming_packet, valp); +} + +int +sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp) +{ + return sshbuf_get_string(ssh->state->incoming_packet, valp, lenp); +} + +int +sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) +{ + return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp); +} + +int +sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) +{ + return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp); +} + +#ifdef WITH_OPENSSL +#ifdef OPENSSL_HAS_ECC +int +sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g) +{ + return sshbuf_get_ec(ssh->state->incoming_packet, v, g); +} +#endif /* OPENSSL_HAS_ECC */ + +#ifdef WITH_SSH1 +int +sshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v) +{ + return sshbuf_get_bignum1(ssh->state->incoming_packet, v); +} +#endif /* WITH_SSH1 */ + +int +sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v) +{ + return sshbuf_get_bignum2(ssh->state->incoming_packet, v); +} +#endif /* WITH_OPENSSL */ + +int +sshpkt_get_end(struct ssh *ssh) +{ + if (sshbuf_len(ssh->state->incoming_packet) > 0) + return SSH_ERR_UNEXPECTED_TRAILING_DATA; + return 0; +} + +const u_char * +sshpkt_ptr(struct ssh *ssh, size_t *lenp) +{ + if (lenp != NULL) + *lenp = sshbuf_len(ssh->state->incoming_packet); + return sshbuf_ptr(ssh->state->incoming_packet); +} + +/* start a new packet */ + +int +sshpkt_start(struct ssh *ssh, u_char type) +{ + u_char buf[9]; + int len; + + DBG(debug("packet_start[%d]", type)); + len = compat20 ? 6 : 9; + memset(buf, 0, len - 1); + buf[len - 1] = type; + sshbuf_reset(ssh->state->outgoing_packet); + return sshbuf_put(ssh->state->outgoing_packet, buf, len); +} + +/* send it */ + +int +sshpkt_send(struct ssh *ssh) +{ + if (compat20) + return ssh_packet_send2(ssh); + else + return ssh_packet_send1(ssh); +} + +int +sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) +{ + char buf[1024]; + va_list args; + int r; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + if (compat20) { + if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || + (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || + (r = sshpkt_put_cstring(ssh, buf)) != 0 || + (r = sshpkt_put_cstring(ssh, "")) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; + } else { + if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 || + (r = sshpkt_put_cstring(ssh, buf)) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; + } + return 0; +} + +/* roundup current message to pad bytes */ +int +sshpkt_add_padding(struct ssh *ssh, u_char pad) +{ + ssh->state->extra_pad = pad; + return 0; +} diff --git a/crypto/openssh/packet.h b/crypto/openssh/packet.h index f8edf85..7b06544 100644 --- a/crypto/openssh/packet.h +++ b/crypto/openssh/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.59 2013/07/12 00:19:59 djm Exp $ */ +/* $OpenBSD: packet.h,v 1.66 2015/01/30 01:13:33 djm Exp $ */ /* * Author: Tatu Ylonen @@ -18,110 +18,189 @@ #include -#include -#ifdef OPENSSL_HAS_ECC -#include -#endif - -void packet_set_connection(int, int); -void packet_set_timeout(int, int); -void packet_set_nonblocking(void); -int packet_get_connection_in(void); -int packet_get_connection_out(void); -void packet_close(void); -void packet_set_encryption_key(const u_char *, u_int, int); -u_int packet_get_encryption_key(u_char *); -void packet_set_protocol_flags(u_int); -u_int packet_get_protocol_flags(void); -void packet_start_compression(int); -void packet_set_interactive(int, int, int); -int packet_is_interactive(void); -void packet_set_server(void); -void packet_set_authenticated(void); - -void packet_start(u_char); -void packet_put_char(int ch); -void packet_put_int(u_int value); -void packet_put_int64(u_int64_t value); -void packet_put_bignum(BIGNUM * value); -void packet_put_bignum2(BIGNUM * value); -#ifdef OPENSSL_HAS_ECC -void packet_put_ecpoint(const EC_GROUP *, const EC_POINT *); -#endif -void packet_put_string(const void *buf, u_int len); -void packet_put_cstring(const char *str); -void packet_put_raw(const void *buf, u_int len); -void packet_send(void); - -int packet_read(void); -void packet_read_expect(int type); -void packet_process_incoming(const char *buf, u_int len); -int packet_read_seqnr(u_int32_t *seqnr_p); -int packet_read_poll_seqnr(u_int32_t *seqnr_p); - -u_int packet_get_char(void); -u_int packet_get_int(void); -u_int64_t packet_get_int64(void); -void packet_get_bignum(BIGNUM * value); -void packet_get_bignum2(BIGNUM * value); -#ifdef OPENSSL_HAS_ECC -void packet_get_ecpoint(const EC_GROUP *, EC_POINT *); -#endif -void *packet_get_raw(u_int *length_ptr); -void *packet_get_string(u_int *length_ptr); -char *packet_get_cstring(u_int *length_ptr); -void *packet_get_string_ptr(u_int *length_ptr); -void packet_disconnect(const char *fmt,...) __attribute__((noreturn)) __attribute__((format(printf, 1, 2))); -void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); - -void set_newkeys(int mode); -int packet_get_keyiv_len(int); -void packet_get_keyiv(int, u_char *, u_int); -int packet_get_keycontext(int, u_char *); -void packet_set_keycontext(int, u_char *); -void packet_get_state(int, u_int32_t *, u_int64_t *, u_int32_t *, u_int64_t *); -void packet_set_state(int, u_int32_t, u_int64_t, u_int32_t, u_int64_t); -int packet_get_ssh1_cipher(void); -void packet_set_iv(int, u_char *); -void *packet_get_newkeys(int); - -void packet_write_poll(void); -void packet_write_wait(void); -int packet_have_data_to_write(void); -int packet_not_very_much_data_to_write(void); - -int packet_connection_is_on_socket(void); -int packet_remaining(void); -void packet_send_ignore(int); -void packet_add_padding(u_char); +#ifdef WITH_OPENSSL +# include +# ifdef OPENSSL_HAS_ECC +# include +# else /* OPENSSL_HAS_ECC */ +# define EC_KEY void +# define EC_GROUP void +# define EC_POINT void +# endif /* OPENSSL_HAS_ECC */ +#else /* WITH_OPENSSL */ +# define BIGNUM void +# define EC_KEY void +# define EC_GROUP void +# define EC_POINT void +#endif /* WITH_OPENSSL */ + +#include +#include "openbsd-compat/sys-queue.h" + +struct kex; +struct sshkey; +struct sshbuf; +struct session_state; /* private session data */ + +#include "dispatch.h" /* typedef, DISPATCH_MAX */ + +struct key_entry { + TAILQ_ENTRY(key_entry) next; + struct sshkey *key; +}; + +struct ssh { + /* Session state */ + struct session_state *state; + + /* Key exchange */ + struct kex *kex; + + /* cached remote ip address and port*/ + char *remote_ipaddr; + int remote_port; + + /* Dispatcher table */ + dispatch_fn *dispatch[DISPATCH_MAX]; + /* number of packets to ignore in the dispatcher */ + int dispatch_skip_packets; + + /* datafellows */ + int compat; + + /* Lists for private and public keys */ + TAILQ_HEAD(, key_entry) private_keys; + TAILQ_HEAD(, key_entry) public_keys; + + /* APP data */ + void *app_data; +}; + +struct ssh *ssh_alloc_session_state(void); +struct ssh *ssh_packet_set_connection(struct ssh *, int, int); +void ssh_packet_set_timeout(struct ssh *, int, int); +int ssh_packet_stop_discard(struct ssh *); +int ssh_packet_connection_af(struct ssh *); +void ssh_packet_set_nonblocking(struct ssh *); +int ssh_packet_get_connection_in(struct ssh *); +int ssh_packet_get_connection_out(struct ssh *); +void ssh_packet_close(struct ssh *); +void ssh_packet_set_encryption_key(struct ssh *, const u_char *, u_int, int); +void ssh_packet_set_protocol_flags(struct ssh *, u_int); +u_int ssh_packet_get_protocol_flags(struct ssh *); +int ssh_packet_start_compression(struct ssh *, int); +void ssh_packet_set_tos(struct ssh *, int); +void ssh_packet_set_interactive(struct ssh *, int, int, int); +int ssh_packet_is_interactive(struct ssh *); +void ssh_packet_set_server(struct ssh *); +void ssh_packet_set_authenticated(struct ssh *); + +int ssh_packet_send1(struct ssh *); +int ssh_packet_send2_wrapped(struct ssh *); +int ssh_packet_send2(struct ssh *); + +int ssh_packet_read(struct ssh *); +int ssh_packet_read_expect(struct ssh *, u_int type); +int ssh_packet_read_poll(struct ssh *); +int ssh_packet_read_poll1(struct ssh *, u_char *); +int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); +int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); +int ssh_packet_read_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p); +int ssh_packet_read_poll_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p); + +const void *ssh_packet_get_string_ptr(struct ssh *, u_int *length_ptr); +void ssh_packet_disconnect(struct ssh *, const char *fmt, ...) + __attribute__((format(printf, 2, 3))) + __attribute__((noreturn)); +void ssh_packet_send_debug(struct ssh *, const char *fmt, ...) __attribute__((format(printf, 2, 3))); + +int ssh_set_newkeys(struct ssh *, int mode); +void ssh_packet_get_bytes(struct ssh *, u_int64_t *, u_int64_t *); + +typedef void *(ssh_packet_comp_alloc_func)(void *, u_int, u_int); +typedef void (ssh_packet_comp_free_func)(void *, void *); +void ssh_packet_set_compress_hooks(struct ssh *, void *, + ssh_packet_comp_alloc_func *, ssh_packet_comp_free_func *); + +int ssh_packet_write_poll(struct ssh *); +int ssh_packet_write_wait(struct ssh *); +int ssh_packet_have_data_to_write(struct ssh *); +int ssh_packet_not_very_much_data_to_write(struct ssh *); + +int ssh_packet_connection_is_on_socket(struct ssh *); +int ssh_packet_remaining(struct ssh *); +void ssh_packet_send_ignore(struct ssh *, int); void tty_make_modes(int, struct termios *); void tty_parse_modes(int, int *); -void packet_set_alive_timeouts(int); -int packet_inc_alive_timeouts(void); -int packet_set_maxsize(u_int); -u_int packet_get_maxsize(void); - -/* don't allow remaining bytes after the end of the message */ -#define packet_check_eom() \ -do { \ - int _len = packet_remaining(); \ - if (_len > 0) { \ - logit("Packet integrity error (%d bytes remaining) at %s:%d", \ - _len ,__FILE__, __LINE__); \ - packet_disconnect("Packet integrity error."); \ - } \ -} while (0) - -int packet_need_rekeying(void); -void packet_set_rekey_limits(u_int32_t, time_t); -time_t packet_get_rekey_timeout(void); - -void packet_backup_state(void); -void packet_restore_state(void); - -void *packet_get_input(void); -void *packet_get_output(void); +void ssh_packet_set_alive_timeouts(struct ssh *, int); +int ssh_packet_inc_alive_timeouts(struct ssh *); +int ssh_packet_set_maxsize(struct ssh *, u_int); +u_int ssh_packet_get_maxsize(struct ssh *); + +int ssh_packet_get_state(struct ssh *, struct sshbuf *); +int ssh_packet_set_state(struct ssh *, struct sshbuf *); + +const char *ssh_remote_ipaddr(struct ssh *); + +int ssh_packet_need_rekeying(struct ssh *); +void ssh_packet_set_rekey_limits(struct ssh *, u_int32_t, time_t); +time_t ssh_packet_get_rekey_timeout(struct ssh *); + +/* XXX FIXME */ +void ssh_packet_backup_state(struct ssh *, struct ssh *); +void ssh_packet_restore_state(struct ssh *, struct ssh *); + +void *ssh_packet_get_input(struct ssh *); +void *ssh_packet_get_output(struct ssh *); + +/* new API */ +int sshpkt_start(struct ssh *ssh, u_char type); +int sshpkt_send(struct ssh *ssh); +int sshpkt_disconnect(struct ssh *, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +int sshpkt_add_padding(struct ssh *, u_char); +void sshpkt_fatal(struct ssh *ssh, const char *tag, int r); + +int sshpkt_put(struct ssh *ssh, const void *v, size_t len); +int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b); +int sshpkt_put_u8(struct ssh *ssh, u_char val); +int sshpkt_put_u32(struct ssh *ssh, u_int32_t val); +int sshpkt_put_u64(struct ssh *ssh, u_int64_t val); +int sshpkt_put_string(struct ssh *ssh, const void *v, size_t len); +int sshpkt_put_cstring(struct ssh *ssh, const void *v); +int sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v); +int sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g); +int sshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v); +int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v); + +int sshpkt_get(struct ssh *ssh, void *valp, size_t len); +int sshpkt_get_u8(struct ssh *ssh, u_char *valp); +int sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp); +int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp); +int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp); +int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); +int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp); +int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g); +int sshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v); +int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v); +int sshpkt_get_end(struct ssh *ssh); +const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); + +/* OLD API */ +extern struct ssh *active_state; +#include "opacket.h" + +#if !defined(WITH_OPENSSL) +# undef BIGNUM +# undef EC_KEY +# undef EC_GROUP +# undef EC_POINT +#elif !defined(OPENSSL_HAS_ECC) +# undef EC_KEY +# undef EC_GROUP +# undef EC_POINT +#endif #endif /* PACKET_H */ diff --git a/crypto/openssh/platform.c b/crypto/openssh/platform.c index 30fc609..ee313da 100644 --- a/crypto/openssh/platform.c +++ b/crypto/openssh/platform.c @@ -1,4 +1,4 @@ -/* $Id: platform.c,v 1.21 2014/01/21 01:59:29 tim Exp $ */ +/* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */ /* * Copyright (c) 2006 Darren Tucker. All rights reserved. @@ -25,6 +25,7 @@ #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" #include "key.h" #include "hostfile.h" diff --git a/crypto/openssh/poly1305.h b/crypto/openssh/poly1305.h index 221efc4..f7db5f8 100644 --- a/crypto/openssh/poly1305.h +++ b/crypto/openssh/poly1305.h @@ -1,4 +1,4 @@ -/* $OpenBSD: poly1305.h,v 1.2 2013/12/19 22:57:13 djm Exp $ */ +/* $OpenBSD: poly1305.h,v 1.4 2014/05/02 03:27:54 djm Exp $ */ /* * Public Domain poly1305 from Andrew Moon diff --git a/crypto/openssh/progressmeter.c b/crypto/openssh/progressmeter.c index bbbc706..319b747 100644 --- a/crypto/openssh/progressmeter.c +++ b/crypto/openssh/progressmeter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: progressmeter.c,v 1.40 2013/09/19 00:24:52 djm Exp $ */ +/* $OpenBSD: progressmeter.c,v 1.41 2015/01/14 13:54:13 djm Exp $ */ /* * Copyright (c) 2003 Nils Nordman. All rights reserved. * @@ -65,7 +65,7 @@ static void update_progress_meter(int); static time_t start; /* start progress */ static time_t last_update; /* last progress update */ -static char *file; /* name of the file being transferred */ +static const char *file; /* name of the file being transferred */ static off_t start_pos; /* initial position of transfer */ static off_t end_pos; /* ending position of transfer */ static off_t cur_pos; /* transfer position as of last refresh */ @@ -248,7 +248,7 @@ update_progress_meter(int ignore) } void -start_progress_meter(char *f, off_t filesize, off_t *ctr) +start_progress_meter(const char *f, off_t filesize, off_t *ctr) { start = last_update = monotime(); file = f; diff --git a/crypto/openssh/progressmeter.h b/crypto/openssh/progressmeter.h index 10bab99..bf179dc 100644 --- a/crypto/openssh/progressmeter.h +++ b/crypto/openssh/progressmeter.h @@ -1,4 +1,4 @@ -/* $OpenBSD: progressmeter.h,v 1.2 2006/03/25 22:22:43 djm Exp $ */ +/* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */ /* * Copyright (c) 2002 Nils Nordman. All rights reserved. * @@ -23,5 +23,5 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -void start_progress_meter(char *, off_t, off_t *); +void start_progress_meter(const char *, off_t, off_t *); void stop_progress_meter(void); diff --git a/crypto/openssh/readconf.c b/crypto/openssh/readconf.c index df8387c..326a59c 100644 --- a/crypto/openssh/readconf.c +++ b/crypto/openssh/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.218 2014/02/23 20:11:36 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.239 2015/07/30 00:01:34 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -20,6 +20,7 @@ __RCSID("$FreeBSD$"); #include #include #include +#include #include #include @@ -29,6 +30,7 @@ __RCSID("$FreeBSD$"); #include #include #include +#include #include #ifdef HAVE_PATHS_H # include @@ -42,6 +44,9 @@ __RCSID("$FreeBSD$"); #ifdef HAVE_UTIL_H #include #endif +#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) +# include +#endif #include "xmalloc.h" #include "ssh.h" @@ -49,14 +54,15 @@ __RCSID("$FreeBSD$"); #include "cipher.h" #include "pathnames.h" #include "log.h" -#include "key.h" +#include "sshkey.h" +#include "misc.h" #include "readconf.h" #include "match.h" -#include "misc.h" -#include "buffer.h" #include "kex.h" #include "mac.h" #include "uidswap.h" +#include "myproposal.h" +#include "digest.h" #include "version.h" /* Format of the configuration file: @@ -126,6 +132,7 @@ __RCSID("$FreeBSD$"); typedef enum { oBadOption, + oVersionAddendum, oHost, oMatch, oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, oGatewayPorts, oExitOnForwardFailure, @@ -137,7 +144,7 @@ typedef enum { oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, - oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, + oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, @@ -152,7 +159,9 @@ typedef enum { oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, - oVersionAddendum, + oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, + oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, + oPubkeyAcceptedKeyTypes, oIgnoredUnknownOption, oDeprecated, oUnsupported } OpCodes; @@ -214,7 +223,7 @@ static struct { { "globalknownhostsfile", oGlobalKnownHostsFile }, { "globalknownhostsfile2", oDeprecated }, { "userknownhostsfile", oUserKnownHostsFile }, - { "userknownhostsfile2", oDeprecated }, + { "userknownhostsfile2", oDeprecated }, { "connectionattempts", oConnectionAttempts }, { "batchmode", oBatchMode }, { "checkhostip", oCheckHostIP }, @@ -265,11 +274,20 @@ static struct { { "canonicalizehostname", oCanonicalizeHostname }, { "canonicalizemaxdots", oCanonicalizeMaxDots }, { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, + { "streamlocalbindmask", oStreamLocalBindMask }, + { "streamlocalbindunlink", oStreamLocalBindUnlink }, + { "revokedhostkeys", oRevokedHostKeys }, + { "fingerprinthash", oFingerprintHash }, + { "updatehostkeys", oUpdateHostkeys }, + { "hostbasedkeytypes", oHostbasedKeyTypes }, + { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, { "ignoreunknown", oIgnoreUnknown }, { "hpndisabled", oDeprecated }, { "hpnbuffersize", oDeprecated }, { "tcprcvbufpoll", oDeprecated }, { "tcprcvbuf", oDeprecated }, + { "noneenabled", oUnsupported }, + { "noneswitch", oUnsupported }, { "versionaddendum", oVersionAddendum }, { NULL, oBadOption } @@ -281,9 +299,9 @@ static struct { */ void -add_local_forward(Options *options, const Forward *newfwd) +add_local_forward(Options *options, const struct Forward *newfwd) { - Forward *fwd; + struct Forward *fwd; #ifndef NO_IPPORT_RESERVED_CONCEPT extern uid_t original_real_uid; int ipport_reserved; @@ -299,17 +317,21 @@ add_local_forward(Options *options, const Forward *newfwd) ipport_reserved = IPPORT_RESERVED; #endif if (newfwd->listen_port < ipport_reserved && original_real_uid != 0) + if (newfwd->listen_port < ipport_reserved && original_real_uid != 0 && + newfwd->listen_path == NULL) fatal("Privileged ports can only be forwarded by root."); #endif - options->local_forwards = xrealloc(options->local_forwards, + options->local_forwards = xreallocarray(options->local_forwards, options->num_local_forwards + 1, sizeof(*options->local_forwards)); fwd = &options->local_forwards[options->num_local_forwards++]; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; + fwd->listen_path = newfwd->listen_path; fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; + fwd->connect_path = newfwd->connect_path; } /* @@ -318,19 +340,21 @@ add_local_forward(Options *options, const Forward *newfwd) */ void -add_remote_forward(Options *options, const Forward *newfwd) +add_remote_forward(Options *options, const struct Forward *newfwd) { - Forward *fwd; + struct Forward *fwd; - options->remote_forwards = xrealloc(options->remote_forwards, + options->remote_forwards = xreallocarray(options->remote_forwards, options->num_remote_forwards + 1, sizeof(*options->remote_forwards)); fwd = &options->remote_forwards[options->num_remote_forwards++]; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; + fwd->listen_path = newfwd->listen_path; fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; + fwd->connect_path = newfwd->connect_path; fwd->handle = newfwd->handle; fwd->allocated_port = 0; } @@ -342,7 +366,9 @@ clear_forwardings(Options *options) for (i = 0; i < options->num_local_forwards; i++) { free(options->local_forwards[i].listen_host); + free(options->local_forwards[i].listen_path); free(options->local_forwards[i].connect_host); + free(options->local_forwards[i].connect_path); } if (options->num_local_forwards > 0) { free(options->local_forwards); @@ -351,7 +377,9 @@ clear_forwardings(Options *options) options->num_local_forwards = 0; for (i = 0; i < options->num_remote_forwards; i++) { free(options->remote_forwards[i].listen_host); + free(options->remote_forwards[i].listen_path); free(options->remote_forwards[i].connect_host); + free(options->remote_forwards[i].connect_path); } if (options->num_remote_forwards > 0) { free(options->remote_forwards); @@ -366,6 +394,7 @@ add_identity_file(Options *options, const char *dir, const char *filename, int userprovided) { char *path; + int i; if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) fatal("Too many identity files specified (max %d)", @@ -376,6 +405,16 @@ add_identity_file(Options *options, const char *dir, const char *filename, else (void)xasprintf(&path, "%.100s%.100s", dir, filename); + /* Avoid registering duplicates */ + for (i = 0; i < options->num_identity_files; i++) { + if (options->identity_file_userprovided[i] == userprovided && + strcmp(options->identity_files[i], path) == 0) { + debug2("%s: ignoring duplicate key %s", __func__, path); + free(path); + return; + } + } + options->identity_file_userprovided[options->num_identity_files] = userprovided; options->identity_files[options->num_identity_files++] = path; @@ -463,7 +502,7 @@ execute_in_shell(const char *cmd) if (!WIFEXITED(status)) { error("command '%.100s' exited abnormally", cmd); return -1; - } + } debug3("command returned status %d", WEXITSTATUS(status)); return WEXITSTATUS(status); } @@ -473,12 +512,12 @@ execute_in_shell(const char *cmd) */ static int match_cfg_line(Options *options, char **condition, struct passwd *pw, - const char *host_arg, const char *filename, int linenum) + const char *host_arg, const char *original_host, int post_canon, + const char *filename, int linenum) { - char *arg, *attrib, *cmd, *cp = *condition, *host; + char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; const char *ruser; - int r, port, result = 1, attributes = 0; - size_t len; + int r, port, this_result, result = 1, attributes = 0, negate; char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; /* @@ -494,53 +533,63 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, } else host = xstrdup(host_arg); - debug3("checking match for '%s' host %s", cp, host); - while ((attrib = strdelim(&cp)) && *attrib != '\0') { - attributes++; + debug2("checking match for '%s' host %s originally %s", + cp, host, original_host); + while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { + criteria = NULL; + this_result = 1; + if ((negate = attrib[0] == '!')) + attrib++; + /* criteria "all" and "canonical" have no argument */ if (strcasecmp(attrib, "all") == 0) { - if (attributes != 1 || + if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && *arg != '\0')) { - error("'all' cannot be combined with other " - "Match attributes"); + error("%.200s line %d: '%s' cannot be combined " + "with other Match attributes", + filename, linenum, oattrib); result = -1; goto out; } - *condition = cp; - result = 1; + if (result) + result = negate ? 0 : 1; goto out; } + attributes++; + if (strcasecmp(attrib, "canonical") == 0) { + r = !!post_canon; /* force bitmask member to boolean */ + if (r == (negate ? 1 : 0)) + this_result = result = 0; + debug3("%.200s line %d: %smatched '%s'", + filename, linenum, + this_result ? "" : "not ", oattrib); + continue; + } + /* All other criteria require an argument */ if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { error("Missing Match criteria for %s", attrib); result = -1; goto out; } - len = strlen(arg); if (strcasecmp(attrib, "host") == 0) { - if (match_hostname(host, arg, len) != 1) - result = 0; - else - debug("%.200s line %d: matched 'Host %.100s' ", - filename, linenum, host); + criteria = xstrdup(host); + r = match_hostname(host, arg) == 1; + if (r == (negate ? 1 : 0)) + this_result = result = 0; } else if (strcasecmp(attrib, "originalhost") == 0) { - if (match_hostname(host_arg, arg, len) != 1) - result = 0; - else - debug("%.200s line %d: matched " - "'OriginalHost %.100s' ", - filename, linenum, host_arg); + criteria = xstrdup(original_host); + r = match_hostname(original_host, arg) == 1; + if (r == (negate ? 1 : 0)) + this_result = result = 0; } else if (strcasecmp(attrib, "user") == 0) { - if (match_pattern_list(ruser, arg, len, 0) != 1) - result = 0; - else - debug("%.200s line %d: matched 'User %.100s' ", - filename, linenum, ruser); + criteria = xstrdup(ruser); + r = match_pattern_list(ruser, arg, 0) == 1; + if (r == (negate ? 1 : 0)) + this_result = result = 0; } else if (strcasecmp(attrib, "localuser") == 0) { - if (match_pattern_list(pw->pw_name, arg, len, 0) != 1) - result = 0; - else - debug("%.200s line %d: matched " - "'LocalUser %.100s' ", - filename, linenum, pw->pw_name); + criteria = xstrdup(pw->pw_name); + r = match_pattern_list(pw->pw_name, arg, 0) == 1; + if (r == (negate ? 1 : 0)) + this_result = result = 0; } else if (strcasecmp(attrib, "exec") == 0) { if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); @@ -553,47 +602,49 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, "d", pw->pw_dir, "h", host, "l", thishost, - "n", host_arg, + "n", original_host, "p", portstr, "r", ruser, "u", pw->pw_name, (char *)NULL); if (result != 1) { /* skip execution if prior predicate failed */ - debug("%.200s line %d: skipped exec \"%.100s\"", - filename, linenum, cmd); - } else { - r = execute_in_shell(cmd); - if (r == -1) { - fatal("%.200s line %d: match exec " - "'%.100s' error", filename, - linenum, cmd); - } else if (r == 0) { - debug("%.200s line %d: matched " - "'exec \"%.100s\"'", filename, - linenum, cmd); - } else { - debug("%.200s line %d: no match " - "'exec \"%.100s\"'", filename, - linenum, cmd); - result = 0; - } + debug3("%.200s line %d: skipped exec " + "\"%.100s\"", filename, linenum, cmd); + free(cmd); + continue; } + r = execute_in_shell(cmd); + if (r == -1) { + fatal("%.200s line %d: match exec " + "'%.100s' error", filename, + linenum, cmd); + } + criteria = xstrdup(cmd); free(cmd); + /* Force exit status to boolean */ + r = r == 0; + if (r == (negate ? 1 : 0)) + this_result = result = 0; } else { error("Unsupported Match attribute %s", attrib); result = -1; goto out; } + debug3("%.200s line %d: %smatched '%s \"%.100s\"' ", + filename, linenum, this_result ? "": "not ", + oattrib, criteria); + free(criteria); } if (attributes == 0) { error("One or more attributes required for Match"); result = -1; goto out; } - debug3("match %sfound", result ? "" : "not "); - *condition = cp; out: + if (result != -1) + debug2("match %sfound", result ? "" : "not "); + *condition = cp; free(host); return result; } @@ -638,8 +689,8 @@ parse_token(const char *cp, const char *filename, int linenum, for (i = 0; keywords[i].name; i++) if (strcmp(cp, keywords[i].name) == 0) return keywords[i].opcode; - if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown, - strlen(ignored_unknown), 1) == 1) + if (ignored_unknown != NULL && + match_pattern_list(cp, ignored_unknown, 1) == 1) return oIgnoredUnknownOption; error("%s: line %d: Bad configuration option: %s", filename, linenum, cp); @@ -716,7 +767,8 @@ static const struct multistate multistate_canonicalizehostname[] = { #define WHITESPACE " \t\r\n" int process_config_line(Options *options, struct passwd *pw, const char *host, - char *line, const char *filename, int linenum, int *activep, int userconfig) + const char *original_host, char *line, const char *filename, + int linenum, int *activep, int flags) { char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; char **cpptr, fwdarg[256]; @@ -725,7 +777,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, LogLevel *log_level_ptr; long long val64; size_t len; - Forward fwd; + struct Forward fwd; const struct multistate *multistate_ptr; struct allowed_cname *cname; @@ -735,7 +787,9 @@ process_config_line(Options *options, struct passwd *pw, const char *host, } /* Strip trailing whitespace */ - for (len = strlen(line) - 1; len > 0; len--) { + if ((len = strlen(line)) == 0) + return 0; + for (len--; len > 0; len--) { if (strchr(WHITESPACE, line[len]) == NULL) break; line[len] = '\0'; @@ -772,7 +826,9 @@ parse_time: if (!arg || *arg == '\0') fatal("%s line %d: missing time value.", filename, linenum); - if ((value = convtime(arg)) == -1) + if (strcmp(arg, "none") == 0) + value = -1; + else if ((value = convtime(arg)) == -1) fatal("%s line %d: invalid time value.", filename, linenum); if (*activep && *intptr == -1) @@ -809,13 +865,13 @@ parse_time: case oForwardX11Trusted: intptr = &options->forward_x11_trusted; goto parse_flag; - + case oForwardX11Timeout: intptr = &options->forward_x11_timeout; goto parse_time; case oGatewayPorts: - intptr = &options->gateway_ports; + intptr = &options->fwd_opts.gateway_ports; goto parse_flag; case oExitOnForwardFailure: @@ -944,7 +1000,8 @@ parse_time: if (*intptr >= SSH_MAX_IDENTITY_FILES) fatal("%.200s line %d: Too many identity files specified (max %d).", filename, linenum, SSH_MAX_IDENTITY_FILES); - add_identity_file(options, NULL, arg, userconfig); + add_identity_file(options, NULL, + arg, flags & SSHCONF_USERCONF); } break; @@ -1053,7 +1110,7 @@ parse_int: arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing argument.", filename, linenum); - if (!ciphers_valid(arg)) + if (!ciphers_valid(*arg == '+' ? arg + 1 : arg)) fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, arg ? arg : ""); if (*activep && options->ciphers == NULL) @@ -1064,7 +1121,7 @@ parse_int: arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing argument.", filename, linenum); - if (!mac_valid(arg)) + if (!mac_valid(*arg == '+' ? arg + 1 : arg)) fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", filename, linenum, arg ? arg : ""); if (*activep && options->macs == NULL) @@ -1076,7 +1133,7 @@ parse_int: if (!arg || *arg == '\0') fatal("%.200s line %d: Missing argument.", filename, linenum); - if (!kex_names_valid(arg)) + if (!kex_names_valid(*arg == '+' ? arg + 1 : arg)) fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", filename, linenum, arg ? arg : ""); if (*activep && options->kex_algorithms == NULL) @@ -1084,14 +1141,17 @@ parse_int: break; case oHostKeyAlgorithms: + charptr = &options->hostkeyalgorithms; +parse_keytypes: arg = strdelim(&s); if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (!key_names_valid2(arg)) - fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", - filename, linenum, arg ? arg : ""); - if (*activep && options->hostkeyalgorithms == NULL) - options->hostkeyalgorithms = xstrdup(arg); + fatal("%.200s line %d: Missing argument.", + filename, linenum); + if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1)) + fatal("%s line %d: Bad key types '%s'.", + filename, linenum, arg ? arg : ""); + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); break; case oProtocol: @@ -1192,8 +1252,8 @@ parse_int: if (cmdline) fatal("Host directive not supported as a command-line " "option"); - value = match_cfg_line(options, &s, pw, host, - filename, linenum); + value = match_cfg_line(options, &s, pw, host, original_host, + flags & SSHCONF_POSTCANON, filename, linenum); if (value < 0) fatal("%.200s line %d: Bad Match condition", filename, linenum); @@ -1205,13 +1265,13 @@ parse_int: arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing argument.", filename, linenum); - if (arg[0] == '^' && arg[2] == 0 && + if (strcmp(arg, "none") == 0) + value = SSH_ESCAPECHAR_NONE; + else if (arg[1] == '\0') + value = (u_char) arg[0]; + else if (arg[0] == '^' && arg[2] == 0 && (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) value = (u_char) arg[1] & 31; - else if (strlen(arg) == 1) - value = (u_char) arg[0]; - else if (strcmp(arg, "none") == 0) - value = SSH_ESCAPECHAR_NONE; else { fatal("%.200s line %d: Bad escape character.", filename, linenum); @@ -1431,6 +1491,51 @@ parse_int: intptr = &options->canonicalize_fallback_local; goto parse_flag; + case oStreamLocalBindMask: + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); + /* Parse mode in octal format */ + value = strtol(arg, &endofnumber, 8); + if (arg == endofnumber || value < 0 || value > 0777) + fatal("%.200s line %d: Bad mask.", filename, linenum); + options->fwd_opts.streamlocal_bind_mask = (mode_t)value; + break; + + case oStreamLocalBindUnlink: + intptr = &options->fwd_opts.streamlocal_bind_unlink; + goto parse_flag; + + case oRevokedHostKeys: + charptr = &options->revoked_host_keys; + goto parse_string; + + case oFingerprintHash: + intptr = &options->fingerprint_hash; + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", + filename, linenum); + if ((value = ssh_digest_alg_by_name(arg)) == -1) + fatal("%.200s line %d: Invalid hash algorithm \"%s\".", + filename, linenum, arg); + if (*activep && *intptr == -1) + *intptr = value; + break; + + case oUpdateHostkeys: + intptr = &options->update_hostkeys; + multistate_ptr = multistate_yesnoask; + goto parse_multistate; + + case oHostbasedKeyTypes: + charptr = &options->hostbased_key_types; + goto parse_keytypes; + + case oPubkeyAcceptedKeyTypes: + charptr = &options->pubkey_key_types; + goto parse_keytypes; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); @@ -1442,7 +1547,7 @@ parse_int: return 0; default: - fatal("process_config_line: Unimplemented opcode %d", opcode); + fatal("%s: Unimplemented opcode %d", __func__, opcode); } /* Check that there is no garbage at end of line. */ @@ -1462,7 +1567,7 @@ parse_int: int read_config_file(const char *filename, struct passwd *pw, const char *host, - Options *options, int flags) + const char *original_host, Options *options, int flags) { FILE *f; char line[1024]; @@ -1493,8 +1598,8 @@ read_config_file(const char *filename, struct passwd *pw, const char *host, while (fgets(line, sizeof(line), f)) { /* Update line number counter. */ linenum++; - if (process_config_line(options, pw, host, line, filename, - linenum, &active, flags & SSHCONF_USERCONF) != 0) + if (process_config_line(options, pw, host, original_host, + line, filename, linenum, &active, flags) != 0) bad_options++; } fclose(f); @@ -1522,13 +1627,16 @@ void initialize_options(Options * options) { memset(options, 'X', sizeof(*options)); + options->version_addendum = NULL; options->forward_agent = -1; options->forward_x11 = -1; options->forward_x11_trusted = -1; options->forward_x11_timeout = -1; options->exit_on_forward_failure = -1; options->xauth_location = NULL; - options->gateway_ports = -1; + options->fwd_opts.gateway_ports = -1; + options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; + options->fwd_opts.streamlocal_bind_unlink = -1; options->use_privileged_port = -1; options->rsa_authentication = -1; options->pubkey_authentication = -1; @@ -1605,7 +1713,11 @@ initialize_options(Options * options) options->canonicalize_max_dots = -1; options->canonicalize_fallback_local = -1; options->canonicalize_hostname = -1; - options->version_addendum = NULL; + options->revoked_host_keys = NULL; + options->fingerprint_hash = -1; + options->update_hostkeys = -1; + options->hostbased_key_types = NULL; + options->pubkey_key_types = NULL; } /* @@ -1642,8 +1754,12 @@ fill_default_options(Options * options) options->exit_on_forward_failure = 0; if (options->xauth_location == NULL) options->xauth_location = _PATH_XAUTH; - if (options->gateway_ports == -1) - options->gateway_ports = 0; + if (options->fwd_opts.gateway_ports == -1) + options->fwd_opts.gateway_ports = 0; + if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) + options->fwd_opts.streamlocal_bind_mask = 0177; + if (options->fwd_opts.streamlocal_bind_unlink == -1) + options->fwd_opts.streamlocal_bind_unlink = 0; if (options->use_privileged_port == -1) options->use_privileged_port = 0; if (options->rsa_authentication == -1) @@ -1687,9 +1803,6 @@ fill_default_options(Options * options) /* Selected in ssh_login(). */ if (options->cipher == -1) options->cipher = SSH_CIPHER_NOT_SET; - /* options->ciphers, default set in myproposals.h */ - /* options->macs, default set in myproposals.h */ - /* options->kex_algorithms, default set in myproposals.h */ /* options->hostkeyalgorithms, default set in myproposals.h */ if (options->protocol == SSH_PROTO_UNKNOWN) options->protocol = SSH_PROTO_2; @@ -1784,6 +1897,19 @@ fill_default_options(Options * options) options->canonicalize_fallback_local = 1; if (options->canonicalize_hostname == -1) options->canonicalize_hostname = SSH_CANONICALISE_NO; + if (options->fingerprint_hash == -1) + options->fingerprint_hash = SSH_FP_HASH_DEFAULT; + if (options->update_hostkeys == -1) + options->update_hostkeys = 0; + if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || + kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 || + kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 || + kex_assemble_names(KEX_DEFAULT_PK_ALG, + &options->hostbased_key_types) != 0 || + kex_assemble_names(KEX_DEFAULT_PK_ALG, + &options->pubkey_key_types) != 0) + fatal("%s: kex_assemble_names failed", __func__); + #define CLEAR_ON_NONE(v) \ do { \ if (option_clear_or_none(v)) { \ @@ -1794,6 +1920,7 @@ fill_default_options(Options * options) CLEAR_ON_NONE(options->local_command); CLEAR_ON_NONE(options->proxy_command); CLEAR_ON_NONE(options->control_path); + CLEAR_ON_NONE(options->revoked_host_keys); /* options->user will be set in the main program if appropriate */ /* options->hostname will be set in the main program if appropriate */ /* options->host_key_alias should not be set by default */ @@ -1802,22 +1929,93 @@ fill_default_options(Options * options) options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); } +struct fwdarg { + char *arg; + int ispath; +}; + +/* + * parse_fwd_field + * parses the next field in a port forwarding specification. + * sets fwd to the parsed field and advances p past the colon + * or sets it to NULL at end of string. + * returns 0 on success, else non-zero. + */ +static int +parse_fwd_field(char **p, struct fwdarg *fwd) +{ + char *ep, *cp = *p; + int ispath = 0; + + if (*cp == '\0') { + *p = NULL; + return -1; /* end of string */ + } + + /* + * A field escaped with square brackets is used literally. + * XXX - allow ']' to be escaped via backslash? + */ + if (*cp == '[') { + /* find matching ']' */ + for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { + if (*ep == '/') + ispath = 1; + } + /* no matching ']' or not at end of field. */ + if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) + return -1; + /* NUL terminate the field and advance p past the colon */ + *ep++ = '\0'; + if (*ep != '\0') + *ep++ = '\0'; + fwd->arg = cp + 1; + fwd->ispath = ispath; + *p = ep; + return 0; + } + + for (cp = *p; *cp != '\0'; cp++) { + switch (*cp) { + case '\\': + memmove(cp, cp + 1, strlen(cp + 1) + 1); + if (*cp == '\0') + return -1; + break; + case '/': + ispath = 1; + break; + case ':': + *cp++ = '\0'; + goto done; + } + } +done: + fwd->arg = *p; + fwd->ispath = ispath; + *p = cp; + return 0; +} + /* * parse_forward * parses a string containing a port forwarding specification of the form: * dynamicfwd == 0 - * [listenhost:]listenport:connecthost:connectport + * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath + * listenpath:connectpath * dynamicfwd == 1 * [listenhost:]listenport * returns number of arguments parsed or zero on error */ int -parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) +parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) { + struct fwdarg fwdargs[4]; + char *p, *cp; int i; - char *p, *cp, *fwdarg[4]; - memset(fwd, '\0', sizeof(*fwd)); + memset(fwd, 0, sizeof(*fwd)); + memset(fwdargs, 0, sizeof(fwdargs)); cp = p = xstrdup(fwdspec); @@ -1825,39 +2023,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) while (isspace((u_char)*cp)) cp++; - for (i = 0; i < 4; ++i) - if ((fwdarg[i] = hpdelim(&cp)) == NULL) + for (i = 0; i < 4; ++i) { + if (parse_fwd_field(&cp, &fwdargs[i]) != 0) break; + } /* Check for trailing garbage */ - if (cp != NULL) + if (cp != NULL && *cp != '\0') { i = 0; /* failure */ + } switch (i) { case 1: - fwd->listen_host = NULL; - fwd->listen_port = a2port(fwdarg[0]); + if (fwdargs[0].ispath) { + fwd->listen_path = xstrdup(fwdargs[0].arg); + fwd->listen_port = PORT_STREAMLOCAL; + } else { + fwd->listen_host = NULL; + fwd->listen_port = a2port(fwdargs[0].arg); + } fwd->connect_host = xstrdup("socks"); break; case 2: - fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); - fwd->listen_port = a2port(fwdarg[1]); - fwd->connect_host = xstrdup("socks"); + if (fwdargs[0].ispath && fwdargs[1].ispath) { + fwd->listen_path = xstrdup(fwdargs[0].arg); + fwd->listen_port = PORT_STREAMLOCAL; + fwd->connect_path = xstrdup(fwdargs[1].arg); + fwd->connect_port = PORT_STREAMLOCAL; + } else if (fwdargs[1].ispath) { + fwd->listen_host = NULL; + fwd->listen_port = a2port(fwdargs[0].arg); + fwd->connect_path = xstrdup(fwdargs[1].arg); + fwd->connect_port = PORT_STREAMLOCAL; + } else { + fwd->listen_host = xstrdup(fwdargs[0].arg); + fwd->listen_port = a2port(fwdargs[1].arg); + fwd->connect_host = xstrdup("socks"); + } break; case 3: - fwd->listen_host = NULL; - fwd->listen_port = a2port(fwdarg[0]); - fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); - fwd->connect_port = a2port(fwdarg[2]); + if (fwdargs[0].ispath) { + fwd->listen_path = xstrdup(fwdargs[0].arg); + fwd->listen_port = PORT_STREAMLOCAL; + fwd->connect_host = xstrdup(fwdargs[1].arg); + fwd->connect_port = a2port(fwdargs[2].arg); + } else if (fwdargs[2].ispath) { + fwd->listen_host = xstrdup(fwdargs[0].arg); + fwd->listen_port = a2port(fwdargs[1].arg); + fwd->connect_path = xstrdup(fwdargs[2].arg); + fwd->connect_port = PORT_STREAMLOCAL; + } else { + fwd->listen_host = NULL; + fwd->listen_port = a2port(fwdargs[0].arg); + fwd->connect_host = xstrdup(fwdargs[1].arg); + fwd->connect_port = a2port(fwdargs[2].arg); + } break; case 4: - fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); - fwd->listen_port = a2port(fwdarg[1]); - fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); - fwd->connect_port = a2port(fwdarg[3]); + fwd->listen_host = xstrdup(fwdargs[0].arg); + fwd->listen_port = a2port(fwdargs[1].arg); + fwd->connect_host = xstrdup(fwdargs[2].arg); + fwd->connect_port = a2port(fwdargs[3].arg); break; default: i = 0; /* failure */ @@ -1869,29 +2098,342 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) if (!(i == 1 || i == 2)) goto fail_free; } else { - if (!(i == 3 || i == 4)) - goto fail_free; - if (fwd->connect_port <= 0) + if (!(i == 3 || i == 4)) { + if (fwd->connect_path == NULL && + fwd->listen_path == NULL) + goto fail_free; + } + if (fwd->connect_port <= 0 && fwd->connect_path == NULL) goto fail_free; } - if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) + if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || + (!remotefwd && fwd->listen_port == 0)) goto fail_free; - if (fwd->connect_host != NULL && strlen(fwd->connect_host) >= NI_MAXHOST) goto fail_free; + /* XXX - if connecting to a remote socket, max sun len may not match this host */ + if (fwd->connect_path != NULL && + strlen(fwd->connect_path) >= PATH_MAX_SUN) + goto fail_free; if (fwd->listen_host != NULL && strlen(fwd->listen_host) >= NI_MAXHOST) goto fail_free; - + if (fwd->listen_path != NULL && + strlen(fwd->listen_path) >= PATH_MAX_SUN) + goto fail_free; return (i); fail_free: free(fwd->connect_host); fwd->connect_host = NULL; + free(fwd->connect_path); + fwd->connect_path = NULL; free(fwd->listen_host); fwd->listen_host = NULL; + free(fwd->listen_path); + fwd->listen_path = NULL; return (0); } + +/* XXX the following is a near-vebatim copy from servconf.c; refactor */ +static const char * +fmt_multistate_int(int val, const struct multistate *m) +{ + u_int i; + + for (i = 0; m[i].key != NULL; i++) { + if (m[i].value == val) + return m[i].key; + } + return "UNKNOWN"; +} + +static const char * +fmt_intarg(OpCodes code, int val) +{ + if (val == -1) + return "unset"; + switch (code) { + case oAddressFamily: + return fmt_multistate_int(val, multistate_addressfamily); + case oVerifyHostKeyDNS: + case oStrictHostKeyChecking: + case oUpdateHostkeys: + return fmt_multistate_int(val, multistate_yesnoask); + case oControlMaster: + return fmt_multistate_int(val, multistate_controlmaster); + case oTunnel: + return fmt_multistate_int(val, multistate_tunnel); + case oRequestTTY: + return fmt_multistate_int(val, multistate_requesttty); + case oCanonicalizeHostname: + return fmt_multistate_int(val, multistate_canonicalizehostname); + case oFingerprintHash: + return ssh_digest_alg_name(val); + case oProtocol: + switch (val) { + case SSH_PROTO_1: + return "1"; + case SSH_PROTO_2: + return "2"; + case (SSH_PROTO_1|SSH_PROTO_2): + return "2,1"; + default: + return "UNKNOWN"; + } + default: + switch (val) { + case 0: + return "no"; + case 1: + return "yes"; + default: + return "UNKNOWN"; + } + } +} + +static const char * +lookup_opcode_name(OpCodes code) +{ + u_int i; + + for (i = 0; keywords[i].name != NULL; i++) + if (keywords[i].opcode == code) + return(keywords[i].name); + return "UNKNOWN"; +} + +static void +dump_cfg_int(OpCodes code, int val) +{ + printf("%s %d\n", lookup_opcode_name(code), val); +} + +static void +dump_cfg_fmtint(OpCodes code, int val) +{ + printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); +} + +static void +dump_cfg_string(OpCodes code, const char *val) +{ + if (val == NULL) + return; + printf("%s %s\n", lookup_opcode_name(code), val); +} + +static void +dump_cfg_strarray(OpCodes code, u_int count, char **vals) +{ + u_int i; + + for (i = 0; i < count; i++) + printf("%s %s\n", lookup_opcode_name(code), vals[i]); +} + +static void +dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) +{ + u_int i; + + printf("%s", lookup_opcode_name(code)); + for (i = 0; i < count; i++) + printf(" %s", vals[i]); + printf("\n"); +} + +static void +dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) +{ + const struct Forward *fwd; + u_int i; + + /* oDynamicForward */ + for (i = 0; i < count; i++) { + fwd = &fwds[i]; + if (code == oDynamicForward && + strcmp(fwd->connect_host, "socks") != 0) + continue; + if (code == oLocalForward && + strcmp(fwd->connect_host, "socks") == 0) + continue; + printf("%s", lookup_opcode_name(code)); + if (fwd->listen_port == PORT_STREAMLOCAL) + printf(" %s", fwd->listen_path); + else if (fwd->listen_host == NULL) + printf(" %d", fwd->listen_port); + else { + printf(" [%s]:%d", + fwd->listen_host, fwd->listen_port); + } + if (code != oDynamicForward) { + if (fwd->connect_port == PORT_STREAMLOCAL) + printf(" %s", fwd->connect_path); + else if (fwd->connect_host == NULL) + printf(" %d", fwd->connect_port); + else { + printf(" [%s]:%d", + fwd->connect_host, fwd->connect_port); + } + } + printf("\n"); + } +} + +void +dump_client_config(Options *o, const char *host) +{ + int i; + char vbuf[5]; + + /* Most interesting options first: user, host, port */ + dump_cfg_string(oUser, o->user); + dump_cfg_string(oHostName, host); + dump_cfg_int(oPort, o->port); + + /* Flag options */ + dump_cfg_fmtint(oAddressFamily, o->address_family); + dump_cfg_fmtint(oBatchMode, o->batch_mode); + dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); + dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); + dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication); + dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); + dump_cfg_fmtint(oCompression, o->compression); + dump_cfg_fmtint(oControlMaster, o->control_master); + dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); + dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); + dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); + dump_cfg_fmtint(oForwardAgent, o->forward_agent); + dump_cfg_fmtint(oForwardX11, o->forward_x11); + dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); + dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); +#ifdef GSSAPI + dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); + dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); +#endif /* GSSAPI */ + dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); + dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); + dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); + dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); + dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); + dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); + dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); + dump_cfg_fmtint(oProtocol, o->protocol); + dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); + dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); + dump_cfg_fmtint(oRequestTTY, o->request_tty); + dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication); + dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication); + dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); + dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); + dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); + dump_cfg_fmtint(oTunnel, o->tun_open); + dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port); + dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); + dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); + dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); + + /* Integer options */ + dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); + dump_cfg_int(oCompressionLevel, o->compression_level); + dump_cfg_int(oConnectionAttempts, o->connection_attempts); + dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); + dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); + dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); + dump_cfg_int(oServerAliveInterval, o->server_alive_interval); + + /* String options */ + dump_cfg_string(oBindAddress, o->bind_address); + dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT); + dump_cfg_string(oControlPath, o->control_path); + dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG); + dump_cfg_string(oHostKeyAlias, o->host_key_alias); + dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types); + dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); + dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); + dump_cfg_string(oLocalCommand, o->local_command); + dump_cfg_string(oLogLevel, log_level_name(o->log_level)); + dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); + dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); + dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); + dump_cfg_string(oProxyCommand, o->proxy_command); + dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); + dump_cfg_string(oXAuthLocation, o->xauth_location); + + /* Forwards */ + dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); + dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); + dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); + + /* String array options */ + dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); + dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); + dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); + dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); + dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); + + /* Special cases */ + + /* oConnectTimeout */ + if (o->connection_timeout == -1) + printf("connecttimeout none\n"); + else + dump_cfg_int(oConnectTimeout, o->connection_timeout); + + /* oTunnelDevice */ + printf("tunneldevice"); + if (o->tun_local == SSH_TUNID_ANY) + printf(" any"); + else + printf(" %d", o->tun_local); + if (o->tun_remote == SSH_TUNID_ANY) + printf(":any"); + else + printf(":%d", o->tun_remote); + printf("\n"); + + /* oCanonicalizePermittedCNAMEs */ + if ( o->num_permitted_cnames > 0) { + printf("canonicalizePermittedcnames"); + for (i = 0; i < o->num_permitted_cnames; i++) { + printf(" %s:%s", o->permitted_cnames[i].source_list, + o->permitted_cnames[i].target_list); + } + printf("\n"); + } + + /* oCipher */ + if (o->cipher != SSH_CIPHER_NOT_SET) + printf("Cipher %s\n", cipher_name(o->cipher)); + + /* oControlPersist */ + if (o->control_persist == 0 || o->control_persist_timeout == 0) + dump_cfg_fmtint(oControlPersist, o->control_persist); + else + dump_cfg_int(oControlPersist, o->control_persist_timeout); + + /* oEscapeChar */ + if (o->escape_char == SSH_ESCAPECHAR_NONE) + printf("escapechar none\n"); + else { + vis(vbuf, o->escape_char, VIS_WHITE, 0); + printf("escapechar %s\n", vbuf); + } + + /* oIPQoS */ + printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); + printf("%s\n", iptos2str(o->ip_qos_bulk)); + + /* oRekeyLimit */ + printf("rekeylimit %lld %d\n", + (long long)o->rekey_limit, o->rekey_interval); + + /* oStreamLocalBindMask */ + printf("streamlocalbindmask 0%o\n", + o->fwd_opts.streamlocal_bind_mask); +} diff --git a/crypto/openssh/readconf.h b/crypto/openssh/readconf.h index 8ce8fec..3360667 100644 --- a/crypto/openssh/readconf.h +++ b/crypto/openssh/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.101 2014/02/23 20:11:36 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.110 2015/07/10 06:21:53 markus Exp $ */ /* $FreeBSD$ */ /* @@ -17,21 +17,12 @@ #ifndef READCONF_H #define READCONF_H -/* Data structure for representing a forwarding request. */ - -typedef struct { - char *listen_host; /* Host (address) to listen on. */ - int listen_port; /* Port to forward. */ - char *connect_host; /* Host to connect. */ - int connect_port; /* Port to connect on connect_host. */ - int allocated_port; /* Dynamically allocated listen port */ - int handle; /* Handle for dynamic listen ports */ -} Forward; /* Data structure for representing option data. */ #define MAX_SEND_ENV 256 #define SSH_MAX_HOSTS_FILES 32 #define MAX_CANON_DOMAINS 32 +#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path) struct allowed_cname { char *source_list; @@ -45,7 +36,7 @@ typedef struct { int forward_x11_trusted; /* Trust Forward X11 display. */ int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ char *xauth_location; /* Location for xauth program */ - int gateway_ports; /* Allow remote connects to forwarded ports. */ + struct ForwardOptions fwd_opts; /* forwarding options */ int use_privileged_port; /* Don't use privileged port if false. */ int rhosts_rsa_authentication; /* Try rhosts with RSA * authentication. */ @@ -103,15 +94,15 @@ typedef struct { int num_identity_files; /* Number of files for RSA/DSA identities. */ char *identity_files[SSH_MAX_IDENTITY_FILES]; int identity_file_userprovided[SSH_MAX_IDENTITY_FILES]; - Key *identity_keys[SSH_MAX_IDENTITY_FILES]; + struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES]; /* Local TCP/IP forward requests. */ int num_local_forwards; - Forward *local_forwards; + struct Forward *local_forwards; /* Remote TCP/IP forward requests. */ int num_remote_forwards; - Forward *remote_forwards; + struct Forward *remote_forwards; int clear_forwardings; int enable_ssh_keysign; @@ -154,7 +145,16 @@ typedef struct { int num_permitted_cnames; struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS]; - char *version_addendum; /* Appended to SSH banner */ + char *revoked_host_keys; + + int fingerprint_hash; + + int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */ + + char *hostbased_key_types; + char *pubkey_key_types; + + char *version_addendum; /* Appended to SSH banner */ char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ } Options; @@ -176,20 +176,26 @@ typedef struct { #define SSHCONF_CHECKPERM 1 /* check permissions on config file */ #define SSHCONF_USERCONF 2 /* user provided config file not system */ +#define SSHCONF_POSTCANON 4 /* After hostname canonicalisation */ + +#define SSH_UPDATE_HOSTKEYS_NO 0 +#define SSH_UPDATE_HOSTKEYS_YES 1 +#define SSH_UPDATE_HOSTKEYS_ASK 2 void initialize_options(Options *); void fill_default_options(Options *); void fill_default_options_for_canonicalization(Options *); -int process_config_line(Options *, struct passwd *, const char *, char *, - const char *, int, int *, int); +int process_config_line(Options *, struct passwd *, const char *, + const char *, char *, const char *, int, int *, int); int read_config_file(const char *, struct passwd *, const char *, - Options *, int); -int parse_forward(Forward *, const char *, int, int); + const char *, Options *, int); +int parse_forward(struct Forward *, const char *, int, int); int default_ssh_port(void); int option_clear_or_none(const char *); +void dump_client_config(Options *o, const char *host); -void add_local_forward(Options *, const Forward *); -void add_remote_forward(Options *, const Forward *); +void add_local_forward(Options *, const struct Forward *); +void add_remote_forward(Options *, const struct Forward *); void add_identity_file(Options *, const char *, const char *, int); #endif /* READCONF_H */ diff --git a/crypto/openssh/regress/.cvsignore b/crypto/openssh/regress/.cvsignore new file mode 100644 index 0000000..3fd25b0 --- /dev/null +++ b/crypto/openssh/regress/.cvsignore @@ -0,0 +1,31 @@ +*-agent +*.copy +*.log +*.prv +*.pub +actual +authorized_keys_* +batch +copy.dd* +data +expect +host.rsa* +key.* +known_hosts +krl-* +modpipe +remote_pid +revoked-* +revoked-ca +revoked-keyid +revoked-serials +rsa +rsa1 +sftp-server.sh +ssh-log-wrapper.sh +ssh_config +ssh_proxy* +sshd_config +sshd_proxy* +t*.out +t*.out[0-9] diff --git a/crypto/openssh/regress/Makefile b/crypto/openssh/regress/Makefile index 6e3b8d6..cba83f4 100644 --- a/crypto/openssh/regress/Makefile +++ b/crypto/openssh/regress/Makefile @@ -1,11 +1,14 @@ -# $OpenBSD: Makefile,v 1.68 2014/01/25 04:35:32 dtucker Exp $ +# $OpenBSD: Makefile,v 1.81 2015/05/21 06:44:25 djm Exp $ -REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t-exec -tests: $(REGRESS_TARGETS) +REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec +tests: prep $(REGRESS_TARGETS) # Interop tests are not run by default interop interop-tests: t-exec-interop +prep: + test "x${USE_VALGRIND}" = "x" || mkdir -p $(OBJ)/valgrind-out + clean: for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done test -z "${SUDO}" || ${SUDO} rm -f ${SUDO_CLEAN} @@ -51,6 +54,7 @@ LTESTS= connect \ multiplex \ reexec \ brokenkeys \ + cfgparse \ cfgmatch \ addrmatch \ localcommand \ @@ -64,7 +68,15 @@ LTESTS= connect \ keys-command \ forward-control \ integrity \ - krl + krl \ + multipubkey \ + limit-keytype \ + hostkey-agent \ + keygen-knownhosts \ + hostkey-rotate \ + principals-command + + # dhgex \ INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers @@ -75,6 +87,7 @@ INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers USER!= id -un CLEANFILES= t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \ t8.out t8.out.pub t9.out t9.out.pub t10.out t10.out.pub \ + t12.out t12.out.pub \ authorized_keys_${USER} known_hosts pidfile testdata \ ssh_config sshd_config.orig ssh_proxy sshd_config sshd_proxy \ rsa.pub rsa rsa1.pub rsa1 host.rsa host.rsa1 \ @@ -91,7 +104,8 @@ CLEANFILES= t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \ regress.log failed-regress.log ssh-log-wrapper.sh \ sftp-server.sh sftp-server.log sftp.log setuid-allowed \ data ed25519-agent ed25519-agent.pub key.ed25519-512 \ - key.ed25519-512.pub + key.ed25519-512.pub netcat host_krl_* host_revoked_* \ + kh.* user_*key* agent-key.* known_hosts.* hkr.* SUDO_CLEAN+= /var/run/testdata_${USER} /var/run/keycommand_${USER} @@ -119,7 +133,7 @@ t3: ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub t4: - ${TEST_SSH_SSHKEYGEN} -lf ${.CURDIR}/rsa_openssh.pub |\ + ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t4.ok t5: @@ -164,6 +178,16 @@ t10: $(OBJ)/t10.out ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t10.out > /dev/null ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null +t11: + ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\ + awk '{print $$2}' | diff - ${.CURDIR}/t11.ok + +$(OBJ)/t12.out: + ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $@ + +t12: $(OBJ)/t12.out + ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t12.out.pub | grep test-comment-1234 >/dev/null + t-exec: ${LTESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ for TEST in ""$?; do \ @@ -180,3 +204,18 @@ t-exec-interop: ${INTEROP_TESTS:=.sh} # Not run by default interop: ${INTEROP_TARGETS} + +# Unit tests, built by top-level Makefile +unit: + set -e ; if test -z "${SKIP_UNIT}" ; then \ + V="" ; \ + test "x${USE_VALGRIND}" = "x" || \ + V=${.CURDIR}/valgrind-unit.sh ; \ + $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ + $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ + -d ${.CURDIR}/unittests/sshkey/testdata ; \ + $$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \ + $$V ${.OBJDIR}/unittests/kex/test_kex ; \ + $$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \ + -d ${.CURDIR}/unittests/hostkeys/testdata ; \ + fi diff --git a/crypto/openssh/regress/README.regress b/crypto/openssh/regress/README.regress index 82e4cc7..9b99bda 100644 --- a/crypto/openssh/regress/README.regress +++ b/crypto/openssh/regress/README.regress @@ -31,7 +31,7 @@ TEST_SHELL: shell used for running the test scripts. TEST_SSH_PORT: TCP port to be used for the listening tests. TEST_SSH_SSH_CONFOPTS: Configuration directives to be added to ssh_config before running each test. -TEST_SSH_SSHD_CONFOTPS: Configuration directives to be added to sshd_config +TEST_SSH_SSHD_CONFOPTS: Configuration directives to be added to sshd_config before running each test. diff --git a/crypto/openssh/regress/agent-pkcs11.sh b/crypto/openssh/regress/agent-pkcs11.sh index db33ab3..3aa20c8 100755 --- a/crypto/openssh/regress/agent-pkcs11.sh +++ b/crypto/openssh/regress/agent-pkcs11.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent-pkcs11.sh,v 1.1 2010/02/08 10:52:47 markus Exp $ +# $OpenBSD: agent-pkcs11.sh,v 1.2 2015/01/12 11:46:32 djm Exp $ # Placed in the Public Domain. tid="pkcs11 agent test" @@ -6,6 +6,8 @@ tid="pkcs11 agent test" TEST_SSH_PIN="" TEST_SSH_PKCS11=/usr/local/lib/soft-pkcs11.so.0.0 +test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist" + # setup environment for soft-pkcs11 token SOFTPKCS11RC=$OBJ/pkcs11.info export SOFTPKCS11RC diff --git a/crypto/openssh/regress/agent-timeout.sh b/crypto/openssh/regress/agent-timeout.sh index 6882659..9598c20 100644 --- a/crypto/openssh/regress/agent-timeout.sh +++ b/crypto/openssh/regress/agent-timeout.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent-timeout.sh,v 1.2 2013/05/17 01:16:09 dtucker Exp $ +# $OpenBSD: agent-timeout.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="agent timeout test" @@ -12,7 +12,7 @@ if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" else trace "add keys with timeout" - for t in rsa rsa1; do + for t in ${SSH_KEYTYPES}; do ${SSHADD} -t ${SSHAGENT_TIMEOUT} $OBJ/$t > /dev/null 2>&1 if [ $? -ne 0 ]; then fail "ssh-add did succeed exit code 0" diff --git a/crypto/openssh/regress/agent.sh b/crypto/openssh/regress/agent.sh index caad3c8..c5e2794 100644 --- a/crypto/openssh/regress/agent.sh +++ b/crypto/openssh/regress/agent.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent.sh,v 1.10 2014/02/27 21:21:25 djm Exp $ +# $OpenBSD: agent.sh,v 1.11 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="simple agent test" @@ -20,7 +20,7 @@ else fi trace "overwrite authorized keys" printf '' > $OBJ/authorized_keys_$USER - for t in ed25519 rsa rsa1; do + for t in ${SSH_KEYTYPES}; do # generate user key for agent rm -f $OBJ/$t-agent ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t-agent ||\ @@ -46,7 +46,7 @@ else fi trace "simple connect via agent" - for p in 1 2; do + for p in ${SSH_PROTOCOLS}; do ${SSH} -$p -F $OBJ/ssh_proxy somehost exit 5$p r=$? if [ $r -ne 5$p ]; then @@ -55,7 +55,7 @@ else done trace "agent forwarding" - for p in 1 2; do + for p in ${SSH_PROTOCOLS}; do ${SSH} -A -$p -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then diff --git a/crypto/openssh/regress/broken-pipe.sh b/crypto/openssh/regress/broken-pipe.sh index c08c849..a416f7a 100644 --- a/crypto/openssh/regress/broken-pipe.sh +++ b/crypto/openssh/regress/broken-pipe.sh @@ -1,9 +1,9 @@ -# $OpenBSD: broken-pipe.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ +# $OpenBSD: broken-pipe.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="broken pipe test" -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "protocol $p" for i in 1 2 3 4; do ${SSH} -$p -F $OBJ/ssh_config_config nexthost echo $i 2> /dev/null | true diff --git a/crypto/openssh/regress/cert-hostkey.sh b/crypto/openssh/regress/cert-hostkey.sh index 1d9e0ed..3f53922 100755 --- a/crypto/openssh/regress/cert-hostkey.sh +++ b/crypto/openssh/regress/cert-hostkey.sh @@ -1,55 +1,106 @@ -# $OpenBSD: cert-hostkey.sh,v 1.9 2014/01/26 10:22:10 djm Exp $ +# $OpenBSD: cert-hostkey.sh,v 1.13 2015/07/10 06:23:25 markus Exp $ # Placed in the Public Domain. tid="certified host keys" -rm -f $OBJ/known_hosts-cert $OBJ/host_ca_key* $OBJ/cert_host_key* +rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/host_revoked_* +rm -f $OBJ/cert_host_key* $OBJ/host_krl_* + +# Allow all hostkey/pubkey types, prefer certs for the client +types="" +for i in `$SSH -Q key`; do + if [ -z "$types" ]; then + types="$i" + continue + fi + case "$i" in + *cert*) types="$i,$types";; + *) types="$types,$i";; + esac +done +( + echo "HostKeyAlgorithms ${types}" + echo "PubkeyAcceptedKeyTypes *" +) >> $OBJ/ssh_proxy cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak +( + echo "HostKeyAlgorithms *" + echo "PubkeyAcceptedKeyTypes *" +) >> $OBJ/sshd_proxy_bak HOSTS='localhost-with-alias,127.0.0.1,::1' -# Create a CA key and add it to known hosts -${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/host_ca_key ||\ +# Create a CA key and add it to known hosts. Ed25519 chosed for speed. +${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/host_ca_key ||\ fail "ssh-keygen of host_ca_key failed" ( printf '@cert-authority ' printf "$HOSTS " cat $OBJ/host_ca_key.pub -) > $OBJ/known_hosts-cert +) > $OBJ/known_hosts-cert.orig +cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert + +# Plain text revocation files +touch $OBJ/host_revoked_empty +touch $OBJ/host_revoked_plain +touch $OBJ/host_revoked_cert +cp $OBJ/host_ca_key.pub $OBJ/host_revoked_ca PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` -type_has_legacy() { - case $1 in - ed25519*|ecdsa*) return 1 ;; - esac - return 0 -} +# Prepare certificate, plain key and CA KRLs +${SSHKEYGEN} -kf $OBJ/host_krl_empty || fatal "KRL init failed" +${SSHKEYGEN} -kf $OBJ/host_krl_plain || fatal "KRL init failed" +${SSHKEYGEN} -kf $OBJ/host_krl_cert || fatal "KRL init failed" +${SSHKEYGEN} -kf $OBJ/host_krl_ca $OBJ/host_ca_key.pub \ + || fatal "KRL init failed" # Generate and sign host keys +serial=1 for ktype in $PLAIN_TYPES ; do verbose "$tid: sign host ${ktype} cert" # Generate and sign a host key ${SSHKEYGEN} -q -N '' -t ${ktype} \ -f $OBJ/cert_host_key_${ktype} || \ - fail "ssh-keygen of cert_host_key_${ktype} failed" - ${SSHKEYGEN} -h -q -s $OBJ/host_ca_key \ + fatal "ssh-keygen of cert_host_key_${ktype} failed" + ${SSHKEYGEN} -ukf $OBJ/host_krl_plain \ + $OBJ/cert_host_key_${ktype}.pub || fatal "KRL update failed" + cat $OBJ/cert_host_key_${ktype}.pub >> $OBJ/host_revoked_plain + ${SSHKEYGEN} -h -q -s $OBJ/host_ca_key -z $serial \ -I "regress host key for $USER" \ -n $HOSTS $OBJ/cert_host_key_${ktype} || - fail "couldn't sign cert_host_key_${ktype}" - type_has_legacy $ktype || continue - cp $OBJ/cert_host_key_${ktype} $OBJ/cert_host_key_${ktype}_v00 - cp $OBJ/cert_host_key_${ktype}.pub $OBJ/cert_host_key_${ktype}_v00.pub - verbose "$tid: sign host ${ktype}_v00 cert" - ${SSHKEYGEN} -t v00 -h -q -s $OBJ/host_ca_key \ - -I "regress host key for $USER" \ - -n $HOSTS $OBJ/cert_host_key_${ktype}_v00 || - fail "couldn't sign cert_host_key_${ktype}_v00" + fatal "couldn't sign cert_host_key_${ktype}" + ${SSHKEYGEN} -ukf $OBJ/host_krl_cert \ + $OBJ/cert_host_key_${ktype}-cert.pub || \ + fatal "KRL update failed" + cat $OBJ/cert_host_key_${ktype}-cert.pub >> $OBJ/host_revoked_cert + serial=`expr $serial + 1` done -# Basic connect tests +attempt_connect() { + _ident="$1" + _expect_success="$2" + shift; shift + verbose "$tid: $_ident expect success $_expect_success" + cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert + ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ + "$@" -F $OBJ/ssh_proxy somehost true + _r=$? + if [ "x$_expect_success" = "xyes" ] ; then + if [ $_r -ne 0 ]; then + fail "ssh cert connect $_ident failed" + fi + else + if [ $_r -eq 0 ]; then + fail "ssh cert connect $_ident succeeded unexpectedly" + fi + fi +} + +# Basic connect and revocation tests. for privsep in yes no ; do - for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do + for ktype in $PLAIN_TYPES ; do verbose "$tid: host ${ktype} cert connect privsep $privsep" ( cat $OBJ/sshd_proxy_bak @@ -58,12 +109,24 @@ for privsep in yes no ; do echo UsePrivilegeSeparation $privsep ) > $OBJ/sshd_proxy - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ - -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ - -F $OBJ/ssh_proxy somehost true - if [ $? -ne 0 ]; then - fail "ssh cert connect failed" - fi + # test name expect success + attempt_connect "$ktype basic connect" "yes" + attempt_connect "$ktype empty KRL" "yes" \ + -oRevokedHostKeys=$OBJ/host_krl_empty + attempt_connect "$ktype KRL w/ plain key revoked" "no" \ + -oRevokedHostKeys=$OBJ/host_krl_plain + attempt_connect "$ktype KRL w/ cert revoked" "no" \ + -oRevokedHostKeys=$OBJ/host_krl_cert + attempt_connect "$ktype KRL w/ CA revoked" "no" \ + -oRevokedHostKeys=$OBJ/host_krl_ca + attempt_connect "$ktype empty plaintext revocation" "yes" \ + -oRevokedHostKeys=$OBJ/host_revoked_empty + attempt_connect "$ktype plain key plaintext revocation" "no" \ + -oRevokedHostKeys=$OBJ/host_revoked_plain + attempt_connect "$ktype cert plaintext revocation" "no" \ + -oRevokedHostKeys=$OBJ/host_revoked_cert + attempt_connect "$ktype CA plaintext revocation" "no" \ + -oRevokedHostKeys=$OBJ/host_revoked_ca done done @@ -72,13 +135,14 @@ done printf '@cert-authority ' printf "$HOSTS " cat $OBJ/host_ca_key.pub - for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do + for ktype in $PLAIN_TYPES ; do test -f "$OBJ/cert_host_key_${ktype}.pub" || fatal "no pubkey" printf "@revoked * `cat $OBJ/cert_host_key_${ktype}.pub`\n" done -) > $OBJ/known_hosts-cert +) > $OBJ/known_hosts-cert.orig +cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert for privsep in yes no ; do - for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do + for ktype in $PLAIN_TYPES ; do verbose "$tid: host ${ktype} revoked cert privsep $privsep" ( cat $OBJ/sshd_proxy_bak @@ -87,6 +151,7 @@ for privsep in yes no ; do echo UsePrivilegeSeparation $privsep ) > $OBJ/sshd_proxy + cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 @@ -104,14 +169,16 @@ done printf '@revoked ' printf "* " cat $OBJ/host_ca_key.pub -) > $OBJ/known_hosts-cert -for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do +) > $OBJ/known_hosts-cert.orig +cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert +for ktype in $PLAIN_TYPES ; do verbose "$tid: host ${ktype} revoked cert" ( cat $OBJ/sshd_proxy_bak echo HostKey $OBJ/cert_host_key_${ktype} echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub ) > $OBJ/sshd_proxy + cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 @@ -125,24 +192,18 @@ done printf '@cert-authority ' printf "$HOSTS " cat $OBJ/host_ca_key.pub -) > $OBJ/known_hosts-cert +) > $OBJ/known_hosts-cert.orig +cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert test_one() { ident=$1 result=$2 sign_opts=$3 - for kt in rsa rsa_v00 ; do - case $kt in - *_v00) args="-t v00" ;; - *) args="" ;; - esac - - verbose "$tid: host cert connect $ident $kt expect $result" + for kt in rsa ed25519 ; do ${SSHKEYGEN} -q -s $OBJ/host_ca_key \ -I "regress host key for $USER" \ - $sign_opts $args \ - $OBJ/cert_host_key_${kt} || + $sign_opts $OBJ/cert_host_key_${kt} || fail "couldn't sign cert_host_key_${kt}" ( cat $OBJ/sshd_proxy_bak @@ -150,6 +211,7 @@ test_one() { echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub ) > $OBJ/sshd_proxy + cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 @@ -175,36 +237,33 @@ test_one "cert valid interval" success "-h -V-1w:+2w" test_one "cert has constraints" failure "-h -Oforce-command=false" # Check downgrade of cert to raw key when no CA found -for v in v01 v00 ; do - for ktype in $PLAIN_TYPES ; do - type_has_legacy $ktype || continue - rm -f $OBJ/known_hosts-cert $OBJ/cert_host_key* - verbose "$tid: host ${ktype} ${v} cert downgrade to raw key" - # Generate and sign a host key - ${SSHKEYGEN} -q -N '' -t ${ktype} \ - -f $OBJ/cert_host_key_${ktype} || \ - fail "ssh-keygen of cert_host_key_${ktype} failed" - ${SSHKEYGEN} -t ${v} -h -q -s $OBJ/host_ca_key \ - -I "regress host key for $USER" \ - -n $HOSTS $OBJ/cert_host_key_${ktype} || - fail "couldn't sign cert_host_key_${ktype}" - ( - printf "$HOSTS " - cat $OBJ/cert_host_key_${ktype}.pub - ) > $OBJ/known_hosts-cert - ( - cat $OBJ/sshd_proxy_bak - echo HostKey $OBJ/cert_host_key_${ktype} - echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub - ) > $OBJ/sshd_proxy - - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ - -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ - -F $OBJ/ssh_proxy somehost true - if [ $? -ne 0 ]; then - fail "ssh cert connect failed" - fi - done +for ktype in $PLAIN_TYPES ; do + rm -f $OBJ/known_hosts-cert $OBJ/cert_host_key* + verbose "$tid: host ${ktype} ${v} cert downgrade to raw key" + # Generate and sign a host key + ${SSHKEYGEN} -q -N '' -t ${ktype} \ + -f $OBJ/cert_host_key_${ktype} || \ + fail "ssh-keygen of cert_host_key_${ktype} failed" + ${SSHKEYGEN} -t ${v} -h -q -s $OBJ/host_ca_key \ + -I "regress host key for $USER" \ + -n $HOSTS $OBJ/cert_host_key_${ktype} || + fail "couldn't sign cert_host_key_${ktype}" + ( + printf "$HOSTS " + cat $OBJ/cert_host_key_${ktype}.pub + ) > $OBJ/known_hosts-cert + ( + cat $OBJ/sshd_proxy_bak + echo HostKey $OBJ/cert_host_key_${ktype} + echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub + ) > $OBJ/sshd_proxy + + ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ + -F $OBJ/ssh_proxy somehost true + if [ $? -ne 0 ]; then + fail "ssh cert connect failed" + fi done # Wrong certificate @@ -212,33 +271,32 @@ done printf '@cert-authority ' printf "$HOSTS " cat $OBJ/host_ca_key.pub -) > $OBJ/known_hosts-cert -for v in v01 v00 ; do - for kt in $PLAIN_TYPES ; do - type_has_legacy $kt || continue - rm -f $OBJ/cert_host_key* - # Self-sign key - ${SSHKEYGEN} -q -N '' -t ${kt} \ - -f $OBJ/cert_host_key_${kt} || \ - fail "ssh-keygen of cert_host_key_${kt} failed" - ${SSHKEYGEN} -t ${v} -h -q -s $OBJ/cert_host_key_${kt} \ - -I "regress host key for $USER" \ - -n $HOSTS $OBJ/cert_host_key_${kt} || - fail "couldn't sign cert_host_key_${kt}" - verbose "$tid: host ${kt} connect wrong cert" - ( - cat $OBJ/sshd_proxy_bak - echo HostKey $OBJ/cert_host_key_${kt} - echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub - ) > $OBJ/sshd_proxy - - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ - -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ - -F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1 - if [ $? -eq 0 ]; then - fail "ssh cert connect $ident succeeded unexpectedly" - fi - done +) > $OBJ/known_hosts-cert.orig +cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert +for kt in $PLAIN_TYPES ; do + rm -f $OBJ/cert_host_key* + # Self-sign key + ${SSHKEYGEN} -q -N '' -t ${kt} \ + -f $OBJ/cert_host_key_${kt} || \ + fail "ssh-keygen of cert_host_key_${kt} failed" + ${SSHKEYGEN} -t ${v} -h -q -s $OBJ/cert_host_key_${kt} \ + -I "regress host key for $USER" \ + -n $HOSTS $OBJ/cert_host_key_${kt} || + fail "couldn't sign cert_host_key_${kt}" + verbose "$tid: host ${kt} connect wrong cert" + ( + cat $OBJ/sshd_proxy_bak + echo HostKey $OBJ/cert_host_key_${kt} + echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub + ) > $OBJ/sshd_proxy + + cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert + ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ + -F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1 + if [ $? -eq 0 ]; then + fail "ssh cert connect $ident succeeded unexpectedly" + fi done -rm -f $OBJ/known_hosts-cert $OBJ/host_ca_key* $OBJ/cert_host_key* +rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/cert_host_key* diff --git a/crypto/openssh/regress/cert-userkey.sh b/crypto/openssh/regress/cert-userkey.sh index b093a91..c38c00a 100755 --- a/crypto/openssh/regress/cert-userkey.sh +++ b/crypto/openssh/regress/cert-userkey.sh @@ -1,18 +1,17 @@ -# $OpenBSD: cert-userkey.sh,v 1.12 2013/12/06 13:52:46 markus Exp $ +# $OpenBSD: cert-userkey.sh,v 1.14 2015/07/10 06:23:25 markus Exp $ # Placed in the Public Domain. tid="certified user keys" rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key* cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak +cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` -type_has_legacy() { - case $1 in - ed25519*|ecdsa*) return 1 ;; - esac - return 0 +kname() { + n=`echo "$1" | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/'` + echo "$n*,ssh-rsa*,ssh-ed25519*" } # Create a CA key @@ -28,18 +27,11 @@ for ktype in $PLAIN_TYPES ; do ${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \ -z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype} || fail "couldn't sign cert_user_key_${ktype}" - type_has_legacy $ktype || continue - cp $OBJ/cert_user_key_${ktype} $OBJ/cert_user_key_${ktype}_v00 - cp $OBJ/cert_user_key_${ktype}.pub $OBJ/cert_user_key_${ktype}_v00.pub - verbose "$tid: sign host ${ktype}_v00 cert" - ${SSHKEYGEN} -q -t v00 -s $OBJ/user_ca_key -I \ - "regress user key for $USER" \ - -n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype}_v00 || - fatal "couldn't sign cert_user_key_${ktype}_v00" done # Test explicitly-specified principals -for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do +for ktype in $PLAIN_TYPES ; do + t=$(kname $ktype) for privsep in yes no ; do _prefix="${ktype} privsep $privsep" @@ -51,7 +43,12 @@ for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do echo "AuthorizedPrincipalsFile " \ "$OBJ/authorized_principals_%u" echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" + echo "PubkeyAcceptedKeyTypes ${t}" ) > $OBJ/sshd_proxy + ( + cat $OBJ/ssh_proxy_bak + echo "PubkeyAcceptedKeyTypes ${t}" + ) > $OBJ/ssh_proxy # Missing authorized_principals verbose "$tid: ${_prefix} missing authorized_principals" @@ -124,7 +121,12 @@ for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do ( cat $OBJ/sshd_proxy_bak echo "UsePrivilegeSeparation $privsep" + echo "PubkeyAcceptedKeyTypes ${t}" ) > $OBJ/sshd_proxy + ( + cat $OBJ/ssh_proxy_bak + echo "PubkeyAcceptedKeyTypes ${t}" + ) > $OBJ/ssh_proxy # Wrong principals list verbose "$tid: ${_prefix} wrong principals key option" @@ -165,7 +167,8 @@ basic_tests() { extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub" fi - for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do + for ktype in $PLAIN_TYPES ; do + t=$(kname $ktype) for privsep in yes no ; do _prefix="${ktype} privsep $privsep $auth" # Simple connect @@ -173,8 +176,13 @@ basic_tests() { ( cat $OBJ/sshd_proxy_bak echo "UsePrivilegeSeparation $privsep" + echo "PubkeyAcceptedKeyTypes ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy + ( + cat $OBJ/ssh_proxy_bak + echo "PubkeyAcceptedKeyTypes ${t}" + ) > $OBJ/ssh_proxy ${SSH} -2i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true @@ -188,6 +196,7 @@ basic_tests() { cat $OBJ/sshd_proxy_bak echo "UsePrivilegeSeparation $privsep" echo "RevokedKeys $OBJ/cert_user_key_revoked" + echo "PubkeyAcceptedKeyTypes ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy cp $OBJ/cert_user_key_${ktype}.pub \ @@ -220,6 +229,7 @@ basic_tests() { ( cat $OBJ/sshd_proxy_bak echo "RevokedKeys $OBJ/user_ca_key.pub" + echo "PubkeyAcceptedKeyTypes ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy ${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ @@ -232,6 +242,7 @@ basic_tests() { verbose "$tid: $auth CA does not authenticate" ( cat $OBJ/sshd_proxy_bak + echo "PubkeyAcceptedKeyTypes ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy verbose "$tid: ensure CA key does not authenticate user" @@ -257,12 +268,7 @@ test_one() { fi for auth in $auth_choice ; do - for ktype in rsa rsa_v00 ; do - case $ktype in - *_v00) keyv="-t v00" ;; - *) keyv="" ;; - esac - + for ktype in rsa ed25519 ; do cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy if test "x$auth" = "xauthorized_keys" ; then # Add CA to authorized_keys @@ -274,6 +280,8 @@ test_one() { echo > $OBJ/authorized_keys_$USER echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \ >> $OBJ/sshd_proxy + echo "PubkeyAcceptedKeyTypes ${t}*" \ + >> $OBJ/sshd_proxy if test "x$auth_opt" != "x" ; then echo $auth_opt >> $OBJ/sshd_proxy fi @@ -282,8 +290,7 @@ test_one() { verbose "$tid: $ident auth $auth expect $result $ktype" ${SSHKEYGEN} -q -s $OBJ/user_ca_key \ -I "regress user key for $USER" \ - $sign_opts $keyv \ - $OBJ/cert_user_key_${ktype} || + $sign_opts $OBJ/cert_user_key_${ktype} || fail "couldn't sign cert_user_key_${ktype}" ${SSH} -2i $OBJ/cert_user_key_${ktype} \ @@ -335,13 +342,10 @@ test_one "principals key option no principals" failure "" \ # Wrong certificate cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy -for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do - case $ktype in - *_v00) args="-t v00" ;; - *) args="" ;; - esac +for ktype in $PLAIN_TYPES ; do + t=$(kname $ktype) # Self-sign - ${SSHKEYGEN} $args -q -s $OBJ/cert_user_key_${ktype} -I \ + ${SSHKEYGEN} -q -s $OBJ/cert_user_key_${ktype} -I \ "regress user key for $USER" \ -n $USER $OBJ/cert_user_key_${ktype} || fail "couldn't sign cert_user_key_${ktype}" diff --git a/crypto/openssh/regress/cfgmatch.sh b/crypto/openssh/regress/cfgmatch.sh index 80cf229..0562963 100644 --- a/crypto/openssh/regress/cfgmatch.sh +++ b/crypto/openssh/regress/cfgmatch.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cfgmatch.sh,v 1.8 2013/05/17 00:37:40 dtucker Exp $ +# $OpenBSD: cfgmatch.sh,v 1.9 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="sshd_config match" @@ -56,7 +56,7 @@ start_sshd #set -x # Test Match + PermitOpen in sshd_config. This should be permitted -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "match permitopen localhost proto $p" start_client -F $OBJ/ssh_config ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ @@ -65,7 +65,7 @@ for p in 1 2; do done # Same but from different source. This should not be permitted -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "match permitopen proxy proto $p" start_client -F $OBJ/ssh_proxy ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ @@ -74,11 +74,12 @@ for p in 1 2; do done # Retry previous with key option, should also be denied. -printf 'permitopen="127.0.0.1:'$PORT'" ' >$OBJ/authorized_keys_$USER -cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER -printf 'permitopen="127.0.0.1:'$PORT'" ' >>$OBJ/authorized_keys_$USER -cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER -for p in 1 2; do +cp /dev/null $OBJ/authorized_keys_$USER +for t in ${SSH_KEYTYPES}; do + printf 'permitopen="127.0.0.1:'$PORT'" ' >> $OBJ/authorized_keys_$USER + cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER +done +for p in ${SSH_PROTOCOLS}; do trace "match permitopen proxy w/key opts proto $p" start_client -F $OBJ/ssh_proxy ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ @@ -88,7 +89,7 @@ done # Test both sshd_config and key options permitting the same dst/port pair. # Should be permitted. -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "match permitopen localhost proto $p" start_client -F $OBJ/ssh_config ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ @@ -102,7 +103,7 @@ echo "Match User $USER" >>$OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy # Test that a Match overrides a PermitOpen in the global section -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "match permitopen proxy w/key opts proto $p" start_client -F $OBJ/ssh_proxy ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ @@ -117,7 +118,7 @@ echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy # Test that a rule that doesn't match doesn't override, plus test a # PermitOpen entry that's not at the start of the list -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "nomatch permitopen proxy w/key opts proto $p" start_client -F $OBJ/ssh_proxy ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ diff --git a/crypto/openssh/regress/cfgparse.sh b/crypto/openssh/regress/cfgparse.sh new file mode 100755 index 0000000..736f389 --- /dev/null +++ b/crypto/openssh/regress/cfgparse.sh @@ -0,0 +1,75 @@ +# $OpenBSD: cfgparse.sh,v 1.5 2015/05/29 03:05:13 djm Exp $ +# Placed in the Public Domain. + +tid="config parse" + +# This is a reasonable proxy for IPv6 support. +if ! config_defined HAVE_STRUCT_IN6_ADDR ; then + SKIP_IPV6=yes +fi + +# We need to use the keys generated for the regression test because sshd -T +# will fail if we're not running with SUDO (no permissions for real keys) or +# if we are # running tests on a system that has never had sshd installed +# (keys won't exist). + +grep "HostKey " $OBJ/sshd_config > $OBJ/sshd_config_minimal +SSHD_KEYS="`cat $OBJ/sshd_config_minimal`" + +verbose "reparse minimal config" +($SUDO ${SSHD} -T -f $OBJ/sshd_config_minimal >$OBJ/sshd_config.1 && + $SUDO ${SSHD} -T -f $OBJ/sshd_config.1 >$OBJ/sshd_config.2 && + diff $OBJ/sshd_config.1 $OBJ/sshd_config.2) || fail "reparse minimal config" + +verbose "reparse regress config" +($SUDO ${SSHD} -T -f $OBJ/sshd_config >$OBJ/sshd_config.1 && + $SUDO ${SSHD} -T -f $OBJ/sshd_config.1 >$OBJ/sshd_config.2 && + diff $OBJ/sshd_config.1 $OBJ/sshd_config.2) || fail "reparse regress config" + +verbose "listenaddress order" +# expected output +cat > $OBJ/sshd_config.0 <> $OBJ/sshd_config.0 < $OBJ/sshd_config.1 <> $OBJ/sshd_config.1 <$OBJ/sshd_config.2 && + diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ + fail "listenaddress order 1" +# test 2: listenaddress first +cat > $OBJ/sshd_config.1 <> $OBJ/sshd_config.1 <$OBJ/sshd_config.2 && + diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ + fail "listenaddress order 2" + +# cleanup +rm -f $OBJ/sshd_config.[012] diff --git a/crypto/openssh/regress/cipher-speed.sh b/crypto/openssh/regress/cipher-speed.sh index a6d53a7..575dc23 100644 --- a/crypto/openssh/regress/cipher-speed.sh +++ b/crypto/openssh/regress/cipher-speed.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cipher-speed.sh,v 1.11 2013/11/21 03:18:51 djm Exp $ +# $OpenBSD: cipher-speed.sh,v 1.13 2015/03/24 20:22:17 markus Exp $ # Placed in the Public Domain. tid="cipher speed" @@ -25,13 +25,17 @@ for c in `${SSH} -Q cipher`; do n=0; for m in `${SSH} -Q mac`; do fi done # No point trying all MACs for AEAD ciphers since they are ignored. - if ssh -Q cipher-auth | grep "^${c}\$" >/dev/null 2>&1 ; then + if ${SSH} -Q cipher-auth | grep "^${c}\$" >/dev/null 2>&1 ; then break fi n=`expr $n + 1` done; done -ciphers="3des blowfish" +if ssh_version 1; then + ciphers="3des blowfish" +else + ciphers="" +fi for c in $ciphers; do trace "proto 1 cipher $c" for x in $tries; do diff --git a/crypto/openssh/regress/connect-privsep.sh b/crypto/openssh/regress/connect-privsep.sh index 94cc64a..9a51f56 100644 --- a/crypto/openssh/regress/connect-privsep.sh +++ b/crypto/openssh/regress/connect-privsep.sh @@ -1,4 +1,4 @@ -# $OpenBSD: connect-privsep.sh,v 1.4 2012/07/02 14:37:06 dtucker Exp $ +# $OpenBSD: connect-privsep.sh,v 1.6 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="proxy connect with privsep" @@ -6,7 +6,7 @@ tid="proxy connect with privsep" cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true if [ $? -ne 0 ]; then fail "ssh privsep+proxyconnect protocol $p failed" @@ -16,7 +16,7 @@ done cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy echo 'UsePrivilegeSeparation sandbox' >> $OBJ/sshd_proxy -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true if [ $? -ne 0 ]; then # XXX replace this with fail once sandbox has stabilised @@ -26,8 +26,8 @@ done # Because sandbox is sensitive to changes in libc, especially malloc, retest # with every malloc.conf option (and none). -for m in '' A F G H J P R S X Z '<' '>'; do - for p in 1 2; do +for m in '' A F G H J P R S X '<' '>'; do + for p in ${SSH_PROTOCOLS}; do env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true if [ $? -ne 0 ]; then fail "ssh privsep/sandbox+proxyconnect protocol $p mopt '$m' failed" diff --git a/crypto/openssh/regress/connect.sh b/crypto/openssh/regress/connect.sh index 2186fa6..f0d55d3 100644 --- a/crypto/openssh/regress/connect.sh +++ b/crypto/openssh/regress/connect.sh @@ -1,11 +1,11 @@ -# $OpenBSD: connect.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ +# $OpenBSD: connect.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="simple connect" start_sshd -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true if [ $? -ne 0 ]; then fail "ssh connect with protocol $p failed" diff --git a/crypto/openssh/regress/dhgex.sh b/crypto/openssh/regress/dhgex.sh index 4c1a3d8..57fca4a 100755 --- a/crypto/openssh/regress/dhgex.sh +++ b/crypto/openssh/regress/dhgex.sh @@ -1,10 +1,11 @@ -# $OpenBSD: dhgex.sh,v 1.1 2014/01/25 04:35:32 dtucker Exp $ +# $OpenBSD: dhgex.sh,v 1.2 2014/04/21 22:15:37 djm Exp $ # Placed in the Public Domain. tid="dhgex" LOG=${TEST_SSH_LOGFILE} rm -f ${LOG} +cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak kexs=`${SSH} -Q kex | grep diffie-hellman-group-exchange` @@ -14,6 +15,9 @@ ssh_test_dhgex() cipher="$1"; shift kex="$1"; shift + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy + echo "KexAlgorithms=$kex" >> $OBJ/sshd_proxy + echo "Ciphers=$cipher" >> $OBJ/sshd_proxy rm -f ${LOG} opts="-oKexAlgorithms=$kex -oCiphers=$cipher" groupsz="1024<$bits<8192" diff --git a/crypto/openssh/regress/dynamic-forward.sh b/crypto/openssh/regress/dynamic-forward.sh index 42fa8ac..dd67c96 100644 --- a/crypto/openssh/regress/dynamic-forward.sh +++ b/crypto/openssh/regress/dynamic-forward.sh @@ -1,4 +1,4 @@ -# $OpenBSD: dynamic-forward.sh,v 1.10 2013/05/17 04:29:14 dtucker Exp $ +# $OpenBSD: dynamic-forward.sh,v 1.11 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="dynamic forwarding" @@ -17,7 +17,7 @@ trace "will use ProxyCommand $proxycmd" start_sshd -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do n=0 error="1" trace "start dynamic forwarding, fork to background" diff --git a/crypto/openssh/regress/exit-status.sh b/crypto/openssh/regress/exit-status.sh index 56b78a6..397d8d7 100644 --- a/crypto/openssh/regress/exit-status.sh +++ b/crypto/openssh/regress/exit-status.sh @@ -1,9 +1,9 @@ -# $OpenBSD: exit-status.sh,v 1.6 2002/03/15 13:08:56 markus Exp $ +# $OpenBSD: exit-status.sh,v 1.7 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="remote exit status" -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do for s in 0 1 4 5 44; do trace "proto $p status $s" verbose "test $tid: proto $p status $s" diff --git a/crypto/openssh/regress/forcecommand.sh b/crypto/openssh/regress/forcecommand.sh index 44d2b7f..8a9b090 100644 --- a/crypto/openssh/regress/forcecommand.sh +++ b/crypto/openssh/regress/forcecommand.sh @@ -1,30 +1,32 @@ -# $OpenBSD: forcecommand.sh,v 1.2 2013/05/17 00:37:40 dtucker Exp $ +# $OpenBSD: forcecommand.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="forced command" cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak -printf 'command="true" ' >$OBJ/authorized_keys_$USER -cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER -printf 'command="true" ' >>$OBJ/authorized_keys_$USER -cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER +cp /dev/null $OBJ/authorized_keys_$USER +for t in ${SSH_KEYTYPES}; do + printf 'command="true" ' >>$OBJ/authorized_keys_$USER + cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER +done -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "forced command in key option proto $p" ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || fail "forced command in key proto $p" done -printf 'command="false" ' >$OBJ/authorized_keys_$USER -cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER -printf 'command="false" ' >>$OBJ/authorized_keys_$USER -cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER +cp /dev/null $OBJ/authorized_keys_$USER +for t in ${SSH_KEYTYPES}; do + printf 'command="false" ' >> $OBJ/authorized_keys_$USER + cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER +done cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "ForceCommand true" >> $OBJ/sshd_proxy -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "forced command in sshd_config overrides key option proto $p" ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || fail "forced command in key proto $p" @@ -35,7 +37,7 @@ echo "ForceCommand false" >> $OBJ/sshd_proxy echo "Match User $USER" >> $OBJ/sshd_proxy echo " ForceCommand true" >> $OBJ/sshd_proxy -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "forced command with match proto $p" ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || fail "forced command in key proto $p" diff --git a/crypto/openssh/regress/forward-control.sh b/crypto/openssh/regress/forward-control.sh index 7f7d105..9195709 100755 --- a/crypto/openssh/regress/forward-control.sh +++ b/crypto/openssh/regress/forward-control.sh @@ -1,4 +1,4 @@ -# $OpenBSD: forward-control.sh,v 1.2 2013/11/18 05:09:32 naddy Exp $ +# $OpenBSD: forward-control.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="sshd control of local and remote forwarding" @@ -99,7 +99,7 @@ cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak # Sanity check: ensure the default config allows forwarding -for p in 1 2 ; do +for p in ${SSH_PROTOCOLS} ; do check_lfwd $p Y "proto $p, default configuration" check_rfwd $p Y "proto $p, default configuration" done @@ -115,7 +115,7 @@ all_tests() { _permit_rfwd=$7 _badfwd=127.0.0.1:22 _goodfwd=127.0.0.1:${PORT} - for _proto in 1 2 ; do + for _proto in ${SSH_PROTOCOLS} ; do cp ${OBJ}/authorized_keys_${USER}.bak \ ${OBJ}/authorized_keys_${USER} _prefix="proto $_proto, AllowTcpForwarding=$_tcpfwd" diff --git a/crypto/openssh/regress/forwarding.sh b/crypto/openssh/regress/forwarding.sh index 94873f2..fb4f35a 100644 --- a/crypto/openssh/regress/forwarding.sh +++ b/crypto/openssh/regress/forwarding.sh @@ -1,4 +1,4 @@ -# $OpenBSD: forwarding.sh,v 1.11 2013/06/10 21:56:43 dtucker Exp $ +# $OpenBSD: forwarding.sh,v 1.15 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="local and remote forwarding" @@ -10,6 +10,9 @@ start_sshd base=33 last=$PORT fwd="" +CTL=$OBJ/ctl-sock +rm -f $CTL + for j in 0 1 2; do for i in 0 1 2; do a=$base$j$i @@ -20,21 +23,24 @@ for j in 0 1 2; do last=$a done done -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do q=`expr 3 - $p` + if ! ssh_version $q; then + q=$p + fi trace "start forwarding, fork to background" ${SSH} -$p -F $OBJ/ssh_config -f $fwd somehost sleep 10 trace "transfer over forwarded channels and check result" ${SSH} -$q -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \ somehost cat ${DATA} > ${COPY} - test -f ${COPY} || fail "failed copy of ${DATA}" + test -s ${COPY} || fail "failed copy of ${DATA}" cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" sleep 10 done -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do for d in L R; do trace "exit on -$d forward failure, proto $p" @@ -64,7 +70,7 @@ for d in L R; do done done -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "simple clear forwarding proto $p" ${SSH} -$p -F $OBJ/ssh_config -oClearAllForwardings=yes somehost true @@ -107,15 +113,31 @@ done echo "LocalForward ${base}01 127.0.0.1:$PORT" >> $OBJ/ssh_config echo "RemoteForward ${base}02 127.0.0.1:${base}01" >> $OBJ/ssh_config -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do trace "config file: start forwarding, fork to background" - ${SSH} -$p -F $OBJ/ssh_config -f somehost sleep 10 + ${SSH} -S $CTL -M -$p -F $OBJ/ssh_config -f somehost sleep 10 trace "config file: transfer over forwarded channels and check result" ${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \ somehost cat ${DATA} > ${COPY} - test -f ${COPY} || fail "failed copy of ${DATA}" + test -s ${COPY} || fail "failed copy of ${DATA}" cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" - wait + ${SSH} -S $CTL -O exit somehost +done + +for p in 2; do + trace "transfer over chained unix domain socket forwards and check result" + rm -f $OBJ/unix-[123].fwd + ${SSH} -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehost sleep 10 + ${SSH} -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost sleep 10 + ${SSH} -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost sleep 10 + ${SSH} -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost sleep 10 + ${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=4' \ + somehost cat ${DATA} > ${COPY} + test -s ${COPY} || fail "failed copy ${DATA}" + cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" + + #wait + sleep 10 done diff --git a/crypto/openssh/regress/host-expand.sh b/crypto/openssh/regress/host-expand.sh index 6cc0e60..2a95bfe 100755 --- a/crypto/openssh/regress/host-expand.sh +++ b/crypto/openssh/regress/host-expand.sh @@ -1,4 +1,4 @@ -# $OpenBSD: host-expand.sh,v 1.3 2014/02/27 23:17:41 djm Exp $ +# $OpenBSD: host-expand.sh,v 1.4 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="expand %h and %n" @@ -11,7 +11,7 @@ somehost 127.0.0.1 EOE -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do verbose "test $tid: proto $p" ${SSH} -F $OBJ/ssh_proxy -$p somehost true >$OBJ/actual diff $OBJ/expect $OBJ/actual || fail "$tid proto $p" diff --git a/crypto/openssh/regress/hostkey-agent.sh b/crypto/openssh/regress/hostkey-agent.sh new file mode 100755 index 0000000..094700d --- /dev/null +++ b/crypto/openssh/regress/hostkey-agent.sh @@ -0,0 +1,53 @@ +# $OpenBSD: hostkey-agent.sh,v 1.6 2015/07/10 06:23:25 markus Exp $ +# Placed in the Public Domain. + +tid="hostkey agent" + +rm -f $OBJ/agent-key.* $OBJ/ssh_proxy.orig $OBJ/known_hosts.orig + +trace "start agent" +eval `${SSHAGENT} -s` > /dev/null +r=$? +[ $r -ne 0 ] && fatal "could not start ssh-agent: exit code $r" + +grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig +echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig + +trace "load hostkeys" +for k in `${SSH} -Q key-plain` ; do + ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k" + ( + printf 'localhost-with-alias,127.0.0.1,::1 ' + cat $OBJ/agent-key.$k.pub + ) >> $OBJ/known_hosts.orig + ${SSHADD} $OBJ/agent-key.$k >/dev/null 2>&1 || \ + fatal "couldn't load key $OBJ/agent-key.$k" + echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy.orig + # Remove private key so the server can't use it. + rm $OBJ/agent-key.$k || fatal "couldn't rm $OBJ/agent-key.$k" +done +cp $OBJ/known_hosts.orig $OBJ/known_hosts + +unset SSH_AUTH_SOCK + +for ps in no yes; do + for k in `${SSH} -Q key-plain` ; do + verbose "key type $k privsep=$ps" + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy + echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy + opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" + cp $OBJ/known_hosts.orig $OBJ/known_hosts + SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` + if [ $? -ne 0 ]; then + fail "protocol $p privsep=$ps failed" + fi + if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then + fail "bad SSH_CONNECTION key type $k privsep=$ps" + fi + done +done + +trace "kill agent" +${SSHAGENT} -k > /dev/null + diff --git a/crypto/openssh/regress/hostkey-rotate.sh b/crypto/openssh/regress/hostkey-rotate.sh new file mode 100755 index 0000000..3aa8c40 --- /dev/null +++ b/crypto/openssh/regress/hostkey-rotate.sh @@ -0,0 +1,128 @@ +# $OpenBSD: hostkey-rotate.sh,v 1.4 2015/07/10 06:23:25 markus Exp $ +# Placed in the Public Domain. + +tid="hostkey rotate" + +# Need full names here since they are used in HostKeyAlgorithms +HOSTKEY_TYPES="ecdsa-sha2-nistp256 ssh-ed25519 ssh-rsa ssh-dss" + +rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig + +grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig +echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy +rm $OBJ/known_hosts + +trace "prepare hostkeys" +nkeys=0 +all_algs="" +for k in `${SSH} -Q key-plain` ; do + ${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k" + echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig + nkeys=`expr $nkeys + 1` + test "x$all_algs" = "x" || all_algs="${all_algs}," + all_algs="${all_algs}$k" +done + +dossh() { + # All ssh should succeed in this test + ${SSH} -F $OBJ/ssh_proxy "$@" x true || fail "ssh $@ failed" +} + +expect_nkeys() { + _expected=$1 + _message=$2 + _n=`wc -l $OBJ/known_hosts | awk '{ print $1 }'` || fatal "wc failed" + [ "x$_n" = "x$_expected" ] || fail "$_message (got $_n wanted $_expected)" +} + +check_key_present() { + _type=$1 + _kfile=$2 + test "x$_kfile" = "x" && _kfile="$OBJ/hkr.${_type}.pub" + _kpub=`awk "/$_type /"' { print $2 }' < $_kfile` || \ + fatal "awk failed" + fgrep "$_kpub" $OBJ/known_hosts > /dev/null +} + +cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + +# Connect to sshd with StrictHostkeyChecking=no +verbose "learn hostkey with StrictHostKeyChecking=no" +>$OBJ/known_hosts +dossh -oHostKeyAlgorithms=ssh-ed25519 -oStrictHostKeyChecking=no +# Verify no additional keys learned +expect_nkeys 1 "unstrict connect keys" +check_key_present ssh-ed25519 || fail "unstrict didn't learn key" + +# Connect to sshd as usual +verbose "learn additional hostkeys" +dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs +# Check that other keys learned +expect_nkeys $nkeys "learn hostkeys" +check_key_present ssh-rsa || fail "didn't learn keys" + +# Check each key type +for k in `${SSH} -Q key-plain` ; do + verbose "learn additional hostkeys, type=$k" + dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$k,$all_algs + expect_nkeys $nkeys "learn hostkeys $k" + check_key_present $k || fail "didn't learn $k" +done + +# Change one hostkey (non primary) and relearn +verbose "learn changed non-primary hostkey" +mv $OBJ/hkr.ssh-rsa.pub $OBJ/hkr.ssh-rsa.pub.old +rm -f $OBJ/hkr.ssh-rsa +${SSHKEYGEN} -qt ssh-rsa -f $OBJ/hkr.ssh-rsa -N '' || fatal "ssh-keygen $k" +dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs +# Check that the key was replaced +expect_nkeys $nkeys "learn hostkeys" +check_key_present ssh-rsa $OBJ/hkr.ssh-rsa.pub.old && fail "old key present" +check_key_present ssh-rsa || fail "didn't learn changed key" + +# Add new hostkey (primary type) to sshd and connect +verbose "learn new primary hostkey" +${SSHKEYGEN} -qt ssh-rsa -f $OBJ/hkr.ssh-rsa-new -N '' || fatal "ssh-keygen $k" +( cat $OBJ/sshd_proxy.orig ; echo HostKey $OBJ/hkr.ssh-rsa-new ) \ + > $OBJ/sshd_proxy +# Check new hostkey added +dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa,$all_algs +expect_nkeys `expr $nkeys + 1` "learn hostkeys" +check_key_present ssh-rsa || fail "current key missing" +check_key_present ssh-rsa $OBJ/hkr.ssh-rsa-new.pub || fail "new key missing" + +# Remove old hostkey (primary type) from sshd +verbose "rotate primary hostkey" +cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy +mv $OBJ/hkr.ssh-rsa.pub $OBJ/hkr.ssh-rsa.pub.old +mv $OBJ/hkr.ssh-rsa-new.pub $OBJ/hkr.ssh-rsa.pub +mv $OBJ/hkr.ssh-rsa-new $OBJ/hkr.ssh-rsa +# Check old hostkey removed +dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa,$all_algs +expect_nkeys $nkeys "learn hostkeys" +check_key_present ssh-rsa $OBJ/hkr.ssh-rsa.pub.old && fail "old key present" +check_key_present ssh-rsa || fail "didn't learn changed key" + +# Connect again, forcing rotated key +verbose "check rotate primary hostkey" +dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa +expect_nkeys 1 "learn hostkeys" +check_key_present ssh-rsa || fail "didn't learn changed key" + +# $OpenBSD: hostkey-rotate.sh,v 1.4 2015/07/10 06:23:25 markus Exp $ +# Placed in the Public Domain. + +tid="hostkey rotate" + +# Prepare hostkeys file with one key + +# Connect to sshd + +# Check that other keys learned + +# Change one hostkey (non primary) + +# Connect to sshd + +# Check that the key was replaced + diff --git a/crypto/openssh/regress/integrity.sh b/crypto/openssh/regress/integrity.sh index 852d826..1d49767 100755 --- a/crypto/openssh/regress/integrity.sh +++ b/crypto/openssh/regress/integrity.sh @@ -1,7 +1,8 @@ -# $OpenBSD: integrity.sh,v 1.12 2013/11/21 03:18:51 djm Exp $ +# $OpenBSD: integrity.sh,v 1.16 2015/03/24 20:22:17 markus Exp $ # Placed in the Public Domain. tid="integrity" +cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak # start at byte 2900 (i.e. after kex) and corrupt at different offsets # XXX the test hangs if we modify the low bytes of the packet length @@ -19,7 +20,7 @@ echo "KexAlgorithms diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" \ >> $OBJ/ssh_proxy # sshd-command for proxy (see test-exec.sh) -cmd="$SUDO sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" +cmd="$SUDO sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" for m in $macs; do trace "test $tid: mac $m" @@ -34,11 +35,15 @@ for m in $macs; do # avoid modifying the high bytes of the length continue fi + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy # modify output from sshd at offset $off pxy="proxycommand=$cmd | $OBJ/modpipe -wm xor:$off:1" - if ssh -Q cipher-auth | grep "^${m}\$" >/dev/null 2>&1 ; then + if ${SSH} -Q cipher-auth | grep "^${m}\$" >/dev/null 2>&1 ; then + echo "Ciphers=$m" >> $OBJ/sshd_proxy macopt="-c $m" else + echo "Ciphers=aes128-ctr" >> $OBJ/sshd_proxy + echo "MACs=$m" >> $OBJ/sshd_proxy macopt="-m $m -c aes128-ctr" fi verbose "test $tid: $m @$off" @@ -49,14 +54,14 @@ for m in $macs; do fail "ssh -m $m succeeds with bit-flip at $off" fi ecnt=`expr $ecnt + 1` - output=$(tail -2 $TEST_SSH_LOGFILE | egrep -v "^debug" | \ + out=$(tail -2 $TEST_SSH_LOGFILE | egrep -v "^debug" | \ tr -s '\r\n' '.') - case "$output" in + case "$out" in Bad?packet*) elen=`expr $elen + 1`; skip=3;; - Corrupted?MAC* | Decryption?integrity?check?failed*) + Corrupted?MAC* | *message?authentication?code?incorrect*) emac=`expr $emac + 1`; skip=0;; padding*) epad=`expr $epad + 1`; skip=0;; - *) fail "unexpected error mac $m at $off";; + *) fail "unexpected error mac $m at $off: $out";; esac done verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen" diff --git a/crypto/openssh/regress/kextype.sh b/crypto/openssh/regress/kextype.sh index 8c2ac09..e271899 100755 --- a/crypto/openssh/regress/kextype.sh +++ b/crypto/openssh/regress/kextype.sh @@ -1,4 +1,4 @@ -# $OpenBSD: kextype.sh,v 1.4 2013/11/07 04:26:56 dtucker Exp $ +# $OpenBSD: kextype.sh,v 1.6 2015/03/24 20:19:15 markus Exp $ # Placed in the Public Domain. tid="login with different key exchange algorithms" @@ -7,6 +7,11 @@ TIME=/usr/bin/time cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak +# Make server accept all key exchanges. +ALLKEX=`${SSH} -Q kex` +KEXOPT=`echo $ALLKEX | tr ' ' ,` +echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy + tries="1 2 3 4" for k in `${SSH} -Q kex`; do verbose "kex $k" diff --git a/crypto/openssh/regress/key-options.sh b/crypto/openssh/regress/key-options.sh index f98d78b..7a68ad3 100755 --- a/crypto/openssh/regress/key-options.sh +++ b/crypto/openssh/regress/key-options.sh @@ -1,4 +1,4 @@ -# $OpenBSD: key-options.sh,v 1.2 2008/06/30 08:07:34 djm Exp $ +# $OpenBSD: key-options.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="key options" @@ -8,7 +8,7 @@ authkeys="$OBJ/authorized_keys_${USER}" cp $authkeys $origkeys # Test command= forced command -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do sed "s/.*/$c &/" $origkeys >$authkeys verbose "key option proto $p $c" @@ -24,7 +24,7 @@ done # Test no-pty sed 's/.*/no-pty &/' $origkeys >$authkeys -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do verbose "key option proto $p no-pty" r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost tty` if [ -f "$r" ]; then @@ -35,7 +35,7 @@ done # Test environment= echo 'PermitUserEnvironment yes' >> $OBJ/sshd_proxy sed 's/.*/environment="FOO=bar" &/' $origkeys >$authkeys -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do verbose "key option proto $p environment" r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost 'echo $FOO'` if [ "$r" != "bar" ]; then @@ -45,7 +45,7 @@ done # Test from= restriction start_sshd -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do for f in 127.0.0.1 '127.0.0.0\/8'; do cat $origkeys >$authkeys ${SSH} -$p -q -F $OBJ/ssh_proxy somehost true diff --git a/crypto/openssh/regress/keygen-change.sh b/crypto/openssh/regress/keygen-change.sh index 08d3590..e561850 100644 --- a/crypto/openssh/regress/keygen-change.sh +++ b/crypto/openssh/regress/keygen-change.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keygen-change.sh,v 1.2 2002/07/16 09:15:55 markus Exp $ +# $OpenBSD: keygen-change.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="change passphrase for key" @@ -6,7 +6,12 @@ tid="change passphrase for key" S1="secret1" S2="2secret" -for t in rsa dsa rsa1; do +KEYTYPES=`${SSH} -Q key-plain` +if ssh_version 1; then + KEYTYPES="${KEYTYPES} rsa1" +fi + +for t in $KEYTYPES; do # generate user key for agent trace "generating $t key" rm -f $OBJ/$t-key diff --git a/crypto/openssh/regress/keygen-knownhosts.sh b/crypto/openssh/regress/keygen-knownhosts.sh new file mode 100755 index 0000000..693cd0e --- /dev/null +++ b/crypto/openssh/regress/keygen-knownhosts.sh @@ -0,0 +1,197 @@ +# $OpenBSD: keygen-knownhosts.sh,v 1.3 2015/07/17 03:34:27 djm Exp $ +# Placed in the Public Domain. + +tid="ssh-keygen known_hosts" + +rm -f $OBJ/kh.* + +# Generate some keys for testing (just ed25519 for speed) and make a hosts file. +for x in host-a host-b host-c host-d host-e host-f host-a2 host-b2; do + ${SSHKEYGEN} -qt ed25519 -f $OBJ/kh.$x -C "$x" -N "" || \ + fatal "ssh-keygen failed" + # Add a comment that we expect should be preserved. + echo "# $x" >> $OBJ/kh.hosts + ( + case "$x" in + host-a|host-b) printf "$x " ;; + host-c) printf "@cert-authority $x " ;; + host-d) printf "@revoked $x " ;; + host-e) printf "host-e* " ;; + host-f) printf "host-f,host-g,host-h " ;; + host-a2) printf "host-a " ;; + host-b2) printf "host-b " ;; + esac + cat $OBJ/kh.${x}.pub + # Blank line should be preserved. + echo "" >> $OBJ/kh.hosts + ) >> $OBJ/kh.hosts +done + +# Generate a variant with an invalid line. We'll use this for most tests, +# because keygen should be able to cope and it should be preserved in any +# output file. +cat $OBJ/kh.hosts >> $OBJ/kh.invalid +echo "host-i " >> $OBJ/kh.invalid + +cp $OBJ/kh.invalid $OBJ/kh.invalid.orig +cp $OBJ/kh.hosts $OBJ/kh.hosts.orig + +expect_key() { + _host=$1 + _hosts=$2 + _key=$3 + _line=$4 + _mark=$5 + _marker="" + test "x$_mark" = "xCA" && _marker="@cert-authority " + test "x$_mark" = "xREVOKED" && _marker="@revoked " + test "x$_line" != "x" && + echo "# Host $_host found: line $_line $_mark" >> $OBJ/kh.expect + printf "${_marker}$_hosts " >> $OBJ/kh.expect + cat $OBJ/kh.${_key}.pub >> $OBJ/kh.expect || + fatal "${_key}.pub missing" +} + +check_find() { + _host=$1 + _name=$2 + _keygenopt=$3 + ${SSHKEYGEN} $_keygenopt -f $OBJ/kh.invalid -F $_host > $OBJ/kh.result + if ! diff -w $OBJ/kh.expect $OBJ/kh.result ; then + fail "didn't find $_name" + fi +} + +# Find key +rm -f $OBJ/kh.expect +expect_key host-a host-a host-a 2 +expect_key host-a host-a host-a2 20 +check_find host-a "simple find" + +# find CA key +rm -f $OBJ/kh.expect +expect_key host-c host-c host-c 8 CA +check_find host-c "find CA key" + +# find revoked key +rm -f $OBJ/kh.expect +expect_key host-d host-d host-d 11 REVOKED +check_find host-d "find revoked key" + +# find key with wildcard +rm -f $OBJ/kh.expect +expect_key host-e.somedomain "host-e*" host-e 14 +check_find host-e.somedomain "find wildcard key" + +# find key among multiple hosts +rm -f $OBJ/kh.expect +expect_key host-h "host-f,host-g,host-h " host-f 17 +check_find host-h "find multiple hosts" + +check_hashed_find() { + _host=$1 + _name=$2 + _file=$3 + test "x$_file" = "x" && _file=$OBJ/kh.invalid + ${SSHKEYGEN} -f $_file -HF $_host | grep '|1|' | \ + sed "s/^[^ ]*/$_host/" > $OBJ/kh.result + if ! diff -w $OBJ/kh.expect $OBJ/kh.result ; then + fail "didn't find $_name" + fi +} + +# Find key and hash +rm -f $OBJ/kh.expect +expect_key host-a host-a host-a +expect_key host-a host-a host-a2 +check_hashed_find host-a "find simple and hash" + +# Find CA key and hash +rm -f $OBJ/kh.expect +expect_key host-c host-c host-c "" CA +# CA key output is not hashed. +check_find host-c "find simple and hash" -H + +# Find revoked key and hash +rm -f $OBJ/kh.expect +expect_key host-d host-d host-d "" REVOKED +# Revoked key output is not hashed. +check_find host-d "find simple and hash" -H + +# find key with wildcard and hash +rm -f $OBJ/kh.expect +expect_key host-e "host-e*" host-e "" +# Key with wildcard hostname should not be hashed. +check_find host-e "find wildcard key" -H + +# find key among multiple hosts +rm -f $OBJ/kh.expect +# Comma-separated hostnames should be expanded and hashed. +expect_key host-f "host-h " host-f +expect_key host-g "host-h " host-f +expect_key host-h "host-h " host-f +check_hashed_find host-h "find multiple hosts" + +# Attempt remove key on invalid file. +cp $OBJ/kh.invalid.orig $OBJ/kh.invalid +${SSHKEYGEN} -qf $OBJ/kh.invalid -R host-a 2>/dev/null +diff $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "remove on invalid succeeded" + +# Remove key +cp $OBJ/kh.hosts.orig $OBJ/kh.hosts +${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-a 2>/dev/null +grep -v "^host-a " $OBJ/kh.hosts.orig > $OBJ/kh.expect +diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove simple" + +# Remove CA key +cp $OBJ/kh.hosts.orig $OBJ/kh.hosts +${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-c 2>/dev/null +# CA key should not be removed. +diff $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove CA" + +# Remove revoked key +cp $OBJ/kh.hosts.orig $OBJ/kh.hosts +${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-d 2>/dev/null +# revoked key should not be removed. +diff $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove revoked" + +# Remove wildcard +cp $OBJ/kh.hosts.orig $OBJ/kh.hosts +${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-e.blahblah 2>/dev/null +grep -v "^host-e[*] " $OBJ/kh.hosts.orig > $OBJ/kh.expect +diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard" + +# Remove multiple +cp $OBJ/kh.hosts.orig $OBJ/kh.hosts +${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-h 2>/dev/null +grep -v "^host-f," $OBJ/kh.hosts.orig > $OBJ/kh.expect +diff $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard" + +# Attempt hash on invalid file +cp $OBJ/kh.invalid.orig $OBJ/kh.invalid +${SSHKEYGEN} -qf $OBJ/kh.invalid -H 2>/dev/null && fail "hash invalid succeeded" +diff $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "invalid file modified" + +# Hash valid file +cp $OBJ/kh.hosts.orig $OBJ/kh.hosts +${SSHKEYGEN} -qf $OBJ/kh.hosts -H 2>/dev/null || fail "hash failed" +diff $OBJ/kh.hosts.old $OBJ/kh.hosts.orig || fail "backup differs" +grep "^host-[abfgh]" $OBJ/kh.hosts && fail "original hostnames persist" + +cp $OBJ/kh.hosts $OBJ/kh.hashed.orig + +# Test lookup +rm -f $OBJ/kh.expect +expect_key host-a host-a host-a +expect_key host-a host-a host-a2 +check_hashed_find host-a "find simple in hashed" $OBJ/kh.hosts + +# Test multiple expanded +rm -f $OBJ/kh.expect +expect_key host-h host-h host-f +check_hashed_find host-h "find simple in hashed" $OBJ/kh.hosts + +# Test remove +cp $OBJ/kh.hashed.orig $OBJ/kh.hashed +${SSHKEYGEN} -qf $OBJ/kh.hashed -R host-a 2>/dev/null +${SSHKEYGEN} -qf $OBJ/kh.hashed -F host-a && fail "found key after hashed remove" diff --git a/crypto/openssh/regress/keys-command.sh b/crypto/openssh/regress/keys-command.sh index b595a43..700273b 100755 --- a/crypto/openssh/regress/keys-command.sh +++ b/crypto/openssh/regress/keys-command.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keys-command.sh,v 1.2 2012/12/06 06:06:54 dtucker Exp $ +# $OpenBSD: keys-command.sh,v 1.3 2015/05/21 06:40:02 djm Exp $ # Placed in the Public Domain. tid="authorized keys from command" @@ -9,26 +9,63 @@ if test -z "$SUDO" ; then exit 0 fi +rm -f $OBJ/keys-command-args + +touch $OBJ/keys-command-args +chmod a+rw $OBJ/keys-command-args + +expected_key_text=`awk '{ print $2 }' < $OBJ/rsa.pub` +expected_key_fp=`$SSHKEYGEN -lf $OBJ/rsa.pub | awk '{ print $2 }'` + # Establish a AuthorizedKeysCommand in /var/run where it will have # acceptable directory permissions. KEY_COMMAND="/var/run/keycommand_${LOGNAME}" -cat << _EOF | $SUDO sh -c "cat > '$KEY_COMMAND'" +cat << _EOF | $SUDO sh -c "rm -f '$KEY_COMMAND' ; cat > '$KEY_COMMAND'" #!/bin/sh +echo args: "\$@" >> $OBJ/keys-command-args +echo "$PATH" | grep -q mekmitasdigoat && exit 7 test "x\$1" != "x${LOGNAME}" && exit 1 +if test $# -eq 6 ; then + test "x\$2" != "xblah" && exit 2 + test "x\$3" != "x${expected_key_text}" && exit 3 + test "x\$4" != "xssh-rsa" && exit 4 + test "x\$5" != "x${expected_key_fp}" && exit 5 + test "x\$6" != "xblah" && exit 6 +fi exec cat "$OBJ/authorized_keys_${LOGNAME}" _EOF $SUDO chmod 0755 "$KEY_COMMAND" -cp $OBJ/sshd_proxy $OBJ/sshd_proxy.bak -( - grep -vi AuthorizedKeysFile $OBJ/sshd_proxy.bak - echo AuthorizedKeysFile none - echo AuthorizedKeysCommand $KEY_COMMAND - echo AuthorizedKeysCommandUser ${LOGNAME} -) > $OBJ/sshd_proxy - if [ -x $KEY_COMMAND ]; then - ${SSH} -F $OBJ/ssh_proxy somehost true + cp $OBJ/sshd_proxy $OBJ/sshd_proxy.bak + + verbose "AuthorizedKeysCommand with arguments" + ( + grep -vi AuthorizedKeysFile $OBJ/sshd_proxy.bak + echo AuthorizedKeysFile none + echo AuthorizedKeysCommand $KEY_COMMAND %u blah %k %t %f blah + echo AuthorizedKeysCommandUser ${LOGNAME} + ) > $OBJ/sshd_proxy + + # Ensure that $PATH is sanitised in sshd + env PATH=$PATH:/sbin/mekmitasdigoat \ + ${SSH} -F $OBJ/ssh_proxy somehost true + if [ $? -ne 0 ]; then + fail "connect failed" + fi + + verbose "AuthorizedKeysCommand without arguments" + # Check legacy behavior of no-args resulting in username being passed. + ( + grep -vi AuthorizedKeysFile $OBJ/sshd_proxy.bak + echo AuthorizedKeysFile none + echo AuthorizedKeysCommand $KEY_COMMAND + echo AuthorizedKeysCommandUser ${LOGNAME} + ) > $OBJ/sshd_proxy + + # Ensure that $PATH is sanitised in sshd + env PATH=$PATH:/sbin/mekmitasdigoat \ + ${SSH} -F $OBJ/ssh_proxy somehost true if [ $? -ne 0 ]; then fail "connect failed" fi diff --git a/crypto/openssh/regress/keyscan.sh b/crypto/openssh/regress/keyscan.sh index 33f14f0..886f329 100644 --- a/crypto/openssh/regress/keyscan.sh +++ b/crypto/openssh/regress/keyscan.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keyscan.sh,v 1.3 2002/03/15 13:08:56 markus Exp $ +# $OpenBSD: keyscan.sh,v 1.4 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="keyscan" @@ -8,7 +8,12 @@ rm -f ${OBJ}/host.dsa start_sshd -for t in rsa1 rsa dsa; do +KEYTYPES="rsa dsa" +if ssh_version 1; then + KEYTYPES="${KEYTYPES} rsa1" +fi + +for t in $KEYTYPES; do trace "keyscan type $t" ${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \ > /dev/null 2>&1 diff --git a/crypto/openssh/regress/keytype.sh b/crypto/openssh/regress/keytype.sh index 9752acb..8f69778 100755 --- a/crypto/openssh/regress/keytype.sh +++ b/crypto/openssh/regress/keytype.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keytype.sh,v 1.3 2013/12/06 13:52:46 markus Exp $ +# $OpenBSD: keytype.sh,v 1.4 2015/07/10 06:23:25 markus Exp $ # Placed in the Public Domain. tid="login with different key types" @@ -36,14 +36,26 @@ for ut in $ktypes; do htypes=$ut #htypes=$ktypes for ht in $htypes; do + case $ht in + dsa-1024) t=ssh-dss;; + ecdsa-256) t=ecdsa-sha2-nistp256;; + ecdsa-384) t=ecdsa-sha2-nistp384;; + ecdsa-521) t=ecdsa-sha2-nistp521;; + ed25519-512) t=ssh-ed25519;; + rsa-*) t=ssh-rsa;; + esac trace "ssh connect, userkey $ut, hostkey $ht" ( grep -v HostKey $OBJ/sshd_proxy_bak echo HostKey $OBJ/key.$ht + echo PubkeyAcceptedKeyTypes $t + echo HostKeyAlgorithms $t ) > $OBJ/sshd_proxy ( grep -v IdentityFile $OBJ/ssh_proxy_bak echo IdentityFile $OBJ/key.$ut + echo PubkeyAcceptedKeyTypes $t + echo HostKeyAlgorithms $t ) > $OBJ/ssh_proxy ( printf 'localhost-with-alias,127.0.0.1,::1 ' diff --git a/crypto/openssh/regress/krl.sh b/crypto/openssh/regress/krl.sh index 0924637..1077358 100755 --- a/crypto/openssh/regress/krl.sh +++ b/crypto/openssh/regress/krl.sh @@ -1,4 +1,4 @@ -# $OpenBSD: krl.sh,v 1.2 2013/11/21 03:15:46 djm Exp $ +# $OpenBSD: krl.sh,v 1.6 2015/01/30 01:11:39 djm Exp $ # Placed in the Public Domain. tid="key revocation lists" @@ -17,6 +17,8 @@ rm -f $OBJ/revoked-* $OBJ/krl-* # Generate a CA key $SSHKEYGEN -t $ECDSA -f $OBJ/revoked-ca -C "" -N "" > /dev/null || fatal "$SSHKEYGEN CA failed" +$SSHKEYGEN -t ed25519 -f $OBJ/revoked-ca2 -C "" -N "" > /dev/null || + fatal "$SSHKEYGEN CA2 failed" # A specification that revokes some certificates by serial numbers # The serial pattern is chosen to ensure the KRL includes list, range and @@ -37,11 +39,15 @@ serial: 700-797 serial: 798 serial: 799 serial: 599-701 +# Some multiple consecutive serial number ranges +serial: 10000-20000 +serial: 30000-40000 EOF # A specification that revokes some certificated by key ID. touch $OBJ/revoked-keyid for n in 1 2 3 4 10 15 30 50 `jot 500 300` 999 1000 1001 1002; do + test "x$n" = "x499" && continue # Fill in by-ID revocation spec. echo "id: revoked $n" >> $OBJ/revoked-keyid done @@ -53,7 +59,7 @@ keygen() { keytype=$ECDSA case $N in 2 | 10 | 510 | 1001) keytype=rsa;; - 4 | 30 | 520 | 1002) keytype=dsa;; + 4 | 30 | 520 | 1002) keytype=ed25519;; esac $SSHKEYGEN -t $keytype -f $f -C "" -N "" > /dev/null \ || fatal "$SSHKEYGEN failed" @@ -68,37 +74,48 @@ verbose "$tid: generating test keys" REVOKED_SERIALS="1 4 10 50 500 510 520 799 999" for n in $REVOKED_SERIALS ; do f=`keygen $n` - REVOKED_KEYS="$REVOKED_KEYS ${f}.pub" - REVOKED_CERTS="$REVOKED_CERTS ${f}-cert.pub" + RKEYS="$RKEYS ${f}.pub" + RCERTS="$RCERTS ${f}-cert.pub" done -NOTREVOKED_SERIALS="5 9 14 16 29 30 49 51 499 800 1000 1001" -NOTREVOKED="" -for n in $NOTREVOKED_SERIALS ; do - NOTREVOKED_KEYS="$NOTREVOKED_KEYS ${f}.pub" - NOTREVOKED_CERTS="$NOTREVOKED_CERTS ${f}-cert.pub" +UNREVOKED_SERIALS="5 9 14 16 29 49 51 499 800 1010 1011" +UNREVOKED="" +for n in $UNREVOKED_SERIALS ; do + f=`keygen $n` + UKEYS="$UKEYS ${f}.pub" + UCERTS="$UCERTS ${f}-cert.pub" done genkrls() { OPTS=$1 $SSHKEYGEN $OPTS -kf $OBJ/krl-empty - /dev/null || fatal "$SSHKEYGEN KRL failed" -$SSHKEYGEN $OPTS -kf $OBJ/krl-keys $REVOKED_KEYS \ +$SSHKEYGEN $OPTS -kf $OBJ/krl-keys $RKEYS \ >/dev/null || fatal "$SSHKEYGEN KRL failed" -$SSHKEYGEN $OPTS -kf $OBJ/krl-cert $REVOKED_CERTS \ +$SSHKEYGEN $OPTS -kf $OBJ/krl-cert $RCERTS \ >/dev/null || fatal "$SSHKEYGEN KRL failed" -$SSHKEYGEN $OPTS -kf $OBJ/krl-all $REVOKED_KEYS $REVOKED_CERTS \ +$SSHKEYGEN $OPTS -kf $OBJ/krl-all $RKEYS $RCERTS \ >/dev/null || fatal "$SSHKEYGEN KRL failed" $SSHKEYGEN $OPTS -kf $OBJ/krl-ca $OBJ/revoked-ca.pub \ >/dev/null || fatal "$SSHKEYGEN KRL failed" -# KRLs from serial/key-id spec need the CA specified. +# This should fail as KRLs from serial/key-id spec need the CA specified. $SSHKEYGEN $OPTS -kf $OBJ/krl-serial $OBJ/revoked-serials \ >/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly" $SSHKEYGEN $OPTS -kf $OBJ/krl-keyid $OBJ/revoked-keyid \ >/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly" -$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -s $OBJ/revoked-ca $OBJ/revoked-serials \ +# These should succeed; they specify an explicit CA key. +$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -s $OBJ/revoked-ca \ + $OBJ/revoked-serials >/dev/null || fatal "$SSHKEYGEN KRL failed" +$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid -s $OBJ/revoked-ca.pub \ + $OBJ/revoked-keyid >/dev/null || fatal "$SSHKEYGEN KRL failed" +# These should succeed; they specify an wildcard CA key. +$SSHKEYGEN $OPTS -kf $OBJ/krl-serial-wild -s NONE $OBJ/revoked-serials \ >/dev/null || fatal "$SSHKEYGEN KRL failed" -$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid -s $OBJ/revoked-ca.pub $OBJ/revoked-keyid \ +$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid-wild -s NONE $OBJ/revoked-keyid \ >/dev/null || fatal "$SSHKEYGEN KRL failed" +# Revoke the same serials with the second CA key to ensure a multi-CA +# KRL is generated. +$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -u -s $OBJ/revoked-ca2 \ + $OBJ/revoked-serials >/dev/null || fatal "$SSHKEYGEN KRL failed" } ## XXX dump with trace and grep for set cert serials @@ -120,7 +137,7 @@ check_krl() { fatal "key $KEY unexpectedly revoked by KRL $KRL: $TAG" fi } -test_all() { +test_rev() { FILES=$1 TAG=$2 KEYS_RESULT=$3 @@ -129,32 +146,40 @@ test_all() { KEYID_RESULT=$6 CERTS_RESULT=$7 CA_RESULT=$8 + SERIAL_WRESULT=$9 + KEYID_WRESULT=$10 verbose "$tid: checking revocations for $TAG" for f in $FILES ; do - check_krl $f $OBJ/krl-empty no "$TAG" - check_krl $f $OBJ/krl-keys $KEYS_RESULT "$TAG" - check_krl $f $OBJ/krl-all $ALL_RESULT "$TAG" - check_krl $f $OBJ/krl-serial $SERIAL_RESULT "$TAG" - check_krl $f $OBJ/krl-keyid $KEYID_RESULT "$TAG" - check_krl $f $OBJ/krl-cert $CERTS_RESULT "$TAG" - check_krl $f $OBJ/krl-ca $CA_RESULT "$TAG" + check_krl $f $OBJ/krl-empty no "$TAG" + check_krl $f $OBJ/krl-keys $KEYS_RESULT "$TAG" + check_krl $f $OBJ/krl-all $ALL_RESULT "$TAG" + check_krl $f $OBJ/krl-serial $SERIAL_RESULT "$TAG" + check_krl $f $OBJ/krl-keyid $KEYID_RESULT "$TAG" + check_krl $f $OBJ/krl-cert $CERTS_RESULT "$TAG" + check_krl $f $OBJ/krl-ca $CA_RESULT "$TAG" + check_krl $f $OBJ/krl-serial-wild $SERIAL_WRESULT "$TAG" + check_krl $f $OBJ/krl-keyid-wild $KEYID_WRESULT "$TAG" done } -# keys all serial keyid certs CA -test_all "$REVOKED_KEYS" "revoked keys" yes yes no no no no -test_all "$UNREVOKED_KEYS" "unrevoked keys" no no no no no no -test_all "$REVOKED_CERTS" "revoked certs" yes yes yes yes yes yes -test_all "$UNREVOKED_CERTS" "unrevoked certs" no no no no no yes + +test_all() { + # wildcard + # keys all sr# k.ID cert CA sr.# k.ID + test_rev "$RKEYS" "revoked keys" yes yes no no no no no no + test_rev "$UKEYS" "unrevoked keys" no no no no no no no no + test_rev "$RCERTS" "revoked certs" yes yes yes yes yes yes yes yes + test_rev "$UCERTS" "unrevoked certs" no no no no no yes no no +} + +test_all # Check update. Results should be identical. verbose "$tid: testing KRL update" for f in $OBJ/krl-keys $OBJ/krl-cert $OBJ/krl-all \ - $OBJ/krl-ca $OBJ/krl-serial $OBJ/krl-keyid ; do + $OBJ/krl-ca $OBJ/krl-serial $OBJ/krl-keyid \ + $OBJ/krl-serial-wild $OBJ/krl-keyid-wild; do cp -f $OBJ/krl-empty $f genkrls -u done -# keys all serial keyid certs CA -test_all "$REVOKED_KEYS" "revoked keys" yes yes no no no no -test_all "$UNREVOKED_KEYS" "unrevoked keys" no no no no no no -test_all "$REVOKED_CERTS" "revoked certs" yes yes yes yes yes yes -test_all "$UNREVOKED_CERTS" "unrevoked certs" no no no no no yes + +test_all diff --git a/crypto/openssh/regress/limit-keytype.sh b/crypto/openssh/regress/limit-keytype.sh new file mode 100755 index 0000000..2de037b --- /dev/null +++ b/crypto/openssh/regress/limit-keytype.sh @@ -0,0 +1,80 @@ +# $OpenBSD: limit-keytype.sh,v 1.1 2015/01/13 07:49:49 djm Exp $ +# Placed in the Public Domain. + +tid="restrict pubkey type" + +rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key* +rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key* + +mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig +mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig + +# Create a CA key +${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key ||\ + fatal "ssh-keygen failed" + +# Make some keys and a certificate. +${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \ + fatal "ssh-keygen failed" +${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_key2 || \ + fatal "ssh-keygen failed" +${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_key3 || \ + fatal "ssh-keygen failed" +${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \ + -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key3 || + fatal "couldn't sign user_key1" +# Copy the private key alongside the cert to allow better control of when +# it is offered. +mv $OBJ/user_key3-cert.pub $OBJ/cert_user_key3.pub +cp -p $OBJ/user_key3 $OBJ/cert_user_key3 + +grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy + +opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes" +fullopts="$opts -i $OBJ/cert_user_key3 -i $OBJ/user_key1 -i $OBJ/user_key2" + +echo mekmitasdigoat > $OBJ/authorized_principals_$USER +cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER +cat $OBJ/user_key2.pub >> $OBJ/authorized_keys_$USER + +prepare_config() { + ( + grep -v "Protocol" $OBJ/sshd_proxy.orig + echo "Protocol 2" + echo "AuthenticationMethods publickey" + echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" + echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u" + for x in "$@" ; do + echo "$x" + done + ) > $OBJ/sshd_proxy +} + +prepare_config + +# Check we can log in with all key types. +${SSH} $opts -i $OBJ/cert_user_key3 proxy true || fatal "cert failed" +${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" +${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed" + +# Allow plain Ed25519 and RSA. The certificate should fail. +verbose "privsep=$privsep allow rsa,ed25519" +prepare_config "PubkeyAcceptedKeyTypes ssh-rsa,ssh-ed25519" +${SSH} $opts -i $OBJ/cert_user_key3 proxy true && fatal "cert succeeded" +${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" +${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed" + +# Allow Ed25519 only. +verbose "privsep=$privsep allow ed25519" +prepare_config "PubkeyAcceptedKeyTypes ssh-ed25519" +${SSH} $opts -i $OBJ/cert_user_key3 proxy true && fatal "cert succeeded" +${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" +${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded" + +# Allow all certs. Plain keys should fail. +verbose "privsep=$privsep allow cert only" +prepare_config "PubkeyAcceptedKeyTypes ssh-*-cert-v01@openssh.com" +${SSH} $opts -i $OBJ/cert_user_key3 proxy true || fatal "cert failed" +${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded" +${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded" + diff --git a/crypto/openssh/regress/localcommand.sh b/crypto/openssh/regress/localcommand.sh index 8a9b569..220f19a 100755 --- a/crypto/openssh/regress/localcommand.sh +++ b/crypto/openssh/regress/localcommand.sh @@ -1,4 +1,4 @@ -# $OpenBSD: localcommand.sh,v 1.2 2013/05/17 10:24:48 dtucker Exp $ +# $OpenBSD: localcommand.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="localcommand" @@ -6,7 +6,7 @@ tid="localcommand" echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy echo 'LocalCommand echo foo' >> $OBJ/ssh_proxy -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do verbose "test $tid: proto $p localcommand" a=`${SSH} -F $OBJ/ssh_proxy -$p somehost true` if [ "$a" != "foo" ] ; then diff --git a/crypto/openssh/regress/login-timeout.sh b/crypto/openssh/regress/login-timeout.sh index d9b48f3..eb76f55 100644 --- a/crypto/openssh/regress/login-timeout.sh +++ b/crypto/openssh/regress/login-timeout.sh @@ -1,4 +1,4 @@ -# $OpenBSD: login-timeout.sh,v 1.6 2014/02/27 20:04:16 djm Exp $ +# $OpenBSD: login-timeout.sh,v 1.7 2014/03/13 20:44:49 djm Exp $ # Placed in the Public Domain. tid="connect after login grace timeout" @@ -22,6 +22,7 @@ $SUDO kill `$SUDO cat $PIDFILE` trace "test login grace without privsep" echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config start_sshd +sleep 1 (echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 & sleep 15 diff --git a/crypto/openssh/regress/multiplex.sh b/crypto/openssh/regress/multiplex.sh index 3e697e6..acb9234 100644 --- a/crypto/openssh/regress/multiplex.sh +++ b/crypto/openssh/regress/multiplex.sh @@ -1,10 +1,13 @@ -# $OpenBSD: multiplex.sh,v 1.21 2013/05/17 04:29:14 dtucker Exp $ +# $OpenBSD: multiplex.sh,v 1.27 2014/12/22 06:14:29 djm Exp $ # Placed in the Public Domain. CTL=/tmp/openssh.regress.ctl-sock.$$ tid="connection multiplexing" +NC=$OBJ/netcat + +trace "will use ProxyCommand $proxycmd" if config_defined DISABLE_FD_PASSING ; then echo "skipped (not supported on this platform)" exit 0 @@ -29,7 +32,8 @@ start_mux_master() trace "start master, fork to background" ${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \ -E $TEST_REGRESS_LOGFILE 2>&1 & - MASTER_PID=$! + # NB. $SSH_PID will be killed by test-exec.sh:cleanup on fatal errors. + SSH_PID=$! wait_for_mux_master_ready } @@ -71,6 +75,25 @@ test -f ${COPY} || fail "scp: failed copy ${DATA}" cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}" rm -f ${COPY} +verbose "test $tid: forward" +trace "forward over TCP/IP and check result" +$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null & +netcat_pid=$! +${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1 +$NC 127.0.0.1 $((${PORT} + 2)) < /dev/null > ${COPY} +cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}" +kill $netcat_pid 2>/dev/null +rm -f ${COPY} $OBJ/unix-[123].fwd + +trace "forward over UNIX and check result" +$NC -N -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null & +netcat_pid=$! +${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1 +${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1 +$NC -U $OBJ/unix-3.fwd < /dev/null > ${COPY} 2>/dev/null +cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}" +kill $netcat_pid 2>/dev/null +rm -f ${COPY} $OBJ/unix-[123].fwd for s in 0 1 4 5 44; do trace "exit status $s over multiplexed connection" @@ -95,7 +118,7 @@ verbose "test $tid: cmd check" ${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ || fail "check command failed" -verbose "test $tid: cmd forward local" +verbose "test $tid: cmd forward local (TCP)" ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \ || fail "request local forward failed" ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ @@ -105,7 +128,7 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $P:localhost:$PORT otherhost \ ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ && fail "local forward port still listening" -verbose "test $tid: cmd forward remote" +verbose "test $tid: cmd forward remote (TCP)" ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \ || fail "request remote forward failed" ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ @@ -115,13 +138,35 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $P:localhost:$PORT otherhost \ ${SSH} -F $OBJ/ssh_config -p$P otherhost true \ && fail "remote forward port still listening" +verbose "test $tid: cmd forward local (UNIX)" +${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \ + || fail "request local forward failed" +echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \ + || fail "connect to local forward path failed" +${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \ + || fail "cancel local forward failed" +N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l) +test ${N} -eq 0 || fail "local forward path still listening" +rm -f $OBJ/unix-1.fwd + +verbose "test $tid: cmd forward remote (UNIX)" +${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \ + || fail "request remote forward failed" +echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \ + || fail "connect to remote forwarded path failed" +${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \ + || fail "cancel remote forward failed" +N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l) +test ${N} -eq 0 || fail "remote forward path still listening" +rm -f $OBJ/unix-1.fwd + verbose "test $tid: cmd exit" ${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ || fail "send exit command failed" # Wait for master to exit -wait $MASTER_PID -kill -0 $MASTER_PID >/dev/null 2>&1 && fail "exit command failed" +wait $SSH_PID +kill -0 $SSH_PID >/dev/null 2>&1 && fail "exit command failed" # Restart master and test -O stop command with master using -N verbose "test $tid: cmd stop" @@ -138,6 +183,8 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1 # wait until both long-running command and master have exited. wait $SLEEP_PID [ $! != 0 ] || fail "waiting for concurrent command" -wait $MASTER_PID +wait $SSH_PID [ $! != 0 ] || fail "waiting for master stop" -kill -0 $MASTER_PID >/dev/null 2>&1 && fail "stop command failed" +kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed" +SSH_PID="" # Already gone, so don't kill in cleanup + diff --git a/crypto/openssh/regress/multipubkey.sh b/crypto/openssh/regress/multipubkey.sh new file mode 100755 index 0000000..e9d1530 --- /dev/null +++ b/crypto/openssh/regress/multipubkey.sh @@ -0,0 +1,66 @@ +# $OpenBSD: multipubkey.sh,v 1.1 2014/12/22 08:06:03 djm Exp $ +# Placed in the Public Domain. + +tid="multiple pubkey" + +rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key* +rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key* + +mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig +mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig + +# Create a CA key +${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key ||\ + fatal "ssh-keygen failed" + +# Make some keys and a certificate. +${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \ + fatal "ssh-keygen failed" +${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \ + fatal "ssh-keygen failed" +${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \ + -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key1 || + fail "couldn't sign user_key1" +# Copy the private key alongside the cert to allow better control of when +# it is offered. +mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1.pub +cp -p $OBJ/user_key1 $OBJ/cert_user_key1 + +grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy + +opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes" +opts="$opts -i $OBJ/cert_user_key1 -i $OBJ/user_key1 -i $OBJ/user_key2" + +for privsep in no yes; do + ( + grep -v "Protocol" $OBJ/sshd_proxy.orig + echo "Protocol 2" + echo "UsePrivilegeSeparation $privsep" + echo "AuthenticationMethods publickey,publickey" + echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" + echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u" + ) > $OBJ/sshd_proxy + + # Single key should fail. + rm -f $OBJ/authorized_principals_$USER + cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER + ${SSH} $opts proxy true && fail "ssh succeeded with key" + + # Single key with same-public cert should fail. + echo mekmitasdigoat > $OBJ/authorized_principals_$USER + cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER + ${SSH} $opts proxy true && fail "ssh succeeded with key+cert" + + # Multiple plain keys should succeed. + rm -f $OBJ/authorized_principals_$USER + cat $OBJ/user_key1.pub $OBJ/user_key2.pub > \ + $OBJ/authorized_keys_$USER + ${SSH} $opts proxy true || fail "ssh failed with multiple keys" + # Cert and different key should succeed + + # Key and different-public cert should succeed. + echo mekmitasdigoat > $OBJ/authorized_principals_$USER + cat $OBJ/user_key2.pub > $OBJ/authorized_keys_$USER + ${SSH} $opts proxy true || fail "ssh failed with key/cert" +done + diff --git a/crypto/openssh/regress/netcat.c b/crypto/openssh/regress/netcat.c new file mode 100644 index 0000000..6234ba0 --- /dev/null +++ b/crypto/openssh/regress/netcat.c @@ -0,0 +1,1696 @@ +/* $OpenBSD: netcat.c,v 1.126 2014/10/30 16:08:31 tedu Exp $ */ +/* + * Copyright (c) 2001 Eric Jackson + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * 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. + */ + +/* + * Re-written nc(1) for OpenBSD. Original implementation by + * *Hobbit* . + */ + +#include "includes.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "atomicio.h" + +#ifdef HAVE_POLL_H +#include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif +#endif + +/* Telnet options from arpa/telnet.h */ +#define IAC 255 +#define DONT 254 +#define DO 253 +#define WONT 252 +#define WILL 251 + +#ifndef SUN_LEN +#define SUN_LEN(su) \ + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) +#endif + +#define PORT_MAX 65535 +#define PORT_MAX_LEN 6 +#define UNIX_DG_TMP_SOCKET_SIZE 19 + +#define POLL_STDIN 0 +#define POLL_NETOUT 1 +#define POLL_NETIN 2 +#define POLL_STDOUT 3 +#define BUFSIZE 16384 + +/* Command Line Options */ +int dflag; /* detached, no stdin */ +int Fflag; /* fdpass sock to stdout */ +unsigned int iflag; /* Interval Flag */ +int kflag; /* More than one connect */ +int lflag; /* Bind to local port */ +int Nflag; /* shutdown() network socket */ +int nflag; /* Don't do name look up */ +char *Pflag; /* Proxy username */ +char *pflag; /* Localport flag */ +int rflag; /* Random ports flag */ +char *sflag; /* Source Address */ +int tflag; /* Telnet Emulation */ +int uflag; /* UDP - Default to TCP */ +int vflag; /* Verbosity */ +int xflag; /* Socks proxy */ +int zflag; /* Port Scan Flag */ +int Dflag; /* sodebug */ +int Iflag; /* TCP receive buffer size */ +int Oflag; /* TCP send buffer size */ +int Sflag; /* TCP MD5 signature option */ +int Tflag = -1; /* IP Type of Service */ +int rtableid = -1; + +int timeout = -1; +int family = AF_UNSPEC; +char *portlist[PORT_MAX+1]; +char *unix_dg_tmp_socket; + +void atelnet(int, unsigned char *, unsigned int); +void build_ports(char *); +void help(void); +int local_listen(char *, char *, struct addrinfo); +void readwrite(int); +void fdpass(int nfd) __attribute__((noreturn)); +int remote_connect(const char *, const char *, struct addrinfo); +int timeout_connect(int, const struct sockaddr *, socklen_t); +int socks_connect(const char *, const char *, struct addrinfo, + const char *, const char *, struct addrinfo, int, const char *); +int udptest(int); +int unix_bind(char *); +int unix_connect(char *); +int unix_listen(char *); +void set_common_sockopts(int); +int map_tos(char *, int *); +void report_connect(const struct sockaddr *, socklen_t); +void usage(int); +ssize_t drainbuf(int, unsigned char *, size_t *); +ssize_t fillbuf(int, unsigned char *, size_t *); + +static void err(int, const char *, ...) __attribute__((format(printf, 2, 3))); +static void errx(int, const char *, ...) __attribute__((format(printf, 2, 3))); +static void warn(const char *, ...) __attribute__((format(printf, 1, 2))); + +static void +err(int r, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: ", strerror(errno)); + vfprintf(stderr, fmt, args); + fputc('\n', stderr); + va_end(args); + exit(r); +} + +static void +errx(int r, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + fputc('\n', stderr); + va_end(args); + exit(r); +} + +static void +warn(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: ", strerror(errno)); + vfprintf(stderr, fmt, args); + fputc('\n', stderr); + va_end(args); +} + +int +main(int argc, char *argv[]) +{ + int ch, s, ret, socksv; + char *host, *uport; + struct addrinfo hints; + struct servent *sv; + socklen_t len; + struct sockaddr_storage cliaddr; + char *proxy = NULL; + const char *errstr, *proxyhost = "", *proxyport = NULL; + struct addrinfo proxyhints; + char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE]; + + ret = 1; + s = 0; + socksv = 5; + host = NULL; + uport = NULL; + sv = NULL; + + while ((ch = getopt(argc, argv, + "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) { + switch (ch) { + case '4': + family = AF_INET; + break; + case '6': + family = AF_INET6; + break; + case 'U': + family = AF_UNIX; + break; + case 'X': + if (strcasecmp(optarg, "connect") == 0) + socksv = -1; /* HTTP proxy CONNECT */ + else if (strcmp(optarg, "4") == 0) + socksv = 4; /* SOCKS v.4 */ + else if (strcmp(optarg, "5") == 0) + socksv = 5; /* SOCKS v.5 */ + else + errx(1, "unsupported proxy protocol"); + break; + case 'd': + dflag = 1; + break; + case 'F': + Fflag = 1; + break; + case 'h': + help(); + break; + case 'i': + iflag = strtonum(optarg, 0, UINT_MAX, &errstr); + if (errstr) + errx(1, "interval %s: %s", errstr, optarg); + break; + case 'k': + kflag = 1; + break; + case 'l': + lflag = 1; + break; + case 'N': + Nflag = 1; + break; + case 'n': + nflag = 1; + break; + case 'P': + Pflag = optarg; + break; + case 'p': + pflag = optarg; + break; + case 'r': + rflag = 1; + break; + case 's': + sflag = optarg; + break; + case 't': + tflag = 1; + break; + case 'u': + uflag = 1; + break; +#ifdef SO_RTABLE + case 'V': + rtableid = (int)strtonum(optarg, 0, + RT_TABLEID_MAX, &errstr); + if (errstr) + errx(1, "rtable %s: %s", errstr, optarg); + break; +#endif + case 'v': + vflag = 1; + break; + case 'w': + timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr); + if (errstr) + errx(1, "timeout %s: %s", errstr, optarg); + timeout *= 1000; + break; + case 'x': + xflag = 1; + if ((proxy = strdup(optarg)) == NULL) + errx(1, "strdup"); + break; + case 'z': + zflag = 1; + break; + case 'D': + Dflag = 1; + break; + case 'I': + Iflag = strtonum(optarg, 1, 65536 << 14, &errstr); + if (errstr != NULL) + errx(1, "TCP receive window %s: %s", + errstr, optarg); + break; + case 'O': + Oflag = strtonum(optarg, 1, 65536 << 14, &errstr); + if (errstr != NULL) + errx(1, "TCP send window %s: %s", + errstr, optarg); + break; + case 'S': + Sflag = 1; + break; + case 'T': + errstr = NULL; + errno = 0; + if (map_tos(optarg, &Tflag)) + break; + if (strlen(optarg) > 1 && optarg[0] == '0' && + optarg[1] == 'x') + Tflag = (int)strtol(optarg, NULL, 16); + else + Tflag = (int)strtonum(optarg, 0, 255, + &errstr); + if (Tflag < 0 || Tflag > 255 || errstr || errno) + errx(1, "illegal tos value %s", optarg); + break; + default: + usage(1); + } + } + argc -= optind; + argv += optind; + + /* Cruft to make sure options are clean, and used properly. */ + if (argv[0] && !argv[1] && family == AF_UNIX) { + host = argv[0]; + uport = NULL; + } else if (argv[0] && !argv[1]) { + if (!lflag) + usage(1); + uport = argv[0]; + host = NULL; + } else if (argv[0] && argv[1]) { + host = argv[0]; + uport = argv[1]; + } else + usage(1); + + if (lflag && sflag) + errx(1, "cannot use -s and -l"); + if (lflag && pflag) + errx(1, "cannot use -p and -l"); + if (lflag && zflag) + errx(1, "cannot use -z and -l"); + if (!lflag && kflag) + errx(1, "must use -l with -k"); + + /* Get name of temporary socket for unix datagram client */ + if ((family == AF_UNIX) && uflag && !lflag) { + if (sflag) { + unix_dg_tmp_socket = sflag; + } else { + strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX", + UNIX_DG_TMP_SOCKET_SIZE); + if (mktemp(unix_dg_tmp_socket_buf) == NULL) + err(1, "mktemp"); + unix_dg_tmp_socket = unix_dg_tmp_socket_buf; + } + } + + /* Initialize addrinfo structure. */ + if (family != AF_UNIX) { + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = family; + hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; + if (nflag) + hints.ai_flags |= AI_NUMERICHOST; + } + + if (xflag) { + if (uflag) + errx(1, "no proxy support for UDP mode"); + + if (lflag) + errx(1, "no proxy support for listen"); + + if (family == AF_UNIX) + errx(1, "no proxy support for unix sockets"); + + /* XXX IPv6 transport to proxy would probably work */ + if (family == AF_INET6) + errx(1, "no proxy support for IPv6"); + + if (sflag) + errx(1, "no proxy support for local source address"); + + proxyhost = strsep(&proxy, ":"); + proxyport = proxy; + + memset(&proxyhints, 0, sizeof(struct addrinfo)); + proxyhints.ai_family = family; + proxyhints.ai_socktype = SOCK_STREAM; + proxyhints.ai_protocol = IPPROTO_TCP; + if (nflag) + proxyhints.ai_flags |= AI_NUMERICHOST; + } + + if (lflag) { + int connfd; + ret = 0; + + if (family == AF_UNIX) { + if (uflag) + s = unix_bind(host); + else + s = unix_listen(host); + } + + /* Allow only one connection at a time, but stay alive. */ + for (;;) { + if (family != AF_UNIX) + s = local_listen(host, uport, hints); + if (s < 0) + err(1, "local_listen"); + /* + * For UDP and -k, don't connect the socket, let it + * receive datagrams from multiple socket pairs. + */ + if (uflag && kflag) + readwrite(s); + /* + * For UDP and not -k, we will use recvfrom() initially + * to wait for a caller, then use the regular functions + * to talk to the caller. + */ + else if (uflag && !kflag) { + int rv, plen; + char buf[16384]; + struct sockaddr_storage z; + + len = sizeof(z); + plen = 2048; + rv = recvfrom(s, buf, plen, MSG_PEEK, + (struct sockaddr *)&z, &len); + if (rv < 0) + err(1, "recvfrom"); + + rv = connect(s, (struct sockaddr *)&z, len); + if (rv < 0) + err(1, "connect"); + + if (vflag) + report_connect((struct sockaddr *)&z, len); + + readwrite(s); + } else { + len = sizeof(cliaddr); + connfd = accept(s, (struct sockaddr *)&cliaddr, + &len); + if (connfd == -1) { + /* For now, all errnos are fatal */ + err(1, "accept"); + } + if (vflag) + report_connect((struct sockaddr *)&cliaddr, len); + + readwrite(connfd); + close(connfd); + } + + if (family != AF_UNIX) + close(s); + else if (uflag) { + if (connect(s, NULL, 0) < 0) + err(1, "connect"); + } + + if (!kflag) + break; + } + } else if (family == AF_UNIX) { + ret = 0; + + if ((s = unix_connect(host)) > 0 && !zflag) { + readwrite(s); + close(s); + } else + ret = 1; + + if (uflag) + unlink(unix_dg_tmp_socket); + exit(ret); + + } else { + int i = 0; + + /* Construct the portlist[] array. */ + build_ports(uport); + + /* Cycle through portlist, connecting to each port. */ + for (i = 0; portlist[i] != NULL; i++) { + if (s) + close(s); + + if (xflag) + s = socks_connect(host, portlist[i], hints, + proxyhost, proxyport, proxyhints, socksv, + Pflag); + else + s = remote_connect(host, portlist[i], hints); + + if (s < 0) + continue; + + ret = 0; + if (vflag || zflag) { + /* For UDP, make sure we are connected. */ + if (uflag) { + if (udptest(s) == -1) { + ret = 1; + continue; + } + } + + /* Don't look up port if -n. */ + if (nflag) + sv = NULL; + else { + sv = getservbyport( + ntohs(atoi(portlist[i])), + uflag ? "udp" : "tcp"); + } + + fprintf(stderr, + "Connection to %s %s port [%s/%s] " + "succeeded!\n", host, portlist[i], + uflag ? "udp" : "tcp", + sv ? sv->s_name : "*"); + } + if (Fflag) + fdpass(s); + else if (!zflag) + readwrite(s); + } + } + + if (s) + close(s); + + exit(ret); +} + +/* + * unix_bind() + * Returns a unix socket bound to the given path + */ +int +unix_bind(char *path) +{ + struct sockaddr_un sun_sa; + int s; + + /* Create unix domain socket. */ + if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM, + 0)) < 0) + return (-1); + + memset(&sun_sa, 0, sizeof(struct sockaddr_un)); + sun_sa.sun_family = AF_UNIX; + + if (strlcpy(sun_sa.sun_path, path, sizeof(sun_sa.sun_path)) >= + sizeof(sun_sa.sun_path)) { + close(s); + errno = ENAMETOOLONG; + return (-1); + } + + if (bind(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) { + close(s); + return (-1); + } + return (s); +} + +/* + * unix_connect() + * Returns a socket connected to a local unix socket. Returns -1 on failure. + */ +int +unix_connect(char *path) +{ + struct sockaddr_un sun_sa; + int s; + + if (uflag) { + if ((s = unix_bind(unix_dg_tmp_socket)) < 0) + return (-1); + } else { + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return (-1); + } + (void)fcntl(s, F_SETFD, FD_CLOEXEC); + + memset(&sun_sa, 0, sizeof(struct sockaddr_un)); + sun_sa.sun_family = AF_UNIX; + + if (strlcpy(sun_sa.sun_path, path, sizeof(sun_sa.sun_path)) >= + sizeof(sun_sa.sun_path)) { + close(s); + errno = ENAMETOOLONG; + return (-1); + } + if (connect(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) { + close(s); + return (-1); + } + return (s); + +} + +/* + * unix_listen() + * Create a unix domain socket, and listen on it. + */ +int +unix_listen(char *path) +{ + int s; + if ((s = unix_bind(path)) < 0) + return (-1); + + if (listen(s, 5) < 0) { + close(s); + return (-1); + } + return (s); +} + +/* + * remote_connect() + * Returns a socket connected to a remote host. Properly binds to a local + * port or source address if needed. Returns -1 on failure. + */ +int +remote_connect(const char *host, const char *port, struct addrinfo hints) +{ + struct addrinfo *res, *res0; + int s, error; +#if defined(SO_RTABLE) || defined(SO_BINDANY) + int on = 1; +#endif + + if ((error = getaddrinfo(host, port, &hints, &res))) + errx(1, "getaddrinfo: %s", gai_strerror(error)); + + res0 = res; + do { + if ((s = socket(res0->ai_family, res0->ai_socktype, + res0->ai_protocol)) < 0) + continue; + +#ifdef SO_RTABLE + if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE, + &rtableid, sizeof(rtableid)) == -1)) + err(1, "setsockopt SO_RTABLE"); +#endif + /* Bind to a local port or source address if specified. */ + if (sflag || pflag) { + struct addrinfo ahints, *ares; + +#ifdef SO_BINDANY + /* try SO_BINDANY, but don't insist */ + setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on)); +#endif + memset(&ahints, 0, sizeof(struct addrinfo)); + ahints.ai_family = res0->ai_family; + ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; + ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; + ahints.ai_flags = AI_PASSIVE; + if ((error = getaddrinfo(sflag, pflag, &ahints, &ares))) + errx(1, "getaddrinfo: %s", gai_strerror(error)); + + if (bind(s, (struct sockaddr *)ares->ai_addr, + ares->ai_addrlen) < 0) + err(1, "bind failed"); + freeaddrinfo(ares); + } + + set_common_sockopts(s); + + if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0) + break; + else if (vflag) + warn("connect to %s port %s (%s) failed", host, port, + uflag ? "udp" : "tcp"); + + close(s); + s = -1; + } while ((res0 = res0->ai_next) != NULL); + + freeaddrinfo(res); + + return (s); +} + +int +timeout_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct pollfd pfd; + socklen_t optlen; + int flags = 0, optval; + int ret; + + if (timeout != -1) { + flags = fcntl(s, F_GETFL, 0); + if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) + err(1, "set non-blocking mode"); + } + + if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) { + pfd.fd = s; + pfd.events = POLLOUT; + if ((ret = poll(&pfd, 1, timeout)) == 1) { + optlen = sizeof(optval); + if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR, + &optval, &optlen)) == 0) { + errno = optval; + ret = optval == 0 ? 0 : -1; + } + } else if (ret == 0) { + errno = ETIMEDOUT; + ret = -1; + } else + err(1, "poll failed"); + } + + if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1) + err(1, "restoring flags"); + + return (ret); +} + +/* + * local_listen() + * Returns a socket listening on a local port, binds to specified source + * address. Returns -1 on failure. + */ +int +local_listen(char *host, char *port, struct addrinfo hints) +{ + struct addrinfo *res, *res0; + int s, ret, x = 1; + int error; + + /* Allow nodename to be null. */ + hints.ai_flags |= AI_PASSIVE; + + /* + * In the case of binding to a wildcard address + * default to binding to an ipv4 address. + */ + if (host == NULL && hints.ai_family == AF_UNSPEC) + hints.ai_family = AF_INET; + + if ((error = getaddrinfo(host, port, &hints, &res))) + errx(1, "getaddrinfo: %s", gai_strerror(error)); + + res0 = res; + do { + if ((s = socket(res0->ai_family, res0->ai_socktype, + res0->ai_protocol)) < 0) + continue; + +#ifdef SO_RTABLE + if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE, + &rtableid, sizeof(rtableid)) == -1)) + err(1, "setsockopt SO_RTABLE"); +#endif +#ifdef SO_REUSEPORT + ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); + if (ret == -1) + err(1, "setsockopt"); +#endif + set_common_sockopts(s); + + if (bind(s, (struct sockaddr *)res0->ai_addr, + res0->ai_addrlen) == 0) + break; + + close(s); + s = -1; + } while ((res0 = res0->ai_next) != NULL); + + if (!uflag && s != -1) { + if (listen(s, 1) < 0) + err(1, "listen"); + } + + freeaddrinfo(res); + + return (s); +} + +/* + * readwrite() + * Loop that polls on the network file descriptor and stdin. + */ +void +readwrite(int net_fd) +{ + struct pollfd pfd[4]; + int stdin_fd = STDIN_FILENO; + int stdout_fd = STDOUT_FILENO; + unsigned char netinbuf[BUFSIZE]; + size_t netinbufpos = 0; + unsigned char stdinbuf[BUFSIZE]; + size_t stdinbufpos = 0; + int n, num_fds; + ssize_t ret; + + /* don't read from stdin if requested */ + if (dflag) + stdin_fd = -1; + + /* stdin */ + pfd[POLL_STDIN].fd = stdin_fd; + pfd[POLL_STDIN].events = POLLIN; + + /* network out */ + pfd[POLL_NETOUT].fd = net_fd; + pfd[POLL_NETOUT].events = 0; + + /* network in */ + pfd[POLL_NETIN].fd = net_fd; + pfd[POLL_NETIN].events = POLLIN; + + /* stdout */ + pfd[POLL_STDOUT].fd = stdout_fd; + pfd[POLL_STDOUT].events = 0; + + while (1) { + /* both inputs are gone, buffers are empty, we are done */ + if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1 + && stdinbufpos == 0 && netinbufpos == 0) { + close(net_fd); + return; + } + /* both outputs are gone, we can't continue */ + if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) { + close(net_fd); + return; + } + /* listen and net in gone, queues empty, done */ + if (lflag && pfd[POLL_NETIN].fd == -1 + && stdinbufpos == 0 && netinbufpos == 0) { + close(net_fd); + return; + } + + /* help says -i is for "wait between lines sent". We read and + * write arbitrary amounts of data, and we don't want to start + * scanning for newlines, so this is as good as it gets */ + if (iflag) + sleep(iflag); + + /* poll */ + num_fds = poll(pfd, 4, timeout); + + /* treat poll errors */ + if (num_fds == -1) { + close(net_fd); + err(1, "polling error"); + } + + /* timeout happened */ + if (num_fds == 0) + return; + + /* treat socket error conditions */ + for (n = 0; n < 4; n++) { + if (pfd[n].revents & (POLLERR|POLLNVAL)) { + pfd[n].fd = -1; + } + } + /* reading is possible after HUP */ + if (pfd[POLL_STDIN].events & POLLIN && + pfd[POLL_STDIN].revents & POLLHUP && + ! (pfd[POLL_STDIN].revents & POLLIN)) + pfd[POLL_STDIN].fd = -1; + + if (pfd[POLL_NETIN].events & POLLIN && + pfd[POLL_NETIN].revents & POLLHUP && + ! (pfd[POLL_NETIN].revents & POLLIN)) + pfd[POLL_NETIN].fd = -1; + + if (pfd[POLL_NETOUT].revents & POLLHUP) { + if (Nflag) + shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); + pfd[POLL_NETOUT].fd = -1; + } + /* if HUP, stop watching stdout */ + if (pfd[POLL_STDOUT].revents & POLLHUP) + pfd[POLL_STDOUT].fd = -1; + /* if no net out, stop watching stdin */ + if (pfd[POLL_NETOUT].fd == -1) + pfd[POLL_STDIN].fd = -1; + /* if no stdout, stop watching net in */ + if (pfd[POLL_STDOUT].fd == -1) { + if (pfd[POLL_NETIN].fd != -1) + shutdown(pfd[POLL_NETIN].fd, SHUT_RD); + pfd[POLL_NETIN].fd = -1; + } + + /* try to read from stdin */ + if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) { + ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf, + &stdinbufpos); + /* error or eof on stdin - remove from pfd */ + if (ret == 0 || ret == -1) + pfd[POLL_STDIN].fd = -1; + /* read something - poll net out */ + if (stdinbufpos > 0) + pfd[POLL_NETOUT].events = POLLOUT; + /* filled buffer - remove self from polling */ + if (stdinbufpos == BUFSIZE) + pfd[POLL_STDIN].events = 0; + } + /* try to write to network */ + if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) { + ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf, + &stdinbufpos); + if (ret == -1) + pfd[POLL_NETOUT].fd = -1; + /* buffer empty - remove self from polling */ + if (stdinbufpos == 0) + pfd[POLL_NETOUT].events = 0; + /* buffer no longer full - poll stdin again */ + if (stdinbufpos < BUFSIZE) + pfd[POLL_STDIN].events = POLLIN; + } + /* try to read from network */ + if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) { + ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf, + &netinbufpos); + if (ret == -1) + pfd[POLL_NETIN].fd = -1; + /* eof on net in - remove from pfd */ + if (ret == 0) { + shutdown(pfd[POLL_NETIN].fd, SHUT_RD); + pfd[POLL_NETIN].fd = -1; + } + /* read something - poll stdout */ + if (netinbufpos > 0) + pfd[POLL_STDOUT].events = POLLOUT; + /* filled buffer - remove self from polling */ + if (netinbufpos == BUFSIZE) + pfd[POLL_NETIN].events = 0; + /* handle telnet */ + if (tflag) + atelnet(pfd[POLL_NETIN].fd, netinbuf, + netinbufpos); + } + /* try to write to stdout */ + if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) { + ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf, + &netinbufpos); + if (ret == -1) + pfd[POLL_STDOUT].fd = -1; + /* buffer empty - remove self from polling */ + if (netinbufpos == 0) + pfd[POLL_STDOUT].events = 0; + /* buffer no longer full - poll net in again */ + if (netinbufpos < BUFSIZE) + pfd[POLL_NETIN].events = POLLIN; + } + + /* stdin gone and queue empty? */ + if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) { + if (pfd[POLL_NETOUT].fd != -1 && Nflag) + shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); + pfd[POLL_NETOUT].fd = -1; + } + /* net in gone and queue empty? */ + if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) { + pfd[POLL_STDOUT].fd = -1; + } + } +} + +ssize_t +drainbuf(int fd, unsigned char *buf, size_t *bufpos) +{ + ssize_t n; + ssize_t adjust; + + n = write(fd, buf, *bufpos); + /* don't treat EAGAIN, EINTR as error */ + if (n == -1 && (errno == EAGAIN || errno == EINTR)) + n = -2; + if (n <= 0) + return n; + /* adjust buffer */ + adjust = *bufpos - n; + if (adjust > 0) + memmove(buf, buf + n, adjust); + *bufpos -= n; + return n; +} + + +ssize_t +fillbuf(int fd, unsigned char *buf, size_t *bufpos) +{ + size_t num = BUFSIZE - *bufpos; + ssize_t n; + + n = read(fd, buf + *bufpos, num); + /* don't treat EAGAIN, EINTR as error */ + if (n == -1 && (errno == EAGAIN || errno == EINTR)) + n = -2; + if (n <= 0) + return n; + *bufpos += n; + return n; +} + +/* + * fdpass() + * Pass the connected file descriptor to stdout and exit. + */ +void +fdpass(int nfd) +{ +#if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) + struct msghdr msg; +#ifndef HAVE_ACCRIGHTS_IN_MSGHDR + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(int))]; + } cmsgbuf; + struct cmsghdr *cmsg; +#endif + struct iovec vec; + char ch = '\0'; + struct pollfd pfd; + ssize_t r; + + memset(&msg, 0, sizeof(msg)); +#ifdef HAVE_ACCRIGHTS_IN_MSGHDR + msg.msg_accrights = (caddr_t)&nfd; + msg.msg_accrightslen = sizeof(nfd); +#else + memset(&cmsgbuf, 0, sizeof(cmsgbuf)); + msg.msg_control = (caddr_t)&cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = nfd; +#endif + + vec.iov_base = &ch; + vec.iov_len = 1; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + + bzero(&pfd, sizeof(pfd)); + pfd.fd = STDOUT_FILENO; + for (;;) { + r = sendmsg(STDOUT_FILENO, &msg, 0); + if (r == -1) { + if (errno == EAGAIN || errno == EINTR) { + pfd.events = POLLOUT; + if (poll(&pfd, 1, -1) == -1) + err(1, "poll"); + continue; + } + err(1, "sendmsg"); + } else if (r == -1) + errx(1, "sendmsg: unexpected return value %zd", r); + else + break; + } + exit(0); +#else + errx(1, "%s: file descriptor passing not supported", __func__); +#endif +} + +/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */ +void +atelnet(int nfd, unsigned char *buf, unsigned int size) +{ + unsigned char *p, *end; + unsigned char obuf[4]; + + if (size < 3) + return; + end = buf + size - 2; + + for (p = buf; p < end; p++) { + if (*p != IAC) + continue; + + obuf[0] = IAC; + p++; + if ((*p == WILL) || (*p == WONT)) + obuf[1] = DONT; + else if ((*p == DO) || (*p == DONT)) + obuf[1] = WONT; + else + continue; + + p++; + obuf[2] = *p; + if (atomicio(vwrite, nfd, obuf, 3) != 3) + warn("Write Error!"); + } +} + +/* + * build_ports() + * Build an array of ports in portlist[], listing each port + * that we should try to connect to. + */ +void +build_ports(char *p) +{ + const char *errstr; + char *n; + int hi, lo, cp; + int x = 0; + + if ((n = strchr(p, '-')) != NULL) { + *n = '\0'; + n++; + + /* Make sure the ports are in order: lowest->highest. */ + hi = strtonum(n, 1, PORT_MAX, &errstr); + if (errstr) + errx(1, "port number %s: %s", errstr, n); + lo = strtonum(p, 1, PORT_MAX, &errstr); + if (errstr) + errx(1, "port number %s: %s", errstr, p); + + if (lo > hi) { + cp = hi; + hi = lo; + lo = cp; + } + + /* Load ports sequentially. */ + for (cp = lo; cp <= hi; cp++) { + portlist[x] = calloc(1, PORT_MAX_LEN); + if (portlist[x] == NULL) + errx(1, "calloc"); + snprintf(portlist[x], PORT_MAX_LEN, "%d", cp); + x++; + } + + /* Randomly swap ports. */ + if (rflag) { + int y; + char *c; + + for (x = 0; x <= (hi - lo); x++) { + y = (arc4random() & 0xFFFF) % (hi - lo); + c = portlist[x]; + portlist[x] = portlist[y]; + portlist[y] = c; + } + } + } else { + hi = strtonum(p, 1, PORT_MAX, &errstr); + if (errstr) + errx(1, "port number %s: %s", errstr, p); + portlist[0] = strdup(p); + if (portlist[0] == NULL) + errx(1, "strdup"); + } +} + +/* + * udptest() + * Do a few writes to see if the UDP port is there. + * Fails once PF state table is full. + */ +int +udptest(int s) +{ + int i, ret; + + for (i = 0; i <= 3; i++) { + if (write(s, "X", 1) == 1) + ret = 1; + else + ret = -1; + } + return (ret); +} + +void +set_common_sockopts(int s) +{ + int x = 1; + +#ifdef TCP_MD5SIG + if (Sflag) { + if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, + &x, sizeof(x)) == -1) + err(1, "setsockopt"); + } +#endif + if (Dflag) { + if (setsockopt(s, SOL_SOCKET, SO_DEBUG, + &x, sizeof(x)) == -1) + err(1, "setsockopt"); + } + if (Tflag != -1) { + if (setsockopt(s, IPPROTO_IP, IP_TOS, + &Tflag, sizeof(Tflag)) == -1) + err(1, "set IP ToS"); + } + if (Iflag) { + if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, + &Iflag, sizeof(Iflag)) == -1) + err(1, "set TCP receive buffer size"); + } + if (Oflag) { + if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, + &Oflag, sizeof(Oflag)) == -1) + err(1, "set TCP send buffer size"); + } +} + +int +map_tos(char *s, int *val) +{ + /* DiffServ Codepoints and other TOS mappings */ + const struct toskeywords { + const char *keyword; + int val; + } *t, toskeywords[] = { + { "af11", IPTOS_DSCP_AF11 }, + { "af12", IPTOS_DSCP_AF12 }, + { "af13", IPTOS_DSCP_AF13 }, + { "af21", IPTOS_DSCP_AF21 }, + { "af22", IPTOS_DSCP_AF22 }, + { "af23", IPTOS_DSCP_AF23 }, + { "af31", IPTOS_DSCP_AF31 }, + { "af32", IPTOS_DSCP_AF32 }, + { "af33", IPTOS_DSCP_AF33 }, + { "af41", IPTOS_DSCP_AF41 }, + { "af42", IPTOS_DSCP_AF42 }, + { "af43", IPTOS_DSCP_AF43 }, + { "critical", IPTOS_PREC_CRITIC_ECP }, + { "cs0", IPTOS_DSCP_CS0 }, + { "cs1", IPTOS_DSCP_CS1 }, + { "cs2", IPTOS_DSCP_CS2 }, + { "cs3", IPTOS_DSCP_CS3 }, + { "cs4", IPTOS_DSCP_CS4 }, + { "cs5", IPTOS_DSCP_CS5 }, + { "cs6", IPTOS_DSCP_CS6 }, + { "cs7", IPTOS_DSCP_CS7 }, + { "ef", IPTOS_DSCP_EF }, + { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, + { "lowdelay", IPTOS_LOWDELAY }, + { "netcontrol", IPTOS_PREC_NETCONTROL }, + { "reliability", IPTOS_RELIABILITY }, + { "throughput", IPTOS_THROUGHPUT }, + { NULL, -1 }, + }; + + for (t = toskeywords; t->keyword != NULL; t++) { + if (strcmp(s, t->keyword) == 0) { + *val = t->val; + return (1); + } + } + + return (0); +} + +void +report_connect(const struct sockaddr *sa, socklen_t salen) +{ + char remote_host[NI_MAXHOST]; + char remote_port[NI_MAXSERV]; + int herr; + int flags = NI_NUMERICSERV; + + if (nflag) + flags |= NI_NUMERICHOST; + + if ((herr = getnameinfo(sa, salen, + remote_host, sizeof(remote_host), + remote_port, sizeof(remote_port), + flags)) != 0) { + if (herr == EAI_SYSTEM) + err(1, "getnameinfo"); + else + errx(1, "getnameinfo: %s", gai_strerror(herr)); + } + + fprintf(stderr, + "Connection from %s %s " + "received!\n", remote_host, remote_port); +} + +void +help(void) +{ + usage(0); + fprintf(stderr, "\tCommand Summary:\n\ + \t-4 Use IPv4\n\ + \t-6 Use IPv6\n\ + \t-D Enable the debug socket option\n\ + \t-d Detach from stdin\n\ + \t-F Pass socket fd\n\ + \t-h This help text\n\ + \t-I length TCP receive buffer length\n\ + \t-i secs\t Delay interval for lines sent, ports scanned\n\ + \t-k Keep inbound sockets open for multiple connects\n\ + \t-l Listen mode, for inbound connects\n\ + \t-N Shutdown the network socket after EOF on stdin\n\ + \t-n Suppress name/port resolutions\n\ + \t-O length TCP send buffer length\n\ + \t-P proxyuser\tUsername for proxy authentication\n\ + \t-p port\t Specify local port for remote connects\n\ + \t-r Randomize remote ports\n\ + \t-S Enable the TCP MD5 signature option\n\ + \t-s addr\t Local source address\n\ + \t-T toskeyword\tSet IP Type of Service\n\ + \t-t Answer TELNET negotiation\n\ + \t-U Use UNIX domain socket\n\ + \t-u UDP mode\n\ + \t-V rtable Specify alternate routing table\n\ + \t-v Verbose\n\ + \t-w secs\t Timeout for connects and final net reads\n\ + \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ + \t-x addr[:port]\tSpecify proxy address and port\n\ + \t-z Zero-I/O mode [used for scanning]\n\ + Port numbers can be individual or ranges: lo-hi [inclusive]\n"); + exit(1); +} + +void +usage(int ret) +{ + fprintf(stderr, + "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n" + "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n" + "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" + "\t [-x proxy_address[:port]] [destination] [port]\n"); + if (ret) + exit(1); +} + +/* *** src/usr.bin/nc/socks.c *** */ + + +/* $OpenBSD: socks.c,v 1.20 2012/03/08 09:56:28 espie Exp $ */ + +/* + * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. + * Copyright (c) 2004, 2005 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define SOCKS_PORT "1080" +#define HTTP_PROXY_PORT "3128" +#define HTTP_MAXHDRS 64 +#define SOCKS_V5 5 +#define SOCKS_V4 4 +#define SOCKS_NOAUTH 0 +#define SOCKS_NOMETHOD 0xff +#define SOCKS_CONNECT 1 +#define SOCKS_IPV4 1 +#define SOCKS_DOMAIN 3 +#define SOCKS_IPV6 4 + +int remote_connect(const char *, const char *, struct addrinfo); +int socks_connect(const char *, const char *, struct addrinfo, + const char *, const char *, struct addrinfo, int, + const char *); + +static int +decode_addrport(const char *h, const char *p, struct sockaddr *addr, + socklen_t addrlen, int v4only, int numeric) +{ + int r; + struct addrinfo hints, *res; + + bzero(&hints, sizeof(hints)); + hints.ai_family = v4only ? PF_INET : PF_UNSPEC; + hints.ai_flags = numeric ? AI_NUMERICHOST : 0; + hints.ai_socktype = SOCK_STREAM; + r = getaddrinfo(h, p, &hints, &res); + /* Don't fatal when attempting to convert a numeric address */ + if (r != 0) { + if (!numeric) { + errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p, + gai_strerror(r)); + } + return (-1); + } + if (addrlen < res->ai_addrlen) { + freeaddrinfo(res); + errx(1, "internal error: addrlen < res->ai_addrlen"); + } + memcpy(addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + return (0); +} + +static int +proxy_read_line(int fd, char *buf, size_t bufsz) +{ + size_t off; + + for(off = 0;;) { + if (off >= bufsz) + errx(1, "proxy read too long"); + if (atomicio(read, fd, buf + off, 1) != 1) + err(1, "proxy read"); + /* Skip CR */ + if (buf[off] == '\r') + continue; + if (buf[off] == '\n') { + buf[off] = '\0'; + break; + } + off++; + } + return (off); +} + +static const char * +getproxypass(const char *proxyuser, const char *proxyhost) +{ + char prompt[512]; + static char pw[256]; + + snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ", + proxyuser, proxyhost); + if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL) + errx(1, "Unable to read proxy passphrase"); + return (pw); +} + +int +socks_connect(const char *host, const char *port, + struct addrinfo hints __attribute__ ((__unused__)), + const char *proxyhost, const char *proxyport, struct addrinfo proxyhints, + int socksv, const char *proxyuser) +{ + int proxyfd, r, authretry = 0; + size_t hlen, wlen = 0; + unsigned char buf[1024]; + size_t cnt; + struct sockaddr_storage addr; + struct sockaddr_in *in4 = (struct sockaddr_in *)&addr; + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr; + in_port_t serverport; + const char *proxypass = NULL; + + if (proxyport == NULL) + proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT; + + /* Abuse API to lookup port */ + if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr, + sizeof(addr), 1, 1) == -1) + errx(1, "unknown port \"%.64s\"", port); + serverport = in4->sin_port; + + again: + if (authretry++ > 3) + errx(1, "Too many authentication failures"); + + proxyfd = remote_connect(proxyhost, proxyport, proxyhints); + + if (proxyfd < 0) + return (-1); + + if (socksv == 5) { + if (decode_addrport(host, port, (struct sockaddr *)&addr, + sizeof(addr), 0, 1) == -1) + addr.ss_family = 0; /* used in switch below */ + + /* Version 5, one method: no authentication */ + buf[0] = SOCKS_V5; + buf[1] = 1; + buf[2] = SOCKS_NOAUTH; + cnt = atomicio(vwrite, proxyfd, buf, 3); + if (cnt != 3) + err(1, "write failed (%zu/3)", cnt); + + cnt = atomicio(read, proxyfd, buf, 2); + if (cnt != 2) + err(1, "read failed (%zu/3)", cnt); + + if (buf[1] == SOCKS_NOMETHOD) + errx(1, "authentication method negotiation failed"); + + switch (addr.ss_family) { + case 0: + /* Version 5, connect: domain name */ + + /* Max domain name length is 255 bytes */ + hlen = strlen(host); + if (hlen > 255) + errx(1, "host name too long for SOCKS5"); + buf[0] = SOCKS_V5; + buf[1] = SOCKS_CONNECT; + buf[2] = 0; + buf[3] = SOCKS_DOMAIN; + buf[4] = hlen; + memcpy(buf + 5, host, hlen); + memcpy(buf + 5 + hlen, &serverport, sizeof serverport); + wlen = 7 + hlen; + break; + case AF_INET: + /* Version 5, connect: IPv4 address */ + buf[0] = SOCKS_V5; + buf[1] = SOCKS_CONNECT; + buf[2] = 0; + buf[3] = SOCKS_IPV4; + memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); + memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port); + wlen = 10; + break; + case AF_INET6: + /* Version 5, connect: IPv6 address */ + buf[0] = SOCKS_V5; + buf[1] = SOCKS_CONNECT; + buf[2] = 0; + buf[3] = SOCKS_IPV6; + memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr); + memcpy(buf + 20, &in6->sin6_port, + sizeof in6->sin6_port); + wlen = 22; + break; + default: + errx(1, "internal error: silly AF"); + } + + cnt = atomicio(vwrite, proxyfd, buf, wlen); + if (cnt != wlen) + err(1, "write failed (%zu/%zu)", cnt, wlen); + + cnt = atomicio(read, proxyfd, buf, 4); + if (cnt != 4) + err(1, "read failed (%zu/4)", cnt); + if (buf[1] != 0) + errx(1, "connection failed, SOCKS error %d", buf[1]); + switch (buf[3]) { + case SOCKS_IPV4: + cnt = atomicio(read, proxyfd, buf + 4, 6); + if (cnt != 6) + err(1, "read failed (%zu/6)", cnt); + break; + case SOCKS_IPV6: + cnt = atomicio(read, proxyfd, buf + 4, 18); + if (cnt != 18) + err(1, "read failed (%zu/18)", cnt); + break; + default: + errx(1, "connection failed, unsupported address type"); + } + } else if (socksv == 4) { + /* This will exit on lookup failure */ + decode_addrport(host, port, (struct sockaddr *)&addr, + sizeof(addr), 1, 0); + + /* Version 4 */ + buf[0] = SOCKS_V4; + buf[1] = SOCKS_CONNECT; /* connect */ + memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port); + memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); + buf[8] = 0; /* empty username */ + wlen = 9; + + cnt = atomicio(vwrite, proxyfd, buf, wlen); + if (cnt != wlen) + err(1, "write failed (%zu/%zu)", cnt, wlen); + + cnt = atomicio(read, proxyfd, buf, 8); + if (cnt != 8) + err(1, "read failed (%zu/8)", cnt); + if (buf[1] != 90) + errx(1, "connection failed, SOCKS error %d", buf[1]); + } else if (socksv == -1) { + /* HTTP proxy CONNECT */ + + /* Disallow bad chars in hostname */ + if (strcspn(host, "\r\n\t []:") != strlen(host)) + errx(1, "Invalid hostname"); + + /* Try to be sane about numeric IPv6 addresses */ + if (strchr(host, ':') != NULL) { + r = snprintf(buf, sizeof(buf), + "CONNECT [%s]:%d HTTP/1.0\r\n", + host, ntohs(serverport)); + } else { + r = snprintf(buf, sizeof(buf), + "CONNECT %s:%d HTTP/1.0\r\n", + host, ntohs(serverport)); + } + if (r == -1 || (size_t)r >= sizeof(buf)) + errx(1, "hostname too long"); + r = strlen(buf); + + cnt = atomicio(vwrite, proxyfd, buf, r); + if (cnt != (size_t)r) + err(1, "write failed (%zu/%d)", cnt, r); + + if (authretry > 1) { + char resp[1024]; + + proxypass = getproxypass(proxyuser, proxyhost); + r = snprintf(buf, sizeof(buf), "%s:%s", + proxyuser, proxypass); + if (r == -1 || (size_t)r >= sizeof(buf) || + b64_ntop(buf, strlen(buf), resp, + sizeof(resp)) == -1) + errx(1, "Proxy username/password too long"); + r = snprintf(buf, sizeof(buf), "Proxy-Authorization: " + "Basic %s\r\n", resp); + if (r == -1 || (size_t)r >= sizeof(buf)) + errx(1, "Proxy auth response too long"); + r = strlen(buf); + if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != (size_t)r) + err(1, "write failed (%zu/%d)", cnt, r); + } + + /* Terminate headers */ + if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2) + err(1, "write failed (2/%d)", r); + + /* Read status reply */ + proxy_read_line(proxyfd, buf, sizeof(buf)); + if (proxyuser != NULL && + strncmp(buf, "HTTP/1.0 407 ", 12) == 0) { + if (authretry > 1) { + fprintf(stderr, "Proxy authentication " + "failed\n"); + } + close(proxyfd); + goto again; + } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 && + strncmp(buf, "HTTP/1.1 200 ", 12) != 0) + errx(1, "Proxy error: \"%s\"", buf); + + /* Headers continue until we hit an empty line */ + for (r = 0; r < HTTP_MAXHDRS; r++) { + proxy_read_line(proxyfd, buf, sizeof(buf)); + if (*buf == '\0') + break; + } + if (*buf != '\0') + errx(1, "Too many proxy headers received"); + } else + errx(1, "Unknown proxy protocol %d", socksv); + + return (proxyfd); +} + diff --git a/crypto/openssh/regress/principals-command.sh b/crypto/openssh/regress/principals-command.sh new file mode 100755 index 0000000..b90a8cf --- /dev/null +++ b/crypto/openssh/regress/principals-command.sh @@ -0,0 +1,145 @@ +# $OpenBSD: principals-command.sh,v 1.1 2015/05/21 06:44:25 djm Exp $ +# Placed in the Public Domain. + +tid="authorized principals command" + +rm -f $OBJ/user_ca_key* $OBJ/cert_user_key* +cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak + +if test -z "$SUDO" ; then + echo "skipped (SUDO not set)" + echo "need SUDO to create file in /var/run, test won't work without" + exit 0 +fi + +# Establish a AuthorizedPrincipalsCommand in /var/run where it will have +# acceptable directory permissions. +PRINCIPALS_CMD="/var/run/principals_command_${LOGNAME}" +cat << _EOF | $SUDO sh -c "cat > '$PRINCIPALS_CMD'" +#!/bin/sh +test "x\$1" != "x${LOGNAME}" && exit 1 +test -f "$OBJ/authorized_principals_${LOGNAME}" && + exec cat "$OBJ/authorized_principals_${LOGNAME}" +_EOF +test $? -eq 0 || fatal "couldn't prepare principals command" +$SUDO chmod 0755 "$PRINCIPALS_CMD" + +# Create a CA key and a user certificate. +${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key || \ + fatal "ssh-keygen of user_ca_key failed" +${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/cert_user_key || \ + fatal "ssh-keygen of cert_user_key failed" +${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \ + -z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key || \ + fatal "couldn't sign cert_user_key" + +if [ -x $PRINCIPALS_CMD ]; then + # Test explicitly-specified principals + for privsep in yes no ; do + _prefix="privsep $privsep" + + # Setup for AuthorizedPrincipalsCommand + rm -f $OBJ/authorized_keys_$USER + ( + cat $OBJ/sshd_proxy_bak + echo "UsePrivilegeSeparation $privsep" + echo "AuthorizedKeysFile none" + echo "AuthorizedPrincipalsCommand $PRINCIPALS_CMD %u" + echo "AuthorizedPrincipalsCommandUser ${LOGNAME}" + echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" + ) > $OBJ/sshd_proxy + + # XXX test missing command + # XXX test failing command + + # Empty authorized_principals + verbose "$tid: ${_prefix} empty authorized_principals" + echo > $OBJ/authorized_principals_$USER + ${SSH} -2i $OBJ/cert_user_key \ + -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 + if [ $? -eq 0 ]; then + fail "ssh cert connect succeeded unexpectedly" + fi + + # Wrong authorized_principals + verbose "$tid: ${_prefix} wrong authorized_principals" + echo gregorsamsa > $OBJ/authorized_principals_$USER + ${SSH} -2i $OBJ/cert_user_key \ + -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 + if [ $? -eq 0 ]; then + fail "ssh cert connect succeeded unexpectedly" + fi + + # Correct authorized_principals + verbose "$tid: ${_prefix} correct authorized_principals" + echo mekmitasdigoat > $OBJ/authorized_principals_$USER + ${SSH} -2i $OBJ/cert_user_key \ + -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh cert connect failed" + fi + + # authorized_principals with bad key option + verbose "$tid: ${_prefix} authorized_principals bad key opt" + echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER + ${SSH} -2i $OBJ/cert_user_key \ + -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 + if [ $? -eq 0 ]; then + fail "ssh cert connect succeeded unexpectedly" + fi + + # authorized_principals with command=false + verbose "$tid: ${_prefix} authorized_principals command=false" + echo 'command="false" mekmitasdigoat' > \ + $OBJ/authorized_principals_$USER + ${SSH} -2i $OBJ/cert_user_key \ + -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 + if [ $? -eq 0 ]; then + fail "ssh cert connect succeeded unexpectedly" + fi + + # authorized_principals with command=true + verbose "$tid: ${_prefix} authorized_principals command=true" + echo 'command="true" mekmitasdigoat' > \ + $OBJ/authorized_principals_$USER + ${SSH} -2i $OBJ/cert_user_key \ + -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh cert connect failed" + fi + + # Setup for principals= key option + rm -f $OBJ/authorized_principals_$USER + ( + cat $OBJ/sshd_proxy_bak + echo "UsePrivilegeSeparation $privsep" + ) > $OBJ/sshd_proxy + + # Wrong principals list + verbose "$tid: ${_prefix} wrong principals key option" + ( + printf 'cert-authority,principals="gregorsamsa" ' + cat $OBJ/user_ca_key.pub + ) > $OBJ/authorized_keys_$USER + ${SSH} -2i $OBJ/cert_user_key \ + -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 + if [ $? -eq 0 ]; then + fail "ssh cert connect succeeded unexpectedly" + fi + + # Correct principals list + verbose "$tid: ${_prefix} correct principals key option" + ( + printf 'cert-authority,principals="mekmitasdigoat" ' + cat $OBJ/user_ca_key.pub + ) > $OBJ/authorized_keys_$USER + ${SSH} -2i $OBJ/cert_user_key \ + -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh cert connect failed" + fi + done +else + echo "SKIPPED: $PRINCIPALS_COMMAND not executable " \ + "(/var/run mounted noexec?)" +fi diff --git a/crypto/openssh/regress/proto-mismatch.sh b/crypto/openssh/regress/proto-mismatch.sh index fb521f2..9e8024b 100644 --- a/crypto/openssh/regress/proto-mismatch.sh +++ b/crypto/openssh/regress/proto-mismatch.sh @@ -1,4 +1,4 @@ -# $OpenBSD: proto-mismatch.sh,v 1.3 2002/03/15 13:08:56 markus Exp $ +# $OpenBSD: proto-mismatch.sh,v 1.4 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="protocol version mismatch" @@ -16,4 +16,6 @@ mismatch () } mismatch 2 SSH-1.5-HALLO -mismatch 1 SSH-2.0-HALLO +if ssh_version 1; then + mismatch 1 SSH-2.0-HALLO +fi diff --git a/crypto/openssh/regress/proto-version.sh b/crypto/openssh/regress/proto-version.sh index b876dd7..cf49461 100644 --- a/crypto/openssh/regress/proto-version.sh +++ b/crypto/openssh/regress/proto-version.sh @@ -1,4 +1,4 @@ -# $OpenBSD: proto-version.sh,v 1.4 2013/05/17 00:37:40 dtucker Exp $ +# $OpenBSD: proto-version.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="sshd version with different protocol combinations" @@ -28,7 +28,9 @@ check_version () fi } -check_version 2,1 199 -check_version 1,2 199 check_version 2 20 -check_version 1 15 +if ssh_version 1; then + check_version 2,1 199 + check_version 1,2 199 + check_version 1 15 +fi diff --git a/crypto/openssh/regress/proxy-connect.sh b/crypto/openssh/regress/proxy-connect.sh index 76e602d..f816962 100644 --- a/crypto/openssh/regress/proxy-connect.sh +++ b/crypto/openssh/regress/proxy-connect.sh @@ -1,26 +1,31 @@ -# $OpenBSD: proxy-connect.sh,v 1.6 2013/03/07 00:20:34 djm Exp $ +# $OpenBSD: proxy-connect.sh,v 1.8 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="proxy connect" -verbose "plain username" -for p in 1 2; do - ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true - if [ $? -ne 0 ]; then - fail "ssh proxyconnect protocol $p failed" - fi - SSH_CONNECTION=`${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 'echo $SSH_CONNECTION'` +mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig + +for ps in no yes; do + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy + + for p in ${SSH_PROTOCOLS}; do + for c in no yes; do + verbose "plain username protocol $p privsep=$ps comp=$c" + opts="-$p -oCompression=$c -F $OBJ/ssh_proxy" + SSH_CONNECTION=`${SSH} $opts 999.999.999.999 'echo $SSH_CONNECTION'` if [ $? -ne 0 ]; then - fail "ssh proxyconnect protocol $p failed" + fail "ssh proxyconnect protocol $p privsep=$ps comp=$c failed" fi if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then - fail "bad SSH_CONNECTION" + fail "bad SSH_CONNECTION protocol $p privsep=$ps comp=$c" fi + done + done done -verbose "username with style" -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do + verbose "username with style protocol $p" ${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \ fail "ssh proxyconnect protocol $p failed" done - diff --git a/crypto/openssh/regress/reconfigure.sh b/crypto/openssh/regress/reconfigure.sh index 9fd2895..eecddd3 100644 --- a/crypto/openssh/regress/reconfigure.sh +++ b/crypto/openssh/regress/reconfigure.sh @@ -1,20 +1,30 @@ -# $OpenBSD: reconfigure.sh,v 1.2 2003/06/21 09:14:05 markus Exp $ +# $OpenBSD: reconfigure.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="simple connect after reconfigure" # we need the full path to sshd for -HUP -case $SSHD in -/*) - # full path is OK - ;; -*) - # otherwise make fully qualified - SSHD=$OBJ/$SSHD -esac +if test "x$USE_VALGRIND" = "x" ; then + case $SSHD in + /*) + # full path is OK + ;; + *) + # otherwise make fully qualified + SSHD=$OBJ/$SSHD + esac +fi start_sshd +trace "connect before restart" +for p in ${SSH_PROTOCOLS} ; do + ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true + if [ $? -ne 0 ]; then + fail "ssh connect with protocol $p failed before reconfigure" + fi +done + PID=`$SUDO cat $PIDFILE` rm -f $PIDFILE $SUDO kill -HUP $PID @@ -28,7 +38,8 @@ done test -f $PIDFILE || fatal "sshd did not restart" -for p in 1 2; do +trace "connect after restart" +for p in ${SSH_PROTOCOLS} ; do ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true if [ $? -ne 0 ]; then fail "ssh connect with protocol $p failed after reconfigure" diff --git a/crypto/openssh/regress/reexec.sh b/crypto/openssh/regress/reexec.sh index 433573f..5c0a7b4 100644 --- a/crypto/openssh/regress/reexec.sh +++ b/crypto/openssh/regress/reexec.sh @@ -1,4 +1,4 @@ -# $OpenBSD: reexec.sh,v 1.7 2013/05/17 10:23:52 dtucker Exp $ +# $OpenBSD: reexec.sh,v 1.8 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="reexec tests" @@ -19,7 +19,7 @@ start_sshd_copy () copy_tests () { rm -f ${COPY} - for p in 1 2; do + for p in ${SSH_PROTOCOLS} ; do verbose "$tid: proto $p" ${SSH} -nqo "Protocol=$p" -F $OBJ/ssh_config somehost \ cat ${DATA} > ${COPY} diff --git a/crypto/openssh/regress/rekey.sh b/crypto/openssh/regress/rekey.sh index cf9401e..0d4444d 100644 --- a/crypto/openssh/regress/rekey.sh +++ b/crypto/openssh/regress/rekey.sh @@ -1,4 +1,4 @@ -# $OpenBSD: rekey.sh,v 1.14 2013/11/21 03:18:51 djm Exp $ +# $OpenBSD: rekey.sh,v 1.16 2015/02/14 12:43:16 markus Exp $ # Placed in the Public Domain. tid="rekey" @@ -6,14 +6,22 @@ tid="rekey" LOG=${TEST_SSH_LOGFILE} rm -f ${LOG} +cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak # Test rekeying based on data volume only. # Arguments will be passed to ssh. ssh_data_rekeying() { + _kexopt=$1 ; shift + _opts="$@" + if ! test -z "$_kexopts" ; then + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy + echo "$_kexopt" >> $OBJ/sshd_proxy + _opts="$_opts -o$_kexopt" + fi rm -f ${COPY} ${LOG} - ${SSH} <${DATA} -oCompression=no $@ -v -F $OBJ/ssh_proxy somehost \ - "cat > ${COPY}" + _opts="$_opts -oCompression=no" + ${SSH} <${DATA} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}" if [ $? -ne 0 ]; then fail "ssh failed ($@)" fi @@ -41,7 +49,7 @@ done for opt in $opts; do verbose "client rekey $opt" - ssh_data_rekeying -oRekeyLimit=256k -o$opt + ssh_data_rekeying "$opt" -oRekeyLimit=256k done # AEAD ciphers are magical so test with all KexAlgorithms @@ -49,14 +57,14 @@ if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then for c in `${SSH} -Q cipher-auth`; do for kex in `${SSH} -Q kex`; do verbose "client rekey $c $kex" - ssh_data_rekeying -oRekeyLimit=256k -oCiphers=$c -oKexAlgorithms=$kex + ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c done done fi for s in 16 1k 128k 256k; do verbose "client rekeylimit ${s}" - ssh_data_rekeying -oCompression=no -oRekeyLimit=$s + ssh_data_rekeying "" -oCompression=no -oRekeyLimit=$s done for s in 5 10; do @@ -92,9 +100,29 @@ for s in 5 10; do fi done -echo "rekeylimit default 5" >>$OBJ/sshd_proxy +for s in 16 1k 128k 256k; do + verbose "server rekeylimit ${s}" + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy + echo "rekeylimit ${s}" >>$OBJ/sshd_proxy + rm -f ${COPY} ${LOG} + ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "cat ${DATA}" \ + > ${COPY} + if [ $? -ne 0 ]; then + fail "ssh failed" + fi + cmp ${DATA} ${COPY} || fail "corrupted copy" + n=`grep 'NEWKEYS sent' ${LOG} | wc -l` + n=`expr $n - 1` + trace "$n rekeying(s)" + if [ $n -lt 1 ]; then + fail "no rekeying occured" + fi +done + for s in 5 10; do verbose "server rekeylimit default ${s} no data" + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy + echo "rekeylimit default ${s}" >>$OBJ/sshd_proxy rm -f ${COPY} ${LOG} ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "sleep $s;sleep 3" if [ $? -ne 0 ]; then diff --git a/crypto/openssh/regress/ssh-com.sh b/crypto/openssh/regress/ssh-com.sh index 6c5cfe8..4371d52 100644 --- a/crypto/openssh/regress/ssh-com.sh +++ b/crypto/openssh/regress/ssh-com.sh @@ -1,4 +1,4 @@ -# $OpenBSD: ssh-com.sh,v 1.8 2013/05/17 00:37:40 dtucker Exp $ +# $OpenBSD: ssh-com.sh,v 1.9 2015/05/08 07:29:00 djm Exp $ # Placed in the Public Domain. tid="connect to ssh.com server" @@ -44,14 +44,14 @@ cat << EOF > $OBJ/sshd2_config HostKeyFile ${SRC}/dsa_ssh2.prv PublicHostKeyFile ${SRC}/dsa_ssh2.pub RandomSeedFile ${OBJ}/random_seed - MaxConnections 0 + MaxConnections 0 PermitRootLogin yes VerboseMode no CheckMail no Ssh1Compatibility no EOF -# create client config +# create client config sed "s/HostKeyAlias.*/HostKeyAlias ssh2-localhost-with-alias/" \ < $OBJ/ssh_config > $OBJ/ssh_config_com diff --git a/crypto/openssh/regress/ssh2putty.sh b/crypto/openssh/regress/ssh2putty.sh index 691db16..bcf83af 100755 --- a/crypto/openssh/regress/ssh2putty.sh +++ b/crypto/openssh/regress/ssh2putty.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: ssh2putty.sh,v 1.2 2009/10/06 23:51:49 dtucker Exp $ +# $OpenBSD: ssh2putty.sh,v 1.3 2015/05/08 07:26:13 djm Exp $ if test "x$1" = "x" -o "x$2" = "x" -o "x$3" = "x" ; then echo "Usage: ssh2putty hostname port ssh-private-key" @@ -19,13 +19,13 @@ else fi public_exponent=` - openssl rsa -noout -text -in $KEYFILE | grep ^publicExponent | + openssl rsa -noout -text -in $KEYFILE | grep ^publicExponent | sed 's/.*(//;s/).*//' ` test $? -ne 0 && exit 1 modulus=` - openssl rsa -noout -modulus -in $KEYFILE | grep ^Modulus= | + openssl rsa -noout -modulus -in $KEYFILE | grep ^Modulus= | sed 's/^Modulus=/0x/' | tr A-Z a-z ` test $? -ne 0 && exit 1 diff --git a/crypto/openssh/regress/sshd-log-wrapper.sh b/crypto/openssh/regress/sshd-log-wrapper.sh index a9386be..c00934c 100644 --- a/crypto/openssh/regress/sshd-log-wrapper.sh +++ b/crypto/openssh/regress/sshd-log-wrapper.sh @@ -3,11 +3,9 @@ # Placed in the Public Domain. # # simple wrapper for sshd proxy mode to catch stderr output -# sh sshd-log-wrapper.sh /path/to/sshd /path/to/logfile +# sh sshd-log-wrapper.sh /path/to/logfile /path/to/sshd [args...] -sshd=$1 -log=$2 -shift +log=$1 shift -exec $sshd -E$log $@ +exec "$@" -E$log diff --git a/crypto/openssh/regress/stderr-data.sh b/crypto/openssh/regress/stderr-data.sh index b0bd235..8c8149a 100644 --- a/crypto/openssh/regress/stderr-data.sh +++ b/crypto/openssh/regress/stderr-data.sh @@ -1,10 +1,10 @@ -# $OpenBSD: stderr-data.sh,v 1.3 2013/05/17 04:29:14 dtucker Exp $ +# $OpenBSD: stderr-data.sh,v 1.4 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="stderr data transfer" for n in '' -n; do -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do verbose "test $tid: proto $p ($n)" ${SSH} $n -$p -F $OBJ/ssh_proxy otherhost \ exec sh -c \'"exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \ diff --git a/crypto/openssh/regress/t11.ok b/crypto/openssh/regress/t11.ok new file mode 100644 index 0000000..1925bb4 --- /dev/null +++ b/crypto/openssh/regress/t11.ok @@ -0,0 +1 @@ +SHA256:4w1rnrek3klTJOTVhwuCIFd5k+pq9Bfo5KTxxb8BqbY diff --git a/crypto/openssh/regress/t4.ok b/crypto/openssh/regress/t4.ok index 8c4942b..4631ea8 100644 --- a/crypto/openssh/regress/t4.ok +++ b/crypto/openssh/regress/t4.ok @@ -1 +1 @@ -3b:dd:44:e9:49:18:84:95:f1:e7:33:6b:9d:93:b1:36 +MD5:3b:dd:44:e9:49:18:84:95:f1:e7:33:6b:9d:93:b1:36 diff --git a/crypto/openssh/regress/test-exec.sh b/crypto/openssh/regress/test-exec.sh index aac8aa5..114e129 100644 --- a/crypto/openssh/regress/test-exec.sh +++ b/crypto/openssh/regress/test-exec.sh @@ -1,4 +1,4 @@ -# $OpenBSD: test-exec.sh,v 1.47 2013/11/09 05:41:34 dtucker Exp $ +# $OpenBSD: test-exec.sh,v 1.51 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. #SUDO=sudo @@ -130,6 +130,11 @@ if [ "x$TEST_SSH_CONCH" != "x" ]; then esac fi +SSH_PROTOCOLS=`$SSH -Q protocol-version` +if [ "x$TEST_SSH_PROTOCOLS" != "x" ]; then + SSH_PROTOCOLS="${TEST_SSH_PROTOCOLS}" +fi + # Path to sshd must be absolute for rexec case "$SSHD" in /*) ;; @@ -141,6 +146,55 @@ case "$SSHAGENT" in *) SSHAGENT=`which $SSHAGENT` ;; esac +# Record the actual binaries used. +SSH_BIN=${SSH} +SSHD_BIN=${SSHD} +SSHAGENT_BIN=${SSHAGENT} +SSHADD_BIN=${SSHADD} +SSHKEYGEN_BIN=${SSHKEYGEN} +SSHKEYSCAN_BIN=${SSHKEYSCAN} +SFTP_BIN=${SFTP} +SFTPSERVER_BIN=${SFTPSERVER} +SCP_BIN=${SCP} + +if [ "x$USE_VALGRIND" != "x" ]; then + mkdir -p $OBJ/valgrind-out + VG_TEST=`basename $SCRIPT .sh` + + # Some tests are difficult to fix. + case "$VG_TEST" in + connect-privsep|reexec) + VG_SKIP=1 ;; + esac + + if [ x"$VG_SKIP" = "x" ]; then + VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*" + VG_LOG="$OBJ/valgrind-out/${VG_TEST}." + VG_OPTS="--track-origins=yes --leak-check=full" + VG_OPTS="$VG_OPTS --trace-children=yes" + VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}" + VG_PATH="valgrind" + if [ "x$VALGRIND_PATH" != "x" ]; then + VG_PATH="$VALGRIND_PATH" + fi + VG="$VG_PATH $VG_OPTS" + SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH" + SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD" + SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT" + SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD" + SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN" + SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN" + SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}" + SCP="$VG --log-file=${VG_LOG}scp.%p $SCP" + cat > $OBJ/valgrind-sftp-server.sh << EOF +#!/bin/sh +exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@" +EOF + chmod a+rx $OBJ/valgrind-sftp-server.sh + SFTPSERVER="$OBJ/valgrind-sftp-server.sh" + fi +fi + # Logfiles. # SSH_LOGFILE should be the debug output of ssh(1) only # SSHD_LOGFILE should be the debug output of sshd(8) only @@ -175,7 +229,7 @@ SSH="$SSHLOGWRAP" # [kbytes] to ensure the file is at least that large. DATANAME=data DATA=$OBJ/${DATANAME} -cat ${SSHAGENT} >${DATA} +cat ${SSHAGENT_BIN} >${DATA} chmod u+w ${DATA} COPY=$OBJ/copy rm -f ${COPY} @@ -183,7 +237,7 @@ rm -f ${COPY} increase_datafile_size() { while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do - cat ${SSHAGENT} >>${DATA} + cat ${SSHAGENT_BIN} >>${DATA} done } @@ -240,13 +294,20 @@ md5 () { # helper cleanup () { + if [ "x$SSH_PID" != "x" ]; then + if [ $SSH_PID -lt 2 ]; then + echo bad pid for ssh: $SSH_PID + else + kill $SSH_PID + fi + fi if [ -f $PIDFILE ]; then pid=`$SUDO cat $PIDFILE` if [ "X$pid" = "X" ]; then echo no sshd running else if [ $pid -lt 2 ]; then - echo bad pid for ssh: $pid + echo bad pid for sshd: $pid else $SUDO kill $pid trace "wait for sshd to exit" @@ -318,16 +379,27 @@ fatal () exit $RESULT } +ssh_version () +{ + echo ${SSH_PROTOCOLS} | grep "$1" >/dev/null +} + RESULT=0 PIDFILE=$OBJ/pidfile trap fatal 3 2 +if ssh_version 1; then + PROTO="2,1" +else + PROTO="2" +fi + # create server config cat << EOF > $OBJ/sshd_config StrictModes no Port $PORT - Protocol 2,1 + Protocol $PROTO AddressFamily inet ListenAddress 127.0.0.1 #ListenAddress ::1 @@ -353,7 +425,7 @@ echo 'StrictModes no' >> $OBJ/sshd_proxy # create client config cat << EOF > $OBJ/ssh_config Host * - Protocol 2,1 + Protocol $PROTO Hostname 127.0.0.1 HostKeyAlias localhost-with-alias Port $PORT @@ -372,16 +444,21 @@ Host * EOF if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then - trace "adding ssh_config option $TEST_SSH_SSHD_CONFOPTS" + trace "adding ssh_config option $TEST_SSH_SSH_CONFOPTS" echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config fi rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER +if ssh_version 1; then + SSH_KEYTYPES="rsa rsa1" +else + SSH_KEYTYPES="rsa ed25519" +fi trace "generate keys" -for t in rsa rsa1; do +for t in ${SSH_KEYTYPES}; do # generate user key - if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN} -nt $OBJ/$t ]; then + if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then rm -f $OBJ/$t ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ fail "ssh-keygen for $t failed" @@ -444,7 +521,7 @@ if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy - echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy + echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy REGRESS_INTEROP_PUTTY=yes fi @@ -452,7 +529,7 @@ fi # create a proxy version of the client config ( cat $OBJ/ssh_config - echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy + echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy ) > $OBJ/ssh_proxy # check proxy config diff --git a/crypto/openssh/regress/transfer.sh b/crypto/openssh/regress/transfer.sh index 1ae3ef5..36c1463 100644 --- a/crypto/openssh/regress/transfer.sh +++ b/crypto/openssh/regress/transfer.sh @@ -1,9 +1,9 @@ -# $OpenBSD: transfer.sh,v 1.2 2013/05/17 04:29:14 dtucker Exp $ +# $OpenBSD: transfer.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="transfer data" -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do verbose "$tid: proto $p" rm -f ${COPY} ${SSH} -n -q -$p -F $OBJ/ssh_proxy somehost cat ${DATA} > ${COPY} diff --git a/crypto/openssh/regress/try-ciphers.sh b/crypto/openssh/regress/try-ciphers.sh index ac34ced..889a735 100644 --- a/crypto/openssh/regress/try-ciphers.sh +++ b/crypto/openssh/regress/try-ciphers.sh @@ -1,27 +1,36 @@ -# $OpenBSD: try-ciphers.sh,v 1.22 2013/11/21 03:18:51 djm Exp $ +# $OpenBSD: try-ciphers.sh,v 1.25 2015/03/24 20:22:17 markus Exp $ # Placed in the Public Domain. tid="try ciphers" +cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak + for c in `${SSH} -Q cipher`; do n=0 for m in `${SSH} -Q mac`; do trace "proto 2 cipher $c mac $m" verbose "test $tid: proto 2 cipher $c mac $m" + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy + echo "Ciphers=$c" >> $OBJ/sshd_proxy + echo "MACs=$m" >> $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy -2 -m $m -c $c somehost true if [ $? -ne 0 ]; then fail "ssh -2 failed with mac $m cipher $c" fi # No point trying all MACs for AEAD ciphers since they # are ignored. - if ssh -Q cipher-auth | grep "^${c}\$" >/dev/null 2>&1 ; then + if ${SSH} -Q cipher-auth | grep "^${c}\$" >/dev/null 2>&1 ; then break fi n=`expr $n + 1` done done -ciphers="3des blowfish" +if ssh_version 1; then + ciphers="3des blowfish" +else + ciphers="" +fi for c in $ciphers; do trace "proto 1 cipher $c" verbose "test $tid: proto 1 cipher $c" diff --git a/crypto/openssh/regress/unittests/Makefile b/crypto/openssh/regress/unittests/Makefile new file mode 100644 index 0000000..d3d9082 --- /dev/null +++ b/crypto/openssh/regress/unittests/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile,v 1.5 2015/02/16 22:21:03 djm Exp $ +REGRESS_FAIL_EARLY= yes +SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys + +.include diff --git a/crypto/openssh/regress/unittests/Makefile.inc b/crypto/openssh/regress/unittests/Makefile.inc new file mode 100644 index 0000000..7385e2b --- /dev/null +++ b/crypto/openssh/regress/unittests/Makefile.inc @@ -0,0 +1,59 @@ +# $OpenBSD: Makefile.inc,v 1.6 2015/07/01 23:11:18 djm Exp $ + +.include +.include + +# enable warnings +WARNINGS=Yes + +DEBUG=-g +CFLAGS+= -fstack-protector-all +CDIAGFLAGS= -Wall +CDIAGFLAGS+= -Wextra +CDIAGFLAGS+= -Werror +CDIAGFLAGS+= -Wchar-subscripts +CDIAGFLAGS+= -Wcomment +CDIAGFLAGS+= -Wformat +CDIAGFLAGS+= -Wformat-security +CDIAGFLAGS+= -Wimplicit +CDIAGFLAGS+= -Winline +CDIAGFLAGS+= -Wmissing-declarations +CDIAGFLAGS+= -Wmissing-prototypes +CDIAGFLAGS+= -Wparentheses +CDIAGFLAGS+= -Wpointer-arith +CDIAGFLAGS+= -Wreturn-type +CDIAGFLAGS+= -Wshadow +CDIAGFLAGS+= -Wsign-compare +CDIAGFLAGS+= -Wstrict-aliasing +CDIAGFLAGS+= -Wstrict-prototypes +CDIAGFLAGS+= -Wswitch +CDIAGFLAGS+= -Wtrigraphs +CDIAGFLAGS+= -Wuninitialized +CDIAGFLAGS+= -Wunused +.if ${COMPILER_VERSION} == "gcc4" +CDIAGFLAGS+= -Wpointer-sign +CDIAGFLAGS+= -Wold-style-definition +.endif + +SSHREL=../../../../../usr.bin/ssh + +CFLAGS+=-I${.CURDIR}/../test_helper -I${.CURDIR}/${SSHREL} + +.if exists(${.CURDIR}/../test_helper/${__objdir}) +LDADD+=-L${.CURDIR}/../test_helper/${__objdir} -ltest_helper +DPADD+=${.CURDIR}/../test_helper/${__objdir}/libtest_helper.a +.else +LDADD+=-L${.CURDIR}/../test_helper -ltest_helper +DPADD+=${.CURDIR}/../test_helper/libtest_helper.a +.endif + +.if exists(${.CURDIR}/${SSHREL}/lib/${__objdir}) +LDADD+=-L${.CURDIR}/${SSHREL}/lib/${__objdir} -lssh +DPADD+=${.CURDIR}/${SSHREL}/lib/${__objdir}/libssh.a +.else +LDADD+=-L${.CURDIR}/${SSHREL}/lib -lssh +DPADD+=${.CURDIR}/${SSHREL}/lib/libssh.a +.endif + +LDADD+= -lcrypto +DPADD+= ${LIBCRYPTO} diff --git a/crypto/openssh/regress/unittests/bitmap/Makefile b/crypto/openssh/regress/unittests/bitmap/Makefile new file mode 100644 index 0000000..b704d22 --- /dev/null +++ b/crypto/openssh/regress/unittests/bitmap/Makefile @@ -0,0 +1,12 @@ +# $OpenBSD: Makefile,v 1.1 2015/01/15 07:36:28 djm Exp $ + +TEST_ENV= "MALLOC_OPTIONS=AFGJPRX" + +PROG=test_bitmap +SRCS=tests.c +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include diff --git a/crypto/openssh/regress/unittests/bitmap/tests.c b/crypto/openssh/regress/unittests/bitmap/tests.c new file mode 100644 index 0000000..23025f9 --- /dev/null +++ b/crypto/openssh/regress/unittests/bitmap/tests.c @@ -0,0 +1,135 @@ +/* $OpenBSD: tests.c,v 1.1 2015/01/15 07:36:28 djm Exp $ */ +/* + * Regress test for bitmap.h bitmap API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include + +#include + +#include "../test_helper/test_helper.h" + +#include "bitmap.h" + +#define NTESTS 131 + +void +tests(void) +{ + struct bitmap *b; + BIGNUM *bn; + size_t len; + int i, j, k, n; + u_char bbuf[1024], bnbuf[1024]; + int r; + + TEST_START("bitmap_new"); + b = bitmap_new(); + ASSERT_PTR_NE(b, NULL); + bn = BN_new(); + ASSERT_PTR_NE(bn, NULL); + TEST_DONE(); + + TEST_START("bitmap_set_bit / bitmap_test_bit"); + for (i = -1; i < NTESTS; i++) { + for (j = -1; j < NTESTS; j++) { + for (k = -1; k < NTESTS; k++) { + bitmap_zero(b); + BN_clear(bn); + + test_subtest_info("set %d/%d/%d", i, j, k); + /* Set bits */ + if (i >= 0) { + ASSERT_INT_EQ(bitmap_set_bit(b, i), 0); + ASSERT_INT_EQ(BN_set_bit(bn, i), 1); + } + if (j >= 0) { + ASSERT_INT_EQ(bitmap_set_bit(b, j), 0); + ASSERT_INT_EQ(BN_set_bit(bn, j), 1); + } + if (k >= 0) { + ASSERT_INT_EQ(bitmap_set_bit(b, k), 0); + ASSERT_INT_EQ(BN_set_bit(bn, k), 1); + } + + /* Check perfect match between bitmap and bn */ + test_subtest_info("match %d/%d/%d", i, j, k); + for (n = 0; n < NTESTS; n++) { + ASSERT_INT_EQ(BN_is_bit_set(bn, n), + bitmap_test_bit(b, n)); + } + + /* Test length calculations */ + test_subtest_info("length %d/%d/%d", i, j, k); + ASSERT_INT_EQ(BN_num_bits(bn), + (int)bitmap_nbits(b)); + ASSERT_INT_EQ(BN_num_bytes(bn), + (int)bitmap_nbytes(b)); + + /* Test serialisation */ + test_subtest_info("serialise %d/%d/%d", + i, j, k); + len = bitmap_nbytes(b); + memset(bbuf, 0xfc, sizeof(bbuf)); + ASSERT_INT_EQ(bitmap_to_string(b, bbuf, + sizeof(bbuf)), 0); + for (n = len; n < (int)sizeof(bbuf); n++) + ASSERT_U8_EQ(bbuf[n], 0xfc); + r = BN_bn2bin(bn, bnbuf); + ASSERT_INT_GE(r, 0); + ASSERT_INT_EQ(r, (int)len); + ASSERT_MEM_EQ(bbuf, bnbuf, len); + + /* Test deserialisation */ + test_subtest_info("deserialise %d/%d/%d", + i, j, k); + bitmap_zero(b); + ASSERT_INT_EQ(bitmap_from_string(b, bnbuf, + len), 0); + for (n = 0; n < NTESTS; n++) { + ASSERT_INT_EQ(BN_is_bit_set(bn, n), + bitmap_test_bit(b, n)); + } + + /* Test clearing bits */ + test_subtest_info("clear %d/%d/%d", + i, j, k); + for (n = 0; n < NTESTS; n++) { + ASSERT_INT_EQ(bitmap_set_bit(b, n), 0); + ASSERT_INT_EQ(BN_set_bit(bn, n), 1); + } + if (i >= 0) { + bitmap_clear_bit(b, i); + BN_clear_bit(bn, i); + } + if (j >= 0) { + bitmap_clear_bit(b, j); + BN_clear_bit(bn, j); + } + if (k >= 0) { + bitmap_clear_bit(b, k); + BN_clear_bit(bn, k); + } + for (n = 0; n < NTESTS; n++) { + ASSERT_INT_EQ(BN_is_bit_set(bn, n), + bitmap_test_bit(b, n)); + } + } + } + } + bitmap_free(b); + BN_free(bn); + TEST_DONE(); +} + diff --git a/crypto/openssh/regress/unittests/hostkeys/Makefile b/crypto/openssh/regress/unittests/hostkeys/Makefile new file mode 100644 index 0000000..f52a85f --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/Makefile @@ -0,0 +1,12 @@ +# $OpenBSD: Makefile,v 1.1 2015/02/16 22:18:34 djm Exp $ + +TEST_ENV= "MALLOC_OPTIONS=AFGJPRX" + +PROG=test_hostkeys +SRCS=tests.c test_iterate.c +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata + +.include diff --git a/crypto/openssh/regress/unittests/hostkeys/mktestdata.sh b/crypto/openssh/regress/unittests/hostkeys/mktestdata.sh new file mode 100755 index 0000000..36890ba --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/mktestdata.sh @@ -0,0 +1,94 @@ +#!/bin/sh +# $OpenBSD: mktestdata.sh,v 1.1 2015/02/16 22:18:34 djm Exp $ + +set -ex + +cd testdata + +rm -f rsa1* rsa* dsa* ecdsa* ed25519* +rm -f known_hosts* + +gen_all() { + _n=$1 + _ecdsa_bits=256 + test "x$_n" = "x1" && _ecdsa_bits=384 + test "x$_n" = "x2" && _ecdsa_bits=521 + ssh-keygen -qt rsa1 -b 1024 -C "RSA1 #$_n" -N "" -f rsa1_$_n + ssh-keygen -qt rsa -b 1024 -C "RSA #$_n" -N "" -f rsa_$_n + ssh-keygen -qt dsa -b 1024 -C "DSA #$_n" -N "" -f dsa_$_n + ssh-keygen -qt ecdsa -b $_ecdsa_bits -C "ECDSA #$_n" -N "" -f ecdsa_$_n + ssh-keygen -qt ed25519 -C "ED25519 #$_n" -N "" -f ed25519_$_n + # Don't need private keys + rm -f rsa1_$_n rsa_$_n dsa_$_n ecdsa_$_n ed25519_$_n +} + +hentries() { + _preamble=$1 + _kspec=$2 + for k in `ls -1 $_kspec | sort` ; do + printf "$_preamble " + cat $k + done + echo +} + +gen_all 1 +gen_all 2 +gen_all 3 +gen_all 4 +gen_all 5 +gen_all 6 + +# A section of known_hosts with hashed hostnames. +( + hentries "sisyphus.example.com" "*_5.pub" + hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_6.pub" +) > known_hosts_hash_frag +ssh-keygen -Hf known_hosts_hash_frag +rm -f known_hosts_hash_frag.old + +# Populated known_hosts, including comments, hashed names and invalid lines +( + echo "# Plain host keys, plain host names" + hentries "sisyphus.example.com" "*_1.pub" + + echo "# Plain host keys, hostnames + addresses" + hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_2.pub" + + echo "# Some hosts with wildcard names / IPs" + hentries "*.example.com,192.0.2.*,2001:*" "*_3.pub" + + echo "# Hashed hostname and address entries" + cat known_hosts_hash_frag + rm -f known_hosts_hash_frag + echo + + echo "# Revoked and CA keys" + printf "@revoked sisyphus.example.com " ; cat rsa1_4.pub + printf "@revoked sisyphus.example.com " ; cat ed25519_4.pub + printf "@cert-authority prometheus.example.com " ; cat ecdsa_4.pub + printf "@cert-authority *.example.com " ; cat dsa_4.pub + + printf "\n" + echo "# Some invalid lines" + # Invalid marker + printf "@what sisyphus.example.com " ; cat rsa1_1.pub + # Key missing + echo "sisyphus.example.com " + # Key blob missing + echo "prometheus.example.com ssh-ed25519 " + # Key blob truncated + echo "sisyphus.example.com ssh-dsa AAAATgAAAAdz" + # RSA1 key truncated after key bits + echo "prometheus.example.com 1024 " + # RSA1 key truncated after exponent + echo "sisyphus.example.com 1024 65535 " + # RSA1 key incorrect key bits + printf "prometheus.example.com 1025 " ; cut -d' ' -f2- < rsa1_1.pub + # Invalid type + echo "sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==" + # Type mismatch with blob + echo "prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==" +) > known_hosts + +echo OK diff --git a/crypto/openssh/regress/unittests/hostkeys/test_iterate.c b/crypto/openssh/regress/unittests/hostkeys/test_iterate.c new file mode 100644 index 0000000..2eaaf06 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/test_iterate.c @@ -0,0 +1,1171 @@ +/* $OpenBSD: test_iterate.c,v 1.4 2015/03/31 22:59:01 djm Exp $ */ +/* + * Regress test for hostfile.h hostkeys_foreach() + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include + +#include "../test_helper/test_helper.h" + +#include "sshkey.h" +#include "authfile.h" +#include "hostfile.h" + +struct expected { + const char *key_file; /* Path for key, NULL for none */ + int no_parse_status; /* Expected status w/o key parsing */ + int no_parse_keytype; /* Expected keytype w/o key parsing */ + int match_host_p; /* Match 'prometheus.example.com' */ + int match_host_s; /* Match 'sisyphus.example.com' */ + int match_ipv4; /* Match '192.0.2.1' */ + int match_ipv6; /* Match '2001:db8::1' */ + int match_flags; /* Expected flags from match */ + struct hostkey_foreach_line l; /* Expected line contents */ +}; + +struct cbctx { + const struct expected *expected; + size_t nexpected; + size_t i; + int flags; + int match_host_p; + int match_host_s; + int match_ipv4; + int match_ipv6; +}; + +/* + * hostkeys_foreach() iterator callback that verifies the line passed + * against an array of expected entries. + */ +static int +check(struct hostkey_foreach_line *l, void *_ctx) +{ + struct cbctx *ctx = (struct cbctx *)_ctx; + const struct expected *expected; + int parse_key = (ctx->flags & HKF_WANT_PARSE_KEY) != 0; + const int matching = (ctx->flags & HKF_WANT_MATCH) != 0; + u_int expected_status, expected_match; + int expected_keytype; + + test_subtest_info("entry %zu/%zu, file line %ld", + ctx->i + 1, ctx->nexpected, l->linenum); + + for (;;) { + ASSERT_SIZE_T_LT(ctx->i, ctx->nexpected); + expected = ctx->expected + ctx->i++; + /* If we are matching host/IP then skip entries that don't */ + if (!matching) + break; + if (ctx->match_host_p && expected->match_host_p) + break; + if (ctx->match_host_s && expected->match_host_s) + break; + if (ctx->match_ipv4 && expected->match_ipv4) + break; + if (ctx->match_ipv6 && expected->match_ipv6) + break; + } + expected_status = (parse_key || expected->no_parse_status < 0) ? + expected->l.status : (u_int)expected->no_parse_status; + expected_match = expected->l.match; +#define UPDATE_MATCH_STATUS(x) do { \ + if (ctx->x && expected->x) { \ + expected_match |= expected->x; \ + if (expected_status == HKF_STATUS_OK) \ + expected_status = HKF_STATUS_MATCHED; \ + } \ + } while (0) + expected_keytype = (parse_key || expected->no_parse_keytype < 0) ? + expected->l.keytype : expected->no_parse_keytype; + +#ifndef WITH_SSH1 + if (parse_key && (expected->l.keytype == KEY_RSA1 || + expected->no_parse_keytype == KEY_RSA1)) { + expected_status = HKF_STATUS_INVALID; + expected_keytype = KEY_UNSPEC; + parse_key = 0; + } +#endif +#ifndef OPENSSL_HAS_ECC + if (expected->l.keytype == KEY_ECDSA || + expected->no_parse_keytype == KEY_ECDSA) { + expected_status = HKF_STATUS_INVALID; + expected_keytype = KEY_UNSPEC; + parse_key = 0; + } +#endif + + UPDATE_MATCH_STATUS(match_host_p); + UPDATE_MATCH_STATUS(match_host_s); + UPDATE_MATCH_STATUS(match_ipv4); + UPDATE_MATCH_STATUS(match_ipv6); + + ASSERT_PTR_NE(l->path, NULL); /* Don't care about path */ + ASSERT_LONG_LONG_EQ(l->linenum, expected->l.linenum); + ASSERT_U_INT_EQ(l->status, expected_status); + ASSERT_U_INT_EQ(l->match, expected_match); + /* Not all test entries contain fulltext */ + if (expected->l.line != NULL) + ASSERT_STRING_EQ(l->line, expected->l.line); + ASSERT_INT_EQ(l->marker, expected->l.marker); + /* XXX we skip hashed hostnames for now; implement checking */ + if (expected->l.hosts != NULL) + ASSERT_STRING_EQ(l->hosts, expected->l.hosts); + /* Not all test entries contain raw keys */ + if (expected->l.rawkey != NULL) + ASSERT_STRING_EQ(l->rawkey, expected->l.rawkey); + /* XXX synthesise raw key for cases lacking and compare */ + ASSERT_INT_EQ(l->keytype, expected_keytype); + if (parse_key) { + if (expected->l.key == NULL) + ASSERT_PTR_EQ(l->key, NULL); + if (expected->l.key != NULL) { + ASSERT_PTR_NE(l->key, NULL); + ASSERT_INT_EQ(sshkey_equal(l->key, expected->l.key), 1); + } + } + if (parse_key && !(l->comment == NULL && expected->l.comment == NULL)) + ASSERT_STRING_EQ(l->comment, expected->l.comment); + return 0; +} + +/* Loads public keys for a set of expected results */ +static void +prepare_expected(struct expected *expected, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) { + if (expected[i].key_file == NULL) + continue; +#ifndef WITH_SSH1 + if (expected[i].l.keytype == KEY_RSA1) + continue; +#endif +#ifndef OPENSSL_HAS_ECC + if (expected[i].l.keytype == KEY_ECDSA) + continue; +#endif + ASSERT_INT_EQ(sshkey_load_public( + test_data_file(expected[i].key_file), &expected[i].l.key, + NULL), 0); + } +} + +struct expected expected_full[] = { + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, /* path, don't care */ + 1, /* line number */ + HKF_STATUS_COMMENT, /* status */ + 0, /* match flags */ + "# Plain host keys, plain host names", /* full line, optional */ + MRK_NONE, /* marker (CA / revoked) */ + NULL, /* hosts text */ + NULL, /* raw key, optional */ + KEY_UNSPEC, /* key type */ + NULL, /* deserialised key */ + NULL, /* comment */ + } }, + { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 2, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #1", + } }, + { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 3, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #1", + } }, + { "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 4, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #1", + } }, + { "rsa1_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 5, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_RSA1, + NULL, /* filled at runtime */ + "RSA1 #1", + } }, + { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 6, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #1", + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 7, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 8, + HKF_STATUS_COMMENT, + 0, + "# Plain host keys, hostnames + addresses", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 9, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #2", + } }, + { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 10, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #2", + } }, + { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 11, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #2", + } }, + { "rsa1_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 12, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_RSA1, + NULL, /* filled at runtime */ + "RSA1 #2", + } }, + { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 13, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "prometheus.example.com,192.0.2.1,2001:db8::1", + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #2", + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 14, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 15, + HKF_STATUS_COMMENT, + 0, + "# Some hosts with wildcard names / IPs", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 16, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #3", + } }, + { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 17, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #3", + } }, + { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 18, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #3", + } }, + { "rsa1_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 19, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_RSA1, + NULL, /* filled at runtime */ + "RSA1 #3", + } }, + { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { + NULL, + 20, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + "*.example.com,192.0.2.*,2001:*", + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #3", + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 21, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 22, + HKF_STATUS_COMMENT, + 0, + "# Hashed hostname and address entries", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 23, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #5", + } }, + { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 24, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #5", + } }, + { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 25, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #5", + } }, + { "rsa1_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 26, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA1, + NULL, /* filled at runtime */ + "RSA1 #5", + } }, + { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { + NULL, + 27, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #5", + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 28, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + /* + * The next series have each key listed multiple times, as the + * hostname and addresses in the pre-hashed known_hosts are split + * to separate lines. + */ + { "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 29, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #6", + } }, + { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 30, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #6", + } }, + { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 31, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #6", + } }, + { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 32, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #6", + } }, + { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 33, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #6", + } }, + { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 34, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #6", + } }, + { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 35, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #6", + } }, + { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 36, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #6", + } }, + { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 37, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #6", + } }, + { "rsa1_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 38, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA1, + NULL, /* filled at runtime */ + "RSA1 #6", + } }, + { "rsa1_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 39, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA1, + NULL, /* filled at runtime */ + "RSA1 #6", + } }, + { "rsa1_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 40, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA1, + NULL, /* filled at runtime */ + "RSA1 #6", + } }, + { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { + NULL, + 41, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #6", + } }, + { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { + NULL, + 42, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #6", + } }, + { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { + NULL, + 43, + HKF_STATUS_OK, + 0, + NULL, + MRK_NONE, + NULL, + NULL, + KEY_RSA, + NULL, /* filled at runtime */ + "RSA #6", + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 44, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 45, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 46, + HKF_STATUS_COMMENT, + 0, + "# Revoked and CA keys", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { "rsa1_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 47, + HKF_STATUS_OK, + 0, + NULL, + MRK_REVOKE, + "sisyphus.example.com", + NULL, + KEY_RSA1, + NULL, /* filled at runtime */ + "RSA1 #4", + } }, + { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 48, + HKF_STATUS_OK, + 0, + NULL, + MRK_REVOKE, + "sisyphus.example.com", + NULL, + KEY_ED25519, + NULL, /* filled at runtime */ + "ED25519 #4", + } }, + { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { + NULL, + 49, + HKF_STATUS_OK, + 0, + NULL, + MRK_CA, + "prometheus.example.com", + NULL, + KEY_ECDSA, + NULL, /* filled at runtime */ + "ECDSA #4", + } }, + { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 50, + HKF_STATUS_OK, + 0, + NULL, + MRK_CA, + "*.example.com", + NULL, + KEY_DSA, + NULL, /* filled at runtime */ + "DSA #4", + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 51, + HKF_STATUS_COMMENT, + 0, + "", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 52, + HKF_STATUS_COMMENT, + 0, + "# Some invalid lines", + MRK_NONE, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, 0, 0, 0, -1, { + NULL, + 53, + HKF_STATUS_INVALID, + 0, + NULL, + MRK_ERROR, + NULL, + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 54, + HKF_STATUS_INVALID, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { + NULL, + 55, + HKF_STATUS_INVALID, + 0, + NULL, + MRK_NONE, + "prometheus.example.com", + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 56, + HKF_STATUS_INVALID, /* Would be ok if key not parsed */ + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { + NULL, + 57, + HKF_STATUS_INVALID, /* Would be ok if key not parsed */ + 0, + NULL, + MRK_NONE, + "prometheus.example.com", + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, HKF_STATUS_OK, KEY_RSA1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 58, + HKF_STATUS_INVALID, /* Would be ok if key not parsed */ + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_UNSPEC, + NULL, + NULL, + } }, + { NULL, HKF_STATUS_OK, KEY_RSA1, HKF_MATCH_HOST, 0, 0, 0, -1, { + NULL, + 59, + HKF_STATUS_INVALID, /* Would be ok if key not parsed */ + 0, + NULL, + MRK_NONE, + "prometheus.example.com", + NULL, + KEY_UNSPEC, + NULL, /* filled at runtime */ + NULL, + } }, + { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + NULL, + 60, + HKF_STATUS_INVALID, + 0, + NULL, + MRK_NONE, + "sisyphus.example.com", + NULL, + KEY_UNSPEC, + NULL, /* filled at runtime */ + NULL, + } }, + { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, { + NULL, + 61, + HKF_STATUS_INVALID, /* Would be ok if key not parsed */ + 0, + NULL, + MRK_NONE, + "prometheus.example.com", + NULL, + KEY_UNSPEC, + NULL, /* filled at runtime */ + NULL, + } }, +}; + +void test_iterate(void); + +void +test_iterate(void) +{ + struct cbctx ctx; + + TEST_START("hostkeys_iterate all with key parse"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_PARSE_KEY; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, NULL, NULL, ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate all without key parse"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, NULL, NULL, ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host 1"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_host_p = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host 2"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_host_s = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host 1"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_host_p = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host 2"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_host_s = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host missing"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host missing"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify IPv4"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_ipv4 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify IPv6"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_ipv6 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate match IPv4"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_ipv4 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate match IPv6"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_ipv6 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify addr missing"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "192.168.0.1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate match addr missing"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "tiresias.example.org", "::1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host 2 and IPv4"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = 0; + ctx.match_host_s = 1; + ctx.match_ipv4 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host 1 and IPv6"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH; + ctx.match_host_p = 1; + ctx.match_ipv6 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "prometheus.example.com", "2001:db8::1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate specify host 2 and IPv4 w/ key parse"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_PARSE_KEY; + ctx.match_host_s = 1; + ctx.match_ipv4 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0); + TEST_DONE(); + + TEST_START("hostkeys_iterate match host 1 and IPv6 w/ key parse"); + memset(&ctx, 0, sizeof(ctx)); + ctx.expected = expected_full; + ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full); + ctx.flags = HKF_WANT_MATCH|HKF_WANT_PARSE_KEY; + ctx.match_host_p = 1; + ctx.match_ipv6 = 1; + prepare_expected(expected_full, ctx.nexpected); + ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), + check, &ctx, "prometheus.example.com", "2001:db8::1", ctx.flags), 0); + TEST_DONE(); +} + diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_1.pub new file mode 100644 index 0000000..56e1e37 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_1.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_2.pub new file mode 100644 index 0000000..394e0bf --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_2.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_3.pub new file mode 100644 index 0000000..e506ea4 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_3.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_4.pub new file mode 100644 index 0000000..8552c38 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_4.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_5.pub new file mode 100644 index 0000000..149e1ef --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_5.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_6.pub new file mode 100644 index 0000000..edbb976 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_6.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_1.pub new file mode 100644 index 0000000..16a535b --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_1.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_2.pub new file mode 100644 index 0000000..d2bad11 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_2.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_3.pub new file mode 100644 index 0000000..e3ea925 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_3.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_4.pub new file mode 100644 index 0000000..2d616f5 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_4.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_5.pub new file mode 100644 index 0000000..a3df9b3 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_5.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_6.pub new file mode 100644 index 0000000..139f5a7 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_6.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_1.pub new file mode 100644 index 0000000..0b12efe --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_1.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_2.pub new file mode 100644 index 0000000..78e262b --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_2.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_3.pub new file mode 100644 index 0000000..64e5f12 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_3.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_4.pub new file mode 100644 index 0000000..47b6724 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_4.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_5.pub new file mode 100644 index 0000000..72ccae6 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_5.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_6.pub new file mode 100644 index 0000000..0f71973 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_6.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/known_hosts b/crypto/openssh/regress/unittests/hostkeys/testdata/known_hosts new file mode 100644 index 0000000..3740f67 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/known_hosts @@ -0,0 +1,61 @@ +# Plain host keys, plain host names +sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 +sisyphus.example.com ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1 +sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1 +sisyphus.example.com 1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 +sisyphus.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1 + +# Plain host keys, hostnames + addresses +prometheus.example.com,192.0.2.1,2001:db8::1 ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2 +prometheus.example.com,192.0.2.1,2001:db8::1 ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2 +prometheus.example.com,192.0.2.1,2001:db8::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2 +prometheus.example.com,192.0.2.1,2001:db8::1 1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2 +prometheus.example.com,192.0.2.1,2001:db8::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2 + +# Some hosts with wildcard names / IPs +*.example.com,192.0.2.*,2001:* ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3 +*.example.com,192.0.2.*,2001:* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3 +*.example.com,192.0.2.*,2001:* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3 +*.example.com,192.0.2.*,2001:* 1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3 +*.example.com,192.0.2.*,2001:* ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3 + +# Hashed hostname and address entries +|1|6FWxoqTCAfm8sZ7T/q73OmxCFGM=|S4eQmusok4cbyDzzGEFGIAthDbw= ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 +|1|hTrfD0CuuB9ZbOa1CHFYvIk/gKE=|tPmW50t7flncm1UyM+DR97ubDNU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5 +|1|fOGqe75X5ZpTz4c7DitP4E8/y30=|Lmcch2fh54bUYoV//S2VqDFVeiY= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5 +|1|0RVzLjY3lwE3MRweguaAXaCCWk8=|DbcIgJQcRZJMYI6NYDOM6oJycPk= 1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5 +|1|4q79XnHpKBNQhyMLAqbPPDN+JKo=|k1Wvjjb52zDdrXWM801+wX5oH8U= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5 + +|1|0M6PIx6THA3ipIOvTl3fcgn2z+A=|bwEJAOwJz+Sm7orFdgj170mD/zY= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|a6WGHcL+9gX3e96tMlgDSDJwtSg=|5Dqlb/yqNEf7jgfllrp/ygLmRV8= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|OeCpi7Pn5Q6c8la4fPf9G8YctT8=|sC6D7lDXTafIpokZJ1+1xWg2R6Q= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|BHESVyiJ7G2NN0lxrw7vT109jmk=|TKof+015J77bXqibsh0N1Lp0MKk= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|wY53mZNASDJ5/P3JYCJ4FUNa6WQ=|v8p0MfV5lqlZB2J0yLxl/gsWVQo= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|horeoyFPwfKhyFN+zJZ5LCfOo/I=|2ofvp0tNwCbKsV8FuiFA4gQG2Z8= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|Aw4fXumZfx6jEIJuDGIyeEMd81A=|5FdLtdm2JeKNsS8IQeQlGYIadOE= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|+dGUNpv6GblrDd5fgHLlOWpSbEo=|He/pQ1yJjtiCyTNWpGwjBD4sZFI= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|E/PACGl8m1T7QnPedOoooozstP0=|w6DQAFT8yZgj0Hlkz5R1TppYHCA= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|SaoyMStgxpYfwedSXBAghi8Zo0s=|Gz78k69GaE6iViV3OOvbStKqyTA= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 +|1|8qfGeiT5WTCzWYbXPQ+lsLg7km4=|1sIBwiSUr8IGkvrUGm3/9QYurmA= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 +|1|87M1OtyHg1BZiDY3rT6lYsZFnAU=|eddAQVcMNbn2OB87XWXFQnYo6R4= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 +|1|60w3wFfC0XWI+rRmRlxIRhh8lwE=|yMhsGrzBJKiesAdSQ/PVgkCrDKk= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 +|1|5gdEMmLUJC7grqWhRJPy2OTaSyE=|/XTfmLMa/B8npcVCGFRdaHl+d/0= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 +|1|6FGCWUr42GHdMB/eifnHNCuwgdk=|ONJvYZ/ANmi59R5HrOhLPmvYENM= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 + + +# Revoked and CA keys +@revoked sisyphus.example.com 1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4 +@revoked sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4 +@cert-authority prometheus.example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4 +@cert-authority *.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4 + +# Some invalid lines +@what sisyphus.example.com 1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 +sisyphus.example.com +prometheus.example.com ssh-ed25519 +sisyphus.example.com ssh-dsa AAAATgAAAAdz +prometheus.example.com 1024 +sisyphus.example.com 1024 65535 +prometheus.example.com 1025 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 +sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg== +prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg== diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_1.pub new file mode 100644 index 0000000..772ce9c --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_1.pub @@ -0,0 +1 @@ +1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_2.pub new file mode 100644 index 0000000..78794b9 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_2.pub @@ -0,0 +1 @@ +1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_3.pub new file mode 100644 index 0000000..0c035fe --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_3.pub @@ -0,0 +1 @@ +1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_4.pub new file mode 100644 index 0000000..00064423 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_4.pub @@ -0,0 +1 @@ +1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_5.pub new file mode 100644 index 0000000..bb53c26 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_5.pub @@ -0,0 +1 @@ +1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_6.pub new file mode 100644 index 0000000..85d6576 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_6.pub @@ -0,0 +1 @@ +1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_1.pub new file mode 100644 index 0000000..2b87885 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_1.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_2.pub new file mode 100644 index 0000000..33f1fd9 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_2.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_3.pub new file mode 100644 index 0000000..c2f6b20 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_3.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_4.pub new file mode 100644 index 0000000..35545a7 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_4.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDI8AdjBAozcdRnIikVlt69iyDHKyrtxmpdkbRy9bWaL86OH+PTmLUk5e+T/ufiakpeE2pm0hkE3e4Sh/FsY+rsQdRoraWVNFfchcMeVlKvuy5RZN0ElvmaQebOJUeNeBn2LLw8aL8bJ4CP/bQRKrmrSSqjz3+4H9YNVyyk1OGBPQ== RSA #4 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_5.pub new file mode 100644 index 0000000..befbaa7 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_5.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5 diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_6.pub new file mode 100644 index 0000000..393e116 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_6.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 diff --git a/crypto/openssh/regress/unittests/hostkeys/tests.c b/crypto/openssh/regress/unittests/hostkeys/tests.c new file mode 100644 index 0000000..92c7646 --- /dev/null +++ b/crypto/openssh/regress/unittests/hostkeys/tests.c @@ -0,0 +1,16 @@ +/* $OpenBSD: tests.c,v 1.1 2015/02/16 22:18:34 djm Exp $ */ +/* + * Regress test for known_hosts-related API. + * + * Placed in the public domain + */ + +void tests(void); +void test_iterate(void); /* test_iterate.c */ + +void +tests(void) +{ + test_iterate(); +} + diff --git a/crypto/openssh/regress/unittests/kex/Makefile b/crypto/openssh/regress/unittests/kex/Makefile new file mode 100644 index 0000000..6532cb0 --- /dev/null +++ b/crypto/openssh/regress/unittests/kex/Makefile @@ -0,0 +1,14 @@ +# $OpenBSD: Makefile,v 1.2 2015/01/24 10:39:21 miod Exp $ + +TEST_ENV= "MALLOC_OPTIONS=AFGJPRX" + +PROG=test_kex +SRCS=tests.c test_kex.c +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include + +LDADD+=-lz diff --git a/crypto/openssh/regress/unittests/kex/test_kex.c b/crypto/openssh/regress/unittests/kex/test_kex.c new file mode 100644 index 0000000..6e5999b --- /dev/null +++ b/crypto/openssh/regress/unittests/kex/test_kex.c @@ -0,0 +1,202 @@ +/* $OpenBSD: test_kex.c,v 1.2 2015/07/10 06:23:25 markus Exp $ */ +/* + * Regress test KEX + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "ssh_api.h" +#include "sshbuf.h" +#include "packet.h" +#include "myproposal.h" + +struct ssh *active_state = NULL; /* XXX - needed for linking */ + +void kex_tests(void); +static int do_debug = 0; + +static int +do_send_and_receive(struct ssh *from, struct ssh *to) +{ + u_char type; + size_t len; + const u_char *buf; + int r; + + for (;;) { + if ((r = ssh_packet_next(from, &type)) != 0) { + fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r)); + return r; + } + if (type != 0) + return 0; + buf = ssh_output_ptr(from, &len); + if (do_debug) + printf("%zu", len); + if (len == 0) + return 0; + if ((r = ssh_output_consume(from, len)) != 0 || + (r = ssh_input_append(to, buf, len)) != 0) + return r; + } +} + +static void +run_kex(struct ssh *client, struct ssh *server) +{ + int r = 0; + + while (!server->kex->done || !client->kex->done) { + if (do_debug) + printf(" S:"); + if ((r = do_send_and_receive(server, client))) + break; + if (do_debug) + printf(" C:"); + if ((r = do_send_and_receive(client, server))) + break; + } + if (do_debug) + printf("done: %s\n", ssh_err(r)); + ASSERT_INT_EQ(r, 0); + ASSERT_INT_EQ(server->kex->done, 1); + ASSERT_INT_EQ(client->kex->done, 1); +} + +static void +do_kex_with_key(char *kex, int keytype, int bits) +{ + struct ssh *client = NULL, *server = NULL, *server2 = NULL; + struct sshkey *private, *public; + struct sshbuf *state; + struct kex_params kex_params; + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + char *keyname = NULL; + + TEST_START("sshkey_generate"); + ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0); + TEST_DONE(); + + TEST_START("sshkey_from_private"); + ASSERT_INT_EQ(sshkey_from_private(private, &public), 0); + TEST_DONE(); + + TEST_START("ssh_init"); + memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); + if (kex != NULL) + kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; + keyname = strdup(sshkey_ssh_name(private)); + ASSERT_PTR_NE(keyname, NULL); + kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; + ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); + ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0); + ASSERT_PTR_NE(client, NULL); + ASSERT_PTR_NE(server, NULL); + TEST_DONE(); + + TEST_START("ssh_add_hostkey"); + ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0); + ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0); + TEST_DONE(); + + TEST_START("kex"); + run_kex(client, server); + TEST_DONE(); + + TEST_START("rekeying client"); + ASSERT_INT_EQ(kex_send_kexinit(client), 0); + run_kex(client, server); + TEST_DONE(); + + TEST_START("rekeying server"); + ASSERT_INT_EQ(kex_send_kexinit(server), 0); + run_kex(client, server); + TEST_DONE(); + + TEST_START("ssh_packet_get_state"); + state = sshbuf_new(); + ASSERT_PTR_NE(state, NULL); + ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0); + ASSERT_INT_GE(sshbuf_len(state), 1); + TEST_DONE(); + + TEST_START("ssh_packet_set_state"); + server2 = NULL; + ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0); + ASSERT_PTR_NE(server2, NULL); + ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0); + kex_free(server2->kex); /* XXX or should ssh_packet_set_state()? */ + ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0); + ASSERT_INT_EQ(sshbuf_len(state), 0); + sshbuf_free(state); + ASSERT_PTR_NE(server2->kex, NULL); + /* XXX we need to set the callbacks */ + server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; + server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; +#ifdef OPENSSL_HAS_ECC + server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; +#endif + server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server; + server2->kex->load_host_public_key = server->kex->load_host_public_key; + server2->kex->load_host_private_key = server->kex->load_host_private_key; + server2->kex->sign = server->kex->sign; + TEST_DONE(); + + TEST_START("rekeying server2"); + ASSERT_INT_EQ(kex_send_kexinit(server2), 0); + run_kex(client, server2); + ASSERT_INT_EQ(kex_send_kexinit(client), 0); + run_kex(client, server2); + TEST_DONE(); + + TEST_START("cleanup"); + sshkey_free(private); + sshkey_free(public); + ssh_free(client); + ssh_free(server); + ssh_free(server2); + free(keyname); + TEST_DONE(); +} + +static void +do_kex(char *kex) +{ + do_kex_with_key(kex, KEY_RSA, 2048); + do_kex_with_key(kex, KEY_DSA, 1024); +#ifdef OPENSSL_HAS_ECC + do_kex_with_key(kex, KEY_ECDSA, 256); +#endif + do_kex_with_key(kex, KEY_ED25519, 256); +} + +void +kex_tests(void) +{ + do_kex("curve25519-sha256@libssh.org"); +#ifdef OPENSSL_HAS_ECC + do_kex("ecdh-sha2-nistp256"); + do_kex("ecdh-sha2-nistp384"); + do_kex("ecdh-sha2-nistp521"); +#endif + do_kex("diffie-hellman-group-exchange-sha256"); + do_kex("diffie-hellman-group-exchange-sha1"); + do_kex("diffie-hellman-group14-sha1"); + do_kex("diffie-hellman-group1-sha1"); +} diff --git a/crypto/openssh/regress/unittests/kex/tests.c b/crypto/openssh/regress/unittests/kex/tests.c new file mode 100644 index 0000000..e7036ec --- /dev/null +++ b/crypto/openssh/regress/unittests/kex/tests.c @@ -0,0 +1,14 @@ +/* $OpenBSD: tests.c,v 1.1 2015/01/15 23:41:29 markus Exp $ */ +/* + * Placed in the public domain + */ + +#include "../test_helper/test_helper.h" + +void kex_tests(void); + +void +tests(void) +{ + kex_tests(); +} diff --git a/crypto/openssh/regress/unittests/sshbuf/Makefile b/crypto/openssh/regress/unittests/sshbuf/Makefile new file mode 100644 index 0000000..85f99ac --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/Makefile @@ -0,0 +1,14 @@ +# $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $ + +PROG=test_sshbuf +SRCS=tests.c +SRCS+=test_sshbuf.c +SRCS+=test_sshbuf_getput_basic.c +SRCS+=test_sshbuf_getput_crypto.c +SRCS+=test_sshbuf_misc.c +SRCS+=test_sshbuf_fuzz.c +SRCS+=test_sshbuf_getput_fuzz.c +SRCS+=test_sshbuf_fixed.c + +.include + diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf.c new file mode 100644 index 0000000..ee77d69 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf.c @@ -0,0 +1,240 @@ +/* $OpenBSD: test_sshbuf.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#define SSHBUF_INTERNAL 1 /* access internals for testing */ +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "sshbuf.h" + +void sshbuf_tests(void); + +void +sshbuf_tests(void) +{ + struct sshbuf *p1; + const u_char *cdp; + u_char *dp; + size_t sz; + int r; + + TEST_START("allocate sshbuf"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + TEST_DONE(); + + TEST_START("max size on fresh buffer"); + ASSERT_SIZE_T_GT(sshbuf_max_size(p1), 0); + TEST_DONE(); + + TEST_START("available on fresh buffer"); + ASSERT_SIZE_T_GT(sshbuf_avail(p1), 0); + TEST_DONE(); + + TEST_START("len = 0 on empty buffer"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + TEST_DONE(); + + TEST_START("set valid max size"); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 65536), 0); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 65536); + TEST_DONE(); + + TEST_START("available on limited buffer"); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 65536); + TEST_DONE(); + + TEST_START("free"); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("consume on empty buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0); + ASSERT_INT_EQ(sshbuf_consume(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("consume_end on empty buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 0), 0); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("reserve space"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + r = sshbuf_reserve(p1, 1, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + *dp = 0x11; + r = sshbuf_reserve(p1, 3, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + *dp++ = 0x22; + *dp++ = 0x33; + *dp++ = 0x44; + TEST_DONE(); + + TEST_START("sshbuf_len on filled buffer"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + TEST_DONE(); + + TEST_START("sshbuf_ptr on filled buffer"); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(cdp, NULL); + ASSERT_U8_EQ(cdp[0], 0x11); + ASSERT_U8_EQ(cdp[1], 0x22); + ASSERT_U8_EQ(cdp[2], 0x33); + ASSERT_U8_EQ(cdp[3], 0x44); + TEST_DONE(); + + TEST_START("consume on filled buffer"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + r = sshbuf_consume(p1, 64); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(p1, NULL); + ASSERT_U8_EQ(cdp[0], 0x22); + ASSERT_INT_EQ(sshbuf_consume(p1, 2), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(p1, NULL); + ASSERT_U8_EQ(cdp[0], 0x44); + r = sshbuf_consume(p1, 2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + r = sshbuf_consume(p1, 1); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("consume_end on filled buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + r = sshbuf_reserve(p1, 4, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + *dp++ = 0x11; + *dp++ = 0x22; + *dp++ = 0x33; + *dp++ = 0x44; + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + r = sshbuf_consume_end(p1, 5); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 3), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(cdp, NULL); + ASSERT_U8_EQ(*cdp, 0x11); + r = sshbuf_consume_end(p1, 2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("fill limited buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223); + r = sshbuf_reserve(p1, 1223, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + memset(dp, 0xd7, 1223); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0); + r = sshbuf_reserve(p1, 1, &dp); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_PTR_EQ(dp, NULL); + TEST_DONE(); + + TEST_START("consume and force compaction"); + ASSERT_INT_EQ(sshbuf_consume(p1, 223), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223); + r = sshbuf_reserve(p1, 224, &dp); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_PTR_EQ(dp, NULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223); + r = sshbuf_reserve(p1, 223, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + memset(dp, 0x7d, 223); + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(cdp, NULL); + ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000); + ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223); + TEST_DONE(); + + TEST_START("resize full buffer"); + r = sshbuf_set_max_size(p1, 1000); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + sz = roundup(1223 + SSHBUF_SIZE_INC * 3, SSHBUF_SIZE_INC); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sz), 0); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - 1223); + ASSERT_INT_EQ(sshbuf_len(p1), 1223); + TEST_DONE(); + + /* NB. uses sshbuf internals */ + TEST_START("alloc chunking"); + r = sshbuf_reserve(p1, 1, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + *dp = 0xff; + cdp = sshbuf_ptr(p1); + ASSERT_PTR_NE(cdp, NULL); + ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000); + ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223); + ASSERT_MEM_FILLED_EQ(cdp + 1223, 0xff, 1); + ASSERT_SIZE_T_EQ(sshbuf_alloc(p1) % SSHBUF_SIZE_INC, 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("reset buffer"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); + r = sshbuf_reserve(p1, 1223, &dp); + ASSERT_INT_EQ(r, 0); + ASSERT_PTR_NE(dp, NULL); + memset(dp, 0xd7, 1223); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223); + sshbuf_reset(p1); + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223); + sshbuf_free(p1); + TEST_DONE(); +} diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_fixed.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_fixed.c new file mode 100644 index 0000000..df4925f --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_fixed.c @@ -0,0 +1,126 @@ +/* $OpenBSD: test_sshbuf_fixed.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#define SSHBUF_INTERNAL 1 /* access internals for testing */ +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include + +#include "../test_helper/test_helper.h" + +#include "sshbuf.h" +#include "ssherr.h" + +void sshbuf_fixed(void); + +const u_char test_buf[] = "\x01\x12\x34\x56\x78\x00\x00\x00\x05hello"; + +void +sshbuf_fixed(void) +{ + struct sshbuf *p1, *p2, *p3; + u_char c; + char *s; + u_int i; + size_t l; + + TEST_START("sshbuf_from"); + p1 = sshbuf_from(test_buf, sizeof(test_buf)); + ASSERT_PTR_NE(p1, NULL); + ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL); + ASSERT_INT_EQ(sshbuf_check_reserve(p1, 1), SSH_ERR_BUFFER_READ_ONLY); + ASSERT_INT_EQ(sshbuf_reserve(p1, 1, NULL), SSH_ERR_BUFFER_READ_ONLY); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 200), SSH_ERR_BUFFER_READ_ONLY); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), SSH_ERR_BUFFER_READ_ONLY); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_from data"); + p1 = sshbuf_from(test_buf, sizeof(test_buf) - 1); + ASSERT_PTR_NE(p1, NULL); + ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf); + ASSERT_INT_EQ(sshbuf_get_u8(p1, &c), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 1); + ASSERT_U8_EQ(c, 1); + ASSERT_INT_EQ(sshbuf_get_u32(p1, &i), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 5); + ASSERT_U32_EQ(i, 0x12345678); + ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s, &l), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + ASSERT_STRING_EQ(s, "hello"); + ASSERT_SIZE_T_EQ(l, 5); + sshbuf_free(p1); + free(s); + TEST_DONE(); + + TEST_START("sshbuf_fromb "); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1); + ASSERT_PTR_EQ(sshbuf_parent(p1), NULL); + ASSERT_INT_EQ(sshbuf_put(p1, test_buf, sizeof(test_buf) - 1), 0); + p2 = sshbuf_fromb(p1); + ASSERT_PTR_NE(p2, NULL); + ASSERT_U_INT_EQ(sshbuf_refcount(p1), 2); + ASSERT_PTR_EQ(sshbuf_parent(p1), NULL); + ASSERT_PTR_EQ(sshbuf_parent(p2), p1); + ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1)); + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_PTR_NE(sshbuf_ptr(p2), NULL); + ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL); + ASSERT_PTR_EQ(sshbuf_mutable_ptr(p2), NULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sshbuf_len(p2)); + ASSERT_INT_EQ(sshbuf_get_u8(p2, &c), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 1); + ASSERT_U8_EQ(c, 1); + ASSERT_INT_EQ(sshbuf_get_u32(p2, &i), 0); + ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 5); + ASSERT_U32_EQ(i, 0x12345678); + ASSERT_INT_EQ(sshbuf_get_cstring(p2, &s, &l), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0); + ASSERT_STRING_EQ(s, "hello"); + ASSERT_SIZE_T_EQ(l, 5); + sshbuf_free(p1); + ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1); + sshbuf_free(p2); + free(s); + TEST_DONE(); + + TEST_START("sshbuf_froms"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x01), 0); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); + ASSERT_INT_EQ(sshbuf_put_cstring(p1, "hello"), 0); + p2 = sshbuf_new(); + ASSERT_PTR_NE(p2, NULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(test_buf) - 1); + ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p2), sizeof(test_buf) + 4 - 1); + ASSERT_INT_EQ(sshbuf_froms(p2, &p3), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0); + ASSERT_PTR_NE(p3, NULL); + ASSERT_PTR_NE(sshbuf_ptr(p3), NULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p3), sizeof(test_buf) - 1); + ASSERT_MEM_EQ(sshbuf_ptr(p3), test_buf, sizeof(test_buf) - 1); + sshbuf_free(p3); + ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0); + ASSERT_INT_EQ(sshbuf_consume_end(p2, 1), 0); + ASSERT_INT_EQ(sshbuf_froms(p2, &p3), SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_PTR_EQ(p3, NULL); + sshbuf_free(p2); + sshbuf_free(p1); +} diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_fuzz.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_fuzz.c new file mode 100644 index 0000000..c52376b --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_fuzz.c @@ -0,0 +1,127 @@ +/* $OpenBSD: test_sshbuf_fuzz.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "sshbuf.h" + +#define NUM_FUZZ_TESTS (1 << 18) + +void sshbuf_fuzz_tests(void); + +void +sshbuf_fuzz_tests(void) +{ + struct sshbuf *p1; + u_char *dp; + size_t sz, sz2, i; + u_int32_t r; + int ret; + + /* NB. uses sshbuf internals */ + TEST_START("fuzz alloc/dealloc"); + p1 = sshbuf_new(); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0); + ASSERT_PTR_NE(p1, NULL); + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); + for (i = 0; i < NUM_FUZZ_TESTS; i++) { + r = arc4random_uniform(10); + if (r == 0) { + /* 10% chance: small reserve */ + r = arc4random_uniform(10); + fuzz_reserve: + sz = sshbuf_avail(p1); + sz2 = sshbuf_len(p1); + ret = sshbuf_reserve(p1, r, &dp); + if (ret < 0) { + ASSERT_PTR_EQ(dp, NULL); + ASSERT_SIZE_T_LT(sz, r); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); + } else { + ASSERT_PTR_NE(dp, NULL); + ASSERT_SIZE_T_GE(sz, r); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r); + memset(dp, arc4random_uniform(255) + 1, r); + } + } else if (r < 3) { + /* 20% chance: big reserve */ + r = arc4random_uniform(8 * 1024); + goto fuzz_reserve; + } else if (r == 3) { + /* 10% chance: small consume */ + r = arc4random_uniform(10); + fuzz_consume: + sz = sshbuf_avail(p1); + sz2 = sshbuf_len(p1); + /* 50% change consume from end, otherwise start */ + ret = ((arc4random() & 1) ? + sshbuf_consume : sshbuf_consume_end)(p1, r); + if (ret < 0) { + ASSERT_SIZE_T_LT(sz2, r); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2); + } else { + ASSERT_SIZE_T_GE(sz2, r); + ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r); + } + } else if (r < 8) { + /* 40% chance: big consume */ + r = arc4random_uniform(2 * 1024); + goto fuzz_consume; + } else if (r == 8) { + /* 10% chance: reset max size */ + r = arc4random_uniform(16 * 1024); + sz = sshbuf_max_size(p1); + if (sshbuf_set_max_size(p1, r) < 0) + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); + else + ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r); + } else { + if (arc4random_uniform(8192) == 0) { + /* tiny chance: new buffer */ + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); + sshbuf_free(p1); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, + 16 * 1024), 0); + } else { + /* Almost 10%: giant reserve */ + /* use arc4random_buf for r > 2^32 on 64 bit */ + arc4random_buf(&r, sizeof(r)); + while (r < SSHBUF_SIZE_MAX / 2) { + r <<= 1; + r |= arc4random() & 1; + } + goto fuzz_reserve; + } + } + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024); + } + ASSERT_PTR_NE(sshbuf_ptr(p1), NULL); + ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1)); + sshbuf_free(p1); + TEST_DONE(); +} diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_basic.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_basic.c new file mode 100644 index 0000000..966e843 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_basic.c @@ -0,0 +1,484 @@ +/* $OpenBSD: test_sshbuf_getput_basic.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include + +#include "../test_helper/test_helper.h" +#include "ssherr.h" +#include "sshbuf.h" + +void sshbuf_getput_basic_tests(void); + +void +sshbuf_getput_basic_tests(void) +{ + struct sshbuf *p1, *p2; + const u_char *cd; + u_char *d, d2[32], x[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x99 + }; + u_int64_t v64; + u_int32_t v32; + u_int16_t v16; + u_char v8; + size_t s; + char *s2; + int r; + u_char bn1[] = { 0x00, 0x00, 0x00 }; + u_char bn2[] = { 0x00, 0x00, 0x01, 0x02 }; + u_char bn3[] = { 0x00, 0x80, 0x09 }; + u_char bn_exp1[] = { 0x00, 0x00, 0x00, 0x00 }; + u_char bn_exp2[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 0x02 }; + u_char bn_exp3[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x80, 0x09 }; + + TEST_START("PEEK_U64"); + ASSERT_U64_EQ(PEEK_U64(x), 0x1122334455667788ULL); + TEST_DONE(); + + TEST_START("PEEK_U32"); + ASSERT_U32_EQ(PEEK_U32(x), 0x11223344); + TEST_DONE(); + + TEST_START("PEEK_U16"); + ASSERT_U16_EQ(PEEK_U16(x), 0x1122); + TEST_DONE(); + + TEST_START("POKE_U64"); + bzero(d2, sizeof(d2)); + POKE_U64(d2, 0x1122334455667788ULL); + ASSERT_MEM_EQ(d2, x, 8); + TEST_DONE(); + + TEST_START("POKE_U32"); + bzero(d2, sizeof(d2)); + POKE_U32(d2, 0x11223344); + ASSERT_MEM_EQ(d2, x, 4); + TEST_DONE(); + + TEST_START("POKE_U16"); + bzero(d2, sizeof(d2)); + POKE_U16(d2, 0x1122); + ASSERT_MEM_EQ(d2, x, 2); + TEST_DONE(); + + TEST_START("sshbuf_put"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 5), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5); + cd = sshbuf_ptr(p1); + ASSERT_PTR_NE(cd, NULL); + ASSERT_U8_EQ(cd[0], 0x11); + ASSERT_U8_EQ(cd[1], 0x22); + ASSERT_U8_EQ(cd[2], 0x33); + ASSERT_U8_EQ(cd[3], 0x44); + ASSERT_U8_EQ(cd[4], 0x55); + TEST_DONE(); + + TEST_START("sshbuf_get"); + ASSERT_INT_EQ(sshbuf_get(p1, d2, 4), 0); + ASSERT_MEM_EQ(d2, x, 4); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55); + TEST_DONE(); + + TEST_START("sshbuf_get truncated"); + r = sshbuf_get(p1, d2, 4); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55); + TEST_DONE(); + + TEST_START("sshbuf_put truncated"); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0); + r = sshbuf_put(p1, x, 5); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_u64"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10); + ASSERT_INT_EQ(sshbuf_get_u64(p1, &v64), 0); + ASSERT_U64_EQ(v64, 0x1122334455667788ULL); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + TEST_DONE(); + + TEST_START("sshbuf_get_u64 truncated"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + r = sshbuf_get_u64(p1, &v64); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_u32"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10); + ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0); + ASSERT_U32_EQ(v32, 0x11223344); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 6); + ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0); + ASSERT_U32_EQ(v32, 0x55667788); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + TEST_DONE(); + + TEST_START("sshbuf_get_u32 truncated"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + r = sshbuf_get_u32(p1, &v32); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_u16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 9), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 9); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); + ASSERT_U16_EQ(v16, 0x1122); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 7); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); + ASSERT_U16_EQ(v16, 0x3344); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); + ASSERT_U16_EQ(v16, 0x5566); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0); + ASSERT_U16_EQ(v16, 0x7788); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + TEST_DONE(); + + TEST_START("sshbuf_get_u16 truncated"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + r = sshbuf_get_u16(p1, &v16); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_u8"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, x, 2), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0); + ASSERT_U8_EQ(v8, 0x11); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0); + ASSERT_U8_EQ(v8, 0x22); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + TEST_DONE(); + + TEST_START("sshbuf_get_u8 truncated"); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + r = sshbuf_get_u8(p1, &v8); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u64"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u64 exact"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 8), 0); + ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u64 limited"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 7), 0); + r = sshbuf_put_u64(p1, 0x1122334455667788ULL); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u32"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u32 exact"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u32 limited"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 3), 0); + r = sshbuf_put_u32(p1, 0x11223344); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 2), 0); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_u16 limited"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1), 0); + r = sshbuf_put_u16(p1, 0x1122); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_string"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 + 4); + ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0); + ASSERT_SIZE_T_EQ(s, sizeof(x)); + ASSERT_MEM_EQ(d, x, sizeof(x)); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + free(d); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_string exact"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4), 0); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0); + ASSERT_SIZE_T_EQ(s, sizeof(x)); + ASSERT_MEM_EQ(d, x, sizeof(x)); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + free(d); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_string truncated"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3); + r = sshbuf_get_string(p1, &d, &s); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_string giant"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + r = sshbuf_get_string(p1, &d, &s); + ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_cstring giant"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + r = sshbuf_get_cstring(p1, &s2, &s); + ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_cstring embedded \\0"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + r = sshbuf_get_cstring(p1, &s2, NULL); + ASSERT_INT_EQ(r, SSH_ERR_INVALID_FORMAT); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_cstring trailing \\0"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x) - 1), 0); + ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x) - 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 - 1); + ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s2, &s), 0); + ASSERT_SIZE_T_EQ(s, sizeof(x) - 1); + ASSERT_MEM_EQ(s2, x, s); + free(s2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_string"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_string(p1, x, sizeof(x)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4); + ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), sizeof(x)); + ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, x, sizeof(x)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_string limited"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4 - 1), 0); + r = sshbuf_put_string(p1, x, sizeof(x)); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_string giant"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + r = sshbuf_put_string(p1, (void *)0x01, 0xfffffffc); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_putf"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + r = sshbuf_putf(p1, "%s %d %x", "hello", 23, 0x5f); + ASSERT_INT_EQ(r, 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 11); + ASSERT_MEM_EQ(sshbuf_ptr(p1), "hello 23 5f", 11); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_putb"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + p2 = sshbuf_new(); + ASSERT_PTR_NE(p2, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, "blahblahblah", 12), 0); + ASSERT_INT_EQ(sshbuf_putb(p2, p1), 0); + sshbuf_free(p1); + ASSERT_SIZE_T_EQ(sshbuf_len(p2), 12); + ASSERT_MEM_EQ(sshbuf_ptr(p2), "blahblahblah", 12); + sshbuf_free(p2); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes empty buf"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, NULL, 0), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes all zeroes"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn1, sizeof(bn1)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes simple"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2+2, sizeof(bn2)-2), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes leading zero"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2, sizeof(bn2)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes neg"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3+1, sizeof(bn3)-1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3)); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2_bytes neg and leading zero"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3, sizeof(bn3)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3)); + ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3)); + sshbuf_free(p1); + TEST_DONE(); +} diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c new file mode 100644 index 0000000..a68e132 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c @@ -0,0 +1,409 @@ +/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include + +#include +#include +#ifdef OPENSSL_HAS_NISTP256 +# include +#endif + +#include "../test_helper/test_helper.h" +#include "ssherr.h" +#include "sshbuf.h" + +void sshbuf_getput_crypto_tests(void); + +void +sshbuf_getput_crypto_tests(void) +{ + struct sshbuf *p1; + BIGNUM *bn, *bn2; + /* This one has num_bits != num_bytes * 8 to test bignum1 encoding */ + const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10"; + /* This one has MSB set to test bignum2 encoding negative-avoidance */ + const char *hexbn2 = "f0e0d0c0b0a0908070605040302010007fff11"; + u_char expbn1[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + }; + u_char expbn2[] = { + 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, + 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, + 0x7f, 0xff, 0x11 + }; +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) + const u_char *d; + size_t s; + BIGNUM *bn_x, *bn_y; + int ec256_nid = NID_X9_62_prime256v1; + char *ec256_x = "0C828004839D0106AA59575216191357" + "34B451459DADB586677EF9DF55784999"; + char *ec256_y = "4D196B50F0B4E94B3C73E3A9D4CD9DF2" + "C8F9A35E42BDD047550F69D80EC23CD4"; + u_char expec256[] = { + 0x04, + 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06, + 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57, + 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86, + 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99, + 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b, + 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2, + 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47, + 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4 + }; + EC_KEY *eck; + EC_POINT *ecp; +#endif + int r; + +#define MKBN(b, bnn) \ + do { \ + bnn = NULL; \ + ASSERT_INT_GT(BN_hex2bn(&bnn, b), 0); \ + } while (0) + + TEST_START("sshbuf_put_bignum1"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 2); + ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn)); + ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn1, sizeof(expbn1)); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum1 limited"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0); + r = sshbuf_put_bignum1(p1, bn); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum1 bn2"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 2); + ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn)); + ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn2, sizeof(expbn2)); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum1 bn2 limited"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0); + r = sshbuf_put_bignum1(p1, bn); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 4); + ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn)); + ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, expbn1, sizeof(expbn1)); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2 limited"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 3), 0); + r = sshbuf_put_bignum2(p1, bn); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2 bn2"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4 + 1); /* MSB */ + ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn) + 1); + ASSERT_U8_EQ(*(sshbuf_ptr(p1) + 4), 0x00); + ASSERT_MEM_EQ(sshbuf_ptr(p1) + 5, expbn2, sizeof(expbn2)); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_put_bignum2 bn2 limited"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn2) + 3), 0); + r = sshbuf_put_bignum2(p1, bn); + ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); + BN_free(bn); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum1"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1)); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); + bn2 = BN_new(); + ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0); + ASSERT_BIGNUM_EQ(bn, bn2); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum1 truncated"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1); + bn2 = BN_new(); + r = sshbuf_get_bignum1(p1, bn2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum1 giant"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xffff), 0); + ASSERT_INT_EQ(sshbuf_reserve(p1, (0xffff + 7) / 8, NULL), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8)); + bn2 = BN_new(); + r = sshbuf_get_bignum1(p1, bn2); + ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8)); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum1 bn2"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2)); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); + bn2 = BN_new(); + ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0); + ASSERT_BIGNUM_EQ(bn, bn2); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum1 bn2 truncated"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1); + bn2 = BN_new(); + r = sshbuf_get_bignum1(p1, bn2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + sizeof(expbn1)); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); + bn2 = BN_new(); + ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0); + ASSERT_BIGNUM_EQ(bn, bn2); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 truncated"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0); + bn2 = BN_new(); + r = sshbuf_get_bignum2(p1, bn2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 3); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 giant"); + MKBN(hexbn1, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 65536), 0); + ASSERT_INT_EQ(sshbuf_reserve(p1, 65536, NULL), 0); + bn2 = BN_new(); + r = sshbuf_get_bignum2(p1, bn2); + ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 65536 + 4); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 bn2"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); /* MSB */ + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + 1 + sizeof(expbn2)); + ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); + bn2 = BN_new(); + ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0); + ASSERT_BIGNUM_EQ(bn, bn2); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 bn2 truncated"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0); + bn2 = BN_new(); + r = sshbuf_get_bignum2(p1, bn2); + ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 1 + 4 - 1); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_get_bignum2 bn2 negative"); + MKBN(hexbn2, bn); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); + ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); + bn2 = BN_new(); + r = sshbuf_get_bignum2(p1, bn2); + ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_IS_NEGATIVE); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4); + BN_free(bn); + BN_free(bn2); + sshbuf_free(p1); + TEST_DONE(); + +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) + TEST_START("sshbuf_put_ec"); + eck = EC_KEY_new_by_curve_name(ec256_nid); + ASSERT_PTR_NE(eck, NULL); + ecp = EC_POINT_new(EC_KEY_get0_group(eck)); + ASSERT_PTR_NE(ecp, NULL); + MKBN(ec256_x, bn_x); + MKBN(ec256_y, bn_y); + ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp( + EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1); + ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1); + BN_free(bn_x); + BN_free(bn_y); + EC_POINT_free(ecp); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_eckey(p1, eck), 0); + ASSERT_INT_EQ(sshbuf_get_string_direct(p1, &d, &s), 0); + ASSERT_SIZE_T_EQ(s, sizeof(expec256)); + ASSERT_MEM_EQ(d, expec256, sizeof(expec256)); + sshbuf_free(p1); + EC_KEY_free(eck); + TEST_DONE(); + + TEST_START("sshbuf_get_ec"); + eck = EC_KEY_new_by_curve_name(ec256_nid); + ASSERT_PTR_NE(eck, NULL); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_string(p1, expec256, sizeof(expec256)), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expec256) + 4); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); + ASSERT_INT_EQ(sshbuf_get_eckey(p1, eck), 0); + bn_x = BN_new(); + bn_y = BN_new(); + ASSERT_PTR_NE(bn_x, NULL); + ASSERT_PTR_NE(bn_y, NULL); + ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp( + EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck), + bn_x, bn_y, NULL), 1); + MKBN(ec256_x, bn); + MKBN(ec256_y, bn2); + ASSERT_INT_EQ(BN_cmp(bn_x, bn), 0); + ASSERT_INT_EQ(BN_cmp(bn_y, bn2), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + sshbuf_free(p1); + EC_KEY_free(eck); + BN_free(bn_x); + BN_free(bn_y); + BN_free(bn); + BN_free(bn2); + TEST_DONE(); +#endif +} + diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c new file mode 100644 index 0000000..c6b5c29 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c @@ -0,0 +1,130 @@ +/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.2 2014/05/02 02:54:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include + +#include +#include +#ifdef OPENSSL_HAS_NISTP256 +# include +#endif + +#include "../test_helper/test_helper.h" +#include "ssherr.h" +#include "sshbuf.h" + +void sshbuf_getput_fuzz_tests(void); + +static void +attempt_parse_blob(u_char *blob, size_t len) +{ + struct sshbuf *p1; + BIGNUM *bn; +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) + EC_KEY *eck; +#endif + u_char *s; + size_t l; + u_int8_t u8; + u_int16_t u16; + u_int32_t u32; + u_int64_t u64; + + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0); + sshbuf_get_u8(p1, &u8); + sshbuf_get_u16(p1, &u16); + sshbuf_get_u32(p1, &u32); + sshbuf_get_u64(p1, &u64); + if (sshbuf_get_string(p1, &s, &l) == 0) { + bzero(s, l); + free(s); + } + bn = BN_new(); + sshbuf_get_bignum1(p1, bn); + BN_clear_free(bn); + bn = BN_new(); + sshbuf_get_bignum2(p1, bn); + BN_clear_free(bn); +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) + eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + ASSERT_PTR_NE(eck, NULL); + sshbuf_get_eckey(p1, eck); + EC_KEY_free(eck); +#endif + sshbuf_free(p1); +} + + +static void +onerror(void *fuzz) +{ + fprintf(stderr, "Failed during fuzz:\n"); + fuzz_dump((struct fuzz *)fuzz); +} + +void +sshbuf_getput_fuzz_tests(void) +{ + u_char blob[] = { + /* u8 */ + 0xd0, + /* u16 */ + 0xc0, 0xde, + /* u32 */ + 0xfa, 0xce, 0xde, 0xad, + /* u64 */ + 0xfe, 0xed, 0xac, 0x1d, 0x1f, 0x1c, 0xbe, 0xef, + /* string */ + 0x00, 0x00, 0x00, 0x09, + 'O', ' ', 'G', 'o', 'r', 'g', 'o', 'n', '!', + /* bignum1 */ + 0x79, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + /* bignum2 */ + 0x00, 0x00, 0x00, 0x14, + 0x00, + 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, + 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, + 0x7f, 0xff, 0x11, + /* EC point (NIST-256 curve) */ + 0x00, 0x00, 0x00, 0x41, + 0x04, + 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06, + 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57, + 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86, + 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99, + 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b, + 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2, + 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47, + 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4, + }; + struct fuzz *fuzz; + + TEST_START("fuzz blob parsing"); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP | + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, blob, sizeof(blob)); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) + attempt_parse_blob(blob, sizeof(blob)); + fuzz_cleanup(fuzz); + TEST_DONE(); + TEST_ONERROR(NULL, NULL); +} + diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_misc.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_misc.c new file mode 100644 index 0000000..f155491 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_misc.c @@ -0,0 +1,138 @@ +/* $OpenBSD: test_sshbuf_misc.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include + +#include "../test_helper/test_helper.h" + +#include "sshbuf.h" + +void sshbuf_misc_tests(void); + +void +sshbuf_misc_tests(void) +{ + struct sshbuf *p1; + char tmp[512], *p; + FILE *out; + size_t sz; + + TEST_START("sshbuf_dump"); + out = tmpfile(); + ASSERT_PTR_NE(out, NULL); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); + sshbuf_dump(p1, out); + fflush(out); + rewind(out); + sz = fread(tmp, 1, sizeof(tmp), out); + ASSERT_INT_EQ(ferror(out), 0); + ASSERT_INT_NE(feof(out), 0); + ASSERT_SIZE_T_GT(sz, 0); + tmp[sz] = '\0'; + ASSERT_PTR_NE(strstr(tmp, "12 34 56 78"), NULL); + fclose(out); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob16"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0); + p = sshbuf_dtob16(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_STRING_EQ(p, "12345678"); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob64 len 1"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); + p = sshbuf_dtob64(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_STRING_EQ(p, "EQ=="); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob64 len 2"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0); + p = sshbuf_dtob64(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_STRING_EQ(p, "ESI="); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob64 len 3"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0); + ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x33), 0); + p = sshbuf_dtob64(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_STRING_EQ(p, "ESIz"); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_dtob64 len 8191"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_reserve(p1, 8192, NULL), 0); + bzero(sshbuf_mutable_ptr(p1), 8192); + p = sshbuf_dtob64(p1); + ASSERT_PTR_NE(p, NULL); + ASSERT_SIZE_T_EQ(strlen(p), ((8191 + 2) / 3) * 4); + free(p); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_b64tod len 1"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A=="), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); + ASSERT_U8_EQ(*sshbuf_ptr(p1), 0xd0); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_b64tod len 2"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A8="), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); + ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), 0xd00f); + sshbuf_free(p1); + TEST_DONE(); + + TEST_START("sshbuf_b64tod len 4"); + p1 = sshbuf_new(); + ASSERT_PTR_NE(p1, NULL); + ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A/QDw=="), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4); + ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), 0xd00fd00f); + sshbuf_free(p1); + TEST_DONE(); +} + diff --git a/crypto/openssh/regress/unittests/sshbuf/tests.c b/crypto/openssh/regress/unittests/sshbuf/tests.c new file mode 100644 index 0000000..1557e43 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshbuf/tests.c @@ -0,0 +1,28 @@ +/* $OpenBSD: tests.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "../test_helper/test_helper.h" + +void sshbuf_tests(void); +void sshbuf_getput_basic_tests(void); +void sshbuf_getput_crypto_tests(void); +void sshbuf_misc_tests(void); +void sshbuf_fuzz_tests(void); +void sshbuf_getput_fuzz_tests(void); +void sshbuf_fixed(void); + +void +tests(void) +{ + sshbuf_tests(); + sshbuf_getput_basic_tests(); + sshbuf_getput_crypto_tests(); + sshbuf_misc_tests(); + sshbuf_fuzz_tests(); + sshbuf_getput_fuzz_tests(); + sshbuf_fixed(); +} diff --git a/crypto/openssh/regress/unittests/sshkey/Makefile b/crypto/openssh/regress/unittests/sshkey/Makefile new file mode 100644 index 0000000..1bcd266 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/Makefile @@ -0,0 +1,13 @@ +# $OpenBSD: Makefile,v 1.1 2014/06/24 01:14:18 djm Exp $ + +TEST_ENV= "MALLOC_OPTIONS=AFGJPRX" + +PROG=test_sshkey +SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata + +.include + diff --git a/crypto/openssh/regress/unittests/sshkey/common.c b/crypto/openssh/regress/unittests/sshkey/common.c new file mode 100644 index 0000000..b598f05 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/common.c @@ -0,0 +1,84 @@ +/* $OpenBSD: common.c,v 1.2 2015/01/08 13:10:58 djm Exp $ */ +/* + * Helpers for key API tests + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#ifdef OPENSSL_HAS_NISTP256 +# include +#endif + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "authfile.h" +#include "sshkey.h" +#include "sshbuf.h" + +#include "common.h" + +struct sshbuf * +load_file(const char *name) +{ + int fd; + struct sshbuf *ret; + + ASSERT_PTR_NE(ret = sshbuf_new(), NULL); + ASSERT_INT_NE(fd = open(test_data_file(name), O_RDONLY), -1); + ASSERT_INT_EQ(sshkey_load_file(fd, ret), 0); + close(fd); + return ret; +} + +struct sshbuf * +load_text_file(const char *name) +{ + struct sshbuf *ret = load_file(name); + const u_char *p; + + /* Trim whitespace at EOL */ + for (p = sshbuf_ptr(ret); sshbuf_len(ret) > 0;) { + if (p[sshbuf_len(ret) - 1] == '\r' || + p[sshbuf_len(ret) - 1] == '\t' || + p[sshbuf_len(ret) - 1] == ' ' || + p[sshbuf_len(ret) - 1] == '\n') + ASSERT_INT_EQ(sshbuf_consume_end(ret, 1), 0); + else + break; + } + /* \0 terminate */ + ASSERT_INT_EQ(sshbuf_put_u8(ret, 0), 0); + return ret; +} + +BIGNUM * +load_bignum(const char *name) +{ + BIGNUM *ret = NULL; + struct sshbuf *buf; + + buf = load_text_file(name); + ASSERT_INT_NE(BN_hex2bn(&ret, (const char *)sshbuf_ptr(buf)), 0); + sshbuf_free(buf); + return ret; +} + diff --git a/crypto/openssh/regress/unittests/sshkey/common.h b/crypto/openssh/regress/unittests/sshkey/common.h new file mode 100644 index 0000000..bf7d19d --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/common.h @@ -0,0 +1,16 @@ +/* $OpenBSD: common.h,v 1.1 2014/06/24 01:14:18 djm Exp $ */ +/* + * Helpers for key API tests + * + * Placed in the public domain + */ + +/* Load a binary file into a buffer */ +struct sshbuf *load_file(const char *name); + +/* Load a text file into a buffer */ +struct sshbuf *load_text_file(const char *name); + +/* Load a bignum from a file */ +BIGNUM *load_bignum(const char *name); + diff --git a/crypto/openssh/regress/unittests/sshkey/mktestdata.sh b/crypto/openssh/regress/unittests/sshkey/mktestdata.sh new file mode 100755 index 0000000..e111001 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/mktestdata.sh @@ -0,0 +1,192 @@ +#!/bin/sh +# $OpenBSD: mktestdata.sh,v 1.5 2015/07/07 14:53:30 markus Exp $ + +PW=mekmitasdigoat + +rsa1_params() { + _in="$1" + _outbase="$2" + set -e + ssh-keygen -f $_in -e -m pkcs8 | \ + openssl rsa -noout -text -pubin | \ + awk '/^Modulus:$/,/^Exponent:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n + # XXX need conversion support in ssh-keygen for the other params + for x in n ; do + echo "" >> ${_outbase}.$x + echo ============ ${_outbase}.$x + cat ${_outbase}.$x + echo ============ + done +} + +rsa_params() { + _in="$1" + _outbase="$2" + set -e + openssl rsa -noout -text -in $_in | \ + awk '/^modulus:$/,/^publicExponent:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n + openssl rsa -noout -text -in $_in | \ + awk '/^prime1:$/,/^prime2:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.p + openssl rsa -noout -text -in $_in | \ + awk '/^prime2:$/,/^exponent1:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.q + for x in n p q ; do + echo "" >> ${_outbase}.$x + echo ============ ${_outbase}.$x + cat ${_outbase}.$x + echo ============ + done +} + +dsa_params() { + _in="$1" + _outbase="$2" + set -e + openssl dsa -noout -text -in $_in | \ + awk '/^priv:$/,/^pub:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv + openssl dsa -noout -text -in $_in | \ + awk '/^pub:/,/^P:/' | #\ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub + openssl dsa -noout -text -in $_in | \ + awk '/^G:/,0' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.g + for x in priv pub g ; do + echo "" >> ${_outbase}.$x + echo ============ ${_outbase}.$x + cat ${_outbase}.$x + echo ============ + done +} + +ecdsa_params() { + _in="$1" + _outbase="$2" + set -e + openssl ec -noout -text -in $_in | \ + awk '/^priv:$/,/^pub:/' | \ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv + openssl ec -noout -text -in $_in | \ + awk '/^pub:/,/^ASN1 OID:/' | #\ + grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub + openssl ec -noout -text -in $_in | \ + grep "ASN1 OID:" | tr -d '\n' | \ + sed 's/.*: //;s/ *$//' > ${_outbase}.curve + for x in priv pub curve ; do + echo "" >> ${_outbase}.$x + echo ============ ${_outbase}.$x + cat ${_outbase}.$x + echo ============ + done +} + +set -ex + +cd testdata + +rm -f rsa1_1 rsa_1 dsa_1 ecdsa_1 ed25519_1 +rm -f rsa1_2 rsa_2 dsa_2 ecdsa_2 ed25519_2 +rm -f rsa_n dsa_n ecdsa_n # new-format keys +rm -f rsa1_1_pw rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw +rm -f rsa_n_pw dsa_n_pw ecdsa_n_pw +rm -f pw *.pub *.bn.* *.param.* *.fp *.fp.bb + +ssh-keygen -t rsa1 -b 1024 -C "RSA1 test key #1" -N "" -f rsa1_1 +ssh-keygen -t rsa -b 1024 -C "RSA test key #1" -N "" -f rsa_1 +ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 +ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 +ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1 + +ssh-keygen -t rsa1 -b 2048 -C "RSA1 test key #2" -N "" -f rsa1_2 +ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 +ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 +ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 +ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_2 + +cp rsa_1 rsa_n +cp dsa_1 dsa_n +cp ecdsa_1 ecdsa_n + +cp rsa1_1 rsa1_1_pw +cp rsa_1 rsa_1_pw +cp dsa_1 dsa_1_pw +cp ecdsa_1 ecdsa_1_pw +cp ed25519_1 ed25519_1_pw +cp rsa_1 rsa_n_pw +cp dsa_1 dsa_n_pw +cp ecdsa_1 ecdsa_n_pw + +ssh-keygen -pf rsa1_1_pw -N "$PW" +ssh-keygen -pf rsa_1_pw -N "$PW" +ssh-keygen -pf dsa_1_pw -N "$PW" +ssh-keygen -pf ecdsa_1_pw -N "$PW" +ssh-keygen -pf ed25519_1_pw -N "$PW" +ssh-keygen -opf rsa_n_pw -N "$PW" +ssh-keygen -opf dsa_n_pw -N "$PW" +ssh-keygen -opf ecdsa_n_pw -N "$PW" + +rsa1_params rsa1_1 rsa1_1.param +rsa1_params rsa1_2 rsa1_2.param +rsa_params rsa_1 rsa_1.param +rsa_params rsa_2 rsa_2.param +dsa_params dsa_1 dsa_1.param +dsa_params dsa_1 dsa_1.param +ecdsa_params ecdsa_1 ecdsa_1.param +ecdsa_params ecdsa_2 ecdsa_2.param +# XXX ed25519 params + +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 1 rsa_1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 2 dsa_1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 3 ecdsa_1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 4 ed25519_1.pub + +ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 5 rsa_1.pub +ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 6 dsa_1.pub +ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 7 ecdsa_1.pub +ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 8 ed25519_1.pub + +ssh-keygen -lf rsa1_1 | awk '{print $2}' > rsa1_1.fp +ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp +ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp +ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp +ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp +ssh-keygen -lf rsa1_2 | awk '{print $2}' > rsa1_2.fp +ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp +ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp +ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp +ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp + +ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp +ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp +ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp +ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp + +ssh-keygen -Bf rsa1_1 | awk '{print $2}' > rsa1_1.fp.bb +ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb +ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb +ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb +ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb +ssh-keygen -Bf rsa1_2 | awk '{print $2}' > rsa1_2.fp.bb +ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb +ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb +ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb +ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb + +# XXX Extend ssh-keygen to do detached signatures (better to test/fuzz against) + +echo "$PW" > pw diff --git a/crypto/openssh/regress/unittests/sshkey/test_file.c b/crypto/openssh/regress/unittests/sshkey/test_file.c new file mode 100644 index 0000000..c8a2369 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/test_file.c @@ -0,0 +1,460 @@ +/* $OpenBSD: test_file.c,v 1.4 2015/07/07 14:53:30 markus Exp $ */ +/* + * Regress test for sshkey.h key management API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#ifdef OPENSSL_HAS_NISTP256 +# include +#endif + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "authfile.h" +#include "sshkey.h" +#include "sshbuf.h" +#include "digest.h" + +#include "common.h" + +void sshkey_file_tests(void); + +void +sshkey_file_tests(void) +{ + struct sshkey *k1, *k2; + struct sshbuf *buf, *pw; + BIGNUM *a, *b, *c; + char *cp; + + TEST_START("load passphrase"); + pw = load_text_file("pw"); + TEST_DONE(); + +#ifdef WITH_SSH1 + TEST_START("parse RSA1 from private"); + buf = load_file("rsa1_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa1_1", + &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + a = load_bignum("rsa1_1.param.n"); + ASSERT_BIGNUM_EQ(k1->rsa->n, a); + BN_free(a); + TEST_DONE(); + + TEST_START("parse RSA1 from private w/ passphrase"); + buf = load_file("rsa1_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), "rsa1_1_pw", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load RSA1 from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa1_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("RSA1 key hex fingerprint"); + buf = load_text_file("rsa1_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("RSA1 key bubblebabble fingerprint"); + buf = load_text_file("rsa1_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); +#endif + + TEST_START("parse RSA from private"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa_1", + &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + a = load_bignum("rsa_1.param.n"); + b = load_bignum("rsa_1.param.p"); + c = load_bignum("rsa_1.param.q"); + ASSERT_BIGNUM_EQ(k1->rsa->n, a); + ASSERT_BIGNUM_EQ(k1->rsa->p, b); + ASSERT_BIGNUM_EQ(k1->rsa->q, c); + BN_free(a); + BN_free(b); + BN_free(c); + TEST_DONE(); + + TEST_START("parse RSA from private w/ passphrase"); + buf = load_file("rsa_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), "rsa_1_pw", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse RSA from new-format"); + buf = load_file("rsa_n"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + "", "rsa_n", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse RSA from new-format w/ passphrase"); + buf = load_file("rsa_n_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), "rsa_n_pw", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load RSA from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load RSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_RSA_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("RSA key hex fingerprint"); + buf = load_text_file("rsa_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("RSA cert hex fingerprint"); + buf = load_text_file("rsa_1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("RSA key bubblebabble fingerprint"); + buf = load_text_file("rsa_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); + + TEST_START("parse DSA from private"); + buf = load_file("dsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "dsa_1", + &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + a = load_bignum("dsa_1.param.g"); + b = load_bignum("dsa_1.param.priv"); + c = load_bignum("dsa_1.param.pub"); + ASSERT_BIGNUM_EQ(k1->dsa->g, a); + ASSERT_BIGNUM_EQ(k1->dsa->priv_key, b); + ASSERT_BIGNUM_EQ(k1->dsa->pub_key, c); + BN_free(a); + BN_free(b); + BN_free(c); + TEST_DONE(); + + TEST_START("parse DSA from private w/ passphrase"); + buf = load_file("dsa_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), "dsa_1_pw", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse DSA from new-format"); + buf = load_file("dsa_n"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + "", "dsa_n", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse DSA from new-format w/ passphrase"); + buf = load_file("dsa_n_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), "dsa_n_pw", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load DSA from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load DSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_DSA_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("DSA key hex fingerprint"); + buf = load_text_file("dsa_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("DSA cert hex fingerprint"); + buf = load_text_file("dsa_1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("DSA key bubblebabble fingerprint"); + buf = load_text_file("dsa_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); + +#ifdef OPENSSL_HAS_ECC + TEST_START("parse ECDSA from private"); + buf = load_file("ecdsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "ecdsa_1", + &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + buf = load_text_file("ecdsa_1.param.curve"); + ASSERT_STRING_EQ((const char *)sshbuf_ptr(buf), + OBJ_nid2sn(k1->ecdsa_nid)); + sshbuf_free(buf); + a = load_bignum("ecdsa_1.param.priv"); + b = load_bignum("ecdsa_1.param.pub"); + c = EC_POINT_point2bn(EC_KEY_get0_group(k1->ecdsa), + EC_KEY_get0_public_key(k1->ecdsa), POINT_CONVERSION_UNCOMPRESSED, + NULL, NULL); + ASSERT_PTR_NE(c, NULL); + ASSERT_BIGNUM_EQ(EC_KEY_get0_private_key(k1->ecdsa), a); + ASSERT_BIGNUM_EQ(b, c); + BN_free(a); + BN_free(b); + BN_free(c); + TEST_DONE(); + + TEST_START("parse ECDSA from private w/ passphrase"); + buf = load_file("ecdsa_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), "ecdsa_1_pw", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse ECDSA from new-format"); + buf = load_file("ecdsa_n"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + "", "ecdsa_n", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("parse ECDSA from new-format w/ passphrase"); + buf = load_file("ecdsa_n_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), "ecdsa_n_pw", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load ECDSA from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load ECDSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_ECDSA_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("ECDSA key hex fingerprint"); + buf = load_text_file("ecdsa_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("ECDSA cert hex fingerprint"); + buf = load_text_file("ecdsa_1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("ECDSA key bubblebabble fingerprint"); + buf = load_text_file("ecdsa_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); +#endif /* OPENSSL_HAS_ECC */ + + TEST_START("parse Ed25519 from private"); + buf = load_file("ed25519_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "ed25519_1", + &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + ASSERT_INT_EQ(k1->type, KEY_ED25519); + /* XXX check key contents */ + TEST_DONE(); + + TEST_START("parse Ed25519 from private w/ passphrase"); + buf = load_file("ed25519_1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), "ed25519_1_pw", &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load Ed25519 from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load Ed25519 cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_ED25519_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("Ed25519 key hex fingerprint"); + buf = load_text_file("ed25519_1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("Ed25519 cert hex fingerprint"); + buf = load_text_file("ed25519_1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("Ed25519 key bubblebabble fingerprint"); + buf = load_text_file("ed25519_1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); + + sshbuf_free(pw); + +} diff --git a/crypto/openssh/regress/unittests/sshkey/test_fuzz.c b/crypto/openssh/regress/unittests/sshkey/test_fuzz.c new file mode 100644 index 0000000..1f08a2e4 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/test_fuzz.c @@ -0,0 +1,411 @@ +/* $OpenBSD: test_fuzz.c,v 1.4 2015/03/04 23:22:35 djm Exp $ */ +/* + * Fuzz tests for key parsing + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#ifdef OPENSSL_HAS_NISTP256 +# include +#endif + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "authfile.h" +#include "sshkey.h" +#include "sshbuf.h" + +#include "common.h" + +void sshkey_fuzz_tests(void); + +static void +onerror(void *fuzz) +{ + fprintf(stderr, "Failed during fuzz:\n"); + fuzz_dump((struct fuzz *)fuzz); +} + +static void +public_fuzz(struct sshkey *k) +{ + struct sshkey *k1; + struct sshbuf *buf; + struct fuzz *fuzz; + + ASSERT_PTR_NE(buf = sshbuf_new(), NULL); + ASSERT_INT_EQ(sshkey_putb(k, buf), 0); + /* XXX need a way to run the tests in "slow, but complete" mode */ + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */ + FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */ + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, + sshbuf_mutable_ptr(buf), sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf), + &k1), 0); + sshkey_free(k1); + sshbuf_free(buf); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0) + sshkey_free(k1); + } + fuzz_cleanup(fuzz); +} + +static void +sig_fuzz(struct sshkey *k) +{ + struct fuzz *fuzz; + u_char *sig, c[] = "some junk to be signed"; + size_t l; + + ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), 0), 0); + ASSERT_SIZE_T_GT(l, 0); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* too slow FUZZ_2_BIT_FLIP | */ + FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, sig, l); + ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), 0), 0); + free(sig); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + /* Ensure 1-bit difference at least */ + if (fuzz_matches_original(fuzz)) + continue; + ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz), + c, sizeof(c), 0), 0); + } + fuzz_cleanup(fuzz); +} + +void +sshkey_fuzz_tests(void) +{ + struct sshkey *k1; + struct sshbuf *buf, *fuzzed; + struct fuzz *fuzz; + int r; + +#ifdef WITH_SSH1 + TEST_START("fuzz RSA1 private"); + buf = load_file("rsa1_1"); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, + sshbuf_mutable_ptr(buf), sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", "key", + &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz RSA1 public"); + buf = load_file("rsa1_1_pw"); + fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | + FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, + sshbuf_mutable_ptr(buf), sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); +#endif + + TEST_START("fuzz RSA private"); + buf = load_file("rsa_1"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", "key", + &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz RSA new-format private"); + buf = load_file("rsa_n"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", "key", + &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz DSA private"); + buf = load_file("dsa_1"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", "key", + &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz DSA new-format private"); + buf = load_file("dsa_n"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", "key", + &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("fuzz ECDSA private"); + buf = load_file("ecdsa_1"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", "key", + &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz ECDSA new-format private"); + buf = load_file("ecdsa_n"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", "key", + &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); +#endif + + TEST_START("fuzz Ed25519 private"); + buf = load_file("ed25519_1"); + fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshkey_free(k1); + sshbuf_free(buf); + ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); + TEST_ONERROR(onerror, fuzz); + for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { + r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); + ASSERT_INT_EQ(r, 0); + if (sshkey_parse_private_fileblob(fuzzed, "", "key", + &k1, NULL) == 0) + sshkey_free(k1); + sshbuf_reset(fuzzed); + } + sshbuf_free(fuzzed); + fuzz_cleanup(fuzz); + TEST_DONE(); + + TEST_START("fuzz RSA public"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshbuf_free(buf); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz RSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz DSA public"); + buf = load_file("dsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshbuf_free(buf); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz DSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("fuzz ECDSA public"); + buf = load_file("ecdsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshbuf_free(buf); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz ECDSA cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); +#endif + + TEST_START("fuzz Ed25519 public"); + buf = load_file("ed25519_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshbuf_free(buf); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz Ed25519 cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0); + public_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz RSA sig"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("fuzz DSA sig"); + buf = load_file("dsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("fuzz ECDSA sig"); + buf = load_file("ecdsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); +#endif + + TEST_START("fuzz Ed25519 sig"); + buf = load_file("ed25519_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", + &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1); + sshkey_free(k1); + TEST_DONE(); + +/* XXX fuzz decoded new-format blobs too */ + +} diff --git a/crypto/openssh/regress/unittests/sshkey/test_sshkey.c b/crypto/openssh/regress/unittests/sshkey/test_sshkey.c new file mode 100644 index 0000000..9b3ce7e --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/test_sshkey.c @@ -0,0 +1,521 @@ +/* $OpenBSD: test_sshkey.c,v 1.7 2015/08/05 05:27:33 djm Exp $ */ +/* + * Regress test for sshkey.h key management API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include + +#include +#include +#include +#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) +# include +#endif + +#include "../test_helper/test_helper.h" + +#include "ssherr.h" +#include "sshbuf.h" +#define SSHBUF_INTERNAL 1 /* access internals for testing */ +#include "sshkey.h" + +#include "authfile.h" +#include "common.h" +#include "ssh2.h" + +void sshkey_tests(void); + +static void +put_opt(struct sshbuf *b, const char *name, const char *value) +{ + struct sshbuf *sect; + + sect = sshbuf_new(); + ASSERT_PTR_NE(sect, NULL); + ASSERT_INT_EQ(sshbuf_put_cstring(b, name), 0); + if (value != NULL) + ASSERT_INT_EQ(sshbuf_put_cstring(sect, value), 0); + ASSERT_INT_EQ(sshbuf_put_stringb(b, sect), 0); + sshbuf_free(sect); +} + +static void +build_cert(struct sshbuf *b, const struct sshkey *k, const char *type, + const struct sshkey *sign_key, const struct sshkey *ca_key) +{ + struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts; + u_char *sigblob; + size_t siglen; + + ca_buf = sshbuf_new(); + ASSERT_PTR_NE(ca_buf, NULL); + ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0); + + /* + * Get the public key serialisation by rendering the key and skipping + * the type string. This is a bit of a hack :/ + */ + pk = sshbuf_new(); + ASSERT_PTR_NE(pk, NULL); + ASSERT_INT_EQ(sshkey_putb_plain(k, pk), 0); + ASSERT_INT_EQ(sshbuf_skip_string(pk), 0); + + principals = sshbuf_new(); + ASSERT_PTR_NE(principals, NULL); + ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0); + ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0); + + critopts = sshbuf_new(); + ASSERT_PTR_NE(critopts, NULL); + put_opt(critopts, "force-command", "/usr/local/bin/nethack"); + put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1"); + + exts = sshbuf_new(); + ASSERT_PTR_NE(exts, NULL); + put_opt(critopts, "permit-X11-forwarding", NULL); + + ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0); + ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */ + ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */ + ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */ + ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */ + ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */ + ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */ + ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */ + ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ + ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ + ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, + sshbuf_ptr(b), sshbuf_len(b), 0), 0); + ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ + + free(sigblob); + sshbuf_free(ca_buf); + sshbuf_free(exts); + sshbuf_free(critopts); + sshbuf_free(principals); + sshbuf_free(pk); +} + +static void +signature_test(struct sshkey *k, struct sshkey *bad, const u_char *d, size_t l) +{ + size_t len; + u_char *sig; + + ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, 0), 0); + ASSERT_SIZE_T_GT(len, 8); + ASSERT_PTR_NE(sig, NULL); + ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, 0), 0); + ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, 0), 0); + /* Fuzz test is more comprehensive, this is just a smoke test */ + sig[len - 5] ^= 0x10; + ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, 0), 0); + free(sig); +} + +static void +banana(u_char *s, size_t l) +{ + size_t o; + const u_char the_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a' }; + + for (o = 0; o < l; o += sizeof(the_banana)) { + if (l - o < sizeof(the_banana)) { + memcpy(s + o, "nanananana", l - o); + break; + } + memcpy(s + o, banana, sizeof(the_banana)); + } +} + +static void +signature_tests(struct sshkey *k, struct sshkey *bad) +{ + u_char i, buf[2049]; + size_t lens[] = { + 1, 2, 7, 8, 9, 15, 16, 17, 31, 32, 33, 127, 128, 129, + 255, 256, 257, 1023, 1024, 1025, 2047, 2048, 2049 + }; + + for (i = 0; i < (sizeof(lens)/sizeof(lens[0])); i++) { + test_subtest_info("%s key, banana length %zu", + sshkey_type(k), lens[i]); + banana(buf, lens[i]); + signature_test(k, bad, buf, lens[i]); + } +} + +static struct sshkey * +get_private(const char *n) +{ + struct sshbuf *b; + struct sshkey *ret; + + b = load_file(n); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", n, &ret, NULL), 0); + sshbuf_free(b); + return ret; +} + +void +sshkey_tests(void) +{ + struct sshkey *k1, *k2, *k3, *k4, *kr, *kd, *kf; +#ifdef OPENSSL_HAS_ECC + struct sshkey *ke; +#endif + struct sshbuf *b; + + TEST_START("new invalid"); + k1 = sshkey_new(-42); + ASSERT_PTR_EQ(k1, NULL); + TEST_DONE(); + + TEST_START("new/free KEY_UNSPEC"); + k1 = sshkey_new(KEY_UNSPEC); + ASSERT_PTR_NE(k1, NULL); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("new/free KEY_RSA1"); + k1 = sshkey_new(KEY_RSA1); + ASSERT_PTR_NE(k1, 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); + TEST_DONE(); + + TEST_START("new/free KEY_RSA"); + k1 = sshkey_new(KEY_RSA); + ASSERT_PTR_NE(k1, 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); + TEST_DONE(); + + TEST_START("new/free KEY_DSA"); + k1 = sshkey_new(KEY_DSA); + ASSERT_PTR_NE(k1, 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); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("new/free KEY_ECDSA"); + k1 = sshkey_new(KEY_ECDSA); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */ + sshkey_free(k1); + TEST_DONE(); +#endif + + TEST_START("new/free KEY_ED25519"); + k1 = sshkey_new(KEY_ED25519); + ASSERT_PTR_NE(k1, NULL); + /* These should be blank until key loaded or generated */ + ASSERT_PTR_EQ(k1->ed25519_sk, NULL); + ASSERT_PTR_EQ(k1->ed25519_pk, NULL); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("new_private KEY_RSA"); + k1 = sshkey_new_private(KEY_RSA); + ASSERT_PTR_NE(k1, 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); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("new_private KEY_DSA"); + k1 = sshkey_new_private(KEY_DSA); + ASSERT_PTR_NE(k1, 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); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("generate KEY_RSA too small modulus"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 128, &k1), + SSH_ERR_INVALID_ARGUMENT); + ASSERT_PTR_EQ(k1, NULL); + TEST_DONE(); + + TEST_START("generate KEY_RSA too large modulus"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1 << 20, &k1), + SSH_ERR_INVALID_ARGUMENT); + ASSERT_PTR_EQ(k1, NULL); + TEST_DONE(); + + TEST_START("generate KEY_DSA wrong bits"); + ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 2048, &k1), + SSH_ERR_INVALID_ARGUMENT); + ASSERT_PTR_EQ(k1, NULL); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("generate KEY_ECDSA wrong bits"); + ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1), + SSH_ERR_INVALID_ARGUMENT); + ASSERT_PTR_EQ(k1, NULL); + sshkey_free(k1); + TEST_DONE(); +#endif + + TEST_START("generate KEY_RSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 767, &kr), + SSH_ERR_INVALID_ARGUMENT); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0); + ASSERT_PTR_NE(kr, NULL); + ASSERT_PTR_NE(kr->rsa, NULL); + ASSERT_PTR_NE(kr->rsa->n, NULL); + 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_START("generate KEY_DSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); + ASSERT_PTR_NE(kd, NULL); + ASSERT_PTR_NE(kd->dsa, NULL); + ASSERT_PTR_NE(kd->dsa->g, NULL); + ASSERT_PTR_NE(kd->dsa->priv_key, NULL); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("generate KEY_ECDSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &ke), 0); + ASSERT_PTR_NE(ke, NULL); + ASSERT_PTR_NE(ke->ecdsa, NULL); + ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL); + ASSERT_PTR_NE(EC_KEY_get0_private_key(ke->ecdsa), NULL); + TEST_DONE(); +#endif + + TEST_START("generate KEY_ED25519"); + ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &kf), 0); + ASSERT_PTR_NE(kf, NULL); + ASSERT_INT_EQ(kf->type, KEY_ED25519); + ASSERT_PTR_NE(kf->ed25519_pk, NULL); + ASSERT_PTR_NE(kf->ed25519_sk, NULL); + TEST_DONE(); + + TEST_START("demote KEY_RSA"); + ASSERT_INT_EQ(sshkey_demote(kr, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(kr, k1); + ASSERT_INT_EQ(k1->type, KEY_RSA); + 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_START("equal KEY_RSA/demoted KEY_RSA"); + ASSERT_INT_EQ(sshkey_equal(kr, k1), 1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("demote KEY_DSA"); + ASSERT_INT_EQ(sshkey_demote(kd, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(kd, k1); + ASSERT_INT_EQ(k1->type, KEY_DSA); + ASSERT_PTR_NE(k1->dsa, NULL); + ASSERT_PTR_NE(k1->dsa->g, NULL); + ASSERT_PTR_EQ(k1->dsa->priv_key, NULL); + TEST_DONE(); + + TEST_START("equal KEY_DSA/demoted KEY_DSA"); + ASSERT_INT_EQ(sshkey_equal(kd, k1), 1); + sshkey_free(k1); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("demote KEY_ECDSA"); + ASSERT_INT_EQ(sshkey_demote(ke, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(ke, k1); + ASSERT_INT_EQ(k1->type, KEY_ECDSA); + ASSERT_PTR_NE(k1->ecdsa, NULL); + ASSERT_INT_EQ(k1->ecdsa_nid, ke->ecdsa_nid); + ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL); + ASSERT_PTR_EQ(EC_KEY_get0_private_key(k1->ecdsa), NULL); + TEST_DONE(); + + TEST_START("equal KEY_ECDSA/demoted KEY_ECDSA"); + ASSERT_INT_EQ(sshkey_equal(ke, k1), 1); + sshkey_free(k1); + TEST_DONE(); +#endif + + TEST_START("demote KEY_ED25519"); + ASSERT_INT_EQ(sshkey_demote(kf, &k1), 0); + ASSERT_PTR_NE(k1, NULL); + ASSERT_PTR_NE(kf, k1); + ASSERT_INT_EQ(k1->type, KEY_ED25519); + ASSERT_PTR_NE(k1->ed25519_pk, NULL); + ASSERT_PTR_EQ(k1->ed25519_sk, NULL); + TEST_DONE(); + + TEST_START("equal KEY_ED25519/demoted KEY_ED25519"); + ASSERT_INT_EQ(sshkey_equal(kf, k1), 1); + sshkey_free(k1); + TEST_DONE(); + + TEST_START("equal mismatched key types"); + ASSERT_INT_EQ(sshkey_equal(kd, kr), 0); +#ifdef OPENSSL_HAS_ECC + ASSERT_INT_EQ(sshkey_equal(kd, ke), 0); + ASSERT_INT_EQ(sshkey_equal(kr, ke), 0); + ASSERT_INT_EQ(sshkey_equal(ke, kf), 0); +#endif + ASSERT_INT_EQ(sshkey_equal(kd, kf), 0); + TEST_DONE(); + + TEST_START("equal different keys"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &k1), 0); + ASSERT_INT_EQ(sshkey_equal(kr, k1), 0); + sshkey_free(k1); + ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &k1), 0); + ASSERT_INT_EQ(sshkey_equal(kd, k1), 0); + sshkey_free(k1); +#ifdef OPENSSL_HAS_ECC + ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &k1), 0); + ASSERT_INT_EQ(sshkey_equal(ke, k1), 0); + sshkey_free(k1); +#endif + ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &k1), 0); + ASSERT_INT_EQ(sshkey_equal(kf, k1), 0); + sshkey_free(k1); + TEST_DONE(); + + sshkey_free(kr); + sshkey_free(kd); +#ifdef OPENSSL_HAS_ECC + sshkey_free(ke); +#endif + sshkey_free(kf); + + TEST_START("certify key"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"), + &k1, NULL), 0); + k2 = get_private("ed25519_2"); + ASSERT_INT_EQ(sshkey_to_certified(k1), 0); + ASSERT_PTR_NE(k1->cert, NULL); + k1->cert->type = SSH2_CERT_TYPE_USER; + k1->cert->serial = 1234; + k1->cert->key_id = strdup("estragon"); + ASSERT_PTR_NE(k1->cert->key_id, NULL); + k1->cert->principals = calloc(4, sizeof(*k1->cert->principals)); + ASSERT_PTR_NE(k1->cert->principals, NULL); + k1->cert->principals[0] = strdup("estragon"); + k1->cert->principals[1] = strdup("vladimir"); + k1->cert->principals[2] = strdup("pozzo"); + k1->cert->principals[3] = strdup("lucky"); + ASSERT_PTR_NE(k1->cert->principals[0], NULL); + ASSERT_PTR_NE(k1->cert->principals[1], NULL); + ASSERT_PTR_NE(k1->cert->principals[2], NULL); + ASSERT_PTR_NE(k1->cert->principals[3], NULL); + k1->cert->valid_after = 0; + k1->cert->valid_before = (u_int64_t)-1; + k1->cert->critical = sshbuf_new(); + ASSERT_PTR_NE(k1->cert->critical, NULL); + k1->cert->extensions = sshbuf_new(); + ASSERT_PTR_NE(k1->cert->extensions, NULL); + put_opt(k1->cert->critical, "force-command", "/usr/bin/true"); + put_opt(k1->cert->critical, "source-address", "127.0.0.1"); + put_opt(k1->cert->extensions, "permit-X11-forwarding", NULL); + put_opt(k1->cert->extensions, "permit-agent-forwarding", NULL); + ASSERT_INT_EQ(sshkey_from_private(k2, &k1->cert->signature_key), 0); + ASSERT_INT_EQ(sshkey_certify(k1, k2), 0); + b = sshbuf_new(); + ASSERT_PTR_NE(b, NULL); + ASSERT_INT_EQ(sshkey_putb(k1, b), 0); + ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k3), 0); + + sshkey_free(k1); + sshkey_free(k2); + sshkey_free(k3); + sshbuf_reset(b); + TEST_DONE(); + + TEST_START("sign and verify RSA"); + k1 = get_private("rsa_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("sign and verify DSA"); + k1 = get_private("dsa_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("sign and verify ECDSA"); + k1 = get_private("ecdsa_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); +#endif + + TEST_START("sign and verify ED25519"); + k1 = get_private("ed25519_1"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_2.pub"), &k2, + NULL), 0); + signature_tests(k1, k2); + sshkey_free(k1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("nested certificate"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, + NULL), 0); + k3 = get_private("rsa_1"); + build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1); + ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4), + SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); + ASSERT_PTR_EQ(k4, NULL); + sshkey_free(k1); + sshkey_free(k2); + sshkey_free(k3); + sshbuf_free(b); + TEST_DONE(); + +} diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1 b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1 new file mode 100644 index 0000000..d3f2482 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1 @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2m +Ka43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8Py +mcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwIVAKMD +/50qQy7j8JaMk+1+Xtg1pK01AoGBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwbl +o4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4P +h8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgz +LND26HrdAoGBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb +OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joo +t+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAhRYIbQ5 +KfXsZuBPuWe5FJz3ldaEgw== +-----END DSA PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp new file mode 100644 index 0000000..75ff0e9 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp @@ -0,0 +1 @@ +SHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.pub b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.pub new file mode 100644 index 0000000..e768db1 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.pub @@ -0,0 +1 @@ +ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgdTlbNU9Hn9Qng3FHxwH971bxCIoq1ern/QWFFDWXgmYAAACBAPqS600VGwdPAQC/p3f0uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw62+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxbOXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAAAAAAAAAAYAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANowB8AAAAABNHmBwAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAFMAAAALc3NoLWVkMjU1MTkAAABAh/z1LIdNL1b66tQ8t9DY9BTB3BQKpTKmc7ezyFKLwl96yaIniZwD9Ticdbe/8i/Li3uCFE3EAt8NAIv9zff8Bg== DSA test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp new file mode 100644 index 0000000..75ff0e9 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp @@ -0,0 +1 @@ +SHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp.bb new file mode 100644 index 0000000..ba37776 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp.bb @@ -0,0 +1 @@ +xetag-todiz-mifah-torec-mynyv-cyvit-gopon-pygag-rupic-cenav-bexax diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.g b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.g new file mode 100644 index 0000000..e51c3f9 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.g @@ -0,0 +1 @@ +00eee5f505556d24a8cb996ae9c3adbe97fc525c0e6bafb30706e5a3882615dd51c17d725a403c910ed1ae109283c1dcea62069ca460291962ff72e06d27d9d286c525e86446d116b4de0f87c7d551e4bbe2241b23015078a9581c894d4d1a06b406dd8b79c7755f81064110735577ae3a98aa18cea33ff236c8332cd0f6e87add diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.priv b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.priv new file mode 100644 index 0000000..4f74331 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.priv @@ -0,0 +1 @@ +5821b43929f5ec66e04fb967b9149cf795d68483 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.pub b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.pub new file mode 100644 index 0000000..ba0313b --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.param.pub @@ -0,0 +1 @@ +00e757a727e6a1b10168ea9902ebe08f53f4ba18c6d8fdf551fbabbf6d8558f054dc0f6aae4c5b397c04d0bc2f8c2bebb1057f96b621273fed8b2b38d1579a86e956644e520073171887fde4b88b4a0697323928ee3a28b7e2caf3896d2f29b067840c9d88e765249c95fd54bb240c714b5bdf8f88d2ef58727ca1a7699216c42d diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.pub b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.pub new file mode 100644 index 0000000..41cae2f --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAPqS600VGwdPAQC/p3f0uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw62+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxbOXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQt DSA test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1_pw b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1_pw new file mode 100644 index 0000000..24c7303 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1_pw @@ -0,0 +1,15 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,BC8386C373B22EB7F00ADC821D5D8BE9 + ++HDV2DQ09sxrIAeXTz9r3YFuPRa2hk1+NGcr3ETkXbC6KiZ14wpTnGTloKwaQjIW +eXTa9mpCOWAoohgvsVb+hOuOlP7AfeHu1IXV4EAS+GDpkiV5UxlCXXwqlD75Buu4 +wwDd/p4SWzILH3WGjDk5JIXoxWNY13LHwC7Q6gtGJx4AicUG7YBRTXMIBDa/Kh77 +6o2rFETKmp4VHBvHbakmiETfptdM8bbWxKWeY2vakThyESgeofsLoTOQCIwlEfJC +s2D/KYL65C8VbHYgIoSLTQnooO45DDyxIuhCqP+H23mhv9vB1Od3nc2atgHj/XFs +dcOPFkF/msDRYqxY3V0AS6+jpKwFodZ7g/hyGcyPxOkzlJVuKoKuH6P5PyQ69Gx0 +iqri0xEPyABr7kGlXNrjjctojX+B4WwSnjg/2euXXWFXCRalIdA7ErATTiQbGOx7 +Vd6Gn8PZbSy1MkqEDrZRip0pfAFJYI/8GXPC75BpnRsrVlfhtrngbW+kBP35LzaN +l2K+RQ3gSB3iFoqNb1Kuu6T5MZlyVl5H2dVlJSeb1euQ2OycXdDoFTyJ4AiyWS7w +Vlh8zeJnso5QRDjMwx99pZilbbuFGSLsahiGEveFc6o= +-----END DSA PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2 b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2 new file mode 100644 index 0000000..3cc9631 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2 @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvQIBAAKBgQCbyPXNdHeLsjpobPVCMkfagBkt15Zsltqf/PGNP1y1cuz7rsTX +ZekQwUkSTNm5coqXe+ZOw2O4tjobJDd60I1/VPgaB0NYlQR9Hn87M284WD4f6VY+ +aunHmP134a8ybG5G4NqVNF3ihvxAR2pVITqb7kE46r2uYZNcNlHI8voRCwIVAMcP +bwqFNsQbH5pJyZW30wj4KVZ3AoGBAIK98BVeKQVf8qDFqx9ovMuNgVSxpd+N0Yta +5ZEy1OI2ziu5RhjueIM2K7Gq2Mnp38ob1AM53BUxqlcBJaHEDa6rj6yvuMgW9oCJ +dImBM8sIFxfBbXNbpJiMaDwa6WyT84OkpDE6uuAepTMnWOUWkUVkAiyokHDUGXkG +GyoQblbXAoGBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0 +FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk +0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZAhUAsY2f +bDFNzgZ4DaZ9wLRzTgOswPU= +-----END DSA PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp new file mode 100644 index 0000000..51fbeb4 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp @@ -0,0 +1 @@ +SHA256:ecwhWcXgpdBxZ2e+OjpRRY7dqXHHCD62BGtoVQQBwCk diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp.bb new file mode 100644 index 0000000..4d908ee --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp.bb @@ -0,0 +1 @@ +xeser-megad-pocan-rozit-belup-tapoh-fapif-kyvit-vonav-cehab-naxax diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.pub b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.pub new file mode 100644 index 0000000..77bb555 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAJvI9c10d4uyOmhs9UIyR9qAGS3XlmyW2p/88Y0/XLVy7PuuxNdl6RDBSRJM2blyipd75k7DY7i2OhskN3rQjX9U+BoHQ1iVBH0efzszbzhYPh/pVj5q6ceY/XfhrzJsbkbg2pU0XeKG/EBHalUhOpvuQTjqva5hk1w2Ucjy+hELAAAAFQDHD28KhTbEGx+aScmVt9MI+ClWdwAAAIEAgr3wFV4pBV/yoMWrH2i8y42BVLGl343Ri1rlkTLU4jbOK7lGGO54gzYrsarYyenfyhvUAzncFTGqVwElocQNrquPrK+4yBb2gIl0iYEzywgXF8Ftc1ukmIxoPBrpbJPzg6SkMTq64B6lMydY5RaRRWQCLKiQcNQZeQYbKhBuVtcAAACBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZ DSA test key #2 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_n b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_n new file mode 100644 index 0000000..d3f2482 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_n @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2m +Ka43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8Py +mcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwIVAKMD +/50qQy7j8JaMk+1+Xtg1pK01AoGBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwbl +o4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4P +h8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgz +LND26HrdAoGBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb +OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joo +t+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAhRYIbQ5 +KfXsZuBPuWe5FJz3ldaEgw== +-----END DSA PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_n_pw b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_n_pw new file mode 100644 index 0000000..24ac299 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_n_pw @@ -0,0 +1,21 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABCVs+LsMJ +wnB5zM9U9pTXrGAAAAEAAAAAEAAAGzAAAAB3NzaC1kc3MAAACBAPqS600VGwdPAQC/p3f0 +uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y +4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0 +k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw6 +2+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl +6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/ +I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb +OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84 +ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAAAB4HiOcRW4w+sIqBL0 +TPVbf0glN1hUi0rcE63Pqxmvxb8LkldC4IxAUagPrjhNAEW2AY42+CvPrtGB1z7gDADAIW +xZX6wKwIcXP0Qh+xHE12F4u6mwfasssnAp4t1Ki8uCjMjnimgb3KdWpp0kiUV0oR062TXV +PAdfrWjaq4fw0KOqbHIAG/v36AqzuqjSTfDbqvLZM3y0gp2Q1RxaQVJA5ZIKKyqRyFX7sr +BaEIyCgeE3hM0EB7BycY1oIcS/eNxrACBWVJCENl5N7LtEYXNX7TANFniztfXzwaqGTT6A +fCfbW4gz1UKldLUBzbIrPwMWlirAstbHvOf/2Iay2pNAs/SHhI0aF2jsGfvv5/D6N+r9dG +B2SgDKBg7pywMH1DTvg6YT3P4GjCx0GUHqRCFLvD1rDdk4KSjvaRMpVq1PJ0/Wv6UGtsMS +TR0PaEHDRNZqAX4YxqujnWrGKuRJhuz0eUvp7fZvbWHtiAMKV7368kkeUmkOHanb+TS+zs +KINX8ev8zJZ6WVr8Vl+IQavpv0i2bXwS6QqbEuifpv/+uBb7pqRiU4u8en0eMdX1bZoTPM +R6xHCnGD/Jpb3zS91Ya57T6CiXZ12KCaL6nWGnCkZVpzkfJ2HjFklWSWBQ6uyaosDQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1 b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1 new file mode 100644 index 0000000..80382b6 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1 @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMoAoGCCqGSM49 +AwEHoUQDQgAEDFlblkOrW9ydKVhtM+9AY3c9saBE7SG3lFx38nBavkADDaI9jh3/ +kvG/Jt9vpm22qwoklTCGDfzCkXkIKaWlBw== +-----END EC PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp new file mode 100644 index 0000000..e48304f --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp @@ -0,0 +1 @@ +SHA256:8ty77fOpABat1y88aNdclQTfU+lVvWe7jYZGw8VYtfg diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub new file mode 100644 index 0000000..55e2a25 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgOtFRnMigkGliaYfPmX5IidVWfV3tRH6lqRXv0l8bvKoAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQcAAAAAAAAABwAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2jAHwAAAAAE0eYHAAAAAAAAAAAAAAAAAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQcAAABkAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABJAAAAIHbxGwTnue7KxhHXGFvRcxBnekhQ3Qx84vV/Vs4oVCrpAAAAIQC7vk2+d14aS7td7kVXLQn392oALjEBzMZoDvT1vT/zOA== ECDSA test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp new file mode 100644 index 0000000..e48304f --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp @@ -0,0 +1 @@ +SHA256:8ty77fOpABat1y88aNdclQTfU+lVvWe7jYZGw8VYtfg diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb new file mode 100644 index 0000000..fa23c33 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb @@ -0,0 +1 @@ +xibah-vocun-sogyn-byhen-rivem-hegyh-luneh-dozyr-vatyf-dufid-myxyx diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.curve b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.curve new file mode 100644 index 0000000..fa04004 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.curve @@ -0,0 +1 @@ +prime256v1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.priv b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.priv new file mode 100644 index 0000000..dc908ad --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.priv @@ -0,0 +1 @@ +00f3cdc940278ef16bf9e4ffeedfc8ca3b9041dfda2c589363dd8b07d8088f2acc diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.pub b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.pub new file mode 100644 index 0000000..71c9584 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.param.pub @@ -0,0 +1 @@ +040c595b9643ab5bdc9d29586d33ef4063773db1a044ed21b7945c77f2705abe40030da23d8e1dff92f1bf26df6fa66db6ab0a249530860dfcc291790829a5a507 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.pub b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.pub new file mode 100644 index 0000000..84a71f9 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQc= ECDSA test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1_pw b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1_pw new file mode 100644 index 0000000..5c83a65 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1_pw @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,7BA38DE00F67851E4207216809C3BB15 + +8QkFoZHQkj9a2mt032sp+WKaJ1fwteqWDd4RpAW9OzDgqzMx1QO43qJgBDTfhzjt +M2Q8YfiGjfBEYpg4kCbacfcV68DEV4z6Ll7rIzzzO7OfWUNL++brD64vKx4z6f46 ++sn4nbZTXilpkzi/nmPDVzrNmTSywA8T7Yf0QcBUxks= +-----END EC PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2 b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2 new file mode 100644 index 0000000..0f4e844 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2 @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBqBtN7e6Essd3dlsgISViPCXXC0atlNkGtoMgSQdBTKVUfeJOi4lc +RZaXJdXnqWUqI/KEsH8h8QN4YcB8ugmAcc+gBwYFK4EEACOhgYkDgYYABAHZ2VNy +oDedBwqsdzY+kkNptc9DrtRCVmO6cULLj+691MhItqVqTMJbTFlI4MnAg9PoGTF/ +0KmLJfy8vSffXGKqqwGKcFNtd1XCo+7Qu9tXbxron9g6Dmu7y8jaLkixcwZwnwLs +6GmA9qZGuiAfOGV0Gf9/u98sr+vikOa4Ow5JFDTw5g== +-----END EC PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp new file mode 100644 index 0000000..581e48a --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp @@ -0,0 +1 @@ +SHA256:ed8YniRHA6qCrErCRnzrWxPHxYuA62a+CAFYUVxJgaI diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb new file mode 100644 index 0000000..e1cc664 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb @@ -0,0 +1 @@ +xufag-danul-putub-mokin-pugaz-covid-dofag-nihuz-sysab-genar-zaxyx diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.curve b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.curve new file mode 100644 index 0000000..617ea2f --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.curve @@ -0,0 +1 @@ +secp521r1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.priv b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.priv new file mode 100644 index 0000000..dd898d9 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.priv @@ -0,0 +1 @@ +01a81b4dedee84b2c777765b202125623c25d70b46ad94d906b683204907414ca5547de24e8b895c45969725d5e7a9652a23f284b07f21f1037861c07cba098071cf diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.pub b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.pub new file mode 100644 index 0000000..94301c9 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.param.pub @@ -0,0 +1 @@ +0401d9d95372a0379d070aac77363e924369b5cf43aed4425663ba7142cb8feebdd4c848b6a56a4cc25b4c5948e0c9c083d3e819317fd0a98b25fcbcbd27df5c62aaab018a70536d7755c2a3eed0bbdb576f1ae89fd83a0e6bbbcbc8da2e48b17306709f02ece86980f6a646ba201f38657419ff7fbbdf2cafebe290e6b83b0e491434f0e6 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.pub b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.pub new file mode 100644 index 0000000..be9d84b --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHZ2VNyoDedBwqsdzY+kkNptc9DrtRCVmO6cULLj+691MhItqVqTMJbTFlI4MnAg9PoGTF/0KmLJfy8vSffXGKqqwGKcFNtd1XCo+7Qu9tXbxron9g6Dmu7y8jaLkixcwZwnwLs6GmA9qZGuiAfOGV0Gf9/u98sr+vikOa4Ow5JFDTw5g== ECDSA test key #2 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_n b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_n new file mode 100644 index 0000000..80382b6 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_n @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMoAoGCCqGSM49 +AwEHoUQDQgAEDFlblkOrW9ydKVhtM+9AY3c9saBE7SG3lFx38nBavkADDaI9jh3/ +kvG/Jt9vpm22qwoklTCGDfzCkXkIKaWlBw== +-----END EC PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_n_pw b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_n_pw new file mode 100644 index 0000000..36b7fa7 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_n_pw @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABC4UwEov5 +z0RrCm7AMCxbuiAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz +dHAyNTYAAABBBAxZW5ZDq1vcnSlYbTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvy +bfb6ZttqsKJJUwhg38wpF5CCmlpQcAAACgbCnAklQTHrf5qiHiMxKYwQJ7k/X9mp4fXD4v +xUbgNZiXSxN26mn8mC2rH+WA6Lk3CexR/hrtLI2ndpBsYu1h6HhVkOwwm3Kd/PMKArCupW +l6sYEabrT0EghXR/3aDEZvj79hgKSdu3RpayLvMdbCR8k1cg0/mDmR9hicWfeJ61n/IH05 +tUR268+0BVRW9kDhh/cuv8tVY4L09jCCQ6CpsA== +-----END OPENSSH PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1 b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1 new file mode 100644 index 0000000..6b0ae01 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAJjnj4Ao54+A +KAAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQ +AAAED3KgoDbjR54V7bdNpfKlQY5m20UK1QaHytkCR+6rZEDFOG6kY7Rf4UtCFvPwKgo/Bz +tXck2xC4a2WyA34XtIwZAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg== +-----END OPENSSH PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp new file mode 100644 index 0000000..a9674e2 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp @@ -0,0 +1 @@ +SHA256:L3k/oJubblSY0lB9Ulsl7emDMnRPKm/8udf2ccwk560 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.pub b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.pub new file mode 100644 index 0000000..649b4e8 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.pub @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIIxzuxl4z3uwAIslne8Huft+1n1IhHAlNbWZkQyyECCGAAAAIFOG6kY7Rf4UtCFvPwKgo/BztXck2xC4a2WyA34XtIwZAAAAAAAAAAgAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANowB8AAAAABNHmBwAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAFMAAAALc3NoLWVkMjU1MTkAAABABGTn+Bmz86Ajk+iqKCSdP5NClsYzn4alJd0V5bizhP0Kumc/HbqQfSt684J1WdSzih+EjvnTgBhK9jTBKb90AQ== ED25519 test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp new file mode 100644 index 0000000..a9674e2 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp @@ -0,0 +1 @@ +SHA256:L3k/oJubblSY0lB9Ulsl7emDMnRPKm/8udf2ccwk560 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp.bb new file mode 100644 index 0000000..309f2da --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp.bb @@ -0,0 +1 @@ +xubop-rekyd-bakal-nubuf-pahaf-gicuh-logeb-gocif-petod-galip-fuxux diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.pub b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.pub new file mode 100644 index 0000000..e533059 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFOG6kY7Rf4UtCFvPwKgo/BztXck2xC4a2WyA34XtIwZ ED25519 test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1_pw b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1_pw new file mode 100644 index 0000000..c3b7ae7 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1_pw @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABCus+kaow +AUjHphacvRp98dAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIFOG6kY7Rf4UtCFv +PwKgo/BztXck2xC4a2WyA34XtIwZAAAAoJaqqgiYQuElraJAmYOm7Tb4nJ3eI4oj9mQ52M +/Yd+ION2Ur1v8BDewpDX+LHEYgKHo3Mlmcn2UyF+QJ+7xUCW7QCtk/4szrJzw74DlEl6mH +T8PT/f/av7PpECBD/YD3NoDlB9OWm/Q4sHcxfBEKfTGD7s2Onn71HgrdEOPqd4Sj/IQigR +drfjtXEMlD32k9n3dd2eS9x7AHWYaGFEMkOcY= +-----END OPENSSH PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2 b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2 new file mode 100644 index 0000000..e4aed63 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACDPVKyLnm3eZE0lm0IfM3Uy9AsdGSBtozcoCt21blYBCwAAAJix1mBGsdZg +RgAAAAtzc2gtZWQyNTUxOQAAACDPVKyLnm3eZE0lm0IfM3Uy9AsdGSBtozcoCt21blYBCw +AAAECZEQHXs18o3DKjhUYaTyt+bUbhqfMeqmsKjYyFvzGVgs9UrIuebd5kTSWbQh8zdTL0 +Cx0ZIG2jNygK3bVuVgELAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg== +-----END OPENSSH PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp new file mode 100644 index 0000000..0496626 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp @@ -0,0 +1 @@ +SHA256:vMbaARqVciRgXyZPNHDo+P5p5WK5yWG1Oo6VC35Bomw diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp.bb new file mode 100644 index 0000000..abba789 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp.bb @@ -0,0 +1 @@ +xuces-bapyb-vikob-zesyv-budod-nupip-kebon-tacyc-fofed-lezic-soxax diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.pub b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.pub new file mode 100644 index 0000000..af34236 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM9UrIuebd5kTSWbQh8zdTL0Cx0ZIG2jNygK3bVuVgEL ED25519 test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/pw b/crypto/openssh/regress/unittests/sshkey/testdata/pw new file mode 100644 index 0000000..8a1dff9 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/pw @@ -0,0 +1 @@ +mekmitasdigoat diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1 b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1 new file mode 100644 index 0000000..161cc04 Binary files /dev/null and b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1 differ diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp new file mode 100644 index 0000000..21b3d1a --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp @@ -0,0 +1 @@ +SHA256:/kk7K9S9kwYFiFilnZYFwCsQJweI/SGQVR2nIa8VBhE diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp.bb new file mode 100644 index 0000000..62991b3 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp.bb @@ -0,0 +1 @@ +xilil-nabyf-gynih-duheb-gokyp-bofet-nekac-bosod-lozin-kuvyh-poxix diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.param.n b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.param.n new file mode 100644 index 0000000..9a2549b --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.param.n @@ -0,0 +1 @@ +00ce8ca77a556eba887f9a866c084a6402785354a81c10854d343181fa09351223a65f99915f8433d11a9c41677d307c03c3a39865b83e7172d2c1d878333c980438d6e4462106a0065cd75cfea7ca7f21538bf2f43f2af49cacee51b22e3bdcc5e87b59cc691f7c6942a77ef13bfdfb24300777b727348d0ba7900ba06b886729 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.pub b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.pub new file mode 100644 index 0000000..f665b0d --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.pub @@ -0,0 +1 @@ +1024 65537 145043942670517902781741650890610683756045780348507433188994725700923246927874581962206512480287863636935077725837494808988986557337885675565086448774391442851909709751605441036910145362277967349042489937363543710406342212883803780768870873303921572812138116796733586484633244057911618360651775855949808953129 RSA1 test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1_pw b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1_pw new file mode 100644 index 0000000..e73c679 Binary files /dev/null and b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1_pw differ diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2 b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2 new file mode 100644 index 0000000..1d672dd Binary files /dev/null and b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2 differ diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp new file mode 100644 index 0000000..00516d5 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp @@ -0,0 +1 @@ +SHA256:JaOeRCnLl/TLe7vn1+aQ4ONyKZCUhK5x3k4VHilmbpE diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp.bb new file mode 100644 index 0000000..b4989a5 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp.bb @@ -0,0 +1 @@ +xipag-zohut-zepuk-pisyv-kamog-pupus-netud-tudis-melup-cynov-gaxox diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.param.n b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.param.n new file mode 100644 index 0000000..25d438d --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.param.n @@ -0,0 +1 @@ +00cab091b57a154740c1bb7020f46a21a19dc40f647db2aab1babd30cabe241f0437391e68376ba35e48c624b8eaf6b59424d4c1a848c9fd1ef5cdc7c1b7f5e5df23b7ad513b79021286d38c52fdfae35656659e8649b2bf8bedf7c99664e45534007bd1c5dc3de1dafdf2d34ad087155951aa0f3d500b36d0d804bbccdef15ab31ca3dd40bdf5196065a97f397ef576caffb606be8232f6e0614aea0e979b9584296673fabb1dbd9f3212495c428842a2ab1f1768dd424fb6fdceeeab9126cacdfc834f0a0d09ba73ad8360d183ba85bb1565555cc6a536eb8d06df1a1e841107c021ae28a2d8b3465f9d8b58ef4045aea1c4ad7f8bf639574d6b142af67b4eb3 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.pub b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.pub new file mode 100644 index 0000000..acab6dd --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.pub @@ -0,0 +1 @@ +2048 65537 25587207108642486834576012232250034427766229965612147538722032399009467293691448851087324679403117563681753304072089087252850866332601294130674473984011813227791089686736237645788471744456489819306046398653719249100878753563464696688916667605969658659855996383142110932332560049231682024775766802333675397528993897914717996946881193454997890776063024953924432026083898531677702536941151535135950834711001926404724453460085864892836473957600610133803037286539329764689125111700732309717375455919436557475211197800228646235077584780367991159670572954337165006813357814232200750568307753718414790655085790471723847208627 RSA1 test key #2 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1 b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1 new file mode 100644 index 0000000..5de3f84 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u +d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd +NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB +AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ +GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj +Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv +Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i +PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa +WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj +mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi +C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e +NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ +h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs= +-----END RSA PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp new file mode 100644 index 0000000..79f380a --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp @@ -0,0 +1 @@ +SHA256:l6itGumSMcRBBAFteCgmjQBIXqLK/jFGUH3viHX1RmE diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.pub b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.pub new file mode 100644 index 0000000..3bacf3c --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg98LhS2EHxLOWCLopZPwHdg/RJXusnkOqQXSc9R7aITkAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wAAAAAAAAAFAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaMAfAAAAAATR5gcAAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgU4bqRjtF/hS0IW8/AqCj8HO1dyTbELhrZbIDfhe0jBkAAABTAAAAC3NzaC1lZDI1NTE5AAAAQI3QGlUCzC07KorupxpDkkGy6tniaZ8EvBflzvv+itXWNchGvfUeHmVT6aX0sRqehdz/lR+GmXRoZBhofwh0qAM= RSA test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp new file mode 100644 index 0000000..79f380a --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp @@ -0,0 +1 @@ +SHA256:l6itGumSMcRBBAFteCgmjQBIXqLK/jFGUH3viHX1RmE diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp.bb new file mode 100644 index 0000000..45bacd5 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp.bb @@ -0,0 +1 @@ +xosis-fodod-votot-dibum-ryvac-rediz-naruf-votun-kevis-halis-gexux diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.n b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.n new file mode 100644 index 0000000..4933712 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.n @@ -0,0 +1 @@ +00cb5799544edec5ac00ec781fc21a1119ce9a288e3116e72f3e78fbcba6998adcc98c235f2e77abf1ce92b76f064b624552c9f2582341e622e1a176eef232b5bac1bf3881babc0b7d57a1ef4439170852e192bc329d3523354a39610eab916e50c507c913a2a5f2c7596aad779c5f297121438bd2313ebb4ad4d7debba43271fb diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.p b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.p new file mode 100644 index 0000000..4783d21 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.p @@ -0,0 +1 @@ +00f56077ef05be4574906f52175ed8897e8da1626bc9b055534d6a20f6102c57c7a0b31b3e7864b101f4d3d57c35192bc949e14243a9e956361de23c5dd179f583 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.q b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.q new file mode 100644 index 0000000..00fc8a2 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.param.q @@ -0,0 +1 @@ +00d42541cc014be26370a657953f3adfcbaf713f781639adba33133f184eb3c7d8c2ec7810dca3da58a746fc5b87b34f396934436832e619c67c22f32ebbb36029 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.pub b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.pub new file mode 100644 index 0000000..23ef872 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+w== RSA test key #1 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1_pw b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1_pw new file mode 100644 index 0000000..b4c0674 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1_pw @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,0C3F819F6EEA66A471BAEEDDA8171606 + +AhQNxgw7Z2un3dpm6KPHF1u5qVvOczm0yiTyPK4U11B3TTRhXOHdzPLAcKMX71Xq +fmLm2/JIZATUbLTaysLKIQlmAgtpmXoKLv9b90R3AXLophgToZzOLpvlQTCt+y9G +0E3QQZG/LFy9BLNyw6uD5cy0RHT3FQb5VQDwfBvR/I+K3qWBFLlb7Rw9bCujYczu +D3bimcDj/k6YkrWVsEa81Ch5RF2RClOYufti6bsvc4xIsB0Kd++vokER+kXFuQqf +Tl0Jz+SG0kr9QtjVvkhBtSxzJ6/olAosoUySQ5hqsB8iECufBgp1KelXqsHFJQXy +gCvVmGiivFUinX0rKOuWCHTplsSKQ9BnPSwDAAs8A7ZLcTXcLs/hMQ5r6fmOYfNN +YthhjZyE2ciJO0lydGJUJMb5aJUak0rl+uINRlYCHTRLVwmCOmpfqz9SfcJb1ieU +4Us8NR+pXJar4U0+C2wVlNJkAdpL6GvYxN6vp7vLa+BiFwIZOQozswacIZk/ScXm +QL9rmWug51RCmDeenX46WTEZeB0o0+xi60sDEDhhe4+iNYcJu5L0BJ5lqRFe3I5n +HRRv1mBEjbF2fDcg/ChYfOXsc4gDivH2nObabeASuMFZyadmXfA8tnXRZf+7Wuy/ +LZGYbM2xLeEyV3ss16WBHuIqexDt04OEZvs0jN90zj6Yv7qKCB975bdOcuKkN2Nn +n9lA11R2pgsCs6COp9rYiWXkXZeDf3sW6kdcEV+/SzkVsv4JlHcsIzgk4WGVF/E/ +ZkU4J9AvSdJPzEQDM+yszp0eeUow4+SAgpuNTqZiUO/2UUVbsr3qvlYMoCixhFAN +-----END RSA PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2 b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2 new file mode 100644 index 0000000..2441d52 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2 @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA9NEUXp78SAkmL4+eAj4mBzPOjk+ccCPVzkTR+mZJdyTwkJAB +HUN4cn4a2kTmh7Er+N8CXCsiqxIOV1GfH2fwaCiBlOEXeQJi/cMjxr9kVWO4FhC6 +l1UqbvPUdrUCUZjFTA9/Ah9MKgk7qGYq5SjE3p+sn4GLhRKbqmq9LjiHgMmkBuv/ +a1Slit+rXHzO2F8fH5hkjeHivyYVgw45aNvGCe2RRfbpoeW2mRtgIv7y9wSewt6a +mhEDXSo/F6mkqA7xVinzro5NettEXLo91tA9Hb6f6x/Mc/GJDNXTKhpWCGeJ6xeW +nAefDZORWAY7Y9YbuAxhEJVi9QL5NWoFOA0C6wIDAQABAoIBAQDtRGVVfwhKWHOl +zK76xXjdqhwaWJXpKRHiI1jOMawpyKdNtAMgdW+apxUnTXePMurG/HuxEC09VvaH +MhfhvD6G9BsCS1UQdnuyLRnTWVLIXyjeWcA9QtEpTy8vDSb+Je2xVaNmTybl5qTn +BH22Mtj6Wg5XWJn7kplDhMdssGTDLsSCMw/rcxe9iT2qOKyltQal23RHzR7SijGp +QTtBp2SDGhvMZcyGuyMqJ084W8sdJpbyVzdDim2iaZdHlk7uvW2n0HcJ56I6yhIq +2U8wfgEEwydGVGHgmQNJ/n+SiT/hv6g5ebhDS46X9F9m5CHDwhdr0DrhPBVSsdhl +1HeJ0+FhAoGBAPuC3uNHToiJis688juKlwc3SQ6ger5ffAg3yaNhEcpHkvOtdZlF +/CfX94xazMov/YqFwkvpSSdKsX+PeXuaqnb1hPKNYX5t45U9RjB/ox7BIQj/2rPx +Bfs99UFW9HKP4HsVmLu1xeJg1Pc9iylTK/xrnwfYiZ+H7IGVccizjnqHAoGBAPkv +n1flAdxBzJH/O0rXoig2EtZsDRMPY51MGDdqVOW14ZOfTVlmu0OSnkSKQm2twfro +TPDVb2TY3wTRutz8H9yOFW1c1Nz4YOyTb8FmJhE2FWAQ9t8QpwUlhn15if72dS/Y +22+vP+AYu7wfqGL7QVVEXho5hGjXi053iEvfXBl9AoGAeZISpo1LGphRLgkKlVky +E1zXxWgwrGB/FYHRx1UeQkZCc+K+Wy4G6kNr9r3VC04TIafx+Lt0jrd+AIibUfG6 +v/GBJ7TLEU+QmAycJskrUaxMiYsSbbPtDjoumDytv8pn2VbhEqqUUg44IqHu6DS5 +qDNlFWfHbgNHgIN6EmcoUXUCgYEAi2G57X4pRjx/4wIy9jAbggaNDuctgQXQoIGZ +4hVWG49a+CnZKDKweKGgaZI0igjxQhmCQAwC3RP520Y9EbLtV38aOSv93QQJowrt +Le6nSGVKG4whqrAz3EsbKUA8kiLldbgFNjl+ryjmidnjZEpKRxmQ0XZuu/4k6+Us +ldQAPjkCgYBwjSm5eDUtK2eEPaBtbJykV05CTv5rn6CKC9L7ZBTkCcdU1hxeqe99 +wb22decnNawGRP1a5cGwqKJPOfkgybJVkdr6aqQW8ClzdFSaenjzs+nVW+T9JTXf +9lFpIZg5kN/geld3B9B4C99riTM0jg9hbe2RQvpLRTrZbnWMA1XoRw== +-----END RSA PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp new file mode 100644 index 0000000..4659639 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp @@ -0,0 +1 @@ +SHA256:NoQh0XBUuYUSWqnzOzOBnfpgJTRWLMj7BlWAb8IbjeE diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp.bb b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp.bb new file mode 100644 index 0000000..e9d1e4a --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp.bb @@ -0,0 +1 @@ +xogit-gupof-mydon-hocep-zuval-feson-rarif-cefar-tobar-ryvap-kuxex diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.n b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.n new file mode 100644 index 0000000..a669dbf --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.n @@ -0,0 +1 @@ +00f4d1145e9efc4809262f8f9e023e260733ce8e4f9c7023d5ce44d1fa66497724f09090011d4378727e1ada44e687b12bf8df025c2b22ab120e57519f1f67f068288194e117790262fdc323c6bf645563b81610ba97552a6ef3d476b5025198c54c0f7f021f4c2a093ba8662ae528c4de9fac9f818b85129baa6abd2e388780c9a406ebff6b54a58adfab5c7cced85f1f1f98648de1e2bf2615830e3968dbc609ed9145f6e9a1e5b6991b6022fef2f7049ec2de9a9a11035d2a3f17a9a4a80ef15629f3ae8e4d7adb445cba3dd6d03d1dbe9feb1fcc73f1890cd5d32a1a56086789eb17969c079f0d939158063b63d61bb80c61109562f502f9356a05380d02eb diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.p b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.p new file mode 100644 index 0000000..be7c1c3 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.p @@ -0,0 +1 @@ +00fb82dee3474e88898acebcf23b8a970737490ea07abe5f7c0837c9a36111ca4792f3ad759945fc27d7f78c5accca2ffd8a85c24be949274ab17f8f797b9aaa76f584f28d617e6de3953d46307fa31ec12108ffdab3f105fb3df54156f4728fe07b1598bbb5c5e260d4f73d8b29532bfc6b9f07d8899f87ec819571c8b38e7a87 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.q b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.q new file mode 100644 index 0000000..6f2c542 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.param.q @@ -0,0 +1 @@ +00f92f9f57e501dc41cc91ff3b4ad7a2283612d66c0d130f639d4c18376a54e5b5e1939f4d5966bb43929e448a426dadc1fae84cf0d56f64d8df04d1badcfc1fdc8e156d5cd4dcf860ec936fc166261136156010f6df10a70525867d7989fef6752fd8db6faf3fe018bbbc1fa862fb4155445e1a398468d78b4e77884bdf5c197d diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.pub b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.pub new file mode 100644 index 0000000..3322fbc --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD00RRenvxICSYvj54CPiYHM86OT5xwI9XORNH6Zkl3JPCQkAEdQ3hyfhraROaHsSv43wJcKyKrEg5XUZ8fZ/BoKIGU4Rd5AmL9wyPGv2RVY7gWELqXVSpu89R2tQJRmMVMD38CH0wqCTuoZirlKMTen6yfgYuFEpuqar0uOIeAyaQG6/9rVKWK36tcfM7YXx8fmGSN4eK/JhWDDjlo28YJ7ZFF9umh5baZG2Ai/vL3BJ7C3pqaEQNdKj8XqaSoDvFWKfOujk1620Rcuj3W0D0dvp/rH8xz8YkM1dMqGlYIZ4nrF5acB58Nk5FYBjtj1hu4DGEQlWL1Avk1agU4DQLr RSA test key #2 diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_n b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_n new file mode 100644 index 0000000..5de3f84 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_n @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u +d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd +NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB +AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ +GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj +Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv +Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i +PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa +WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj +mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi +C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e +NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ +h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs= +-----END RSA PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_n_pw b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_n_pw new file mode 100644 index 0000000..dc18373 --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_n_pw @@ -0,0 +1,17 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABAFw/Wg/V +I5SAXWj/HJr9qeAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDLV5lUTt7F +rADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18ud6vxzpK3bwZLYkVSyfJYI0HmIuGhdu +7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKdNSM1SjlhDquRblDFB8kToqXyx1lqrXecXylx +IUOL0jE+u0rU1967pDJx+wAAAgD1iSGiMlMJt2VH4kx5yr0wCJS+4UOmX0bxKO7UH5Jcul +K5eaSe5ZoKE7hTYBaz0K5dRF/0fqLsvVZlE4quDjFLN6Hyavgn2W/QM7SUqBHgRMal9pgH +LnxX6mFNWJ+4yb7f3bcbVIdgmMm3sT9Xjwaf5xgzNlR2mkUWtFwjyQh6FxUo5apNzqNBwO +l2Q4xfmyZTp1s++pStQ/su6obXpxnE2Nx5G/D84ZL5iWl+njUy/MvJTazHRbiTSyihU+UA +mUr5ZNuP3WUYY+h3KVlHpYHJYB7l3AMTKuPMFLhY9V7BJ+DuKPaqBgX4hvRzY0eVQiFr61 +ovjWjvfu1ulx550JqdYCgH2PpP0E89OQne35Cxs9QPThfe8DKojC9YquYh9zmVTvr7kNiE +Soluk/7oKpQIDaC+/SRk7AJ2e3Cbt1lXyGNn37PuqaaC/apaF/DOD6Yig9aClS7jOUrT96 +56trFAYfHEIKbRCUSMCiM1+x6HOLYf5ROrGE9KxT3kUD9XMsMpTva+cPpHUpbGpXcYE10N +MyYDz+V5M2/ZoIdEhscJNQ3UnhaZpeEaqcOyNyo90n3Dnaw/WpMDD/kNMGfm8daTaYInnQ +QnwA2gwlYfpTAqxE71oXgOuGmtA0yqJB4778Xq26Pb+B7/mZZZe6n0FVmiNC+ZG37ZGOw/ +iGL9e2Sxzw== +-----END OPENSSH PRIVATE KEY----- diff --git a/crypto/openssh/regress/unittests/sshkey/tests.c b/crypto/openssh/regress/unittests/sshkey/tests.c new file mode 100644 index 0000000..13f265c --- /dev/null +++ b/crypto/openssh/regress/unittests/sshkey/tests.c @@ -0,0 +1,27 @@ +/* $OpenBSD: tests.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include + +#include "../test_helper/test_helper.h" + +void sshkey_tests(void); +void sshkey_file_tests(void); +void sshkey_fuzz_tests(void); + +void +tests(void) +{ + OpenSSL_add_all_algorithms(); + ERR_load_CRYPTO_strings(); + + sshkey_tests(); + sshkey_file_tests(); + sshkey_fuzz_tests(); +} diff --git a/crypto/openssh/regress/unittests/test_helper/Makefile b/crypto/openssh/regress/unittests/test_helper/Makefile new file mode 100644 index 0000000..5b3894c --- /dev/null +++ b/crypto/openssh/regress/unittests/test_helper/Makefile @@ -0,0 +1,16 @@ +# $OpenBSD: Makefile,v 1.2 2015/01/20 22:58:57 djm Exp $ + +LIB= test_helper +SRCS= test_helper.c fuzz.c + +DEBUGLIBS= no +NOPROFILE= yes +NOPIC= yes + +# Hack to allow building with SUBDIR in ../../Makefile +regress: all + +install: + @echo -n + +.include diff --git a/crypto/openssh/regress/unittests/test_helper/fuzz.c b/crypto/openssh/regress/unittests/test_helper/fuzz.c new file mode 100644 index 0000000..99f1d03 --- /dev/null +++ b/crypto/openssh/regress/unittests/test_helper/fuzz.c @@ -0,0 +1,438 @@ +/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for fuzz tests */ + +#include "includes.h" + +#include +#include + +#include +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include +#include +#include + +#include "test_helper.h" +#include "atomicio.h" + +/* #define FUZZ_DEBUG */ + +#ifdef FUZZ_DEBUG +# define FUZZ_DBG(x) do { \ + printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ + printf x; \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +#else +# define FUZZ_DBG(x) +#endif + +/* For brevity later */ +typedef unsigned long long fuzz_ullong; + +/* For base-64 fuzzing */ +static const char fuzz_b64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +struct fuzz { + /* Fuzz method currently in use */ + int strategy; + + /* Fuzz methods remaining */ + int strategies; + + /* Original seed data blob */ + void *seed; + size_t slen; + + /* Current working copy of seed with fuzz mutations applied */ + u_char *fuzzed; + + /* Used by fuzz methods */ + size_t o1, o2; +}; + +static const char * +fuzz_ntop(u_int n) +{ + switch (n) { + case 0: + return "NONE"; + case FUZZ_1_BIT_FLIP: + return "FUZZ_1_BIT_FLIP"; + case FUZZ_2_BIT_FLIP: + return "FUZZ_2_BIT_FLIP"; + case FUZZ_1_BYTE_FLIP: + return "FUZZ_1_BYTE_FLIP"; + case FUZZ_2_BYTE_FLIP: + return "FUZZ_2_BYTE_FLIP"; + case FUZZ_TRUNCATE_START: + return "FUZZ_TRUNCATE_START"; + case FUZZ_TRUNCATE_END: + return "FUZZ_TRUNCATE_END"; + case FUZZ_BASE64: + return "FUZZ_BASE64"; + default: + abort(); + } +} + +static int +fuzz_fmt(struct fuzz *fuzz, char *s, size_t n) +{ + if (fuzz == NULL) + return -1; + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen * 8, fuzz->o1); + return 0; + case FUZZ_2_BIT_FLIP: + snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n", + fuzz_ntop(fuzz->strategy), + (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, + ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, + fuzz->o1, fuzz->o2); + return 0; + case FUZZ_1_BYTE_FLIP: + snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_2_BYTE_FLIP: + snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n", + fuzz_ntop(fuzz->strategy), + (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, + ((fuzz_ullong)fuzz->slen) * fuzz->slen, + fuzz->o1, fuzz->o2); + return 0; + case FUZZ_TRUNCATE_START: + snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_TRUNCATE_END: + snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_BASE64: + assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); + snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n", + fuzz_ntop(fuzz->strategy), + (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, + fuzz->slen * (fuzz_ullong)64, fuzz->o1, + fuzz_b64chars[fuzz->o2]); + return 0; + default: + return -1; + abort(); + } +} + +static void +dump(u_char *p, size_t len) +{ + size_t i, j; + + for (i = 0; i < len; i += 16) { + fprintf(stderr, "%.4zd: ", i); + for (j = i; j < i + 16; j++) { + if (j < len) + fprintf(stderr, "%02x ", p[j]); + else + fprintf(stderr, " "); + } + fprintf(stderr, " "); + for (j = i; j < i + 16; j++) { + if (j < len) { + if (isascii(p[j]) && isprint(p[j])) + fprintf(stderr, "%c", p[j]); + else + fprintf(stderr, "."); + } + } + fprintf(stderr, "\n"); + } +} + +void +fuzz_dump(struct fuzz *fuzz) +{ + char buf[256]; + + if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) { + fprintf(stderr, "%s: fuzz invalid\n", __func__); + abort(); + } + fputs(buf, stderr); + fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen); + dump(fuzz->seed, fuzz->slen); + fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz)); + dump(fuzz_ptr(fuzz), fuzz_len(fuzz)); +} + +#ifdef SIGINFO +static struct fuzz *last_fuzz; + +static void +siginfo(int unused __attribute__((__unused__))) +{ + char buf[256]; + + test_info(buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); + if (last_fuzz != NULL) { + fuzz_fmt(last_fuzz, buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); + } +} +#endif + +struct fuzz * +fuzz_begin(u_int strategies, const void *p, size_t l) +{ + struct fuzz *ret = calloc(sizeof(*ret), 1); + + assert(p != NULL); + assert(ret != NULL); + ret->seed = malloc(l); + assert(ret->seed != NULL); + memcpy(ret->seed, p, l); + ret->slen = l; + ret->strategies = strategies; + + assert(ret->slen < SIZE_MAX / 8); + assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1))); + + FUZZ_DBG(("begin, ret = %p", ret)); + + fuzz_next(ret); + +#ifdef SIGINFO + last_fuzz = ret; + signal(SIGINFO, siginfo); +#endif + + return ret; +} + +void +fuzz_cleanup(struct fuzz *fuzz) +{ + FUZZ_DBG(("cleanup, fuzz = %p", fuzz)); +#ifdef SIGINFO + last_fuzz = NULL; + signal(SIGINFO, SIG_DFL); +#endif + assert(fuzz != NULL); + assert(fuzz->seed != NULL); + assert(fuzz->fuzzed != NULL); + free(fuzz->seed); + free(fuzz->fuzzed); + free(fuzz); +} + +static int +fuzz_strategy_done(struct fuzz *fuzz) +{ + FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu", + fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen)); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + return fuzz->o1 >= fuzz->slen * 8; + case FUZZ_2_BIT_FLIP: + return fuzz->o2 >= fuzz->slen * 8; + case FUZZ_2_BYTE_FLIP: + return fuzz->o2 >= fuzz->slen; + case FUZZ_1_BYTE_FLIP: + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + case FUZZ_BASE64: + return fuzz->o1 >= fuzz->slen; + default: + abort(); + } +} + +void +fuzz_next(struct fuzz *fuzz) +{ + u_int i; + + FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, " + "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), + (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); + + if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) { + /* If we are just starting out, we need to allocate too */ + if (fuzz->fuzzed == NULL) { + FUZZ_DBG(("alloc")); + fuzz->fuzzed = calloc(fuzz->slen, 1); + } + /* Pick next strategy */ + FUZZ_DBG(("advance")); + for (i = 1; i <= FUZZ_MAX; i <<= 1) { + if ((fuzz->strategies & i) != 0) { + fuzz->strategy = i; + break; + } + } + FUZZ_DBG(("selected = %u", fuzz->strategy)); + if (fuzz->strategy == 0) { + FUZZ_DBG(("done, no more strategies")); + return; + } + fuzz->strategies &= ~(fuzz->strategy); + fuzz->o1 = fuzz->o2 = 0; + } + + assert(fuzz->fuzzed != NULL); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + assert(fuzz->o1 / 8 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); + fuzz->o1++; + break; + case FUZZ_2_BIT_FLIP: + assert(fuzz->o1 / 8 < fuzz->slen); + assert(fuzz->o2 / 8 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); + fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8); + fuzz->o1++; + if (fuzz->o1 >= fuzz->slen * 8) { + fuzz->o1 = 0; + fuzz->o2++; + } + break; + case FUZZ_1_BYTE_FLIP: + assert(fuzz->o1 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] ^= 0xff; + fuzz->o1++; + break; + case FUZZ_2_BYTE_FLIP: + assert(fuzz->o1 < fuzz->slen); + assert(fuzz->o2 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] ^= 0xff; + fuzz->fuzzed[fuzz->o2] ^= 0xff; + fuzz->o1++; + if (fuzz->o1 >= fuzz->slen) { + fuzz->o1 = 0; + fuzz->o2++; + } + break; + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->o1++; + break; + case FUZZ_BASE64: + assert(fuzz->o1 < fuzz->slen); + assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2]; + fuzz->o2++; + if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) { + fuzz->o2 = 0; + fuzz->o1++; + } + break; + default: + abort(); + } + + FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, " + "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), + (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); +} + +int +fuzz_matches_original(struct fuzz *fuzz) +{ + if (fuzz_len(fuzz) != fuzz->slen) + return 0; + return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0; +} + +int +fuzz_done(struct fuzz *fuzz) +{ + FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz, + (u_long)fuzz->strategies)); + + return fuzz_strategy_done(fuzz) && fuzz->strategies == 0; +} + +size_t +fuzz_len(struct fuzz *fuzz) +{ + assert(fuzz->fuzzed != NULL); + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + case FUZZ_2_BIT_FLIP: + case FUZZ_1_BYTE_FLIP: + case FUZZ_2_BYTE_FLIP: + case FUZZ_BASE64: + return fuzz->slen; + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->slen - fuzz->o1; + default: + abort(); + } +} + +u_char * +fuzz_ptr(struct fuzz *fuzz) +{ + assert(fuzz->fuzzed != NULL); + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + case FUZZ_2_BIT_FLIP: + case FUZZ_1_BYTE_FLIP: + case FUZZ_2_BYTE_FLIP: + case FUZZ_BASE64: + return fuzz->fuzzed; + case FUZZ_TRUNCATE_START: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->fuzzed + fuzz->o1; + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->fuzzed; + default: + abort(); + } +} + diff --git a/crypto/openssh/regress/unittests/test_helper/test_helper.c b/crypto/openssh/regress/unittests/test_helper/test_helper.c new file mode 100644 index 0000000..26ca26b --- /dev/null +++ b/crypto/openssh/regress/unittests/test_helper/test_helper.c @@ -0,0 +1,526 @@ +/* $OpenBSD: test_helper.c,v 1.6 2015/03/03 20:42:49 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for regress tests */ + +#include "includes.h" + +#include +#include +#include + +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include +#include +#include +#include + +#include + +#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) +# include +#endif + +#include "test_helper.h" +#include "atomicio.h" + +#define TEST_CHECK_INT(r, pred) do { \ + switch (pred) { \ + case TEST_EQ: \ + if (r == 0) \ + return; \ + break; \ + case TEST_NE: \ + if (r != 0) \ + return; \ + break; \ + case TEST_LT: \ + if (r < 0) \ + return; \ + break; \ + case TEST_LE: \ + if (r <= 0) \ + return; \ + break; \ + case TEST_GT: \ + if (r > 0) \ + return; \ + break; \ + case TEST_GE: \ + if (r >= 0) \ + return; \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +#define TEST_CHECK(x1, x2, pred) do { \ + switch (pred) { \ + case TEST_EQ: \ + if (x1 == x2) \ + return; \ + break; \ + case TEST_NE: \ + if (x1 != x2) \ + return; \ + break; \ + case TEST_LT: \ + if (x1 < x2) \ + return; \ + break; \ + case TEST_LE: \ + if (x1 <= x2) \ + return; \ + break; \ + case TEST_GT: \ + if (x1 > x2) \ + return; \ + break; \ + case TEST_GE: \ + if (x1 >= x2) \ + return; \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +extern char *__progname; + +static int verbose_mode = 0; +static int quiet_mode = 0; +static char *active_test_name = NULL; +static u_int test_number = 0; +static test_onerror_func_t *test_onerror = NULL; +static void *onerror_ctx = NULL; +static const char *data_dir = NULL; +static char subtest_info[512]; + +int +main(int argc, char **argv) +{ + int ch; + + /* Handle systems without __progname */ + if (__progname == NULL) { + __progname = strrchr(argv[0], '/'); + if (__progname == NULL || __progname[1] == '\0') + __progname = argv[0]; + else + __progname++; + if ((__progname = strdup(__progname)) == NULL) { + fprintf(stderr, "strdup failed\n"); + exit(1); + } + } + + while ((ch = getopt(argc, argv, "vqd:")) != -1) { + switch (ch) { + case 'd': + data_dir = optarg; + break; + case 'q': + verbose_mode = 0; + quiet_mode = 1; + break; + case 'v': + verbose_mode = 1; + quiet_mode = 0; + break; + default: + fprintf(stderr, "Unrecognised command line option\n"); + fprintf(stderr, "Usage: %s [-v]\n", __progname); + exit(1); + } + } + setvbuf(stdout, NULL, _IONBF, 0); + if (!quiet_mode) + printf("%s: ", __progname); + if (verbose_mode) + printf("\n"); + + tests(); + + if (!quiet_mode) + printf(" %u tests ok\n", test_number); + return 0; +} + +const char * +test_data_file(const char *name) +{ + static char ret[PATH_MAX]; + + if (data_dir != NULL) + snprintf(ret, sizeof(ret), "%s/%s", data_dir, name); + else + strlcpy(ret, name, sizeof(ret)); + if (access(ret, F_OK) != 0) { + fprintf(stderr, "Cannot access data file %s: %s\n", + ret, strerror(errno)); + exit(1); + } + return ret; +} + +void +test_info(char *s, size_t len) +{ + snprintf(s, len, "In test %u: \"%s\"%s%s\n", test_number, + active_test_name == NULL ? "" : active_test_name, + *subtest_info != '\0' ? " - " : "", subtest_info); +} + +#ifdef SIGINFO +static void +siginfo(int unused __attribute__((__unused__))) +{ + char buf[256]; + + test_info(buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); +} +#endif + +void +test_start(const char *n) +{ + assert(active_test_name == NULL); + assert((active_test_name = strdup(n)) != NULL); + *subtest_info = '\0'; + if (verbose_mode) + printf("test %u - \"%s\": ", test_number, active_test_name); + test_number++; +#ifdef SIGINFO + signal(SIGINFO, siginfo); +#endif +} + +void +set_onerror_func(test_onerror_func_t *f, void *ctx) +{ + test_onerror = f; + onerror_ctx = ctx; +} + +void +test_done(void) +{ + *subtest_info = '\0'; + assert(active_test_name != NULL); + free(active_test_name); + active_test_name = NULL; + if (verbose_mode) + printf("OK\n"); + else if (!quiet_mode) { + printf("."); + fflush(stdout); + } +} + +void +test_subtest_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(subtest_info, sizeof(subtest_info), fmt, ap); + va_end(ap); +} + +void +ssl_err_check(const char *file, int line) +{ + long openssl_error = ERR_get_error(); + + if (openssl_error == 0) + return; + + fprintf(stderr, "\n%s:%d: uncaught OpenSSL error: %s", + file, line, ERR_error_string(openssl_error, NULL)); + abort(); +} + +static const char * +pred_name(enum test_predicate p) +{ + switch (p) { + case TEST_EQ: + return "EQ"; + case TEST_NE: + return "NE"; + case TEST_LT: + return "LT"; + case TEST_LE: + return "LE"; + case TEST_GT: + return "GT"; + case TEST_GE: + return "GE"; + default: + return "UNKNOWN"; + } +} + +static void +test_die(void) +{ + if (test_onerror != NULL) + test_onerror(onerror_ctx); + abort(); +} + +static void +test_header(const char *file, int line, const char *a1, const char *a2, + const char *name, enum test_predicate pred) +{ + fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n", + file, line, test_number, active_test_name, + *subtest_info != '\0' ? " - " : "", subtest_info); + fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n", + name, pred_name(pred), a1, + a2 != NULL ? ", " : "", a2 != NULL ? a2 : ""); +} + +void +assert_bignum(const char *file, int line, const char *a1, const char *a2, + const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred) +{ + int r = BN_cmp(aa1, aa2); + + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "BIGNUM", pred); + fprintf(stderr, "%12s = 0x%s\n", a1, BN_bn2hex(aa1)); + fprintf(stderr, "%12s = 0x%s\n", a2, BN_bn2hex(aa2)); + test_die(); +} + +void +assert_string(const char *file, int line, const char *a1, const char *a2, + const char *aa1, const char *aa2, enum test_predicate pred) +{ + int r; + + /* Verify pointers are not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE); + + r = strcmp(aa1, aa2); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "STRING", pred); + fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1)); + fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2)); + test_die(); +} + +static char * +tohex(const void *_s, size_t l) +{ + u_int8_t *s = (u_int8_t *)_s; + size_t i, j; + const char *hex = "0123456789abcdef"; + char *r = malloc((l * 2) + 1); + + assert(r != NULL); + for (i = j = 0; i < l; i++) { + r[j++] = hex[(s[i] >> 4) & 0xf]; + r[j++] = hex[s[i] & 0xf]; + } + r[j] = '\0'; + return r; +} + +void +assert_mem(const char *file, int line, const char *a1, const char *a2, + const void *aa1, const void *aa2, size_t l, enum test_predicate pred) +{ + int r; + + if (l == 0) + return; + /* If length is >0, then verify pointers are not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE); + + r = memcmp(aa1, aa2, l); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "STRING", pred); + fprintf(stderr, "%12s = %s (len %zu)\n", a1, tohex(aa1, MIN(l, 256)), l); + fprintf(stderr, "%12s = %s (len %zu)\n", a2, tohex(aa2, MIN(l, 256)), l); + test_die(); +} + +static int +memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where) +{ + size_t i; + + for (i = 0; i < l; i++) { + if (s[i] != v) { + *where = i; + return 1; + } + } + return 0; +} + +void +assert_mem_filled(const char *file, int line, const char *a1, + const void *aa1, u_char v, size_t l, enum test_predicate pred) +{ + size_t where = -1; + int r; + char tmp[64]; + + if (l == 0) + return; + /* If length is >0, then verify the pointer is not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + + r = memvalcmp(aa1, v, l, &where); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, NULL, "MEM_ZERO", pred); + fprintf(stderr, "%20s = %s%s (len %zu)\n", a1, + tohex(aa1, MIN(l, 20)), l > 20 ? "..." : "", l); + snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where); + fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp, + ((u_char *)aa1)[where], v); + test_die(); +} + +void +assert_int(const char *file, int line, const char *a1, const char *a2, + int aa1, int aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "INT", pred); + fprintf(stderr, "%12s = %d\n", a1, aa1); + fprintf(stderr, "%12s = %d\n", a2, aa2); + test_die(); +} + +void +assert_size_t(const char *file, int line, const char *a1, const char *a2, + size_t aa1, size_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "SIZE_T", pred); + fprintf(stderr, "%12s = %zu\n", a1, aa1); + fprintf(stderr, "%12s = %zu\n", a2, aa2); + test_die(); +} + +void +assert_u_int(const char *file, int line, const char *a1, const char *a2, + u_int aa1, u_int aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U_INT", pred); + fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2); + test_die(); +} + +void +assert_long_long(const char *file, int line, const char *a1, const char *a2, + long long aa1, long long aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "LONG LONG", pred); + fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2); + test_die(); +} + +void +assert_char(const char *file, int line, const char *a1, const char *a2, + char aa1, char aa2, enum test_predicate pred) +{ + char buf[8]; + + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "CHAR", pred); + fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, + vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1); + fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, + vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2); + test_die(); +} + +void +assert_u8(const char *file, int line, const char *a1, const char *a2, + u_int8_t aa1, u_int8_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U8", pred); + fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u16(const char *file, int line, const char *a1, const char *a2, + u_int16_t aa1, u_int16_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U16", pred); + fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u32(const char *file, int line, const char *a1, const char *a2, + u_int32_t aa1, u_int32_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U32", pred); + fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2); + test_die(); +} + +void +assert_u64(const char *file, int line, const char *a1, const char *a2, + u_int64_t aa1, u_int64_t aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U64", pred); + fprintf(stderr, "%12s = 0x%016llx %llu\n", a1, + (unsigned long long)aa1, (unsigned long long)aa1); + fprintf(stderr, "%12s = 0x%016llx %llu\n", a2, + (unsigned long long)aa2, (unsigned long long)aa2); + test_die(); +} + +void +assert_ptr(const char *file, int line, const char *a1, const char *a2, + const void *aa1, const void *aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "PTR", pred); + fprintf(stderr, "%12s = %p\n", a1, aa1); + fprintf(stderr, "%12s = %p\n", a2, aa2); + test_die(); +} + diff --git a/crypto/openssh/regress/unittests/test_helper/test_helper.h b/crypto/openssh/regress/unittests/test_helper/test_helper.h new file mode 100644 index 0000000..1d9c669 --- /dev/null +++ b/crypto/openssh/regress/unittests/test_helper/test_helper.h @@ -0,0 +1,303 @@ +/* $OpenBSD: test_helper.h,v 1.6 2015/01/18 19:52:44 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for regress tests */ + +#ifndef _TEST_HELPER_H +#define _TEST_HELPER_H + +#include "includes.h" + +#include +#ifdef HAVE_STDINT_H +# include +#endif + +#include +#include + +enum test_predicate { + TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE +}; +typedef void (test_onerror_func_t)(void *); + +/* Supplied by test suite */ +void tests(void); + +const char *test_data_file(const char *name); +void test_start(const char *n); +void test_info(char *s, size_t len); +void set_onerror_func(test_onerror_func_t *f, void *ctx); +void test_done(void); +void test_subtest_info(const char *fmt, ...) + __attribute__((format(printf, 1, 2))); +void ssl_err_check(const char *file, int line); +void assert_bignum(const char *file, int line, + const char *a1, const char *a2, + const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred); +void assert_string(const char *file, int line, + const char *a1, const char *a2, + const char *aa1, const char *aa2, enum test_predicate pred); +void assert_mem(const char *file, int line, + const char *a1, const char *a2, + const void *aa1, const void *aa2, size_t l, enum test_predicate pred); +void assert_mem_filled(const char *file, int line, + const char *a1, + const void *aa1, u_char v, size_t l, enum test_predicate pred); +void assert_int(const char *file, int line, + const char *a1, const char *a2, + int aa1, int aa2, enum test_predicate pred); +void assert_size_t(const char *file, int line, + const char *a1, const char *a2, + size_t aa1, size_t aa2, enum test_predicate pred); +void assert_u_int(const char *file, int line, + const char *a1, const char *a2, + u_int aa1, u_int aa2, enum test_predicate pred); +void assert_long_long(const char *file, int line, + const char *a1, const char *a2, + long long aa1, long long aa2, enum test_predicate pred); +void assert_char(const char *file, int line, + const char *a1, const char *a2, + char aa1, char aa2, enum test_predicate pred); +void assert_ptr(const char *file, int line, + const char *a1, const char *a2, + const void *aa1, const void *aa2, enum test_predicate pred); +void assert_u8(const char *file, int line, + const char *a1, const char *a2, + u_int8_t aa1, u_int8_t aa2, enum test_predicate pred); +void assert_u16(const char *file, int line, + const char *a1, const char *a2, + u_int16_t aa1, u_int16_t aa2, enum test_predicate pred); +void assert_u32(const char *file, int line, + const char *a1, const char *a2, + u_int32_t aa1, u_int32_t aa2, enum test_predicate pred); +void assert_u64(const char *file, int line, + const char *a1, const char *a2, + u_int64_t aa1, u_int64_t aa2, enum test_predicate pred); + +#define TEST_START(n) test_start(n) +#define TEST_DONE() test_done() +#define TEST_ONERROR(f, c) set_onerror_func(f, c) +#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__) + +#define ASSERT_BIGNUM_EQ(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_STRING_EQ(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_MEM_EQ(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ) +#define ASSERT_MEM_FILLED_EQ(a1, c, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ) +#define ASSERT_MEM_ZERO_EQ(a1, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ) +#define ASSERT_INT_EQ(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_SIZE_T_EQ(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U_INT_EQ(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_LONG_LONG_EQ(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_CHAR_EQ(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_PTR_EQ(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U8_EQ(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U16_EQ(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U32_EQ(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U64_EQ(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) + +#define ASSERT_BIGNUM_NE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_STRING_NE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_MEM_NE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE) +#define ASSERT_MEM_ZERO_NE(a1, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE) +#define ASSERT_INT_NE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_SIZE_T_NE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U_INT_NE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_LONG_LONG_NE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_CHAR_NE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_PTR_NE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U8_NE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U16_NE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U32_NE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U64_NE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) + +#define ASSERT_BIGNUM_LT(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_STRING_LT(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_MEM_LT(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT) +#define ASSERT_INT_LT(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_SIZE_T_LT(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U_INT_LT(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_LONG_LONG_LT(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_CHAR_LT(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_PTR_LT(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U8_LT(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U16_LT(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U32_LT(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U64_LT(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) + +#define ASSERT_BIGNUM_LE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_STRING_LE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_MEM_LE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE) +#define ASSERT_INT_LE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_SIZE_T_LE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U_INT_LE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_LONG_LONG_LE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_CHAR_LE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_PTR_LE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U8_LE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U16_LE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U32_LE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U64_LE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) + +#define ASSERT_BIGNUM_GT(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_STRING_GT(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_MEM_GT(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT) +#define ASSERT_INT_GT(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_SIZE_T_GT(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U_INT_GT(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_LONG_LONG_GT(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_CHAR_GT(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_PTR_GT(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U8_GT(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U16_GT(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U32_GT(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U64_GT(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) + +#define ASSERT_BIGNUM_GE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_STRING_GE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_MEM_GE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE) +#define ASSERT_INT_GE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_SIZE_T_GE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U_INT_GE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_LONG_LONG_GE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_CHAR_GE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_PTR_GE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U8_GE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U16_GE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U32_GE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U64_GE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) + +/* Fuzzing support */ + +struct fuzz; +#define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */ +#define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */ +#define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */ +#define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */ +#define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */ +#define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */ +#define FUZZ_BASE64 0x00000040 /* Try all base64 chars */ +#define FUZZ_MAX FUZZ_BASE64 + +/* Start fuzzing a blob of data with selected strategies (bitmask) */ +struct fuzz *fuzz_begin(u_int strategies, const void *p, size_t l); + +/* Free a fuzz context */ +void fuzz_cleanup(struct fuzz *fuzz); + +/* Prepare the next fuzz case in the series */ +void fuzz_next(struct fuzz *fuzz); + +/* + * Check whether this fuzz case is identical to the original + * This is slow, but useful if the caller needs to ensure that all tests + * generated change the input (e.g. when fuzzing signatures). + */ +int fuzz_matches_original(struct fuzz *fuzz); + +/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */ +int fuzz_done(struct fuzz *fuzz); + +/* Return the length and a pointer to the current fuzzed case */ +size_t fuzz_len(struct fuzz *fuzz); +u_char *fuzz_ptr(struct fuzz *fuzz); + +/* Dump the current fuzz case to stderr */ +void fuzz_dump(struct fuzz *fuzz); + +#endif /* _TEST_HELPER_H */ diff --git a/crypto/openssh/regress/valgrind-unit.sh b/crypto/openssh/regress/valgrind-unit.sh new file mode 100755 index 0000000..433cb06 --- /dev/null +++ b/crypto/openssh/regress/valgrind-unit.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +UNIT_BINARY="$1" +shift +UNIT_ARGS="$@" + +test "x$OBJ" = "x" && OBJ=$PWD + +# This mostly replicates the logic in test-exec.sh for running the +# regress tests under valgrind. +VG_TEST=`basename $UNIT_BINARY` +VG_LOG="$OBJ/valgrind-out/${VG_TEST}.%p" +VG_OPTS="--track-origins=yes --leak-check=full --log-file=${VG_LOG}" +VG_OPTS="$VG_OPTS --trace-children=yes" +VG_PATH="valgrind" +if [ "x$VALGRIND_PATH" != "x" ]; then + VG_PATH="$VALGRIND_PATH" +fi + +exec $VG_PATH $VG_OPTS $UNIT_BINARY $UNIT_ARGS diff --git a/crypto/openssh/regress/yes-head.sh b/crypto/openssh/regress/yes-head.sh index a8e6bc8..1fc7542 100644 --- a/crypto/openssh/regress/yes-head.sh +++ b/crypto/openssh/regress/yes-head.sh @@ -1,9 +1,9 @@ -# $OpenBSD: yes-head.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ +# $OpenBSD: yes-head.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ # Placed in the Public Domain. tid="yes pipe head" -for p in 1 2; do +for p in ${SSH_PROTOCOLS}; do lines=`${SSH} -$p -F $OBJ/ssh_proxy thishost 'sh -c "while true;do echo yes;done | _POSIX2_VERSION=199209 head -2000"' | (sleep 3 ; wc -l)` if [ $? -ne 0 ]; then fail "yes|head test failed" diff --git a/crypto/openssh/rijndael.c b/crypto/openssh/rijndael.c index 7432ea2..40ab7b1 100644 --- a/crypto/openssh/rijndael.c +++ b/crypto/openssh/rijndael.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rijndael.c,v 1.16 2004/06/23 00:39:38 mouring Exp $ */ +/* $OpenBSD: rijndael.c,v 1.20 2015/03/16 11:09:52 djm Exp $ */ /** * rijndael-alg-fst.c @@ -25,6 +25,7 @@ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "includes.h" #include @@ -32,20 +33,19 @@ #include "rijndael.h" -#define FULL_UNROLL +#undef FULL_UNROLL /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; +Td4[x] = Si[x].[01]; */ static const u32 Te0[256] = { @@ -247,7 +247,6 @@ static const u32 Te2[256] = { 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; static const u32 Te3[256] = { - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, @@ -313,72 +312,7 @@ static const u32 Te3[256] = { 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; -static const u32 Te4[256] = { - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; +#if 0 static const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, @@ -532,7 +466,6 @@ static const u32 Td2[256] = { 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, - 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, @@ -644,72 +577,41 @@ static const u32 Td3[256] = { 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; -static const u32 Td4[256] = { - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +static const u8 Td4[256] = { + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, }; +#endif static const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, @@ -724,8 +626,10 @@ static const u32 rcon[] = { * * @return the number of rounds for the given cipher key size. */ -static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { - int i = 0; +int +rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) +{ + int i = 0; u32 temp; rk[0] = GETU32(cipherKey ); @@ -736,10 +640,10 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int for (;;) { temp = rk[3]; rk[4] = rk[0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; @@ -756,10 +660,10 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int for (;;) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; @@ -778,49 +682,47 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int for (;;) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; - if (++i == 7) { - return 14; - } + if (++i == 7) { + return 14; + } temp = rk[11]; rk[12] = rk[ 4] ^ - (Te4[(temp >> 24) ] & 0xff000000) ^ - (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(temp ) & 0xff] & 0x000000ff); + (Te2[(temp >> 24) ] & 0xff000000) ^ + (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(temp ) & 0xff] & 0x000000ff); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; - rk[15] = rk[ 7] ^ rk[14]; + rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } return 0; } +#if 0 /** * Expand the cipher key into the decryption key schedule. * * @return the number of rounds for the given cipher key size. */ -static int -rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits, - int have_encrypt) { +int +rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) +{ int Nr, i, j; u32 temp; - if (have_encrypt) { - Nr = have_encrypt; - } else { - /* expand the cipher key: */ - Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); - } + /* expand the cipher key: */ + Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); + /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; @@ -832,30 +734,34 @@ rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits, for (i = 1; i < Nr; i++) { rk += 4; rk[0] = - Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + Td0[Te1[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[0] ) & 0xff] & 0xff]; rk[1] = - Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + Td0[Te1[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[1] ) & 0xff] & 0xff]; rk[2] = - Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + Td0[Te1[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[2] ) & 0xff] & 0xff]; rk[3] = - Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + Td0[Te1[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[3] ) & 0xff] & 0xff]; } return Nr; } +#endif -static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { +void +rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], + u8 ct[16]) +{ u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; @@ -871,50 +777,50 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16 s3 = GETU32(pt + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; @@ -1007,36 +913,40 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16 * map cipher state to byte array block: */ s0 = - (Te4[(t0 >> 24) ] & 0xff000000) ^ - (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + (Te2[(t0 >> 24) ] & 0xff000000) ^ + (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t3 ) & 0xff] & 0x000000ff) ^ rk[0]; PUTU32(ct , s0); s1 = - (Te4[(t1 >> 24) ] & 0xff000000) ^ - (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + (Te2[(t1 >> 24) ] & 0xff000000) ^ + (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t0 ) & 0xff] & 0x000000ff) ^ rk[1]; PUTU32(ct + 4, s1); s2 = - (Te4[(t2 >> 24) ] & 0xff000000) ^ - (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + (Te2[(t2 >> 24) ] & 0xff000000) ^ + (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t1 ) & 0xff] & 0x000000ff) ^ rk[2]; PUTU32(ct + 8, s2); s3 = - (Te4[(t3 >> 24) ] & 0xff000000) ^ - (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + (Te2[(t3 >> 24) ] & 0xff000000) ^ + (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t2 ) & 0xff] & 0x000000ff) ^ rk[3]; PUTU32(ct + 12, s3); } -static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { +#if 0 +static void +rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], + u8 pt[16]) +{ u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; @@ -1187,58 +1097,33 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16 * apply last round and * map cipher state to byte array block: */ - s0 = - (Td4[(t0 >> 24) ] & 0xff000000) ^ - (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[0]; + s0 = + (Td4[(t0 >> 24) ] << 24) ^ + (Td4[(t3 >> 16) & 0xff] << 16) ^ + (Td4[(t2 >> 8) & 0xff] << 8) ^ + (Td4[(t1 ) & 0xff]) ^ + rk[0]; PUTU32(pt , s0); - s1 = - (Td4[(t1 >> 24) ] & 0xff000000) ^ - (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[1]; + s1 = + (Td4[(t1 >> 24) ] << 24) ^ + (Td4[(t0 >> 16) & 0xff] << 16) ^ + (Td4[(t3 >> 8) & 0xff] << 8) ^ + (Td4[(t2 ) & 0xff]) ^ + rk[1]; PUTU32(pt + 4, s1); - s2 = - (Td4[(t2 >> 24) ] & 0xff000000) ^ - (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[2]; + s2 = + (Td4[(t2 >> 24) ] << 24) ^ + (Td4[(t1 >> 16) & 0xff] << 16) ^ + (Td4[(t0 >> 8) & 0xff] << 8) ^ + (Td4[(t3 ) & 0xff]) ^ + rk[2]; PUTU32(pt + 8, s2); - s3 = - (Td4[(t3 >> 24) ] & 0xff000000) ^ - (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[3]; + s3 = + (Td4[(t3 >> 24) ] << 24) ^ + (Td4[(t2 >> 16) & 0xff] << 16) ^ + (Td4[(t1 >> 8) & 0xff] << 8) ^ + (Td4[(t0 ) & 0xff]) ^ + rk[3]; PUTU32(pt + 12, s3); } - -void -rijndael_set_key(rijndael_ctx *ctx, u_char *key, int bits, int do_encrypt) -{ - ctx->Nr = rijndaelKeySetupEnc(ctx->ek, key, bits); - if (do_encrypt) { - ctx->decrypt = 0; - memset(ctx->dk, 0, sizeof(ctx->dk)); - } else { - ctx->decrypt = 1; - memcpy(ctx->dk, ctx->ek, sizeof(ctx->dk)); - rijndaelKeySetupDec(ctx->dk, key, bits, ctx->Nr); - } -} - -void -rijndael_decrypt(rijndael_ctx *ctx, u_char *src, u_char *dst) -{ - rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst); -} - -void -rijndael_encrypt(rijndael_ctx *ctx, u_char *src, u_char *dst) -{ - rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst); -} +#endif diff --git a/crypto/openssh/rijndael.h b/crypto/openssh/rijndael.h index c614bb1..53e74e0 100644 --- a/crypto/openssh/rijndael.h +++ b/crypto/openssh/rijndael.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rijndael.h,v 1.12 2001/12/19 07:18:56 deraadt Exp $ */ +/* $OpenBSD: rijndael.h,v 1.14 2014/04/29 15:42:07 markus Exp $ */ /** * rijndael-alg-fst.h @@ -25,27 +25,32 @@ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __RIJNDAEL_H -#define __RIJNDAEL_H +#ifndef _PRIVATE_RIJNDAEL_H +#define _PRIVATE_RIJNDAEL_H -#define MAXKC (256/32) -#define MAXKB (256/8) -#define MAXNR 14 +#define AES_MAXKEYBITS (256) +#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8) +/* for 256-bit keys, fewer for less */ +#define AES_MAXROUNDS 14 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; +int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int); +void rijndaelEncrypt(const unsigned int [], int, const unsigned char [], + unsigned char []); + /* The structure for key information */ typedef struct { int decrypt; - int Nr; /* key-length-dependent number of rounds */ - u32 ek[4*(MAXNR + 1)]; /* encrypt key schedule */ - u32 dk[4*(MAXNR + 1)]; /* decrypt key schedule */ + int Nr; /* key-length-dependent number of rounds */ + u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */ + u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */ } rijndael_ctx; void rijndael_set_key(rijndael_ctx *, u_char *, int, int); void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *); void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *); -#endif /* __RIJNDAEL_H */ +#endif /* _PRIVATE_RIJNDAEL_H */ diff --git a/crypto/openssh/roaming_client.c b/crypto/openssh/roaming_client.c index de049cd..cb13285 100644 --- a/crypto/openssh/roaming_client.c +++ b/crypto/openssh/roaming_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roaming_client.c,v 1.7 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: roaming_client.c,v 1.9 2015/01/27 12:54:06 okan Exp $ */ /* * Copyright (c) 2004-2009 AppGate Network Security AB * @@ -21,16 +21,10 @@ #include #include -#ifdef HAVE_INTTYPES_H -#include -#endif #include #include #include -#include -#include - #include "xmalloc.h" #include "buffer.h" #include "channels.h" diff --git a/crypto/openssh/roaming_common.c b/crypto/openssh/roaming_common.c index 787bef0..ea06460 100644 --- a/crypto/openssh/roaming_common.c +++ b/crypto/openssh/roaming_common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roaming_common.c,v 1.12 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: roaming_common.c,v 1.13 2015/01/27 12:54:06 okan Exp $ */ /* * Copyright (c) 2004-2009 AppGate Network Security AB * @@ -22,9 +22,6 @@ #include #include -#ifdef HAVE_INTTYPES_H -#include -#endif #include #include #include diff --git a/crypto/openssh/roaming_dummy.c b/crypto/openssh/roaming_dummy.c index 45c4008..837de69 100644 --- a/crypto/openssh/roaming_dummy.c +++ b/crypto/openssh/roaming_dummy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roaming_dummy.c,v 1.3 2009/06/21 09:04:03 dtucker Exp $ */ +/* $OpenBSD: roaming_dummy.c,v 1.4 2015/01/19 19:52:16 markus Exp $ */ /* * Copyright (c) 2004-2009 AppGate Network Security AB * @@ -35,6 +35,17 @@ get_recv_bytes(void) return 0; } +u_int64_t +get_sent_bytes(void) +{ + return 0; +} + +void +roam_set_bytes(u_int64_t sent, u_int64_t recvd) +{ +} + ssize_t roaming_write(int fd, const void *buf, size_t count, int *cont) { diff --git a/crypto/openssh/rsa.c b/crypto/openssh/rsa.c index d0b5bbf..5ecacef 100644 --- a/crypto/openssh/rsa.c +++ b/crypto/openssh/rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -67,85 +67,122 @@ #include #include -#include "xmalloc.h" #include "rsa.h" #include "log.h" +#include "ssherr.h" -void +int rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) { - u_char *inbuf, *outbuf; - int len, ilen, olen; + u_char *inbuf = NULL, *outbuf = NULL; + int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) - fatal("rsa_public_encrypt() exponent too small or not odd"); + return SSH_ERR_INVALID_ARGUMENT; olen = BN_num_bytes(key->n); - outbuf = xmalloc(olen); + if ((outbuf = malloc(olen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } ilen = BN_num_bytes(in); - inbuf = xmalloc(ilen); + if ((inbuf = malloc(ilen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } BN_bn2bin(in, inbuf); if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, - RSA_PKCS1_PADDING)) <= 0) - fatal("rsa_public_encrypt() failed"); + RSA_PKCS1_PADDING)) <= 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } - if (BN_bin2bn(outbuf, len, out) == NULL) - fatal("rsa_public_encrypt: BN_bin2bn failed"); + if (BN_bin2bn(outbuf, len, out) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + r = 0; - explicit_bzero(outbuf, olen); - explicit_bzero(inbuf, ilen); - free(outbuf); - free(inbuf); + out: + if (outbuf != NULL) { + explicit_bzero(outbuf, olen); + free(outbuf); + } + if (inbuf != NULL) { + explicit_bzero(inbuf, ilen); + free(inbuf); + } + return r; } int rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) { - u_char *inbuf, *outbuf; - int len, ilen, olen; + u_char *inbuf = NULL, *outbuf = NULL; + int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; olen = BN_num_bytes(key->n); - outbuf = xmalloc(olen); + if ((outbuf = malloc(olen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } ilen = BN_num_bytes(in); - inbuf = xmalloc(ilen); + if ((inbuf = malloc(ilen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } BN_bn2bin(in, inbuf); if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, RSA_PKCS1_PADDING)) <= 0) { - error("rsa_private_decrypt() failed"); - } else { - if (BN_bin2bn(outbuf, len, out) == NULL) - fatal("rsa_private_decrypt: BN_bin2bn failed"); + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } else if (BN_bin2bn(outbuf, len, out) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + r = 0; + out: + if (outbuf != NULL) { + explicit_bzero(outbuf, olen); + free(outbuf); + } + if (inbuf != NULL) { + explicit_bzero(inbuf, ilen); + free(inbuf); } - explicit_bzero(outbuf, olen); - explicit_bzero(inbuf, ilen); - free(outbuf); - free(inbuf); - return len; + return r; } /* calculate p-1 and q-1 */ -void +int rsa_generate_additional_parameters(RSA *rsa) { - BIGNUM *aux; - BN_CTX *ctx; + BIGNUM *aux = NULL; + BN_CTX *ctx = NULL; + int r; - if ((aux = BN_new()) == NULL) - fatal("rsa_generate_additional_parameters: BN_new failed"); if ((ctx = BN_CTX_new()) == NULL) - fatal("rsa_generate_additional_parameters: BN_CTX_new failed"); + return SSH_ERR_ALLOC_FAIL; + if ((aux = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || (BN_sub(aux, rsa->p, BN_value_one()) == 0) || - (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) - fatal("rsa_generate_additional_parameters: BN_sub/mod failed"); - + (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + r = 0; + out: BN_clear_free(aux); BN_CTX_free(ctx); + return r; } diff --git a/crypto/openssh/rsa.h b/crypto/openssh/rsa.h index b841ea4..c476707 100644 --- a/crypto/openssh/rsa.h +++ b/crypto/openssh/rsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rsa.h,v 1.16 2006/03/25 22:22:43 djm Exp $ */ +/* $OpenBSD: rsa.h,v 1.17 2014/06/24 01:13:21 djm Exp $ */ /* * Author: Tatu Ylonen @@ -19,8 +19,8 @@ #include #include -void rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); +int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *); -void rsa_generate_additional_parameters(RSA *); +int rsa_generate_additional_parameters(RSA *); #endif /* RSA_H */ diff --git a/crypto/openssh/sandbox-seccomp-filter.c b/crypto/openssh/sandbox-seccomp-filter.c index c0c17c2..2462bcc 100644 --- a/crypto/openssh/sandbox-seccomp-filter.c +++ b/crypto/openssh/sandbox-seccomp-filter.c @@ -25,6 +25,8 @@ */ /* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */ +/* XXX it should be possible to do logging via the log socket safely */ + #ifdef SANDBOX_SECCOMP_FILTER_DEBUG /* Use the kernel headers in case of an older toolchain. */ # include @@ -41,6 +43,7 @@ #include #include +#include #include #include #include @@ -77,6 +80,16 @@ #define SC_ALLOW(_nr) \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) +#define SC_ALLOW_ARG(_nr, _arg_nr, _arg_val) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 4), \ + /* load first syscall argument */ \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + offsetof(struct seccomp_data, args[(_arg_nr)])), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_arg_val), 0, 1), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ + /* reload syscall number; all rules expect it in accumulator */ \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + offsetof(struct seccomp_data, nr)) /* Syscall filtering set for preauth. */ static const struct sock_filter preauth_insns[] = { @@ -88,40 +101,105 @@ static const struct sock_filter preauth_insns[] = { /* Load the syscall number for checking. */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)), + + /* Syscalls to non-fatally deny */ +#ifdef __NR_fstat + SC_DENY(fstat, EACCES), +#endif +#ifdef __NR_fstat64 + SC_DENY(fstat64, EACCES), +#endif +#ifdef __NR_open SC_DENY(open, EACCES), - SC_ALLOW(getpid), - SC_ALLOW(gettimeofday), +#endif +#ifdef __NR_openat + SC_DENY(openat, EACCES), +#endif +#ifdef __NR_newfstatat + SC_DENY(newfstatat, EACCES), +#endif +#ifdef __NR_stat + SC_DENY(stat, EACCES), +#endif +#ifdef __NR_stat64 + SC_DENY(stat64, EACCES), +#endif + + /* Syscalls to permit */ +#ifdef __NR_brk + SC_ALLOW(brk), +#endif +#ifdef __NR_clock_gettime SC_ALLOW(clock_gettime), -#ifdef __NR_time /* not defined on EABI ARM */ - SC_ALLOW(time), #endif - SC_ALLOW(read), - SC_ALLOW(write), +#ifdef __NR_close SC_ALLOW(close), -#ifdef __NR_shutdown /* not defined on archs that go via socketcall(2) */ - SC_ALLOW(shutdown), #endif - SC_ALLOW(brk), - SC_ALLOW(poll), -#ifdef __NR__newselect - SC_ALLOW(_newselect), -#else - SC_ALLOW(select), +#ifdef __NR_exit + SC_ALLOW(exit), +#endif +#ifdef __NR_exit_group + SC_ALLOW(exit_group), +#endif +#ifdef __NR_getpgid + SC_ALLOW(getpgid), +#endif +#ifdef __NR_getpid + SC_ALLOW(getpid), #endif +#ifdef __NR_gettimeofday + SC_ALLOW(gettimeofday), +#endif +#ifdef __NR_madvise SC_ALLOW(madvise), -#ifdef __NR_mmap2 /* EABI ARM only has mmap2() */ - SC_ALLOW(mmap2), #endif #ifdef __NR_mmap SC_ALLOW(mmap), #endif +#ifdef __NR_mmap2 + SC_ALLOW(mmap2), +#endif +#ifdef __NR_mremap + SC_ALLOW(mremap), +#endif +#ifdef __NR_munmap SC_ALLOW(munmap), - SC_ALLOW(exit_group), +#endif +#ifdef __NR__newselect + SC_ALLOW(_newselect), +#endif +#ifdef __NR_poll + SC_ALLOW(poll), +#endif +#ifdef __NR_pselect6 + SC_ALLOW(pselect6), +#endif +#ifdef __NR_read + SC_ALLOW(read), +#endif #ifdef __NR_rt_sigprocmask SC_ALLOW(rt_sigprocmask), -#else +#endif +#ifdef __NR_select + SC_ALLOW(select), +#endif +#ifdef __NR_shutdown + SC_ALLOW(shutdown), +#endif +#ifdef __NR_sigprocmask SC_ALLOW(sigprocmask), #endif +#ifdef __NR_time + SC_ALLOW(time), +#endif +#ifdef __NR_write + SC_ALLOW(write), +#endif +#ifdef __NR_socketcall + SC_ALLOW_ARG(socketcall, 0, SYS_SHUTDOWN), +#endif + + /* Default deny */ BPF_STMT(BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), }; diff --git a/crypto/openssh/sandbox-systrace.c b/crypto/openssh/sandbox-systrace.c index 6706c9a..3830ed1 100644 --- a/crypto/openssh/sandbox-systrace.c +++ b/crypto/openssh/sandbox-systrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sandbox-systrace.c,v 1.9 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: sandbox-systrace.c,v 1.17 2015/07/27 16:29:23 guenther Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -20,7 +20,6 @@ #ifdef SANDBOX_SYSTRACE #include -#include #include #include #include @@ -37,6 +36,7 @@ #include #include #include +#include #include "atomicio.h" #include "log.h" @@ -50,22 +50,34 @@ struct sandbox_policy { /* Permitted syscalls in preauth. Unlisted syscalls get SYSTR_POLICY_KILL */ static const struct sandbox_policy preauth_policy[] = { - { SYS_open, SYSTR_POLICY_NEVER }, - - { SYS___sysctl, SYSTR_POLICY_PERMIT }, + { SYS_clock_gettime, SYSTR_POLICY_PERMIT }, { SYS_close, SYSTR_POLICY_PERMIT }, { SYS_exit, SYSTR_POLICY_PERMIT }, +#ifdef SYS_getentropy + /* OpenBSD 5.6 and newer use getentropy(2) to seed arc4random(3). */ + { SYS_getentropy, SYSTR_POLICY_PERMIT }, +#else + /* Previous releases used sysctl(3)'s kern.arnd variable. */ + { SYS___sysctl, SYSTR_POLICY_PERMIT }, +#endif { SYS_getpid, SYSTR_POLICY_PERMIT }, + { SYS_getpgid, SYSTR_POLICY_PERMIT }, { SYS_gettimeofday, SYSTR_POLICY_PERMIT }, - { SYS_clock_gettime, SYSTR_POLICY_PERMIT }, +#ifdef SYS_kbind + { SYS_kbind, SYSTR_POLICY_PERMIT }, +#endif { SYS_madvise, SYSTR_POLICY_PERMIT }, { SYS_mmap, SYSTR_POLICY_PERMIT }, { SYS_mprotect, SYSTR_POLICY_PERMIT }, { SYS_mquery, SYSTR_POLICY_PERMIT }, - { SYS_poll, SYSTR_POLICY_PERMIT }, { SYS_munmap, SYSTR_POLICY_PERMIT }, + { SYS_open, SYSTR_POLICY_NEVER }, + { SYS_poll, SYSTR_POLICY_PERMIT }, { SYS_read, SYSTR_POLICY_PERMIT }, { SYS_select, SYSTR_POLICY_PERMIT }, +#ifdef SYS_sendsyslog + { SYS_sendsyslog, SYSTR_POLICY_PERMIT }, +#endif { SYS_shutdown, SYSTR_POLICY_PERMIT }, { SYS_sigprocmask, SYSTR_POLICY_PERMIT }, { SYS_write, SYSTR_POLICY_PERMIT }, diff --git a/crypto/openssh/scard/.cvsignore b/crypto/openssh/scard/.cvsignore new file mode 100644 index 0000000..5349d34 --- /dev/null +++ b/crypto/openssh/scard/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Ssh.bin diff --git a/crypto/openssh/scp.0 b/crypto/openssh/scp.0 deleted file mode 100644 index b9eeffc..0000000 --- a/crypto/openssh/scp.0 +++ /dev/null @@ -1,163 +0,0 @@ -SCP(1) OpenBSD Reference Manual SCP(1) - -NAME - scp - secure copy (remote file copy program) - -SYNOPSIS - scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] - [-l limit] [-o ssh_option] [-P port] [-S program] - [[user@]host1:]file1 ... [[user@]host2:]file2 - -DESCRIPTION - scp copies files between hosts on a network. It uses ssh(1) for data - transfer, and uses the same authentication and provides the same security - as ssh(1). Unlike rcp(1), scp will ask for passwords or passphrases if - they are needed for authentication. - - File names may contain a user and host specification to indicate that the - file is to be copied to/from that host. Local file names can be made - explicit using absolute or relative pathnames to avoid scp treating file - names containing `:' as host specifiers. Copies between two remote hosts - are also permitted. - - The options are as follows: - - -1 Forces scp to use protocol 1. - - -2 Forces scp to use protocol 2. - - -3 Copies between two remote hosts are transferred through the local - host. Without this option the data is copied directly between - the two remote hosts. Note that this option disables the - progress meter. - - -4 Forces scp to use IPv4 addresses only. - - -6 Forces scp to use IPv6 addresses only. - - -B Selects batch mode (prevents asking for passwords or - passphrases). - - -C Compression enable. Passes the -C flag to ssh(1) to enable - compression. - - -c cipher - Selects the cipher to use for encrypting the data transfer. This - option is directly passed to ssh(1). - - -F ssh_config - Specifies an alternative per-user configuration file for ssh. - This option is directly passed to ssh(1). - - -i identity_file - Selects the file from which the identity (private key) for public - key authentication is read. This option is directly passed to - ssh(1). - - -l limit - Limits the used bandwidth, specified in Kbit/s. - - -o ssh_option - Can be used to pass options to ssh in the format used in - ssh_config(5). This is useful for specifying options for which - there is no separate scp command-line flag. For full details of - the options listed below, and their possible values, see - ssh_config(5). - - AddressFamily - BatchMode - BindAddress - CanonicalDomains - CanonicalizeFallbackLocal - CanonicalizeHostname - CanonicalizeMaxDots - CanonicalizePermittedCNAMEs - ChallengeResponseAuthentication - CheckHostIP - Cipher - Ciphers - Compression - CompressionLevel - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - ControlPersist - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - HostName - IdentityFile - IdentitiesOnly - IPQoS - KbdInteractiveAuthentication - KbdInteractiveDevices - KexAlgorithms - LogLevel - MACs - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PKCS11Provider - Port - PreferredAuthentications - Protocol - ProxyCommand - PubkeyAuthentication - RekeyLimit - RhostsRSAAuthentication - RSAAuthentication - SendEnv - ServerAliveInterval - ServerAliveCountMax - StrictHostKeyChecking - TCPKeepAlive - UsePrivilegedPort - User - UserKnownHostsFile - VerifyHostKeyDNS - - -P port - Specifies the port to connect to on the remote host. Note that - this option is written with a capital `P', because -p is already - reserved for preserving the times and modes of the file in - rcp(1). - - -p Preserves modification times, access times, and modes from the - original file. - - -q Quiet mode: disables the progress meter as well as warning and - diagnostic messages from ssh(1). - - -r Recursively copy entire directories. Note that scp follows - symbolic links encountered in the tree traversal. - - -S program - Name of program to use for the encrypted connection. The program - must understand ssh(1) options. - - -v Verbose mode. Causes scp and ssh(1) to print debugging messages - about their progress. This is helpful in debugging connection, - authentication, and configuration problems. - -EXIT STATUS - The scp utility exits 0 on success, and >0 if an error occurs. - -SEE ALSO - rcp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), - ssh_config(5), sshd(8) - -HISTORY - scp is based on the rcp(1) program in BSD source code from the Regents of - the University of California. - -AUTHORS - Timo Rinne - Tatu Ylonen - -OpenBSD 5.5 October 20, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/scp.1 b/crypto/openssh/scp.1 index 3b67cff..279b0d7 100644 --- a/crypto/openssh/scp.1 +++ b/crypto/openssh/scp.1 @@ -8,9 +8,9 @@ .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" -.\" $OpenBSD: scp.1,v 1.61 2013/10/20 09:51:26 djm Exp $ +.\" $OpenBSD: scp.1,v 1.67 2015/07/10 06:21:53 markus Exp $ .\" -.Dd $Mdocdate: October 20 2013 $ +.Dd $Mdocdate: July 10 2015 $ .Dt SCP 1 .Os .Sh NAME @@ -30,14 +30,14 @@ .Sm off .Oo .Op Ar user No @ -.Ar host1 No : +.Ar host1 : .Oc Ar file1 .Sm on .Ar ... .Sm off .Oo .Op Ar user No @ -.Ar host2 No : +.Ar host2 : .Oc Ar file2 .Sm on .Ek @@ -49,8 +49,6 @@ It uses for data transfer, and uses the same authentication and provides the same security as .Xr ssh 1 . -Unlike -.Xr rcp 1 , .Nm will ask for passwords or passphrases if they are needed for authentication. @@ -152,6 +150,7 @@ For full details of the options listed below, and their possible values, see .It HashKnownHosts .It Host .It HostbasedAuthentication +.It HostbasedKeyTypes .It HostKeyAlgorithms .It HostKeyAlias .It HostName @@ -171,6 +170,7 @@ For full details of the options listed below, and their possible values, see .It PreferredAuthentications .It Protocol .It ProxyCommand +.It PubkeyAcceptedKeyTypes .It PubkeyAuthentication .It RekeyLimit .It RhostsRSAAuthentication @@ -180,6 +180,7 @@ For full details of the options listed below, and their possible values, see .It ServerAliveCountMax .It StrictHostKeyChecking .It TCPKeepAlive +.It UpdateHostKeys .It UsePrivilegedPort .It User .It UserKnownHostsFile @@ -191,8 +192,7 @@ Note that this option is written with a capital .Sq P , because .Fl p -is already reserved for preserving the times and modes of the file in -.Xr rcp 1 . +is already reserved for preserving the times and modes of the file. .It Fl p Preserves modification times, access times, and modes from the original file. @@ -225,7 +225,6 @@ debugging connection, authentication, and configuration problems. .Sh EXIT STATUS .Ex -std scp .Sh SEE ALSO -.Xr rcp 1 , .Xr sftp 1 , .Xr ssh 1 , .Xr ssh-add 1 , @@ -235,9 +234,7 @@ debugging connection, authentication, and configuration problems. .Xr sshd 8 .Sh HISTORY .Nm -is based on the -.Xr rcp 1 -program in +is based on the rcp program in .Bx source code from the Regents of the University of California. .Sh AUTHORS diff --git a/crypto/openssh/scp.c b/crypto/openssh/scp.c index 18d3b1d..593fe89 100644 --- a/crypto/openssh/scp.c +++ b/crypto/openssh/scp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scp.c,v 1.179 2013/11/20 20:53:10 deraadt Exp $ */ +/* $OpenBSD: scp.c,v 1.182 2015/04/24 01:36:00 deraadt Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). @@ -95,6 +95,7 @@ #include #include #include +#include #include #include #include @@ -747,9 +748,9 @@ source(int argc, char **argv) static BUF buffer; BUF *bp; off_t i, statbytes; - size_t amt; + size_t amt, nr; int fd = -1, haderr, indx; - char *last, *name, buf[2048], encname[MAXPATHLEN]; + char *last, *name, buf[2048], encname[PATH_MAX]; int len; for (indx = 0; indx < argc; ++indx) { @@ -820,12 +821,16 @@ next: if (fd != -1) { if (i + (off_t)amt > stb.st_size) amt = stb.st_size - i; if (!haderr) { - if (atomicio(read, fd, bp->buf, amt) != amt) + if ((nr = atomicio(read, fd, + bp->buf, amt)) != amt) { haderr = errno; + memset(bp->buf + nr, 0, amt - nr); + } } /* Keep writing after error to retain sync */ if (haderr) { (void)atomicio(vwrite, remout, bp->buf, amt); + memset(bp->buf, 0, amt); continue; } if (atomicio6(vwrite, remout, bp->buf, amt, scpio, @@ -854,7 +859,7 @@ rsource(char *name, struct stat *statp) { DIR *dirp; struct dirent *dp; - char *last, *vect[1], path[MAXPATHLEN]; + char *last, *vect[1], path[PATH_MAX]; if (!(dirp = opendir(name))) { run_err("%s: %s", name, strerror(errno)); @@ -1328,7 +1333,7 @@ allocbuf(BUF *bp, int fd, int blksize) if (bp->buf == NULL) bp->buf = xmalloc(size); else - bp->buf = xrealloc(bp->buf, 1, size); + bp->buf = xreallocarray(bp->buf, 1, size); memset(bp->buf, 0, size); bp->cnt = size; return (bp); diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index 61fe7a9..6f5c07d 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.249 2014/01/29 06:18:35 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.280 2015/08/06 14:53:21 deraadt Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -29,6 +29,7 @@ __RCSID("$FreeBSD$"); #include #include #include +#include #include #include #ifdef HAVE_UTIL_H @@ -40,10 +41,10 @@ __RCSID("$FreeBSD$"); #include "ssh.h" #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" #include "compat.h" #include "pathnames.h" -#include "misc.h" #include "cipher.h" #include "key.h" #include "kex.h" @@ -55,6 +56,8 @@ __RCSID("$FreeBSD$"); #include "packet.h" #include "hostfile.h" #include "auth.h" +#include "myproposal.h" +#include "digest.h" #include "version.h" static void add_listen_addr(ServerOptions *, char *, int); @@ -77,6 +80,8 @@ initialize_server_options(ServerOptions *options) /* Standard Options */ options->num_ports = 0; options->ports_from_cmdline = 0; + options->queued_listen_addrs = NULL; + options->num_queued_listens = 0; options->listen_addrs = NULL; options->address_family = -1; options->num_host_key_files = 0; @@ -95,6 +100,7 @@ initialize_server_options(ServerOptions *options) options->x11_display_offset = -1; options->x11_use_localhost = -1; options->permit_tty = -1; + options->permit_user_rc = -1; options->xauth_location = NULL; options->strict_modes = -1; options->tcp_keep_alive = -1; @@ -103,14 +109,18 @@ initialize_server_options(ServerOptions *options) options->rhosts_rsa_authentication = -1; options->hostbased_authentication = -1; options->hostbased_uses_name_from_packet_only = -1; + options->hostbased_key_types = NULL; + options->hostkeyalgorithms = NULL; options->rsa_authentication = -1; options->pubkey_authentication = -1; + options->pubkey_key_types = NULL; options->kerberos_authentication = -1; options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; options->gss_cleanup_creds = -1; + options->gss_strict_acceptor = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; @@ -121,6 +131,7 @@ initialize_server_options(ServerOptions *options) options->rekey_limit = -1; options->rekey_interval = -1; options->allow_tcp_forwarding = -1; + options->allow_streamlocal_forwarding = -1; options->allow_agent_forwarding = -1; options->num_allow_users = 0; options->num_deny_users = 0; @@ -130,7 +141,9 @@ initialize_server_options(ServerOptions *options) options->macs = NULL; options->kex_algorithms = NULL; options->protocol = SSH_PROTO_UNKNOWN; - options->gateway_ports = -1; + options->fwd_opts.gateway_ports = -1; + options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; + options->fwd_opts.streamlocal_bind_unlink = -1; options->num_subsystems = 0; options->max_startups_begin = -1; options->max_startups_rate = -1; @@ -152,14 +165,26 @@ initialize_server_options(ServerOptions *options) options->revoked_keys_file = NULL; options->trusted_user_ca_keys = NULL; options->authorized_principals_file = NULL; + options->authorized_principals_command = NULL; + options->authorized_principals_command_user = NULL; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->version_addendum = NULL; + options->fingerprint_hash = -1; +} + +/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ +static int +option_clear_or_none(const char *o) +{ + return o == NULL || strcasecmp(o, "none") == 0; } void fill_default_server_options(ServerOptions *options) { + int i; + /* Portable-specific options */ if (options->use_pam == -1) options->use_pam = 1; @@ -167,6 +192,8 @@ fill_default_server_options(ServerOptions *options) /* Standard Options */ if (options->protocol == SSH_PROTO_UNKNOWN) options->protocol = SSH_PROTO_2; + if (options->protocol & SSH_PROTO_1) + error("WARNING: SSH protocol version 1 enabled"); if (options->num_host_key_files == 0) { /* fill default hostkeys for protocols */ if (options->protocol & SSH_PROTO_1) @@ -188,10 +215,12 @@ fill_default_server_options(ServerOptions *options) /* No certificates by default */ if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; + if (options->address_family == -1) + options->address_family = AF_UNSPEC; if (options->listen_addrs == NULL) add_listen_addr(options, NULL, 0); if (options->pid_file == NULL) - options->pid_file = _PATH_SSH_DAEMON_PID_FILE; + options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); if (options->server_key_bits == -1) options->server_key_bits = 1024; if (options->login_grace_time == -1) @@ -215,9 +244,11 @@ fill_default_server_options(ServerOptions *options) if (options->x11_use_localhost == -1) options->x11_use_localhost = 1; if (options->xauth_location == NULL) - options->xauth_location = _PATH_XAUTH; + options->xauth_location = xstrdup(_PATH_XAUTH); if (options->permit_tty == -1) options->permit_tty = 1; + if (options->permit_user_rc == -1) + options->permit_user_rc = 1; if (options->strict_modes == -1) options->strict_modes = 1; if (options->tcp_keep_alive == -1) @@ -232,6 +263,8 @@ fill_default_server_options(ServerOptions *options) options->hostbased_authentication = 0; if (options->hostbased_uses_name_from_packet_only == -1) options->hostbased_uses_name_from_packet_only = 0; + if (options->hostkeyalgorithms == NULL) + options->hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG); if (options->rsa_authentication == -1) options->rsa_authentication = 1; if (options->pubkey_authentication == -1) @@ -248,6 +281,8 @@ fill_default_server_options(ServerOptions *options) options->gss_authentication = 0; if (options->gss_cleanup_creds == -1) options->gss_cleanup_creds = 1; + if (options->gss_strict_acceptor == -1) + options->gss_strict_acceptor = 0; if (options->password_authentication == -1) options->password_authentication = 0; if (options->kbd_interactive_authentication == -1) @@ -268,10 +303,12 @@ fill_default_server_options(ServerOptions *options) options->rekey_interval = 0; if (options->allow_tcp_forwarding == -1) options->allow_tcp_forwarding = FORWARD_ALLOW; + if (options->allow_streamlocal_forwarding == -1) + options->allow_streamlocal_forwarding = FORWARD_ALLOW; if (options->allow_agent_forwarding == -1) options->allow_agent_forwarding = 1; - if (options->gateway_ports == -1) - options->gateway_ports = 0; + if (options->fwd_opts.gateway_ports == -1) + options->fwd_opts.gateway_ports = 0; if (options->max_startups == -1) options->max_startups = 100; if (options->max_startups_rate == -1) @@ -302,10 +339,45 @@ fill_default_server_options(ServerOptions *options) options->ip_qos_bulk = IPTOS_THROUGHPUT; if (options->version_addendum == NULL) options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); + if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) + options->fwd_opts.streamlocal_bind_mask = 0177; + if (options->fwd_opts.streamlocal_bind_unlink == -1) + options->fwd_opts.streamlocal_bind_unlink = 0; + if (options->fingerprint_hash == -1) + options->fingerprint_hash = SSH_FP_HASH_DEFAULT; + + if (kex_assemble_names(KEX_SERVER_ENCRYPT, &options->ciphers) != 0 || + kex_assemble_names(KEX_SERVER_MAC, &options->macs) != 0 || + kex_assemble_names(KEX_SERVER_KEX, &options->kex_algorithms) != 0 || + kex_assemble_names(KEX_DEFAULT_PK_ALG, + &options->hostbased_key_types) != 0 || + kex_assemble_names(KEX_DEFAULT_PK_ALG, + &options->pubkey_key_types) != 0) + fatal("%s: kex_assemble_names failed", __func__); + /* Turn privilege separation on by default */ if (use_privsep == -1) use_privsep = PRIVSEP_ON; +#define CLEAR_ON_NONE(v) \ + do { \ + if (option_clear_or_none(v)) { \ + free(v); \ + v = NULL; \ + } \ + } while(0) + CLEAR_ON_NONE(options->pid_file); + CLEAR_ON_NONE(options->xauth_location); + CLEAR_ON_NONE(options->banner); + CLEAR_ON_NONE(options->trusted_user_ca_keys); + CLEAR_ON_NONE(options->revoked_keys_file); + CLEAR_ON_NONE(options->authorized_principals_file); + for (i = 0; i < options->num_host_key_files; i++) + CLEAR_ON_NONE(options->host_key_files[i]); + for (i = 0; i < options->num_host_cert_files; i++) + CLEAR_ON_NONE(options->host_cert_files[i]); +#undef CLEAR_ON_NONE + #ifndef HAVE_MMAP if (use_privsep && options->compression == 1) { error("This platform does not support both privilege " @@ -323,8 +395,8 @@ typedef enum { /* Portable-specific options */ sUsePAM, /* Standard Options */ - sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, - sPermitRootLogin, sLogFacility, sLogLevel, + sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, + sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel, sRhostsRSAAuthentication, sRSAAuthentication, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, sKerberosGetAFSToken, @@ -337,19 +409,24 @@ typedef enum { sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, - sMaxStartups, sMaxAuthTries, sMaxSessions, + sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes, + sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, sBanner, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, - sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, + sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes, + sHostKeyAlgorithms, + sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, + sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, + sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, sHostCertificate, sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, + sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, sKexAlgorithms, sIPQoS, sVersionAddendum, sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, - sAuthenticationMethods, sHostKeyAgent, + sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, + sStreamLocalBindMask, sStreamLocalBindUnlink, + sAllowStreamLocalForwarding, sFingerprintHash, sDeprecated, sUnsupported } ServerOpCodes; @@ -386,8 +463,11 @@ static struct { { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL }, { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, + { "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL }, + { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL }, { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL }, { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, + { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL }, { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ #ifdef KRB5 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, @@ -409,9 +489,11 @@ static struct { #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, + { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, #endif { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, @@ -462,6 +544,7 @@ static struct { { "acceptenv", sAcceptEnv, SSHCFG_ALL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, { "permittty", sPermitTTY, SSHCFG_ALL }, + { "permituserrc", sPermitUserRC, SSHCFG_ALL }, { "match", sMatch, SSHCFG_ALL }, { "permitopen", sPermitOpen, SSHCFG_ALL }, { "forcecommand", sForceCommand, SSHCFG_ALL }, @@ -474,8 +557,14 @@ static struct { { "ipqos", sIPQoS, SSHCFG_ALL }, { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, + { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL }, + { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL }, { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, + { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, + { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, + { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, + { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { "noneenabled", sUnsupported, SSHCFG_ALL }, { "hpndisabled", sDeprecated, SSHCFG_ALL }, { "hpnbuffersize", sDeprecated, SSHCFG_ALL }, @@ -518,8 +607,10 @@ parse_token(const char *cp, const char *filename, char * derelativise_path(const char *path) { - char *expanded, *ret, cwd[MAXPATHLEN]; + char *expanded, *ret, cwd[PATH_MAX]; + if (strcasecmp(path, "none") == 0) + return xstrdup("none"); expanded = tilde_expand_filename(path, getuid()); if (*expanded == '/') return expanded; @@ -535,10 +626,6 @@ add_listen_addr(ServerOptions *options, char *addr, int port) { u_int i; - if (options->num_ports == 0) - options->ports[options->num_ports++] = SSH_DEFAULT_PORT; - if (options->address_family == -1) - options->address_family = AF_UNSPEC; if (port == 0) for (i = 0; i < options->num_ports; i++) add_one_listen_addr(options, addr, options->ports[i]); @@ -568,6 +655,51 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port) options->listen_addrs = aitop; } +/* + * Queue a ListenAddress to be processed once we have all of the Ports + * and AddressFamily options. + */ +static void +queue_listen_addr(ServerOptions *options, char *addr, int port) +{ + options->queued_listen_addrs = xreallocarray( + options->queued_listen_addrs, options->num_queued_listens + 1, + sizeof(addr)); + options->queued_listen_ports = xreallocarray( + options->queued_listen_ports, options->num_queued_listens + 1, + sizeof(port)); + options->queued_listen_addrs[options->num_queued_listens] = + xstrdup(addr); + options->queued_listen_ports[options->num_queued_listens] = port; + options->num_queued_listens++; +} + +/* + * Process queued (text) ListenAddress entries. + */ +static void +process_queued_listen_addrs(ServerOptions *options) +{ + u_int i; + + if (options->num_ports == 0) + options->ports[options->num_ports++] = SSH_DEFAULT_PORT; + if (options->address_family == -1) + options->address_family = AF_UNSPEC; + + for (i = 0; i < options->num_queued_listens; i++) { + add_listen_addr(options, options->queued_listen_addrs[i], + options->queued_listen_ports[i]); + free(options->queued_listen_addrs[i]); + options->queued_listen_addrs[i] = NULL; + } + free(options->queued_listen_addrs); + options->queued_listen_addrs = NULL; + free(options->queued_listen_ports); + options->queued_listen_ports = NULL; + options->num_queued_listens = 0; +} + struct connection_info * get_connection_info(int populate, int use_dns) { @@ -653,7 +785,6 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) { int result = 1, attributes = 0, port; char *arg, *attrib, *cp = *condition; - size_t len; if (ci == NULL) debug3("checking syntax for 'Match %s'", cp); @@ -680,13 +811,12 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) error("Missing Match criteria for %s", attrib); return -1; } - len = strlen(arg); if (strcasecmp(attrib, "user") == 0) { if (ci == NULL || ci->user == NULL) { result = 0; continue; } - if (match_pattern_list(ci->user, arg, len, 0) != 1) + if (match_pattern_list(ci->user, arg, 0) != 1) result = 0; else debug("user %.100s matched 'User %.100s' at " @@ -707,7 +837,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) result = 0; continue; } - if (match_hostname(ci->host, arg, len) != 1) + if (match_hostname(ci->host, arg) != 1) result = 0; else debug("connection from %.100s matched 'Host " @@ -794,6 +924,7 @@ static const struct multistate multistate_addressfamily[] = { }; static const struct multistate multistate_permitrootlogin[] = { { "without-password", PERMIT_NO_PASSWD }, + { "prohibit-password", PERMIT_NO_PASSWD }, { "forced-commands-only", PERMIT_FORCED_ONLY }, { "yes", PERMIT_YES }, { "no", PERMIT_NO }, @@ -884,9 +1015,6 @@ process_server_config_line(ServerOptions *options, char *line, /* ignore ports from configfile if cmdline specifies ports */ if (options->ports_from_cmdline) return 0; - if (options->listen_addrs != NULL) - fatal("%s line %d: ports must be specified before " - "ListenAddress.", filename, linenum); if (options->num_ports >= MAX_PORTS) fatal("%s line %d: too many ports.", filename, linenum); @@ -922,7 +1050,7 @@ process_server_config_line(ServerOptions *options, char *line, if ((value = convtime(arg)) == -1) fatal("%s line %d: invalid time value.", filename, linenum); - if (*intptr == -1) + if (*activep && *intptr == -1) *intptr = value; break; @@ -938,7 +1066,7 @@ process_server_config_line(ServerOptions *options, char *line, /* check for bare IPv6 address: no "[]" and 2 or more ":" */ if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL && strchr(p+1, ':') != NULL) { - add_listen_addr(options, arg, 0); + queue_listen_addr(options, arg, 0); break; } p = hpdelim(&arg); @@ -951,16 +1079,13 @@ process_server_config_line(ServerOptions *options, char *line, else if ((port = a2port(arg)) <= 0) fatal("%s line %d: bad port number", filename, linenum); - add_listen_addr(options, p, port); + queue_listen_addr(options, p, port); break; case sAddressFamily: intptr = &options->address_family; multistate_ptr = multistate_addressfamily; - if (options->listen_addrs != NULL) - fatal("%s line %d: address family must be specified " - "before ListenAddress.", filename, linenum); parse_multistate: arg = strdelim(&cp); if (!arg || *arg == '\0') @@ -1064,6 +1189,24 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->hostbased_uses_name_from_packet_only; goto parse_flag; + case sHostbasedAcceptedKeyTypes: + charptr = &options->hostbased_key_types; + parse_keytypes: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", + filename, linenum); + if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1)) + fatal("%s line %d: Bad key types '%s'.", + filename, linenum, arg ? arg : ""); + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + break; + + case sHostKeyAlgorithms: + charptr = &options->hostkeyalgorithms; + goto parse_keytypes; + case sRSAAuthentication: intptr = &options->rsa_authentication; goto parse_flag; @@ -1072,6 +1215,10 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->pubkey_authentication; goto parse_flag; + case sPubkeyAcceptedKeyTypes: + charptr = &options->pubkey_key_types; + goto parse_keytypes; + case sKerberosAuthentication: intptr = &options->kerberos_authentication; goto parse_flag; @@ -1096,6 +1243,10 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->gss_cleanup_creds; goto parse_flag; + case sGssStrictAcceptor: + intptr = &options->gss_strict_acceptor; + goto parse_flag; + case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; @@ -1136,6 +1287,10 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->permit_tty; goto parse_flag; + case sPermitUserRC: + intptr = &options->permit_user_rc; + goto parse_flag; + case sStrictModes: intptr = &options->strict_modes; goto parse_flag; @@ -1193,7 +1348,7 @@ process_server_config_line(ServerOptions *options, char *line, break; case sGatewayPorts: - intptr = &options->gateway_ports; + intptr = &options->fwd_opts.gateway_ports; multistate_ptr = multistate_gatewayports; goto parse_multistate; @@ -1228,6 +1383,11 @@ process_server_config_line(ServerOptions *options, char *line, multistate_ptr = multistate_tcpfwd; goto parse_multistate; + case sAllowStreamLocalForwarding: + intptr = &options->allow_streamlocal_forwarding; + multistate_ptr = multistate_tcpfwd; + goto parse_multistate; + case sAllowAgentForwarding: intptr = &options->allow_agent_forwarding; goto parse_flag; @@ -1289,7 +1449,7 @@ process_server_config_line(ServerOptions *options, char *line, arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: Missing argument.", filename, linenum); - if (!ciphers_valid(arg)) + if (!ciphers_valid(*arg == '+' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, arg ? arg : ""); if (options->ciphers == NULL) @@ -1300,7 +1460,7 @@ process_server_config_line(ServerOptions *options, char *line, arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: Missing argument.", filename, linenum); - if (!mac_valid(arg)) + if (!mac_valid(*arg == '+' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 mac spec '%s'.", filename, linenum, arg ? arg : ""); if (options->macs == NULL) @@ -1312,7 +1472,7 @@ process_server_config_line(ServerOptions *options, char *line, if (!arg || *arg == '\0') fatal("%s line %d: Missing argument.", filename, linenum); - if (!kex_names_valid(arg)) + if (!kex_names_valid(*arg == '+' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", filename, linenum, arg ? arg : ""); if (options->kex_algorithms == NULL) @@ -1361,7 +1521,7 @@ process_server_config_line(ServerOptions *options, char *line, len = strlen(p) + 1; while ((arg = strdelim(&cp)) != NULL && *arg != '\0') { len += 1 + strlen(arg); - p = xrealloc(p, 1, len); + p = xreallocarray(p, 1, len); strlcat(p, " ", len); strlcat(p, arg, len); } @@ -1476,7 +1636,7 @@ process_server_config_line(ServerOptions *options, char *line, if (value == -1) fatal("%s line %d: Bad yes/point-to-point/ethernet/" "no argument: %s", filename, linenum, arg); - if (*intptr == -1) + if (*activep && *intptr == -1) *intptr = value; break; @@ -1529,7 +1689,7 @@ process_server_config_line(ServerOptions *options, char *line, break; case sForceCommand: - if (cp == NULL) + if (cp == NULL || *cp == '\0') fatal("%.200s line %d: Missing argument.", filename, linenum); len = strspn(cp, WHITESPACE); @@ -1574,7 +1734,7 @@ process_server_config_line(ServerOptions *options, char *line, break; case sVersionAddendum: - if (cp == NULL) + if (cp == NULL || *cp == '\0') fatal("%.200s line %d: Missing argument.", filename, linenum); len = strspn(cp, WHITESPACE); @@ -1590,6 +1750,9 @@ process_server_config_line(ServerOptions *options, char *line, return 0; case sAuthorizedKeysCommand: + if (cp == NULL) + fatal("%.200s line %d: Missing argument.", filename, + linenum); len = strspn(cp, WHITESPACE); if (*activep && options->authorized_keys_command == NULL) { if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0) @@ -1604,12 +1767,43 @@ process_server_config_line(ServerOptions *options, char *line, charptr = &options->authorized_keys_command_user; arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing AuthorizedKeysCommandUser " + "argument.", filename, linenum); + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + break; + + case sAuthorizedPrincipalsCommand: + if (cp == NULL) + fatal("%.200s line %d: Missing argument.", filename, + linenum); + len = strspn(cp, WHITESPACE); + if (*activep && + options->authorized_principals_command == NULL) { + if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0) + fatal("%.200s line %d: " + "AuthorizedPrincipalsCommand must be " + "an absolute path", filename, linenum); + options->authorized_principals_command = + xstrdup(cp + len); + } + return 0; + + case sAuthorizedPrincipalsCommandUser: + charptr = &options->authorized_principals_command_user; + + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing " + "AuthorizedPrincipalsCommandUser argument.", + filename, linenum); if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sAuthenticationMethods: - if (*activep && options->num_auth_methods == 0) { + if (options->num_auth_methods == 0) { while ((arg = strdelim(&cp)) && *arg != '\0') { if (options->num_auth_methods >= MAX_AUTH_METHODS) @@ -1620,12 +1814,43 @@ process_server_config_line(ServerOptions *options, char *line, fatal("%s line %d: invalid " "authentication method list.", filename, linenum); + if (!*activep) + continue; options->auth_methods[ options->num_auth_methods++] = xstrdup(arg); } } return 0; + case sStreamLocalBindMask: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing StreamLocalBindMask " + "argument.", filename, linenum); + /* Parse mode in octal format */ + value = strtol(arg, &p, 8); + if (arg == p || value < 0 || value > 0777) + fatal("%s line %d: Bad mask.", filename, linenum); + if (*activep) + options->fwd_opts.streamlocal_bind_mask = (mode_t)value; + break; + + case sStreamLocalBindUnlink: + intptr = &options->fwd_opts.streamlocal_bind_unlink; + goto parse_flag; + + case sFingerprintHash: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", + filename, linenum); + if ((value = ssh_digest_alg_by_name(arg)) == -1) + fatal("%.200s line %d: Invalid hash algorithm \"%s\".", + filename, linenum, arg); + if (*activep) + options->fingerprint_hash = value; + break; + case sDeprecated: logit("%s line %d: Deprecated option %s", filename, linenum, arg); @@ -1765,13 +1990,15 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(permit_empty_passwd); M_CP_INTOPT(allow_tcp_forwarding); + M_CP_INTOPT(allow_streamlocal_forwarding); M_CP_INTOPT(allow_agent_forwarding); M_CP_INTOPT(permit_tun); - M_CP_INTOPT(gateway_ports); + M_CP_INTOPT(fwd_opts.gateway_ports); M_CP_INTOPT(x11_display_offset); M_CP_INTOPT(x11_forwarding); M_CP_INTOPT(x11_use_localhost); M_CP_INTOPT(permit_tty); + M_CP_INTOPT(permit_user_rc); M_CP_INTOPT(max_sessions); M_CP_INTOPT(max_authtries); M_CP_INTOPT(ip_qos_interactive); @@ -1832,6 +2059,7 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", filename, bad_options); + process_queued_listen_addrs(options); } static const char * @@ -1864,6 +2092,10 @@ fmt_intarg(ServerOpCodes code, int val) return fmt_multistate_int(val, multistate_privsep); case sAllowTcpForwarding: return fmt_multistate_int(val, multistate_tcpfwd); + case sAllowStreamLocalForwarding: + return fmt_multistate_int(val, multistate_tcpfwd); + case sFingerprintHash: + return ssh_digest_alg_name(val); case sProtocol: switch (val) { case SSH_PROTO_1: @@ -1905,6 +2137,12 @@ dump_cfg_int(ServerOpCodes code, int val) } static void +dump_cfg_oct(ServerOpCodes code, int val) +{ + printf("%s 0%o\n", lookup_opcode_name(code), val); +} + +static void dump_cfg_fmtint(ServerOpCodes code, int val) { printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); @@ -1915,7 +2153,8 @@ dump_cfg_string(ServerOpCodes code, const char *val) { if (val == NULL) return; - printf("%s %s\n", lookup_opcode_name(code), val); + printf("%s %s\n", lookup_opcode_name(code), + val == NULL ? "none" : val); } static void @@ -1932,6 +2171,8 @@ dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) { u_int i; + if (count <= 0) + return; printf("%s", lookup_opcode_name(code)); for (i = 0; i < count; i++) printf(" %s", vals[i]); @@ -1945,6 +2186,7 @@ dump_config(ServerOptions *o) int ret; struct addrinfo *ai; char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL; + char *laddr1 = xstrdup(""), *laddr2 = NULL; /* these are usually at the top of the config */ for (i = 0; i < o->num_ports; i++) @@ -1952,7 +2194,11 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sProtocol, o->protocol); dump_cfg_fmtint(sAddressFamily, o->address_family); - /* ListenAddress must be after Port */ + /* + * ListenAddress must be after Port. add_one_listen_addr pushes + * addresses onto a stack, so to maintain ordering we need to + * print these in reverse order. + */ for (ai = o->listen_addrs; ai; ai = ai->ai_next) { if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), port, sizeof(port), @@ -1961,16 +2207,22 @@ dump_config(ServerOptions *o) (ret != EAI_SYSTEM) ? gai_strerror(ret) : strerror(errno)); } else { + laddr2 = laddr1; if (ai->ai_family == AF_INET6) - printf("listenaddress [%s]:%s\n", addr, port); + xasprintf(&laddr1, "listenaddress [%s]:%s\n%s", + addr, port, laddr2); else - printf("listenaddress %s:%s\n", addr, port); + xasprintf(&laddr1, "listenaddress %s:%s\n%s", + addr, port, laddr2); + free(laddr2); } } + printf("%s", laddr1); + free(laddr1); /* integer arguments */ #ifdef USE_PAM - dump_cfg_int(sUsePAM, o->use_pam); + dump_cfg_fmtint(sUsePAM, o->use_pam); #endif dump_cfg_int(sServerKeyBits, o->server_key_bits); dump_cfg_int(sLoginGraceTime, o->login_grace_time); @@ -1980,6 +2232,7 @@ dump_config(ServerOptions *o) dump_cfg_int(sMaxSessions, o->max_sessions); dump_cfg_int(sClientAliveInterval, o->client_alive_interval); dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); + dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); /* formatted integer arguments */ dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); @@ -2013,23 +2266,26 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); dump_cfg_fmtint(sPermitTTY, o->permit_tty); + dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc); dump_cfg_fmtint(sStrictModes, o->strict_modes); dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); dump_cfg_fmtint(sUseLogin, o->use_login); dump_cfg_fmtint(sCompression, o->compression); - dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); + dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); dump_cfg_fmtint(sUseDNS, o->use_dns); dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); + dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding); + dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); + dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); /* string arguments */ dump_cfg_string(sPidFile, o->pid_file); dump_cfg_string(sXAuthLocation, o->xauth_location); - dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : - cipher_alg_list(',', 0)); - dump_cfg_string(sMacs, o->macs ? o->macs : mac_alg_list(',')); + dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT); + dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC); dump_cfg_string(sBanner, o->banner); dump_cfg_string(sForceCommand, o->adm_forced_command); dump_cfg_string(sChrootDirectory, o->chroot_directory); @@ -2037,12 +2293,21 @@ dump_config(ServerOptions *o) dump_cfg_string(sRevokedKeys, o->revoked_keys_file); dump_cfg_string(sAuthorizedPrincipalsFile, o->authorized_principals_file); - dump_cfg_string(sVersionAddendum, o->version_addendum); + dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0' + ? "none" : o->version_addendum); dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); + dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); + dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); dump_cfg_string(sHostKeyAgent, o->host_key_agent); - dump_cfg_string(sKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : - kex_alg_list(',')); + dump_cfg_string(sKexAlgorithms, + o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX); + dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ? + o->hostbased_key_types : KEX_DEFAULT_PK_ALG); + dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ? + o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG); + dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ? + o->pubkey_key_types : KEX_DEFAULT_PK_ALG); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); @@ -2053,7 +2318,7 @@ dump_config(ServerOptions *o) o->authorized_keys_files); dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, o->host_key_files); - dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files, + dump_cfg_strarray(sHostCertificate, o->num_host_cert_files, o->host_cert_files); dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); diff --git a/crypto/openssh/servconf.h b/crypto/openssh/servconf.h index 752d1c5..f4137af 100644 --- a/crypto/openssh/servconf.h +++ b/crypto/openssh/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.112 2014/01/29 06:18:35 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.120 2015/07/10 06:21:53 markus Exp $ */ /* * Author: Tatu Ylonen @@ -58,7 +58,9 @@ typedef struct { u_int num_ports; u_int ports_from_cmdline; int ports[MAX_PORTS]; /* Port number to listen on. */ - char *listen_addr; /* Address on which the server listens. */ + u_int num_queued_listens; + char **queued_listen_addrs; + int *queued_listen_ports; struct addrinfo *listen_addrs; /* Addresses on which the server listens. */ int address_family; /* Address family used by the server. */ char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */ @@ -83,6 +85,7 @@ typedef struct { int x11_use_localhost; /* If true, use localhost for fake X11 server. */ char *xauth_location; /* Location of xauth program */ int permit_tty; /* If false, deny pty allocation */ + int permit_user_rc; /* If false, deny ~/.ssh/rc execution */ int strict_modes; /* If true, require string home dir modes. */ int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */ int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ @@ -91,15 +94,18 @@ typedef struct { char *macs; /* Supported SSH2 macs. */ char *kex_algorithms; /* SSH2 kex methods in order of preference. */ int protocol; /* Supported protocol versions. */ - int gateway_ports; /* If true, allow remote connects to forwarded ports. */ + struct ForwardOptions fwd_opts; /* forwarding options */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for system logging. */ int rhosts_rsa_authentication; /* If true, permit rhosts RSA * authentication. */ int hostbased_authentication; /* If true, permit ssh2 hostbased auth */ int hostbased_uses_name_from_packet_only; /* experimental */ + char *hostbased_key_types; /* Key types allowed for hostbased */ + char *hostkeyalgorithms; /* SSH2 server key types */ int rsa_authentication; /* If true, permit RSA authentication. */ int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ + char *pubkey_key_types; /* Key types allowed for public key */ int kerberos_authentication; /* If true, permit Kerberos * authentication. */ int kerberos_or_local_passwd; /* If true, permit kerberos @@ -113,6 +119,7 @@ typedef struct { * authenticated with Kerberos. */ int gss_authentication; /* If true, permit GSSAPI authentication */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ + int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ @@ -123,6 +130,7 @@ typedef struct { int use_login; /* If true, login(1) is used */ int compression; /* If true, compression is allowed */ int allow_tcp_forwarding; /* One of FORWARD_* */ + int allow_streamlocal_forwarding; /* One of FORWARD_* */ int allow_agent_forwarding; u_int num_allow_users; char *allow_users[MAX_ALLOW_USERS]; @@ -172,9 +180,11 @@ typedef struct { char *chroot_directory; char *revoked_keys_file; char *trusted_user_ca_keys; - char *authorized_principals_file; char *authorized_keys_command; char *authorized_keys_command_user; + char *authorized_principals_file; + char *authorized_principals_command; + char *authorized_principals_command_user; int64_t rekey_limit; int rekey_interval; @@ -183,6 +193,8 @@ typedef struct { u_int num_auth_methods; char *auth_methods[MAX_AUTH_METHODS]; + + int fingerprint_hash; } ServerOptions; /* Information about the incoming connection as used by Match */ @@ -208,9 +220,13 @@ struct connection_info { M_CP_STROPT(banner); \ M_CP_STROPT(trusted_user_ca_keys); \ M_CP_STROPT(revoked_keys_file); \ - M_CP_STROPT(authorized_principals_file); \ M_CP_STROPT(authorized_keys_command); \ M_CP_STROPT(authorized_keys_command_user); \ + M_CP_STROPT(authorized_principals_file); \ + M_CP_STROPT(authorized_principals_command); \ + M_CP_STROPT(authorized_principals_command_user); \ + M_CP_STROPT(hostbased_key_types); \ + M_CP_STROPT(pubkey_key_types); \ M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ M_CP_STRARRAYOPT(allow_users, num_allow_users); \ M_CP_STRARRAYOPT(deny_users, num_deny_users); \ diff --git a/crypto/openssh/serverloop.c b/crypto/openssh/serverloop.c index 2f8e3a0..306ac36 100644 --- a/crypto/openssh/serverloop.c +++ b/crypto/openssh/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.170 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: serverloop.c,v 1.178 2015/02/20 22:17:21 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -37,8 +37,8 @@ #include "includes.h" +#include /* MIN MAX */ #include -#include #include #include #ifdef HAVE_SYS_TIME_H @@ -61,6 +61,7 @@ #include "packet.h" #include "buffer.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "canohost.h" #include "sshpty.h" @@ -77,13 +78,12 @@ #include "dispatch.h" #include "auth-options.h" #include "serverloop.h" -#include "misc.h" #include "roaming.h" +#include "ssherr.h" extern ServerOptions options; /* XXX */ -extern Kex *xxx_kex; extern Authctxt *the_authctxt; extern int use_privsep; @@ -545,7 +545,7 @@ drain_output(void) static void process_buffered_input_packets(void) { - dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL); + dispatch_run(DISPATCH_NONBLOCK, NULL, active_state); } /* @@ -851,7 +851,7 @@ server_loop2(Authctxt *authctxt) for (;;) { process_buffered_input_packets(); - rekeying = (xxx_kex != NULL && !xxx_kex->done); + rekeying = (active_state->kex != NULL && !active_state->kex->done); if (!rekeying && packet_not_very_much_data_to_write()) channel_output_poll(); @@ -874,8 +874,8 @@ server_loop2(Authctxt *authctxt) channel_after_select(readset, writeset); if (packet_need_rekeying()) { debug("need rekeying"); - xxx_kex->done = 0; - kex_send_kexinit(xxx_kex); + active_state->kex->done = 0; + kex_send_kexinit(active_state); } } process_input(readset); @@ -895,7 +895,7 @@ server_loop2(Authctxt *authctxt) session_destroy_all(NULL); } -static void +static int server_input_keep_alive(int type, u_int32_t seq, void *ctxt) { debug("Got %d/%u for keepalive", type, seq); @@ -905,9 +905,10 @@ server_input_keep_alive(int type, u_int32_t seq, void *ctxt) * the bogus CHANNEL_REQUEST we send for keepalives. */ packet_set_alive_timeouts(0); + return 0; } -static void +static int server_input_stdin_data(int type, u_int32_t seq, void *ctxt) { char *data; @@ -916,15 +917,16 @@ server_input_stdin_data(int type, u_int32_t seq, void *ctxt) /* Stdin data from the client. Append it to the buffer. */ /* Ignore any data if the client has closed stdin. */ if (fdin == -1) - return; + return 0; data = packet_get_string(&data_len); packet_check_eom(); buffer_append(&stdin_buffer, data, data_len); explicit_bzero(data, data_len); free(data); + return 0; } -static void +static int server_input_eof(int type, u_int32_t seq, void *ctxt) { /* @@ -935,9 +937,10 @@ server_input_eof(int type, u_int32_t seq, void *ctxt) debug("EOF received for stdin."); packet_check_eom(); stdin_eof = 1; + return 0; } -static void +static int server_input_window_size(int type, u_int32_t seq, void *ctxt) { u_int row = packet_get_int(); @@ -949,6 +952,7 @@ server_input_window_size(int type, u_int32_t seq, void *ctxt) packet_check_eom(); if (fdin != -1) pty_change_window_size(fdin, row, col, xpixel, ypixel); + return 0; } static Channel * @@ -970,7 +974,7 @@ server_request_direct_tcpip(void) /* XXX fine grained permissions */ if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && !no_port_forwarding_flag) { - c = channel_connect_to(target, target_port, + c = channel_connect_to_port(target, target_port, "direct-tcpip", "direct-tcpip"); } else { logit("refused local port forward: " @@ -985,6 +989,38 @@ server_request_direct_tcpip(void) } static Channel * +server_request_direct_streamlocal(void) +{ + Channel *c = NULL; + char *target, *originator; + u_short originator_port; + + target = packet_get_string(NULL); + originator = packet_get_string(NULL); + originator_port = packet_get_int(); + packet_check_eom(); + + debug("server_request_direct_streamlocal: originator %s port %d, target %s", + originator, originator_port, target); + + /* XXX fine grained permissions */ + if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && + !no_port_forwarding_flag) { + c = channel_connect_to_path(target, + "direct-streamlocal@openssh.com", "direct-streamlocal"); + } else { + logit("refused streamlocal port forward: " + "originator %s port %d, target %s", + originator, originator_port, target); + } + + free(originator); + free(target); + + return c; +} + +static Channel * server_request_tun(void) { Channel *c = NULL; @@ -1061,7 +1097,7 @@ server_request_session(void) return c; } -static void +static int server_input_channel_open(int type, u_int32_t seq, void *ctxt) { Channel *c = NULL; @@ -1081,6 +1117,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) c = server_request_session(); } else if (strcmp(ctype, "direct-tcpip") == 0) { c = server_request_direct_tcpip(); + } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { + c = server_request_direct_streamlocal(); } else if (strcmp(ctype, "tun@openssh.com") == 0) { c = server_request_tun(); } @@ -1109,14 +1147,86 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) packet_send(); } free(ctype); + return 0; } -static void +static int +server_input_hostkeys_prove(struct sshbuf **respp) +{ + struct ssh *ssh = active_state; /* XXX */ + struct sshbuf *resp = NULL; + struct sshbuf *sigbuf = NULL; + struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; + int r, ndx, success = 0; + const u_char *blob; + u_char *sig = 0; + size_t blen, slen; + + if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + + while (ssh_packet_remaining(ssh) > 0) { + sshkey_free(key); + key = NULL; + if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 || + (r = sshkey_from_blob(blob, blen, &key)) != 0) { + error("%s: couldn't parse key: %s", + __func__, ssh_err(r)); + goto out; + } + /* + * Better check that this is actually one of our hostkeys + * before attempting to sign anything with it. + */ + if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) { + error("%s: unknown host %s key", + __func__, sshkey_type(key)); + goto out; + } + /* + * XXX refactor: make kex->sign just use an index rather + * than passing in public and private keys + */ + if ((key_prv = get_hostkey_by_index(ndx)) == NULL && + (key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) { + error("%s: can't retrieve hostkey %d", __func__, ndx); + goto out; + } + sshbuf_reset(sigbuf); + free(sig); + sig = NULL; + if ((r = sshbuf_put_cstring(sigbuf, + "hostkeys-prove-00@openssh.com")) != 0 || + (r = sshbuf_put_string(sigbuf, + ssh->kex->session_id, ssh->kex->session_id_len)) != 0 || + (r = sshkey_puts(key, sigbuf)) != 0 || + (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen, + sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), 0)) != 0 || + (r = sshbuf_put_string(resp, sig, slen)) != 0) { + error("%s: couldn't prepare signature: %s", + __func__, ssh_err(r)); + goto out; + } + } + /* Success */ + *respp = resp; + resp = NULL; /* don't free it */ + success = 1; + out: + free(sig); + sshbuf_free(resp); + sshbuf_free(sigbuf); + sshkey_free(key); + return success; +} + +static int server_input_global_request(int type, u_int32_t seq, void *ctxt) { char *rtype; int want_reply; - int success = 0, allocated_listen_port = 0; + int r, success = 0, allocated_listen_port = 0; + struct sshbuf *resp = NULL; rtype = packet_get_string(NULL); want_reply = packet_get_char(); @@ -1125,63 +1235,99 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) /* -R style forwarding */ if (strcmp(rtype, "tcpip-forward") == 0) { struct passwd *pw; - char *listen_address; - u_short listen_port; + struct Forward fwd; pw = the_authctxt->pw; if (pw == NULL || !the_authctxt->valid) fatal("server_input_global_request: no/invalid user"); - listen_address = packet_get_string(NULL); - listen_port = (u_short)packet_get_int(); + memset(&fwd, 0, sizeof(fwd)); + fwd.listen_host = packet_get_string(NULL); + fwd.listen_port = (u_short)packet_get_int(); debug("server_input_global_request: tcpip-forward listen %s port %d", - listen_address, listen_port); + fwd.listen_host, fwd.listen_port); /* check permissions */ if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || no_port_forwarding_flag || - (!want_reply && listen_port == 0) + (!want_reply && fwd.listen_port == 0) #ifndef NO_IPPORT_RESERVED_CONCEPT - || (listen_port != 0 && listen_port < IPPORT_RESERVED && - pw->pw_uid != 0) + || (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED && + pw->pw_uid != 0) #endif ) { success = 0; packet_send_debug("Server has disabled port forwarding."); } else { /* Start listening on the port */ - success = channel_setup_remote_fwd_listener( - listen_address, listen_port, - &allocated_listen_port, options.gateway_ports); + success = channel_setup_remote_fwd_listener(&fwd, + &allocated_listen_port, &options.fwd_opts); } - free(listen_address); + free(fwd.listen_host); + if ((resp = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + if ((r = sshbuf_put_u32(resp, allocated_listen_port)) != 0) + fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r)); } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { - char *cancel_address; - u_short cancel_port; + struct Forward fwd; - cancel_address = packet_get_string(NULL); - cancel_port = (u_short)packet_get_int(); + memset(&fwd, 0, sizeof(fwd)); + fwd.listen_host = packet_get_string(NULL); + fwd.listen_port = (u_short)packet_get_int(); debug("%s: cancel-tcpip-forward addr %s port %d", __func__, - cancel_address, cancel_port); + fwd.listen_host, fwd.listen_port); + + success = channel_cancel_rport_listener(&fwd); + free(fwd.listen_host); + } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { + struct Forward fwd; + + memset(&fwd, 0, sizeof(fwd)); + fwd.listen_path = packet_get_string(NULL); + debug("server_input_global_request: streamlocal-forward listen path %s", + fwd.listen_path); - success = channel_cancel_rport_listener(cancel_address, - cancel_port); - free(cancel_address); + /* check permissions */ + if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0 + || no_port_forwarding_flag) { + success = 0; + packet_send_debug("Server has disabled port forwarding."); + } else { + /* Start listening on the socket */ + success = channel_setup_remote_fwd_listener( + &fwd, NULL, &options.fwd_opts); + } + free(fwd.listen_path); + } else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) { + struct Forward fwd; + + memset(&fwd, 0, sizeof(fwd)); + fwd.listen_path = packet_get_string(NULL); + debug("%s: cancel-streamlocal-forward path %s", __func__, + fwd.listen_path); + + success = channel_cancel_rport_listener(&fwd); + free(fwd.listen_path); } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { no_more_sessions = 1; success = 1; + } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) { + success = server_input_hostkeys_prove(&resp); } if (want_reply) { packet_start(success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); - if (success && allocated_listen_port > 0) - packet_put_int(allocated_listen_port); + if (success && resp != NULL) + ssh_packet_put_raw(active_state, sshbuf_ptr(resp), + sshbuf_len(resp)); packet_send(); packet_write_wait(); } free(rtype); + sshbuf_free(resp); + return 0; } -static void +static int server_input_channel_req(int type, u_int32_t seq, void *ctxt) { Channel *c; @@ -1204,13 +1350,14 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt) } else if ((c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) success = session_input_channel_req(c, rtype); - if (reply) { + if (reply && !(c->flags & CHAN_CLOSE_SENT)) { packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); packet_put_int(c->remote_id); packet_send(); } free(rtype); + return 0; } static void diff --git a/crypto/openssh/session.c b/crypto/openssh/session.c index 1de0c60..d99576b 100644 --- a/crypto/openssh/session.c +++ b/crypto/openssh/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.270 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: session.c,v 1.278 2015/04/24 01:36:00 deraadt Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -50,6 +50,7 @@ __RCSID("$FreeBSD$"); #include #include #include +#include #ifdef HAVE_PATHS_H #include #endif @@ -60,6 +61,7 @@ __RCSID("$FreeBSD$"); #include #include #include +#include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" @@ -84,11 +86,11 @@ __RCSID("$FreeBSD$"); #include "authfd.h" #include "pathnames.h" #include "log.h" +#include "misc.h" #include "servconf.h" #include "sshlogin.h" #include "serverloop.h" #include "canohost.h" -#include "misc.h" #include "session.h" #include "kex.h" #include "monitor_wrap.h" @@ -183,7 +185,6 @@ auth_input_request_forwarding(struct passwd * pw) { Channel *nc; int sock = -1; - struct sockaddr_un sunaddr; if (auth_sock_name != NULL) { error("authentication forwarding requested twice."); @@ -209,33 +210,15 @@ auth_input_request_forwarding(struct passwd * pw) xasprintf(&auth_sock_name, "%s/agent.%ld", auth_sock_dir, (long) getpid()); - /* Create the socket. */ - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - error("socket: %.100s", strerror(errno)); - restore_uid(); - goto authsock_err; - } - - /* Bind it to the name. */ - memset(&sunaddr, 0, sizeof(sunaddr)); - sunaddr.sun_family = AF_UNIX; - strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path)); - - if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { - error("bind: %.100s", strerror(errno)); - restore_uid(); - goto authsock_err; - } + /* Start a Unix listener on auth_sock_name. */ + sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0); /* Restore the privileged uid. */ restore_uid(); - /* Start listening on the socket. */ - if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { - error("listen: %.100s", strerror(errno)); + /* Check for socket/bind/listen failure. */ + if (sock < 0) goto authsock_err; - } /* Allocate a channel for the authentication agent socket. */ nc = channel_new("auth socket", @@ -274,6 +257,7 @@ do_authenticated(Authctxt *authctxt) setproctitle("%s", authctxt->pw->pw_name); /* setup the channel layer */ + /* XXX - streamlocal? */ if (no_port_forwarding_flag || (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) channel_disable_adm_local_opens(); @@ -393,7 +377,7 @@ do_authenticated1(Authctxt *authctxt) } debug("Received TCP/IP port forwarding request."); if (channel_input_port_forward_request(s->pw->pw_uid == 0, - options.gateway_ports) < 0) { + &options.fwd_opts) < 0) { debug("Port forwarding failed."); break; } @@ -1014,7 +998,7 @@ child_set_env(char ***envp, u_int *envsizep, const char *name, if (envsize >= 1000) fatal("child_set_env: too many env vars"); envsize += 50; - env = (*envp) = xrealloc(env, envsize, sizeof(char *)); + env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); *envsizep = envsize; } /* Need to set the NULL pointer at end of array beyond the new slot. */ @@ -1370,7 +1354,8 @@ do_rc_files(Session *s, const char *shell) /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ if (!s->is_subsystem && options.adm_forced_command == NULL && - !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) { + !no_user_rc && options.permit_user_rc && + stat(_PATH_SSH_USER_RC, &st) >= 0) { snprintf(cmd, sizeof cmd, "%s -c '%s %s'", shell, _PATH_BSHELL, _PATH_SSH_USER_RC); if (debug_flag) @@ -1465,7 +1450,7 @@ static void safely_chroot(const char *path, uid_t uid) { const char *cp; - char component[MAXPATHLEN]; + char component[PATH_MAX]; struct stat st; if (*path != '/') @@ -1517,6 +1502,9 @@ void do_setusercontext(struct passwd *pw) { char *chroot_path, *tmp; +#ifdef USE_LIBIAF + int doing_chroot = 0; +#endif platform_setusercontext(pw); @@ -1556,6 +1544,9 @@ do_setusercontext(struct passwd *pw) /* Make sure we don't attempt to chroot again */ free(options.chroot_directory); options.chroot_directory = NULL; +#ifdef USE_LIBIAF + doing_chroot = 1; +#endif } #ifdef HAVE_LOGIN_CAP @@ -1570,7 +1561,14 @@ do_setusercontext(struct passwd *pw) (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK); #else # ifdef USE_LIBIAF - if (set_id(pw->pw_name) != 0) { +/* In a chroot environment, the set_id() will always fail; typically + * because of the lack of necessary authentication services and runtime + * such as ./usr/lib/libiaf.so, ./usr/lib/libpam.so.1, and ./etc/passwd + * We skip it in the internal sftp chroot case. + * We'll lose auditing and ACLs but permanently_set_uid will + * take care of the rest. + */ + if ((doing_chroot == 0) && set_id(pw->pw_name) != 0) { fatal("set_id(%s) Failed", pw->pw_name); } # endif /* USE_LIBIAF */ @@ -1635,11 +1633,11 @@ launch_login(struct passwd *pw, const char *hostname) static void child_close_fds(void) { - extern AuthenticationConnection *auth_conn; + extern int auth_sock; - if (auth_conn) { - ssh_close_authentication_connection(auth_conn); - auth_conn = NULL; + if (auth_sock != -1) { + close(auth_sock); + auth_sock = -1; } if (packet_get_connection_in() == packet_get_connection_out()) @@ -1928,7 +1926,7 @@ session_new(void) return NULL; debug2("%s: allocate (allocated %d max %d)", __func__, sessions_nalloc, options.max_sessions); - tmp = xrealloc(sessions, sessions_nalloc + 1, + tmp = xreallocarray(sessions, sessions_nalloc + 1, sizeof(*sessions)); if (tmp == NULL) { error("%s: cannot allocate %d sessions", @@ -2255,7 +2253,7 @@ session_env_req(Session *s) for (i = 0; i < options.num_accept_env; i++) { if (match_pattern(name, options.accept_env[i])) { debug2("Setting env %d: %s=%s", s->num_env, name, val); - s->env = xrealloc(s->env, s->num_env + 1, + s->env = xreallocarray(s->env, s->num_env + 1, sizeof(*s->env)); s->env[s->num_env].name = name; s->env[s->num_env].val = val; @@ -2652,7 +2650,7 @@ session_setup_x11fwd(Session *s) { struct stat st; char display[512], auth_display[512]; - char hostname[MAXHOSTNAMELEN]; + char hostname[NI_MAXHOST]; u_int i; if (no_x11_forwarding_flag) { @@ -2663,7 +2661,7 @@ session_setup_x11fwd(Session *s) debug("X11 forwarding disabled in server configuration file."); return 0; } - if (!options.xauth_location || + if (options.xauth_location == NULL || (stat(options.xauth_location, &st) == -1)) { packet_send_debug("No xauth program; cannot forward with spoofing."); return 0; diff --git a/crypto/openssh/sftp-client.c b/crypto/openssh/sftp-client.c index 2f5907c..5dbeb47 100644 --- a/crypto/openssh/sftp-client.c +++ b/crypto/openssh/sftp-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.c,v 1.114 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.120 2015/05/28 04:50:53 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -22,8 +22,8 @@ #include "includes.h" +#include /* MIN MAX */ #include -#include #ifdef HAVE_SYS_STATVFS_H #include #endif @@ -47,7 +47,8 @@ #include #include "xmalloc.h" -#include "buffer.h" +#include "ssherr.h" +#include "sshbuf.h" #include "log.h" #include "atomicio.h" #include "progressmeter.h" @@ -83,8 +84,8 @@ struct sftp_conn { struct bwlimit bwlimit_in, bwlimit_out; }; -static char * -get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, +static u_char * +get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, const char *errfmt, ...) __attribute__((format(printf, 4, 5))); /* ARGSUSED */ @@ -98,36 +99,39 @@ sftpio(void *_bwlimit, size_t amount) } static void -send_msg(struct sftp_conn *conn, Buffer *m) +send_msg(struct sftp_conn *conn, struct sshbuf *m) { u_char mlen[4]; struct iovec iov[2]; - if (buffer_len(m) > SFTP_MAX_MSG_LENGTH) - fatal("Outbound message too long %u", buffer_len(m)); + if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) + fatal("Outbound message too long %zu", sshbuf_len(m)); /* Send length first */ - put_u32(mlen, buffer_len(m)); + put_u32(mlen, sshbuf_len(m)); iov[0].iov_base = mlen; iov[0].iov_len = sizeof(mlen); - iov[1].iov_base = buffer_ptr(m); - iov[1].iov_len = buffer_len(m); + iov[1].iov_base = (u_char *)sshbuf_ptr(m); + iov[1].iov_len = sshbuf_len(m); if (atomiciov6(writev, conn->fd_out, iov, 2, conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != - buffer_len(m) + sizeof(mlen)) + sshbuf_len(m) + sizeof(mlen)) fatal("Couldn't send packet: %s", strerror(errno)); - buffer_clear(m); + sshbuf_reset(m); } static void -get_msg(struct sftp_conn *conn, Buffer *m) +get_msg(struct sftp_conn *conn, struct sshbuf *m) { u_int msg_len; + u_char *p; + int r; - buffer_append_space(m, 4); - if (atomicio6(read, conn->fd_in, buffer_ptr(m), 4, + if ((r = sshbuf_reserve(m, 4, &p)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (atomicio6(read, conn->fd_in, p, 4, conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { if (errno == EPIPE) fatal("Connection closed"); @@ -135,12 +139,14 @@ get_msg(struct sftp_conn *conn, Buffer *m) fatal("Couldn't read packet: %s", strerror(errno)); } - msg_len = buffer_get_int(m); + if ((r = sshbuf_get_u32(m, &msg_len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (msg_len > SFTP_MAX_MSG_LENGTH) fatal("Received message too long %u", msg_len); - buffer_append_space(m, msg_len); - if (atomicio6(read, conn->fd_in, buffer_ptr(m), msg_len, + if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (atomicio6(read, conn->fd_in, p, msg_len, conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != msg_len) { if (errno == EPIPE) @@ -151,46 +157,56 @@ get_msg(struct sftp_conn *conn, Buffer *m) } static void -send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, +send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, u_int len) { - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, code); - buffer_put_int(&msg, id); - buffer_put_string(&msg, s, len); - send_msg(conn, &msg); + struct sshbuf *msg; + int r; + + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, code)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_string(msg, s, len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); - buffer_free(&msg); + sshbuf_free(msg); } static void send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, - char *s, u_int len, Attrib *a) + const void *s, u_int len, Attrib *a) { - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, code); - buffer_put_int(&msg, id); - buffer_put_string(&msg, s, len); - encode_attrib(&msg, a); - send_msg(conn, &msg); + struct sshbuf *msg; + int r; + + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, code)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_string(msg, s, len)) != 0 || + (r = encode_attrib(msg, a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); - buffer_free(&msg); + sshbuf_free(msg); } static u_int get_status(struct sftp_conn *conn, u_int expected_id) { - Buffer msg; - u_int type, id, status; + struct sshbuf *msg; + u_char type; + u_int id, status; + int r; - buffer_init(&msg); - get_msg(conn, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + get_msg(conn, msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); @@ -198,112 +214,136 @@ get_status(struct sftp_conn *conn, u_int expected_id) fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", SSH2_FXP_STATUS, type); - status = buffer_get_int(&msg); - buffer_free(&msg); + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + sshbuf_free(msg); debug3("SSH2_FXP_STATUS %u", status); return status; } -static char * -get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, +static u_char * +get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, const char *errfmt, ...) { - Buffer msg; - u_int type, id; - char *handle, errmsg[256]; + struct sshbuf *msg; + u_int id, status; + u_char type; + u_char *handle; + char errmsg[256]; va_list args; - int status; + int r; va_start(args, errfmt); if (errfmt != NULL) vsnprintf(errmsg, sizeof(errmsg), errfmt, args); va_end(args); - buffer_init(&msg); - get_msg(conn, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + get_msg(conn, msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (id != expected_id) fatal("%s: ID mismatch (%u != %u)", errfmt == NULL ? __func__ : errmsg, id, expected_id); if (type == SSH2_FXP_STATUS) { - status = buffer_get_int(&msg); + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (errfmt != NULL) error("%s: %s", errmsg, fx2txt(status)); - buffer_free(&msg); + sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_HANDLE) fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); - handle = buffer_get_string(&msg, len); - buffer_free(&msg); + if ((r = sshbuf_get_string(msg, &handle, len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + sshbuf_free(msg); - return(handle); + return handle; } static Attrib * get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) { - Buffer msg; - u_int type, id; - Attrib *a; + struct sshbuf *msg; + u_int id; + u_char type; + int r; + static Attrib a; - buffer_init(&msg); - get_msg(conn, &msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + get_msg(conn, msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("Received stat reply T:%u I:%u", type, id); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { - int status = buffer_get_int(&msg); + u_int status; + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (quiet) debug("Couldn't stat remote file: %s", fx2txt(status)); else error("Couldn't stat remote file: %s", fx2txt(status)); - buffer_free(&msg); + sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_ATTRS) { fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", SSH2_FXP_ATTRS, type); } - a = decode_attrib(&msg); - buffer_free(&msg); + if ((r = decode_attrib(msg, &a)) != 0) { + error("%s: couldn't decode attrib: %s", __func__, ssh_err(r)); + sshbuf_free(msg); + return NULL; + } + sshbuf_free(msg); - return(a); + return &a; } static int get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, u_int expected_id, int quiet) { - Buffer msg; - u_int type, id, flag; + struct sshbuf *msg; + u_char type; + u_int id; + u_int64_t flag; + int r; - buffer_init(&msg); - get_msg(conn, &msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + get_msg(conn, msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("Received statvfs reply T:%u I:%u", type, id); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { - int status = buffer_get_int(&msg); + u_int status; + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (quiet) debug("Couldn't statvfs: %s", fx2txt(status)); else error("Couldn't statvfs: %s", fx2txt(status)); - buffer_free(&msg); + sshbuf_free(msg); return -1; } else if (type != SSH2_FXP_EXTENDED_REPLY) { fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", @@ -311,22 +351,23 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, } memset(st, 0, sizeof(*st)); - st->f_bsize = buffer_get_int64(&msg); - st->f_frsize = buffer_get_int64(&msg); - st->f_blocks = buffer_get_int64(&msg); - st->f_bfree = buffer_get_int64(&msg); - st->f_bavail = buffer_get_int64(&msg); - st->f_files = buffer_get_int64(&msg); - st->f_ffree = buffer_get_int64(&msg); - st->f_favail = buffer_get_int64(&msg); - st->f_fsid = buffer_get_int64(&msg); - flag = buffer_get_int64(&msg); - st->f_namemax = buffer_get_int64(&msg); + if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || + (r = sshbuf_get_u64(msg, &flag)) != 0 || + (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; - buffer_free(&msg); + sshbuf_free(msg); return 0; } @@ -335,9 +376,10 @@ struct sftp_conn * do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, u_int64_t limit_kbps) { - u_int type; - Buffer msg; + u_char type; + struct sshbuf *msg; struct sftp_conn *ret; + int r; ret = xcalloc(1, sizeof(*ret)); ret->msg_id = 1; @@ -348,52 +390,62 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, ret->exts = 0; ret->limit_kbps = 0; - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_INIT); - buffer_put_int(&msg, SSH2_FILEXFER_VERSION); - send_msg(ret, &msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 || + (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(ret, msg); - buffer_clear(&msg); + sshbuf_reset(msg); - get_msg(ret, &msg); + get_msg(ret, msg); /* Expecting a VERSION reply */ - if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { + if ((r = sshbuf_get_u8(msg, &type)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (type != SSH2_FXP_VERSION) { error("Invalid packet back from SSH2_FXP_INIT (type %u)", type); - buffer_free(&msg); + sshbuf_free(msg); + free(ret); return(NULL); } - ret->version = buffer_get_int(&msg); + if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug2("Remote version: %u", ret->version); /* Check for extensions */ - while (buffer_len(&msg) > 0) { - char *name = buffer_get_string(&msg, NULL); - char *value = buffer_get_string(&msg, NULL); + while (sshbuf_len(msg) > 0) { + char *name; + u_char *value; + size_t vlen; int known = 0; + if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || + (r = sshbuf_get_string(msg, &value, &vlen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (strcmp(name, "posix-rename@openssh.com") == 0 && - strcmp(value, "1") == 0) { + strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_POSIX_RENAME; known = 1; } else if (strcmp(name, "statvfs@openssh.com") == 0 && - strcmp(value, "2") == 0) { + strcmp((char *)value, "2") == 0) { ret->exts |= SFTP_EXT_STATVFS; known = 1; } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && - strcmp(value, "2") == 0) { + strcmp((char *)value, "2") == 0) { ret->exts |= SFTP_EXT_FSTATVFS; known = 1; } else if (strcmp(name, "hardlink@openssh.com") == 0 && - strcmp(value, "1") == 0) { + strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_HARDLINK; known = 1; - } else if (strcmp(name, "fsync@openssh.com") == 0 && - strcmp(value, "1") == 0) { - ret->exts |= SFTP_EXT_FSYNC; - known = 1; + } else if (strcmp(name, "fsync@openssh.com") == 0 && + strcmp((char *)value, "1") == 0) { + ret->exts |= SFTP_EXT_FSYNC; + known = 1; } if (known) { debug2("Server supports extension \"%s\" revision %s", @@ -405,7 +457,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, free(value); } - buffer_free(&msg); + sshbuf_free(msg); /* Some filexfer v.0 servers don't support large packets */ if (ret->version == 0) @@ -429,54 +481,62 @@ sftp_proto_version(struct sftp_conn *conn) } int -do_close(struct sftp_conn *conn, char *handle, u_int handle_len) +do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) { u_int id, status; - Buffer msg; + struct sshbuf *msg; + int r; - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_CLOSE); - buffer_put_int(&msg, id); - buffer_put_string(&msg, handle, handle_len); - send_msg(conn, &msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_string(msg, handle, handle_len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message SSH2_FXP_CLOSE I:%u", id); status = get_status(conn, id); if (status != SSH2_FX_OK) error("Couldn't close file: %s", fx2txt(status)); - buffer_free(&msg); + sshbuf_free(msg); - return status; + return status == SSH2_FX_OK ? 0 : -1; } static int -do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, +do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, SFTP_DIRENT ***dir) { - Buffer msg; - u_int count, type, id, handle_len, i, expected_id, ents = 0; + struct sshbuf *msg; + u_int count, id, i, expected_id, ents = 0; + size_t handle_len; + u_char type; char *handle; int status = SSH2_FX_FAILURE; + int r; if (dir) *dir = NULL; id = conn->msg_id++; - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_OPENDIR); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, path); - send_msg(conn, &msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, path)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); handle = get_handle(conn, id, &handle_len, "remote readdir(\"%s\")", path); if (handle == NULL) { - buffer_free(&msg); + sshbuf_free(msg); return -1; } @@ -491,18 +551,20 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, debug3("Sending SSH2_FXP_READDIR I:%u", id); - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_READDIR); - buffer_put_int(&msg, id); - buffer_put_string(&msg, handle, handle_len); - send_msg(conn, &msg); + sshbuf_reset(msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_string(msg, handle, handle_len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); - buffer_clear(&msg); + sshbuf_reset(msg); - get_msg(conn, &msg); + get_msg(conn, msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("Received reply T:%u I:%u", type, id); @@ -510,27 +572,43 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { - status = buffer_get_int(&msg); - debug3("Received SSH2_FXP_STATUS %d", status); - if (status == SSH2_FX_EOF) + u_int rstatus; + + if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); + debug3("Received SSH2_FXP_STATUS %d", rstatus); + if (rstatus == SSH2_FX_EOF) break; - error("Couldn't read directory: %s", fx2txt(status)); + error("Couldn't read directory: %s", fx2txt(rstatus)); goto out; } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); - count = buffer_get_int(&msg); + if ((r = sshbuf_get_u32(msg, &count)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (count == 0) break; debug3("Received %d SSH2_FXP_NAME responses", count); for (i = 0; i < count; i++) { char *filename, *longname; - Attrib *a; - - filename = buffer_get_string(&msg, NULL); - longname = buffer_get_string(&msg, NULL); - a = decode_attrib(&msg); + Attrib a; + + if ((r = sshbuf_get_cstring(msg, &filename, + NULL)) != 0 || + (r = sshbuf_get_cstring(msg, &longname, + NULL)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); + if ((r = decode_attrib(msg, &a)) != 0) { + error("%s: couldn't decode attrib: %s", + __func__, ssh_err(r)); + free(filename); + free(longname); + sshbuf_free(msg); + return -1; + } if (print_flag) printf("%s\n", longname); @@ -544,11 +622,11 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, error("Server sent suspect path \"%s\" " "during readdir of \"%s\"", filename, path); } else if (dir) { - *dir = xrealloc(*dir, ents + 2, sizeof(**dir)); + *dir = xreallocarray(*dir, ents + 2, sizeof(**dir)); (*dir)[ents] = xcalloc(1, sizeof(***dir)); (*dir)[ents]->filename = xstrdup(filename); (*dir)[ents]->longname = xstrdup(longname); - memcpy(&(*dir)[ents]->a, a, sizeof(*a)); + memcpy(&(*dir)[ents]->a, &a, sizeof(a)); (*dir)[++ents] = NULL; } free(filename); @@ -558,7 +636,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, status = 0; out: - buffer_free(&msg); + sshbuf_free(msg); do_close(conn, handle, handle_len); free(handle); @@ -577,7 +655,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, } int -do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) +do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) { return(do_lsreaddir(conn, path, 0, dir)); } @@ -597,7 +675,7 @@ void free_sftp_dirents(SFTP_DIRENT **s) } int -do_rm(struct sftp_conn *conn, char *path) +do_rm(struct sftp_conn *conn, const char *path) { u_int status, id; @@ -608,11 +686,11 @@ do_rm(struct sftp_conn *conn, char *path) status = get_status(conn, id); if (status != SSH2_FX_OK) error("Couldn't delete file: %s", fx2txt(status)); - return(status); + return status == SSH2_FX_OK ? 0 : -1; } int -do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag) +do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) { u_int status, id; @@ -624,11 +702,11 @@ do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag) if (status != SSH2_FX_OK && print_flag) error("Couldn't create directory: %s", fx2txt(status)); - return(status); + return status == SSH2_FX_OK ? 0 : -1; } int -do_rmdir(struct sftp_conn *conn, char *path) +do_rmdir(struct sftp_conn *conn, const char *path) { u_int status, id; @@ -640,11 +718,11 @@ do_rmdir(struct sftp_conn *conn, char *path) if (status != SSH2_FX_OK) error("Couldn't remove directory: %s", fx2txt(status)); - return(status); + return status == SSH2_FX_OK ? 0 : -1; } Attrib * -do_stat(struct sftp_conn *conn, char *path, int quiet) +do_stat(struct sftp_conn *conn, const char *path, int quiet) { u_int id; @@ -658,7 +736,7 @@ do_stat(struct sftp_conn *conn, char *path, int quiet) } Attrib * -do_lstat(struct sftp_conn *conn, char *path, int quiet) +do_lstat(struct sftp_conn *conn, const char *path, int quiet) { u_int id; @@ -679,7 +757,8 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet) #ifdef notyet Attrib * -do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) +do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, + int quiet) { u_int id; @@ -692,7 +771,7 @@ do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) #endif int -do_setstat(struct sftp_conn *conn, char *path, Attrib *a) +do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) { u_int status, id; @@ -705,11 +784,11 @@ do_setstat(struct sftp_conn *conn, char *path, Attrib *a) error("Couldn't setstat on \"%s\": %s", path, fx2txt(status)); - return(status); + return status == SSH2_FX_OK ? 0 : -1; } int -do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, +do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, Attrib *a) { u_int status, id; @@ -722,181 +801,201 @@ do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, if (status != SSH2_FX_OK) error("Couldn't fsetstat: %s", fx2txt(status)); - return(status); + return status == SSH2_FX_OK ? 0 : -1; } char * -do_realpath(struct sftp_conn *conn, char *path) +do_realpath(struct sftp_conn *conn, const char *path) { - Buffer msg; - u_int type, expected_id, count, id; + struct sshbuf *msg; + u_int expected_id, count, id; char *filename, *longname; - Attrib *a; + Attrib a; + u_char type; + int r; expected_id = id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_REALPATH, path, strlen(path)); - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); - get_msg(conn, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); + get_msg(conn, msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { - u_int status = buffer_get_int(&msg); + u_int status; + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); error("Couldn't canonicalize: %s", fx2txt(status)); - buffer_free(&msg); + sshbuf_free(msg); return NULL; } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); - count = buffer_get_int(&msg); + if ((r = sshbuf_get_u32(msg, &count)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (count != 1) fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); - filename = buffer_get_string(&msg, NULL); - longname = buffer_get_string(&msg, NULL); - a = decode_attrib(&msg); + if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || + (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || + (r = decode_attrib(msg, &a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, - (unsigned long)a->size); + (unsigned long)a.size); free(longname); - buffer_free(&msg); + sshbuf_free(msg); return(filename); } int -do_rename(struct sftp_conn *conn, char *oldpath, char *newpath, +do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy) { - Buffer msg; + struct sshbuf *msg; u_int status, id; - int use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; + int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* Send rename request */ id = conn->msg_id++; if (use_ext) { - buffer_put_char(&msg, SSH2_FXP_EXTENDED); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, "posix-rename@openssh.com"); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, + "posix-rename@openssh.com")) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } else { - buffer_put_char(&msg, SSH2_FXP_RENAME); - buffer_put_int(&msg, id); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } - buffer_put_cstring(&msg, oldpath); - buffer_put_cstring(&msg, newpath); - send_msg(conn, &msg); + if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || + (r = sshbuf_put_cstring(msg, newpath)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message %s \"%s\" -> \"%s\"", - use_ext ? "posix-rename@openssh.com" : "SSH2_FXP_RENAME", - oldpath, newpath); - buffer_free(&msg); + use_ext ? "posix-rename@openssh.com" : + "SSH2_FXP_RENAME", oldpath, newpath); + sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); - return(status); + return status == SSH2_FX_OK ? 0 : -1; } int -do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) +do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) { - Buffer msg; + struct sshbuf *msg; u_int status, id; + int r; if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { error("Server does not support hardlink@openssh.com extension"); return -1; } - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* Send link request */ id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_EXTENDED); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, "hardlink@openssh.com"); - buffer_put_cstring(&msg, oldpath); - buffer_put_cstring(&msg, newpath); - send_msg(conn, &msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, oldpath)) != 0 || + (r = sshbuf_put_cstring(msg, newpath)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", oldpath, newpath); - buffer_free(&msg); + sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); - return(status); + return status == SSH2_FX_OK ? 0 : -1; } int -do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) +do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) { - Buffer msg; + struct sshbuf *msg; u_int status, id; + int r; if (conn->version < 3) { error("This server does not support the symlink operation"); return(SSH2_FX_OP_UNSUPPORTED); } - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* Send symlink request */ id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_SYMLINK); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, oldpath); - buffer_put_cstring(&msg, newpath); - send_msg(conn, &msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, oldpath)) != 0 || + (r = sshbuf_put_cstring(msg, newpath)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, newpath); - buffer_free(&msg); + sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); - return(status); + return status == SSH2_FX_OK ? 0 : -1; } int -do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) +do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) { - Buffer msg; + struct sshbuf *msg; u_int status, id; + int r; /* Silently return if the extension is not supported */ if ((conn->exts & SFTP_EXT_FSYNC) == 0) return -1; - buffer_init(&msg); - /* Send fsync request */ + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); id = conn->msg_id++; - - buffer_put_char(&msg, SSH2_FXP_EXTENDED); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, "fsync@openssh.com"); - buffer_put_string(&msg, handle, handle_len); - send_msg(conn, &msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || + (r = sshbuf_put_string(msg, handle, handle_len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message fsync@openssh.com I:%u", id); - buffer_free(&msg); + sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) @@ -907,50 +1006,58 @@ do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) #ifdef notyet char * -do_readlink(struct sftp_conn *conn, char *path) +do_readlink(struct sftp_conn *conn, const char *path) { - Buffer msg; - u_int type, expected_id, count, id; + struct sshbuf *msg; + u_int expected_id, count, id; char *filename, *longname; - Attrib *a; + Attrib a; + u_char type; + int r; expected_id = id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); - get_msg(conn, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); + get_msg(conn, msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { - u_int status = buffer_get_int(&msg); + u_int status; + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); error("Couldn't readlink: %s", fx2txt(status)); - buffer_free(&msg); + sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); - count = buffer_get_int(&msg); + if ((r = sshbuf_get_u32(msg, &count)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (count != 1) fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); - filename = buffer_get_string(&msg, NULL); - longname = buffer_get_string(&msg, NULL); - a = decode_attrib(&msg); + if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || + (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || + (r = decode_attrib(msg, &a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("SSH_FXP_READLINK %s -> %s", path, filename); free(longname); - buffer_free(&msg); + sshbuf_free(msg); - return(filename); + return filename; } #endif @@ -958,8 +1065,9 @@ int do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, int quiet) { - Buffer msg; + struct sshbuf *msg; u_int id; + int r; if ((conn->exts & SFTP_EXT_STATVFS) == 0) { error("Server does not support statvfs@openssh.com extension"); @@ -968,24 +1076,26 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, id = conn->msg_id++; - buffer_init(&msg); - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_EXTENDED); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, "statvfs@openssh.com"); - buffer_put_cstring(&msg, path); - send_msg(conn, &msg); - buffer_free(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + sshbuf_reset(msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, path)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); + sshbuf_free(msg); return get_decode_statvfs(conn, st, id, quiet); } #ifdef notyet int -do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, +do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, struct sftp_statvfs *st, int quiet) { - Buffer msg; + struct sshbuf *msg; u_int id; if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { @@ -995,14 +1105,16 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, id = conn->msg_id++; - buffer_init(&msg); - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_EXTENDED); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, "fstatvfs@openssh.com"); - buffer_put_string(&msg, handle, handle_len); - send_msg(conn, &msg); - buffer_free(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + sshbuf_reset(msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || + (r = sshbuf_put_string(msg, handle, handle_len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); + sshbuf_free(msg); return get_decode_statvfs(conn, st, id, quiet); } @@ -1010,42 +1122,48 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, static void send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, - u_int len, char *handle, u_int handle_len) + u_int len, const u_char *handle, u_int handle_len) { - Buffer msg; - - buffer_init(&msg); - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_READ); - buffer_put_int(&msg, id); - buffer_put_string(&msg, handle, handle_len); - buffer_put_int64(&msg, offset); - buffer_put_int(&msg, len); - send_msg(conn, &msg); - buffer_free(&msg); + struct sshbuf *msg; + int r; + + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + sshbuf_reset(msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || + (r = sshbuf_put_u64(msg, offset)) != 0 || + (r = sshbuf_put_u32(msg, len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); + sshbuf_free(msg); } int -do_download(struct sftp_conn *conn, char *remote_path, char *local_path, - Attrib *a, int preserve_flag, int resume_flag, int fsync_flag) +do_download(struct sftp_conn *conn, const char *remote_path, + const char *local_path, Attrib *a, int preserve_flag, int resume_flag, + int fsync_flag) { Attrib junk; - Buffer msg; - char *handle; - int local_fd = -1, status = 0, write_error; - int read_error, write_errno, reordered = 0; + struct sshbuf *msg; + u_char *handle; + int local_fd = -1, write_error; + int read_error, write_errno, reordered = 0, r; u_int64_t offset = 0, size, highwater; - u_int handle_len, mode, type, id, buflen, num_req, max_req; + u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; off_t progress_counter; + size_t handle_len; struct stat st; struct request { u_int id; - u_int len; + size_t len; u_int64_t offset; TAILQ_ENTRY(request) tq; }; TAILQ_HEAD(reqhead, request) requests; struct request *req; + u_char type; TAILQ_INIT(&requests); @@ -1070,23 +1188,26 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, size = 0; buflen = conn->transfer_buflen; - buffer_init(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + + attrib_clear(&junk); /* Send empty attributes */ /* Send open request */ id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_OPEN); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, remote_path); - buffer_put_int(&msg, SSH2_FXF_READ); - attrib_clear(&junk); /* Send empty attributes */ - encode_attrib(&msg, &junk); - send_msg(conn, &msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, remote_path)) != 0 || + (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || + (r = encode_attrib(msg, &junk)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); handle = get_handle(conn, id, &handle_len, "remote open(\"%s\")", remote_path); if (handle == NULL) { - buffer_free(&msg); + sshbuf_free(msg); return(-1); } @@ -1113,7 +1234,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, "local file is larger than remote", local_path); fail: do_close(conn, handle, handle_len); - buffer_free(&msg); + sshbuf_free(msg); free(handle); if (local_fd != -1) close(local_fd); @@ -1131,8 +1252,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, start_progress_meter(remote_path, size, &progress_counter); while (num_req > 0 || max_req > 0) { - char *data; - u_int len; + u_char *data; + size_t len; /* * Simulate EOF on interrupt: stop sending new requests and @@ -1161,10 +1282,11 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, req->len, handle, handle_len); } - buffer_clear(&msg); - get_msg(conn, &msg); - type = buffer_get_char(&msg); - id = buffer_get_int(&msg); + sshbuf_reset(msg); + get_msg(conn, msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("Received reply T:%u I:%u R:%d", type, id, max_req); /* Find the request in our queue */ @@ -1177,7 +1299,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, switch (type) { case SSH2_FXP_STATUS: - status = buffer_get_int(&msg); + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); if (status != SSH2_FX_EOF) read_error = 1; max_req = 0; @@ -1186,13 +1310,15 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, num_req--; break; case SSH2_FXP_DATA: - data = buffer_get_string(&msg, &len); + if ((r = sshbuf_get_string(msg, &data, &len)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); debug3("Received data %llu -> %llu", (unsigned long long)req->offset, (unsigned long long)req->offset + len - 1); if (len > req->len) fatal("Received more data than asked for " - "%u > %u", len, req->len); + "%zu > %zu", len, req->len); if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || atomicio(vwrite, local_fd, data, len) != len) && !write_error) { @@ -1259,7 +1385,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, "server reordered requests", local_path); } debug("truncating at %llu", (unsigned long long)highwater); - ftruncate(local_fd, highwater); + if (ftruncate(local_fd, highwater) == -1) + error("ftruncate \"%s\": %s", local_path, + strerror(errno)); } if (read_error) { error("Couldn't read from remote file \"%s\" : %s", @@ -1269,12 +1397,13 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, } else if (write_error) { error("Couldn't write to \"%s\": %s", local_path, strerror(write_errno)); - status = -1; + status = SSH2_FX_FAILURE; do_close(conn, handle, handle_len); } else { - status = do_close(conn, handle, handle_len); - if (interrupted || status != SSH2_FX_OK) - status = -1; + if (do_close(conn, handle, handle_len) != 0 || interrupted) + status = SSH2_FX_FAILURE; + else + status = SSH2_FX_OK; /* Override umask and utimes if asked */ #ifdef HAVE_FCHMOD if (preserve_flag && fchmod(local_fd, mode) == -1) @@ -1301,16 +1430,16 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, } } close(local_fd); - buffer_free(&msg); + sshbuf_free(msg); free(handle); return(status); } static int -download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, - Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, - int fsync_flag) +download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + int depth, Attrib *dirattrib, int preserve_flag, int print_flag, + int resume_flag, int fsync_flag) { int i, ret = 0; SFTP_DIRENT **dir_entries; @@ -1400,9 +1529,9 @@ download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, } int -download_dir(struct sftp_conn *conn, char *src, char *dst, - Attrib *dirattrib, int preserve_flag, int print_flag, - int resume_flag, int fsync_flag) +download_dir(struct sftp_conn *conn, const char *src, const char *dst, + Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, + int fsync_flag) { char *src_canon; int ret; @@ -1419,17 +1548,18 @@ download_dir(struct sftp_conn *conn, char *src, char *dst, } int -do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, - int preserve_flag, int fsync_flag) +do_upload(struct sftp_conn *conn, const char *local_path, + const char *remote_path, int preserve_flag, int resume, int fsync_flag) { - int local_fd; - int status = SSH2_FX_OK; - u_int handle_len, id, type; + int r, local_fd; + u_int status = SSH2_FX_OK; + u_int id; + u_char type; off_t offset, progress_counter; - char *handle, *data; - Buffer msg; + u_char *handle, *data; + struct sshbuf *msg; struct stat sb; - Attrib a; + Attrib a, *c = NULL; u_int32_t startid; u_int32_t ackid; struct outstanding_ack { @@ -1440,6 +1570,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, }; TAILQ_HEAD(ackhead, outstanding_ack) acks; struct outstanding_ack *ack = NULL; + size_t handle_len; TAILQ_INIT(&acks); @@ -1467,25 +1598,48 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, if (!preserve_flag) a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; - buffer_init(&msg); + if (resume) { + /* Get remote file size if it exists */ + if ((c = do_stat(conn, remote_path, 0)) == NULL) { + close(local_fd); + return -1; + } + + if ((off_t)c->size >= sb.st_size) { + error("destination file bigger or same size as " + "source file"); + close(local_fd); + return -1; + } + + if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { + close(local_fd); + return -1; + } + } + + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* Send open request */ id = conn->msg_id++; - buffer_put_char(&msg, SSH2_FXP_OPEN); - buffer_put_int(&msg, id); - buffer_put_cstring(&msg, remote_path); - buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); - encode_attrib(&msg, &a); - send_msg(conn, &msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, remote_path)) != 0 || + (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| + (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 || + (r = encode_attrib(msg, &a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); - buffer_clear(&msg); + sshbuf_reset(msg); handle = get_handle(conn, id, &handle_len, "remote open(\"%s\")", remote_path); if (handle == NULL) { close(local_fd); - buffer_free(&msg); + sshbuf_free(msg); return -1; } @@ -1493,7 +1647,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, data = xmalloc(conn->transfer_buflen); /* Read from local and write to remote */ - offset = progress_counter = 0; + offset = progress_counter = (resume ? c->size : 0); if (showprogress) start_progress_meter(local_path, sb.st_size, &progress_counter); @@ -1525,13 +1679,16 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, ack->len = len; TAILQ_INSERT_TAIL(&acks, ack, tq); - buffer_clear(&msg); - buffer_put_char(&msg, SSH2_FXP_WRITE); - buffer_put_int(&msg, ack->id); - buffer_put_string(&msg, handle, handle_len); - buffer_put_int64(&msg, offset); - buffer_put_string(&msg, data, len); - send_msg(conn, &msg); + sshbuf_reset(msg); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || + (r = sshbuf_put_u32(msg, ack->id)) != 0 || + (r = sshbuf_put_string(msg, handle, + handle_len)) != 0 || + (r = sshbuf_put_u64(msg, offset)) != 0 || + (r = sshbuf_put_string(msg, data, len)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); + send_msg(conn, msg); debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", id, (unsigned long long)offset, len); } else if (TAILQ_FIRST(&acks) == NULL) @@ -1542,27 +1699,31 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, if (id == startid || len == 0 || id - ackid >= conn->num_requests) { - u_int r_id; + u_int rid; - buffer_clear(&msg); - get_msg(conn, &msg); - type = buffer_get_char(&msg); - r_id = buffer_get_int(&msg); + sshbuf_reset(msg); + get_msg(conn, msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &rid)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); if (type != SSH2_FXP_STATUS) fatal("Expected SSH2_FXP_STATUS(%d) packet, " "got %d", SSH2_FXP_STATUS, type); - status = buffer_get_int(&msg); - debug3("SSH2_FXP_STATUS %d", status); + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); + debug3("SSH2_FXP_STATUS %u", status); /* Find the request in our queue */ for (ack = TAILQ_FIRST(&acks); - ack != NULL && ack->id != r_id; + ack != NULL && ack->id != rid; ack = TAILQ_NEXT(ack, tq)) ; if (ack == NULL) - fatal("Can't find request for ID %u", r_id); + fatal("Can't find request for ID %u", rid); TAILQ_REMOVE(&acks, ack, tq); debug3("In write loop, ack for %u %u bytes at %lld", ack->id, ack->len, (long long)ack->offset); @@ -1574,7 +1735,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, if (offset < 0) fatal("%s: offset < 0", __func__); } - buffer_free(&msg); + sshbuf_free(msg); if (showprogress) stop_progress_meter(); @@ -1583,13 +1744,13 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, if (status != SSH2_FX_OK) { error("Couldn't write to remote file \"%s\": %s", remote_path, fx2txt(status)); - status = -1; + status = SSH2_FX_FAILURE; } if (close(local_fd) == -1) { error("Couldn't close local file \"%s\": %s", local_path, strerror(errno)); - status = -1; + status = SSH2_FX_FAILURE; } /* Override umask and utimes if asked */ @@ -1600,17 +1761,19 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, (void)do_fsync(conn, handle, handle_len); if (do_close(conn, handle, handle_len) != SSH2_FX_OK) - status = -1; + status = SSH2_FX_FAILURE; + free(handle); - return status; + return status == SSH2_FX_OK ? 0 : -1; } static int -upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, - int preserve_flag, int print_flag, int fsync_flag) +upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + int depth, int preserve_flag, int print_flag, int resume, int fsync_flag) { - int ret = 0, status; + int ret = 0; + u_int status; DIR *dirp; struct dirent *dp; char *filename, *new_src, *new_dst; @@ -1677,12 +1840,12 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, continue; if (upload_dir_internal(conn, new_src, new_dst, - depth + 1, preserve_flag, print_flag, + depth + 1, preserve_flag, print_flag, resume, fsync_flag) == -1) ret = -1; } else if (S_ISREG(sb.st_mode)) { if (do_upload(conn, new_src, new_dst, - preserve_flag, fsync_flag) == -1) { + preserve_flag, resume, fsync_flag) == -1) { error("Uploading of file %s to %s failed!", new_src, new_dst); ret = -1; @@ -1700,8 +1863,8 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, } int -upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, - int print_flag, int fsync_flag) +upload_dir(struct sftp_conn *conn, const char *src, const char *dst, + int preserve_flag, int print_flag, int resume, int fsync_flag) { char *dst_canon; int ret; @@ -1712,14 +1875,14 @@ upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, } ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, - print_flag, fsync_flag); + print_flag, resume, fsync_flag); free(dst_canon); return ret; } char * -path_append(char *p1, char *p2) +path_append(const char *p1, const char *p2) { char *ret; size_t len = strlen(p1) + strlen(p2) + 2; diff --git a/crypto/openssh/sftp-client.h b/crypto/openssh/sftp-client.h index ba92ad0..f814b07 100644 --- a/crypto/openssh/sftp-client.h +++ b/crypto/openssh/sftp-client.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.h,v 1.24 2013/10/17 00:30:13 djm Exp $ */ +/* $OpenBSD: sftp-client.h,v 1.27 2015/05/08 06:45:13 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller @@ -56,79 +56,81 @@ struct sftp_conn *do_init(int, int, u_int, u_int, u_int64_t); u_int sftp_proto_version(struct sftp_conn *); /* Close file referred to by 'handle' */ -int do_close(struct sftp_conn *, char *, u_int); +int do_close(struct sftp_conn *, const u_char *, u_int); /* Read contents of 'path' to NULL-terminated array 'dir' */ -int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); +int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ void free_sftp_dirents(SFTP_DIRENT **); /* Delete file 'path' */ -int do_rm(struct sftp_conn *, char *); +int do_rm(struct sftp_conn *, const char *); /* Create directory 'path' */ -int do_mkdir(struct sftp_conn *, char *, Attrib *, int); +int do_mkdir(struct sftp_conn *, const char *, Attrib *, int); /* Remove directory 'path' */ -int do_rmdir(struct sftp_conn *, char *); +int do_rmdir(struct sftp_conn *, const char *); /* Get file attributes of 'path' (follows symlinks) */ -Attrib *do_stat(struct sftp_conn *, char *, int); +Attrib *do_stat(struct sftp_conn *, const char *, int); /* Get file attributes of 'path' (does not follow symlinks) */ -Attrib *do_lstat(struct sftp_conn *, char *, int); +Attrib *do_lstat(struct sftp_conn *, const char *, int); /* Set file attributes of 'path' */ -int do_setstat(struct sftp_conn *, char *, Attrib *); +int do_setstat(struct sftp_conn *, const char *, Attrib *); /* Set file attributes of open file 'handle' */ -int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); +int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); /* Canonicalise 'path' - caller must free result */ -char *do_realpath(struct sftp_conn *, char *); +char *do_realpath(struct sftp_conn *, const char *); /* Get statistics for filesystem hosting file at "path" */ int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); /* Rename 'oldpath' to 'newpath' */ -int do_rename(struct sftp_conn *, char *, char *m, int force_legacy); +int do_rename(struct sftp_conn *, const char *, const char *, int force_legacy); /* Link 'oldpath' to 'newpath' */ -int do_hardlink(struct sftp_conn *, char *, char *); +int do_hardlink(struct sftp_conn *, const char *, const char *); /* Rename 'oldpath' to 'newpath' */ -int do_symlink(struct sftp_conn *, char *, char *); +int do_symlink(struct sftp_conn *, const char *, const char *); /* Call fsync() on open file 'handle' */ -int do_fsync(struct sftp_conn *conn, char *, u_int); +int do_fsync(struct sftp_conn *conn, u_char *, u_int); /* * Download 'remote_path' to 'local_path'. Preserve permissions and times * if 'pflag' is set */ -int do_download(struct sftp_conn *, char *, char *, Attrib *, int, int, int); +int do_download(struct sftp_conn *, const char *, const char *, + Attrib *, int, int, int); /* - * Recursively download 'remote_directory' to 'local_directory'. Preserve + * Recursively download 'remote_directory' to 'local_directory'. Preserve * times if 'pflag' is set */ -int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, - int, int, int); +int download_dir(struct sftp_conn *, const char *, const char *, + Attrib *, int, int, int, int); /* * Upload 'local_path' to 'remote_path'. Preserve permissions and times * if 'pflag' is set */ -int do_upload(struct sftp_conn *, char *, char *, int, int); +int do_upload(struct sftp_conn *, const char *, const char *, int, int, int); /* - * Recursively upload 'local_directory' to 'remote_directory'. Preserve + * Recursively upload 'local_directory' to 'remote_directory'. Preserve * times if 'pflag' is set */ -int upload_dir(struct sftp_conn *, char *, char *, int, int, int); +int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, + int); /* Concatenate paths, taking care of slashes. Caller must free result. */ -char *path_append(char *, char *); +char *path_append(const char *, const char *); #endif diff --git a/crypto/openssh/sftp-common.c b/crypto/openssh/sftp-common.c index b546a9f..feccfd6 100644 --- a/crypto/openssh/sftp-common.c +++ b/crypto/openssh/sftp-common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-common.c,v 1.26 2014/01/09 03:26:00 guenther Exp $ */ +/* $OpenBSD: sftp-common.c,v 1.28 2015/01/20 23:14:00 deraadt Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Damien Miller. All rights reserved. @@ -27,9 +27,9 @@ #include "includes.h" __RCSID("$FreeBSD$"); +#include /* MAX */ #include #include -#include #include #include @@ -43,7 +43,8 @@ __RCSID("$FreeBSD$"); #endif #include "xmalloc.h" -#include "buffer.h" +#include "ssherr.h" +#include "sshbuf.h" #include "log.h" #include "sftp.h" @@ -101,59 +102,81 @@ attrib_to_stat(const Attrib *a, struct stat *st) } /* Decode attributes in buffer */ -Attrib * -decode_attrib(Buffer *b) +int +decode_attrib(struct sshbuf *b, Attrib *a) { - static Attrib a; - - attrib_clear(&a); - a.flags = buffer_get_int(b); - if (a.flags & SSH2_FILEXFER_ATTR_SIZE) - a.size = buffer_get_int64(b); - if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { - a.uid = buffer_get_int(b); - a.gid = buffer_get_int(b); - } - if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) - a.perm = buffer_get_int(b); - if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { - a.atime = buffer_get_int(b); - a.mtime = buffer_get_int(b); + int r; + + attrib_clear(a); + if ((r = sshbuf_get_u32(b, &a->flags)) != 0) + return r; + if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { + if ((r = sshbuf_get_u64(b, &a->size)) != 0) + return r; + } + if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { + if ((r = sshbuf_get_u32(b, &a->uid)) != 0 || + (r = sshbuf_get_u32(b, &a->gid)) != 0) + return r; + } + if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { + if ((r = sshbuf_get_u32(b, &a->perm)) != 0) + return r; + } + if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { + if ((r = sshbuf_get_u32(b, &a->atime)) != 0 || + (r = sshbuf_get_u32(b, &a->mtime)) != 0) + return r; } /* vendor-specific extensions */ - if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) { - char *type, *data; - int i, count; + if (a->flags & SSH2_FILEXFER_ATTR_EXTENDED) { + char *type; + u_char *data; + size_t dlen; + u_int i, count; - count = buffer_get_int(b); + if ((r = sshbuf_get_u32(b, &count)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); for (i = 0; i < count; i++) { - type = buffer_get_string(b, NULL); - data = buffer_get_string(b, NULL); - debug3("Got file attribute \"%s\"", type); + if ((r = sshbuf_get_cstring(b, &type, NULL)) != 0 || + (r = sshbuf_get_string(b, &data, &dlen)) != 0) + return r; + debug3("Got file attribute \"%.100s\" len %zu", + type, dlen); free(type); free(data); } } - return &a; + return 0; } /* Encode attributes to buffer */ -void -encode_attrib(Buffer *b, const Attrib *a) +int +encode_attrib(struct sshbuf *b, const Attrib *a) { - buffer_put_int(b, a->flags); - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) - buffer_put_int64(b, a->size); + int r; + + if ((r = sshbuf_put_u32(b, a->flags)) != 0) + return r; + if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { + if ((r = sshbuf_put_u64(b, a->size)) != 0) + return r; + } if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { - buffer_put_int(b, a->uid); - buffer_put_int(b, a->gid); + if ((r = sshbuf_put_u32(b, a->uid)) != 0 || + (r = sshbuf_put_u32(b, a->gid)) != 0) + return r; + } + if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { + if ((r = sshbuf_put_u32(b, a->perm)) != 0) + return r; } - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) - buffer_put_int(b, a->perm); if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { - buffer_put_int(b, a->atime); - buffer_put_int(b, a->mtime); + if ((r = sshbuf_put_u32(b, a->atime)) != 0 || + (r = sshbuf_put_u32(b, a->mtime)) != 0) + return r; } + return 0; } /* Convert from SSH2_FX_ status to text error message */ diff --git a/crypto/openssh/sftp-common.h b/crypto/openssh/sftp-common.h index 9ed86c0..2e778a9 100644 --- a/crypto/openssh/sftp-common.h +++ b/crypto/openssh/sftp-common.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-common.h,v 1.11 2010/01/13 01:40:16 djm Exp $ */ +/* $OpenBSD: sftp-common.h,v 1.12 2015/01/14 13:54:13 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -28,6 +28,7 @@ /* Maximum packet that we are willing to send/accept */ #define SFTP_MAX_MSG_LENGTH (256 * 1024) +struct sshbuf; typedef struct Attrib Attrib; /* File attributes */ @@ -44,8 +45,8 @@ struct Attrib { void attrib_clear(Attrib *); void stat_to_attrib(const struct stat *, Attrib *); void attrib_to_stat(const Attrib *, struct stat *); -Attrib *decode_attrib(Buffer *); -void encode_attrib(Buffer *, const Attrib *); +int decode_attrib(struct sshbuf *, Attrib *); +int encode_attrib(struct sshbuf *, const Attrib *); char *ls_file(const char *, const struct stat *, int, int); const char *fx2txt(int); diff --git a/crypto/openssh/sftp-glob.c b/crypto/openssh/sftp-glob.c index d85aecc..43a1beb 100644 --- a/crypto/openssh/sftp-glob.c +++ b/crypto/openssh/sftp-glob.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-glob.c,v 1.26 2013/11/08 11:15:19 dtucker Exp $ */ +/* $OpenBSD: sftp-glob.c,v 1.27 2015/01/14 13:54:13 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -25,10 +25,10 @@ #include #include #include +#include #include "xmalloc.h" #include "sftp.h" -#include "buffer.h" #include "sftp-common.h" #include "sftp-client.h" diff --git a/crypto/openssh/sftp-server.0 b/crypto/openssh/sftp-server.0 deleted file mode 100644 index ce7ddc0..0000000 --- a/crypto/openssh/sftp-server.0 +++ /dev/null @@ -1,95 +0,0 @@ -SFTP-SERVER(8) OpenBSD System Manager's Manual SFTP-SERVER(8) - -NAME - sftp-server - SFTP server subsystem - -SYNOPSIS - sftp-server [-ehR] [-d start_directory] [-f log_facility] [-l log_level] - [-P blacklisted_requests] [-p whitelisted_requests] - [-u umask] - sftp-server -Q protocol_feature - -DESCRIPTION - sftp-server is a program that speaks the server side of SFTP protocol to - stdout and expects client requests from stdin. sftp-server is not - intended to be called directly, but from sshd(8) using the Subsystem - option. - - Command-line flags to sftp-server should be specified in the Subsystem - declaration. See sshd_config(5) for more information. - - Valid options are: - - -d start_directory - specifies an alternate starting directory for users. The - pathname may contain the following tokens that are expanded at - runtime: %% is replaced by a literal '%', %h is replaced by the - home directory of the user being authenticated, and %u is - replaced by the username of that user. The default is to use the - user's home directory. This option is useful in conjunction with - the sshd_config(5) ChrootDirectory option. - - -e Causes sftp-server to print logging information to stderr instead - of syslog for debugging. - - -f log_facility - Specifies the facility code that is used when logging messages - from sftp-server. The possible values are: DAEMON, USER, AUTH, - LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. - The default is AUTH. - - -h Displays sftp-server usage information. - - -l log_level - Specifies which messages will be logged by sftp-server. The - possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, - DEBUG1, DEBUG2, and DEBUG3. INFO and VERBOSE log transactions - that sftp-server performs on behalf of the client. DEBUG and - DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher - levels of debugging output. The default is ERROR. - - -P blacklisted_requests - Specify a comma-separated list of SFTP protocol requests that are - banned by the server. sftp-server will reply to any blacklisted - request with a failure. The -Q flag can be used to determine the - supported request types. If both a blacklist and a whitelist are - specified, then the blacklist is applied before the whitelist. - - -p whitelisted_requests - Specify a comma-separated list of SFTP protocol requests that are - permitted by the server. All request types that are not on the - whitelist will be logged and replied to with a failure message. - - Care must be taken when using this feature to ensure that - requests made implicitly by SFTP clients are permitted. - - -Q protocol_feature - Query protocol features supported by sftp-server. At present the - only feature that may be queried is ``requests'', which may be - used for black or whitelisting (flags -P and -p respectively). - - -R Places this instance of sftp-server into a read-only mode. - Attempts to open files for writing, as well as other operations - that change the state of the filesystem, will be denied. - - -u umask - Sets an explicit umask(2) to be applied to newly-created files - and directories, instead of the user's default mask. - - For logging to work, sftp-server must be able to access /dev/log. Use of - sftp-server in a chroot configuration therefore requires that syslogd(8) - establish a logging socket inside the chroot directory. - -SEE ALSO - sftp(1), ssh(1), sshd_config(5), sshd(8) - - T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- - filexfer-02.txt, October 2001, work in progress material. - -HISTORY - sftp-server first appeared in OpenBSD 2.8. - -AUTHORS - Markus Friedl - -OpenBSD 5.5 October 14, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/sftp-server.8 b/crypto/openssh/sftp-server.8 index 1e0b277..c117398 100644 --- a/crypto/openssh/sftp-server.8 +++ b/crypto/openssh/sftp-server.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp-server.8,v 1.25 2013/10/14 14:18:56 jmc Exp $ +.\" $OpenBSD: sftp-server.8,v 1.27 2014/12/11 04:16:14 djm Exp $ .\" .\" Copyright (c) 2000 Markus Friedl. All rights reserved. .\" @@ -22,7 +22,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: October 14 2013 $ +.Dd $Mdocdate: December 11 2014 $ .Dt SFTP-SERVER 8 .Os .Sh NAME @@ -67,7 +67,7 @@ Valid options are: specifies an alternate starting directory for users. The pathname may contain the following tokens that are expanded at runtime: %% is replaced by a literal '%', -%h is replaced by the home directory of the user being authenticated, +%d is replaced by the home directory of the user being authenticated, and %u is replaced by the username of that user. The default is to use the user's home directory. This option is useful in conjunction with the @@ -140,11 +140,11 @@ to be applied to newly-created files and directories, instead of the user's default mask. .El .Pp -For logging to work, +On some systems, .Nm must be able to access -.Pa /dev/log . -Use of +.Pa /dev/log +for logging to work, and use of .Nm in a chroot configuration therefore requires that .Xr syslogd 8 diff --git a/crypto/openssh/sftp-server.c b/crypto/openssh/sftp-server.c index b8eb59c..eac11d7 100644 --- a/crypto/openssh/sftp-server.c +++ b/crypto/openssh/sftp-server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-server.c,v 1.103 2014/01/17 06:23:24 dtucker Exp $ */ +/* $OpenBSD: sftp-server.c,v 1.107 2015/08/20 22:32:42 deraadt Exp $ */ /* * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. * @@ -17,8 +17,8 @@ #include "includes.h" +#include /* MIN */ #include -#include #include #ifdef HAVE_SYS_TIME_H # include @@ -29,6 +29,9 @@ #ifdef HAVE_SYS_STATVFS_H #include #endif +#ifdef HAVE_SYS_PRCTL_H +#include +#endif #include #include @@ -37,13 +40,13 @@ #include #include #include -#include #include #include #include #include "xmalloc.h" -#include "buffer.h" +#include "sshbuf.h" +#include "ssherr.h" #include "log.h" #include "misc.h" #include "match.h" @@ -52,11 +55,6 @@ #include "sftp.h" #include "sftp-common.h" -/* helper */ -#define get_int64() buffer_get_int64(&iqueue); -#define get_int() buffer_get_int(&iqueue); -#define get_string(lenp) buffer_get_string(&iqueue, lenp); - /* Our verbosity */ static LogLevel log_level = SYSLOG_LEVEL_ERROR; @@ -65,8 +63,8 @@ static struct passwd *pw = NULL; static char *client_addr = NULL; /* input and output queue */ -static Buffer iqueue; -static Buffer oqueue; +struct sshbuf *iqueue; +struct sshbuf *oqueue; /* Version of client */ static u_int version; @@ -272,12 +270,6 @@ string_from_portable(int pflags) return ret; } -static Attrib * -get_attrib(void) -{ - return decode_attrib(&iqueue); -} - /* handle handles */ typedef struct Handle Handle; @@ -317,7 +309,7 @@ handle_new(int use, const char *name, int fd, int flags, DIR *dirp) if (num_handles + 1 <= num_handles) return -1; num_handles++; - handles = xrealloc(handles, num_handles, sizeof(Handle)); + handles = xreallocarray(handles, num_handles, sizeof(Handle)); handle_unused(num_handles - 1); } @@ -341,7 +333,7 @@ handle_is_ok(int i, int type) } static int -handle_to_string(int handle, char **stringp, int *hlenp) +handle_to_string(int handle, u_char **stringp, int *hlenp) { if (stringp == NULL || hlenp == NULL) return -1; @@ -352,7 +344,7 @@ handle_to_string(int handle, char **stringp, int *hlenp) } static int -handle_from_string(const char *handle, u_int hlen) +handle_from_string(const u_char *handle, u_int hlen) { int val; @@ -474,29 +466,31 @@ handle_log_exit(void) } static int -get_handle(void) +get_handle(struct sshbuf *queue, int *hp) { - char *handle; - int val = -1; - u_int hlen; + u_char *handle; + int r; + size_t hlen; - handle = get_string(&hlen); + *hp = -1; + if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0) + return r; if (hlen < 256) - val = handle_from_string(handle, hlen); + *hp = handle_from_string(handle, hlen); free(handle); - return val; + return 0; } /* send replies */ static void -send_msg(Buffer *m) +send_msg(struct sshbuf *m) { - int mlen = buffer_len(m); + int r; - buffer_put_int(&oqueue, mlen); - buffer_append(&oqueue, buffer_ptr(m), mlen); - buffer_consume(m, mlen); + if ((r = sshbuf_put_stringb(oqueue, m)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + sshbuf_reset(m); } static const char * @@ -520,38 +514,46 @@ status_to_message(u_int32_t status) static void send_status(u_int32_t id, u_int32_t status) { - Buffer msg; + struct sshbuf *msg; + int r; debug3("request %u: sent status %u", id, status); if (log_level > SYSLOG_LEVEL_VERBOSE || (status != SSH2_FX_OK && status != SSH2_FX_EOF)) logit("sent status %s", status_to_message(status)); - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_STATUS); - buffer_put_int(&msg, id); - buffer_put_int(&msg, status); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_u32(msg, status)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (version >= 3) { - buffer_put_cstring(&msg, status_to_message(status)); - buffer_put_cstring(&msg, ""); + if ((r = sshbuf_put_cstring(msg, + status_to_message(status))) != 0 || + (r = sshbuf_put_cstring(msg, "")) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } - send_msg(&msg); - buffer_free(&msg); + send_msg(msg); + sshbuf_free(msg); } static void -send_data_or_handle(char type, u_int32_t id, const char *data, int dlen) +send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen) { - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, type); - buffer_put_int(&msg, id); - buffer_put_string(&msg, data, dlen); - send_msg(&msg); - buffer_free(&msg); + struct sshbuf *msg; + int r; + + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, type)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_string(msg, data, dlen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(msg); + sshbuf_free(msg); } static void -send_data(u_int32_t id, const char *data, int dlen) +send_data(u_int32_t id, const u_char *data, int dlen) { debug("request %u: sent data len %d", id, dlen); send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); @@ -560,7 +562,7 @@ send_data(u_int32_t id, const char *data, int dlen) static void send_handle(u_int32_t id, int handle) { - char *string; + u_char *string; int hlen; handle_to_string(handle, &string, &hlen); @@ -572,62 +574,71 @@ send_handle(u_int32_t id, int handle) static void send_names(u_int32_t id, int count, const Stat *stats) { - Buffer msg; - int i; - - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_NAME); - buffer_put_int(&msg, id); - buffer_put_int(&msg, count); + struct sshbuf *msg; + int i, r; + + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_u32(msg, count)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: sent names count %d", id, count); for (i = 0; i < count; i++) { - buffer_put_cstring(&msg, stats[i].name); - buffer_put_cstring(&msg, stats[i].long_name); - encode_attrib(&msg, &stats[i].attrib); + if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 || + (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 || + (r = encode_attrib(msg, &stats[i].attrib)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } - send_msg(&msg); - buffer_free(&msg); + send_msg(msg); + sshbuf_free(msg); } static void send_attrib(u_int32_t id, const Attrib *a) { - Buffer msg; + struct sshbuf *msg; + int r; debug("request %u: sent attrib have 0x%x", id, a->flags); - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_ATTRS); - buffer_put_int(&msg, id); - encode_attrib(&msg, a); - send_msg(&msg); - buffer_free(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = encode_attrib(msg, a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(msg); + sshbuf_free(msg); } static void send_statvfs(u_int32_t id, struct statvfs *st) { - Buffer msg; + struct sshbuf *msg; u_int64_t flag; + int r; flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0; flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY); - buffer_put_int(&msg, id); - buffer_put_int64(&msg, st->f_bsize); - buffer_put_int64(&msg, st->f_frsize); - buffer_put_int64(&msg, st->f_blocks); - buffer_put_int64(&msg, st->f_bfree); - buffer_put_int64(&msg, st->f_bavail); - buffer_put_int64(&msg, st->f_files); - buffer_put_int64(&msg, st->f_ffree); - buffer_put_int64(&msg, st->f_favail); - buffer_put_int64(&msg, FSID_TO_ULONG(st->f_fsid)); - buffer_put_int64(&msg, flag); - buffer_put_int64(&msg, st->f_namemax); - send_msg(&msg); - buffer_free(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 || + (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 || + (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 || + (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 || + (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 || + (r = sshbuf_put_u64(msg, st->f_files)) != 0 || + (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 || + (r = sshbuf_put_u64(msg, st->f_favail)) != 0 || + (r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 || + (r = sshbuf_put_u64(msg, flag)) != 0 || + (r = sshbuf_put_u64(msg, st->f_namemax)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(msg); + sshbuf_free(msg); } /* parse incoming */ @@ -635,53 +646,59 @@ send_statvfs(u_int32_t id, struct statvfs *st) static void process_init(void) { - Buffer msg; + struct sshbuf *msg; + int r; - version = get_int(); + if ((r = sshbuf_get_u32(iqueue, &version)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); verbose("received client version %u", version); - buffer_init(&msg); - buffer_put_char(&msg, SSH2_FXP_VERSION); - buffer_put_int(&msg, SSH2_FILEXFER_VERSION); - /* POSIX rename extension */ - buffer_put_cstring(&msg, "posix-rename@openssh.com"); - buffer_put_cstring(&msg, "1"); /* version */ - /* statvfs extension */ - buffer_put_cstring(&msg, "statvfs@openssh.com"); - buffer_put_cstring(&msg, "2"); /* version */ - /* fstatvfs extension */ - buffer_put_cstring(&msg, "fstatvfs@openssh.com"); - buffer_put_cstring(&msg, "2"); /* version */ - /* hardlink extension */ - buffer_put_cstring(&msg, "hardlink@openssh.com"); - buffer_put_cstring(&msg, "1"); /* version */ - /* fsync extension */ - buffer_put_cstring(&msg, "fsync@openssh.com"); - buffer_put_cstring(&msg, "1"); /* version */ - send_msg(&msg); - buffer_free(&msg); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 || + (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 || + /* POSIX rename extension */ + (r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ + /* statvfs extension */ + (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */ + /* fstatvfs extension */ + (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */ + /* hardlink extension */ + (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ + /* fsync extension */ + (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send_msg(msg); + sshbuf_free(msg); } static void process_open(u_int32_t id) { u_int32_t pflags; - Attrib *a; + Attrib a; char *name; - int handle, fd, flags, mode, status = SSH2_FX_FAILURE; + int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; + + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || + (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ + (r = decode_attrib(iqueue, &a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - name = get_string(NULL); - pflags = get_int(); /* portable flags */ debug3("request %u: open flags %d", id, pflags); - a = get_attrib(); flags = flags_from_portable(pflags); - mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; + mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); if (readonly && ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR)) { verbose("Refusing open request in read-only mode"); - status = SSH2_FX_PERMISSION_DENIED; + status = SSH2_FX_PERMISSION_DENIED; } else { fd = open(name, flags, mode); if (fd < 0) { @@ -704,9 +721,11 @@ process_open(u_int32_t id) static void process_close(u_int32_t id) { - int handle, ret, status = SSH2_FX_FAILURE; + int r, handle, ret, status = SSH2_FX_FAILURE; + + if ((r = get_handle(iqueue, &handle)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - handle = get_handle(); debug3("request %u: close handle %u", id, handle); handle_log_close(handle, NULL); ret = handle_close(handle); @@ -717,14 +736,15 @@ process_close(u_int32_t id) static void process_read(u_int32_t id) { - char buf[64*1024]; + u_char buf[64*1024]; u_int32_t len; - int handle, fd, ret, status = SSH2_FX_FAILURE; + int r, handle, fd, ret, status = SSH2_FX_FAILURE; u_int64_t off; - handle = get_handle(); - off = get_int64(); - len = get_int(); + if ((r = get_handle(iqueue, &handle)) != 0 || + (r = sshbuf_get_u64(iqueue, &off)) != 0 || + (r = sshbuf_get_u32(iqueue, &len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: read \"%s\" (handle %d) off %llu len %d", id, handle_to_name(handle), handle, (unsigned long long)off, len); @@ -758,18 +778,19 @@ static void process_write(u_int32_t id) { u_int64_t off; - u_int len; - int handle, fd, ret, status; - char *data; + size_t len; + int r, handle, fd, ret, status; + u_char *data; - handle = get_handle(); - off = get_int64(); - data = get_string(&len); + if ((r = get_handle(iqueue, &handle)) != 0 || + (r = sshbuf_get_u64(iqueue, &off)) != 0 || + (r = sshbuf_get_string(iqueue, &data, &len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - debug("request %u: write \"%s\" (handle %d) off %llu len %d", + debug("request %u: write \"%s\" (handle %d) off %llu len %zu", id, handle_to_name(handle), handle, (unsigned long long)off, len); fd = handle_to_fd(handle); - + if (fd < 0) status = SSH2_FX_FAILURE; else { @@ -802,13 +823,15 @@ process_do_stat(u_int32_t id, int do_lstat) Attrib a; struct stat st; char *name; - int ret, status = SSH2_FX_FAILURE; + int r, status = SSH2_FX_FAILURE; + + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - name = get_string(NULL); debug3("request %u: %sstat", id, do_lstat ? "l" : ""); verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); - ret = do_lstat ? lstat(name, &st) : stat(name, &st); - if (ret < 0) { + r = do_lstat ? lstat(name, &st) : stat(name, &st); + if (r < 0) { status = errno_to_portable(errno); } else { stat_to_attrib(&st, &a); @@ -837,15 +860,16 @@ process_fstat(u_int32_t id) { Attrib a; struct stat st; - int fd, ret, handle, status = SSH2_FX_FAILURE; + int fd, r, handle, status = SSH2_FX_FAILURE; - handle = get_handle(); + if ((r = get_handle(iqueue, &handle)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: fstat \"%s\" (handle %u)", id, handle_to_name(handle), handle); fd = handle_to_fd(handle); if (fd >= 0) { - ret = fstat(fd, &st); - if (ret < 0) { + r = fstat(fd, &st); + if (r < 0) { status = errno_to_portable(errno); } else { stat_to_attrib(&st, &a); @@ -872,42 +896,44 @@ attrib_to_tv(const Attrib *a) static void process_setstat(u_int32_t id) { - Attrib *a; + Attrib a; char *name; - int status = SSH2_FX_OK, ret; + int r, status = SSH2_FX_OK; + + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || + (r = decode_attrib(iqueue, &a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - name = get_string(NULL); - a = get_attrib(); debug("request %u: setstat name \"%s\"", id, name); - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { + if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", - name, (unsigned long long)a->size); - ret = truncate(name, a->size); - if (ret == -1) + name, (unsigned long long)a.size); + r = truncate(name, a.size); + if (r == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { - logit("set \"%s\" mode %04o", name, a->perm); - ret = chmod(name, a->perm & 07777); - if (ret == -1) + if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { + logit("set \"%s\" mode %04o", name, a.perm); + r = chmod(name, a.perm & 07777); + if (r == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { + if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { char buf[64]; - time_t t = a->mtime; + time_t t = a.mtime; strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", localtime(&t)); logit("set \"%s\" modtime %s", name, buf); - ret = utimes(name, attrib_to_tv(a)); - if (ret == -1) + r = utimes(name, attrib_to_tv(&a)); + if (r == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { + if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { logit("set \"%s\" owner %lu group %lu", name, - (u_long)a->uid, (u_long)a->gid); - ret = chown(name, a->uid, a->gid); - if (ret == -1) + (u_long)a.uid, (u_long)a.gid); + r = chown(name, a.uid, a.gid); + if (r == -1) status = errno_to_portable(errno); } send_status(id, status); @@ -917,12 +943,14 @@ process_setstat(u_int32_t id) static void process_fsetstat(u_int32_t id) { - Attrib *a; - int handle, fd, ret; + Attrib a; + int handle, fd, r; int status = SSH2_FX_OK; - handle = get_handle(); - a = get_attrib(); + if ((r = get_handle(iqueue, &handle)) != 0 || + (r = decode_attrib(iqueue, &a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + debug("request %u: fsetstat handle %d", id, handle); fd = handle_to_fd(handle); if (fd < 0) @@ -930,47 +958,47 @@ process_fsetstat(u_int32_t id) else { char *name = handle_to_name(handle); - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { + if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", - name, (unsigned long long)a->size); - ret = ftruncate(fd, a->size); - if (ret == -1) + name, (unsigned long long)a.size); + r = ftruncate(fd, a.size); + if (r == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { - logit("set \"%s\" mode %04o", name, a->perm); + if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { + logit("set \"%s\" mode %04o", name, a.perm); #ifdef HAVE_FCHMOD - ret = fchmod(fd, a->perm & 07777); + r = fchmod(fd, a.perm & 07777); #else - ret = chmod(name, a->perm & 07777); + r = chmod(name, a.perm & 07777); #endif - if (ret == -1) + if (r == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { + if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { char buf[64]; - time_t t = a->mtime; + time_t t = a.mtime; strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", localtime(&t)); logit("set \"%s\" modtime %s", name, buf); #ifdef HAVE_FUTIMES - ret = futimes(fd, attrib_to_tv(a)); + r = futimes(fd, attrib_to_tv(&a)); #else - ret = utimes(name, attrib_to_tv(a)); + r = utimes(name, attrib_to_tv(&a)); #endif - if (ret == -1) + if (r == -1) status = errno_to_portable(errno); } - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { + if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { logit("set \"%s\" owner %lu group %lu", name, - (u_long)a->uid, (u_long)a->gid); + (u_long)a.uid, (u_long)a.gid); #ifdef HAVE_FCHOWN - ret = fchown(fd, a->uid, a->gid); + r = fchown(fd, a.uid, a.gid); #else - ret = chown(name, a->uid, a->gid); + r = chown(name, a.uid, a.gid); #endif - if (ret == -1) + if (r == -1) status = errno_to_portable(errno); } } @@ -982,9 +1010,11 @@ process_opendir(u_int32_t id) { DIR *dirp = NULL; char *path; - int handle, status = SSH2_FX_FAILURE; + int r, handle, status = SSH2_FX_FAILURE; + + if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - path = get_string(NULL); debug3("request %u: opendir", id); logit("opendir \"%s\"", path); dirp = opendir(path); @@ -1011,9 +1041,11 @@ process_readdir(u_int32_t id) DIR *dirp; struct dirent *dp; char *path; - int handle; + int r, handle; + + if ((r = get_handle(iqueue, &handle)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - handle = get_handle(); debug("request %u: readdir \"%s\" (handle %d)", id, handle_to_name(handle), handle); dirp = handle_to_dir(handle); @@ -1022,7 +1054,7 @@ process_readdir(u_int32_t id) send_status(id, SSH2_FX_FAILURE); } else { struct stat st; - char pathname[MAXPATHLEN]; + char pathname[PATH_MAX]; Stat *stats; int nstats = 10, count = 0, i; @@ -1030,7 +1062,7 @@ process_readdir(u_int32_t id) while ((dp = readdir(dirp)) != NULL) { if (count >= nstats) { nstats *= 2; - stats = xrealloc(stats, nstats, sizeof(Stat)); + stats = xreallocarray(stats, nstats, sizeof(Stat)); } /* XXX OVERFLOW ? */ snprintf(pathname, sizeof pathname, "%s%s%s", path, @@ -1063,14 +1095,15 @@ static void process_remove(u_int32_t id) { char *name; - int status = SSH2_FX_FAILURE; - int ret; + int r, status = SSH2_FX_FAILURE; + + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - name = get_string(NULL); debug3("request %u: remove", id); logit("remove name \"%s\"", name); - ret = unlink(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + r = unlink(name); + status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(name); } @@ -1078,18 +1111,20 @@ process_remove(u_int32_t id) static void process_mkdir(u_int32_t id) { - Attrib *a; + Attrib a; char *name; - int ret, mode, status = SSH2_FX_FAILURE; + int r, mode, status = SSH2_FX_FAILURE; - name = get_string(NULL); - a = get_attrib(); - mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? - a->perm & 07777 : 0777; + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || + (r = decode_attrib(iqueue, &a)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? + a.perm & 07777 : 0777; debug3("request %u: mkdir", id); logit("mkdir name \"%s\" mode 0%o", name, mode); - ret = mkdir(name, mode); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + r = mkdir(name, mode); + status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(name); } @@ -1098,13 +1133,15 @@ static void process_rmdir(u_int32_t id) { char *name; - int ret, status; + int r, status; + + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - name = get_string(NULL); debug3("request %u: rmdir", id); logit("rmdir name \"%s\"", name); - ret = rmdir(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + r = rmdir(name); + status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(name); } @@ -1112,10 +1149,13 @@ process_rmdir(u_int32_t id) static void process_realpath(u_int32_t id) { - char resolvedname[MAXPATHLEN]; + char resolvedname[PATH_MAX]; char *path; + int r; + + if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - path = get_string(NULL); if (path[0] == '\0') { free(path); path = xstrdup("."); @@ -1137,11 +1177,13 @@ static void process_rename(u_int32_t id) { char *oldpath, *newpath; - int status; + int r, status; struct stat sb; - oldpath = get_string(NULL); - newpath = get_string(NULL); + if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || + (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + debug3("request %u: rename", id); logit("rename old \"%s\" new \"%s\"", oldpath, newpath); status = SSH2_FX_FAILURE; @@ -1194,11 +1236,13 @@ process_rename(u_int32_t id) static void process_readlink(u_int32_t id) { - int len; - char buf[MAXPATHLEN]; + int r, len; + char buf[PATH_MAX]; char *path; - path = get_string(NULL); + if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + debug3("request %u: readlink", id); verbose("readlink \"%s\"", path); if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) @@ -1218,15 +1262,17 @@ static void process_symlink(u_int32_t id) { char *oldpath, *newpath; - int ret, status; + int r, status; + + if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || + (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - oldpath = get_string(NULL); - newpath = get_string(NULL); debug3("request %u: symlink", id); logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); /* this will fail if 'newpath' exists */ - ret = symlink(oldpath, newpath); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + r = symlink(oldpath, newpath); + status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(oldpath); free(newpath); @@ -1236,14 +1282,16 @@ static void process_extended_posix_rename(u_int32_t id) { char *oldpath, *newpath; - int ret, status; + int r, status; + + if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || + (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - oldpath = get_string(NULL); - newpath = get_string(NULL); debug3("request %u: posix-rename", id); logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); - ret = rename(oldpath, newpath); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + r = rename(oldpath, newpath); + status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(oldpath); free(newpath); @@ -1254,8 +1302,10 @@ process_extended_statvfs(u_int32_t id) { char *path; struct statvfs st; + int r; - path = get_string(NULL); + if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("request %u: statvfs", id); logit("statvfs \"%s\"", path); @@ -1269,10 +1319,11 @@ process_extended_statvfs(u_int32_t id) static void process_extended_fstatvfs(u_int32_t id) { - int handle, fd; + int r, handle, fd; struct statvfs st; - handle = get_handle(); + if ((r = get_handle(iqueue, &handle)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: fstatvfs \"%s\" (handle %u)", id, handle_to_name(handle), handle); if ((fd = handle_to_fd(handle)) < 0) { @@ -1289,14 +1340,16 @@ static void process_extended_hardlink(u_int32_t id) { char *oldpath, *newpath; - int ret, status; + int r, status; + + if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || + (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - oldpath = get_string(NULL); - newpath = get_string(NULL); debug3("request %u: hardlink", id); logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); - ret = link(oldpath, newpath); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + r = link(oldpath, newpath); + status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; send_status(id, status); free(oldpath); free(newpath); @@ -1305,16 +1358,17 @@ process_extended_hardlink(u_int32_t id) static void process_extended_fsync(u_int32_t id) { - int handle, fd, ret, status = SSH2_FX_OP_UNSUPPORTED; + int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED; - handle = get_handle(); + if ((r = get_handle(iqueue, &handle)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("request %u: fsync (handle %u)", id, handle); verbose("fsync \"%s\"", handle_to_name(handle)); if ((fd = handle_to_fd(handle)) < 0) status = SSH2_FX_NO_SUCH_FILE; else if (handle_is_ok(handle, HANDLE_FILE)) { - ret = fsync(fd); - status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + r = fsync(fd); + status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; } send_status(id, status); } @@ -1323,9 +1377,10 @@ static void process_extended(u_int32_t id) { char *request; - u_int i; + int i, r; - request = get_string(NULL); + if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); for (i = 0; extended_handlers[i].handler != NULL; i++) { if (strcmp(request, extended_handlers[i].ext_name) == 0) { if (!request_permitted(&extended_handlers[i])) @@ -1347,14 +1402,18 @@ process_extended(u_int32_t id) static void process(void) { - u_int msg_len, buf_len, consumed, type, i; - u_char *cp; + u_int msg_len; + u_int buf_len; + u_int consumed; + u_char type; + const u_char *cp; + int i, r; u_int32_t id; - buf_len = buffer_len(&iqueue); + buf_len = sshbuf_len(iqueue); if (buf_len < 5) return; /* Incomplete message. */ - cp = buffer_ptr(&iqueue); + cp = sshbuf_ptr(iqueue); msg_len = get_u32(cp); if (msg_len > SFTP_MAX_MSG_LENGTH) { error("bad message from %s local user %s", @@ -1363,9 +1422,11 @@ process(void) } if (buf_len < msg_len + 4) return; - buffer_consume(&iqueue, 4); + if ((r = sshbuf_consume(iqueue, 4)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); buf_len -= 4; - type = buffer_get_char(&iqueue); + if ((r = sshbuf_get_u8(iqueue, &type)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); switch (type) { case SSH2_FXP_INIT: @@ -1375,13 +1436,15 @@ process(void) case SSH2_FXP_EXTENDED: if (!init_done) fatal("Received extended request before init"); - id = get_int(); + if ((r = sshbuf_get_u32(iqueue, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); process_extended(id); break; default: if (!init_done) fatal("Received %u request before init", type); - id = get_int(); + if ((r = sshbuf_get_u32(iqueue, &id)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); for (i = 0; handlers[i].handler != NULL; i++) { if (type == handlers[i].type) { if (!request_permitted(&handlers[i])) { @@ -1397,17 +1460,18 @@ process(void) error("Unknown message %u", type); } /* discard the remaining bytes from the current packet */ - if (buf_len < buffer_len(&iqueue)) { + if (buf_len < sshbuf_len(iqueue)) { error("iqueue grew unexpectedly"); sftp_server_cleanup_exit(255); } - consumed = buf_len - buffer_len(&iqueue); + consumed = buf_len - sshbuf_len(iqueue); if (msg_len < consumed) { error("msg_len %u < consumed %u", msg_len, consumed); sftp_server_cleanup_exit(255); } - if (msg_len > consumed) - buffer_consume(&iqueue, msg_len - consumed); + if (msg_len > consumed && + (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } /* Cleanup handler that logs active handles upon normal exit */ @@ -1440,7 +1504,7 @@ int sftp_server_main(int argc, char **argv, struct passwd *user_pw) { fd_set *rset, *wset; - int i, in, out, max, ch, skipargs = 0, log_stderr = 0; + int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0; ssize_t len, olen, set_size; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; char *cp, *homedir = NULL, buf[4*4096]; @@ -1523,6 +1587,17 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) log_init(__progname, log_level, log_facility, log_stderr); +#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) + /* + * On Linux, we should try to avoid making /proc/self/{mem,maps} + * available to the user so that sftp access doesn't automatically + * imply arbitrary code execution access that will break + * restricted configurations. + */ + if (prctl(PR_SET_DUMPABLE, 0) != 0) + fatal("unable to make the process undumpable"); +#endif /* defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) */ + if ((cp = getenv("SSH_CONNECTION")) != NULL) { client_addr = xstrdup(cp); if ((cp = strchr(client_addr, ' ')) == NULL) { @@ -1551,12 +1626,14 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) if (out > max) max = out; - buffer_init(&iqueue); - buffer_init(&oqueue); + if ((iqueue = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((oqueue = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); - rset = (fd_set *)xmalloc(set_size); - wset = (fd_set *)xmalloc(set_size); + rset = xmalloc(set_size); + wset = xmalloc(set_size); if (homedir != NULL) { if (chdir(homedir) != 0) { @@ -1574,11 +1651,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) * the worst-case length packet it can generate, * otherwise apply backpressure by stopping reads. */ - if (buffer_check_alloc(&iqueue, sizeof(buf)) && - buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) + if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 && + (r = sshbuf_check_reserve(oqueue, + SFTP_MAX_MSG_LENGTH)) == 0) FD_SET(in, rset); + else if (r != SSH_ERR_NO_BUFFER_SPACE) + fatal("%s: sshbuf_check_reserve failed: %s", + __func__, ssh_err(r)); - olen = buffer_len(&oqueue); + olen = sshbuf_len(oqueue); if (olen > 0) FD_SET(out, wset); @@ -1598,18 +1679,20 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) } else if (len < 0) { error("read: %s", strerror(errno)); sftp_server_cleanup_exit(1); - } else { - buffer_append(&iqueue, buf, len); + } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) { + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); } } /* send oqueue to stdout */ if (FD_ISSET(out, wset)) { - len = write(out, buffer_ptr(&oqueue), olen); + len = write(out, sshbuf_ptr(oqueue), olen); if (len < 0) { error("write: %s", strerror(errno)); sftp_server_cleanup_exit(1); - } else { - buffer_consume(&oqueue, len); + } else if ((r = sshbuf_consume(oqueue, len)) != 0) { + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); } } @@ -1618,7 +1701,11 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) * into the output buffer, otherwise stop processing input * and let the output queue drain. */ - if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) + r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH); + if (r == 0) process(); + else if (r != SSH_ERR_NO_BUFFER_SPACE) + fatal("%s: sshbuf_check_reserve: %s", + __func__, ssh_err(r)); } } diff --git a/crypto/openssh/sftp.0 b/crypto/openssh/sftp.0 deleted file mode 100644 index 7139aac..0000000 --- a/crypto/openssh/sftp.0 +++ /dev/null @@ -1,370 +0,0 @@ -SFTP(1) OpenBSD Reference Manual SFTP(1) - -NAME - sftp - secure file transfer program - -SYNOPSIS - sftp [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher] - [-D sftp_server_path] [-F ssh_config] [-i identity_file] [-l limit] - [-o ssh_option] [-P port] [-R num_requests] [-S program] - [-s subsystem | sftp_server] host - sftp [user@]host[:file ...] - sftp [user@]host[:dir[/]] - sftp -b batchfile [user@]host - -DESCRIPTION - sftp is an interactive file transfer program, similar to ftp(1), which - performs all operations over an encrypted ssh(1) transport. It may also - use many features of ssh, such as public key authentication and - compression. sftp connects and logs into the specified host, then enters - an interactive command mode. - - The second usage format will retrieve files automatically if a non- - interactive authentication method is used; otherwise it will do so after - successful interactive authentication. - - The third usage format allows sftp to start in a remote directory. - - The final usage format allows for automated sessions using the -b option. - In such cases, it is necessary to configure non-interactive - authentication to obviate the need to enter a password at connection time - (see sshd(8) and ssh-keygen(1) for details). - - Since some usage formats use colon characters to delimit host names from - path names, IPv6 addresses must be enclosed in square brackets to avoid - ambiguity. - - The options are as follows: - - -1 Specify the use of protocol version 1. - - -2 Specify the use of protocol version 2. - - -4 Forces sftp to use IPv4 addresses only. - - -6 Forces sftp to use IPv6 addresses only. - - -a Attempt to continue interrupted downloads rather than overwriting - existing partial or complete copies of files. If the remote file - contents differ from the partial local copy then the resultant - file is likely to be corrupt. - - -B buffer_size - Specify the size of the buffer that sftp uses when transferring - files. Larger buffers require fewer round trips at the cost of - higher memory consumption. The default is 32768 bytes. - - -b batchfile - Batch mode reads a series of commands from an input batchfile - instead of stdin. Since it lacks user interaction it should be - used in conjunction with non-interactive authentication. A - batchfile of `-' may be used to indicate standard input. sftp - will abort if any of the following commands fail: get, put, - reget, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod, chown, - chgrp, lpwd, df, symlink, and lmkdir. Termination on error can - be suppressed on a command by command basis by prefixing the - command with a `-' character (for example, -rm /tmp/blah*). - - -C Enables compression (via ssh's -C flag). - - -c cipher - Selects the cipher to use for encrypting the data transfers. - This option is directly passed to ssh(1). - - -D sftp_server_path - Connect directly to a local sftp server (rather than via ssh(1)). - This option may be useful in debugging the client and server. - - -F ssh_config - Specifies an alternative per-user configuration file for ssh(1). - This option is directly passed to ssh(1). - - -f Requests that files be flushed to disk immediately after - transfer. When uploading files, this feature is only enabled if - the server implements the "fsync@openssh.com" extension. - - -i identity_file - Selects the file from which the identity (private key) for public - key authentication is read. This option is directly passed to - ssh(1). - - -l limit - Limits the used bandwidth, specified in Kbit/s. - - -o ssh_option - Can be used to pass options to ssh in the format used in - ssh_config(5). This is useful for specifying options for which - there is no separate sftp command-line flag. For example, to - specify an alternate port use: sftp -oPort=24. For full details - of the options listed below, and their possible values, see - ssh_config(5). - - AddressFamily - BatchMode - BindAddress - CanonicalDomains - CanonicalizeFallbackLocal - CanonicalizeHostname - CanonicalizeMaxDots - CanonicalizePermittedCNAMEs - ChallengeResponseAuthentication - CheckHostIP - Cipher - Ciphers - Compression - CompressionLevel - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - ControlPersist - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - HostName - IdentityFile - IdentitiesOnly - IPQoS - KbdInteractiveAuthentication - KbdInteractiveDevices - KexAlgorithms - LogLevel - MACs - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PKCS11Provider - Port - PreferredAuthentications - Protocol - ProxyCommand - PubkeyAuthentication - RekeyLimit - RhostsRSAAuthentication - RSAAuthentication - SendEnv - ServerAliveInterval - ServerAliveCountMax - StrictHostKeyChecking - TCPKeepAlive - UsePrivilegedPort - User - UserKnownHostsFile - VerifyHostKeyDNS - - -P port - Specifies the port to connect to on the remote host. - - -p Preserves modification times, access times, and modes from the - original files transferred. - - -q Quiet mode: disables the progress meter as well as warning and - diagnostic messages from ssh(1). - - -R num_requests - Specify how many requests may be outstanding at any one time. - Increasing this may slightly improve file transfer speed but will - increase memory usage. The default is 64 outstanding requests. - - -r Recursively copy entire directories when uploading and - downloading. Note that sftp does not follow symbolic links - encountered in the tree traversal. - - -S program - Name of the program to use for the encrypted connection. The - program must understand ssh(1) options. - - -s subsystem | sftp_server - Specifies the SSH2 subsystem or the path for an sftp server on - the remote host. A path is useful for using sftp over protocol - version 1, or when the remote sshd(8) does not have an sftp - subsystem configured. - - -v Raise logging level. This option is also passed to ssh. - -INTERACTIVE COMMANDS - Once in interactive mode, sftp understands a set of commands similar to - those of ftp(1). Commands are case insensitive. Pathnames that contain - spaces must be enclosed in quotes. Any special characters contained - within pathnames that are recognized by glob(3) must be escaped with - backslashes (`\'). - - bye Quit sftp. - - cd path - Change remote directory to path. - - chgrp grp path - Change group of file path to grp. path may contain glob(3) - characters and may match multiple files. grp must be a numeric - GID. - - chmod mode path - Change permissions of file path to mode. path may contain - glob(3) characters and may match multiple files. - - chown own path - Change owner of file path to own. path may contain glob(3) - characters and may match multiple files. own must be a numeric - UID. - - df [-hi] [path] - Display usage information for the filesystem holding the current - directory (or path if specified). If the -h flag is specified, - the capacity information will be displayed using "human-readable" - suffixes. The -i flag requests display of inode information in - addition to capacity information. This command is only supported - on servers that implement the ``statvfs@openssh.com'' extension. - - exit Quit sftp. - - get [-afPpr] remote-path [local-path] - Retrieve the remote-path and store it on the local machine. If - the local path name is not specified, it is given the same name - it has on the remote machine. remote-path may contain glob(3) - characters and may match multiple files. If it does and - local-path is specified, then local-path must specify a - directory. - - If the -a flag is specified, then attempt to resume partial - transfers of existing files. Note that resumption assumes that - any partial copy of the local file matches the remote copy. If - the remote file contents differ from the partial local copy then - the resultant file is likely to be corrupt. - - If the -f flag is specified, then fsync(2) will be called after - the file transfer has completed to flush the file to disk. - - If either the -P or -p flag is specified, then full file - permissions and access times are copied too. - - If the -r flag is specified then directories will be copied - recursively. Note that sftp does not follow symbolic links when - performing recursive transfers. - - help Display help text. - - lcd path - Change local directory to path. - - lls [ls-options [path]] - Display local directory listing of either path or current - directory if path is not specified. ls-options may contain any - flags supported by the local system's ls(1) command. path may - contain glob(3) characters and may match multiple files. - - lmkdir path - Create local directory specified by path. - - ln [-s] oldpath newpath - Create a link from oldpath to newpath. If the -s flag is - specified the created link is a symbolic link, otherwise it is a - hard link. - - lpwd Print local working directory. - - ls [-1afhlnrSt] [path] - Display a remote directory listing of either path or the current - directory if path is not specified. path may contain glob(3) - characters and may match multiple files. - - The following flags are recognized and alter the behaviour of ls - accordingly: - - -1 Produce single columnar output. - - -a List files beginning with a dot (`.'). - - -f Do not sort the listing. The default sort order is - lexicographical. - - -h When used with a long format option, use unit suffixes: - Byte, Kilobyte, Megabyte, Gigabyte, Terabyte, Petabyte, - and Exabyte in order to reduce the number of digits to - four or fewer using powers of 2 for sizes (K=1024, - M=1048576, etc.). - - -l Display additional details including permissions and - ownership information. - - -n Produce a long listing with user and group information - presented numerically. - - -r Reverse the sort order of the listing. - - -S Sort the listing by file size. - - -t Sort the listing by last modification time. - - lumask umask - Set local umask to umask. - - mkdir path - Create remote directory specified by path. - - progress - Toggle display of progress meter. - - put [-fPpr] local-path [remote-path] - Upload local-path and store it on the remote machine. If the - remote path name is not specified, it is given the same name it - has on the local machine. local-path may contain glob(3) - characters and may match multiple files. If it does and - remote-path is specified, then remote-path must specify a - directory. - - If the -f flag is specified, then a request will be sent to the - server to call fsync(2) after the file has been transferred. - Note that this is only supported by servers that implement the - "fsync@openssh.com" extension. - - If either the -P or -p flag is specified, then full file - permissions and access times are copied too. - - If the -r flag is specified then directories will be copied - recursively. Note that sftp does not follow symbolic links when - performing recursive transfers. - - pwd Display remote working directory. - - quit Quit sftp. - - reget [-Ppr] remote-path [local-path] - Resume download of remote-path. Equivalent to get with the -a - flag set. - - rename oldpath newpath - Rename remote file from oldpath to newpath. - - rm path - Delete remote file specified by path. - - rmdir path - Remove remote directory specified by path. - - symlink oldpath newpath - Create a symbolic link from oldpath to newpath. - - version - Display the sftp protocol version. - - !command - Execute command in local shell. - - ! Escape to local shell. - - ? Synonym for help. - -SEE ALSO - ftp(1), ls(1), scp(1), ssh(1), ssh-add(1), ssh-keygen(1), glob(3), - ssh_config(5), sftp-server(8), sshd(8) - - T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- - filexfer-00.txt, January 2001, work in progress material. - -OpenBSD 5.5 October 20, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/sftp.1 b/crypto/openssh/sftp.1 index a700c2a..214f011 100644 --- a/crypto/openssh/sftp.1 +++ b/crypto/openssh/sftp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.97 2013/10/20 09:51:26 djm Exp $ +.\" $OpenBSD: sftp.1,v 1.101 2015/01/30 11:43:14 djm Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -22,7 +22,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: October 20 2013 $ +.Dd $Mdocdate: January 30 2015 $ .Dt SFTP 1 .Os .Sh NAME @@ -108,10 +108,10 @@ Forces .Nm to use IPv6 addresses only. .It Fl a -Attempt to continue interrupted downloads rather than overwriting existing -partial or complete copies of files. -If the remote file contents differ from the partial local copy then the -resultant file is likely to be corrupt. +Attempt to continue interrupted transfers rather than overwriting +existing partial or complete copies of files. +If the partial contents differ from those being transferred, +then the resultant file is likely to be corrupt. .It Fl B Ar buffer_size Specify the size of the buffer that .Nm @@ -134,7 +134,7 @@ may be used to indicate standard input. .Nm will abort if any of the following commands fail: -.Ic get , put , reget , rename , ln , +.Ic get , put , reget , reput, rename , ln , .Ic rm , mkdir , chdir , ls , .Ic lchdir , chmod , chown , .Ic chgrp , lpwd , df , symlink , @@ -215,6 +215,7 @@ For full details of the options listed below, and their possible values, see .It HashKnownHosts .It Host .It HostbasedAuthentication +.It HostbasedKeyTypes .It HostKeyAlgorithms .It HostKeyAlias .It HostName @@ -243,6 +244,7 @@ For full details of the options listed below, and their possible values, see .It ServerAliveCountMax .It StrictHostKeyChecking .It TCPKeepAlive +.It UpdateHostKeys .It UsePrivilegedPort .It User .It UserKnownHostsFile @@ -495,7 +497,7 @@ Create remote directory specified by .It Ic progress Toggle display of progress meter. .It Xo Ic put -.Op Fl fPpr +.Op Fl afPpr .Ar local-path .Op Ar remote-path .Xc @@ -515,6 +517,15 @@ is specified, then must specify a directory. .Pp If the +.Fl a +flag is specified, then attempt to resume partial +transfers of existing files. +Note that resumption assumes that any partial copy of the remote file +matches the local copy. +If the local file contents differ from the remote local copy then +the resultant file is likely to be corrupt. +.Pp +If the .Fl f flag is specified, then a request will be sent to the server to call .Xr fsync 2 @@ -552,6 +563,18 @@ Equivalent to with the .Fl a flag set. +.It Xo Ic reput +.Op Fl Ppr +.Op Ar local-path +.Ar remote-path +.Xc +Resume upload of +.Op Ar local-path . +Equivalent to +.Ic put +with the +.Fl a +flag set. .It Ic rename Ar oldpath Ar newpath Rename remote file from .Ar oldpath diff --git a/crypto/openssh/sftp.c b/crypto/openssh/sftp.c index ad1f8c8..788601a 100644 --- a/crypto/openssh/sftp.c +++ b/crypto/openssh/sftp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.158 2013/11/20 20:54:10 deraadt Exp $ */ +/* $OpenBSD: sftp.c,v 1.171 2015/08/20 22:32:42 deraadt Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -17,6 +17,7 @@ #include "includes.h" +#include /* MIN MAX */ #include #include #ifdef HAVE_SYS_STAT_H @@ -46,6 +47,7 @@ #else typedef void EditLine; #endif +#include #include #include #include @@ -63,7 +65,8 @@ typedef void EditLine; #include "misc.h" #include "sftp.h" -#include "buffer.h" +#include "ssherr.h" +#include "sshbuf.h" #include "sftp-common.h" #include "sftp-client.h" @@ -88,7 +91,7 @@ int showprogress = 1; /* When this option is set, we always recursively download/upload directories */ int global_rflag = 0; -/* When this option is set, we resume download if possible */ +/* When this option is set, we resume download or upload if possible */ int global_aflag = 0; /* When this option is set, the file transfers will always preserve times */ @@ -151,14 +154,15 @@ enum sftp_command { I_PUT, I_PWD, I_QUIT, + I_REGET, I_RENAME, + I_REPUT, I_RM, I_RMDIR, I_SHELL, I_SYMLINK, I_VERSION, I_PROGRESS, - I_REGET, }; struct CMD { @@ -201,6 +205,7 @@ static const struct CMD cmds[] = { { "quit", I_QUIT, NOARGS }, { "reget", I_REGET, REMOTE }, { "rename", I_RENAME, REMOTE }, + { "reput", I_REPUT, LOCAL }, { "rm", I_RM, REMOTE }, { "rmdir", I_RMDIR, REMOTE }, { "symlink", I_SYMLINK, REMOTE }, @@ -248,8 +253,9 @@ help(void) "df [-hi] [path] Display statistics for current directory or\n" " filesystem containing 'path'\n" "exit Quit sftp\n" - "get [-Ppr] remote [local] Download file\n" - "reget remote [local] Resume download file\n" + "get [-afPpRr] remote [local] Download file\n" + "reget [-fPpRr] remote [local] Resume download file\n" + "reput [-fPpRr] [local] remote Resume upload file\n" "help Display this help text\n" "lcd path Change local directory to 'path'\n" "lls [ls-options [path]] Display local directory listing\n" @@ -260,7 +266,7 @@ help(void) "lumask umask Set local umask to 'umask'\n" "mkdir path Create remote directory\n" "progress Toggle display of progress meter\n" - "put [-Ppr] local [remote] Upload file\n" + "put [-afPpRr] local [remote] Upload file\n" "pwd Display remote working directory\n" "quit Quit sftp\n" "rename oldpath newpath Rename remote file\n" @@ -586,15 +592,19 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, char *abs_dst = NULL; glob_t g; char *filename, *tmp=NULL; - int i, err = 0; + int i, r, err = 0; abs_src = xstrdup(src); abs_src = make_absolute(abs_src, pwd); memset(&g, 0, sizeof(g)); debug3("Looking up %s", abs_src); - if (remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) { - error("File \"%s\" not found.", abs_src); + if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) { + if (r == GLOB_NOSPACE) { + error("Too many matches for \"%s\".", abs_src); + } else { + error("File \"%s\" not found.", abs_src); + } err = -1; goto out; } @@ -660,7 +670,7 @@ out: static int process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, - int pflag, int rflag, int fflag) + int pflag, int rflag, int resume, int fflag) { char *tmp_dst = NULL; char *abs_dst = NULL; @@ -723,16 +733,20 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, } free(tmp); - if (!quiet) + resume |= global_aflag; + if (!quiet && resume) + printf("Resuming upload of %s to %s\n", g.gl_pathv[i], + abs_dst); + else if (!quiet && !resume) printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { if (upload_dir(conn, g.gl_pathv[i], abs_dst, - pflag || global_pflag, 1, + pflag || global_pflag, 1, resume, fflag || global_fflag) == -1) err = -1; } else { if (do_upload(conn, g.gl_pathv[i], abs_dst, - pflag || global_pflag, + pflag || global_pflag, resume, fflag || global_fflag) == -1) err = -1; } @@ -855,19 +869,23 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, { char *fname, *lname; glob_t g; - int err; + int err, r; struct winsize ws; u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80; memset(&g, 0, sizeof(g)); - if (remote_glob(conn, path, + if ((r = remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT, - NULL, &g) || + NULL, &g)) != 0 || (g.gl_pathc && !g.gl_matchc)) { if (g.gl_pathc) globfree(&g); - error("Can't ls: \"%s\" not found", path); + if (r == GLOB_NOSPACE) { + error("Can't ls: Too many matches for \"%s\"", path); + } else { + error("Can't ls: \"%s\" not found", path); + } return -1; } @@ -1186,8 +1204,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, } static int -parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, - int *hflag, int *iflag, int *lflag, int *pflag, int *rflag, int *sflag, +parse_args(const char **cpp, int *ignore_errors, int *aflag, + int *fflag, int *hflag, int *iflag, int *lflag, int *pflag, + int *rflag, int *sflag, unsigned long *n_arg, char **path1, char **path2) { const char *cmd, *cp = *cpp; @@ -1239,6 +1258,7 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, switch (cmdnum) { case I_GET: case I_REGET: + case I_REPUT: case I_PUT: if ((optidx = parse_getput_flags(cmd, argv, argc, aflag, fflag, pflag, rflag)) == -1) @@ -1256,11 +1276,6 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, /* Destination is not globbed */ undo_glob_escape(*path2); } - if (*aflag && cmdnum == I_PUT) { - /* XXX implement resume for uploads */ - error("Resume is not supported for uploads"); - return -1; - } break; case I_LINK: if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) @@ -1382,12 +1397,13 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, int err_abort) { char *path1, *path2, *tmp; - int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, iflag = 0; + int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, + iflag = 0; int lflag = 0, pflag = 0, rflag = 0, sflag = 0; int cmdnum, i; unsigned long n_arg = 0; Attrib a, *aa; - char path_buf[MAXPATHLEN]; + char path_buf[PATH_MAX]; int err = 0; glob_t g; @@ -1415,9 +1431,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, err = process_get(conn, path1, path2, *pwd, pflag, rflag, aflag, fflag); break; + case I_REPUT: + aflag = 1; + /* FALLTHROUGH */ case I_PUT: err = process_put(conn, path1, path2, *pwd, pflag, - rflag, fflag); + rflag, aflag, fflag); break; case I_RENAME: path1 = make_absolute(path1, *pwd); @@ -1503,6 +1522,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, err = do_df(conn, path1, hflag, iflag); break; case I_LCHDIR: + tmp = tilde_expand_filename(path1, getuid()); + free(path1); + path1 = tmp; if (chdir(path1) == -1) { error("Couldn't change local directory to " "\"%s\": %s", path1, strerror(errno)); @@ -1834,6 +1856,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, pwdlen = tmplen + 1; /* track last seen '/' */ } free(tmp); + tmp = NULL; if (g.gl_matchc == 0) goto out; @@ -1841,7 +1864,6 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, if (g.gl_matchc > 1) complete_display(g.gl_pathv, pwdlen); - tmp = NULL; /* Don't try to extend globs */ if (file == NULL || hadglob) goto out; @@ -1904,7 +1926,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, lf = el_line(el); if (g.gl_matchc == 1) { i = 0; - if (!terminated) + if (!terminated && quote != '\0') ins[i++] = quote; if (*(lf->cursor - 1) != '/' && (lastarg || *(lf->cursor) != ' ')) @@ -1936,7 +1958,7 @@ complete(EditLine *el, int ch) /* Figure out which argument the cursor points to */ cursor = lf->cursor - lf->buffer; - line = (char *)xmalloc(cursor + 1); + line = xmalloc(cursor + 1); memcpy(line, lf->buffer, cursor); line[cursor] = '\0'; argv = makeargv(line, &carg, 1, "e, &terminated); @@ -1944,7 +1966,7 @@ complete(EditLine *el, int ch) /* Get all the arguments on the line */ len = lf->lastchar - lf->buffer; - line = (char *)xmalloc(len + 1); + line = xmalloc(len + 1); memcpy(line, lf->buffer, len); line[len] = '\0'; argv = makeargv(line, &argc, 1, NULL, NULL); @@ -2065,8 +2087,8 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) free(dir); } - setlinebuf(stdout); - setlinebuf(infile); + setvbuf(stdout, NULL, _IOLBF, 0); + setvbuf(infile, NULL, _IOLBF, 0); interactive = !batchmode && isatty(STDIN_FILENO); err = 0; diff --git a/crypto/openssh/ssh-add.0 b/crypto/openssh/ssh-add.0 deleted file mode 100644 index ba43fee..0000000 --- a/crypto/openssh/ssh-add.0 +++ /dev/null @@ -1,123 +0,0 @@ -SSH-ADD(1) OpenBSD Reference Manual SSH-ADD(1) - -NAME - ssh-add - adds private key identities to the authentication agent - -SYNOPSIS - ssh-add [-cDdkLlXx] [-t life] [file ...] - ssh-add -s pkcs11 - ssh-add -e pkcs11 - -DESCRIPTION - ssh-add adds private key identities to the authentication agent, - ssh-agent(1). When run without arguments, it adds the files - ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and - ~/.ssh/identity. After loading a private key, ssh-add will try to load - corresponding certificate information from the filename obtained by - appending -cert.pub to the name of the private key file. Alternative - file names can be given on the command line. - - If any file requires a passphrase, ssh-add asks for the passphrase from - the user. The passphrase is read from the user's tty. ssh-add retries - the last passphrase if multiple identity files are given. - - The authentication agent must be running and the SSH_AUTH_SOCK - environment variable must contain the name of its socket for ssh-add to - work. - - The options are as follows: - - -c Indicates that added identities should be subject to confirmation - before being used for authentication. Confirmation is performed - by the SSH_ASKPASS program mentioned below. Successful - confirmation is signaled by a zero exit status from the - SSH_ASKPASS program, rather than text entered into the requester. - - -D Deletes all identities from the agent. - - -d Instead of adding identities, removes identities from the agent. - If ssh-add has been run without arguments, the keys for the - default identities and their corresponding certificates will be - removed. Otherwise, the argument list will be interpreted as a - list of paths to public key files to specify keys and - certificates to be removed from the agent. If no public key is - found at a given path, ssh-add will append .pub and retry. - - -e pkcs11 - Remove keys provided by the PKCS#11 shared library pkcs11. - - -k When loading keys into or deleting keys from the agent, process - plain private keys only and skip certificates. - - -L Lists public key parameters of all identities currently - represented by the agent. - - -l Lists fingerprints of all identities currently represented by the - agent. - - -s pkcs11 - Add keys provided by the PKCS#11 shared library pkcs11. - - -t life - Set a maximum lifetime when adding identities to an agent. The - lifetime may be specified in seconds or in a time format - specified in sshd_config(5). - - -X Unlock the agent. - - -x Lock the agent with a password. - -ENVIRONMENT - DISPLAY and SSH_ASKPASS - If ssh-add needs a passphrase, it will read the passphrase from - the current terminal if it was run from a terminal. If ssh-add - does not have a terminal associated with it but DISPLAY and - SSH_ASKPASS are set, it will execute the program specified by - SSH_ASKPASS and open an X11 window to read the passphrase. This - is particularly useful when calling ssh-add from a .xsession or - related script. (Note that on some machines it may be necessary - to redirect the input from /dev/null to make this work.) - - SSH_AUTH_SOCK - Identifies the path of a UNIX-domain socket used to communicate - with the agent. - -FILES - ~/.ssh/identity - Contains the protocol version 1 RSA authentication identity of - the user. - - ~/.ssh/id_dsa - Contains the protocol version 2 DSA authentication identity of - the user. - - ~/.ssh/id_ecdsa - Contains the protocol version 2 ECDSA authentication identity of - the user. - - ~/.ssh/id_ed25519 - Contains the protocol version 2 ED25519 authentication identity - of the user. - - ~/.ssh/id_rsa - Contains the protocol version 2 RSA authentication identity of - the user. - - Identity files should not be readable by anyone but the user. Note that - ssh-add ignores identity files if they are accessible by others. - -EXIT STATUS - Exit status is 0 on success, 1 if the specified command fails, and 2 if - ssh-add is unable to contact the authentication agent. - -SEE ALSO - ssh(1), ssh-agent(1), ssh-keygen(1), sshd(8) - -AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by - Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. - -OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/ssh-add.1 b/crypto/openssh/ssh-add.1 index 4812448..f02b595 100644 --- a/crypto/openssh/ssh-add.1 +++ b/crypto/openssh/ssh-add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.59 2013/12/07 11:58:46 naddy Exp $ +.\" $OpenBSD: ssh-add.1,v 1.62 2015/03/30 18:28:37 jmc Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: December 7 2013 $ +.Dd $Mdocdate: March 30 2015 $ .Dt SSH-ADD 1 .Os .Sh NAME @@ -44,6 +44,7 @@ .Sh SYNOPSIS .Nm ssh-add .Op Fl cDdkLlXx +.Op Fl E Ar fingerprint_hash .Op Fl t Ar life .Op Ar .Nm ssh-add @@ -87,12 +88,11 @@ The options are as follows: .It Fl c Indicates that added identities should be subject to confirmation before being used for authentication. -Confirmation is performed by the -.Ev SSH_ASKPASS -program mentioned below. -Successful confirmation is signaled by a zero exit status from the -.Ev SSH_ASKPASS -program, rather than text entered into the requester. +Confirmation is performed by +.Xr ssh-askpass 1 . +Successful confirmation is signaled by a zero exit status from +.Xr ssh-askpass 1 , +rather than text entered into the requester. .It Fl D Deletes all identities from the agent. .It Fl d @@ -108,6 +108,14 @@ If no public key is found at a given path, will append .Pa .pub and retry. +.It Fl E Ar fingerprint_hash +Specifies the hash algorithm used when displaying key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . .It Fl e Ar pkcs11 Remove keys provided by the PKCS#11 shared library .Ar pkcs11 . @@ -147,6 +155,8 @@ and .Ev SSH_ASKPASS are set, it will execute the program specified by .Ev SSH_ASKPASS +(by default +.Dq ssh-askpass ) and open an X11 window to read the passphrase. This is particularly useful when calling .Nm @@ -171,7 +181,7 @@ Contains the protocol version 2 DSA authentication identity of the user. .It Pa ~/.ssh/id_ecdsa Contains the protocol version 2 ECDSA authentication identity of the user. .It Pa ~/.ssh/id_ed25519 -Contains the protocol version 2 ED25519 authentication identity of the user. +Contains the protocol version 2 Ed25519 authentication identity of the user. .It Pa ~/.ssh/id_rsa Contains the protocol version 2 RSA authentication identity of the user. .El @@ -188,6 +198,7 @@ is unable to contact the authentication agent. .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-agent 1 , +.Xr ssh-askpass 1 , .Xr ssh-keygen 1 , .Xr sshd 8 .Sh AUTHORS diff --git a/crypto/openssh/ssh-add.c b/crypto/openssh/ssh-add.c index 3421452..d6271d7 100644 --- a/crypto/openssh/ssh-add.c +++ b/crypto/openssh/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.109 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.123 2015/07/03 03:43:18 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -39,11 +39,11 @@ #include #include -#include #include #include "openbsd-compat/openssl-compat.h" +#include #include #include #include @@ -51,33 +51,42 @@ #include #include #include +#include #include "xmalloc.h" #include "ssh.h" #include "rsa.h" #include "log.h" -#include "key.h" -#include "buffer.h" +#include "sshkey.h" +#include "sshbuf.h" #include "authfd.h" #include "authfile.h" #include "pathnames.h" #include "misc.h" +#include "ssherr.h" +#include "digest.h" /* argv0 */ extern char *__progname; /* Default files to add */ static char *default_files[] = { +#ifdef WITH_OPENSSL _PATH_SSH_CLIENT_ID_RSA, _PATH_SSH_CLIENT_ID_DSA, #ifdef OPENSSL_HAS_ECC _PATH_SSH_CLIENT_ID_ECDSA, #endif +#endif /* WITH_OPENSSL */ _PATH_SSH_CLIENT_ID_ED25519, +#ifdef WITH_SSH1 _PATH_SSH_CLIENT_IDENTITY, +#endif NULL }; +static int fingerprint_hash = SSH_FP_HASH_DEFAULT; + /* Default lifetime (0 == forever) */ static int lifetime = 0; @@ -97,22 +106,22 @@ clear_pass(void) } static int -delete_file(AuthenticationConnection *ac, const char *filename, int key_only) +delete_file(int agent_fd, const char *filename, int key_only) { - Key *public = NULL, *cert = NULL; + struct sshkey *public, *cert = NULL; char *certpath = NULL, *comment = NULL; - int ret = -1; + int r, ret = -1; - public = key_load_public(filename, &comment); - if (public == NULL) { - printf("Bad key file %s\n", filename); + if ((r = sshkey_load_public(filename, &public, &comment)) != 0) { + printf("Bad key file %s: %s\n", filename, ssh_err(r)); return -1; } - if (ssh_remove_identity(ac, public)) { + if ((r = ssh_remove_identity(agent_fd, public)) == 0) { fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); ret = 0; } else - fprintf(stderr, "Could not remove identity: %s\n", filename); + fprintf(stderr, "Could not remove identity \"%s\": %s\n", + filename, ssh_err(r)); if (key_only) goto out; @@ -121,24 +130,30 @@ delete_file(AuthenticationConnection *ac, const char *filename, int key_only) free(comment); comment = NULL; xasprintf(&certpath, "%s-cert.pub", filename); - if ((cert = key_load_public(certpath, &comment)) == NULL) + if ((r = sshkey_load_public(certpath, &cert, &comment)) != 0) { + if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT) + error("Failed to load certificate \"%s\": %s", + certpath, ssh_err(r)); goto out; - if (!key_equal_public(cert, public)) + } + + if (!sshkey_equal_public(cert, public)) fatal("Certificate %s does not match private key %s", certpath, filename); - if (ssh_remove_identity(ac, cert)) { + if ((r = ssh_remove_identity(agent_fd, cert)) == 0) { fprintf(stderr, "Identity removed: %s (%s)\n", certpath, comment); ret = 0; } else - fprintf(stderr, "Could not remove identity: %s\n", certpath); + fprintf(stderr, "Could not remove identity \"%s\": %s\n", + certpath, ssh_err(r)); out: if (cert != NULL) - key_free(cert); + sshkey_free(cert); if (public != NULL) - key_free(public); + sshkey_free(public); free(certpath); free(comment); @@ -147,14 +162,14 @@ delete_file(AuthenticationConnection *ac, const char *filename, int key_only) /* Send a request to remove all identities. */ static int -delete_all(AuthenticationConnection *ac) +delete_all(int agent_fd) { int ret = -1; - if (ssh_remove_all_identities(ac, 1)) + if (ssh_remove_all_identities(agent_fd, 2) == 0) ret = 0; - /* ignore error-code for ssh2 */ - ssh_remove_all_identities(ac, 2); + /* ignore error-code for ssh1 */ + ssh_remove_all_identities(agent_fd, 1); if (ret == 0) fprintf(stderr, "All identities removed.\n"); @@ -165,13 +180,13 @@ delete_all(AuthenticationConnection *ac) } static int -add_file(AuthenticationConnection *ac, const char *filename, int key_only) +add_file(int agent_fd, const char *filename, int key_only) { - Key *private, *cert; + struct sshkey *private, *cert; char *comment = NULL; char msg[1024], *certpath = NULL; - int fd, perms_ok, ret = -1; - Buffer keyblob; + int r, fd, ret = -1; + struct sshbuf *keyblob; if (strcmp(filename, "-") == 0) { fd = STDIN_FILENO; @@ -186,53 +201,73 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only) * will occur multiple times, so check perms first and bail if wrong. */ if (fd != STDIN_FILENO) { - perms_ok = key_perm_ok(fd, filename); - if (!perms_ok) { + if (sshkey_perm_ok(fd, filename) != 0) { close(fd); return -1; } } - buffer_init(&keyblob); - if (!key_load_file(fd, filename, &keyblob)) { - buffer_free(&keyblob); + if ((keyblob = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshkey_load_file(fd, keyblob)) != 0) { + fprintf(stderr, "Error loading key \"%s\": %s\n", + filename, ssh_err(r)); + sshbuf_free(keyblob); close(fd); return -1; } close(fd); /* At first, try empty passphrase */ - private = key_parse_private(&keyblob, filename, "", &comment); + if ((r = sshkey_parse_private_fileblob(keyblob, "", filename, + &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) { + fprintf(stderr, "Error loading key \"%s\": %s\n", + filename, ssh_err(r)); + goto fail_load; + } + /* try last */ + if (private == NULL && pass != NULL) { + if ((r = sshkey_parse_private_fileblob(keyblob, pass, filename, + &private, &comment)) != 0 && + r != SSH_ERR_KEY_WRONG_PASSPHRASE) { + fprintf(stderr, "Error loading key \"%s\": %s\n", + filename, ssh_err(r)); + goto fail_load; + } + } if (comment == NULL) comment = xstrdup(filename); - /* try last */ - if (private == NULL && pass != NULL) - private = key_parse_private(&keyblob, filename, pass, NULL); if (private == NULL) { /* clear passphrase since it did not work */ clear_pass(); - snprintf(msg, sizeof msg, "Enter passphrase for %.200s: ", - comment); + snprintf(msg, sizeof msg, "Enter passphrase for %.200s%s: ", + comment, confirm ? " (will confirm each use)" : ""); for (;;) { pass = read_passphrase(msg, RP_ALLOW_STDIN); - if (strcmp(pass, "") == 0) { + if (strcmp(pass, "") == 0) + goto fail_load; + if ((r = sshkey_parse_private_fileblob(keyblob, pass, + filename, &private, NULL)) == 0) + break; + else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) { + fprintf(stderr, + "Error loading key \"%s\": %s\n", + filename, ssh_err(r)); + fail_load: clear_pass(); free(comment); - buffer_free(&keyblob); + sshbuf_free(keyblob); return -1; } - private = key_parse_private(&keyblob, filename, pass, - &comment); - if (private != NULL) - break; clear_pass(); snprintf(msg, sizeof msg, - "Bad passphrase, try again for %.200s: ", comment); + "Bad passphrase, try again for %.200s%s: ", comment, + confirm ? " (will confirm each use)" : ""); } } - buffer_free(&keyblob); + sshbuf_free(keyblob); - if (ssh_add_identity_constrained(ac, private, comment, lifetime, - confirm)) { + if ((r = ssh_add_identity_constrained(agent_fd, private, comment, + lifetime, confirm)) == 0) { fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); ret = 0; if (lifetime != 0) @@ -242,7 +277,8 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only) fprintf(stderr, "The user must confirm each use of the key\n"); } else { - fprintf(stderr, "Could not add identity: %s\n", filename); + fprintf(stderr, "Could not add identity \"%s\": %s\n", + filename, ssh_err(r)); } /* Skip trying to load the cert if requested */ @@ -251,29 +287,38 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only) /* Now try to add the certificate flavour too */ xasprintf(&certpath, "%s-cert.pub", filename); - if ((cert = key_load_public(certpath, NULL)) == NULL) + if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) { + if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT) + error("Failed to load certificate \"%s\": %s", + certpath, ssh_err(r)); goto out; + } - if (!key_equal_public(cert, private)) { + if (!sshkey_equal_public(cert, private)) { error("Certificate %s does not match private key %s", certpath, filename); - key_free(cert); + sshkey_free(cert); goto out; } /* Graft with private bits */ - if (key_to_certified(private, key_cert_is_legacy(cert)) != 0) { - error("%s: key_to_certified failed", __func__); - key_free(cert); + if ((r = sshkey_to_certified(private)) != 0) { + error("%s: sshkey_to_certified: %s", __func__, ssh_err(r)); + sshkey_free(cert); + goto out; + } + if ((r = sshkey_cert_copy(cert, private)) != 0) { + error("%s: key_cert_copy: %s", __func__, ssh_err(r)); + sshkey_free(cert); goto out; } - key_cert_copy(cert, private); - key_free(cert); + sshkey_free(cert); - if (!ssh_add_identity_constrained(ac, private, comment, - lifetime, confirm)) { - error("Certificate %s (%s) add failed", certpath, - private->cert->key_id); + if ((r = ssh_add_identity_constrained(agent_fd, private, comment, + lifetime, confirm)) != 0) { + error("Certificate %s (%s) add failed: %s", certpath, + private->cert->key_id, ssh_err(r)); + goto out; } fprintf(stderr, "Certificate added: %s (%s)\n", certpath, private->cert->key_id); @@ -282,19 +327,18 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only) if (confirm != 0) fprintf(stderr, "The user must confirm each use of the key\n"); out: - if (certpath != NULL) - free(certpath); + free(certpath); free(comment); - key_free(private); + sshkey_free(private); return ret; } static int -update_card(AuthenticationConnection *ac, int add, const char *id) +update_card(int agent_fd, int add, const char *id) { char *pin = NULL; - int ret = -1; + int r, ret = -1; if (add) { if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", @@ -302,14 +346,14 @@ update_card(AuthenticationConnection *ac, int add, const char *id) return -1; } - if (ssh_update_card(ac, add, id, pin == NULL ? "" : pin, - lifetime, confirm)) { + if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin, + lifetime, confirm)) == 0) { fprintf(stderr, "Card %s: %s\n", add ? "added" : "removed", id); ret = 0; } else { - fprintf(stderr, "Could not %s card: %s\n", - add ? "add" : "remove", id); + fprintf(stderr, "Could not %s card \"%s\": %s\n", + add ? "add" : "remove", id, ssh_err(r)); ret = -1; } free(pin); @@ -317,32 +361,48 @@ update_card(AuthenticationConnection *ac, int add, const char *id) } static int -list_identities(AuthenticationConnection *ac, int do_fp) +list_identities(int agent_fd, int do_fp) { - Key *key; - char *comment, *fp; - int had_identities = 0; - int version; - - for (version = 1; version <= 2; version++) { - for (key = ssh_get_first_identity(ac, &comment, version); - key != NULL; - key = ssh_get_next_identity(ac, &comment, version)) { + char *fp; + int r, had_identities = 0; + struct ssh_identitylist *idlist; + size_t i; +#ifdef WITH_SSH1 + int version = 1; +#else + int version = 2; +#endif + + for (; version <= 2; version++) { + if ((r = ssh_fetch_identitylist(agent_fd, version, + &idlist)) != 0) { + if (r != SSH_ERR_AGENT_NO_IDENTITIES) + fprintf(stderr, "error fetching identities for " + "protocol %d: %s\n", version, ssh_err(r)); + continue; + } + for (i = 0; i < idlist->nkeys; i++) { had_identities = 1; if (do_fp) { - fp = key_fingerprint(key, SSH_FP_MD5, - SSH_FP_HEX); + fp = sshkey_fingerprint(idlist->keys[i], + fingerprint_hash, SSH_FP_DEFAULT); printf("%d %s %s (%s)\n", - key_size(key), fp, comment, key_type(key)); + sshkey_size(idlist->keys[i]), + fp == NULL ? "(null)" : fp, + idlist->comments[i], + sshkey_type(idlist->keys[i])); free(fp); } else { - if (!key_write(key, stdout)) - fprintf(stderr, "key_write failed"); - fprintf(stdout, " %s\n", comment); + if ((r = sshkey_write(idlist->keys[i], + stdout)) != 0) { + fprintf(stderr, "sshkey_write: %s\n", + ssh_err(r)); + continue; + } + fprintf(stdout, " %s\n", idlist->comments[i]); } - key_free(key); - free(comment); } + ssh_free_identitylist(idlist); } if (!had_identities) { printf("The agent has no identities.\n"); @@ -352,10 +412,10 @@ list_identities(AuthenticationConnection *ac, int do_fp) } static int -lock_agent(AuthenticationConnection *ac, int lock) +lock_agent(int agent_fd, int lock) { char prompt[100], *p1, *p2; - int passok = 1, ret = -1; + int r, passok = 1, ret = -1; strlcpy(prompt, "Enter lock password: ", sizeof(prompt)); p1 = read_passphrase(prompt, RP_ALLOW_STDIN); @@ -369,24 +429,28 @@ lock_agent(AuthenticationConnection *ac, int lock) explicit_bzero(p2, strlen(p2)); free(p2); } - if (passok && ssh_lock_agent(ac, lock, p1)) { - fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un"); - ret = 0; - } else - fprintf(stderr, "Failed to %slock agent.\n", lock ? "" : "un"); + if (passok) { + if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) { + fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un"); + ret = 0; + } else { + fprintf(stderr, "Failed to %slock agent: %s\n", + lock ? "" : "un", ssh_err(r)); + } + } explicit_bzero(p1, strlen(p1)); free(p1); return (ret); } static int -do_file(AuthenticationConnection *ac, int deleting, int key_only, char *file) +do_file(int agent_fd, int deleting, int key_only, char *file) { if (deleting) { - if (delete_file(ac, file, key_only) == -1) + if (delete_file(agent_fd, file, key_only) == -1) return -1; } else { - if (add_file(ac, file, key_only) == -1) + if (add_file(agent_fd, file, key_only) == -1) return -1; } return 0; @@ -398,6 +462,7 @@ usage(void) fprintf(stderr, "usage: %s [options] [file ...]\n", __progname); fprintf(stderr, "Options:\n"); fprintf(stderr, " -l List fingerprints of all identities.\n"); + fprintf(stderr, " -E hash Specify hash algorithm used for fingerprints.\n"); fprintf(stderr, " -L List public key parameters of all identities.\n"); fprintf(stderr, " -k Load only keys and not certificates.\n"); fprintf(stderr, " -c Require confirmation to sign using identities\n"); @@ -415,9 +480,10 @@ main(int argc, char **argv) { extern char *optarg; extern int optind; - AuthenticationConnection *ac = NULL; + int agent_fd; char *pkcs11provider = NULL; - int i, ch, deleting = 0, ret = 0, key_only = 0; + int r, i, ch, deleting = 0, ret = 0, key_only = 0; + int xflag = 0, lflag = 0, Dflag = 0; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -425,30 +491,47 @@ main(int argc, char **argv) __progname = ssh_get_progname(argv[0]); seed_rng(); +#ifdef WITH_OPENSSL OpenSSL_add_all_algorithms(); +#endif + + setvbuf(stdout, NULL, _IOLBF, 0); - /* At first, get a connection to the authentication agent. */ - ac = ssh_get_authentication_connection(); - if (ac == NULL) { - fprintf(stderr, - "Could not open a connection to your authentication agent.\n"); + /* First, get a connection to the authentication agent. */ + switch (r = ssh_get_authentication_socket(&agent_fd)) { + case 0: + break; + case SSH_ERR_AGENT_NOT_PRESENT: + fprintf(stderr, "Could not open a connection to your " + "authentication agent.\n"); + exit(2); + default: + fprintf(stderr, "Error connecting to agent: %s\n", ssh_err(r)); exit(2); } - while ((ch = getopt(argc, argv, "klLcdDxXe:s:t:")) != -1) { + + while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) { switch (ch) { + case 'E': + fingerprint_hash = ssh_digest_alg_by_name(optarg); + if (fingerprint_hash == -1) + fatal("Invalid hash algorithm \"%s\"", optarg); + break; case 'k': key_only = 1; break; case 'l': case 'L': - if (list_identities(ac, ch == 'l' ? 1 : 0) == -1) - ret = 1; - goto done; + if (lflag != 0) + fatal("-%c flag already specified", lflag); + lflag = ch; + break; case 'x': case 'X': - if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1) - ret = 1; - goto done; + if (xflag != 0) + fatal("-%c flag already specified", xflag); + xflag = ch; + break; case 'c': confirm = 1; break; @@ -456,9 +539,8 @@ main(int argc, char **argv) deleting = 1; break; case 'D': - if (delete_all(ac) == -1) - ret = 1; - goto done; + Dflag = 1; + break; case 's': pkcs11provider = optarg; break; @@ -479,15 +561,32 @@ main(int argc, char **argv) goto done; } } + + if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1) + fatal("Invalid combination of actions"); + else if (xflag) { + if (lock_agent(agent_fd, xflag == 'x' ? 1 : 0) == -1) + ret = 1; + goto done; + } else if (lflag) { + if (list_identities(agent_fd, lflag == 'l' ? 1 : 0) == -1) + ret = 1; + goto done; + } else if (Dflag) { + if (delete_all(agent_fd) == -1) + ret = 1; + goto done; + } + argc -= optind; argv += optind; if (pkcs11provider != NULL) { - if (update_card(ac, !deleting, pkcs11provider) == -1) + if (update_card(agent_fd, !deleting, pkcs11provider) == -1) ret = 1; goto done; } if (argc == 0) { - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; struct passwd *pw; struct stat st; int count = 0; @@ -504,7 +603,7 @@ main(int argc, char **argv) default_files[i]); if (stat(buf, &st) < 0) continue; - if (do_file(ac, deleting, key_only, buf) == -1) + if (do_file(agent_fd, deleting, key_only, buf) == -1) ret = 1; else count++; @@ -513,13 +612,14 @@ main(int argc, char **argv) ret = 1; } else { for (i = 0; i < argc; i++) { - if (do_file(ac, deleting, key_only, argv[i]) == -1) + if (do_file(agent_fd, deleting, key_only, + argv[i]) == -1) ret = 1; } } clear_pass(); done: - ssh_close_authentication_connection(ac); + ssh_close_authentication_socket(agent_fd); return ret; } diff --git a/crypto/openssh/ssh-agent.0 b/crypto/openssh/ssh-agent.0 deleted file mode 100644 index c11523d..0000000 --- a/crypto/openssh/ssh-agent.0 +++ /dev/null @@ -1,128 +0,0 @@ -SSH-AGENT(1) OpenBSD Reference Manual SSH-AGENT(1) - -NAME - ssh-agent - authentication agent - -SYNOPSIS - ssh-agent [-c | -s] [-d] [-a bind_address] [-t life] [command [arg ...]] - ssh-agent [-c | -s] -k - -DESCRIPTION - ssh-agent is a program to hold private keys used for public key - authentication (RSA, DSA, ECDSA, ED25519). The idea is that ssh-agent is - started in the beginning of an X-session or a login session, and all - other windows or programs are started as clients to the ssh-agent - program. Through use of environment variables the agent can be located - and automatically used for authentication when logging in to other - machines using ssh(1). - - The options are as follows: - - -a bind_address - Bind the agent to the UNIX-domain socket bind_address. The - default is $TMPDIR/ssh-XXXXXXXXXX/agent.. - - -c Generate C-shell commands on stdout. This is the default if - SHELL looks like it's a csh style of shell. - - -d Debug mode. When this option is specified ssh-agent will not - fork. - - -k Kill the current agent (given by the SSH_AGENT_PID environment - variable). - - -s Generate Bourne shell commands on stdout. This is the default if - SHELL does not look like it's a csh style of shell. - - -t life - Set a default value for the maximum lifetime of identities added - to the agent. The lifetime may be specified in seconds or in a - time format specified in sshd_config(5). A lifetime specified - for an identity with ssh-add(1) overrides this value. Without - this option the default maximum lifetime is forever. - - If a commandline is given, this is executed as a subprocess of the agent. - When the command dies, so does the agent. - - The agent initially does not have any private keys. Keys are added using - ssh-add(1). When executed without arguments, ssh-add(1) adds the files - ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and - ~/.ssh/identity. If the identity has a passphrase, ssh-add(1) asks for - the passphrase on the terminal if it has one or from a small X11 program - if running under X11. If neither of these is the case then the - authentication will fail. It then sends the identity to the agent. - Several identities can be stored in the agent; the agent can - automatically use any of these identities. ssh-add -l displays the - identities currently held by the agent. - - The idea is that the agent is run in the user's local PC, laptop, or - terminal. Authentication data need not be stored on any other machine, - and authentication passphrases never go over the network. However, the - connection to the agent is forwarded over SSH remote logins, and the user - can thus use the privileges given by the identities anywhere in the - network in a secure way. - - There are two main ways to get an agent set up: The first is that the - agent starts a new subcommand into which some environment variables are - exported, eg ssh-agent xterm &. The second is that the agent prints the - needed shell commands (either sh(1) or csh(1) syntax can be generated) - which can be evaluated in the calling shell, eg eval `ssh-agent -s` for - Bourne-type shells such as sh(1) or ksh(1) and eval `ssh-agent -c` for - csh(1) and derivatives. - - Later ssh(1) looks at these variables and uses them to establish a - connection to the agent. - - The agent will never send a private key over its request channel. - Instead, operations that require a private key will be performed by the - agent, and the result will be returned to the requester. This way, - private keys are not exposed to clients using the agent. - - A UNIX-domain socket is created and the name of this socket is stored in - the SSH_AUTH_SOCK environment variable. The socket is made accessible - only to the current user. This method is easily abused by root or - another instance of the same user. - - The SSH_AGENT_PID environment variable holds the agent's process ID. - - The agent exits automatically when the command given on the command line - terminates. - -FILES - ~/.ssh/identity - Contains the protocol version 1 RSA authentication identity of - the user. - - ~/.ssh/id_dsa - Contains the protocol version 2 DSA authentication identity of - the user. - - ~/.ssh/id_ecdsa - Contains the protocol version 2 ECDSA authentication identity of - the user. - - ~/.ssh/id_ed25519 - Contains the protocol version 2 ED25519 authentication identity - of the user. - - ~/.ssh/id_rsa - Contains the protocol version 2 RSA authentication identity of - the user. - - $TMPDIR/ssh-XXXXXXXXXX/agent. - UNIX-domain sockets used to contain the connection to the - authentication agent. These sockets should only be readable by - the owner. The sockets should get automatically removed when the - agent exits. - -SEE ALSO - ssh(1), ssh-add(1), ssh-keygen(1), sshd(8) - -AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by - Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. - -OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/ssh-agent.1 b/crypto/openssh/ssh-agent.1 index 90b8fe5..b5e6b0e 100644 --- a/crypto/openssh/ssh-agent.1 +++ b/crypto/openssh/ssh-agent.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.54 2013/12/07 11:58:46 naddy Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.59 2015/04/24 06:26:49 jmc Exp $ .\" $FreeBSD$ .\" .\" Author: Tatu Ylonen @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: December 7 2013 $ +.Dd $Mdocdate: April 24 2015 $ .Dt SSH-AGENT 1 .Os .Sh NAME @@ -44,8 +44,9 @@ .Sh SYNOPSIS .Nm ssh-agent .Op Fl c | s -.Op Fl dx +.Op Fl Ddx .Op Fl a Ar bind_address +.Op Fl E Ar fingerprint_hash .Op Fl t Ar life .Op Ar command Op Ar arg ... .Nm ssh-agent @@ -54,10 +55,9 @@ .Sh DESCRIPTION .Nm is a program to hold private keys used for public key authentication -(RSA, DSA, ECDSA, ED25519). -The idea is that +(RSA, DSA, ECDSA, Ed25519). .Nm -is started in the beginning of an X-session or a login session, and +is usually started in the beginning of an X-session or a login session, and all other windows or programs are started as clients to the ssh-agent program. Through use of environment variables the agent can be located @@ -65,6 +65,19 @@ and automatically used for authentication when logging in to other machines using .Xr ssh 1 . .Pp +The agent initially does not have any private keys. +Keys are added using +.Xr ssh-add 1 . +Multiple identities may be stored in +.Nm +concurrently and +.Xr ssh 1 +will automatically use them if present. +.Xr ssh-add 1 +is also used to remove keys from +.Nm +and to query the keys that are held in one. +.Pp The options are as follows: .Bl -tag -width Ds .It Fl a Ar bind_address @@ -80,11 +93,24 @@ Generate C-shell commands on This is the default if .Ev SHELL looks like it's a csh style of shell. +.It Fl D +Foreground mode. +When this option is specified +.Nm +will not fork. .It Fl d Debug mode. When this option is specified .Nm -will not fork. +will not fork and will write debug information to standard error. +.It Fl E Ar fingerprint_hash +Specifies the hash algorithm used when displaying key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . .It Fl k Kill the current agent (given by the .Ev SSH_AGENT_PID @@ -110,29 +136,6 @@ Exit after the last client has disconnected. If a commandline is given, this is executed as a subprocess of the agent. When the command dies, so does the agent. .Pp -The agent initially does not have any private keys. -Keys are added using -.Xr ssh-add 1 . -When executed without arguments, -.Xr ssh-add 1 -adds the files -.Pa ~/.ssh/id_rsa , -.Pa ~/.ssh/id_dsa , -.Pa ~/.ssh/id_ecdsa , -.Pa ~/.ssh/id_ed25519 -and -.Pa ~/.ssh/identity . -If the identity has a passphrase, -.Xr ssh-add 1 -asks for the passphrase on the terminal if it has one or from a small X11 -program if running under X11. -If neither of these is the case then the authentication will fail. -It then sends the identity to the agent. -Several identities can be stored in the -agent; the agent can automatically use any of these identities. -.Ic ssh-add -l -displays the identities currently held by the agent. -.Pp The idea is that the agent is run in the user's local PC, laptop, or terminal. Authentication data need not be stored on any other @@ -188,16 +191,6 @@ The agent exits automatically when the command given on the command line terminates. .Sh FILES .Bl -tag -width Ds -.It Pa ~/.ssh/identity -Contains the protocol version 1 RSA authentication identity of the user. -.It Pa ~/.ssh/id_dsa -Contains the protocol version 2 DSA authentication identity of the user. -.It Pa ~/.ssh/id_ecdsa -Contains the protocol version 2 ECDSA authentication identity of the user. -.It Pa ~/.ssh/id_ed25519 -Contains the protocol version 2 ED25519 authentication identity of the user. -.It Pa ~/.ssh/id_rsa -Contains the protocol version 2 RSA authentication identity of the user. .It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt .Ux Ns -domain sockets used to contain the connection to the authentication agent. diff --git a/crypto/openssh/ssh-agent.c b/crypto/openssh/ssh-agent.c index 9c3e4cc..52293db 100644 --- a/crypto/openssh/ssh-agent.c +++ b/crypto/openssh/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.183 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.204 2015/07/08 20:24:02 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -37,6 +37,7 @@ #include "includes.h" __RCSID("$FreeBSD$"); +#include /* MIN MAX */ #include #include #include @@ -50,11 +51,14 @@ __RCSID("$FreeBSD$"); #endif #include "openbsd-compat/sys-queue.h" +#ifdef WITH_OPENSSL #include #include "openbsd-compat/openssl-compat.h" +#endif #include #include +#include #ifdef HAVE_PATHS_H # include #endif @@ -65,17 +69,21 @@ __RCSID("$FreeBSD$"); #include #include #include +#ifdef HAVE_UTIL_H +# include +#endif #include "xmalloc.h" #include "ssh.h" #include "rsa.h" -#include "buffer.h" -#include "key.h" +#include "sshbuf.h" +#include "sshkey.h" #include "authfd.h" #include "compat.h" #include "log.h" #include "misc.h" #include "digest.h" +#include "ssherr.h" #ifdef ENABLE_PKCS11 #include "ssh-pkcs11.h" @@ -94,9 +102,9 @@ typedef enum { typedef struct { int fd; sock_type type; - Buffer input; - Buffer output; - Buffer request; + struct sshbuf *input; + struct sshbuf *output; + struct sshbuf *request; } SocketEntry; u_int sockets_alloc = 0; @@ -104,7 +112,7 @@ SocketEntry *sockets = NULL; typedef struct identity { TAILQ_ENTRY(identity) next; - Key *key; + struct sshkey *key; char *comment; char *provider; time_t death; @@ -125,19 +133,28 @@ int max_fd = 0; pid_t parent_pid = -1; time_t parent_alive_interval = 0; +/* pid of process for which cleanup_socket is applicable */ +pid_t cleanup_pid = 0; + /* pathname and directory for AUTH_SOCKET */ -char socket_name[MAXPATHLEN]; -char socket_dir[MAXPATHLEN]; +char socket_name[PATH_MAX]; +char socket_dir[PATH_MAX]; /* locking */ +#define LOCK_SIZE 32 +#define LOCK_SALT_SIZE 16 +#define LOCK_ROUNDS 1 int locked = 0; -char *lock_passwd = NULL; +char lock_passwd[LOCK_SIZE]; +char lock_salt[LOCK_SALT_SIZE]; extern char *__progname; /* Default lifetime in seconds (0 == forever) */ static long lifetime = 0; +static int fingerprint_hash = SSH_FP_HASH_DEFAULT; + /* * Client connection count; incremented in new_socket() and decremented in * close_socket(). When it reaches 0, ssh-agent will exit. Since it is @@ -161,9 +178,9 @@ close_socket(SocketEntry *e) close(e->fd); e->fd = -1; e->type = AUTH_UNUSED; - buffer_free(&e->input); - buffer_free(&e->output); - buffer_free(&e->request); + sshbuf_free(e->input); + sshbuf_free(e->output); + sshbuf_free(e->request); if (last) cleanup_exit(0); } @@ -191,7 +208,7 @@ idtab_lookup(int version) static void free_identity(Identity *id) { - key_free(id->key); + sshkey_free(id->key); free(id->provider); free(id->comment); free(id); @@ -199,13 +216,13 @@ free_identity(Identity *id) /* return matching private key for given public key */ static Identity * -lookup_identity(Key *key, int version) +lookup_identity(struct sshkey *key, int version) { Identity *id; Idtab *tab = idtab_lookup(version); TAILQ_FOREACH(id, &tab->idlist, next) { - if (key_equal(key, id->key)) + if (sshkey_equal(key, id->key)) return (id); } return (NULL); @@ -218,8 +235,9 @@ confirm_key(Identity *id) char *p; int ret = -1; - p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); - if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", + p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT); + if (p != NULL && + ask_permission("Allow use of key %s?\nKey fingerprint %s.", id->comment, p)) ret = 0; free(p); @@ -227,37 +245,68 @@ confirm_key(Identity *id) return (ret); } +static void +send_status(SocketEntry *e, int success) +{ + int r; + + if ((r = sshbuf_put_u32(e->output, 1)) != 0 || + (r = sshbuf_put_u8(e->output, success ? + SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); +} + /* send list of supported public keys to 'client' */ static void process_request_identities(SocketEntry *e, int version) { Idtab *tab = idtab_lookup(version); Identity *id; - Buffer msg; - - buffer_init(&msg); - buffer_put_char(&msg, (version == 1) ? - SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); - buffer_put_int(&msg, tab->nentries); + struct sshbuf *msg; + int r; + + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, (version == 1) ? + SSH_AGENT_RSA_IDENTITIES_ANSWER : + SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || + (r = sshbuf_put_u32(msg, tab->nentries)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); TAILQ_FOREACH(id, &tab->idlist, next) { if (id->key->type == KEY_RSA1) { - buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); - buffer_put_bignum(&msg, id->key->rsa->e); - buffer_put_bignum(&msg, id->key->rsa->n); +#ifdef WITH_SSH1 + if ((r = sshbuf_put_u32(msg, + BN_num_bits(id->key->rsa->n))) != 0 || + (r = sshbuf_put_bignum1(msg, + id->key->rsa->e)) != 0 || + (r = sshbuf_put_bignum1(msg, + id->key->rsa->n)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); +#endif } else { u_char *blob; - u_int blen; - key_to_blob(id->key, &blob, &blen); - buffer_put_string(&msg, blob, blen); + size_t blen; + + if ((r = sshkey_to_blob(id->key, &blob, &blen)) != 0) { + error("%s: sshkey_to_blob: %s", __func__, + ssh_err(r)); + continue; + } + if ((r = sshbuf_put_string(msg, blob, blen)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); free(blob); } - buffer_put_cstring(&msg, id->comment); + if ((r = sshbuf_put_cstring(msg, id->comment)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } - buffer_put_int(&e->output, buffer_len(&msg)); - buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); - buffer_free(&msg); + if ((r = sshbuf_put_stringb(e->output, msg)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + sshbuf_free(msg); } +#ifdef WITH_SSH1 /* ssh1 only */ static void process_authentication_challenge1(SocketEntry *e) @@ -266,40 +315,48 @@ process_authentication_challenge1(SocketEntry *e) u_int response_type; BIGNUM *challenge; Identity *id; - int i, len; - Buffer msg; + int r, len; + struct sshbuf *msg; struct ssh_digest_ctx *md; - Key *key; + struct sshkey *key; - buffer_init(&msg); - key = key_new(KEY_RSA1); + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((key = sshkey_new(KEY_RSA1)) == NULL) + fatal("%s: sshkey_new failed", __func__); if ((challenge = BN_new()) == NULL) - fatal("process_authentication_challenge1: BN_new failed"); + fatal("%s: BN_new failed", __func__); - (void) buffer_get_int(&e->request); /* ignored */ - buffer_get_bignum(&e->request, key->rsa->e); - buffer_get_bignum(&e->request, key->rsa->n); - buffer_get_bignum(&e->request, challenge); + if ((r = sshbuf_get_u32(e->request, NULL)) != 0 || /* ignored */ + (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || + (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0 || + (r = sshbuf_get_bignum1(e->request, challenge))) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* Only protocol 1.1 is supported */ - if (buffer_len(&e->request) == 0) + if (sshbuf_len(e->request) == 0) goto failure; - buffer_get(&e->request, session_id, 16); - response_type = buffer_get_int(&e->request); + if ((r = sshbuf_get(e->request, session_id, sizeof(session_id))) != 0 || + (r = sshbuf_get_u32(e->request, &response_type)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (response_type != 1) goto failure; id = lookup_identity(key, 1); if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { - Key *private = id->key; + struct sshkey *private = id->key; /* Decrypt the challenge using the private key. */ - if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) - goto failure; + if ((r = rsa_private_decrypt(challenge, challenge, + private->rsa) != 0)) { + fatal("%s: rsa_public_encrypt: %s", __func__, + ssh_err(r)); + goto failure; /* XXX ? */ + } - /* The response is MD5 of decrypted challenge plus session id. */ + /* The response is MD5 of decrypted challenge plus session id */ len = BN_num_bytes(challenge); if (len <= 0 || len > 32) { - logit("process_authentication_challenge: bad challenge length %d", len); + logit("%s: bad challenge length %d", __func__, len); goto failure; } memset(buf, 0, 32); @@ -312,92 +369,118 @@ process_authentication_challenge1(SocketEntry *e) ssh_digest_free(md); /* Send the response. */ - buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); - for (i = 0; i < 16; i++) - buffer_put_char(&msg, mdbuf[i]); + if ((r = sshbuf_put_u8(msg, SSH_AGENT_RSA_RESPONSE)) != 0 || + (r = sshbuf_put(msg, mdbuf, sizeof(mdbuf))) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); goto send; } -failure: + failure: /* Unknown identity or protocol error. Send failure. */ - buffer_put_char(&msg, SSH_AGENT_FAILURE); -send: - buffer_put_int(&e->output, buffer_len(&msg)); - buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); - key_free(key); + if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + send: + if ((r = sshbuf_put_stringb(e->output, msg)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + sshkey_free(key); BN_clear_free(challenge); - buffer_free(&msg); + sshbuf_free(msg); } +#endif /* ssh2 only */ static void process_sign_request2(SocketEntry *e) { u_char *blob, *data, *signature = NULL; - u_int blen, dlen, slen = 0; - extern int datafellows; - int odatafellows; - int ok = -1, flags; - Buffer msg; - Key *key; - - datafellows = 0; - - blob = buffer_get_string(&e->request, &blen); - data = buffer_get_string(&e->request, &dlen); - - flags = buffer_get_int(&e->request); - odatafellows = datafellows; + size_t blen, dlen, slen = 0; + u_int compat = 0, flags; + int r, ok = -1; + struct sshbuf *msg; + struct sshkey *key; + struct identity *id; + + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0 || + (r = sshbuf_get_string(e->request, &data, &dlen)) != 0 || + (r = sshbuf_get_u32(e->request, &flags)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (flags & SSH_AGENT_OLD_SIGNATURE) - datafellows = SSH_BUG_SIGBLOB; - - key = key_from_blob(blob, blen); - if (key != NULL) { - Identity *id = lookup_identity(key, 2); - if (id != NULL && (!id->confirm || confirm_key(id) == 0)) - ok = key_sign(id->key, &signature, &slen, data, dlen); - key_free(key); + compat = SSH_BUG_SIGBLOB; + if ((r = sshkey_from_blob(blob, blen, &key)) != 0) { + error("%s: cannot parse key blob: %s", __func__, ssh_err(ok)); + goto send; } - buffer_init(&msg); - if (ok == 0) { - buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); - buffer_put_string(&msg, signature, slen); - } else { - buffer_put_char(&msg, SSH_AGENT_FAILURE); + if ((id = lookup_identity(key, 2)) == NULL) { + verbose("%s: %s key not found", __func__, sshkey_type(key)); + goto send; } - buffer_put_int(&e->output, buffer_len(&msg)); - buffer_append(&e->output, buffer_ptr(&msg), - buffer_len(&msg)); - buffer_free(&msg); + if (id->confirm && confirm_key(id) != 0) { + verbose("%s: user refused key", __func__); + goto send; + } + if ((r = sshkey_sign(id->key, &signature, &slen, + data, dlen, compat)) != 0) { + error("%s: sshkey_sign: %s", __func__, ssh_err(ok)); + goto send; + } + /* Success */ + ok = 0; + send: + sshkey_free(key); + if (ok == 0) { + if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || + (r = sshbuf_put_string(msg, signature, slen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + if ((r = sshbuf_put_stringb(e->output, msg)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + sshbuf_free(msg); free(data); free(blob); free(signature); - datafellows = odatafellows; } /* shared */ static void process_remove_identity(SocketEntry *e, int version) { - u_int blen, bits; - int success = 0; - Key *key = NULL; + size_t blen; + int r, success = 0; + struct sshkey *key = NULL; u_char *blob; +#ifdef WITH_SSH1 + u_int bits; +#endif /* WITH_SSH1 */ switch (version) { +#ifdef WITH_SSH1 case 1: - key = key_new(KEY_RSA1); - bits = buffer_get_int(&e->request); - buffer_get_bignum(&e->request, key->rsa->e); - buffer_get_bignum(&e->request, key->rsa->n); - - if (bits != key_size(key)) - logit("Warning: identity keysize mismatch: actual %u, announced %u", - key_size(key), bits); + if ((key = sshkey_new(KEY_RSA1)) == NULL) { + error("%s: sshkey_new failed", __func__); + return; + } + if ((r = sshbuf_get_u32(e->request, &bits)) != 0 || + (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || + (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + if (bits != sshkey_size(key)) + logit("Warning: identity keysize mismatch: " + "actual %u, announced %u", + sshkey_size(key), bits); break; +#endif /* WITH_SSH1 */ case 2: - blob = buffer_get_string(&e->request, &blen); - key = key_from_blob(blob, blen); + if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if ((r = sshkey_from_blob(blob, blen, &key)) != 0) + error("%s: sshkey_from_blob failed: %s", + __func__, ssh_err(r)); free(blob); break; } @@ -421,11 +504,9 @@ process_remove_identity(SocketEntry *e, int version) tab->nentries--; success = 1; } - key_free(key); + sshkey_free(key); } - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, - success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); + send_status(e, success); } static void @@ -445,8 +526,7 @@ process_remove_all_identities(SocketEntry *e, int version) tab->nentries = 0; /* Send success. */ - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, SSH_AGENT_SUCCESS); + send_status(e, 1); } /* removes expired keys and returns number of seconds until the next expiry */ @@ -480,68 +560,106 @@ reaper(void) return (deadline - now); } +/* + * XXX this and the corresponding serialisation function probably belongs + * in key.c + */ +#ifdef WITH_SSH1 +static int +agent_decode_rsa1(struct sshbuf *m, struct sshkey **kp) +{ + struct sshkey *k = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + + *kp = NULL; + if ((k = sshkey_new_private(KEY_RSA1)) == NULL) + return SSH_ERR_ALLOC_FAIL; + + if ((r = sshbuf_get_u32(m, NULL)) != 0 || /* ignored */ + (r = sshbuf_get_bignum1(m, k->rsa->n)) != 0 || + (r = sshbuf_get_bignum1(m, k->rsa->e)) != 0 || + (r = sshbuf_get_bignum1(m, k->rsa->d)) != 0 || + (r = sshbuf_get_bignum1(m, k->rsa->iqmp)) != 0 || + /* SSH1 and SSL have p and q swapped */ + (r = sshbuf_get_bignum1(m, k->rsa->q)) != 0 || /* p */ + (r = sshbuf_get_bignum1(m, k->rsa->p)) != 0) /* q */ + goto out; + + /* Generate additional parameters */ + if ((r = rsa_generate_additional_parameters(k->rsa)) != 0) + goto out; + /* enable blinding */ + if (RSA_blinding_on(k->rsa, NULL) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + + r = 0; /* success */ + out: + if (r == 0) + *kp = k; + else + sshkey_free(k); + return r; +} +#endif /* WITH_SSH1 */ + static void process_add_identity(SocketEntry *e, int version) { Idtab *tab = idtab_lookup(version); Identity *id; - int type, success = 0, confirm = 0; - char *comment; + int success = 0, confirm = 0; + u_int seconds; + char *comment = NULL; time_t death = 0; - Key *k = NULL; + struct sshkey *k = NULL; + u_char ctype; + int r = SSH_ERR_INTERNAL_ERROR; switch (version) { +#ifdef WITH_SSH1 case 1: - k = key_new_private(KEY_RSA1); - (void) buffer_get_int(&e->request); /* ignored */ - buffer_get_bignum(&e->request, k->rsa->n); - buffer_get_bignum(&e->request, k->rsa->e); - buffer_get_bignum(&e->request, k->rsa->d); - buffer_get_bignum(&e->request, k->rsa->iqmp); - - /* SSH and SSL have p and q swapped */ - buffer_get_bignum(&e->request, k->rsa->q); /* p */ - buffer_get_bignum(&e->request, k->rsa->p); /* q */ - - /* Generate additional parameters */ - rsa_generate_additional_parameters(k->rsa); - - /* enable blinding */ - if (RSA_blinding_on(k->rsa, NULL) != 1) { - error("process_add_identity: RSA_blinding_on failed"); - key_free(k); - goto send; - } + r = agent_decode_rsa1(e->request, &k); break; +#endif /* WITH_SSH1 */ case 2: - k = key_private_deserialize(&e->request); - if (k == NULL) { - buffer_clear(&e->request); - goto send; - } + r = sshkey_private_deserialize(e->request, &k); break; } - comment = buffer_get_string(&e->request, NULL); - if (k == NULL) { - free(comment); - goto send; + if (r != 0 || k == NULL || + (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { + error("%s: decode private key: %s", __func__, ssh_err(r)); + goto err; } - while (buffer_len(&e->request)) { - switch ((type = buffer_get_char(&e->request))) { + + while (sshbuf_len(e->request)) { + if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) { + error("%s: buffer error: %s", __func__, ssh_err(r)); + goto err; + } + switch (ctype) { case SSH_AGENT_CONSTRAIN_LIFETIME: - death = monotime() + buffer_get_int(&e->request); + if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) { + error("%s: bad lifetime constraint: %s", + __func__, ssh_err(r)); + goto err; + } + death = monotime() + seconds; break; case SSH_AGENT_CONSTRAIN_CONFIRM: confirm = 1; break; default: - error("process_add_identity: " - "Unknown constraint type %d", type); + error("%s: Unknown constraint %d", __func__, ctype); + err: + sshbuf_reset(e->request); free(comment); - key_free(k); + sshkey_free(k); goto send; } } + success = 1; if (lifetime && !death) death = monotime() + lifetime; @@ -552,58 +670,79 @@ process_add_identity(SocketEntry *e, int version) /* Increment the number of identities. */ tab->nentries++; } else { - key_free(k); + sshkey_free(k); free(id->comment); } id->comment = comment; id->death = death; id->confirm = confirm; send: - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, - success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); + send_status(e, success); } /* XXX todo: encrypt sensitive data with passphrase */ static void process_lock_agent(SocketEntry *e, int lock) { - int success = 0; - char *passwd; - - passwd = buffer_get_string(&e->request, NULL); - if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { - locked = 0; - explicit_bzero(lock_passwd, strlen(lock_passwd)); - free(lock_passwd); - lock_passwd = NULL; - success = 1; + int r, success = 0, delay; + char *passwd, passwdhash[LOCK_SIZE]; + static u_int fail_count = 0; + size_t pwlen; + + if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (pwlen == 0) { + debug("empty password not supported"); + } else if (locked && !lock) { + if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), + passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0) + fatal("bcrypt_pbkdf"); + if (timingsafe_bcmp(passwdhash, lock_passwd, LOCK_SIZE) == 0) { + debug("agent unlocked"); + locked = 0; + fail_count = 0; + explicit_bzero(lock_passwd, sizeof(lock_passwd)); + success = 1; + } else { + /* delay in 0.1s increments up to 10s */ + if (fail_count < 100) + fail_count++; + delay = 100000 * fail_count; + debug("unlock failed, delaying %0.1lf seconds", + (double)delay/1000000); + usleep(delay); + } + explicit_bzero(passwdhash, sizeof(passwdhash)); } else if (!locked && lock) { + debug("agent locked"); locked = 1; - lock_passwd = xstrdup(passwd); + arc4random_buf(lock_salt, sizeof(lock_salt)); + if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), + lock_passwd, sizeof(lock_passwd), LOCK_ROUNDS) < 0) + fatal("bcrypt_pbkdf"); success = 1; } - explicit_bzero(passwd, strlen(passwd)); + explicit_bzero(passwd, pwlen); free(passwd); - - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, - success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); + send_status(e, success); } static void no_identities(SocketEntry *e, u_int type) { - Buffer msg; + struct sshbuf *msg; + int r; - buffer_init(&msg); - buffer_put_char(&msg, + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_u8(msg, (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? - SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); - buffer_put_int(&msg, 0); - buffer_put_int(&e->output, buffer_len(&msg)); - buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); - buffer_free(&msg); + SSH_AGENT_RSA_IDENTITIES_ANSWER : + SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || + (r = sshbuf_put_u32(msg, 0)) != 0 || + (r = sshbuf_put_stringb(e->output, msg)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + sshbuf_free(msg); } #ifdef ENABLE_PKCS11 @@ -611,19 +750,27 @@ static void process_add_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin; - int i, type, version, count = 0, success = 0, confirm = 0; + int r, i, version, count = 0, success = 0, confirm = 0; + u_int seconds; time_t death = 0; - Key **keys = NULL, *k; + u_char type; + struct sshkey **keys = NULL, *k; Identity *id; Idtab *tab; - provider = buffer_get_string(&e->request, NULL); - pin = buffer_get_string(&e->request, NULL); + if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || + (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - while (buffer_len(&e->request)) { - switch ((type = buffer_get_char(&e->request))) { + while (sshbuf_len(e->request)) { + if ((r = sshbuf_get_u8(e->request, &type)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + switch (type) { case SSH_AGENT_CONSTRAIN_LIFETIME: - death = monotime() + buffer_get_int(&e->request); + if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); + death = monotime() + seconds; break; case SSH_AGENT_CONSTRAIN_CONFIRM: confirm = 1; @@ -653,7 +800,7 @@ process_add_smartcard_key(SocketEntry *e) tab->nentries++; success = 1; } else { - key_free(k); + sshkey_free(k); } keys[i] = NULL; } @@ -661,21 +808,20 @@ send: free(pin); free(provider); free(keys); - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, - success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); + send_status(e, success); } static void process_remove_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin = NULL; - int version, success = 0; + int r, version, success = 0; Identity *id, *nxt; Idtab *tab; - provider = buffer_get_string(&e->request, NULL); - pin = buffer_get_string(&e->request, NULL); + if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || + (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(pin); for (version = 1; version < 3; version++) { @@ -698,9 +844,7 @@ process_remove_smartcard_key(SocketEntry *e) error("process_remove_smartcard_key:" " pkcs11_del_provider failed"); free(provider); - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, - success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); + send_status(e, success); } #endif /* ENABLE_PKCS11 */ @@ -709,30 +853,31 @@ process_remove_smartcard_key(SocketEntry *e) static void process_message(SocketEntry *e) { - u_int msg_len, type; - u_char *cp; + u_int msg_len; + u_char type; + const u_char *cp; + int r; - if (buffer_len(&e->input) < 5) + if (sshbuf_len(e->input) < 5) return; /* Incomplete message. */ - cp = buffer_ptr(&e->input); - msg_len = get_u32(cp); + cp = sshbuf_ptr(e->input); + msg_len = PEEK_U32(cp); if (msg_len > 256 * 1024) { close_socket(e); return; } - if (buffer_len(&e->input) < msg_len + 4) + if (sshbuf_len(e->input) < msg_len + 4) return; /* move the current input to e->request */ - buffer_consume(&e->input, 4); - buffer_clear(&e->request); - buffer_append(&e->request, buffer_ptr(&e->input), msg_len); - buffer_consume(&e->input, msg_len); - type = buffer_get_char(&e->request); + sshbuf_reset(e->request); + if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 || + (r = sshbuf_get_u8(e->request, &type)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* check wheter agent is locked */ if (locked && type != SSH_AGENTC_UNLOCK) { - buffer_clear(&e->request); + sshbuf_reset(e->request); switch (type) { case SSH_AGENTC_REQUEST_RSA_IDENTITIES: case SSH2_AGENTC_REQUEST_IDENTITIES: @@ -741,8 +886,7 @@ process_message(SocketEntry *e) break; default: /* send a fail message for all other request types */ - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, SSH_AGENT_FAILURE); + send_status(e, 0); } return; } @@ -753,6 +897,7 @@ process_message(SocketEntry *e) case SSH_AGENTC_UNLOCK: process_lock_agent(e, type == SSH_AGENTC_LOCK); break; +#ifdef WITH_SSH1 /* ssh1 */ case SSH_AGENTC_RSA_CHALLENGE: process_authentication_challenge1(e); @@ -767,8 +912,9 @@ process_message(SocketEntry *e) case SSH_AGENTC_REMOVE_RSA_IDENTITY: process_remove_identity(e, 1); break; +#endif case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: - process_remove_all_identities(e, 1); + process_remove_all_identities(e, 1); /* safe for !WITH_SSH1 */ break; /* ssh2 */ case SSH2_AGENTC_SIGN_REQUEST: @@ -799,9 +945,8 @@ process_message(SocketEntry *e) default: /* Unknown message. Respond with failure. */ error("Unknown message %d", type); - buffer_clear(&e->request); - buffer_put_int(&e->output, 1); - buffer_put_char(&e->output, SSH_AGENT_FAILURE); + sshbuf_reset(e->request); + send_status(e, 0); break; } } @@ -823,22 +968,28 @@ new_socket(sock_type type, int fd) for (i = 0; i < sockets_alloc; i++) if (sockets[i].type == AUTH_UNUSED) { sockets[i].fd = fd; - buffer_init(&sockets[i].input); - buffer_init(&sockets[i].output); - buffer_init(&sockets[i].request); + if ((sockets[i].input = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((sockets[i].output = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((sockets[i].request = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); sockets[i].type = type; return; } old_alloc = sockets_alloc; new_alloc = sockets_alloc + 10; - sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0])); + sockets = xreallocarray(sockets, new_alloc, sizeof(sockets[0])); for (i = old_alloc; i < new_alloc; i++) sockets[i].type = AUTH_UNUSED; sockets_alloc = new_alloc; sockets[old_alloc].fd = fd; - buffer_init(&sockets[old_alloc].input); - buffer_init(&sockets[old_alloc].output); - buffer_init(&sockets[old_alloc].request); + if ((sockets[old_alloc].input = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((sockets[old_alloc].output = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((sockets[old_alloc].request = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); sockets[old_alloc].type = type; } @@ -884,7 +1035,7 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, case AUTH_SOCKET: case AUTH_CONNECTION: FD_SET(sockets[i].fd, *fdrp); - if (buffer_len(&sockets[i].output) > 0) + if (sshbuf_len(sockets[i].output) > 0) FD_SET(sockets[i].fd, *fdwp); break; default: @@ -911,7 +1062,7 @@ after_select(fd_set *readset, fd_set *writeset) struct sockaddr_un sunaddr; socklen_t slen; char buf[1024]; - int len, sock; + int len, sock, r; u_int i, orig_alloc; uid_t euid; gid_t egid; @@ -947,11 +1098,11 @@ after_select(fd_set *readset, fd_set *writeset) } break; case AUTH_CONNECTION: - if (buffer_len(&sockets[i].output) > 0 && + if (sshbuf_len(sockets[i].output) > 0 && FD_ISSET(sockets[i].fd, writeset)) { len = write(sockets[i].fd, - buffer_ptr(&sockets[i].output), - buffer_len(&sockets[i].output)); + sshbuf_ptr(sockets[i].output), + sshbuf_len(sockets[i].output)); if (len == -1 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) @@ -960,7 +1111,10 @@ after_select(fd_set *readset, fd_set *writeset) close_socket(&sockets[i]); break; } - buffer_consume(&sockets[i].output, len); + if ((r = sshbuf_consume(sockets[i].output, + len)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); } if (FD_ISSET(sockets[i].fd, readset)) { len = read(sockets[i].fd, buf, sizeof(buf)); @@ -972,7 +1126,11 @@ after_select(fd_set *readset, fd_set *writeset) close_socket(&sockets[i]); break; } - buffer_append(&sockets[i].input, buf, len); + if ((r = sshbuf_put(sockets[i].input, + buf, len)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); + explicit_bzero(buf, sizeof(buf)); process_message(&sockets[i]); } break; @@ -984,6 +1142,9 @@ after_select(fd_set *readset, fd_set *writeset) static void cleanup_socket(void) { + if (cleanup_pid != 0 && getpid() != cleanup_pid) + return; + debug("%s: cleanup", __func__); if (socket_name[0]) unlink(socket_name); if (socket_dir[0]) @@ -1025,15 +1186,10 @@ check_parent_exists(void) static void usage(void) { - fprintf(stderr, "usage: %s [options] [command [arg ...]]\n", - __progname); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " -c Generate C-shell commands on stdout.\n"); - fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n"); - fprintf(stderr, " -k Kill the current agent.\n"); - fprintf(stderr, " -d Debug mode.\n"); - fprintf(stderr, " -a socket Bind agent socket to given name.\n"); - fprintf(stderr, " -t life Default identity lifetime (seconds).\n"); + fprintf(stderr, + "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n" + " [-t life] [command [arg ...]]\n" + " ssh-agent [-c | -s] -k\n"); fprintf(stderr, " -x Exit when the last client disconnects.\n"); exit(1); } @@ -1041,22 +1197,21 @@ usage(void) int main(int ac, char **av) { - int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; + int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0; int sock, fd, ch, result, saved_errno; u_int nalloc; char *shell, *format, *pidstr, *agentsocket = NULL; fd_set *readsetp = NULL, *writesetp = NULL; - struct sockaddr_un sunaddr; #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif - int prev_mask; extern int optind; extern char *optarg; pid_t pid; char pidstrbuf[1 + 3 * sizeof pid]; struct timeval *tvp = NULL; size_t len; + mode_t prev_mask; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -1071,13 +1226,20 @@ main(int ac, char **av) prctl(PR_SET_DUMPABLE, 0); #endif +#ifdef WITH_OPENSSL OpenSSL_add_all_algorithms(); +#endif __progname = ssh_get_progname(av[0]); seed_rng(); - while ((ch = getopt(ac, av, "cdksa:t:x")) != -1) { + while ((ch = getopt(ac, av, "cDdksE:a:t:x")) != -1) { switch (ch) { + case 'E': + fingerprint_hash = ssh_digest_alg_by_name(optarg); + if (fingerprint_hash == -1) + fatal("Invalid hash algorithm \"%s\"", optarg); + break; case 'c': if (s_flag) usage(); @@ -1092,10 +1254,15 @@ main(int ac, char **av) s_flag++; break; case 'd': - if (d_flag) + if (d_flag || D_flag) usage(); d_flag++; break; + case 'D': + if (d_flag || D_flag) + usage(); + D_flag++; + break; case 'a': agentsocket = optarg; break; @@ -1115,7 +1282,7 @@ main(int ac, char **av) ac -= optind; av += optind; - if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) + if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag)) usage(); if (ac == 0 && !c_flag && !s_flag) { @@ -1171,34 +1338,23 @@ main(int ac, char **av) * Create socket early so it will exist before command gets run from * the parent. */ - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - perror("socket"); - *socket_name = '\0'; /* Don't unlink any existing file */ - cleanup_exit(1); - } - memset(&sunaddr, 0, sizeof(sunaddr)); - sunaddr.sun_family = AF_UNIX; - strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); prev_mask = umask(0177); - if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { - perror("bind"); + sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0); + if (sock < 0) { + /* XXX - unix_listener() calls error() not perror() */ *socket_name = '\0'; /* Don't unlink any existing file */ - umask(prev_mask); cleanup_exit(1); } umask(prev_mask); - if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { - perror("listen"); - cleanup_exit(1); - } /* * Fork, and have the parent execute the command, if any, or present * the socket data. The child continues as the authentication agent. */ - if (d_flag) { - log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1); + if (D_flag || d_flag) { + log_init(__progname, + d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO, + SYSLOG_FACILITY_AUTH, 1); format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, SSH_AUTHSOCKET_ENV_NAME); @@ -1260,6 +1416,8 @@ main(int ac, char **av) skip: + cleanup_pid = getpid(); + #ifdef ENABLE_PKCS11 pkcs11_init(0); #endif @@ -1268,7 +1426,7 @@ skip: parent_alive_interval = 10; idtab_init(); signal(SIGPIPE, SIG_IGN); - signal(SIGINT, d_flag ? cleanup_handler : SIG_IGN); + signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN); signal(SIGHUP, cleanup_handler); signal(SIGTERM, cleanup_handler); nalloc = 0; diff --git a/crypto/openssh/ssh-dss.c b/crypto/openssh/ssh-dss.c index 6b4abcb..8ed19d8 100644 --- a/crypto/openssh/ssh-dss.c +++ b/crypto/openssh/ssh-dss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-dss.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: ssh-dss.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -25,165 +25,198 @@ #include "includes.h" +#ifdef WITH_OPENSSL + #include #include +#include #include #include #include -#include "xmalloc.h" -#include "buffer.h" +#include "sshbuf.h" #include "compat.h" -#include "log.h" -#include "key.h" +#include "ssherr.h" #include "digest.h" +#define SSHKEY_INTERNAL +#include "sshkey.h" #define INTBLOB_LEN 20 #define SIGBLOB_LEN (2*INTBLOB_LEN) int -ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp, - const u_char *data, u_int datalen) +ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) { - DSA_SIG *sig; + DSA_SIG *sig = NULL; u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; - u_int rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); - Buffer b; - - if (key == NULL || key_type_plain(key->type) != KEY_DSA || - key->dsa == NULL) { - error("%s: no DSA key", __func__); - return -1; - } - - if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, - digest, sizeof(digest)) != 0) { - error("%s: ssh_digest_memory failed", __func__); - return -1; - } - - sig = DSA_do_sign(digest, dlen, key->dsa); - explicit_bzero(digest, sizeof(digest)); - - if (sig == NULL) { - error("ssh_dss_sign: sign failed"); - return -1; + size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); + struct sshbuf *b = NULL; + int ret = SSH_ERR_INVALID_ARGUMENT; + + if (lenp != NULL) + *lenp = 0; + if (sigp != NULL) + *sigp = NULL; + + if (key == NULL || key->dsa == NULL || + sshkey_type_plain(key->type) != KEY_DSA) + return SSH_ERR_INVALID_ARGUMENT; + if (dlen == 0) + return SSH_ERR_INTERNAL_ERROR; + + if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, + digest, sizeof(digest))) != 0) + goto out; + + if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } rlen = BN_num_bytes(sig->r); slen = BN_num_bytes(sig->s); if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { - error("bad sig size %u %u", rlen, slen); - DSA_SIG_free(sig); - return -1; + ret = SSH_ERR_INTERNAL_ERROR; + goto out; } explicit_bzero(sigblob, SIGBLOB_LEN); - BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); - BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); - DSA_SIG_free(sig); + BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); + BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen); - if (datafellows & SSH_BUG_SIGBLOB) { - if (lenp != NULL) - *lenp = SIGBLOB_LEN; + if (compat & SSH_BUG_SIGBLOB) { if (sigp != NULL) { - *sigp = xmalloc(SIGBLOB_LEN); + if ((*sigp = malloc(SIGBLOB_LEN)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(*sigp, sigblob, SIGBLOB_LEN); } + if (lenp != NULL) + *lenp = SIGBLOB_LEN; + ret = 0; } else { /* ietf-drafts */ - buffer_init(&b); - buffer_put_cstring(&b, "ssh-dss"); - buffer_put_string(&b, sigblob, SIGBLOB_LEN); - len = buffer_len(&b); - if (lenp != NULL) - *lenp = len; + if ((b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 || + (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0) + goto out; + len = sshbuf_len(b); if (sigp != NULL) { - *sigp = xmalloc(len); - memcpy(*sigp, buffer_ptr(&b), len); + if ((*sigp = malloc(len)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + memcpy(*sigp, sshbuf_ptr(b), len); } - buffer_free(&b); + if (lenp != NULL) + *lenp = len; + ret = 0; } - return 0; + out: + explicit_bzero(digest, sizeof(digest)); + if (sig != NULL) + DSA_SIG_free(sig); + if (b != NULL) + sshbuf_free(b); + return ret; } + int -ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen, - const u_char *data, u_int datalen) +ssh_dss_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat) { - DSA_SIG *sig; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; - u_int len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); - int rlen, ret; - Buffer b; - - if (key == NULL || key_type_plain(key->type) != KEY_DSA || - key->dsa == NULL) { - error("%s: no DSA key", __func__); - return -1; - } + DSA_SIG *sig = NULL; + u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; + size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); + int ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; + char *ktype = NULL; + + if (key == NULL || key->dsa == NULL || + sshkey_type_plain(key->type) != KEY_DSA) + return SSH_ERR_INVALID_ARGUMENT; + if (dlen == 0) + return SSH_ERR_INTERNAL_ERROR; /* fetch signature */ - if (datafellows & SSH_BUG_SIGBLOB) { - sigblob = xmalloc(signaturelen); + if (compat & SSH_BUG_SIGBLOB) { + if ((sigblob = malloc(signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; memcpy(sigblob, signature, signaturelen); len = signaturelen; } else { /* ietf-drafts */ - char *ktype; - buffer_init(&b); - buffer_append(&b, signature, signaturelen); - ktype = buffer_get_cstring(&b, NULL); + if ((b = sshbuf_from(signature, signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || + sshbuf_get_string(b, &sigblob, &len) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } if (strcmp("ssh-dss", ktype) != 0) { - error("%s: cannot handle type %s", __func__, ktype); - buffer_free(&b); - free(ktype); - return -1; + ret = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; } - free(ktype); - sigblob = buffer_get_string(&b, &len); - rlen = buffer_len(&b); - buffer_free(&b); - if (rlen != 0) { - error("%s: remaining bytes in signature %d", - __func__, rlen); - free(sigblob); - return -1; + if (sshbuf_len(b) != 0) { + ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; } } if (len != SIGBLOB_LEN) { - fatal("bad sigbloblen %u != SIGBLOB_LEN", len); + ret = SSH_ERR_INVALID_FORMAT; + goto out; } /* parse signature */ - if ((sig = DSA_SIG_new()) == NULL) - fatal("%s: DSA_SIG_new failed", __func__); - if ((sig->r = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - if ((sig->s = BN_new()) == NULL) - fatal("ssh_dss_verify: BN_new failed"); + if ((sig = DSA_SIG_new()) == NULL || + (sig->r = BN_new()) == NULL || + (sig->s = BN_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || - (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) - fatal("%s: BN_bin2bn failed", __func__); - - /* clean up */ - explicit_bzero(sigblob, len); - free(sigblob); + (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } /* sha1 the data */ - if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, - digest, sizeof(digest)) != 0) { - error("%s: digest_memory failed", __func__); - return -1; + if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, + digest, sizeof(digest))) != 0) + goto out; + + switch (DSA_do_verify(digest, dlen, sig, key->dsa)) { + case 1: + ret = 0; + break; + case 0: + ret = SSH_ERR_SIGNATURE_INVALID; + goto out; + default: + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } - ret = DSA_do_verify(digest, dlen, sig, key->dsa); + out: explicit_bzero(digest, sizeof(digest)); - - DSA_SIG_free(sig); - - debug("%s: signature %s", __func__, - ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); + if (sig != NULL) + DSA_SIG_free(sig); + if (b != NULL) + sshbuf_free(b); + if (ktype != NULL) + free(ktype); + if (sigblob != NULL) { + explicit_bzero(sigblob, len); + free(sigblob); + } return ret; } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/ssh-ecdsa.c b/crypto/openssh/ssh-ecdsa.c index 551c9c4..2c76f8b 100644 --- a/crypto/openssh/ssh-ecdsa.c +++ b/crypto/openssh/ssh-ecdsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ecdsa.c,v 1.10 2014/02/03 23:28:00 djm Exp $ */ +/* $OpenBSD: ssh-ecdsa.c,v 1.11 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -26,7 +26,7 @@ #include "includes.h" -#ifdef OPENSSL_HAS_ECC +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) #include @@ -37,142 +37,156 @@ #include -#include "xmalloc.h" -#include "buffer.h" -#include "compat.h" -#include "log.h" -#include "key.h" +#include "sshbuf.h" +#include "ssherr.h" #include "digest.h" +#define SSHKEY_INTERNAL +#include "sshkey.h" +/* ARGSUSED */ int -ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, - const u_char *data, u_int datalen) +ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) { - ECDSA_SIG *sig; + ECDSA_SIG *sig = NULL; int hash_alg; u_char digest[SSH_DIGEST_MAX_LENGTH]; - u_int len, dlen; - Buffer b, bb; + size_t len, dlen; + struct sshbuf *b = NULL, *bb = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; - if (key == NULL || key_type_plain(key->type) != KEY_ECDSA || - key->ecdsa == NULL) { - error("%s: no ECDSA key", __func__); - return -1; + if (lenp != NULL) + *lenp = 0; + if (sigp != NULL) + *sigp = NULL; + + if (key == NULL || key->ecdsa == NULL || + sshkey_type_plain(key->type) != KEY_ECDSA) + return SSH_ERR_INVALID_ARGUMENT; + + if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || + (dlen = ssh_digest_bytes(hash_alg)) == 0) + return SSH_ERR_INTERNAL_ERROR; + if ((ret = ssh_digest_memory(hash_alg, data, datalen, + digest, sizeof(digest))) != 0) + goto out; + + if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } - hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid); - if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { - error("%s: bad hash algorithm %d", __func__, hash_alg); - return -1; - } - if (ssh_digest_memory(hash_alg, data, datalen, - digest, sizeof(digest)) != 0) { - error("%s: digest_memory failed", __func__); - return -1; + if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; } - - sig = ECDSA_do_sign(digest, dlen, key->ecdsa); - explicit_bzero(digest, sizeof(digest)); - - if (sig == NULL) { - error("%s: sign failed", __func__); - return -1; + if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 || + (ret = sshbuf_put_bignum2(bb, sig->s)) != 0) + goto out; + if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 || + (ret = sshbuf_put_stringb(b, bb)) != 0) + goto out; + len = sshbuf_len(b); + if (sigp != NULL) { + if ((*sigp = malloc(len)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + memcpy(*sigp, sshbuf_ptr(b), len); } - - buffer_init(&bb); - buffer_put_bignum2(&bb, sig->r); - buffer_put_bignum2(&bb, sig->s); - ECDSA_SIG_free(sig); - - buffer_init(&b); - buffer_put_cstring(&b, key_ssh_name_plain(key)); - buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb)); - buffer_free(&bb); - len = buffer_len(&b); if (lenp != NULL) *lenp = len; - if (sigp != NULL) { - *sigp = xmalloc(len); - memcpy(*sigp, buffer_ptr(&b), len); - } - buffer_free(&b); - - return 0; + ret = 0; + out: + explicit_bzero(digest, sizeof(digest)); + if (b != NULL) + sshbuf_free(b); + if (bb != NULL) + sshbuf_free(bb); + if (sig != NULL) + ECDSA_SIG_free(sig); + return ret; } + +/* ARGSUSED */ int -ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, - const u_char *data, u_int datalen) +ssh_ecdsa_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat) { - ECDSA_SIG *sig; + ECDSA_SIG *sig = NULL; int hash_alg; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; - u_int len, dlen; - int rlen, ret; - Buffer b, bb; - char *ktype; - - if (key == NULL || key_type_plain(key->type) != KEY_ECDSA || - key->ecdsa == NULL) { - error("%s: no ECDSA key", __func__); - return -1; - } + u_char digest[SSH_DIGEST_MAX_LENGTH]; + size_t dlen; + int ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL, *sigbuf = NULL; + char *ktype = NULL; + + if (key == NULL || key->ecdsa == NULL || + sshkey_type_plain(key->type) != KEY_ECDSA) + return SSH_ERR_INVALID_ARGUMENT; + + if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || + (dlen = ssh_digest_bytes(hash_alg)) == 0) + return SSH_ERR_INTERNAL_ERROR; /* fetch signature */ - buffer_init(&b); - buffer_append(&b, signature, signaturelen); - ktype = buffer_get_string(&b, NULL); - if (strcmp(key_ssh_name_plain(key), ktype) != 0) { - error("%s: cannot handle type %s", __func__, ktype); - buffer_free(&b); - free(ktype); - return -1; + if ((b = sshbuf_from(signature, signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || + sshbuf_froms(b, &sigbuf) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; } - free(ktype); - sigblob = buffer_get_string(&b, &len); - rlen = buffer_len(&b); - buffer_free(&b); - if (rlen != 0) { - error("%s: remaining bytes in signature %d", __func__, rlen); - free(sigblob); - return -1; + if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) { + ret = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + if (sshbuf_len(b) != 0) { + ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; } /* parse signature */ - if ((sig = ECDSA_SIG_new()) == NULL) - fatal("%s: ECDSA_SIG_new failed", __func__); - - buffer_init(&bb); - buffer_append(&bb, sigblob, len); - buffer_get_bignum2(&bb, sig->r); - buffer_get_bignum2(&bb, sig->s); - if (buffer_len(&bb) != 0) - fatal("%s: remaining bytes in inner sigblob", __func__); - buffer_free(&bb); - - /* clean up */ - explicit_bzero(sigblob, len); - free(sigblob); - - /* hash the data */ - hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid); - if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { - error("%s: bad hash algorithm %d", __func__, hash_alg); - return -1; + if ((sig = ECDSA_SIG_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 || + sshbuf_get_bignum2(sigbuf, sig->s) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(sigbuf) != 0) { + ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; } - if (ssh_digest_memory(hash_alg, data, datalen, - digest, sizeof(digest)) != 0) { - error("%s: digest_memory failed", __func__); - return -1; + if ((ret = ssh_digest_memory(hash_alg, data, datalen, + digest, sizeof(digest))) != 0) + goto out; + + switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) { + case 1: + ret = 0; + break; + case 0: + ret = SSH_ERR_SIGNATURE_INVALID; + goto out; + default: + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } - ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa); + out: explicit_bzero(digest, sizeof(digest)); - - ECDSA_SIG_free(sig); - - debug("%s: signature %s", __func__, - ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); + if (sigbuf != NULL) + sshbuf_free(sigbuf); + if (b != NULL) + sshbuf_free(b); + if (sig != NULL) + ECDSA_SIG_free(sig); + free(ktype); return ret; } -#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ diff --git a/crypto/openssh/ssh-ed25519.c b/crypto/openssh/ssh-ed25519.c index 160d1f2..b159ff5 100644 --- a/crypto/openssh/ssh-ed25519.c +++ b/crypto/openssh/ssh-ed25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ed25519.c,v 1.3 2014/02/23 20:03:42 djm Exp $ */ +/* $OpenBSD: ssh-ed25519.c,v 1.6 2015/01/15 21:38:50 markus Exp $ */ /* * Copyright (c) 2013 Markus Friedl * @@ -18,132 +18,149 @@ #include "includes.h" #include +#include #include "crypto_api.h" -#include #include #include -#include "xmalloc.h" #include "log.h" -#include "buffer.h" -#include "key.h" +#include "sshbuf.h" +#define SSHKEY_INTERNAL +#include "sshkey.h" +#include "ssherr.h" #include "ssh.h" int -ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp, - const u_char *data, u_int datalen) +ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) { - u_char *sig; - u_int slen, len; + u_char *sig = NULL; + size_t slen = 0, len; unsigned long long smlen; - int ret; - Buffer b; + int r, ret; + struct sshbuf *b = NULL; - if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || - key->ed25519_sk == NULL) { - error("%s: no ED25519 key", __func__); - return -1; - } + if (lenp != NULL) + *lenp = 0; + if (sigp != NULL) + *sigp = NULL; - if (datalen >= UINT_MAX - crypto_sign_ed25519_BYTES) { - error("%s: datalen %u too long", __func__, datalen); - return -1; - } + if (key == NULL || + sshkey_type_plain(key->type) != KEY_ED25519 || + key->ed25519_sk == NULL || + datalen >= INT_MAX - crypto_sign_ed25519_BYTES) + return SSH_ERR_INVALID_ARGUMENT; smlen = slen = datalen + crypto_sign_ed25519_BYTES; - sig = xmalloc(slen); + if ((sig = malloc(slen)) == NULL) + return SSH_ERR_ALLOC_FAIL; if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, key->ed25519_sk)) != 0 || smlen <= datalen) { - error("%s: crypto_sign_ed25519 failed: %d", __func__, ret); - free(sig); - return -1; + r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */ + goto out; } /* encode signature */ - buffer_init(&b); - buffer_put_cstring(&b, "ssh-ed25519"); - buffer_put_string(&b, sig, smlen - datalen); - len = buffer_len(&b); + if ((b = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 || + (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0) + goto out; + len = sshbuf_len(b); + if (sigp != NULL) { + if ((*sigp = malloc(len)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + memcpy(*sigp, sshbuf_ptr(b), len); + } if (lenp != NULL) *lenp = len; - if (sigp != NULL) { - *sigp = xmalloc(len); - memcpy(*sigp, buffer_ptr(&b), len); + /* success */ + r = 0; + out: + sshbuf_free(b); + if (sig != NULL) { + explicit_bzero(sig, slen); + free(sig); } - buffer_free(&b); - explicit_bzero(sig, slen); - free(sig); - return 0; + return r; } int -ssh_ed25519_verify(const Key *key, const u_char *signature, u_int signaturelen, - const u_char *data, u_int datalen) +ssh_ed25519_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat) { - Buffer b; - char *ktype; - u_char *sigblob, *sm, *m; - u_int len; - unsigned long long smlen, mlen; - int rlen, ret; + struct sshbuf *b = NULL; + char *ktype = NULL; + const u_char *sigblob; + u_char *sm = NULL, *m = NULL; + size_t len; + unsigned long long smlen = 0, mlen = 0; + int r, ret; - if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || - key->ed25519_pk == NULL) { - error("%s: no ED25519 key", __func__); - return -1; - } - buffer_init(&b); - buffer_append(&b, signature, signaturelen); - ktype = buffer_get_cstring(&b, NULL); + if (key == NULL || + sshkey_type_plain(key->type) != KEY_ED25519 || + key->ed25519_pk == NULL || + datalen >= INT_MAX - crypto_sign_ed25519_BYTES) + return SSH_ERR_INVALID_ARGUMENT; + + if ((b = sshbuf_from(signature, signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || + (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0) + goto out; if (strcmp("ssh-ed25519", ktype) != 0) { - error("%s: cannot handle type %s", __func__, ktype); - buffer_free(&b); - free(ktype); - return -1; + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; } - free(ktype); - sigblob = buffer_get_string(&b, &len); - rlen = buffer_len(&b); - buffer_free(&b); - if (rlen != 0) { - error("%s: remaining bytes in signature %d", __func__, rlen); - free(sigblob); - return -1; + if (sshbuf_len(b) != 0) { + r = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; } if (len > crypto_sign_ed25519_BYTES) { - error("%s: len %u > crypto_sign_ed25519_BYTES %u", __func__, - len, crypto_sign_ed25519_BYTES); - free(sigblob); - return -1; + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (datalen >= SIZE_MAX - len) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; } smlen = len + datalen; - sm = xmalloc(smlen); + mlen = smlen; + if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } memcpy(sm, sigblob, len); memcpy(sm+len, data, datalen); - mlen = smlen; - m = xmalloc(mlen); if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, key->ed25519_pk)) != 0) { debug2("%s: crypto_sign_ed25519_open failed: %d", __func__, ret); } - if (ret == 0 && mlen != datalen) { - debug2("%s: crypto_sign_ed25519_open " - "mlen != datalen (%llu != %u)", __func__, mlen, datalen); - ret = -1; + if (ret != 0 || mlen != datalen) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; } /* XXX compare 'm' and 'data' ? */ - - explicit_bzero(sigblob, len); - explicit_bzero(sm, smlen); - explicit_bzero(m, smlen); /* NB. mlen may be invalid if ret != 0 */ - free(sigblob); - free(sm); - free(m); - debug("%s: signature %scorrect", __func__, (ret != 0) ? "in" : ""); - - /* translate return code carefully */ - return (ret == 0) ? 1 : -1; + /* success */ + r = 0; + out: + if (sm != NULL) { + explicit_bzero(sm, smlen); + free(sm); + } + if (m != NULL) { + explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */ + free(m); + } + sshbuf_free(b); + free(ktype); + return r; } diff --git a/crypto/openssh/ssh-keygen.0 b/crypto/openssh/ssh-keygen.0 deleted file mode 100644 index c43678f..0000000 --- a/crypto/openssh/ssh-keygen.0 +++ /dev/null @@ -1,562 +0,0 @@ -SSH-KEYGEN(1) OpenBSD Reference Manual SSH-KEYGEN(1) - -NAME - ssh-keygen - authentication key generation, management and conversion - -SYNOPSIS - ssh-keygen [-q] [-b bits] [-t type] [-N new_passphrase] [-C comment] - [-f output_keyfile] - ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile] - ssh-keygen -i [-m key_format] [-f input_keyfile] - ssh-keygen -e [-m key_format] [-f input_keyfile] - ssh-keygen -y [-f input_keyfile] - ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile] - ssh-keygen -l [-f input_keyfile] - ssh-keygen -B [-f input_keyfile] - ssh-keygen -D pkcs11 - ssh-keygen -F hostname [-f known_hosts_file] [-l] - ssh-keygen -H [-f known_hosts_file] - ssh-keygen -R hostname [-f known_hosts_file] - ssh-keygen -r hostname [-f input_keyfile] [-g] - ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point] - ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines] - [-j start_line] [-K checkpt] [-W generator] - ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals] - [-O option] [-V validity_interval] [-z serial_number] file ... - ssh-keygen -L [-f input_keyfile] - ssh-keygen -A - ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number] - file ... - ssh-keygen -Q -f krl_file file ... - -DESCRIPTION - ssh-keygen generates, manages and converts authentication keys for - ssh(1). ssh-keygen can create RSA keys for use by SSH protocol version 1 - and DSA, ECDSA, ED25519 or RSA keys for use by SSH protocol version 2. - The type of key to be generated is specified with the -t option. If - invoked without any arguments, ssh-keygen will generate an RSA key for - use in SSH protocol 2 connections. - - ssh-keygen is also used to generate groups for use in Diffie-Hellman - group exchange (DH-GEX). See the MODULI GENERATION section for details. - - Finally, ssh-keygen can be used to generate and update Key Revocation - Lists, and to test whether given keys have been revoked by one. See the - KEY REVOCATION LISTS section for details. - - Normally each user wishing to use SSH with public key authentication runs - this once to create the authentication key in ~/.ssh/identity, - ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 or ~/.ssh/id_rsa. - Additionally, the system administrator may use this to generate host - keys, as seen in /etc/rc. - - Normally this program generates the key and asks for a file in which to - store the private key. The public key is stored in a file with the same - name but ``.pub'' appended. The program also asks for a passphrase. The - passphrase may be empty to indicate no passphrase (host keys must have an - empty passphrase), or it may be a string of arbitrary length. A - passphrase is similar to a password, except it can be a phrase with a - series of words, punctuation, numbers, whitespace, or any string of - characters you want. Good passphrases are 10-30 characters long, are not - simple sentences or otherwise easily guessable (English prose has only - 1-2 bits of entropy per character, and provides very bad passphrases), - and contain a mix of upper and lowercase letters, numbers, and non- - alphanumeric characters. The passphrase can be changed later by using - the -p option. - - There is no way to recover a lost passphrase. If the passphrase is lost - or forgotten, a new key must be generated and the corresponding public - key copied to other machines. - - For RSA1 keys, there is also a comment field in the key file that is only - for convenience to the user to help identify the key. The comment can - tell what the key is for, or whatever is useful. The comment is - initialized to ``user@host'' when the key is created, but can be changed - using the -c option. - - After a key is generated, instructions below detail where the keys should - be placed to be activated. - - The options are as follows: - - -A For each of the key types (rsa1, rsa, dsa, ecdsa and ed25519) for - which host keys do not exist, generate the host keys with the - default key file path, an empty passphrase, default bits for the - key type, and default comment. This is used by /etc/rc to - generate new host keys. - - -a rounds - When saving a new-format private key (i.e. an ed25519 key or any - SSH protocol 2 key when the -o flag is set), this option - specifies the number of KDF (key derivation function) rounds - used. Higher numbers result in slower passphrase verification - and increased resistance to brute-force password cracking (should - the keys be stolen). - - When screening DH-GEX candidates ( using the -T command). This - option specifies the number of primality tests to perform. - - -B Show the bubblebabble digest of specified private or public key - file. - - -b bits - Specifies the number of bits in the key to create. For RSA keys, - the minimum size is 768 bits and the default is 2048 bits. - Generally, 2048 bits is considered sufficient. DSA keys must be - exactly 1024 bits as specified by FIPS 186-2. For ECDSA keys, - the -b flag determines the key length by selecting from one of - three elliptic curve sizes: 256, 384 or 521 bits. Attempting to - use bit lengths other than these three values for ECDSA keys will - fail. ED25519 keys have a fixed length and the -b flag will be - ignored. - - -C comment - Provides a new comment. - - -c Requests changing the comment in the private and public key - files. This operation is only supported for RSA1 keys. The - program will prompt for the file containing the private keys, for - the passphrase if the key has one, and for the new comment. - - -D pkcs11 - Download the RSA public keys provided by the PKCS#11 shared - library pkcs11. When used in combination with -s, this option - indicates that a CA key resides in a PKCS#11 token (see the - CERTIFICATES section for details). - - -e This option will read a private or public OpenSSH key file and - print to stdout the key in one of the formats specified by the -m - option. The default export format is ``RFC4716''. This option - allows exporting OpenSSH keys for use by other programs, - including several commercial SSH implementations. - - -F hostname - Search for the specified hostname in a known_hosts file, listing - any occurrences found. This option is useful to find hashed host - names or addresses and may also be used in conjunction with the - -H option to print found keys in a hashed format. - - -f filename - Specifies the filename of the key file. - - -G output_file - Generate candidate primes for DH-GEX. These primes must be - screened for safety (using the -T option) before use. - - -g Use generic DNS format when printing fingerprint resource records - using the -r command. - - -H Hash a known_hosts file. This replaces all hostnames and - addresses with hashed representations within the specified file; - the original content is moved to a file with a .old suffix. - These hashes may be used normally by ssh and sshd, but they do - not reveal identifying information should the file's contents be - disclosed. This option will not modify existing hashed hostnames - and is therefore safe to use on files that mix hashed and non- - hashed names. - - -h When signing a key, create a host certificate instead of a user - certificate. Please see the CERTIFICATES section for details. - - -I certificate_identity - Specify the key identity when signing a public key. Please see - the CERTIFICATES section for details. - - -i This option will read an unencrypted private (or public) key file - in the format specified by the -m option and print an OpenSSH - compatible private (or public) key to stdout. - - -J num_lines - Exit after screening the specified number of lines while - performing DH candidate screening using the -T option. - - -j start_line - Start screening at the specified line number while performing DH - candidate screening using the -T option. - - -K checkpt - Write the last line processed to the file checkpt while - performing DH candidate screening using the -T option. This will - be used to skip lines in the input file that have already been - processed if the job is restarted. This option allows importing - keys from other software, including several commercial SSH - implementations. The default import format is ``RFC4716''. - - -k Generate a KRL file. In this mode, ssh-keygen will generate a - KRL file at the location specified via the -f flag that revokes - every key or certificate presented on the command line. - Keys/certificates to be revoked may be specified by public key - file or using the format described in the KEY REVOCATION LISTS - section. - - -L Prints the contents of a certificate. - - -l Show fingerprint of specified public key file. Private RSA1 keys - are also supported. For RSA and DSA keys ssh-keygen tries to - find the matching public key file and prints its fingerprint. If - combined with -v, an ASCII art representation of the key is - supplied with the fingerprint. - - -M memory - Specify the amount of memory to use (in megabytes) when - generating candidate moduli for DH-GEX. - - -m key_format - Specify a key format for the -i (import) or -e (export) - conversion options. The supported key formats are: ``RFC4716'' - (RFC 4716/SSH2 public or private key), ``PKCS8'' (PEM PKCS8 - public key) or ``PEM'' (PEM public key). The default conversion - format is ``RFC4716''. - - -N new_passphrase - Provides the new passphrase. - - -n principals - Specify one or more principals (user or host names) to be - included in a certificate when signing a key. Multiple - principals may be specified, separated by commas. Please see the - CERTIFICATES section for details. - - -O option - Specify a certificate option when signing a key. This option may - be specified multiple times. Please see the CERTIFICATES section - for details. The options that are valid for user certificates - are: - - clear Clear all enabled permissions. This is useful for - clearing the default set of permissions so permissions - may be added individually. - - force-command=command - Forces the execution of command instead of any shell or - command specified by the user when the certificate is - used for authentication. - - no-agent-forwarding - Disable ssh-agent(1) forwarding (permitted by default). - - no-port-forwarding - Disable port forwarding (permitted by default). - - no-pty Disable PTY allocation (permitted by default). - - no-user-rc - Disable execution of ~/.ssh/rc by sshd(8) (permitted by - default). - - no-x11-forwarding - Disable X11 forwarding (permitted by default). - - permit-agent-forwarding - Allows ssh-agent(1) forwarding. - - permit-port-forwarding - Allows port forwarding. - - permit-pty - Allows PTY allocation. - - permit-user-rc - Allows execution of ~/.ssh/rc by sshd(8). - - permit-x11-forwarding - Allows X11 forwarding. - - source-address=address_list - Restrict the source addresses from which the certificate - is considered valid. The address_list is a comma- - separated list of one or more address/netmask pairs in - CIDR format. - - At present, no options are valid for host keys. - - -o Causes ssh-keygen to save SSH protocol 2 private keys using the - new OpenSSH format rather than the more compatible PEM format. - The new format has increased resistance to brute-force password - cracking but is not supported by versions of OpenSSH prior to - 6.5. Ed25519 keys always use the new private key format. - - -P passphrase - Provides the (old) passphrase. - - -p Requests changing the passphrase of a private key file instead of - creating a new private key. The program will prompt for the file - containing the private key, for the old passphrase, and twice for - the new passphrase. - - -Q Test whether keys have been revoked in a KRL. - - -q Silence ssh-keygen. - - -R hostname - Removes all keys belonging to hostname from a known_hosts file. - This option is useful to delete hashed hosts (see the -H option - above). - - -r hostname - Print the SSHFP fingerprint resource record named hostname for - the specified public key file. - - -S start - Specify start point (in hex) when generating candidate moduli for - DH-GEX. - - -s ca_key - Certify (sign) a public key using the specified CA key. Please - see the CERTIFICATES section for details. - - When generating a KRL, -s specifies a path to a CA public key - file used to revoke certificates directly by key ID or serial - number. See the KEY REVOCATION LISTS section for details. - - -T output_file - Test DH group exchange candidate primes (generated using the -G - option) for safety. - - -t type - Specifies the type of key to create. The possible values are - ``rsa1'' for protocol version 1 and ``dsa'', ``ecdsa'', - ``ed25519'', or ``rsa'' for protocol version 2. - - -u Update a KRL. When specified with -k, keys listed via the - command line are added to the existing KRL rather than a new KRL - being created. - - -V validity_interval - Specify a validity interval when signing a certificate. A - validity interval may consist of a single time, indicating that - the certificate is valid beginning now and expiring at that time, - or may consist of two times separated by a colon to indicate an - explicit time interval. The start time may be specified as a - date in YYYYMMDD format, a time in YYYYMMDDHHMMSS format or a - relative time (to the current time) consisting of a minus sign - followed by a relative time in the format described in the TIME - FORMATS section of sshd_config(5). The end time may be specified - as a YYYYMMDD date, a YYYYMMDDHHMMSS time or a relative time - starting with a plus character. - - For example: ``+52w1d'' (valid from now to 52 weeks and one day - from now), ``-4w:+4w'' (valid from four weeks ago to four weeks - from now), ``20100101123000:20110101123000'' (valid from 12:30 - PM, January 1st, 2010 to 12:30 PM, January 1st, 2011), - ``-1d:20110101'' (valid from yesterday to midnight, January 1st, - 2011). - - -v Verbose mode. Causes ssh-keygen to print debugging messages - about its progress. This is helpful for debugging moduli - generation. Multiple -v options increase the verbosity. The - maximum is 3. - - -W generator - Specify desired generator when testing candidate moduli for DH- - GEX. - - -y This option will read a private OpenSSH format file and print an - OpenSSH public key to stdout. - - -z serial_number - Specifies a serial number to be embedded in the certificate to - distinguish this certificate from others from the same CA. The - default serial number is zero. - - When generating a KRL, the -z flag is used to specify a KRL - version number. - -MODULI GENERATION - ssh-keygen may be used to generate groups for the Diffie-Hellman Group - Exchange (DH-GEX) protocol. Generating these groups is a two-step - process: first, candidate primes are generated using a fast, but memory - intensive process. These candidate primes are then tested for - suitability (a CPU-intensive process). - - Generation of primes is performed using the -G option. The desired - length of the primes may be specified by the -b option. For example: - - # ssh-keygen -G moduli-2048.candidates -b 2048 - - By default, the search for primes begins at a random point in the desired - length range. This may be overridden using the -S option, which - specifies a different start point (in hex). - - Once a set of candidates have been generated, they must be screened for - suitability. This may be performed using the -T option. In this mode - ssh-keygen will read candidates from standard input (or a file specified - using the -f option). For example: - - # ssh-keygen -T moduli-2048 -f moduli-2048.candidates - - By default, each candidate will be subjected to 100 primality tests. - This may be overridden using the -a option. The DH generator value will - be chosen automatically for the prime under consideration. If a specific - generator is desired, it may be requested using the -W option. Valid - generator values are 2, 3, and 5. - - Screened DH groups may be installed in /etc/moduli. It is important that - this file contains moduli of a range of bit lengths and that both ends of - a connection share common moduli. - -CERTIFICATES - ssh-keygen supports signing of keys to produce certificates that may be - used for user or host authentication. Certificates consist of a public - key, some identity information, zero or more principal (user or host) - names and a set of options that are signed by a Certification Authority - (CA) key. Clients or servers may then trust only the CA key and verify - its signature on a certificate rather than trusting many user/host keys. - Note that OpenSSH certificates are a different, and much simpler, format - to the X.509 certificates used in ssl(8). - - ssh-keygen supports two types of certificates: user and host. User - certificates authenticate users to servers, whereas host certificates - authenticate server hosts to users. To generate a user certificate: - - $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub - - The resultant certificate will be placed in /path/to/user_key-cert.pub. - A host certificate requires the -h option: - - $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub - - The host certificate will be output to /path/to/host_key-cert.pub. - - It is possible to sign using a CA key stored in a PKCS#11 token by - providing the token library using -D and identifying the CA key by - providing its public half as an argument to -s: - - $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub - - In all cases, key_id is a "key identifier" that is logged by the server - when the certificate is used for authentication. - - Certificates may be limited to be valid for a set of principal - (user/host) names. By default, generated certificates are valid for all - users or hosts. To generate a certificate for a specified set of - principals: - - $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub - $ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub - - Additional limitations on the validity and use of user certificates may - be specified through certificate options. A certificate option may - disable features of the SSH session, may be valid only when presented - from particular source addresses or may force the use of a specific - command. For a list of valid certificate options, see the documentation - for the -O option above. - - Finally, certificates may be defined with a validity lifetime. The -V - option allows specification of certificate start and end times. A - certificate that is presented at a time outside this range will not be - considered valid. By default, certificates are valid from UNIX Epoch to - the distant future. - - For certificates to be used for user or host authentication, the CA - public key must be trusted by sshd(8) or ssh(1). Please refer to those - manual pages for details. - -KEY REVOCATION LISTS - ssh-keygen is able to manage OpenSSH format Key Revocation Lists (KRLs). - These binary files specify keys or certificates to be revoked using a - compact format, taking as little as one bit per certificate if they are - being revoked by serial number. - - KRLs may be generated using the -k flag. This option reads one or more - files from the command line and generates a new KRL. The files may - either contain a KRL specification (see below) or public keys, listed one - per line. Plain public keys are revoked by listing their hash or - contents in the KRL and certificates revoked by serial number or key ID - (if the serial is zero or not available). - - Revoking keys using a KRL specification offers explicit control over the - types of record used to revoke keys and may be used to directly revoke - certificates by serial number or key ID without having the complete - original certificate on hand. A KRL specification consists of lines - containing one of the following directives followed by a colon and some - directive-specific information. - - serial: serial_number[-serial_number] - Revokes a certificate with the specified serial number. Serial - numbers are 64-bit values, not including zero and may be - expressed in decimal, hex or octal. If two serial numbers are - specified separated by a hyphen, then the range of serial numbers - including and between each is revoked. The CA key must have been - specified on the ssh-keygen command line using the -s option. - - id: key_id - Revokes a certificate with the specified key ID string. The CA - key must have been specified on the ssh-keygen command line using - the -s option. - - key: public_key - Revokes the specified key. If a certificate is listed, then it - is revoked as a plain public key. - - sha1: public_key - Revokes the specified key by its SHA1 hash. - - KRLs may be updated using the -u flag in addition to -k. When this - option is specified, keys listed via the command line are merged into the - KRL, adding to those already there. - - It is also possible, given a KRL, to test whether it revokes a particular - key (or keys). The -Q flag will query an existing KRL, testing each key - specified on the commandline. If any key listed on the command line has - been revoked (or an error encountered) then ssh-keygen will exit with a - non-zero exit status. A zero exit status will only be returned if no key - was revoked. - -FILES - ~/.ssh/identity - Contains the protocol version 1 RSA authentication identity of - the user. This file should not be readable by anyone but the - user. It is possible to specify a passphrase when generating the - key; that passphrase will be used to encrypt the private part of - this file using 3DES. This file is not automatically accessed by - ssh-keygen but it is offered as the default file for the private - key. ssh(1) will read this file when a login attempt is made. - - ~/.ssh/identity.pub - Contains the protocol version 1 RSA public key for - authentication. The contents of this file should be added to - ~/.ssh/authorized_keys on all machines where the user wishes to - log in using RSA authentication. There is no need to keep the - contents of this file secret. - - ~/.ssh/id_dsa - ~/.ssh/id_ecdsa - ~/.ssh/id_ed25519 - ~/.ssh/id_rsa - Contains the protocol version 2 DSA, ECDSA, ED25519 or RSA - authentication identity of the user. This file should not be - readable by anyone but the user. It is possible to specify a - passphrase when generating the key; that passphrase will be used - to encrypt the private part of this file using 128-bit AES. This - file is not automatically accessed by ssh-keygen but it is - offered as the default file for the private key. ssh(1) will - read this file when a login attempt is made. - - ~/.ssh/id_dsa.pub - ~/.ssh/id_ecdsa.pub - ~/.ssh/id_ed25519.pub - ~/.ssh/id_rsa.pub - Contains the protocol version 2 DSA, ECDSA, ED25519 or RSA public - key for authentication. The contents of this file should be - added to ~/.ssh/authorized_keys on all machines where the user - wishes to log in using public key authentication. There is no - need to keep the contents of this file secret. - - /etc/moduli - Contains Diffie-Hellman groups used for DH-GEX. The file format - is described in moduli(5). - -SEE ALSO - ssh(1), ssh-add(1), ssh-agent(1), moduli(5), sshd(8) - - The Secure Shell (SSH) Public Key File Format, RFC 4716, 2006. - -AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by - Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. - -OpenBSD 5.5 February 5, 2014 OpenBSD 5.5 diff --git a/crypto/openssh/ssh-keygen.1 b/crypto/openssh/ssh-keygen.1 index 12e00d4..ed17a08 100644 --- a/crypto/openssh/ssh-keygen.1 +++ b/crypto/openssh/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.120 2014/02/05 20:13:25 naddy Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.127 2015/08/20 19:20:06 naddy Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: February 5 2014 $ +.Dd $Mdocdate: August 20 2015 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -46,7 +46,7 @@ .Nm ssh-keygen .Op Fl q .Op Fl b Ar bits -.Op Fl t Ar type +.Op Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1 .Op Fl N Ar new_passphrase .Op Fl C Ar comment .Op Fl f Ar output_keyfile @@ -73,6 +73,8 @@ .Op Fl f Ar keyfile .Nm ssh-keygen .Fl l +.Op Fl v +.Op Fl E Ar fingerprint_hash .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl B @@ -140,7 +142,7 @@ generates, manages and converts authentication keys for .Xr ssh 1 . .Nm can create RSA keys for use by SSH protocol version 1 and -DSA, ECDSA, ED25519 or RSA keys for use by SSH protocol version 2. +DSA, ECDSA, Ed25519 or RSA keys for use by SSH protocol version 2. The type of key to be generated is specified with the .Fl t option. @@ -242,7 +244,7 @@ This option specifies the number of primality tests to perform. Show the bubblebabble digest of specified private or public key file. .It Fl b Ar bits Specifies the number of bits in the key to create. -For RSA keys, the minimum size is 768 bits and the default is 2048 bits. +For RSA keys, the minimum size is 1024 bits and the default is 2048 bits. Generally, 2048 bits is considered sufficient. DSA keys must be exactly 1024 bits as specified by FIPS 186-2. For ECDSA keys, the @@ -251,7 +253,7 @@ flag determines the key length by selecting from one of three elliptic curve sizes: 256, 384 or 521 bits. Attempting to use bit lengths other than these three values for ECDSA keys will fail. -ED25519 keys have a fixed length and the +Ed25519 keys have a fixed length and the .Fl b flag will be ignored. .It Fl C Ar comment @@ -269,6 +271,14 @@ When used in combination with this option indicates that a CA key resides in a PKCS#11 token (see the .Sx CERTIFICATES section for details). +.It Fl E Ar fingerprint_hash +Specifies the hash algorithm used when displaying key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . .It Fl e This option will read a private or public OpenSSH key file and print to stdout the key in one of the formats specified by the @@ -332,6 +342,10 @@ in the format specified by the .Fl m option and print an OpenSSH compatible private (or public) key to stdout. +This option allows importing keys from other software, including several +commercial SSH implementations. +The default import format is +.Dq RFC4716 . .It Fl J Ar num_lines Exit after screening the specified number of lines while performing DH candidate screening using the @@ -350,10 +364,6 @@ while performing DH candidate screening using the option. This will be used to skip lines in the input file that have already been processed if the job is restarted. -This option allows importing keys from other software, including several -commercial SSH implementations. -The default import format is -.Dq RFC4716 . .It Fl k Generate a KRL file. In this mode, @@ -514,7 +524,7 @@ section for details. Test DH group exchange candidate primes (generated using the .Fl G option) for safety. -.It Fl t Ar type +.It Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1 Specifies the type of key to create. The possible values are .Dq rsa1 @@ -670,7 +680,7 @@ and identifying the CA key by providing its public half as an argument to .Fl s : .Pp -.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub +.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub .Pp In all cases, .Ar key_id @@ -683,7 +693,7 @@ By default, generated certificates are valid for all users or hosts. To generate a certificate for a specified set of principals: .Pp .Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub -.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub" +.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain host_key.pub" .Pp Additional limitations on the validity and use of user certificates may be specified through certificate options. @@ -803,7 +813,7 @@ There is no need to keep the contents of this file secret. .It Pa ~/.ssh/id_ecdsa .It Pa ~/.ssh/id_ed25519 .It Pa ~/.ssh/id_rsa -Contains the protocol version 2 DSA, ECDSA, ED25519 or RSA +Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA authentication identity of the user. This file should not be readable by anyone but the user. It is possible to @@ -819,7 +829,7 @@ will read this file when a login attempt is made. .It Pa ~/.ssh/id_ecdsa.pub .It Pa ~/.ssh/id_ed25519.pub .It Pa ~/.ssh/id_rsa.pub -Contains the protocol version 2 DSA, ECDSA, ED25519 or RSA +Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA public key for authentication. The contents of this file should be added to .Pa ~/.ssh/authorized_keys diff --git a/crypto/openssh/ssh-keygen.c b/crypto/openssh/ssh-keygen.c index 2a316bc..4e0a855 100644 --- a/crypto/openssh/ssh-keygen.c +++ b/crypto/openssh/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.241 2014/02/05 20:13:25 naddy Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.277 2015/08/19 23:17:51 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -17,11 +17,12 @@ #include #include #include -#include +#ifdef WITH_OPENSSL #include #include #include "openbsd-compat/openssl-compat.h" +#endif #include #include @@ -35,13 +36,14 @@ #include #include #include +#include #include "xmalloc.h" -#include "key.h" +#include "sshkey.h" #include "rsa.h" #include "authfile.h" #include "uuencode.h" -#include "buffer.h" +#include "sshbuf.h" #include "pathnames.h" #include "log.h" #include "misc.h" @@ -50,9 +52,17 @@ #include "dns.h" #include "ssh.h" #include "ssh2.h" +#include "ssherr.h" #include "ssh-pkcs11.h" #include "atomicio.h" #include "krl.h" +#include "digest.h" + +#ifdef WITH_OPENSSL +# define DEFAULT_KEY_TYPE_NAME "rsa" +#else +# define DEFAULT_KEY_TYPE_NAME "ed25519" +#endif /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ #define DEFAULT_BITS 2048 @@ -90,6 +100,9 @@ int show_cert = 0; int print_fingerprint = 0; int print_bubblebabble = 0; +/* Hash algorithm to use for fingerprints. */ +int fingerprint_hash = SSH_FP_HASH_DEFAULT; + /* The identity file name, given on the command line or entered by the user. */ char identity_file[1024]; int have_identity = 0; @@ -165,43 +178,51 @@ int rounds = 0; /* argv0 */ extern char *__progname; -char hostname[MAXHOSTNAMELEN]; +char hostname[NI_MAXHOST]; +#ifdef WITH_OPENSSL /* moduli.c */ int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long, unsigned long); +#endif static void -type_bits_valid(int type, u_int32_t *bitsp) +type_bits_valid(int type, const char *name, u_int32_t *bitsp) { - u_int maxbits; +#ifdef WITH_OPENSSL + u_int maxbits, nid; +#endif - if (type == KEY_UNSPEC) { - fprintf(stderr, "unknown key type %s\n", key_type_name); - exit(1); - } + if (type == KEY_UNSPEC) + fatal("unknown key type %s", key_type_name); if (*bitsp == 0) { +#ifdef WITH_OPENSSL if (type == KEY_DSA) *bitsp = DEFAULT_BITS_DSA; - else if (type == KEY_ECDSA) - *bitsp = DEFAULT_BITS_ECDSA; - else + else if (type == KEY_ECDSA) { + if (name != NULL && + (nid = sshkey_ecdsa_nid_from_name(name)) > 0) + *bitsp = sshkey_curve_nid_to_bits(nid); + if (*bitsp == 0) + *bitsp = DEFAULT_BITS_ECDSA; + } else +#endif *bitsp = DEFAULT_BITS; } +#ifdef WITH_OPENSSL maxbits = (type == KEY_DSA) ? OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; - if (*bitsp > maxbits) { - fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); - exit(1); - } + if (*bitsp > maxbits) + fatal("key bits exceeds maximum %d", maxbits); if (type == KEY_DSA && *bitsp != 1024) fatal("DSA keys must be 1024 bits"); - else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768) - fatal("Key must at least be 768 bits"); - else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1) + else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 1024) + fatal("Key must at least be 1024 bits"); + else if (type == KEY_ECDSA && sshkey_ecdsa_bits_to_nid(*bitsp) == -1) fatal("Invalid ECDSA key length - valid lengths are " "256, 384 or 521 bits"); +#endif } static void @@ -213,12 +234,11 @@ ask_filename(struct passwd *pw, const char *prompt) if (key_type_name == NULL) name = _PATH_SSH_CLIENT_ID_RSA; else { - switch (key_type_from_name(key_type_name)) { + switch (sshkey_type_from_name(key_type_name)) { case KEY_RSA1: name = _PATH_SSH_CLIENT_IDENTITY; break; case KEY_DSA_CERT: - case KEY_DSA_CERT_V00: case KEY_DSA: name = _PATH_SSH_CLIENT_ID_DSA; break; @@ -229,7 +249,6 @@ ask_filename(struct passwd *pw, const char *prompt) break; #endif case KEY_RSA_CERT: - case KEY_RSA_CERT_V00: case KEY_RSA: name = _PATH_SSH_CLIENT_ID_RSA; break; @@ -238,13 +257,13 @@ ask_filename(struct passwd *pw, const char *prompt) name = _PATH_SSH_CLIENT_ID_ED25519; break; default: - fprintf(stderr, "bad key type\n"); - exit(1); - break; + fatal("bad key type"); } } - snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name); - fprintf(stderr, "%s (%s): ", prompt, identity_file); + snprintf(identity_file, sizeof(identity_file), + "%s/%s", pw->pw_dir, name); + printf("%s (%s): ", prompt, identity_file); + fflush(stdout); if (fgets(buf, sizeof(buf), stdin) == NULL) exit(1); buf[strcspn(buf, "\n")] = '\0'; @@ -253,23 +272,26 @@ ask_filename(struct passwd *pw, const char *prompt) have_identity = 1; } -static Key * +static struct sshkey * load_identity(char *filename) { char *pass; - Key *prv; + struct sshkey *prv; + int r; - prv = key_load_private(filename, "", NULL); - if (prv == NULL) { - if (identity_passphrase) - pass = xstrdup(identity_passphrase); - else - pass = read_passphrase("Enter passphrase: ", - RP_ALLOW_STDIN); - prv = key_load_private(filename, pass, NULL); - explicit_bzero(pass, strlen(pass)); - free(pass); - } + if ((r = sshkey_load_private(filename, "", &prv, NULL)) == 0) + return prv; + if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) + fatal("Load key \"%s\": %s", filename, ssh_err(r)); + if (identity_passphrase) + pass = xstrdup(identity_passphrase); + else + pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); + r = sshkey_load_private(filename, pass, &prv, NULL); + explicit_bzero(pass, strlen(pass)); + free(pass); + if (r != 0) + fatal("Load key \"%s\": %s", filename, ssh_err(r)); return prv; } @@ -278,40 +300,38 @@ load_identity(char *filename) #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb +#ifdef WITH_OPENSSL static void -do_convert_to_ssh2(struct passwd *pw, Key *k) +do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) { - u_int len; + size_t len; u_char *blob; char comment[61]; + int r; - if (k->type == KEY_RSA1) { - fprintf(stderr, "version 1 keys are not supported\n"); - exit(1); - } - if (key_to_blob(k, &blob, &len) <= 0) { - fprintf(stderr, "key_to_blob failed\n"); - exit(1); - } + if (k->type == KEY_RSA1) + fatal("version 1 keys are not supported"); + if ((r = sshkey_to_blob(k, &blob, &len)) != 0) + fatal("key_to_blob failed: %s", ssh_err(r)); /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */ snprintf(comment, sizeof(comment), "%u-bit %s, converted by %s@%s from OpenSSH", - key_size(k), key_type(k), + sshkey_size(k), sshkey_type(k), pw->pw_name, hostname); fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); fprintf(stdout, "Comment: \"%s\"\n", comment); dump_base64(stdout, blob, len); fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); - key_free(k); + sshkey_free(k); free(blob); exit(0); } static void -do_convert_to_pkcs8(Key *k) +do_convert_to_pkcs8(struct sshkey *k) { - switch (key_type_plain(k->type)) { + switch (sshkey_type_plain(k->type)) { case KEY_RSA1: case KEY_RSA: if (!PEM_write_RSA_PUBKEY(stdout, k->rsa)) @@ -328,15 +348,15 @@ do_convert_to_pkcs8(Key *k) break; #endif default: - fatal("%s: unsupported key type %s", __func__, key_type(k)); + fatal("%s: unsupported key type %s", __func__, sshkey_type(k)); } exit(0); } static void -do_convert_to_pem(Key *k) +do_convert_to_pem(struct sshkey *k) { - switch (key_type_plain(k->type)) { + switch (sshkey_type_plain(k->type)) { case KEY_RSA1: case KEY_RSA: if (!PEM_write_RSAPublicKey(stdout, k->rsa)) @@ -350,7 +370,7 @@ do_convert_to_pem(Key *k) #endif /* XXX ECDSA? */ default: - fatal("%s: unsupported key type %s", __func__, key_type(k)); + fatal("%s: unsupported key type %s", __func__, sshkey_type(k)); } exit(0); } @@ -358,20 +378,16 @@ do_convert_to_pem(Key *k) static void do_convert_to(struct passwd *pw) { - Key *k; + struct sshkey *k; struct stat st; + int r; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); if (stat(identity_file, &st) < 0) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); - if ((k = key_load_public(identity_file, NULL)) == NULL) { - if ((k = load_identity(identity_file)) == NULL) { - fprintf(stderr, "load failed\n"); - exit(1); - } - } - + if ((r = sshkey_load_public(identity_file, &k, NULL)) != 0) + k = load_identity(identity_file); switch (convert_format) { case FMT_RFC4716: do_convert_to_ssh2(pw, k); @@ -388,51 +404,63 @@ do_convert_to(struct passwd *pw) exit(0); } +/* + * This is almost exactly the bignum1 encoding, but with 32 bit for length + * instead of 16. + */ static void -buffer_get_bignum_bits(Buffer *b, BIGNUM *value) +buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value) { - u_int bignum_bits = buffer_get_int(b); - u_int bytes = (bignum_bits + 7) / 8; - - if (buffer_len(b) < bytes) - fatal("buffer_get_bignum_bits: input buffer too small: " - "need %d have %d", bytes, buffer_len(b)); - if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL) - fatal("buffer_get_bignum_bits: BN_bin2bn failed"); - buffer_consume(b, bytes); + u_int bytes, bignum_bits; + int r; + + if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + bytes = (bignum_bits + 7) / 8; + if (sshbuf_len(b) < bytes) + fatal("%s: input buffer too small: need %d have %zu", + __func__, bytes, sshbuf_len(b)); + if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL) + fatal("%s: BN_bin2bn failed", __func__); + if ((r = sshbuf_consume(b, bytes)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } -static Key * +static struct sshkey * do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) { - Buffer b; - Key *key = NULL; + struct sshbuf *b; + struct sshkey *key = NULL; char *type, *cipher; - u_char *sig, data[] = "abcde12345"; - int magic, rlen, ktype, i1, i2, i3, i4; - u_int slen; + u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345"; + int r, rlen, ktype; + u_int magic, i1, i2, i3, i4; + size_t slen; u_long e; - buffer_init(&b); - buffer_append(&b, blob, blen); + if ((b = sshbuf_from(blob, blen)) == NULL) + fatal("%s: sshbuf_from failed", __func__); + if ((r = sshbuf_get_u32(b, &magic)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - magic = buffer_get_int(&b); if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { - error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC); - buffer_free(&b); + error("bad magic 0x%x != 0x%x", magic, + SSH_COM_PRIVATE_KEY_MAGIC); + sshbuf_free(b); return NULL; } - i1 = buffer_get_int(&b); - type = buffer_get_string(&b, NULL); - cipher = buffer_get_string(&b, NULL); - i2 = buffer_get_int(&b); - i3 = buffer_get_int(&b); - i4 = buffer_get_int(&b); + if ((r = sshbuf_get_u32(b, &i1)) != 0 || + (r = sshbuf_get_cstring(b, &type, NULL)) != 0 || + (r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 || + (r = sshbuf_get_u32(b, &i2)) != 0 || + (r = sshbuf_get_u32(b, &i3)) != 0 || + (r = sshbuf_get_u32(b, &i4)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("ignore (%d %d %d %d)", i1, i2, i3, i4); if (strcmp(cipher, "none") != 0) { error("unsupported cipher %s", cipher); free(cipher); - buffer_free(&b); + sshbuf_free(b); free(type); return NULL; } @@ -443,54 +471,64 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) } else if (strstr(type, "rsa")) { ktype = KEY_RSA; } else { - buffer_free(&b); + sshbuf_free(b); free(type); return NULL; } - key = key_new_private(ktype); + if ((key = sshkey_new_private(ktype)) == NULL) + fatal("key_new_private failed"); free(type); switch (key->type) { case KEY_DSA: - buffer_get_bignum_bits(&b, key->dsa->p); - buffer_get_bignum_bits(&b, key->dsa->g); - buffer_get_bignum_bits(&b, key->dsa->q); - buffer_get_bignum_bits(&b, key->dsa->pub_key); - buffer_get_bignum_bits(&b, key->dsa->priv_key); + buffer_get_bignum_bits(b, key->dsa->p); + buffer_get_bignum_bits(b, key->dsa->g); + buffer_get_bignum_bits(b, key->dsa->q); + buffer_get_bignum_bits(b, key->dsa->pub_key); + buffer_get_bignum_bits(b, key->dsa->priv_key); break; case KEY_RSA: - e = buffer_get_char(&b); + if ((r = sshbuf_get_u8(b, &e1)) != 0 || + (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || + (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0)) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + e = e1; debug("e %lx", e); if (e < 30) { e <<= 8; - e += buffer_get_char(&b); + e += e2; debug("e %lx", e); e <<= 8; - e += buffer_get_char(&b); + e += e3; debug("e %lx", e); } if (!BN_set_word(key->rsa->e, e)) { - buffer_free(&b); - key_free(key); + sshbuf_free(b); + sshkey_free(key); return NULL; } - buffer_get_bignum_bits(&b, key->rsa->d); - buffer_get_bignum_bits(&b, key->rsa->n); - buffer_get_bignum_bits(&b, key->rsa->iqmp); - buffer_get_bignum_bits(&b, key->rsa->q); - buffer_get_bignum_bits(&b, key->rsa->p); - rsa_generate_additional_parameters(key->rsa); + buffer_get_bignum_bits(b, key->rsa->d); + buffer_get_bignum_bits(b, key->rsa->n); + buffer_get_bignum_bits(b, key->rsa->iqmp); + buffer_get_bignum_bits(b, key->rsa->q); + buffer_get_bignum_bits(b, key->rsa->p); + if ((r = rsa_generate_additional_parameters(key->rsa)) != 0) + fatal("generate RSA parameters failed: %s", ssh_err(r)); break; } - rlen = buffer_len(&b); + rlen = sshbuf_len(b); if (rlen != 0) error("do_convert_private_ssh2_from_blob: " "remaining bytes in key blob %d", rlen); - buffer_free(&b); + sshbuf_free(b); /* try the key */ - key_sign(key, &sig, &slen, data, sizeof(data)); - key_verify(key, sig, slen, data, sizeof(data)); + if (sshkey_sign(key, &sig, &slen, data, sizeof(data), 0) != 0 || + sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) { + sshkey_free(key); + free(sig); + return NULL; + } free(sig); return key; } @@ -503,17 +541,13 @@ get_line(FILE *fp, char *line, size_t len) line[0] = '\0'; while ((c = fgetc(fp)) != EOF) { - if (pos >= len - 1) { - fprintf(stderr, "input line too long.\n"); - exit(1); - } + if (pos >= len - 1) + fatal("input line too long."); switch (c) { case '\r': c = fgetc(fp); - if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) { - fprintf(stderr, "unget: %s\n", strerror(errno)); - exit(1); - } + if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) + fatal("unget: %s", strerror(errno)); return pos; case '\n': return pos; @@ -526,14 +560,13 @@ get_line(FILE *fp, char *line, size_t len) } static void -do_convert_from_ssh2(struct passwd *pw, Key **k, int *private) +do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private) { - int blen; + int r, blen, escaped = 0; u_int len; char line[1024]; u_char blob[8096]; char encoded[8096]; - int escaped = 0; FILE *fp; if ((fp = fopen(identity_file, "r")) == NULL) @@ -566,22 +599,17 @@ do_convert_from_ssh2(struct passwd *pw, Key **k, int *private) (encoded[len-3] == '=')) encoded[len-3] = '\0'; blen = uudecode(encoded, blob, sizeof(blob)); - if (blen < 0) { - fprintf(stderr, "uudecode failed.\n"); - exit(1); - } - *k = *private ? - do_convert_private_ssh2_from_blob(blob, blen) : - key_from_blob(blob, blen); - if (*k == NULL) { - fprintf(stderr, "decode blob failed.\n"); - exit(1); - } + if (blen < 0) + fatal("uudecode failed."); + if (*private) + *k = do_convert_private_ssh2_from_blob(blob, blen); + else if ((r = sshkey_from_blob(blob, blen, k)) != 0) + fatal("decode blob failed: %s", ssh_err(r)); fclose(fp); } static void -do_convert_from_pkcs8(Key **k, int *private) +do_convert_from_pkcs8(struct sshkey **k, int *private) { EVP_PKEY *pubkey; FILE *fp; @@ -595,21 +623,24 @@ do_convert_from_pkcs8(Key **k, int *private) fclose(fp); switch (EVP_PKEY_type(pubkey->type)) { case EVP_PKEY_RSA: - *k = key_new(KEY_UNSPEC); + if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); (*k)->type = KEY_RSA; (*k)->rsa = EVP_PKEY_get1_RSA(pubkey); break; case EVP_PKEY_DSA: - *k = key_new(KEY_UNSPEC); + if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); (*k)->type = KEY_DSA; (*k)->dsa = EVP_PKEY_get1_DSA(pubkey); break; #ifdef OPENSSL_HAS_ECC case EVP_PKEY_EC: - *k = key_new(KEY_UNSPEC); + if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); (*k)->type = KEY_ECDSA; (*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey); - (*k)->ecdsa_nid = key_ecdsa_key_to_nid((*k)->ecdsa); + (*k)->ecdsa_nid = sshkey_ecdsa_key_to_nid((*k)->ecdsa); break; #endif default: @@ -621,7 +652,7 @@ do_convert_from_pkcs8(Key **k, int *private) } static void -do_convert_from_pem(Key **k, int *private) +do_convert_from_pem(struct sshkey **k, int *private) { FILE *fp; RSA *rsa; @@ -632,7 +663,8 @@ do_convert_from_pem(Key **k, int *private) if ((fp = fopen(identity_file, "r")) == NULL) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) { - *k = key_new(KEY_UNSPEC); + if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); (*k)->type = KEY_RSA; (*k)->rsa = rsa; fclose(fp); @@ -641,7 +673,8 @@ do_convert_from_pem(Key **k, int *private) #if notyet /* OpenSSH 0.9.8 lacks this function */ rewind(fp); if ((dsa = PEM_read_DSAPublicKey(fp, NULL, NULL, NULL)) != NULL) { - *k = key_new(KEY_UNSPEC); + if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); (*k)->type = KEY_DSA; (*k)->dsa = dsa; fclose(fp); @@ -655,8 +688,8 @@ do_convert_from_pem(Key **k, int *private) static void do_convert_from(struct passwd *pw) { - Key *k = NULL; - int private = 0, ok = 0; + struct sshkey *k = NULL; + int r, private = 0, ok = 0; struct stat st; if (!have_identity) @@ -678,11 +711,12 @@ do_convert_from(struct passwd *pw) fatal("%s: unknown key format %d", __func__, convert_format); } - if (!private) - ok = key_write(k, stdout); + if (!private) { + if ((r = sshkey_write(k, stdout)) == 0) + ok = 1; if (ok) fprintf(stdout, "\n"); - else { + } else { switch (k->type) { case KEY_DSA: ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, @@ -700,38 +734,32 @@ do_convert_from(struct passwd *pw) break; default: fatal("%s: unsupported key type %s", __func__, - key_type(k)); + sshkey_type(k)); } } - if (!ok) { - fprintf(stderr, "key write failed\n"); - exit(1); - } - key_free(k); + if (!ok) + fatal("key write failed"); + sshkey_free(k); exit(0); } +#endif static void do_print_public(struct passwd *pw) { - Key *prv; + struct sshkey *prv; struct stat st; + int r; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } + if (stat(identity_file, &st) < 0) + fatal("%s: %s", identity_file, strerror(errno)); prv = load_identity(identity_file); - if (prv == NULL) { - fprintf(stderr, "load failed\n"); - exit(1); - } - if (!key_write(prv, stdout)) - fprintf(stderr, "key_write failed"); - key_free(prv); + if ((r = sshkey_write(prv, stdout)) != 0) + error("key_write failed: %s", ssh_err(r)); + sshkey_free(prv); fprintf(stdout, "\n"); exit(0); } @@ -740,14 +768,14 @@ static void do_download(struct passwd *pw) { #ifdef ENABLE_PKCS11 - Key **keys = NULL; + struct sshkey **keys = NULL; int i, nkeys; - enum fp_rep rep; - enum fp_type fptype; + enum sshkey_fp_rep rep; + int fptype; char *fp, *ra; - fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; + fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; pkcs11_init(0); nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys); @@ -755,20 +783,22 @@ do_download(struct passwd *pw) fatal("cannot read public key from pkcs11"); for (i = 0; i < nkeys; i++) { if (print_fingerprint) { - fp = key_fingerprint(keys[i], fptype, rep); - ra = key_fingerprint(keys[i], SSH_FP_MD5, + fp = sshkey_fingerprint(keys[i], fptype, rep); + ra = sshkey_fingerprint(keys[i], fingerprint_hash, SSH_FP_RANDOMART); - printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]), - fp, key_type(keys[i])); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); + printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]), + fp, sshkey_type(keys[i])); if (log_level >= SYSLOG_LEVEL_VERBOSE) printf("%s\n", ra); free(ra); free(fp); } else { - key_write(keys[i], stdout); + (void) sshkey_write(keys[i], stdout); /* XXX check */ fprintf(stdout, "\n"); } - key_free(keys[i]); + sshkey_free(keys[i]); } free(keys); pkcs11_terminate(); @@ -782,31 +812,33 @@ static void do_fingerprint(struct passwd *pw) { FILE *f; - Key *public; + struct sshkey *public; char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; - int i, skip = 0, num = 0, invalid = 1; - enum fp_rep rep; - enum fp_type fptype; + int r, i, skip = 0, num = 0, invalid = 1; + enum sshkey_fp_rep rep; + int fptype; struct stat st; - fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; - + fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - public = key_load_public(identity_file, &comment); - if (public != NULL) { - fp = key_fingerprint(public, fptype, rep); - ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); - printf("%u %s %s (%s)\n", key_size(public), fp, comment, - key_type(public)); + if (stat(identity_file, &st) < 0) + fatal("%s: %s", identity_file, strerror(errno)); + if ((r = sshkey_load_public(identity_file, &public, &comment)) != 0) + debug2("Error loading public key \"%s\": %s", + identity_file, ssh_err(r)); + else { + fp = sshkey_fingerprint(public, fptype, rep); + ra = sshkey_fingerprint(public, fingerprint_hash, + SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); + printf("%u %s %s (%s)\n", sshkey_size(public), fp, comment, + sshkey_type(public)); if (log_level >= SYSLOG_LEVEL_VERBOSE) printf("%s\n", ra); - key_free(public); + sshkey_free(public); free(comment); free(ra); free(fp); @@ -855,34 +887,37 @@ do_fingerprint(struct passwd *pw) *cp++ = '\0'; } ep = cp; - public = key_new(KEY_RSA1); - if (key_read(public, &cp) != 1) { + if ((public = sshkey_new(KEY_RSA1)) == NULL) + fatal("sshkey_new failed"); + if ((r = sshkey_read(public, &cp)) != 0) { cp = ep; - key_free(public); - public = key_new(KEY_UNSPEC); - if (key_read(public, &cp) != 1) { - key_free(public); + sshkey_free(public); + if ((public = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); + if ((r = sshkey_read(public, &cp)) != 0) { + sshkey_free(public); continue; } } comment = *cp ? cp : comment; - fp = key_fingerprint(public, fptype, rep); - ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); - printf("%u %s %s (%s)\n", key_size(public), fp, - comment ? comment : "no comment", key_type(public)); + fp = sshkey_fingerprint(public, fptype, rep); + ra = sshkey_fingerprint(public, fingerprint_hash, + SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); + printf("%u %s %s (%s)\n", sshkey_size(public), fp, + comment ? comment : "no comment", sshkey_type(public)); if (log_level >= SYSLOG_LEVEL_VERBOSE) printf("%s\n", ra); free(ra); free(fp); - key_free(public); + sshkey_free(public); invalid = 0; } fclose(f); - if (invalid) { - printf("%s is not a public key file.\n", identity_file); - exit(1); - } + if (invalid) + fatal("%s is not a public key file.", identity_file); exit(0); } @@ -894,28 +929,32 @@ do_gen_all_hostkeys(struct passwd *pw) char *key_type_display; char *path; } key_types[] = { +#ifdef WITH_OPENSSL +#ifdef WITH_SSH1 { "rsa1", "RSA1", _PATH_HOST_KEY_FILE }, +#endif /* WITH_SSH1 */ { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE }, #ifdef OPENSSL_HAS_ECC { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE }, -#endif +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ { "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE }, { NULL, NULL, NULL } }; int first = 0; struct stat st; - Key *private, *public; + struct sshkey *private, *public; char comment[1024]; - int i, type, fd; + int i, type, fd, r; FILE *f; for (i = 0; key_types[i].key_type; i++) { if (stat(key_types[i].path, &st) == 0) continue; if (errno != ENOENT) { - printf("Could not stat %s: %s", key_types[i].path, + error("Could not stat %s: %s", key_types[i].path, strerror(errno)); first = 0; continue; @@ -927,97 +966,185 @@ do_gen_all_hostkeys(struct passwd *pw) } printf("%s ", key_types[i].key_type_display); fflush(stdout); - type = key_type_from_name(key_types[i].key_type); + type = sshkey_type_from_name(key_types[i].key_type); strlcpy(identity_file, key_types[i].path, sizeof(identity_file)); bits = 0; - type_bits_valid(type, &bits); - private = key_generate(type, bits); - if (private == NULL) { - fprintf(stderr, "key_generate failed\n"); + type_bits_valid(type, NULL, &bits); + if ((r = sshkey_generate(type, bits, &private)) != 0) { + error("key_generate failed: %s", ssh_err(r)); first = 0; continue; } - public = key_from_private(private); + if ((r = sshkey_from_private(private, &public)) != 0) + fatal("sshkey_from_private failed: %s", ssh_err(r)); snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); - if (!key_save_private(private, identity_file, "", comment, - use_new_format, new_format_cipher, rounds)) { - printf("Saving the key failed: %s.\n", identity_file); - key_free(private); - key_free(public); + if ((r = sshkey_save_private(private, identity_file, "", + comment, use_new_format, new_format_cipher, rounds)) != 0) { + error("Saving key \"%s\" failed: %s", + identity_file, ssh_err(r)); + sshkey_free(private); + sshkey_free(public); first = 0; continue; } - key_free(private); + sshkey_free(private); strlcat(identity_file, ".pub", sizeof(identity_file)); fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { - printf("Could not save your public key in %s\n", + error("Could not save your public key in %s", identity_file); - key_free(public); + sshkey_free(public); first = 0; continue; } f = fdopen(fd, "w"); if (f == NULL) { - printf("fdopen %s failed\n", identity_file); - key_free(public); + error("fdopen %s failed", identity_file); + close(fd); + sshkey_free(public); first = 0; continue; } - if (!key_write(public, f)) { - fprintf(stderr, "write key failed\n"); - key_free(public); + if ((r = sshkey_write(public, f)) != 0) { + error("write key failed: %s", ssh_err(r)); + fclose(f); + sshkey_free(public); first = 0; continue; } fprintf(f, " %s\n", comment); fclose(f); - key_free(public); + sshkey_free(public); } if (first != 0) printf("\n"); } -static void -printhost(FILE *f, const char *name, Key *public, int ca, int hash) +struct known_hosts_ctx { + const char *host; /* Hostname searched for in find/delete case */ + FILE *out; /* Output file, stdout for find_hosts case */ + int has_unhashed; /* When hashing, original had unhashed hosts */ + int found_key; /* For find/delete, host was found */ + int invalid; /* File contained invalid items; don't delete */ +}; + +static int +known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx) { - if (print_fingerprint) { - enum fp_rep rep; - enum fp_type fptype; - char *fp, *ra; - - fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; - fp = key_fingerprint(public, fptype, rep); - ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); - printf("%u %s %s (%s)\n", key_size(public), fp, name, - key_type(public)); - if (log_level >= SYSLOG_LEVEL_VERBOSE) - printf("%s\n", ra); - free(ra); - free(fp); - } else { - if (hash && (name = host_hash(name, NULL, 0)) == NULL) - fatal("hash_host failed"); - fprintf(f, "%s%s%s ", ca ? CA_MARKER : "", ca ? " " : "", name); - if (!key_write(public, f)) - fatal("key_write failed"); - fprintf(f, "\n"); + struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx; + char *hashed, *cp, *hosts, *ohosts; + int has_wild = l->hosts && strcspn(l->hosts, "*?!") != strlen(l->hosts); + + switch (l->status) { + case HKF_STATUS_OK: + case HKF_STATUS_MATCHED: + /* + * Don't hash hosts already already hashed, with wildcard + * characters or a CA/revocation marker. + */ + if ((l->match & HKF_MATCH_HOST_HASHED) != 0 || + has_wild || l->marker != MRK_NONE) { + fprintf(ctx->out, "%s\n", l->line); + if (has_wild && !find_host) { + logit("%s:%ld: ignoring host name " + "with wildcard: %.64s", l->path, + l->linenum, l->hosts); + } + return 0; + } + /* + * Split any comma-separated hostnames from the host list, + * hash and store separately. + */ + ohosts = hosts = xstrdup(l->hosts); + while ((cp = strsep(&hosts, ",")) != NULL && *cp != '\0') { + if ((hashed = host_hash(cp, NULL, 0)) == NULL) + fatal("hash_host failed"); + fprintf(ctx->out, "%s %s\n", hashed, l->rawkey); + ctx->has_unhashed = 1; + } + free(ohosts); + return 0; + case HKF_STATUS_INVALID: + /* Retain invalid lines, but mark file as invalid. */ + ctx->invalid = 1; + logit("%s:%ld: invalid line", l->path, l->linenum); + /* FALLTHROUGH */ + default: + fprintf(ctx->out, "%s\n", l->line); + return 0; } + /* NOTREACHED */ + return -1; +} + +static int +known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx) +{ + struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx; + enum sshkey_fp_rep rep; + int fptype; + char *fp; + + fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; + + if (l->status == HKF_STATUS_MATCHED) { + if (delete_host) { + if (l->marker != MRK_NONE) { + /* Don't remove CA and revocation lines */ + fprintf(ctx->out, "%s\n", l->line); + } else { + /* + * Hostname matches and has no CA/revoke + * marker, delete it by *not* writing the + * line to ctx->out. + */ + ctx->found_key = 1; + if (!quiet) + printf("# Host %s found: line %ld\n", + ctx->host, l->linenum); + } + return 0; + } else if (find_host) { + ctx->found_key = 1; + if (!quiet) { + printf("# Host %s found: line %ld %s\n", + ctx->host, + l->linenum, l->marker == MRK_CA ? "CA" : + (l->marker == MRK_REVOKE ? "REVOKED" : "")); + } + if (hash_hosts) + known_hosts_hash(l, ctx); + else if (print_fingerprint) { + fp = sshkey_fingerprint(l->key, fptype, rep); + printf("%s %s %s %s\n", ctx->host, + sshkey_type(l->key), fp, l->comment); + free(fp); + } else + fprintf(ctx->out, "%s\n", l->line); + return 0; + } + } else if (delete_host) { + /* Retain non-matching hosts when deleting */ + if (l->status == HKF_STATUS_INVALID) { + ctx->invalid = 1; + logit("%s:%ld: invalid line", l->path, l->linenum); + } + fprintf(ctx->out, "%s\n", l->line); + } + return 0; } static void do_known_hosts(struct passwd *pw, const char *name) { - FILE *in, *out = stdout; - Key *pub; - char *cp, *cp2, *kp, *kp2; - char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; - int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; - int ca; - int found_key = 0; + char *cp, tmp[PATH_MAX], old[PATH_MAX]; + int r, fd, oerrno, inplace = 0; + struct known_hosts_ctx ctx; + u_int foreach_options; if (!have_identity) { cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); @@ -1027,8 +1154,10 @@ do_known_hosts(struct passwd *pw, const char *name) free(cp); have_identity = 1; } - if ((in = fopen(identity_file, "r")) == NULL) - fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); + + memset(&ctx, 0, sizeof(ctx)); + ctx.out = stdout; + ctx.host = name; /* * Find hosts goes to stdout, hash and deletions happen in-place @@ -1041,166 +1170,40 @@ do_known_hosts(struct passwd *pw, const char *name) strlcat(old, ".old", sizeof(old)) >= sizeof(old)) fatal("known_hosts path too long"); umask(077); - if ((c = mkstemp(tmp)) == -1) + if ((fd = mkstemp(tmp)) == -1) fatal("mkstemp: %s", strerror(errno)); - if ((out = fdopen(c, "w")) == NULL) { - c = errno; + if ((ctx.out = fdopen(fd, "w")) == NULL) { + oerrno = errno; unlink(tmp); - fatal("fdopen: %s", strerror(c)); + fatal("fdopen: %s", strerror(oerrno)); } inplace = 1; } - while (fgets(line, sizeof(line), in)) { - if ((cp = strchr(line, '\n')) == NULL) { - error("line %d too long: %.40s...", num + 1, line); - skip = 1; - invalid = 1; - continue; - } - num++; - if (skip) { - skip = 0; - continue; - } - *cp = '\0'; + /* XXX support identity_file == "-" for stdin */ + foreach_options = find_host ? HKF_WANT_MATCH : 0; + foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0; + if ((r = hostkeys_foreach(identity_file, + hash_hosts ? known_hosts_hash : known_hosts_find_delete, &ctx, + name, NULL, foreach_options)) != 0) + fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r)); - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') { - if (inplace) - fprintf(out, "%s\n", cp); - continue; - } - /* Check whether this is a CA key */ - if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 && - (cp[sizeof(CA_MARKER) - 1] == ' ' || - cp[sizeof(CA_MARKER) - 1] == '\t')) { - ca = 1; - cp += sizeof(CA_MARKER); - } else - ca = 0; - - /* Find the end of the host name portion. */ - for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++) - ; + if (inplace) + fclose(ctx.out); - if (*kp == '\0' || *(kp + 1) == '\0') { - error("line %d missing key: %.40s...", - num, line); - invalid = 1; - continue; - } - *kp++ = '\0'; - kp2 = kp; - - pub = key_new(KEY_RSA1); - if (key_read(pub, &kp) != 1) { - kp = kp2; - key_free(pub); - pub = key_new(KEY_UNSPEC); - if (key_read(pub, &kp) != 1) { - error("line %d invalid key: %.40s...", - num, line); - key_free(pub); - invalid = 1; - continue; - } - } - - if (*cp == HASH_DELIM) { - if (find_host || delete_host) { - cp2 = host_hash(name, cp, strlen(cp)); - if (cp2 == NULL) { - error("line %d: invalid hashed " - "name: %.64s...", num, line); - invalid = 1; - continue; - } - c = (strcmp(cp2, cp) == 0); - if (find_host && c) { - if (!quiet) - printf("# Host %s found: " - "line %d type %s%s\n", name, - num, key_type(pub), - ca ? " (CA key)" : ""); - printhost(out, cp, pub, ca, 0); - found_key = 1; - } - if (delete_host) { - if (!c && !ca) - printhost(out, cp, pub, ca, 0); - else - printf("# Host %s found: " - "line %d type %s\n", name, - num, key_type(pub)); - } - } else if (hash_hosts) - printhost(out, cp, pub, ca, 0); - } else { - if (find_host || delete_host) { - c = (match_hostname(name, cp, - strlen(cp)) == 1); - if (find_host && c) { - if (!quiet) - printf("# Host %s found: " - "line %d type %s%s\n", name, - num, key_type(pub), - ca ? " (CA key)" : ""); - printhost(out, name, pub, - ca, hash_hosts && !ca); - found_key = 1; - } - if (delete_host) { - if (!c && !ca) - printhost(out, cp, pub, ca, 0); - else - printf("# Host %s found: " - "line %d type %s\n", name, - num, key_type(pub)); - } - } else if (hash_hosts) { - for (cp2 = strsep(&cp, ","); - cp2 != NULL && *cp2 != '\0'; - cp2 = strsep(&cp, ",")) { - if (ca) { - fprintf(stderr, "Warning: " - "ignoring CA key for host: " - "%.64s\n", cp2); - printhost(out, cp2, pub, ca, 0); - } else if (strcspn(cp2, "*?!") != - strlen(cp2)) { - fprintf(stderr, "Warning: " - "ignoring host name with " - "metacharacters: %.64s\n", - cp2); - printhost(out, cp2, pub, ca, 0); - } else - printhost(out, cp2, pub, ca, 1); - } - has_unhashed = 1; - } - } - key_free(pub); - } - fclose(in); - - if (invalid) { - fprintf(stderr, "%s is not a valid known_hosts file.\n", - identity_file); + if (ctx.invalid) { + error("%s is not a valid known_hosts file.", identity_file); if (inplace) { - fprintf(stderr, "Not replacing existing known_hosts " - "file because of errors\n"); - fclose(out); + error("Not replacing existing known_hosts " + "file because of errors"); unlink(tmp); } exit(1); - } - - if (inplace) { - fclose(out); - + } else if (delete_host && !ctx.found_key) { + logit("Host %s not found in %s", name, identity_file); + if (inplace) + unlink(tmp); + } else if (inplace) { /* Backup existing file */ if (unlink(old) == -1 && errno != ENOENT) fatal("unlink %.100s: %s", old, strerror(errno)); @@ -1216,17 +1219,16 @@ do_known_hosts(struct passwd *pw, const char *name) exit(1); } - fprintf(stderr, "%s updated.\n", identity_file); - fprintf(stderr, "Original contents retained as %s\n", old); - if (has_unhashed) { - fprintf(stderr, "WARNING: %s contains unhashed " - "entries\n", old); - fprintf(stderr, "Delete this file to ensure privacy " - "of hostnames\n"); + printf("%s updated.\n", identity_file); + printf("Original contents retained as %s\n", old); + if (ctx.has_unhashed) { + logit("WARNING: %s contains unhashed entries", old); + logit("Delete this file to ensure privacy " + "of hostnames"); } } - exit (find_host && !found_key); + exit (find_host && !ctx.found_key); } /* @@ -1239,33 +1241,34 @@ do_change_passphrase(struct passwd *pw) char *comment; char *old_passphrase, *passphrase1, *passphrase2; struct stat st; - Key *private; + struct sshkey *private; + int r; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } + if (stat(identity_file, &st) < 0) + fatal("%s: %s", identity_file, strerror(errno)); /* Try to load the file with empty passphrase. */ - private = key_load_private(identity_file, "", &comment); - if (private == NULL) { + r = sshkey_load_private(identity_file, "", &private, &comment); + if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) { if (identity_passphrase) old_passphrase = xstrdup(identity_passphrase); else old_passphrase = read_passphrase("Enter old passphrase: ", RP_ALLOW_STDIN); - private = key_load_private(identity_file, old_passphrase, - &comment); + r = sshkey_load_private(identity_file, old_passphrase, + &private, &comment); explicit_bzero(old_passphrase, strlen(old_passphrase)); free(old_passphrase); - if (private == NULL) { - printf("Bad passphrase.\n"); - exit(1); - } + if (r != 0) + goto badkey; + } else if (r != 0) { + badkey: + fatal("Failed to load key %s: %s", identity_file, ssh_err(r)); } - printf("Key has comment '%s'\n", comment); + if (comment) + printf("Key has comment '%s'\n", comment); /* Ask the new passphrase (twice). */ if (identity_new_passphrase) { @@ -1293,19 +1296,20 @@ do_change_passphrase(struct passwd *pw) } /* Save the file using the new passphrase. */ - if (!key_save_private(private, identity_file, passphrase1, comment, - use_new_format, new_format_cipher, rounds)) { - printf("Saving the key failed: %s.\n", identity_file); + if ((r = sshkey_save_private(private, identity_file, passphrase1, + comment, use_new_format, new_format_cipher, rounds)) != 0) { + error("Saving key \"%s\" failed: %s.", + identity_file, ssh_err(r)); explicit_bzero(passphrase1, strlen(passphrase1)); free(passphrase1); - key_free(private); + sshkey_free(private); free(comment); exit(1); } /* Destroy the passphrase and the copy of the key in memory. */ explicit_bzero(passphrase1, strlen(passphrase1)); free(passphrase1); - key_free(private); /* Destroys contents */ + sshkey_free(private); /* Destroys contents */ free(comment); printf("Your identification has been saved with the new passphrase.\n"); @@ -1318,30 +1322,25 @@ do_change_passphrase(struct passwd *pw) static int do_print_resource_record(struct passwd *pw, char *fname, char *hname) { - Key *public; + struct sshkey *public; char *comment = NULL; struct stat st; + int r; if (fname == NULL) fatal("%s: no filename", __func__); if (stat(fname, &st) < 0) { if (errno == ENOENT) return 0; - perror(fname); - exit(1); - } - public = key_load_public(fname, &comment); - if (public != NULL) { - export_dns_rr(hname, public, stdout, print_generic); - key_free(public); - free(comment); - return 1; + fatal("%s: %s", fname, strerror(errno)); } - if (comment) - free(comment); - - printf("failed to read v2 public key from %s.\n", fname); - exit(1); + if ((r = sshkey_load_public(fname, &public, &comment)) != 0) + fatal("Failed to read v2 public key from \"%s\": %s.", + fname, ssh_err(r)); + export_dns_rr(hname, public, stdout, print_generic); + sshkey_free(public); + free(comment); + return 1; } /* @@ -1351,20 +1350,23 @@ static void do_change_comment(struct passwd *pw) { char new_comment[1024], *comment, *passphrase; - Key *private; - Key *public; + struct sshkey *private; + struct sshkey *public; struct stat st; FILE *f; - int fd; + int r, fd; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); - if (stat(identity_file, &st) < 0) { - perror(identity_file); - exit(1); - } - private = key_load_private(identity_file, "", &comment); - if (private == NULL) { + if (stat(identity_file, &st) < 0) + fatal("%s: %s", identity_file, strerror(errno)); + if ((r = sshkey_load_private(identity_file, "", + &private, &comment)) == 0) + passphrase = xstrdup(""); + else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) + fatal("Cannot load private key \"%s\": %s.", + identity_file, ssh_err(r)); + else { if (identity_passphrase) passphrase = xstrdup(identity_passphrase); else if (identity_new_passphrase) @@ -1373,19 +1375,19 @@ do_change_comment(struct passwd *pw) passphrase = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); /* Try to load using the passphrase. */ - private = key_load_private(identity_file, passphrase, &comment); - if (private == NULL) { + if ((r = sshkey_load_private(identity_file, passphrase, + &private, &comment)) != 0) { explicit_bzero(passphrase, strlen(passphrase)); free(passphrase); - printf("Bad passphrase.\n"); - exit(1); + fatal("Cannot load private key \"%s\": %s.", + identity_file, ssh_err(r)); } - } else { - passphrase = xstrdup(""); } + /* XXX what about new-format keys? */ if (private->type != KEY_RSA1) { - fprintf(stderr, "Comments are only supported for RSA1 keys.\n"); - key_free(private); + error("Comments are only supported for RSA1 keys."); + explicit_bzero(passphrase, strlen(passphrase)); + sshkey_free(private); exit(1); } printf("Key now has comment '%s'\n", comment); @@ -1397,41 +1399,39 @@ do_change_comment(struct passwd *pw) fflush(stdout); if (!fgets(new_comment, sizeof(new_comment), stdin)) { explicit_bzero(passphrase, strlen(passphrase)); - key_free(private); + sshkey_free(private); exit(1); } new_comment[strcspn(new_comment, "\n")] = '\0'; } /* Save the file using the new passphrase. */ - if (!key_save_private(private, identity_file, passphrase, new_comment, - use_new_format, new_format_cipher, rounds)) { - printf("Saving the key failed: %s.\n", identity_file); + if ((r = sshkey_save_private(private, identity_file, passphrase, + new_comment, use_new_format, new_format_cipher, rounds)) != 0) { + error("Saving key \"%s\" failed: %s", + identity_file, ssh_err(r)); explicit_bzero(passphrase, strlen(passphrase)); free(passphrase); - key_free(private); + sshkey_free(private); free(comment); exit(1); } explicit_bzero(passphrase, strlen(passphrase)); free(passphrase); - public = key_from_private(private); - key_free(private); + if ((r = sshkey_from_private(private, &public)) != 0) + fatal("key_from_private failed: %s", ssh_err(r)); + sshkey_free(private); strlcat(identity_file, ".pub", sizeof(identity_file)); fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - printf("Could not save your public key in %s\n", identity_file); - exit(1); - } + if (fd == -1) + fatal("Could not save your public key in %s", identity_file); f = fdopen(fd, "w"); - if (f == NULL) { - printf("fdopen %s failed\n", identity_file); - exit(1); - } - if (!key_write(public, f)) - fprintf(stderr, "write key failed\n"); - key_free(public); + if (f == NULL) + fatal("fdopen %s failed: %s", identity_file, strerror(errno)); + if ((r = sshkey_write(public, f)) != 0) + fatal("write key failed: %s", ssh_err(r)); + sshkey_free(public); fprintf(f, " %s\n", new_comment); fclose(f); @@ -1480,34 +1480,39 @@ fmt_validity(u_int64_t valid_from, u_int64_t valid_to) } static void -add_flag_option(Buffer *c, const char *name) +add_flag_option(struct sshbuf *c, const char *name) { + int r; + debug3("%s: %s", __func__, name); - buffer_put_cstring(c, name); - buffer_put_string(c, NULL, 0); + if ((r = sshbuf_put_cstring(c, name)) != 0 || + (r = sshbuf_put_string(c, NULL, 0)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); } static void -add_string_option(Buffer *c, const char *name, const char *value) +add_string_option(struct sshbuf *c, const char *name, const char *value) { - Buffer b; + struct sshbuf *b; + int r; debug3("%s: %s=%s", __func__, name, value); - buffer_init(&b); - buffer_put_cstring(&b, value); - - buffer_put_cstring(c, name); - buffer_put_string(c, buffer_ptr(&b), buffer_len(&b)); - - buffer_free(&b); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_put_cstring(b, value)) != 0 || + (r = sshbuf_put_cstring(c, name)) != 0 || + (r = sshbuf_put_stringb(c, b)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + sshbuf_free(b); } #define OPTIONS_CRITICAL 1 #define OPTIONS_EXTENSIONS 2 static void -prepare_options_buf(Buffer *c, int which) +prepare_options_buf(struct sshbuf *c, int which) { - buffer_clear(c); + sshbuf_reset(c); if ((which & OPTIONS_CRITICAL) != 0 && certflags_command != NULL) add_string_option(c, "force-command", certflags_command); @@ -1531,29 +1536,30 @@ prepare_options_buf(Buffer *c, int which) add_string_option(c, "source-address", certflags_src_addr); } -static Key * +static struct sshkey * load_pkcs11_key(char *path) { #ifdef ENABLE_PKCS11 - Key **keys = NULL, *public, *private = NULL; - int i, nkeys; + struct sshkey **keys = NULL, *public, *private = NULL; + int r, i, nkeys; - if ((public = key_load_public(path, NULL)) == NULL) - fatal("Couldn't load CA public key \"%s\"", path); + if ((r = sshkey_load_public(path, &public, NULL)) != 0) + fatal("Couldn't load CA public key \"%s\": %s", + path, ssh_err(r)); nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys); debug3("%s: %d keys", __func__, nkeys); if (nkeys <= 0) fatal("cannot read public key from pkcs11"); for (i = 0; i < nkeys; i++) { - if (key_equal_public(public, keys[i])) { + if (sshkey_equal_public(public, keys[i])) { private = keys[i]; continue; } - key_free(keys[i]); + sshkey_free(keys[i]); } free(keys); - key_free(public); + sshkey_free(public); return private; #else fatal("no pkcs11 support"); @@ -1563,39 +1569,21 @@ load_pkcs11_key(char *path) static void do_ca_sign(struct passwd *pw, int argc, char **argv) { - int i, fd; + int r, i, fd; u_int n; - Key *ca, *public; + struct sshkey *ca, *public; char *otmp, *tmp, *cp, *out, *comment, **plist = NULL; FILE *f; - int v00 = 0; /* legacy keys */ - - if (key_type_name != NULL) { - switch (key_type_from_name(key_type_name)) { - case KEY_RSA_CERT_V00: - case KEY_DSA_CERT_V00: - v00 = 1; - break; - case KEY_UNSPEC: - if (strcasecmp(key_type_name, "v00") == 0) { - v00 = 1; - break; - } else if (strcasecmp(key_type_name, "v01") == 0) - break; - /* FALLTHROUGH */ - default: - fprintf(stderr, "unknown key type %s\n", key_type_name); - exit(1); - } - } +#ifdef ENABLE_PKCS11 pkcs11_init(1); +#endif tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); if (pkcs11provider != NULL) { if ((ca = load_pkcs11_key(tmp)) == NULL) fatal("No PKCS#11 key matching %s found", ca_key_path); - } else if ((ca = load_identity(tmp)) == NULL) - fatal("Couldn't load CA key \"%s\"", tmp); + } else + ca = load_identity(tmp); free(tmp); for (i = 0; i < argc; i++) { @@ -1605,7 +1593,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) otmp = tmp = xstrdup(cert_principals); plist = NULL; for (; (cp = strsep(&tmp, ",")) != NULL; n++) { - plist = xrealloc(plist, n + 1, sizeof(*plist)); + plist = xreallocarray(plist, n + 1, sizeof(*plist)); if (*(plist[n] = xstrdup(cp)) == '\0') fatal("Empty principal name"); } @@ -1613,16 +1601,18 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) } tmp = tilde_expand_filename(argv[i], pw->pw_uid); - if ((public = key_load_public(tmp, &comment)) == NULL) - fatal("%s: unable to open \"%s\"", __func__, tmp); + if ((r = sshkey_load_public(tmp, &public, &comment)) != 0) + fatal("%s: unable to open \"%s\": %s", + __func__, tmp, ssh_err(r)); if (public->type != KEY_RSA && public->type != KEY_DSA && public->type != KEY_ECDSA && public->type != KEY_ED25519) fatal("%s: key \"%s\" type %s cannot be certified", - __func__, tmp, key_type(public)); + __func__, tmp, sshkey_type(public)); /* Prepare certificate to sign */ - if (key_to_certified(public, v00) != 0) - fatal("Could not upgrade key %s to certificate", tmp); + if ((r = sshkey_to_certified(public)) != 0) + fatal("Could not upgrade key %s to certificate: %s", + tmp, ssh_err(r)); public->cert->type = cert_key_type; public->cert->serial = (u_int64_t)cert_serial; public->cert->key_id = xstrdup(cert_key_id); @@ -1630,18 +1620,14 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) public->cert->principals = plist; public->cert->valid_after = cert_valid_from; public->cert->valid_before = cert_valid_to; - if (v00) { - prepare_options_buf(&public->cert->critical, - OPTIONS_CRITICAL|OPTIONS_EXTENSIONS); - } else { - prepare_options_buf(&public->cert->critical, - OPTIONS_CRITICAL); - prepare_options_buf(&public->cert->extensions, - OPTIONS_EXTENSIONS); - } - public->cert->signature_key = key_from_private(ca); - - if (key_certify(public, ca) != 0) + prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL); + prepare_options_buf(public->cert->extensions, + OPTIONS_EXTENSIONS); + if ((r = sshkey_from_private(ca, + &public->cert->signature_key)) != 0) + fatal("key_from_private (ca key): %s", ssh_err(r)); + + if (sshkey_certify(public, ca) != 0) fatal("Couldn't not certify key %s", tmp); if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0) @@ -1654,14 +1640,15 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) strerror(errno)); if ((f = fdopen(fd, "w")) == NULL) fatal("%s: fdopen: %s", __func__, strerror(errno)); - if (!key_write(public, f)) - fatal("Could not write certified key to %s", out); + if ((r = sshkey_write(public, f)) != 0) + fatal("Could not write certified key to %s: %s", + out, ssh_err(r)); fprintf(f, " %s\n", comment); fclose(f); if (!quiet) { logit("Signed %s key %s: id \"%s\" serial %llu%s%s " - "valid %s", key_cert_type(public), + "valid %s", sshkey_cert_type(public), out, public->cert->key_id, (unsigned long long)public->cert->serial, cert_principals != NULL ? " for " : "", @@ -1669,10 +1656,12 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) fmt_validity(cert_valid_from, cert_valid_to)); } - key_free(public); + sshkey_free(public); free(out); } +#ifdef ENABLE_PKCS11 pkcs11_terminate(); +#endif exit(0); } @@ -1818,81 +1807,82 @@ add_cert_option(char *opt) } static void -show_options(const Buffer *optbuf, int v00, int in_critical) +show_options(struct sshbuf *optbuf, int in_critical) { - char *name; - u_char *data; - u_int dlen; - Buffer options, option; - - buffer_init(&options); - buffer_append(&options, buffer_ptr(optbuf), buffer_len(optbuf)); - - buffer_init(&option); - while (buffer_len(&options) != 0) { - name = buffer_get_string(&options, NULL); - data = buffer_get_string_ptr(&options, &dlen); - buffer_append(&option, data, dlen); + char *name, *arg; + struct sshbuf *options, *option = NULL; + int r; + + if ((options = sshbuf_fromb(optbuf)) == NULL) + fatal("%s: sshbuf_fromb failed", __func__); + while (sshbuf_len(options) != 0) { + sshbuf_free(option); + option = NULL; + if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 || + (r = sshbuf_froms(options, &option)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); printf(" %s", name); - if ((v00 || !in_critical) && + if (!in_critical && (strcmp(name, "permit-X11-forwarding") == 0 || strcmp(name, "permit-agent-forwarding") == 0 || strcmp(name, "permit-port-forwarding") == 0 || strcmp(name, "permit-pty") == 0 || strcmp(name, "permit-user-rc") == 0)) printf("\n"); - else if ((v00 || in_critical) && + else if (in_critical && (strcmp(name, "force-command") == 0 || strcmp(name, "source-address") == 0)) { - data = buffer_get_string(&option, NULL); - printf(" %s\n", data); - free(data); + if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); + printf(" %s\n", arg); + free(arg); } else { - printf(" UNKNOWN OPTION (len %u)\n", - buffer_len(&option)); - buffer_clear(&option); + printf(" UNKNOWN OPTION (len %zu)\n", + sshbuf_len(option)); + sshbuf_reset(option); } free(name); - if (buffer_len(&option) != 0) + if (sshbuf_len(option) != 0) fatal("Option corrupt: extra data at end"); } - buffer_free(&option); - buffer_free(&options); + sshbuf_free(option); + sshbuf_free(options); } static void do_show_cert(struct passwd *pw) { - Key *key; + struct sshkey *key; struct stat st; char *key_fp, *ca_fp; - u_int i, v00; + u_int i; + int r; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); if (stat(identity_file, &st) < 0) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); - if ((key = key_load_public(identity_file, NULL)) == NULL) - fatal("%s is not a public key", identity_file); - if (!key_is_cert(key)) + if ((r = sshkey_load_public(identity_file, &key, NULL)) != 0) + fatal("Cannot load public key \"%s\": %s", + identity_file, ssh_err(r)); + if (!sshkey_is_cert(key)) fatal("%s is not a certificate", identity_file); - v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00; - key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - ca_fp = key_fingerprint(key->cert->signature_key, - SSH_FP_MD5, SSH_FP_HEX); + key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT); + ca_fp = sshkey_fingerprint(key->cert->signature_key, + fingerprint_hash, SSH_FP_DEFAULT); + if (key_fp == NULL || ca_fp == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); printf("%s:\n", identity_file); - printf(" Type: %s %s certificate\n", key_ssh_name(key), - key_cert_type(key)); - printf(" Public key: %s %s\n", key_type(key), key_fp); + printf(" Type: %s %s certificate\n", sshkey_ssh_name(key), + sshkey_cert_type(key)); + printf(" Public key: %s %s\n", sshkey_type(key), key_fp); printf(" Signing CA: %s %s\n", - key_type(key->cert->signature_key), ca_fp); + sshkey_type(key->cert->signature_key), ca_fp); printf(" Key ID: \"%s\"\n", key->cert->key_id); - if (!v00) { - printf(" Serial: %llu\n", - (unsigned long long)key->cert->serial); - } + printf(" Serial: %llu\n", (unsigned long long)key->cert->serial); printf(" Valid: %s\n", fmt_validity(key->cert->valid_after, key->cert->valid_before)); printf(" Principals: "); @@ -1905,20 +1895,18 @@ do_show_cert(struct passwd *pw) printf("\n"); } printf(" Critical Options: "); - if (buffer_len(&key->cert->critical) == 0) + if (sshbuf_len(key->cert->critical) == 0) printf("(none)\n"); else { printf("\n"); - show_options(&key->cert->critical, v00, 1); + show_options(key->cert->critical, 1); } - if (!v00) { - printf(" Extensions: "); - if (buffer_len(&key->cert->extensions) == 0) - printf("(none)\n"); - else { - printf("\n"); - show_options(&key->cert->extensions, v00, 0); - } + printf(" Extensions: "); + if (sshbuf_len(key->cert->extensions) == 0) + printf("(none)\n"); + else { + printf("\n"); + show_options(key->cert->extensions, 0); } exit(0); } @@ -1926,27 +1914,28 @@ do_show_cert(struct passwd *pw) static void load_krl(const char *path, struct ssh_krl **krlp) { - Buffer krlbuf; - int fd; + struct sshbuf *krlbuf; + int r, fd; - buffer_init(&krlbuf); + if ((krlbuf = sshbuf_new()) == NULL) + fatal("sshbuf_new failed"); if ((fd = open(path, O_RDONLY)) == -1) fatal("open %s: %s", path, strerror(errno)); - if (!key_load_file(fd, path, &krlbuf)) - fatal("Unable to load KRL"); + if ((r = sshkey_load_file(fd, krlbuf)) != 0) + fatal("Unable to load KRL: %s", ssh_err(r)); close(fd); /* XXX check sigs */ - if (ssh_krl_from_blob(&krlbuf, krlp, NULL, 0) != 0 || + if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 || *krlp == NULL) - fatal("Invalid KRL file"); - buffer_free(&krlbuf); + fatal("Invalid KRL file: %s", ssh_err(r)); + sshbuf_free(krlbuf); } static void -update_krl_from_file(struct passwd *pw, const char *file, const Key *ca, - struct ssh_krl *krl) +update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, + const struct sshkey *ca, struct ssh_krl *krl) { - Key *key = NULL; + struct sshkey *key = NULL; u_long lnum = 0; char *path, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES]; unsigned long long serial, serial2; @@ -1985,7 +1974,7 @@ update_krl_from_file(struct passwd *pw, const char *file, const Key *ca, if (*cp == '\0') continue; if (strncasecmp(cp, "serial:", 7) == 0) { - if (ca == NULL) { + if (ca == NULL && !wild_ca) { fatal("revoking certificates by serial number " "requires specification of a CA key"); } @@ -2022,7 +2011,7 @@ update_krl_from_file(struct passwd *pw, const char *file, const Key *ca, __func__); } } else if (strncasecmp(cp, "id:", 3) == 0) { - if (ca == NULL) { + if (ca == NULL && !wild_ca) { fatal("revoking certificates by key ID " "requires specification of a CA key"); } @@ -2045,10 +2034,11 @@ update_krl_from_file(struct passwd *pw, const char *file, const Key *ca, * Parsing will fail if it isn't. */ } - if ((key = key_new(KEY_UNSPEC)) == NULL) + if ((key = sshkey_new(KEY_UNSPEC)) == NULL) fatal("key_new"); - if (key_read(key, &cp) != 1) - fatal("%s:%lu: invalid key", path, lnum); + if ((r = sshkey_read(key, &cp)) != 0) + fatal("%s:%lu: invalid key: %s", + path, lnum, ssh_err(r)); if (was_explicit_key) r = ssh_krl_revoke_key_explicit(krl, key); else if (was_sha1) @@ -2056,8 +2046,9 @@ update_krl_from_file(struct passwd *pw, const char *file, const Key *ca, else r = ssh_krl_revoke_key(krl, key); if (r != 0) - fatal("%s: revoke key failed", __func__); - key_free(key); + fatal("%s: revoke key failed: %s", + __func__, ssh_err(r)); + sshkey_free(key); } } if (strcmp(path, "-") != 0) @@ -2070,10 +2061,10 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv) { struct ssh_krl *krl; struct stat sb; - Key *ca = NULL; - int fd, i; + struct sshkey *ca = NULL; + int fd, i, r, wild_ca = 0; char *tmp; - Buffer kbuf; + struct sshbuf *kbuf; if (*identity_file == '\0') fatal("KRL generation requires an output file"); @@ -2085,10 +2076,15 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv) fatal("KRL \"%s\" does not exist", identity_file); } if (ca_key_path != NULL) { - tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); - if ((ca = key_load_public(tmp, NULL)) == NULL) - fatal("Cannot load CA public key %s", tmp); - free(tmp); + if (strcasecmp(ca_key_path, "none") == 0) + wild_ca = 1; + else { + tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); + if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0) + fatal("Cannot load CA public key %s: %s", + tmp, ssh_err(r)); + free(tmp); + } } if (updating) @@ -2102,21 +2098,22 @@ do_gen_krl(struct passwd *pw, int updating, int argc, char **argv) ssh_krl_set_comment(krl, identity_comment); for (i = 0; i < argc; i++) - update_krl_from_file(pw, argv[i], ca, krl); + update_krl_from_file(pw, argv[i], wild_ca, ca, krl); - buffer_init(&kbuf); - if (ssh_krl_to_blob(krl, &kbuf, NULL, 0) != 0) + if ((kbuf = sshbuf_new()) == NULL) + fatal("sshbuf_new failed"); + if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0) fatal("Couldn't generate KRL"); if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) fatal("open %s: %s", identity_file, strerror(errno)); - if (atomicio(vwrite, fd, buffer_ptr(&kbuf), buffer_len(&kbuf)) != - buffer_len(&kbuf)) + if (atomicio(vwrite, fd, (void *)sshbuf_ptr(kbuf), sshbuf_len(kbuf)) != + sshbuf_len(kbuf)) fatal("write %s: %s", identity_file, strerror(errno)); close(fd); - buffer_free(&kbuf); + sshbuf_free(kbuf); ssh_krl_free(krl); if (ca != NULL) - key_free(ca); + sshkey_free(ca); } static void @@ -2125,21 +2122,22 @@ do_check_krl(struct passwd *pw, int argc, char **argv) int i, r, ret = 0; char *comment; struct ssh_krl *krl; - Key *k; + struct sshkey *k; if (*identity_file == '\0') fatal("KRL checking requires an input file"); load_krl(identity_file, &krl); for (i = 0; i < argc; i++) { - if ((k = key_load_public(argv[i], &comment)) == NULL) - fatal("Cannot load public key %s", argv[i]); + if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0) + fatal("Cannot load public key %s: %s", + argv[i], ssh_err(r)); r = ssh_krl_check_key(krl, k); printf("%s%s%s%s: %s\n", argv[i], *comment ? " (" : "", comment, *comment ? ")" : "", r == 0 ? "ok" : "REVOKED"); if (r != 0) ret = 1; - key_free(k); + sshkey_free(k); free(comment); } ssh_krl_free(krl); @@ -2149,56 +2147,37 @@ do_check_krl(struct passwd *pw, int argc, char **argv) static void usage(void) { - fprintf(stderr, "usage: %s [options]\n", __progname); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " -A Generate non-existent host keys for all key types.\n"); - fprintf(stderr, " -a number Number of KDF rounds for new key format or moduli primality tests.\n"); - fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); - fprintf(stderr, " -b bits Number of bits in the key to create.\n"); - fprintf(stderr, " -C comment Provide new comment.\n"); - fprintf(stderr, " -c Change comment in private and public key files.\n"); + fprintf(stderr, + "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]\n" + " [-N new_passphrase] [-C comment] [-f output_keyfile]\n" + " ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]\n" + " ssh-keygen -i [-m key_format] [-f input_keyfile]\n" + " ssh-keygen -e [-m key_format] [-f input_keyfile]\n" + " ssh-keygen -y [-f input_keyfile]\n" + " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n" + " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n" + " ssh-keygen -B [-f input_keyfile]\n"); #ifdef ENABLE_PKCS11 - fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n"); + fprintf(stderr, + " ssh-keygen -D pkcs11\n"); #endif - fprintf(stderr, " -e Export OpenSSH to foreign format key file.\n"); - fprintf(stderr, " -F hostname Find hostname in known hosts file.\n"); - fprintf(stderr, " -f filename Filename of the key file.\n"); - fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); - fprintf(stderr, " -g Use generic DNS resource record format.\n"); - fprintf(stderr, " -H Hash names in known_hosts file.\n"); - fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); - fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); - fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n"); - fprintf(stderr, " -J number Screen this number of moduli lines.\n"); - fprintf(stderr, " -j number Start screening moduli at specified line.\n"); - fprintf(stderr, " -K checkpt Write checkpoints to this file.\n"); - fprintf(stderr, " -k Generate a KRL file.\n"); - fprintf(stderr, " -L Print the contents of a certificate.\n"); - fprintf(stderr, " -l Show fingerprint of key file.\n"); - fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); - fprintf(stderr, " -m key_fmt Conversion format for -e/-i (PEM|PKCS8|RFC4716).\n"); - fprintf(stderr, " -N phrase Provide new passphrase.\n"); - fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); - fprintf(stderr, " -O option Specify a certificate option.\n"); - fprintf(stderr, " -o Enforce new private key format.\n"); - fprintf(stderr, " -P phrase Provide old passphrase.\n"); - fprintf(stderr, " -p Change passphrase of private key file.\n"); - fprintf(stderr, " -Q Test whether key(s) are revoked in KRL.\n"); - fprintf(stderr, " -q Quiet.\n"); - fprintf(stderr, " -R hostname Remove host from known_hosts file.\n"); - fprintf(stderr, " -r hostname Print DNS resource record.\n"); - fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n"); - fprintf(stderr, " -s ca_key Certify keys with CA key.\n"); - fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n"); - fprintf(stderr, " -t type Specify type of key to create.\n"); - fprintf(stderr, " -u Update KRL rather than creating a new one.\n"); - fprintf(stderr, " -V from:to Specify certificate validity interval.\n"); - fprintf(stderr, " -v Verbose.\n"); - fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n"); - fprintf(stderr, " -y Read private key file and print public key.\n"); - fprintf(stderr, " -Z cipher Specify a cipher for new private key format.\n"); - fprintf(stderr, " -z serial Specify a serial number.\n"); - + fprintf(stderr, + " ssh-keygen -F hostname [-f known_hosts_file] [-l]\n" + " ssh-keygen -H [-f known_hosts_file]\n" + " ssh-keygen -R hostname [-f known_hosts_file]\n" + " ssh-keygen -r hostname [-f input_keyfile] [-g]\n" +#ifdef WITH_OPENSSL + " ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n" + " ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n" + " [-j start_line] [-K checkpt] [-W generator]\n" +#endif + " ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]\n" + " [-O option] [-V validity_interval] [-z serial_number] file ...\n" + " ssh-keygen -L [-f input_keyfile]\n" + " ssh-keygen -A\n" + " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" + " file ...\n" + " ssh-keygen -Q -f krl_file file ...\n"); exit(1); } @@ -2208,20 +2187,23 @@ usage(void) int main(int argc, char **argv) { - char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; - char *checkpoint = NULL; - char out_file[MAXPATHLEN], *ep, *rr_hostname = NULL; - Key *private, *public; + char dotsshdir[PATH_MAX], comment[1024], *passphrase1, *passphrase2; + char *rr_hostname = NULL, *ep, *fp, *ra; + struct sshkey *private, *public; struct passwd *pw; struct stat st; - int opt, type, fd; + int r, opt, type, fd; + int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; + FILE *f; + const char *errstr; +#ifdef WITH_OPENSSL + /* Moduli generation/screening */ + char out_file[PATH_MAX], *checkpoint = NULL; u_int32_t memory = 0, generator_wanted = 0; int do_gen_candidates = 0, do_screen_candidates = 0; - int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; unsigned long start_lineno = 0, lines_to_process = 0; BIGNUM *start = NULL; - FILE *f; - const char *errstr; +#endif extern int optind; extern char *optarg; @@ -2231,25 +2213,24 @@ main(int argc, char **argv) __progname = ssh_get_progname(argv[0]); +#ifdef WITH_OPENSSL OpenSSL_add_all_algorithms(); +#endif log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); seed_rng(); /* we need this for the home * directory. */ pw = getpwuid(getuid()); - if (!pw) { - printf("No user exists for uid %lu\n", (u_long)getuid()); - exit(1); - } - if (gethostname(hostname, sizeof(hostname)) < 0) { - perror("gethostname"); - exit(1); - } + if (!pw) + fatal("No user exists for uid %lu", (u_long)getuid()); + if (gethostname(hostname, sizeof(hostname)) < 0) + fatal("gethostname: %s", strerror(errno)); - /* Remaining characters: EUYdw */ + /* Remaining characters: UYdw */ while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy" - "C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:a:b:f:g:j:m:n:r:s:t:z:")) != -1) { + "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:" + "a:b:f:g:j:m:n:r:s:t:z:")) != -1) { switch (opt) { case 'A': gen_all_hostkeys = 1; @@ -2260,6 +2241,11 @@ main(int argc, char **argv) fatal("Bits has bad value %s (%s)", optarg, errstr); break; + case 'E': + fingerprint_hash = ssh_digest_alg_by_name(optarg); + if (fingerprint_hash == -1) + fatal("Invalid hash algorithm \"%s\"", optarg); + break; case 'F': find_host = 1; rr_hostname = optarg; @@ -2270,12 +2256,6 @@ main(int argc, char **argv) case 'I': cert_key_id = optarg; break; - case 'J': - lines_to_process = strtoul(optarg, NULL, 10); - break; - case 'j': - start_lineno = strtoul(optarg, NULL, 10); - break; case 'R': delete_host = 1; rr_hostname = optarg; @@ -2317,8 +2297,8 @@ main(int argc, char **argv) change_comment = 1; break; case 'f': - if (strlcpy(identity_file, optarg, sizeof(identity_file)) >= - sizeof(identity_file)) + if (strlcpy(identity_file, optarg, + sizeof(identity_file)) >= sizeof(identity_file)) fatal("Identity filename too long"); have_identity = 1; break; @@ -2390,6 +2370,24 @@ main(int argc, char **argv) case 'r': rr_hostname = optarg; break; + case 'a': + rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr); + if (errstr) + fatal("Invalid number: %s (%s)", + optarg, errstr); + break; + case 'V': + parse_cert_times(optarg); + break; + case 'z': + errno = 0; + cert_serial = strtoull(optarg, &ep, 10); + if (*optarg < '0' || *optarg > '9' || *ep != '\0' || + (errno == ERANGE && cert_serial == ULLONG_MAX)) + fatal("Invalid serial number \"%s\"", optarg); + break; +#ifdef WITH_OPENSSL + /* Moduli generation/screening */ case 'W': generator_wanted = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr); @@ -2397,12 +2395,6 @@ main(int argc, char **argv) fatal("Desired generator has bad value: %s (%s)", optarg, errstr); break; - case 'a': - rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr); - if (errstr) - fatal("Invalid number: %s (%s)", - optarg, errstr); - break; case 'M': memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr); if (errstr) @@ -2421,7 +2413,7 @@ main(int argc, char **argv) fatal("Output filename too long"); break; case 'K': - if (strlen(optarg) >= MAXPATHLEN) + if (strlen(optarg) >= PATH_MAX) fatal("Checkpoint filename too long"); checkpoint = xstrdup(optarg); break; @@ -2430,16 +2422,7 @@ main(int argc, char **argv) if (BN_hex2bn(&start, optarg) == 0) fatal("Invalid start point."); break; - case 'V': - parse_cert_times(optarg); - break; - case 'z': - errno = 0; - cert_serial = strtoull(optarg, &ep, 10); - if (*optarg < '0' || *optarg > '9' || *ep != '\0' || - (errno == ERANGE && cert_serial == ULLONG_MAX)) - fatal("Invalid serial number \"%s\"", optarg); - break; +#endif /* WITH_OPENSSL */ case '?': default: usage(); @@ -2454,19 +2437,19 @@ main(int argc, char **argv) if (ca_key_path != NULL) { if (argc < 1 && !gen_krl) { - printf("Too few arguments.\n"); + error("Too few arguments."); usage(); } } else if (argc > 0 && !gen_krl && !check_krl) { - printf("Too many arguments.\n"); + error("Too many arguments."); usage(); } if (change_passphrase && change_comment) { - printf("Can only have one of -p and -c.\n"); + error("Can only have one of -p and -c."); usage(); } if (print_fingerprint && (delete_host || hash_hosts)) { - printf("Cannot use -l with -H or -R.\n"); + error("Cannot use -l with -H or -R."); usage(); } if (gen_krl) { @@ -2494,10 +2477,12 @@ main(int argc, char **argv) do_change_passphrase(pw); if (change_comment) do_change_comment(pw); +#ifdef WITH_OPENSSL if (convert_to) do_convert_to(pw); if (convert_from) do_convert_from(pw); +#endif if (print_public) do_print_public(pw); if (rr_hostname != NULL) { @@ -2506,10 +2491,8 @@ main(int argc, char **argv) if (have_identity) { n = do_print_resource_record(pw, identity_file, rr_hostname); - if (n == 0) { - perror(identity_file); - exit(1); - } + if (n == 0) + fatal("%s: %s", identity_file, strerror(errno)); exit(0); } else { @@ -2519,13 +2502,15 @@ main(int argc, char **argv) _PATH_HOST_DSA_KEY_FILE, rr_hostname); n += do_print_resource_record(pw, _PATH_HOST_ECDSA_KEY_FILE, rr_hostname); - + n += do_print_resource_record(pw, + _PATH_HOST_ED25519_KEY_FILE, rr_hostname); if (n == 0) fatal("no keys found."); exit(0); } } +#ifdef WITH_OPENSSL if (do_gen_candidates) { FILE *out = fopen(out_file, "w"); @@ -2565,6 +2550,7 @@ main(int argc, char **argv) fatal("modulus screening failed"); return (0); } +#endif if (gen_all_hostkeys) { do_gen_all_hostkeys(pw); @@ -2572,19 +2558,18 @@ main(int argc, char **argv) } if (key_type_name == NULL) - key_type_name = "rsa"; + key_type_name = DEFAULT_KEY_TYPE_NAME; - type = key_type_from_name(key_type_name); - type_bits_valid(type, &bits); + type = sshkey_type_from_name(key_type_name); + type_bits_valid(type, key_type_name, &bits); if (!quiet) - printf("Generating public/private %s key pair.\n", key_type_name); - private = key_generate(type, bits); - if (private == NULL) { - fprintf(stderr, "key_generate failed\n"); - exit(1); - } - public = key_from_private(private); + printf("Generating public/private %s key pair.\n", + key_type_name); + if ((r = sshkey_generate(type, bits, &private)) != 0) + fatal("key_generate failed"); + if ((r = sshkey_from_private(private, &public)) != 0) + fatal("key_from_private failed: %s\n", ssh_err(r)); if (!have_identity) ask_filename(pw, "Enter file in which to save the key"); @@ -2652,9 +2637,10 @@ passphrase_again: } /* Save the key with the given passphrase and comment. */ - if (!key_save_private(private, identity_file, passphrase1, comment, - use_new_format, new_format_cipher, rounds)) { - printf("Saving the key failed: %s.\n", identity_file); + if ((r = sshkey_save_private(private, identity_file, passphrase1, + comment, use_new_format, new_format_cipher, rounds)) != 0) { + error("Saving key \"%s\" failed: %s", + identity_file, ssh_err(r)); explicit_bzero(passphrase1, strlen(passphrase1)); free(passphrase1); exit(1); @@ -2664,31 +2650,29 @@ passphrase_again: free(passphrase1); /* Clear the private key and the random number generator. */ - key_free(private); + sshkey_free(private); if (!quiet) printf("Your identification has been saved in %s.\n", identity_file); strlcat(identity_file, ".pub", sizeof(identity_file)); - fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - printf("Could not save your public key in %s\n", identity_file); - exit(1); - } - f = fdopen(fd, "w"); - if (f == NULL) { - printf("fdopen %s failed\n", identity_file); - exit(1); - } - if (!key_write(public, f)) - fprintf(stderr, "write key failed\n"); + if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) + fatal("Unable to save public key to %s: %s", + identity_file, strerror(errno)); + if ((f = fdopen(fd, "w")) == NULL) + fatal("fdopen %s failed: %s", identity_file, strerror(errno)); + if ((r = sshkey_write(public, f)) != 0) + error("write key failed: %s", ssh_err(r)); fprintf(f, " %s\n", comment); fclose(f); if (!quiet) { - char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); - char *ra = key_fingerprint(public, SSH_FP_MD5, + fp = sshkey_fingerprint(public, fingerprint_hash, + SSH_FP_DEFAULT); + ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("sshkey_fingerprint failed"); printf("Your public key has been saved in %s.\n", identity_file); printf("The key fingerprint is:\n"); @@ -2699,6 +2683,6 @@ passphrase_again: free(fp); } - key_free(public); + sshkey_free(public); exit(0); } diff --git a/crypto/openssh/ssh-keyscan.0 b/crypto/openssh/ssh-keyscan.0 deleted file mode 100644 index 638c19b..0000000 --- a/crypto/openssh/ssh-keyscan.0 +++ /dev/null @@ -1,110 +0,0 @@ -SSH-KEYSCAN(1) OpenBSD Reference Manual SSH-KEYSCAN(1) - -NAME - ssh-keyscan - gather ssh public keys - -SYNOPSIS - ssh-keyscan [-46Hv] [-f file] [-p port] [-T timeout] [-t type] - [host | addrlist namelist] ... - -DESCRIPTION - ssh-keyscan is a utility for gathering the public ssh host keys of a - number of hosts. It was designed to aid in building and verifying - ssh_known_hosts files. ssh-keyscan provides a minimal interface suitable - for use by shell and perl scripts. - - ssh-keyscan uses non-blocking socket I/O to contact as many hosts as - possible in parallel, so it is very efficient. The keys from a domain of - 1,000 hosts can be collected in tens of seconds, even when some of those - hosts are down or do not run ssh. For scanning, one does not need login - access to the machines that are being scanned, nor does the scanning - process involve any encryption. - - The options are as follows: - - -4 Forces ssh-keyscan to use IPv4 addresses only. - - -6 Forces ssh-keyscan to use IPv6 addresses only. - - -f file - Read hosts or ``addrlist namelist'' pairs from file, one per - line. If - is supplied instead of a filename, ssh-keyscan will - read hosts or ``addrlist namelist'' pairs from the standard - input. - - -H Hash all hostnames and addresses in the output. Hashed names may - be used normally by ssh and sshd, but they do not reveal - identifying information should the file's contents be disclosed. - - -p port - Port to connect to on the remote host. - - -T timeout - Set the timeout for connection attempts. If timeout seconds have - elapsed since a connection was initiated to a host or since the - last time anything was read from that host, then the connection - is closed and the host in question considered unavailable. - Default is 5 seconds. - - -t type - Specifies the type of the key to fetch from the scanned hosts. - The possible values are ``rsa1'' for protocol version 1 and - ``dsa'', ``ecdsa'', ``ed25519'', or ``rsa'' for protocol version - 2. Multiple values may be specified by separating them with - commas. The default is to fetch ``rsa'' and ``ecdsa'' keys. - - -v Verbose mode. Causes ssh-keyscan to print debugging messages - about its progress. - -SECURITY - If an ssh_known_hosts file is constructed using ssh-keyscan without - verifying the keys, users will be vulnerable to man in the middle - attacks. On the other hand, if the security model allows such a risk, - ssh-keyscan can help in the detection of tampered keyfiles or man in the - middle attacks which have begun after the ssh_known_hosts file was - created. - -FILES - Input format: - - 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 - - Output format for rsa1 keys: - - host-or-namelist bits exponent modulus - - Output format for rsa, dsa and ecdsa keys: - - host-or-namelist keytype base64-encoded-key - - Where keytype is either ``ecdsa-sha2-nistp256'', ``ecdsa-sha2-nistp384'', - ``ecdsa-sha2-nistp521'', ``ssh-ed25519'', ``ssh-dss'' or ``ssh-rsa''. - - /etc/ssh/ssh_known_hosts - -EXAMPLES - Print the rsa host key for machine hostname: - - $ ssh-keyscan hostname - - Find all hosts from the file ssh_hosts which have new or different keys - from those in the sorted file ssh_known_hosts: - - $ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \ - sort -u - ssh_known_hosts | diff ssh_known_hosts - - -SEE ALSO - ssh(1), sshd(8) - -AUTHORS - David Mazieres wrote the initial version, and Wayne - Davison added support for protocol version - 2. - -BUGS - It generates "Connection closed by remote host" messages on the consoles - of all the machines it scans if the server is older than version 2.9. - This is because it opens a connection to the ssh port, reads the public - key, and drops the connection as soon as it gets the key. - -OpenBSD 5.5 January 28, 2014 OpenBSD 5.5 diff --git a/crypto/openssh/ssh-keyscan.1 b/crypto/openssh/ssh-keyscan.1 index dae4fd9..6bbc480 100644 --- a/crypto/openssh/ssh-keyscan.1 +++ b/crypto/openssh/ssh-keyscan.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.34 2014/01/28 14:13:39 jmc Exp $ +.\" $OpenBSD: ssh-keyscan.1,v 1.36 2014/08/30 15:33:50 sobrado Exp $ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" @@ -6,7 +6,7 @@ .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" -.Dd $Mdocdate: January 28 2014 $ +.Dd $Mdocdate: August 30 2014 $ .Dt SSH-KEYSCAN 1 .Os .Sh NAME @@ -98,9 +98,10 @@ or for protocol version 2. Multiple values may be specified by separating them with commas. The default is to fetch -.Dq rsa +.Dq rsa , +.Dq ecdsa , and -.Dq ecdsa +.Dq ed25519 keys. .It Fl v Verbose mode. @@ -124,12 +125,12 @@ Input format: 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 .Ed .Pp -Output format for rsa1 keys: +Output format for RSA1 keys: .Bd -literal host-or-namelist bits exponent modulus .Ed .Pp -Output format for rsa, dsa and ecdsa keys: +Output format for RSA, DSA, ECDSA, and Ed25519 keys: .Bd -literal host-or-namelist keytype base64-encoded-key .Ed @@ -158,7 +159,7 @@ Find all hosts from the file which have new or different keys from those in the sorted file .Pa ssh_known_hosts : .Bd -literal -$ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \e +$ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \e sort -u - ssh_known_hosts | diff ssh_known_hosts - .Ed .Sh SEE ALSO diff --git a/crypto/openssh/ssh-keyscan.c b/crypto/openssh/ssh-keyscan.c index 8d0a6b8..57d8842 100644 --- a/crypto/openssh/ssh-keyscan.c +++ b/crypto/openssh/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.89 2013/12/06 13:39:49 markus Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.101 2015/04/10 00:08:55 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -9,6 +9,7 @@ #include "includes.h" +#include #include "openbsd-compat/sys-queue.h" #include #ifdef HAVE_SYS_TIME_H @@ -22,7 +23,6 @@ #include #include -#include #include #include #include @@ -33,8 +33,8 @@ #include "xmalloc.h" #include "ssh.h" #include "ssh1.h" -#include "buffer.h" -#include "key.h" +#include "sshbuf.h" +#include "sshkey.h" #include "cipher.h" #include "kex.h" #include "compat.h" @@ -45,6 +45,8 @@ #include "atomicio.h" #include "misc.h" #include "hostfile.h" +#include "ssherr.h" +#include "ssh_api.h" /* Flag indicating whether IPv4 or IPv6. This can be set on the command line. Default value is AF_UNSPEC means both IPv4 and IPv6. */ @@ -58,7 +60,7 @@ int ssh_port = SSH_DEFAULT_PORT; #define KT_ECDSA 8 #define KT_ED25519 16 -int get_keytypes = KT_RSA|KT_ECDSA;/* Get RSA and ECDSA keys by default */ +int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519; int hash_hosts = 0; /* Hash hostname on output */ @@ -74,9 +76,8 @@ extern char *__progname; fd_set *read_wait; size_t read_wait_nfdset; int ncon; -int nonfatal_fatal = 0; -jmp_buf kexjmp; -Key *kexjmp_key; + +struct ssh *active_state = NULL; /* XXX needed for linking */ /* * Keep a connection structure for each file descriptor. The state @@ -93,12 +94,13 @@ typedef struct Connection { int c_len; /* Total bytes which must be read. */ int c_off; /* Length of data read so far. */ int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ + sig_atomic_t c_done; /* SSH2 done */ char *c_namebase; /* Address to free for c_name and c_namelist */ char *c_name; /* Hostname of connection for errors */ char *c_namelist; /* Pointer to other possible addresses */ char *c_output_name; /* Hostname of connection for output */ char *c_data; /* Data read from this fd */ - Kex *c_kex; /* The key-exchange struct for ssh2 */ + struct ssh *c_ssh; /* SSH-connection */ struct timeval c_tv; /* Time at which connection gets aborted */ TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */ } con; @@ -106,6 +108,8 @@ typedef struct Connection { TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */ con *fdcon; +static void keyprint(con *c, struct sshkey *key); + static int fdlim_get(int hard) { @@ -182,45 +186,62 @@ strnnsep(char **stringp, char *delim) return (tok); } -static Key * +#ifdef WITH_SSH1 +static struct sshkey * keygrab_ssh1(con *c) { - static Key *rsa; - static Buffer msg; + static struct sshkey *rsa; + static struct sshbuf *msg; + int r; + u_char type; if (rsa == NULL) { - buffer_init(&msg); - rsa = key_new(KEY_RSA1); + if ((rsa = sshkey_new(KEY_RSA1)) == NULL) { + error("%s: sshkey_new failed", __func__); + return NULL; + } + if ((msg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); } - buffer_append(&msg, c->c_data, c->c_plen); - buffer_consume(&msg, 8 - (c->c_plen & 7)); /* padding */ - if (buffer_get_char(&msg) != (int) SSH_SMSG_PUBLIC_KEY) { + if ((r = sshbuf_put(msg, c->c_data, c->c_plen)) != 0 || + (r = sshbuf_consume(msg, 8 - (c->c_plen & 7))) != 0 || /* padding */ + (r = sshbuf_get_u8(msg, &type)) != 0) + goto buf_err; + if (type != (int) SSH_SMSG_PUBLIC_KEY) { error("%s: invalid packet type", c->c_name); - buffer_clear(&msg); + sshbuf_reset(msg); + return NULL; + } + if ((r = sshbuf_consume(msg, 8)) != 0 || /* cookie */ + /* server key */ + (r = sshbuf_get_u32(msg, NULL)) != 0 || + (r = sshbuf_get_bignum1(msg, NULL)) != 0 || + (r = sshbuf_get_bignum1(msg, NULL)) != 0 || + /* host key */ + (r = sshbuf_get_u32(msg, NULL)) != 0 || + (r = sshbuf_get_bignum1(msg, rsa->rsa->e)) != 0 || + (r = sshbuf_get_bignum1(msg, rsa->rsa->n)) != 0) { + buf_err: + error("%s: buffer error: %s", __func__, ssh_err(r)); + sshbuf_reset(msg); return NULL; } - buffer_consume(&msg, 8); /* cookie */ - - /* server key */ - (void) buffer_get_int(&msg); - buffer_get_bignum(&msg, rsa->rsa->e); - buffer_get_bignum(&msg, rsa->rsa->n); - - /* host key */ - (void) buffer_get_int(&msg); - buffer_get_bignum(&msg, rsa->rsa->e); - buffer_get_bignum(&msg, rsa->rsa->n); - buffer_clear(&msg); + sshbuf_reset(msg); return (rsa); } +#endif static int -hostjump(Key *hostkey) +key_print_wrapper(struct sshkey *hostkey, struct ssh *ssh) { - kexjmp_key = hostkey; - longjmp(kexjmp, 1); + con *c; + + if ((c = ssh_get_app_data(ssh)) != NULL) + keyprint(c, hostkey); + /* always abort key exchange */ + return -1; } static int @@ -239,54 +260,57 @@ ssh2_capable(int remote_major, int remote_minor) return 0; } -static Key * +static void keygrab_ssh2(con *c) { - int j; + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + int r; - packet_set_connection(c->c_fd, c->c_fd); enable_compat20(); myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA ? "ssh-dss" : (c->c_keytype == KT_RSA ? "ssh-rsa" : (c->c_keytype == KT_ED25519 ? "ssh-ed25519" : "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521")); - c->c_kex = kex_setup(myproposal); - c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; - c->c_kex->kex[KEX_ECDH_SHA2] = kexecdh_client; - c->c_kex->kex[KEX_C25519_SHA256] = kexc25519_client; - c->c_kex->verify_host_key = hostjump; - - if (!(j = setjmp(kexjmp))) { - nonfatal_fatal = 1; - dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, c->c_kex); - fprintf(stderr, "Impossible! dispatch_run() returned!\n"); + if ((r = kex_setup(c->c_ssh, myproposal)) != 0) { + free(c->c_ssh); + fprintf(stderr, "kex_setup: %s\n", ssh_err(r)); exit(1); } - nonfatal_fatal = 0; - free(c->c_kex); - c->c_kex = NULL; - packet_close(); - - return j < 0? NULL : kexjmp_key; +#ifdef WITH_OPENSSL + c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; + c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; +# ifdef OPENSSL_HAS_ECC + c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; +# endif +#endif + c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); + /* + * do the key-exchange until an error occurs or until + * the key_print_wrapper() callback sets c_done. + */ + ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done, c->c_ssh); } static void -keyprint(con *c, Key *key) +keyprint(con *c, struct sshkey *key) { char *host = c->c_output_name ? c->c_output_name : c->c_name; + char *hostport = NULL; if (!key) return; if (hash_hosts && (host = host_hash(host, NULL, 0)) == NULL) fatal("host_hash failed"); - fprintf(stdout, "%s ", host); - key_write(key, stdout); + hostport = put_host_port(host, ssh_port); + fprintf(stdout, "%s ", hostport); + sshkey_write(key, stdout); fputs("\n", stdout); + free(hostport); } static int @@ -300,8 +324,10 @@ tcpconnect(char *host) memset(&hints, 0, sizeof(hints)); hints.ai_family = IPv4or6; hints.ai_socktype = SOCK_STREAM; - if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) - fatal("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); + if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { + error("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); + return -1; + } for (ai = aitop; ai; ai = ai->ai_next) { s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s < 0) { @@ -373,6 +399,11 @@ confree(int s) free(fdcon[s].c_data); fdcon[s].c_status = CS_UNUSED; fdcon[s].c_keytype = 0; + if (fdcon[s].c_ssh) { + ssh_packet_close(fdcon[s].c_ssh); + free(fdcon[s].c_ssh); + fdcon[s].c_ssh = NULL; + } TAILQ_REMOVE(&tq, &fdcon[s], c_link); FD_CLR(s, read_wait); ncon--; @@ -440,11 +471,15 @@ congreet(int s) return; } *cp = '\0'; + if ((c->c_ssh = ssh_packet_set_connection(NULL, s, s)) == NULL) + fatal("ssh_packet_set_connection failed"); + ssh_packet_set_timeout(c->c_ssh, timeout, 1); + ssh_set_app_data(c->c_ssh, c); /* back link */ if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) == 3) - compat_datafellows(remote_version); + c->c_ssh->compat = compat_datafellows(remote_version); else - datafellows = 0; + c->c_ssh->compat = 0; if (c->c_keytype != KT_RSA1) { if (!ssh2_capable(remote_major, remote_minor)) { debug("%s doesn't support ssh2", c->c_name); @@ -456,7 +491,7 @@ congreet(int s) confree(s); return; } - fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); + fprintf(stderr, "# %s:%d %s\n", c->c_name, ssh_port, chop(buf)); n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); @@ -471,7 +506,7 @@ congreet(int s) return; } if (c->c_keytype != KT_RSA1) { - keyprint(c, keygrab_ssh2(c)); + keygrab_ssh2(c); confree(s); return; } @@ -506,10 +541,12 @@ conread(int s) c->c_data = xmalloc(c->c_len); c->c_status = CS_KEYS; break; +#ifdef WITH_SSH1 case CS_KEYS: keyprint(c, keygrab_ssh1(c)); confree(s); return; +#endif default: fatal("conread: invalid status %d", c->c_status); break; @@ -595,10 +632,7 @@ fatal(const char *fmt,...) va_start(args, fmt); do_log(SYSLOG_LEVEL_FATAL, fmt, args); va_end(args); - if (nonfatal_fatal) - longjmp(kexjmp, -1); - else - exit(255); + exit(255); } static void @@ -671,7 +705,7 @@ main(int argc, char **argv) get_keytypes = 0; tname = strtok(optarg, ","); while (tname) { - int type = key_type_from_name(tname); + int type = sshkey_type_from_name(tname); switch (type) { case KEY_RSA1: get_keytypes |= KT_RSA1; diff --git a/crypto/openssh/ssh-keysign.0 b/crypto/openssh/ssh-keysign.0 deleted file mode 100644 index 5f18b54..0000000 --- a/crypto/openssh/ssh-keysign.0 +++ /dev/null @@ -1,53 +0,0 @@ -SSH-KEYSIGN(8) OpenBSD System Manager's Manual SSH-KEYSIGN(8) - -NAME - ssh-keysign - ssh helper program for host-based authentication - -SYNOPSIS - ssh-keysign - -DESCRIPTION - ssh-keysign is used by ssh(1) to access the local host keys and generate - the digital signature required during host-based authentication with SSH - protocol version 2. - - ssh-keysign is disabled by default and can only be enabled in the global - client configuration file /etc/ssh/ssh_config by setting EnableSSHKeysign - to ``yes''. - - ssh-keysign is not intended to be invoked by the user, but from ssh(1). - See ssh(1) and sshd(8) for more information about host-based - authentication. - -FILES - /etc/ssh/ssh_config - Controls whether ssh-keysign is enabled. - - /etc/ssh/ssh_host_dsa_key - /etc/ssh/ssh_host_ecdsa_key - /etc/ssh/ssh_host_ed25519_key - /etc/ssh/ssh_host_rsa_key - These files contain the private parts of the host keys used to - generate the digital signature. They should be owned by root, - readable only by root, and not accessible to others. Since they - are readable only by root, ssh-keysign must be set-uid root if - host-based authentication is used. - - /etc/ssh/ssh_host_dsa_key-cert.pub - /etc/ssh/ssh_host_ecdsa_key-cert.pub - /etc/ssh/ssh_host_ed25519_key-cert.pub - /etc/ssh/ssh_host_rsa_key-cert.pub - If these files exist they are assumed to contain public - certificate information corresponding with the private keys - above. - -SEE ALSO - ssh(1), ssh-keygen(1), ssh_config(5), sshd(8) - -HISTORY - ssh-keysign first appeared in OpenBSD 3.2. - -AUTHORS - Markus Friedl - -OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/ssh-keysign.c b/crypto/openssh/ssh-keysign.c index 6bde8ad..1dca3e2 100644 --- a/crypto/openssh/ssh-keysign.c +++ b/crypto/openssh/ssh-keysign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keysign.c,v 1.39 2013/12/06 13:39:49 markus Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.49 2015/07/03 03:56:25 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -35,23 +35,29 @@ #include #include +#ifdef WITH_OPENSSL #include #include #include +#endif #include "xmalloc.h" #include "log.h" -#include "key.h" +#include "sshkey.h" #include "ssh.h" #include "ssh2.h" #include "misc.h" -#include "buffer.h" +#include "sshbuf.h" #include "authfile.h" #include "msg.h" #include "canohost.h" #include "pathnames.h" #include "readconf.h" #include "uidswap.h" +#include "sshkey.h" +#include "ssherr.h" + +struct ssh *active_state = NULL; /* XXX needed for linking */ /* XXX readconf.c needs these */ uid_t original_real_uid; @@ -59,62 +65,73 @@ uid_t original_real_uid; extern char *__progname; static int -valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, - u_int datalen) +valid_request(struct passwd *pw, char *host, struct sshkey **ret, + u_char *data, size_t datalen) { - Buffer b; - Key *key = NULL; - u_char *pkblob; - u_int blen, len; - char *pkalg, *p; - int pktype, fail; - + struct sshbuf *b; + struct sshkey *key = NULL; + u_char type, *pkblob; + char *p; + size_t blen, len; + char *pkalg, *luser; + int r, pktype, fail; + + if (ret != NULL) + *ret = NULL; fail = 0; - buffer_init(&b); - buffer_append(&b, data, datalen); + if ((b = sshbuf_from(data, datalen)) == NULL) + fatal("%s: sshbuf_from failed", __func__); /* session id, currently limited to SHA1 (20 bytes) or SHA256 (32) */ - p = buffer_get_string(&b, &len); + if ((r = sshbuf_get_string(b, NULL, &len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (len != 20 && len != 32) fail++; - free(p); - if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + if ((r = sshbuf_get_u8(b, &type)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (type != SSH2_MSG_USERAUTH_REQUEST) fail++; /* server user */ - buffer_skip_string(&b); + if ((r = sshbuf_skip_string(b)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* service */ - p = buffer_get_string(&b, NULL); + if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (strcmp("ssh-connection", p) != 0) fail++; free(p); /* method */ - p = buffer_get_string(&b, NULL); + if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (strcmp("hostbased", p) != 0) fail++; free(p); /* pubkey */ - pkalg = buffer_get_string(&b, NULL); - pkblob = buffer_get_string(&b, &blen); + if ((r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || + (r = sshbuf_get_string(b, &pkblob, &blen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - pktype = key_type_from_name(pkalg); + pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) fail++; - else if ((key = key_from_blob(pkblob, blen)) == NULL) + else if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { + error("%s: bad key blob: %s", __func__, ssh_err(r)); fail++; - else if (key->type != pktype) + } else if (key->type != pktype) fail++; free(pkalg); free(pkblob); /* client host name, handle trailing dot */ - p = buffer_get_string(&b, &len); - debug2("valid_request: check expect chost %s got %s", host, p); + if ((r = sshbuf_get_cstring(b, &p, &len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + debug2("%s: check expect chost %s got %s", __func__, host, p); if (strlen(host) != len - 1) fail++; else if (p[len - 1] != '.') @@ -124,22 +141,23 @@ valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, free(p); /* local user */ - p = buffer_get_string(&b, NULL); + if ((r = sshbuf_get_cstring(b, &luser, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (strcmp(pw->pw_name, p) != 0) + if (strcmp(pw->pw_name, luser) != 0) fail++; - free(p); + free(luser); /* end of message */ - if (buffer_len(&b) != 0) + if (sshbuf_len(b) != 0) fail++; - buffer_free(&b); + sshbuf_free(b); - debug3("valid_request: fail %d", fail); + debug3("%s: fail %d", __func__, fail); if (fail && key != NULL) - key_free(key); - else + sshkey_free(key); + else if (ret != NULL) *ret = key; return (fail ? -1 : 0); @@ -148,16 +166,18 @@ valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, int main(int argc, char **argv) { - Buffer b; + struct sshbuf *b; Options options; #define NUM_KEYTYPES 4 - Key *keys[NUM_KEYTYPES], *key = NULL; + struct sshkey *keys[NUM_KEYTYPES], *key = NULL; struct passwd *pw; - int key_fd[NUM_KEYTYPES], i, found, version = 2, fd; - u_char *signature, *data; - char *host; - u_int slen, dlen; + int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd; + u_char *signature, *data, rver; + char *host, *fp; + size_t slen, dlen; +#ifdef WITH_OPENSSL u_int32_t rnd[256]; +#endif /* Ensure that stdin and stdout are connected */ if ((fd = open(_PATH_DEVNULL, O_RDWR)) < 2) @@ -167,6 +187,7 @@ main(int argc, char **argv) close(fd); i = 0; + /* XXX This really needs to read sshd_config for the paths */ key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY); key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY); @@ -187,7 +208,7 @@ main(int argc, char **argv) /* verify that ssh-keysign is enabled by the admin */ initialize_options(&options); - (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", &options, 0); + (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", &options, 0); fill_default_options(&options); if (options.enable_ssh_keysign != 1) fatal("ssh-keysign not enabled in %s", @@ -200,37 +221,47 @@ main(int argc, char **argv) if (found == 0) fatal("could not open any host key"); +#ifdef WITH_OPENSSL OpenSSL_add_all_algorithms(); - for (i = 0; i < 256; i++) - rnd[i] = arc4random(); + arc4random_buf(rnd, sizeof(rnd)); RAND_seed(rnd, sizeof(rnd)); +#endif found = 0; for (i = 0; i < NUM_KEYTYPES; i++) { keys[i] = NULL; if (key_fd[i] == -1) continue; - keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC, - NULL, NULL); + r = sshkey_load_private_type_fd(key_fd[i], KEY_UNSPEC, + NULL, &key, NULL); close(key_fd[i]); - if (keys[i] != NULL) + if (r != 0) + debug("parse key %d: %s", i, ssh_err(r)); + else if (key != NULL) { + keys[i] = key; found = 1; + } } if (!found) fatal("no hostkey found"); - buffer_init(&b); - if (ssh_msg_recv(STDIN_FILENO, &b) < 0) + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if (ssh_msg_recv(STDIN_FILENO, b) < 0) fatal("ssh_msg_recv failed"); - if (buffer_get_char(&b) != version) - fatal("bad version"); - fd = buffer_get_int(&b); - if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO)) + if ((r = sshbuf_get_u8(b, &rver)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (rver != version) + fatal("bad version: received %d, expected %d", rver, version); + if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO) fatal("bad fd"); if ((host = get_local_name(fd)) == NULL) fatal("cannot get local name for fd"); - data = buffer_get_string(&b, &dlen); + if ((r = sshbuf_get_string(b, &data, &dlen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (valid_request(pw, host, &key, data, dlen) < 0) fatal("not a valid request"); free(host); @@ -238,22 +269,28 @@ main(int argc, char **argv) found = 0; for (i = 0; i < NUM_KEYTYPES; i++) { if (keys[i] != NULL && - key_equal_public(key, keys[i])) { + sshkey_equal_public(key, keys[i])) { found = 1; break; } } - if (!found) - fatal("no matching hostkey found"); + if (!found) { + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint failed", __func__); + fatal("no matching hostkey found for key %s %s", + sshkey_type(key), fp ? fp : ""); + } - if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) - fatal("key_sign failed"); + if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, 0)) != 0) + fatal("sshkey_sign failed: %s", ssh_err(r)); free(data); /* send reply */ - buffer_clear(&b); - buffer_put_string(&b, signature, slen); - if (ssh_msg_send(STDOUT_FILENO, version, &b) == -1) + sshbuf_reset(b); + if ((r = sshbuf_put_string(b, signature, slen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (ssh_msg_send(STDOUT_FILENO, version, b) == -1) fatal("ssh_msg_send failed"); return (0); diff --git a/crypto/openssh/ssh-pkcs11-client.c b/crypto/openssh/ssh-pkcs11-client.c index 6c9f9d2..8c74864 100644 --- a/crypto/openssh/ssh-pkcs11-client.c +++ b/crypto/openssh/ssh-pkcs11-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-client.c,v 1.4 2013/05/17 00:13:14 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.5 2014/06/24 01:13:21 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -30,6 +30,8 @@ #include #include +#include + #include "pathnames.h" #include "xmalloc.h" #include "buffer.h" diff --git a/crypto/openssh/ssh-pkcs11-helper.0 b/crypto/openssh/ssh-pkcs11-helper.0 deleted file mode 100644 index 20d62f7..0000000 --- a/crypto/openssh/ssh-pkcs11-helper.0 +++ /dev/null @@ -1,25 +0,0 @@ -SSH-PKCS11-HELPER(8) OpenBSD System Manager's Manual SSH-PKCS11-HELPER(8) - -NAME - ssh-pkcs11-helper - ssh-agent helper program for PKCS#11 support - -SYNOPSIS - ssh-pkcs11-helper - -DESCRIPTION - ssh-pkcs11-helper is used by ssh-agent(1) to access keys provided by a - PKCS#11 token. - - ssh-pkcs11-helper is not intended to be invoked by the user, but from - ssh-agent(1). - -SEE ALSO - ssh(1), ssh-add(1), ssh-agent(1) - -HISTORY - ssh-pkcs11-helper first appeared in OpenBSD 4.7. - -AUTHORS - Markus Friedl - -OpenBSD 5.5 July 16, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/ssh-pkcs11-helper.c b/crypto/openssh/ssh-pkcs11-helper.c index b7c52be..f2d5863 100644 --- a/crypto/openssh/ssh-pkcs11-helper.c +++ b/crypto/openssh/ssh-pkcs11-helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-helper.c,v 1.7 2013/12/02 02:56:17 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-helper.c,v 1.11 2015/08/20 22:32:42 deraadt Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -169,7 +169,7 @@ process_sign(void) { u_char *blob, *data, *signature = NULL; u_int blen, dlen, slen = 0; - int ok = -1, ret; + int ok = -1; Key *key, *found; Buffer msg; @@ -179,6 +179,9 @@ process_sign(void) if ((key = key_from_blob(blob, blen)) != NULL) { if ((found = lookup_key(key)) != NULL) { +#ifdef WITH_OPENSSL + int ret; + slen = RSA_size(key->rsa); signature = xmalloc(slen); if ((ret = RSA_private_encrypt(dlen, data, signature, @@ -186,6 +189,7 @@ process_sign(void) slen = ret; ok = 0; } +#endif /* WITH_OPENSSL */ } key_free(key); } @@ -297,8 +301,8 @@ main(int argc, char **argv) buffer_init(&oqueue); set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); - rset = (fd_set *)xmalloc(set_size); - wset = (fd_set *)xmalloc(set_size); + rset = xmalloc(set_size); + wset = xmalloc(set_size); for (;;) { memset(rset, 0, set_size); diff --git a/crypto/openssh/ssh-pkcs11.c b/crypto/openssh/ssh-pkcs11.c index c49cbf4..92614a5 100644 --- a/crypto/openssh/ssh-pkcs11.c +++ b/crypto/openssh/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.11 2013/11/13 13:48:20 markus Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.21 2015/07/18 08:02:17 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -38,7 +38,7 @@ #include "log.h" #include "misc.h" -#include "key.h" +#include "sshkey.h" #include "ssh-pkcs11.h" #include "xmalloc.h" @@ -237,7 +237,7 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, {CKA_ID, NULL, 0}, {CKA_SIGN, NULL, sizeof(true_val) } }; - char *pin, prompt[1024]; + char *pin = NULL, prompt[1024]; int rval = -1; key_filter[0].pValue = &private_key_class; @@ -255,21 +255,30 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, si = &k11->provider->slotinfo[k11->slotidx]; if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { if (!pkcs11_interactive) { - error("need pin"); + error("need pin entry%s", (si->token.flags & + CKF_PROTECTED_AUTHENTICATION_PATH) ? + " on reader keypad" : ""); return (-1); } - snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", - si->token.label); - pin = read_passphrase(prompt, RP_ALLOW_EOF); - if (pin == NULL) - return (-1); /* bail out */ - if ((rv = f->C_Login(si->session, CKU_USER, - (u_char *)pin, strlen(pin))) != CKR_OK) { + if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + verbose("Deferring PIN entry to reader keypad."); + else { + snprintf(prompt, sizeof(prompt), + "Enter PIN for '%s': ", si->token.label); + pin = read_passphrase(prompt, RP_ALLOW_EOF); + if (pin == NULL) + return (-1); /* bail out */ + } + rv = f->C_Login(si->session, CKU_USER, (u_char *)pin, + (pin != NULL) ? strlen(pin) : 0); + if (pin != NULL) { + explicit_bzero(pin, strlen(pin)); free(pin); + } + if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { error("C_Login failed: %lu", rv); return (-1); } - free(pin); si->logged_in = 1; } key_filter[1].pValue = k11->keyid; @@ -366,8 +375,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) return (-1); } if (login_required && pin) { - if ((rv = f->C_Login(session, CKU_USER, - (u_char *)pin, strlen(pin))) != CKR_OK) { + rv = f->C_Login(session, CKU_USER, + (u_char *)pin, strlen(pin)); + if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { error("C_Login failed: %lu", rv); if ((rv = f->C_CloseSession(session)) != CKR_OK) error("C_CloseSession failed: %lu", rv); @@ -385,12 +395,12 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) * keysp points to an (possibly empty) array with *nkeys keys. */ static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG, - CK_ATTRIBUTE [], CK_ATTRIBUTE [3], Key ***, int *) + CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *) __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE)))); static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, - Key ***keysp, int *nkeys) + struct sshkey ***keysp, int *nkeys) { CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; @@ -422,12 +432,12 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, } static int -pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) +pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) { int i; for (i = 0; i < *nkeys; i++) - if (key_equal(key, (*keysp)[i])) + if (sshkey_equal(key, (*keysp)[i])) return (1); return (0); } @@ -435,9 +445,9 @@ pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) static int pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], - Key ***keysp, int *nkeys) + struct sshkey ***keysp, int *nkeys) { - Key *key; + struct sshkey *key; RSA *rsa; X509 *x509; EVP_PKEY *evp; @@ -471,15 +481,23 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, error("C_GetAttributeValue failed: %lu", rv); continue; } - /* check that none of the attributes are zero length */ - if (attribs[0].ulValueLen == 0 || - attribs[1].ulValueLen == 0 || + /* + * Allow CKA_ID (always first attribute) to be empty, but + * ensure that none of the others are zero length. + * XXX assumes CKA_ID is always first. + */ + if (attribs[1].ulValueLen == 0 || attribs[2].ulValueLen == 0) { continue; } /* allocate buffers for attributes */ - for (i = 0; i < 3; i++) - attribs[i].pValue = xmalloc(attribs[i].ulValueLen); + for (i = 0; i < 3; i++) { + if (attribs[i].ulValueLen > 0) { + attribs[i].pValue = xmalloc( + attribs[i].ulValueLen); + } + } + /* * retrieve ID, modulus and public exponent of RSA key, * or ID, subject and value for certificates. @@ -517,16 +535,16 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, } if (rsa && rsa->n && rsa->e && pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { - key = key_new(KEY_UNSPEC); + key = sshkey_new(KEY_UNSPEC); key->rsa = rsa; key->type = KEY_RSA; - key->flags |= KEY_FLAG_EXT; + key->flags |= SSHKEY_FLAG_EXT; if (pkcs11_key_included(keysp, nkeys, key)) { - key_free(key); + sshkey_free(key); } else { /* expand key array and add key */ - *keysp = xrealloc(*keysp, *nkeys + 1, - sizeof(Key *)); + *keysp = xreallocarray(*keysp, *nkeys + 1, + sizeof(struct sshkey *)); (*keysp)[*nkeys] = key; *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); @@ -544,7 +562,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, /* register a new provider, fails if provider already exists */ int -pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp) +pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) { int nkeys, need_finalize = 0; struct pkcs11_provider *p = NULL; @@ -621,6 +639,11 @@ pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp) error("C_GetTokenInfo failed: %lu", rv); continue; } + if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { + debug2("%s: ignoring uninitialised token in slot %lu", + __func__, (unsigned long)i); + continue; + } rmspace(token->label, sizeof(token->label)); rmspace(token->manufacturerID, sizeof(token->manufacturerID)); rmspace(token->model, sizeof(token->model)); diff --git a/crypto/openssh/ssh-pkcs11.h b/crypto/openssh/ssh-pkcs11.h index 59f456a..0ced74f 100644 --- a/crypto/openssh/ssh-pkcs11.h +++ b/crypto/openssh/ssh-pkcs11.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.h,v 1.2 2010/02/24 06:12:53 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.h,v 1.4 2015/01/15 09:40:00 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -16,5 +16,9 @@ */ int pkcs11_init(int); void pkcs11_terminate(void); -int pkcs11_add_provider(char *, char *, Key ***); +int pkcs11_add_provider(char *, char *, struct sshkey ***); int pkcs11_del_provider(char *); + +#if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) +#undef ENABLE_PKCS11 +#endif diff --git a/crypto/openssh/ssh-rsa.c b/crypto/openssh/ssh-rsa.c index c6f25b3..cdc18a4 100644 --- a/crypto/openssh/ssh-rsa.c +++ b/crypto/openssh/ssh-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.c,v 1.51 2014/02/02 03:44:31 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.53 2015/06/15 01:32:50 djm Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl * @@ -17,6 +17,8 @@ #include "includes.h" +#ifdef WITH_OPENSSL + #include #include @@ -25,163 +27,167 @@ #include #include -#include "xmalloc.h" -#include "log.h" -#include "buffer.h" -#include "key.h" +#include "sshbuf.h" #include "compat.h" -#include "misc.h" -#include "ssh.h" +#include "ssherr.h" +#define SSHKEY_INTERNAL +#include "sshkey.h" #include "digest.h" -static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); +static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int -ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, - const u_char *data, u_int datalen) +ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) { int hash_alg; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sig; - u_int slen, dlen, len; - int ok, nid; - Buffer b; + u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; + size_t slen; + u_int dlen, len; + int nid, ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; - if (key == NULL || key_type_plain(key->type) != KEY_RSA || - key->rsa == NULL) { - error("%s: no RSA key", __func__); - return -1; - } + if (lenp != NULL) + *lenp = 0; + if (sigp != NULL) + *sigp = NULL; + + if (key == NULL || key->rsa == NULL || + sshkey_type_plain(key->type) != KEY_RSA) + return SSH_ERR_INVALID_ARGUMENT; + slen = RSA_size(key->rsa); + if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) + return SSH_ERR_INVALID_ARGUMENT; /* hash the data */ hash_alg = SSH_DIGEST_SHA1; nid = NID_sha1; - if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { - error("%s: bad hash algorithm %d", __func__, hash_alg); - return -1; - } - if (ssh_digest_memory(hash_alg, data, datalen, - digest, sizeof(digest)) != 0) { - error("%s: ssh_digest_memory failed", __func__); - return -1; - } + if ((dlen = ssh_digest_bytes(hash_alg)) == 0) + return SSH_ERR_INTERNAL_ERROR; + if ((ret = ssh_digest_memory(hash_alg, data, datalen, + digest, sizeof(digest))) != 0) + goto out; - slen = RSA_size(key->rsa); - sig = xmalloc(slen); - - ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); - explicit_bzero(digest, sizeof(digest)); - - if (ok != 1) { - int ecode = ERR_get_error(); + if ((sig = malloc(slen)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } - error("%s: RSA_sign failed: %s", __func__, - ERR_error_string(ecode, NULL)); - free(sig); - return -1; + if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } if (len < slen) { - u_int diff = slen - len; - debug("slen %u > len %u", slen, len); + size_t diff = slen - len; memmove(sig + diff, sig, len); explicit_bzero(sig, diff); } else if (len > slen) { - error("%s: slen %u slen2 %u", __func__, slen, len); - free(sig); - return -1; + ret = SSH_ERR_INTERNAL_ERROR; + goto out; } /* encode signature */ - buffer_init(&b); - buffer_put_cstring(&b, "ssh-rsa"); - buffer_put_string(&b, sig, slen); - len = buffer_len(&b); + if ((b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((ret = sshbuf_put_cstring(b, "ssh-rsa")) != 0 || + (ret = sshbuf_put_string(b, sig, slen)) != 0) + goto out; + len = sshbuf_len(b); + if (sigp != NULL) { + if ((*sigp = malloc(len)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + memcpy(*sigp, sshbuf_ptr(b), len); + } if (lenp != NULL) *lenp = len; - if (sigp != NULL) { - *sigp = xmalloc(len); - memcpy(*sigp, buffer_ptr(&b), len); + ret = 0; + out: + explicit_bzero(digest, sizeof(digest)); + if (sig != NULL) { + explicit_bzero(sig, slen); + free(sig); } - buffer_free(&b); - explicit_bzero(sig, slen); - free(sig); - - return 0; + if (b != NULL) + sshbuf_free(b); + return ret; } int -ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, - const u_char *data, u_int datalen) +ssh_rsa_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat) { - Buffer b; - int hash_alg; - char *ktype; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; - u_int len, dlen, modlen; - int rlen, ret; + char *ktype = NULL; + int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; + size_t len, diff, modlen, dlen; + struct sshbuf *b = NULL; + u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; - if (key == NULL || key_type_plain(key->type) != KEY_RSA || - key->rsa == NULL) { - error("%s: no RSA key", __func__); - return -1; - } + if (key == NULL || key->rsa == NULL || + sshkey_type_plain(key->type) != KEY_RSA || + BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_INVALID_ARGUMENT; - if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - error("%s: RSA modulus too small: %d < minimum %d bits", - __func__, BN_num_bits(key->rsa->n), - SSH_RSA_MINIMUM_MODULUS_SIZE); - return -1; + if ((b = sshbuf_from(signature, signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; } - buffer_init(&b); - buffer_append(&b, signature, signaturelen); - ktype = buffer_get_cstring(&b, NULL); if (strcmp("ssh-rsa", ktype) != 0) { - error("%s: cannot handle type %s", __func__, ktype); - buffer_free(&b); - free(ktype); - return -1; + ret = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; } - free(ktype); - sigblob = buffer_get_string(&b, &len); - rlen = buffer_len(&b); - buffer_free(&b); - if (rlen != 0) { - error("%s: remaining bytes in signature %d", __func__, rlen); - free(sigblob); - return -1; + if (sshbuf_get_string(b, &sigblob, &len) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(b) != 0) { + ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { - error("%s: len %u > modlen %u", __func__, len, modlen); - free(sigblob); - return -1; + ret = SSH_ERR_KEY_BITS_MISMATCH; + goto out; } else if (len < modlen) { - u_int diff = modlen - len; - debug("%s: add padding: modlen %u > len %u", __func__, - modlen, len); - sigblob = xrealloc(sigblob, 1, modlen); + diff = modlen - len; + osigblob = sigblob; + if ((sigblob = realloc(sigblob, modlen)) == NULL) { + sigblob = osigblob; /* put it back for clear/free */ + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } memmove(sigblob + diff, sigblob, len); explicit_bzero(sigblob, diff); len = modlen; } - /* hash the data */ hash_alg = SSH_DIGEST_SHA1; if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { - error("%s: bad hash algorithm %d", __func__, hash_alg); - return -1; - } - if (ssh_digest_memory(hash_alg, data, datalen, - digest, sizeof(digest)) != 0) { - error("%s: ssh_digest_memory failed", __func__); - return -1; + ret = SSH_ERR_INTERNAL_ERROR; + goto out; } + if ((ret = ssh_digest_memory(hash_alg, data, datalen, + digest, sizeof(digest))) != 0) + goto out; ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, key->rsa); + out: + if (sigblob != NULL) { + explicit_bzero(sigblob, len); + free(sigblob); + } + if (ktype != NULL) + free(ktype); + if (b != NULL) + sshbuf_free(b); explicit_bzero(digest, sizeof(digest)); - explicit_bzero(sigblob, len); - free(sigblob); - debug("%s: signature %scorrect", __func__, (ret == 0) ? "in" : ""); return ret; } @@ -204,15 +210,15 @@ static const u_char id_sha1[] = { }; static int -openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen, - u_char *sigbuf, u_int siglen, RSA *rsa) +openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, + u_char *sigbuf, size_t siglen, RSA *rsa) { - u_int ret, rsasize, oidlen = 0, hlen = 0; + size_t ret, rsasize = 0, oidlen = 0, hlen = 0; int len, oidmatch, hashmatch; const u_char *oid = NULL; u_char *decrypted = NULL; - ret = 0; + ret = SSH_ERR_INTERNAL_ERROR; switch (hash_alg) { case SSH_DIGEST_SHA1: oid = id_sha1; @@ -223,37 +229,40 @@ openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen, goto done; } if (hashlen != hlen) { - error("bad hashlen"); + ret = SSH_ERR_INVALID_ARGUMENT; goto done; } rsasize = RSA_size(rsa); - if (siglen == 0 || siglen > rsasize) { - error("bad siglen"); + if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || + siglen == 0 || siglen > rsasize) { + ret = SSH_ERR_INVALID_ARGUMENT; + goto done; + } + if ((decrypted = malloc(rsasize)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; goto done; } - decrypted = xmalloc(rsasize); if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, RSA_PKCS1_PADDING)) < 0) { - error("RSA_public_decrypt failed: %s", - ERR_error_string(ERR_get_error(), NULL)); + ret = SSH_ERR_LIBCRYPTO_ERROR; goto done; } - if (len < 0 || (u_int)len != hlen + oidlen) { - error("bad decrypted len: %d != %d + %d", len, hlen, oidlen); + if (len < 0 || (size_t)len != hlen + oidlen) { + ret = SSH_ERR_INVALID_FORMAT; goto done; } oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; - if (!oidmatch) { - error("oid mismatch"); - goto done; - } - if (!hashmatch) { - error("hash mismatch"); + if (!oidmatch || !hashmatch) { + ret = SSH_ERR_SIGNATURE_INVALID; goto done; } - ret = 1; + ret = 0; done: - free(decrypted); + if (decrypted) { + explicit_bzero(decrypted, rsasize); + free(decrypted); + } return ret; } +#endif /* WITH_OPENSSL */ diff --git a/crypto/openssh/ssh.0 b/crypto/openssh/ssh.0 deleted file mode 100644 index 16868cf..0000000 --- a/crypto/openssh/ssh.0 +++ /dev/null @@ -1,946 +0,0 @@ -SSH(1) OpenBSD Reference Manual SSH(1) - -NAME - ssh - OpenSSH SSH client (remote login program) - -SYNOPSIS - ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] - [-D [bind_address:]port] [-E log_file] [-e escape_char] - [-F configfile] [-I pkcs11] [-i identity_file] - [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec] - [-O ctl_cmd] [-o option] [-p port] - [-Q cipher | cipher-auth | mac | kex | key] - [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port] - [-w local_tun[:remote_tun]] [user@]hostname [command] - -DESCRIPTION - ssh (SSH client) is a program for logging into a remote machine and for - executing commands on a remote machine. It is intended to replace rlogin - and rsh, and provide secure encrypted communications between two - untrusted hosts over an insecure network. X11 connections and arbitrary - TCP ports can also be forwarded over the secure channel. - - ssh connects and logs into the specified hostname (with optional user - name). The user must prove his/her identity to the remote machine using - one of several methods depending on the protocol version used (see - below). - - If command is specified, it is executed on the remote host instead of a - login shell. - - The options are as follows: - - -1 Forces ssh to try protocol version 1 only. - - -2 Forces ssh to try protocol version 2 only. - - -4 Forces ssh to use IPv4 addresses only. - - -6 Forces ssh to use IPv6 addresses only. - - -A Enables forwarding of the authentication agent connection. This - can also be specified on a per-host basis in a configuration - file. - - Agent forwarding should be enabled with caution. Users with the - ability to bypass file permissions on the remote host (for the - agent's UNIX-domain socket) can access the local agent through - the forwarded connection. An attacker cannot obtain key material - from the agent, however they can perform operations on the keys - that enable them to authenticate using the identities loaded into - the agent. - - -a Disables forwarding of the authentication agent connection. - - -b bind_address - Use bind_address on the local machine as the source address of - the connection. Only useful on systems with more than one - address. - - -C Requests compression of all data (including stdin, stdout, - stderr, and data for forwarded X11 and TCP connections). The - compression algorithm is the same used by gzip(1), and the - ``level'' can be controlled by the CompressionLevel option for - protocol version 1. Compression is desirable on modem lines and - other slow connections, but will only slow down things on fast - networks. The default value can be set on a host-by-host basis - in the configuration files; see the Compression option. - - -c cipher_spec - Selects the cipher specification for encrypting the session. - - Protocol version 1 allows specification of a single cipher. The - supported values are ``3des'', ``blowfish'', and ``des''. 3des - (triple-des) is an encrypt-decrypt-encrypt triple with three - different keys. It is believed to be secure. blowfish is a fast - block cipher; it appears very secure and is much faster than - 3des. des is only supported in the ssh client for - interoperability with legacy protocol 1 implementations that do - not support the 3des cipher. Its use is strongly discouraged due - to cryptographic weaknesses. The default is ``3des''. - - For protocol version 2, cipher_spec is a comma-separated list of - ciphers listed in order of preference. See the Ciphers keyword - in ssh_config(5) for more information. - - -D [bind_address:]port - Specifies a local ``dynamic'' application-level port forwarding. - This works by allocating a socket to listen to port on the local - side, optionally bound to the specified bind_address. Whenever a - connection is made to this port, the connection is forwarded over - the secure channel, and the application protocol is then used to - determine where to connect to from the remote machine. Currently - the SOCKS4 and SOCKS5 protocols are supported, and ssh will act - as a SOCKS server. Only root can forward privileged ports. - Dynamic port forwardings can also be specified in the - configuration file. - - IPv6 addresses can be specified by enclosing the address in - square brackets. Only the superuser can forward privileged - ports. By default, the local port is bound in accordance with - the GatewayPorts setting. However, an explicit bind_address may - be used to bind the connection to a specific address. The - bind_address of ``localhost'' indicates that the listening port - be bound for local use only, while an empty address or `*' - indicates that the port should be available from all interfaces. - - -E log_file - Append debug logs to log_file instead of standard error. - - -e escape_char - Sets the escape character for sessions with a pty (default: `~'). - The escape character is only recognized at the beginning of a - line. The escape character followed by a dot (`.') closes the - connection; followed by control-Z suspends the connection; and - followed by itself sends the escape character once. Setting the - character to ``none'' disables any escapes and makes the session - fully transparent. - - -F configfile - Specifies an alternative per-user configuration file. If a - configuration file is given on the command line, the system-wide - configuration file (/etc/ssh/ssh_config) will be ignored. The - default for the per-user configuration file is ~/.ssh/config. - - -f Requests ssh to go to background just before command execution. - This is useful if ssh is going to ask for passwords or - passphrases, but the user wants it in the background. This - implies -n. The recommended way to start X11 programs at a - remote site is with something like ssh -f host xterm. - - If the ExitOnForwardFailure configuration option is set to - ``yes'', then a client started with -f will wait for all remote - port forwards to be successfully established before placing - itself in the background. - - -g Allows remote hosts to connect to local forwarded ports. - - -I pkcs11 - Specify the PKCS#11 shared library ssh should use to communicate - with a PKCS#11 token providing the user's private RSA key. - - -i identity_file - Selects a file from which the identity (private key) for public - key authentication is read. The default is ~/.ssh/identity for - protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, - ~/.ssh/id_ed25519 and ~/.ssh/id_rsa for protocol version 2. - Identity files may also be specified on a per-host basis in the - configuration file. It is possible to have multiple -i options - (and multiple identities specified in configuration files). ssh - will also try to load certificate information from the filename - obtained by appending -cert.pub to identity filenames. - - -K Enables GSSAPI-based authentication and forwarding (delegation) - of GSSAPI credentials to the server. - - -k Disables forwarding (delegation) of GSSAPI credentials to the - server. - - -L [bind_address:]port:host:hostport - Specifies that the given port on the local (client) host is to be - forwarded to the given host and port on the remote side. This - works by allocating a socket to listen to port on the local side, - optionally bound to the specified bind_address. Whenever a - connection is made to this port, the connection is forwarded over - the secure channel, and a connection is made to host port - hostport from the remote machine. Port forwardings can also be - specified in the configuration file. IPv6 addresses can be - specified by enclosing the address in square brackets. Only the - superuser can forward privileged ports. By default, the local - port is bound in accordance with the GatewayPorts setting. - However, an explicit bind_address may be used to bind the - connection to a specific address. The bind_address of - ``localhost'' indicates that the listening port be bound for - local use only, while an empty address or `*' indicates that the - port should be available from all interfaces. - - -l login_name - Specifies the user to log in as on the remote machine. This also - may be specified on a per-host basis in the configuration file. - - -M Places the ssh client into ``master'' mode for connection - sharing. Multiple -M options places ssh into ``master'' mode - with confirmation required before slave connections are accepted. - Refer to the description of ControlMaster in ssh_config(5) for - details. - - -m mac_spec - Additionally, for protocol version 2 a comma-separated list of - MAC (message authentication code) algorithms can be specified in - order of preference. See the MACs keyword for more information. - - -N Do not execute a remote command. This is useful for just - forwarding ports (protocol version 2 only). - - -n Redirects stdin from /dev/null (actually, prevents reading from - stdin). This must be used when ssh is run in the background. A - common trick is to use this to run X11 programs on a remote - machine. For example, ssh -n shadows.cs.hut.fi emacs & will - start an emacs on shadows.cs.hut.fi, and the X11 connection will - be automatically forwarded over an encrypted channel. The ssh - program will be put in the background. (This does not work if - ssh needs to ask for a password or passphrase; see also the -f - option.) - - -O ctl_cmd - Control an active connection multiplexing master process. When - the -O option is specified, the ctl_cmd argument is interpreted - and passed to the master process. Valid commands are: ``check'' - (check that the master process is running), ``forward'' (request - forwardings without command execution), ``cancel'' (cancel - forwardings), ``exit'' (request the master to exit), and ``stop'' - (request the master to stop accepting further multiplexing - requests). - - -o option - Can be used to give options in the format used in the - configuration file. This is useful for specifying options for - which there is no separate command-line flag. For full details - of the options listed below, and their possible values, see - ssh_config(5). - - AddressFamily - BatchMode - BindAddress - CanonicalDomains - CanonicalizeFallbackLocal - CanonicalizeHostname - CanonicalizeMaxDots - CanonicalizePermittedCNAMEs - ChallengeResponseAuthentication - CheckHostIP - Cipher - Ciphers - ClearAllForwardings - Compression - CompressionLevel - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - ControlPersist - DynamicForward - EscapeChar - ExitOnForwardFailure - ForwardAgent - ForwardX11 - ForwardX11Timeout - ForwardX11Trusted - GatewayPorts - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - HostName - IdentityFile - IdentitiesOnly - IPQoS - KbdInteractiveAuthentication - KbdInteractiveDevices - KexAlgorithms - LocalCommand - LocalForward - LogLevel - MACs - Match - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PermitLocalCommand - PKCS11Provider - Port - PreferredAuthentications - Protocol - ProxyCommand - ProxyUseFdpass - PubkeyAuthentication - RekeyLimit - RemoteForward - RequestTTY - RhostsRSAAuthentication - RSAAuthentication - SendEnv - ServerAliveInterval - ServerAliveCountMax - StrictHostKeyChecking - TCPKeepAlive - Tunnel - TunnelDevice - UsePrivilegedPort - User - UserKnownHostsFile - VerifyHostKeyDNS - VisualHostKey - XAuthLocation - - -p port - Port to connect to on the remote host. This can be specified on - a per-host basis in the configuration file. - - -Q cipher | cipher-auth | mac | kex | key - Queries ssh for the algorithms supported for the specified - version 2. The available features are: cipher (supported - symmetric ciphers), cipher-auth (supported symmetric ciphers that - support authenticated encryption), mac (supported message - integrity codes), kex (key exchange algorithms), key (key types). - - -q Quiet mode. Causes most warning and diagnostic messages to be - suppressed. - - -R [bind_address:]port:host:hostport - Specifies that the given port on the remote (server) host is to - be forwarded to the given host and port on the local side. This - works by allocating a socket to listen to port on the remote - side, and whenever a connection is made to this port, the - connection is forwarded over the secure channel, and a connection - is made to host port hostport from the local machine. - - Port forwardings can also be specified in the configuration file. - Privileged ports can be forwarded only when logging in as root on - the remote machine. IPv6 addresses can be specified by enclosing - the address in square brackets. - - By default, the listening socket on the server will be bound to - the loopback interface only. This may be overridden by - specifying a bind_address. An empty bind_address, or the address - `*', indicates that the remote socket should listen on all - interfaces. Specifying a remote bind_address will only succeed - if the server's GatewayPorts option is enabled (see - sshd_config(5)). - - If the port argument is `0', the listen port will be dynamically - allocated on the server and reported to the client at run time. - When used together with -O forward the allocated port will be - printed to the standard output. - - -S ctl_path - Specifies the location of a control socket for connection - sharing, or the string ``none'' to disable connection sharing. - Refer to the description of ControlPath and ControlMaster in - ssh_config(5) for details. - - -s May be used to request invocation of a subsystem on the remote - system. Subsystems are a feature of the SSH2 protocol which - facilitate the use of SSH as a secure transport for other - applications (eg. sftp(1)). The subsystem is specified as the - remote command. - - -T Disable pseudo-tty allocation. - - -t Force pseudo-tty allocation. This can be used to execute - arbitrary screen-based programs on a remote machine, which can be - very useful, e.g. when implementing menu services. Multiple -t - options force tty allocation, even if ssh has no local tty. - - -V Display the version number and exit. - - -v Verbose mode. Causes ssh to print debugging messages about its - progress. This is helpful in debugging connection, - authentication, and configuration problems. Multiple -v options - increase the verbosity. The maximum is 3. - - -W host:port - Requests that standard input and output on the client be - forwarded to host on port over the secure channel. Implies -N, - -T, ExitOnForwardFailure and ClearAllForwardings. Works with - Protocol version 2 only. - - -w local_tun[:remote_tun] - Requests tunnel device forwarding with the specified tun(4) - devices between the client (local_tun) and the server - (remote_tun). - - The devices may be specified by numerical ID or the keyword - ``any'', which uses the next available tunnel device. If - remote_tun is not specified, it defaults to ``any''. See also - the Tunnel and TunnelDevice directives in ssh_config(5). If the - Tunnel directive is unset, it is set to the default tunnel mode, - which is ``point-to-point''. - - -X Enables X11 forwarding. This can also be specified on a per-host - basis in a configuration file. - - X11 forwarding should be enabled with caution. Users with the - ability to bypass file permissions on the remote host (for the - user's X authorization database) can access the local X11 display - through the forwarded connection. An attacker may then be able - to perform activities such as keystroke monitoring. - - For this reason, X11 forwarding is subjected to X11 SECURITY - extension restrictions by default. Please refer to the ssh -Y - option and the ForwardX11Trusted directive in ssh_config(5) for - more information. - - -x Disables X11 forwarding. - - -Y Enables trusted X11 forwarding. Trusted X11 forwardings are not - subjected to the X11 SECURITY extension controls. - - -y Send log information using the syslog(3) system module. By - default this information is sent to stderr. - - ssh may additionally obtain configuration data from a per-user - configuration file and a system-wide configuration file. The file format - and configuration options are described in ssh_config(5). - -AUTHENTICATION - The OpenSSH SSH client supports SSH protocols 1 and 2. The default is to - use protocol 2 only, though this can be changed via the Protocol option - in ssh_config(5) or the -1 and -2 options (see above). Both protocols - support similar authentication methods, but protocol 2 is the default - since it provides additional mechanisms for confidentiality (the traffic - is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour) and - integrity (hmac-md5, hmac-sha1, hmac-sha2-256, hmac-sha2-512, umac-64, - umac-128, hmac-ripemd160). Protocol 1 lacks a strong mechanism for - ensuring the integrity of the connection. - - The methods available for authentication are: GSSAPI-based - authentication, host-based authentication, public key authentication, - challenge-response authentication, and password authentication. - Authentication methods are tried in the order specified above, though - protocol 2 has a configuration option to change the default order: - PreferredAuthentications. - - Host-based authentication works as follows: If the machine the user logs - in from is listed in /etc/hosts.equiv or /etc/shosts.equiv on the remote - machine, and the user names are the same on both sides, or if the files - ~/.rhosts or ~/.shosts exist in the user's home directory on the remote - machine and contain a line containing the name of the client machine and - the name of the user on that machine, the user is considered for login. - Additionally, the server must be able to verify the client's host key - (see the description of /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts, - below) for login to be permitted. This authentication method closes - security holes due to IP spoofing, DNS spoofing, and routing spoofing. - [Note to the administrator: /etc/hosts.equiv, ~/.rhosts, and the - rlogin/rsh protocol in general, are inherently insecure and should be - disabled if security is desired.] - - Public key authentication works as follows: The scheme is based on - public-key cryptography, using cryptosystems where encryption and - decryption are done using separate keys, and it is unfeasible to derive - the decryption key from the encryption key. The idea is that each user - creates a public/private key pair for authentication purposes. The - server knows the public key, and only the user knows the private key. - ssh implements public key authentication protocol automatically, using - one of the DSA, ECDSA, ED25519 or RSA algorithms. Protocol 1 is - restricted to using only RSA keys, but protocol 2 may use any. The - HISTORY section of ssl(8) contains a brief discussion of the DSA and RSA - algorithms. - - The file ~/.ssh/authorized_keys lists the public keys that are permitted - for logging in. When the user logs in, the ssh program tells the server - which key pair it would like to use for authentication. The client - proves that it has access to the private key and the server checks that - the corresponding public key is authorized to accept the account. - - The user creates his/her key pair by running ssh-keygen(1). This stores - the private key in ~/.ssh/identity (protocol 1), ~/.ssh/id_dsa (protocol - 2 DSA), ~/.ssh/id_ecdsa (protocol 2 ECDSA), ~/.ssh/id_ed25519 (protocol 2 - ED25519), or ~/.ssh/id_rsa (protocol 2 RSA) and stores the public key in - ~/.ssh/identity.pub (protocol 1), ~/.ssh/id_dsa.pub (protocol 2 DSA), - ~/.ssh/id_ecdsa.pub (protocol 2 ECDSA), ~/.ssh/id_ed25519.pub (protocol 2 - ED25519), or ~/.ssh/id_rsa.pub (protocol 2 RSA) in the user's home - directory. The user should then copy the public key to - ~/.ssh/authorized_keys in his/her home directory on the remote machine. - The authorized_keys file corresponds to the conventional ~/.rhosts file, - and has one key per line, though the lines can be very long. After this, - the user can log in without giving the password. - - A variation on public key authentication is available in the form of - certificate authentication: instead of a set of public/private keys, - signed certificates are used. This has the advantage that a single - trusted certification authority can be used in place of many - public/private keys. See the CERTIFICATES section of ssh-keygen(1) for - more information. - - The most convenient way to use public key or certificate authentication - may be with an authentication agent. See ssh-agent(1) for more - information. - - Challenge-response authentication works as follows: The server sends an - arbitrary "challenge" text, and prompts for a response. Protocol 2 - allows multiple challenges and responses; protocol 1 is restricted to - just one challenge/response. Examples of challenge-response - authentication include BSD Authentication (see login.conf(5)) and PAM - (some non-OpenBSD systems). - - Finally, if other authentication methods fail, ssh prompts the user for a - password. The password is sent to the remote host for checking; however, - since all communications are encrypted, the password cannot be seen by - someone listening on the network. - - ssh automatically maintains and checks a database containing - identification for all hosts it has ever been used with. Host keys are - stored in ~/.ssh/known_hosts in the user's home directory. Additionally, - the file /etc/ssh/ssh_known_hosts is automatically checked for known - hosts. Any new hosts are automatically added to the user's file. If a - host's identification ever changes, ssh warns about this and disables - password authentication to prevent server spoofing or man-in-the-middle - attacks, which could otherwise be used to circumvent the encryption. The - StrictHostKeyChecking option can be used to control logins to machines - whose host key is not known or has changed. - - When the user's identity has been accepted by the server, the server - either executes the given command, or logs into the machine and gives the - user a normal shell on the remote machine. All communication with the - remote command or shell will be automatically encrypted. - - If a pseudo-terminal has been allocated (normal login session), the user - may use the escape characters noted below. - - If no pseudo-tty has been allocated, the session is transparent and can - be used to reliably transfer binary data. On most systems, setting the - escape character to ``none'' will also make the session transparent even - if a tty is used. - - The session terminates when the command or shell on the remote machine - exits and all X11 and TCP connections have been closed. - -ESCAPE CHARACTERS - When a pseudo-terminal has been requested, ssh supports a number of - functions through the use of an escape character. - - A single tilde character can be sent as ~~ or by following the tilde by a - character other than those described below. The escape character must - always follow a newline to be interpreted as special. The escape - character can be changed in configuration files using the EscapeChar - configuration directive or on the command line by the -e option. - - The supported escapes (assuming the default `~') are: - - ~. Disconnect. - - ~^Z Background ssh. - - ~# List forwarded connections. - - ~& Background ssh at logout when waiting for forwarded connection / - X11 sessions to terminate. - - ~? Display a list of escape characters. - - ~B Send a BREAK to the remote system (only useful for SSH protocol - version 2 and if the peer supports it). - - ~C Open command line. Currently this allows the addition of port - forwardings using the -L, -R and -D options (see above). It also - allows the cancellation of existing port-forwardings with - -KL[bind_address:]port for local, -KR[bind_address:]port for - remote and -KD[bind_address:]port for dynamic port-forwardings. - !command allows the user to execute a local command if the - PermitLocalCommand option is enabled in ssh_config(5). Basic - help is available, using the -h option. - - ~R Request rekeying of the connection (only useful for SSH protocol - version 2 and if the peer supports it). - - ~V Decrease the verbosity (LogLevel) when errors are being written - to stderr. - - ~v Increase the verbosity (LogLevel) when errors are being written - to stderr. - -TCP FORWARDING - Forwarding of arbitrary TCP connections over the secure channel can be - specified either on the command line or in a configuration file. One - possible application of TCP forwarding is a secure connection to a mail - server; another is going through firewalls. - - In the example below, we look at encrypting communication between an IRC - client and server, even though the IRC server does not directly support - encrypted communications. This works as follows: the user connects to - the remote host using ssh, specifying a port to be used to forward - connections to the remote server. After that it is possible to start the - service which is to be encrypted on the client machine, connecting to the - same local port, and ssh will encrypt and forward the connection. - - The following example tunnels an IRC session from client machine - ``127.0.0.1'' (localhost) to remote server ``server.example.com'': - - $ ssh -f -L 1234:localhost:6667 server.example.com sleep 10 - $ irc -c '#users' -p 1234 pinky 127.0.0.1 - - This tunnels a connection to IRC server ``server.example.com'', joining - channel ``#users'', nickname ``pinky'', using port 1234. It doesn't - matter which port is used, as long as it's greater than 1023 (remember, - only root can open sockets on privileged ports) and doesn't conflict with - any ports already in use. The connection is forwarded to port 6667 on - the remote server, since that's the standard port for IRC services. - - The -f option backgrounds ssh and the remote command ``sleep 10'' is - specified to allow an amount of time (10 seconds, in the example) to - start the service which is to be tunnelled. If no connections are made - within the time specified, ssh will exit. - -X11 FORWARDING - If the ForwardX11 variable is set to ``yes'' (or see the description of - the -X, -x, and -Y options above) and the user is using X11 (the DISPLAY - environment variable is set), the connection to the X11 display is - automatically forwarded to the remote side in such a way that any X11 - programs started from the shell (or command) will go through the - encrypted channel, and the connection to the real X server will be made - from the local machine. The user should not manually set DISPLAY. - Forwarding of X11 connections can be configured on the command line or in - configuration files. - - The DISPLAY value set by ssh will point to the server machine, but with a - display number greater than zero. This is normal, and happens because - ssh creates a ``proxy'' X server on the server machine for forwarding the - connections over the encrypted channel. - - ssh will also automatically set up Xauthority data on the server machine. - For this purpose, it will generate a random authorization cookie, store - it in Xauthority on the server, and verify that any forwarded connections - carry this cookie and replace it by the real cookie when the connection - is opened. The real authentication cookie is never sent to the server - machine (and no cookies are sent in the plain). - - If the ForwardAgent variable is set to ``yes'' (or see the description of - the -A and -a options above) and the user is using an authentication - agent, the connection to the agent is automatically forwarded to the - remote side. - -VERIFYING HOST KEYS - When connecting to a server for the first time, a fingerprint of the - server's public key is presented to the user (unless the option - StrictHostKeyChecking has been disabled). Fingerprints can be determined - using ssh-keygen(1): - - $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key - - If the fingerprint is already known, it can be matched and the key can be - accepted or rejected. Because of the difficulty of comparing host keys - just by looking at hex strings, there is also support to compare host - keys visually, using random art. By setting the VisualHostKey option to - ``yes'', a small ASCII graphic gets displayed on every login to a server, - no matter if the session itself is interactive or not. By learning the - pattern a known server produces, a user can easily find out that the host - key has changed when a completely different pattern is displayed. - Because these patterns are not unambiguous however, a pattern that looks - similar to the pattern remembered only gives a good probability that the - host key is the same, not guaranteed proof. - - To get a listing of the fingerprints along with their random art for all - known hosts, the following command line can be used: - - $ ssh-keygen -lv -f ~/.ssh/known_hosts - - If the fingerprint is unknown, an alternative method of verification is - available: SSH fingerprints verified by DNS. An additional resource - record (RR), SSHFP, is added to a zonefile and the connecting client is - able to match the fingerprint with that of the key presented. - - In this example, we are connecting a client to a server, - ``host.example.com''. The SSHFP resource records should first be added - to the zonefile for host.example.com: - - $ ssh-keygen -r host.example.com. - - The output lines will have to be added to the zonefile. To check that - the zone is answering fingerprint queries: - - $ dig -t SSHFP host.example.com - - Finally the client connects: - - $ ssh -o "VerifyHostKeyDNS ask" host.example.com - [...] - Matching host key fingerprint found in DNS. - Are you sure you want to continue connecting (yes/no)? - - See the VerifyHostKeyDNS option in ssh_config(5) for more information. - -SSH-BASED VIRTUAL PRIVATE NETWORKS - ssh contains support for Virtual Private Network (VPN) tunnelling using - the tun(4) network pseudo-device, allowing two networks to be joined - securely. The sshd_config(5) configuration option PermitTunnel controls - whether the server supports this, and at what level (layer 2 or 3 - traffic). - - The following example would connect client network 10.0.50.0/24 with - remote network 10.0.99.0/24 using a point-to-point connection from - 10.1.1.1 to 10.1.1.2, provided that the SSH server running on the gateway - to the remote network, at 192.168.1.15, allows it. - - On the client: - - # ssh -f -w 0:1 192.168.1.15 true - # ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252 - # route add 10.0.99.0/24 10.1.1.2 - - On the server: - - # ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252 - # route add 10.0.50.0/24 10.1.1.1 - - Client access may be more finely tuned via the /root/.ssh/authorized_keys - file (see below) and the PermitRootLogin server option. The following - entry would permit connections on tun(4) device 1 from user ``jane'' and - on tun device 2 from user ``john'', if PermitRootLogin is set to - ``forced-commands-only'': - - tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane - tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john - - Since an SSH-based setup entails a fair amount of overhead, it may be - more suited to temporary setups, such as for wireless VPNs. More - permanent VPNs are better provided by tools such as ipsecctl(8) and - isakmpd(8). - -ENVIRONMENT - ssh will normally set the following environment variables: - - DISPLAY The DISPLAY variable indicates the location of the - X11 server. It is automatically set by ssh to - point to a value of the form ``hostname:n'', where - ``hostname'' indicates the host where the shell - runs, and `n' is an integer >= 1. ssh uses this - special value to forward X11 connections over the - secure channel. The user should normally not set - DISPLAY explicitly, as that will render the X11 - connection insecure (and will require the user to - manually copy any required authorization cookies). - - HOME Set to the path of the user's home directory. - - LOGNAME Synonym for USER; set for compatibility with - systems that use this variable. - - MAIL Set to the path of the user's mailbox. - - PATH Set to the default PATH, as specified when - compiling ssh. - - SSH_ASKPASS If ssh needs a passphrase, it will read the - passphrase from the current terminal if it was run - from a terminal. If ssh does not have a terminal - associated with it but DISPLAY and SSH_ASKPASS are - set, it will execute the program specified by - SSH_ASKPASS and open an X11 window to read the - passphrase. This is particularly useful when - calling ssh from a .xsession or related script. - (Note that on some machines it may be necessary to - redirect the input from /dev/null to make this - work.) - - SSH_AUTH_SOCK Identifies the path of a UNIX-domain socket used to - communicate with the agent. - - SSH_CONNECTION Identifies the client and server ends of the - connection. The variable contains four space- - separated values: client IP address, client port - number, server IP address, and server port number. - - SSH_ORIGINAL_COMMAND This variable contains the original command line if - a forced command is executed. It can be used to - extract the original arguments. - - SSH_TTY This is set to the name of the tty (path to the - device) associated with the current shell or - command. If the current session has no tty, this - variable is not set. - - TZ This variable is set to indicate the present time - zone if it was set when the daemon was started - (i.e. the daemon passes the value on to new - connections). - - USER Set to the name of the user logging in. - - Additionally, ssh reads ~/.ssh/environment, and adds lines of the format - ``VARNAME=value'' to the environment if the file exists and users are - allowed to change their environment. For more information, see the - PermitUserEnvironment option in sshd_config(5). - -FILES - ~/.rhosts - This file is used for host-based authentication (see above). On - some machines this file may need to be world-readable if the - user's home directory is on an NFS partition, because sshd(8) - reads it as root. Additionally, this file must be owned by the - user, and must not have write permissions for anyone else. The - recommended permission for most machines is read/write for the - user, and not accessible by others. - - ~/.shosts - This file is used in exactly the same way as .rhosts, but allows - host-based authentication without permitting login with - rlogin/rsh. - - ~/.ssh/ - This directory is the default location for all user-specific - configuration and authentication information. There is no - general requirement to keep the entire contents of this directory - secret, but the recommended permissions are read/write/execute - for the user, and not accessible by others. - - ~/.ssh/authorized_keys - Lists the public keys (DSA, ECDSA, ED25519, RSA) that can be used - for logging in as this user. The format of this file is - described in the sshd(8) manual page. This file is not highly - sensitive, but the recommended permissions are read/write for the - user, and not accessible by others. - - ~/.ssh/config - This is the per-user configuration file. The file format and - configuration options are described in ssh_config(5). Because of - the potential for abuse, this file must have strict permissions: - read/write for the user, and not writable by others. - - ~/.ssh/environment - Contains additional definitions for environment variables; see - ENVIRONMENT, above. - - ~/.ssh/identity - ~/.ssh/id_dsa - ~/.ssh/id_ecdsa - ~/.ssh/id_ed25519 - ~/.ssh/id_rsa - Contains the private key for authentication. These files contain - sensitive data and should be readable by the user but not - accessible by others (read/write/execute). ssh will simply - ignore a private key file if it is accessible by others. It is - possible to specify a passphrase when generating the key which - will be used to encrypt the sensitive part of this file using - 3DES. - - ~/.ssh/identity.pub - ~/.ssh/id_dsa.pub - ~/.ssh/id_ecdsa.pub - ~/.ssh/id_ed25519.pub - ~/.ssh/id_rsa.pub - Contains the public key for authentication. These files are not - sensitive and can (but need not) be readable by anyone. - - ~/.ssh/known_hosts - Contains a list of host keys for all hosts the user has logged - into that are not already in the systemwide list of known host - keys. See sshd(8) for further details of the format of this - file. - - ~/.ssh/rc - Commands in this file are executed by ssh when the user logs in, - just before the user's shell (or command) is started. See the - sshd(8) manual page for more information. - - /etc/hosts.equiv - This file is for host-based authentication (see above). It - should only be writable by root. - - /etc/shosts.equiv - This file is used in exactly the same way as hosts.equiv, but - allows host-based authentication without permitting login with - rlogin/rsh. - - /etc/ssh/ssh_config - Systemwide configuration file. The file format and configuration - options are described in ssh_config(5). - - /etc/ssh/ssh_host_key - /etc/ssh/ssh_host_dsa_key - /etc/ssh/ssh_host_ecdsa_key - /etc/ssh/ssh_host_ed25519_key - /etc/ssh/ssh_host_rsa_key - These files contain the private parts of the host keys and are - used for host-based authentication. If protocol version 1 is - used, ssh must be setuid root, since the host key is readable - only by root. For protocol version 2, ssh uses ssh-keysign(8) to - access the host keys, eliminating the requirement that ssh be - setuid root when host-based authentication is used. By default - ssh is not setuid root. - - /etc/ssh/ssh_known_hosts - Systemwide list of known host keys. This file should be prepared - by the system administrator to contain the public host keys of - all machines in the organization. It should be world-readable. - See sshd(8) for further details of the format of this file. - - /etc/ssh/sshrc - Commands in this file are executed by ssh when the user logs in, - just before the user's shell (or command) is started. See the - sshd(8) manual page for more information. - -EXIT STATUS - ssh exits with the exit status of the remote command or with 255 if an - error occurred. - -SEE ALSO - scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh-keyscan(1), - tun(4), hosts.equiv(5), ssh_config(5), ssh-keysign(8), sshd(8) - -STANDARDS - S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned - Numbers, RFC 4250, January 2006. - - T. Ylonen and C. Lonvick, The Secure Shell (SSH) Protocol Architecture, - RFC 4251, January 2006. - - T. Ylonen and C. Lonvick, The Secure Shell (SSH) Authentication Protocol, - RFC 4252, January 2006. - - T. Ylonen and C. Lonvick, The Secure Shell (SSH) Transport Layer - Protocol, RFC 4253, January 2006. - - T. Ylonen and C. Lonvick, The Secure Shell (SSH) Connection Protocol, RFC - 4254, January 2006. - - J. Schlyter and W. Griffin, Using DNS to Securely Publish Secure Shell - (SSH) Key Fingerprints, RFC 4255, January 2006. - - F. Cusack and M. Forssen, Generic Message Exchange Authentication for the - Secure Shell Protocol (SSH), RFC 4256, January 2006. - - J. Galbraith and P. Remaker, The Secure Shell (SSH) Session Channel Break - Extension, RFC 4335, January 2006. - - M. Bellare, T. Kohno, and C. Namprempre, The Secure Shell (SSH) Transport - Layer Encryption Modes, RFC 4344, January 2006. - - B. Harris, Improved Arcfour Modes for the Secure Shell (SSH) Transport - Layer Protocol, RFC 4345, January 2006. - - M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for - the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006. - - J. Galbraith and R. Thayer, The Secure Shell (SSH) Public Key File - Format, RFC 4716, November 2006. - - D. Stebila and J. Green, Elliptic Curve Algorithm Integration in the - Secure Shell Transport Layer, RFC 5656, December 2009. - - A. Perrig and D. Song, Hash Visualization: a New Technique to improve - Real-World Security, 1999, International Workshop on Cryptographic - Techniques and E-Commerce (CrypTEC '99). - -AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by - Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. - -OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/ssh.1 b/crypto/openssh/ssh.1 index 00785ef..9bb6c57 100644 --- a/crypto/openssh/ssh.1 +++ b/crypto/openssh/ssh.1 @@ -33,9 +33,9 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.343 2013/12/07 11:58:46 naddy Exp $ +.\" $OpenBSD: ssh.1,v 1.361 2015/07/20 18:44:12 millert Exp $ .\" $FreeBSD$ -.Dd $Mdocdate: December 7 2013 $ +.Dd $Mdocdate: July 20 2015 $ .Dt SSH 1 .Os .Sh NAME @@ -44,7 +44,7 @@ .Sh SYNOPSIS .Nm ssh .Bk -words -.Op Fl 1246AaCfgKkMNnqsTtVvXxYy +.Op Fl 1246AaCfGgKkMNnqsTtVvXxYy .Op Fl b Ar bind_address .Op Fl c Ar cipher_spec .Op Fl D Oo Ar bind_address : Oc Ns Ar port @@ -53,14 +53,14 @@ .Op Fl F Ar configfile .Op Fl I Ar pkcs11 .Op Fl i Ar identity_file -.Op Fl L Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport +.Op Fl L Ar address .Op Fl l Ar login_name .Op Fl m Ar mac_spec .Op Fl O Ar ctl_cmd .Op Fl o Ar option .Op Fl p Ar port -.Op Fl Q Cm cipher | cipher-auth | mac | kex | key -.Op Fl R Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport +.Op Fl Q Cm cipher | cipher-auth | mac | kex | key | protocol-version +.Op Fl R Ar address .Op Fl S Ar ctl_path .Op Fl W Ar host : Ns Ar port .Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun @@ -74,8 +74,9 @@ executing commands on a remote machine. It is intended to replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network. -X11 connections and arbitrary TCP ports -can also be forwarded over the secure channel. +X11 connections, arbitrary TCP ports and +.Ux Ns -domain +sockets can also be forwarded over the secure channel. .Pp .Nm connects and logs into the specified @@ -93,23 +94,28 @@ is specified, it is executed on the remote host instead of a login shell. .Pp The options are as follows: -.Bl -tag -width Ds +.Pp +.Bl -tag -width Ds -compact .It Fl 1 Forces .Nm to try protocol version 1 only. +.Pp .It Fl 2 Forces .Nm to try protocol version 2 only. +.Pp .It Fl 4 Forces .Nm to use IPv4 addresses only. +.Pp .It Fl 6 Forces .Nm to use IPv6 addresses only. +.Pp .It Fl A Enables forwarding of the authentication agent connection. This can also be specified on a per-host basis in a configuration file. @@ -122,17 +128,22 @@ socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent. +.Pp .It Fl a Disables forwarding of the authentication agent connection. +.Pp .It Fl b Ar bind_address Use .Ar bind_address on the local machine as the source address of the connection. Only useful on systems with more than one address. +.Pp .It Fl C Requests compression of all data (including stdin, stdout, stderr, and -data for forwarded X11 and TCP connections). +data for forwarded X11, TCP and +.Ux Ns -domain +connections). The compression algorithm is the same used by .Xr gzip 1 , and the @@ -146,6 +157,7 @@ The default value can be set on a host-by-host basis in the configuration files; see the .Cm Compression option. +.Pp .It Fl c Ar cipher_spec Selects the cipher specification for encrypting the session. .Pp @@ -155,23 +167,6 @@ The supported values are .Dq blowfish , and .Dq des . -.Ar 3des -(triple-des) is an encrypt-decrypt-encrypt triple with three different keys. -It is believed to be secure. -.Ar blowfish -is a fast block cipher; it appears very secure and is much faster than -.Ar 3des . -.Ar des -is only supported in the -.Nm -client for interoperability with legacy protocol 1 implementations -that do not support the -.Ar 3des -cipher. -Its use is strongly discouraged due to cryptographic weaknesses. -The default is -.Dq 3des . -.Pp For protocol version 2, .Ar cipher_spec is a comma-separated list of ciphers @@ -181,6 +176,7 @@ See the keyword in .Xr ssh_config 5 for more information. +.Pp .It Fl D Xo .Sm off .Oo Ar bind_address : Oc @@ -220,10 +216,12 @@ indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. +.Pp .It Fl E Ar log_file Append debug logs to .Ar log_file instead of standard error. +.Pp .It Fl e Ar escape_char Sets the escape character for sessions with a pty (default: .Ql ~ ) . @@ -236,6 +234,7 @@ and followed by itself sends the escape character once. Setting the character to .Dq none disables any escapes and makes the session fully transparent. +.Pp .It Fl F Ar configfile Specifies an alternative per-user configuration file. If a configuration file is given on the command line, @@ -244,6 +243,7 @@ the system-wide configuration file will be ignored. The default for the per-user configuration file is .Pa ~/.ssh/config . +.Pp .It Fl f Requests .Nm @@ -266,13 +266,27 @@ then a client started with .Fl f will wait for all remote port forwards to be successfully established before placing itself in the background. +.Pp +.It Fl G +Causes +.Nm +to print its configuration after evaluating +.Cm Host +and +.Cm Match +blocks and exit. +.Pp .It Fl g Allows remote hosts to connect to local forwarded ports. +If used on a multiplexed connection, then this option must be specified +on the master process. +.Pp .It Fl I Ar pkcs11 Specify the PKCS#11 shared library .Nm should use to communicate with a PKCS#11 token providing the user's private RSA key. +.Pp .It Fl i Ar identity_file Selects a file from which the identity (private key) for public key authentication is read. @@ -296,33 +310,58 @@ will also try to load certificate information from the filename obtained by appending .Pa -cert.pub to identity filenames. +.Pp .It Fl K Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI credentials to the server. +.Pp .It Fl k Disables forwarding (delegation) of GSSAPI credentials to the server. +.Pp .It Fl L Xo .Sm off .Oo Ar bind_address : Oc .Ar port : host : hostport .Sm on .Xc -Specifies that the given port on the local (client) host is to be -forwarded to the given host and port on the remote side. -This works by allocating a socket to listen to +.It Fl L Xo +.Sm off +.Oo Ar bind_address : Oc +.Ar port : remote_socket +.Sm on +.Xc +.It Fl L Xo +.Sm off +.Ar local_socket : host : hostport +.Sm on +.Xc +.It Fl L Xo +.Sm off +.Ar local_socket : remote_socket +.Sm on +.Xc +Specifies that connections to the given TCP port or Unix socket on the local +(client) host are to be forwarded to the given host and port, or Unix socket, +on the remote side. +This works by allocating a socket to listen to either a TCP .Ar port on the local side, optionally bound to the specified -.Ar bind_address . -Whenever a connection is made to this port, the +.Ar bind_address , +or to a Unix socket. +Whenever a connection is made to the local port or socket, the connection is forwarded over the secure channel, and a connection is -made to +made to either .Ar host port -.Ar hostport +.Ar hostport , +or the Unix socket +.Ar remote_socket , from the remote machine. +.Pp Port forwardings can also be specified in the configuration file. -IPv6 addresses can be specified by enclosing the address in square brackets. Only the superuser can forward privileged ports. +IPv6 addresses can be specified by enclosing the address in square brackets. +.Pp By default, the local port is bound in accordance with the .Cm GatewayPorts setting. @@ -337,9 +376,11 @@ indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. +.Pp .It Fl l Ar login_name Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file. +.Pp .It Fl M Places the .Nm @@ -358,6 +399,7 @@ Refer to the description of in .Xr ssh_config 5 for details. +.Pp .It Fl m Ar mac_spec Additionally, for protocol version 2 a comma-separated list of MAC (message authentication code) algorithms can @@ -365,10 +407,12 @@ be specified in order of preference. See the .Cm MACs keyword for more information. +.Pp .It Fl N Do not execute a remote command. This is useful for just forwarding ports (protocol version 2 only). +.Pp .It Fl n Redirects stdin from .Pa /dev/null @@ -389,6 +433,7 @@ program will be put in the background. needs to ask for a password or passphrase; see also the .Fl f option.) +.Pp .It Fl O Ar ctl_cmd Control an active connection multiplexing master process. When the @@ -407,6 +452,7 @@ Valid commands are: (request the master to exit), and .Dq stop (request the master to stop accepting further multiplexing requests). +.Pp .It Fl o Ar option Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate @@ -438,6 +484,7 @@ For full details of the options listed below, and their possible values, see .It DynamicForward .It EscapeChar .It ExitOnForwardFailure +.It FingerprintHash .It ForwardAgent .It ForwardX11 .It ForwardX11Timeout @@ -449,6 +496,7 @@ For full details of the options listed below, and their possible values, see .It HashKnownHosts .It Host .It HostbasedAuthentication +.It HostbasedKeyTypes .It HostKeyAlgorithms .It HostKeyAlias .It HostName @@ -473,6 +521,7 @@ For full details of the options listed below, and their possible values, see .It Protocol .It ProxyCommand .It ProxyUseFdpass +.It PubkeyAcceptedKeyTypes .It PubkeyAuthentication .It RekeyLimit .It RemoteForward @@ -482,10 +531,13 @@ For full details of the options listed below, and their possible values, see .It SendEnv .It ServerAliveInterval .It ServerAliveCountMax +.It StreamLocalBindMask +.It StreamLocalBindUnlink .It StrictHostKeyChecking .It TCPKeepAlive .It Tunnel .It TunnelDevice +.It UpdateHostKeys .It UsePrivilegedPort .It User .It UserKnownHostsFile @@ -494,11 +546,13 @@ For full details of the options listed below, and their possible values, see .It VisualHostKey .It XAuthLocation .El +.Pp .It Fl p Ar port Port to connect to on the remote host. This can be specified on a per-host basis in the configuration file. -.It Fl Q Cm cipher | cipher-auth | mac | kex | key +.Pp +.It Fl Q Cm cipher | cipher-auth | mac | kex | key | protocol-version Queries .Nm for the algorithms supported for the specified version 2. @@ -512,26 +566,50 @@ The available features are: .Ar kex (key exchange algorithms), .Ar key -(key types). +(key types) and +.Ar protocol-version +(supported SSH protocol versions). +.Pp .It Fl q Quiet mode. Causes most warning and diagnostic messages to be suppressed. +.Pp .It Fl R Xo .Sm off .Oo Ar bind_address : Oc .Ar port : host : hostport .Sm on .Xc -Specifies that the given port on the remote (server) host is to be -forwarded to the given host and port on the local side. -This works by allocating a socket to listen to +.It Fl R Xo +.Sm off +.Oo Ar bind_address : Oc +.Ar port : local_socket +.Sm on +.Xc +.It Fl R Xo +.Sm off +.Ar remote_socket : host : hostport +.Sm on +.Xc +.It Fl R Xo +.Sm off +.Ar remote_socket : local_socket +.Sm on +.Xc +Specifies that connections to the given TCP port or Unix socket on the remote +(server) host are to be forwarded to the given host and port, or Unix socket, +on the local side. +This works by allocating a socket to listen to either a TCP .Ar port -on the remote side, and whenever a connection is made to this port, the -connection is forwarded over the secure channel, and a connection is -made to +or to a Unix socket on the remote side. +Whenever a connection is made to this port or Unix socket, the +connection is forwarded over the secure channel, and a connection +is made to either .Ar host port -.Ar hostport +.Ar hostport , +or +.Ar local_socket , from the local machine. .Pp Port forwardings can also be specified in the configuration file. @@ -539,7 +617,7 @@ Privileged ports can be forwarded only when logging in as root on the remote machine. IPv6 addresses can be specified by enclosing the address in square brackets. .Pp -By default, the listening socket on the server will be bound to the loopback +By default, TCP listening sockets on the server will be bound to the loopback interface only. This may be overridden by specifying a .Ar bind_address . @@ -564,6 +642,7 @@ to the client at run time. When used together with .Ic -O forward the allocated port will be printed to the standard output. +.Pp .It Fl S Ar ctl_path Specifies the location of a control socket for connection sharing, or the string @@ -576,16 +655,19 @@ and in .Xr ssh_config 5 for details. +.Pp .It Fl s May be used to request invocation of a subsystem on the remote system. Subsystems are a feature of the SSH2 protocol which facilitate the use of SSH as a secure transport for other applications (eg.\& .Xr sftp 1 ) . The subsystem is specified as the remote command. +.Pp .It Fl T -Disable pseudo-tty allocation. +Disable pseudo-terminal allocation. +.Pp .It Fl t -Force pseudo-tty allocation. +Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. @@ -594,8 +676,10 @@ Multiple options force tty allocation, even if .Nm has no local tty. +.Pp .It Fl V Display the version number and exit. +.Pp .It Fl v Verbose mode. Causes @@ -607,6 +691,7 @@ Multiple .Fl v options increase the verbosity. The maximum is 3. +.Pp .It Fl W Ar host : Ns Ar port Requests that standard input and output on the client be forwarded to .Ar host @@ -620,6 +705,7 @@ Implies and .Cm ClearAllForwardings . Works with Protocol version 2 only. +.Pp .It Fl w Xo .Ar local_tun Ns Op : Ns Ar remote_tun .Xc @@ -649,6 +735,7 @@ If the .Cm Tunnel directive is unset, it is set to the default tunnel mode, which is .Dq point-to-point . +.Pp .It Fl X Enables X11 forwarding. This can also be specified on a per-host basis in a configuration file. @@ -669,12 +756,15 @@ option and the directive in .Xr ssh_config 5 for more information. +.Pp .It Fl x Disables X11 forwarding. +.Pp .It Fl Y Enables trusted X11 forwarding. Trusted X11 forwardings are not subjected to the X11 SECURITY extension controls. +.Pp .It Fl y Send log information using the .Xr syslog 3 @@ -760,7 +850,7 @@ key pair for authentication purposes. The server knows the public key, and only the user knows the private key. .Nm implements public key authentication protocol automatically, -using one of the DSA, ECDSA, ED25519 or RSA algorithms. +using one of the DSA, ECDSA, Ed25519 or RSA algorithms. Protocol 1 is restricted to using only RSA keys, but protocol 2 may use any. The HISTORY section of @@ -788,7 +878,7 @@ This stores the private key in .Pa ~/.ssh/id_ecdsa (protocol 2 ECDSA), .Pa ~/.ssh/id_ed25519 -(protocol 2 ED25519), +(protocol 2 Ed25519), or .Pa ~/.ssh/id_rsa (protocol 2 RSA) @@ -800,7 +890,7 @@ and stores the public key in .Pa ~/.ssh/id_ecdsa.pub (protocol 2 ECDSA), .Pa ~/.ssh/id_ed25519.pub -(protocol 2 ED25519), +(protocol 2 Ed25519), or .Pa ~/.ssh/id_rsa.pub (protocol 2 RSA) @@ -875,15 +965,26 @@ option can be used to control logins to machines whose host key is not known or has changed. .Pp When the user's identity has been accepted by the server, the server -either executes the given command, or logs into the machine and gives -the user a normal shell on the remote machine. +either executes the given command in a non-interactive session or, +if no command has been specified, logs into the machine and gives +the user a normal shell as an interactive session. All communication with the remote command or shell will be automatically encrypted. .Pp -If a pseudo-terminal has been allocated (normal login session), the +If an interactive session is requested +.Nm +by default will only request a pseudo-terminal (pty) for interactive +sessions when the client has one. +The flags +.Fl T +and +.Fl t +can be used to override this behaviour. +.Pp +If a pseudo-terminal has been allocated the user may use the escape characters noted below. .Pp -If no pseudo-tty has been allocated, +If no pseudo-terminal has been allocated, the session is transparent and can be used to reliably transfer binary data. On most systems, setting the escape character to .Dq none @@ -1094,8 +1195,13 @@ Fingerprints can be determined using .Pp If the fingerprint is already known, it can be matched and the key can be accepted or rejected. +If only legacy (MD5) fingerprints for the server are available, the +.Xr ssh-keygen 1 +.Fl E +option may be used to downgrade the fingerprint algorithm to match. +.Pp Because of the difficulty of comparing host keys -just by looking at hex strings, +just by looking at fingerprint strings, there is also support to compare host keys visually, using .Em random art . @@ -1340,7 +1446,7 @@ secret, but the recommended permissions are read/write/execute for the user, and not accessible by others. .Pp .It Pa ~/.ssh/authorized_keys -Lists the public keys (DSA, ECDSA, ED25519, RSA) +Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used for logging in as this user. The format of this file is described in the .Xr sshd 8 @@ -1467,7 +1573,6 @@ if an error occurred. .Xr ssh-keygen 1 , .Xr ssh-keyscan 1 , .Xr tun 4 , -.Xr hosts.equiv 5 , .Xr ssh_config 5 , .Xr ssh-keysign 8 , .Xr sshd 8 diff --git a/crypto/openssh/ssh.c b/crypto/openssh/ssh.c index eaeb5c7..046dc9d 100644 --- a/crypto/openssh/ssh.c +++ b/crypto/openssh/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.401 2014/02/26 20:18:37 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.420 2015/07/30 00:01:34 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -49,7 +49,6 @@ __RCSID("$FreeBSD$"); #endif #include #include -#include #include #include @@ -68,12 +67,15 @@ __RCSID("$FreeBSD$"); #include #include #include +#include #include #include +#ifdef WITH_OPENSSL #include #include +#endif #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" @@ -84,6 +86,7 @@ __RCSID("$FreeBSD$"); #include "canohost.h" #include "compat.h" #include "cipher.h" +#include "digest.h" #include "packet.h" #include "buffer.h" #include "channels.h" @@ -94,9 +97,9 @@ __RCSID("$FreeBSD$"); #include "dispatch.h" #include "clientloop.h" #include "log.h" +#include "misc.h" #include "readconf.h" #include "sshconnect.h" -#include "misc.h" #include "kex.h" #include "mac.h" #include "sshpty.h" @@ -105,6 +108,8 @@ __RCSID("$FreeBSD$"); #include "uidswap.h" #include "roaming.h" #include "version.h" +#include "ssherr.h" +#include "myproposal.h" #ifdef ENABLE_PKCS11 #include "ssh-pkcs11.h" @@ -197,13 +202,13 @@ static void usage(void) { fprintf(stderr, -"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" +"usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" " [-D [bind_address:]port] [-E log_file] [-e escape_char]\n" " [-F configfile] [-I pkcs11] [-i identity_file]\n" -" [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]\n" +" [-L address] [-l login_name] [-m mac_spec]\n" " [-O ctl_cmd] [-o option] [-p port]\n" " [-Q cipher | cipher-auth | mac | kex | key]\n" -" [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]\n" +" [-R address] [-S ctl_path] [-W host:port]\n" " [-w local_tun[:remote_tun]] [user@]hostname [command]\n" ); exit(255); @@ -274,6 +279,60 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen) } /* + * Attempt to resolve a numeric host address / port to a single address. + * Returns a canonical address string. + * Returns NULL on failure. + * NB. this function must operate with a options having undefined members. + */ +static struct addrinfo * +resolve_addr(const char *name, int port, char *caddr, size_t clen) +{ + char addr[NI_MAXHOST], strport[NI_MAXSERV]; + struct addrinfo hints, *res; + int gaierr; + + if (port <= 0) + port = default_ssh_port(); + snprintf(strport, sizeof strport, "%u", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = options.address_family == -1 ? + AF_UNSPEC : options.address_family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; + if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) { + debug2("%s: could not resolve name %.100s as address: %s", + __func__, name, ssh_gai_strerror(gaierr)); + return NULL; + } + if (res == NULL) { + debug("%s: getaddrinfo %.100s returned no addresses", + __func__, name); + return NULL; + } + if (res->ai_next != NULL) { + debug("%s: getaddrinfo %.100s returned multiple addresses", + __func__, name); + goto fail; + } + if ((gaierr = getnameinfo(res->ai_addr, res->ai_addrlen, + addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) { + debug("%s: Could not format address for name %.100s: %s", + __func__, name, ssh_gai_strerror(gaierr)); + goto fail; + } + if (strlcpy(caddr, addr, clen) >= clen) { + error("%s: host \"%s\" addr \"%s\" too long (max %lu)", + __func__, name, addr, (u_long)clen); + if (clen > 0) + *caddr = '\0'; + fail: + freeaddrinfo(res); + return NULL; + } + return res; +} + +/* * Check whether the cname is a permitted replacement for the hostname * and perform the replacement if it is. * NB. this function must operate with a options having undefined members. @@ -299,10 +358,8 @@ check_follow_cname(char **namep, const char *cname) debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname); for (i = 0; i < options.num_permitted_cnames; i++) { rule = options.permitted_cnames + i; - if (match_pattern_list(*namep, rule->source_list, - strlen(rule->source_list), 1) != 1 || - match_pattern_list(cname, rule->target_list, - strlen(rule->target_list), 1) != 1) + if (match_pattern_list(*namep, rule->source_list, 1) != 1 || + match_pattern_list(cname, rule->target_list, 1) != 1) continue; verbose("Canonicalized DNS aliased hostname " "\"%s\" => \"%s\"", *namep, cname); @@ -323,7 +380,7 @@ static struct addrinfo * resolve_canonicalize(char **hostp, int port) { int i, ndots; - char *cp, *fullhost, cname_target[NI_MAXHOST]; + char *cp, *fullhost, newname[NI_MAXHOST]; struct addrinfo *addrs; if (options.canonicalize_hostname == SSH_CANONICALISE_NO) @@ -337,6 +394,19 @@ resolve_canonicalize(char **hostp, int port) options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) return NULL; + /* Try numeric hostnames first */ + if ((addrs = resolve_addr(*hostp, port, + newname, sizeof(newname))) != NULL) { + debug2("%s: hostname %.100s is address", __func__, *hostp); + if (strcasecmp(*hostp, newname) != 0) { + debug2("%s: canonicalised address \"%s\" => \"%s\"", + __func__, *hostp, newname); + free(*hostp); + *hostp = xstrdup(newname); + } + return addrs; + } + /* Don't apply canonicalization to sufficiently-qualified hostnames */ ndots = 0; for (cp = *hostp; *cp != '\0'; cp++) { @@ -350,20 +420,20 @@ resolve_canonicalize(char **hostp, int port) } /* Attempt each supplied suffix */ for (i = 0; i < options.num_canonical_domains; i++) { - *cname_target = '\0'; + *newname = '\0'; xasprintf(&fullhost, "%s.%s.", *hostp, options.canonical_domains[i]); debug3("%s: attempting \"%s\" => \"%s\"", __func__, *hostp, fullhost); if ((addrs = resolve_host(fullhost, port, 0, - cname_target, sizeof(cname_target))) == NULL) { + newname, sizeof(newname))) == NULL) { free(fullhost); continue; } /* Remove trailing '.' */ fullhost[strlen(fullhost) - 1] = '\0'; /* Follow CNAME if requested */ - if (!check_follow_cname(&fullhost, cname_target)) { + if (!check_follow_cname(&fullhost, newname)) { debug("Canonicalized hostname \"%s\" => \"%s\"", *hostp, fullhost); } @@ -382,27 +452,49 @@ resolve_canonicalize(char **hostp, int port) * file if the user specifies a config file on the command line. */ static void -process_config_files(struct passwd *pw) +process_config_files(const char *host_arg, struct passwd *pw, int post_canon) { - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; int r; if (config != NULL) { if (strcasecmp(config, "none") != 0 && - !read_config_file(config, pw, host, &options, - SSHCONF_USERCONF)) + !read_config_file(config, pw, host, host_arg, &options, + SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0))) fatal("Can't open user config file %.100s: " "%.100s", config, strerror(errno)); } else { r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); if (r > 0 && (size_t)r < sizeof(buf)) - (void)read_config_file(buf, pw, host, &options, - SSHCONF_CHECKPERM|SSHCONF_USERCONF); + (void)read_config_file(buf, pw, host, host_arg, + &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | + (post_canon ? SSHCONF_POSTCANON : 0)); /* Read systemwide configuration file after user config. */ - (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host, - &options, 0); + (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, + host, host_arg, &options, + post_canon ? SSHCONF_POSTCANON : 0); + } +} + +/* Rewrite the port number in an addrinfo list of addresses */ +static void +set_addrinfo_port(struct addrinfo *addrs, int port) +{ + struct addrinfo *addr; + + for (addr = addrs; addr != NULL; addr = addr->ai_next) { + switch (addr->ai_family) { + case AF_INET: + ((struct sockaddr_in *)addr->ai_addr)-> + sin_port = htons(port); + break; + case AF_INET6: + ((struct sockaddr_in6 *)addr->ai_addr)-> + sin6_port = htons(port); + break; + } } } @@ -412,8 +504,8 @@ process_config_files(struct passwd *pw) int main(int ac, char **av) { - int i, r, opt, exit_status, use_syslog; - char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile; + int i, r, opt, exit_status, use_syslog, config_test = 0; + char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile; char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; char cname[NI_MAXHOST]; struct stat st; @@ -421,8 +513,11 @@ main(int ac, char **av) int timeout_ms; extern int optind, optreset; extern char *optarg; - Forward fwd; + struct Forward fwd; struct addrinfo *addrs = NULL; + struct ssh_digest_ctx *md; + u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; + char *conn_hash_hex; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -502,7 +597,7 @@ main(int ac, char **av) again: while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" - "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { + "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { switch (opt) { case '1': options.protocol = SSH_PROTO_1; @@ -535,12 +630,15 @@ main(int ac, char **av) case 'E': logfile = xstrdup(optarg); break; + case 'G': + config_test = 1; + break; case 'Y': options.forward_x11 = 1; options.forward_x11_trusted = 1; break; case 'g': - options.gateway_ports = 1; + options.fwd_opts.gateway_ports = 1; break; case 'O': if (stdio_forward_host != NULL) @@ -580,6 +678,13 @@ main(int ac, char **av) cp = key_alg_list(1, 0); else if (strcmp(optarg, "key-plain") == 0) cp = key_alg_list(0, 1); + else if (strcmp(optarg, "protocol-version") == 0) { +#ifdef WITH_SSH1 + cp = xstrdup("1\n2"); +#else + cp = xstrdup("2"); +#endif + } if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); printf("%s\n", cp); @@ -635,10 +740,10 @@ main(int ac, char **av) *options.version_addendum != '\0') fprintf(stderr, "%s %s, %s\n", SSH_RELEASE, options.version_addendum, - SSLeay_version(SSLEAY_VERSION)); + OPENSSL_VERSION); else fprintf(stderr, "%s, %s\n", SSH_RELEASE, - SSLeay_version(SSLEAY_VERSION)); + OPENSSL_VERSION); if (opt == 'V') exit(0); break; @@ -691,26 +796,26 @@ main(int ac, char **av) } break; case 'c': - if (ciphers_valid(optarg)) { + if (ciphers_valid(*optarg == '+' ? + optarg + 1 : optarg)) { /* SSH2 only */ options.ciphers = xstrdup(optarg); options.cipher = SSH_CIPHER_INVALID; - } else { - /* SSH1 only */ - options.cipher = cipher_number(optarg); - if (options.cipher == -1) { - fprintf(stderr, - "Unknown cipher type '%s'\n", - optarg); - exit(255); - } - if (options.cipher == SSH_CIPHER_3DES) - options.ciphers = "3des-cbc"; - else if (options.cipher == SSH_CIPHER_BLOWFISH) - options.ciphers = "blowfish-cbc"; - else - options.ciphers = (char *)-1; + break; + } + /* SSH1 only */ + options.cipher = cipher_number(optarg); + if (options.cipher == -1) { + fprintf(stderr, "Unknown cipher type '%s'\n", + optarg); + exit(255); } + if (options.cipher == SSH_CIPHER_3DES) + options.ciphers = xstrdup("3des-cbc"); + else if (options.cipher == SSH_CIPHER_BLOWFISH) + options.ciphers = xstrdup("blowfish-cbc"); + else + options.ciphers = xstrdup(KEX_CLIENT_ENCRYPT); break; case 'm': if (mac_valid(optarg)) @@ -783,9 +888,9 @@ main(int ac, char **av) break; case 'o': line = xstrdup(optarg); - if (process_config_line(&options, pw, host ? host : "", - line, "command-line", 0, NULL, SSHCONF_USERCONF) - != 0) + if (process_config_line(&options, pw, + host ? host : "", host ? host : "", line, + "command-line", 0, NULL, SSHCONF_USERCONF) != 0) exit(255); free(line); break; @@ -835,8 +940,10 @@ main(int ac, char **av) host_arg = xstrdup(host); +#ifdef WITH_OPENSSL OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); +#endif /* Initialize the command to execute on remote host. */ buffer_init(&command); @@ -883,10 +990,11 @@ main(int ac, char **av) SYSLOG_FACILITY_USER, !use_syslog); if (debug_flag) - logit("%s, %s", SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); + /* version_addendum is always NULL at this point */ + logit("%s, %s", SSH_RELEASE, OPENSSL_VERSION); /* Parse the configuration files */ - process_config_files(pw); + process_config_files(host_arg, pw, 0); /* Hostname canonicalisation needs a few options filled. */ fill_default_options_for_canonicalization(&options); @@ -898,6 +1006,8 @@ main(int ac, char **av) "h", host, (char *)NULL); free(host); host = cp; + free(options.hostname); + options.hostname = xstrdup(host); } /* If canonicalization requested then try to apply it */ @@ -921,19 +1031,33 @@ main(int ac, char **av) if (addrs == NULL && options.num_permitted_cnames != 0 && (option_clear_or_none(options.proxy_command) || options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { - if ((addrs = resolve_host(host, options.port, 1, - cname, sizeof(cname))) == NULL) - cleanup_exit(255); /* resolve_host logs the error */ - check_follow_cname(&host, cname); + if ((addrs = resolve_host(host, options.port, + option_clear_or_none(options.proxy_command), + cname, sizeof(cname))) == NULL) { + /* Don't fatal proxied host names not in the DNS */ + if (option_clear_or_none(options.proxy_command)) + cleanup_exit(255); /* logged in resolve_host */ + } else + check_follow_cname(&host, cname); } /* - * If the target hostname has changed as a result of canonicalisation - * then re-parse the configuration files as new stanzas may match. + * If canonicalisation is enabled then re-parse the configuration + * files as new stanzas may match. */ - if (strcasecmp(host_arg, host) != 0) { - debug("Hostname has changed; re-reading configuration"); - process_config_files(pw); + if (options.canonicalize_hostname != 0) { + debug("Re-reading configuration after hostname " + "canonicalisation"); + free(options.hostname); + options.hostname = xstrdup(host); + process_config_files(host_arg, pw, 1); + /* + * Address resolution happens early with canonicalisation + * enabled and the port number may have changed since, so + * reset it in address list + */ + if (addrs != NULL && options.port > 0) + set_addrinfo_port(addrs, options.port); } /* Fill configuration defaults. */ @@ -950,6 +1074,12 @@ main(int ac, char **av) strcmp(options.proxy_command, "-") == 0 && options.proxy_use_fdpass) fatal("ProxyCommand=- and ProxyUseFDPass are incompatible"); + if (options.control_persist && + options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { + debug("UpdateHostKeys=ask is incompatible with ControlPersist; " + "disabling"); + options.update_hostkeys = 0; + } #ifndef HAVE_CYGWIN if (original_effective_uid != 0) options.use_privileged_port = 0; @@ -1006,12 +1136,29 @@ main(int ac, char **av) } } + if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || + ssh_digest_update(md, thishost, strlen(thishost)) < 0 || + ssh_digest_update(md, host, strlen(host)) < 0 || + ssh_digest_update(md, portstr, strlen(portstr)) < 0 || + ssh_digest_update(md, options.user, strlen(options.user)) < 0 || + ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) + fatal("%s: mux digest failed", __func__); + ssh_digest_free(md); + conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); + if (options.local_command != NULL) { debug3("expanding LocalCommand: %s", options.local_command); cp = options.local_command; - options.local_command = percent_expand(cp, "d", pw->pw_dir, - "h", host, "l", thishost, "n", host_arg, "r", options.user, - "p", portstr, "u", pw->pw_name, "L", shorthost, + options.local_command = percent_expand(cp, + "C", conn_hash_hex, + "L", shorthost, + "d", pw->pw_dir, + "h", host, + "l", thishost, + "n", host_arg, + "p", portstr, + "r", options.user, + "u", pw->pw_name, (char *)NULL); debug3("expanded LocalCommand: %s", options.local_command); free(cp); @@ -1021,12 +1168,25 @@ main(int ac, char **av) cp = tilde_expand_filename(options.control_path, original_real_uid); free(options.control_path); - options.control_path = percent_expand(cp, "h", host, - "l", thishost, "n", host_arg, "r", options.user, - "p", portstr, "u", pw->pw_name, "L", shorthost, + options.control_path = percent_expand(cp, + "C", conn_hash_hex, + "L", shorthost, + "h", host, + "l", thishost, + "n", host_arg, + "p", portstr, + "r", options.user, + "u", pw->pw_name, (char *)NULL); free(cp); } + free(conn_hash_hex); + + if (config_test) { + dump_client_config(&options, host); + exit(0); + } + if (muxclient_command != 0 && options.control_path == NULL) fatal("No ControlPath specified for \"-O\" command"); if (options.control_path != NULL) @@ -1082,26 +1242,26 @@ main(int ac, char **av) PRIV_START; sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, _PATH_HOST_KEY_FILE, "", NULL, NULL); - sensitive_data.keys[1] = key_load_private_cert(KEY_DSA, - _PATH_HOST_DSA_KEY_FILE, "", NULL); #ifdef OPENSSL_HAS_ECC - sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA, + sensitive_data.keys[1] = key_load_private_cert(KEY_ECDSA, _PATH_HOST_ECDSA_KEY_FILE, "", NULL); #endif + sensitive_data.keys[2] = key_load_private_cert(KEY_ED25519, + _PATH_HOST_ED25519_KEY_FILE, "", NULL); sensitive_data.keys[3] = key_load_private_cert(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL); - sensitive_data.keys[4] = key_load_private_cert(KEY_ED25519, - _PATH_HOST_ED25519_KEY_FILE, "", NULL); - sensitive_data.keys[5] = key_load_private_type(KEY_DSA, - _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); + sensitive_data.keys[4] = key_load_private_cert(KEY_DSA, + _PATH_HOST_DSA_KEY_FILE, "", NULL); #ifdef OPENSSL_HAS_ECC - sensitive_data.keys[6] = key_load_private_type(KEY_ECDSA, + sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA, _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL); #endif + sensitive_data.keys[6] = key_load_private_type(KEY_ED25519, + _PATH_HOST_ED25519_KEY_FILE, "", NULL, NULL); sensitive_data.keys[7] = key_load_private_type(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); - sensitive_data.keys[8] = key_load_private_type(KEY_ED25519, - _PATH_HOST_ED25519_KEY_FILE, "", NULL, NULL); + sensitive_data.keys[8] = key_load_private_type(KEY_DSA, + _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); PRIV_END; if (options.hostbased_authentication == 1 && @@ -1110,26 +1270,26 @@ main(int ac, char **av) sensitive_data.keys[6] == NULL && sensitive_data.keys[7] == NULL && sensitive_data.keys[8] == NULL) { - sensitive_data.keys[1] = key_load_cert( - _PATH_HOST_DSA_KEY_FILE); #ifdef OPENSSL_HAS_ECC - sensitive_data.keys[2] = key_load_cert( + sensitive_data.keys[1] = key_load_cert( _PATH_HOST_ECDSA_KEY_FILE); #endif + sensitive_data.keys[2] = key_load_cert( + _PATH_HOST_ED25519_KEY_FILE); sensitive_data.keys[3] = key_load_cert( _PATH_HOST_RSA_KEY_FILE); sensitive_data.keys[4] = key_load_cert( - _PATH_HOST_ED25519_KEY_FILE); - sensitive_data.keys[5] = key_load_public( - _PATH_HOST_DSA_KEY_FILE, NULL); + _PATH_HOST_DSA_KEY_FILE); #ifdef OPENSSL_HAS_ECC - sensitive_data.keys[6] = key_load_public( + sensitive_data.keys[5] = key_load_public( _PATH_HOST_ECDSA_KEY_FILE, NULL); #endif + sensitive_data.keys[6] = key_load_public( + _PATH_HOST_ED25519_KEY_FILE, NULL); sensitive_data.keys[7] = key_load_public( _PATH_HOST_RSA_KEY_FILE, NULL); sensitive_data.keys[8] = key_load_public( - _PATH_HOST_ED25519_KEY_FILE, NULL); + _PATH_HOST_DSA_KEY_FILE, NULL); sensitive_data.external_keysign = 1; } } @@ -1280,13 +1440,17 @@ fork_postauth(void) static void ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) { - Forward *rfwd = (Forward *)ctxt; + struct Forward *rfwd = (struct Forward *)ctxt; /* XXX verbose() on failure? */ - debug("remote forward %s for: listen %d, connect %s:%d", + debug("remote forward %s for: listen %s%s%d, connect %s:%d", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", - rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); - if (rfwd->listen_port == 0) { + rfwd->listen_path ? rfwd->listen_path : + rfwd->listen_host ? rfwd->listen_host : "", + (rfwd->listen_path || rfwd->listen_host) ? ":" : "", + rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : + rfwd->connect_host, rfwd->connect_port); + if (rfwd->listen_path == NULL && rfwd->listen_port == 0) { if (type == SSH2_MSG_REQUEST_SUCCESS) { rfwd->allocated_port = packet_get_int(); logit("Allocated port %u for remote forward to %s:%d", @@ -1300,12 +1464,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) } if (type == SSH2_MSG_REQUEST_FAILURE) { - if (options.exit_on_forward_failure) - fatal("Error: remote port forwarding failed for " - "listen port %d", rfwd->listen_port); - else - logit("Warning: remote port forwarding failed for " - "listen port %d", rfwd->listen_port); + if (options.exit_on_forward_failure) { + if (rfwd->listen_path != NULL) + fatal("Error: remote port forwarding failed " + "for listen path %s", rfwd->listen_path); + else + fatal("Error: remote port forwarding failed " + "for listen port %d", rfwd->listen_port); + } else { + if (rfwd->listen_path != NULL) + logit("Warning: remote port forwarding failed " + "for listen path %s", rfwd->listen_path); + else + logit("Warning: remote port forwarding failed " + "for listen port %d", rfwd->listen_port); + } } if (++remote_forward_confirms_received == options.num_remote_forwards) { debug("All remote forwarding requests processed"); @@ -1322,6 +1495,13 @@ client_cleanup_stdio_fwd(int id, void *arg) } static void +ssh_stdio_confirm(int id, int success, void *arg) +{ + if (!success) + fatal("stdio forwarding failed"); +} + +static void ssh_init_stdio_forwarding(void) { Channel *c; @@ -1341,6 +1521,7 @@ ssh_init_stdio_forwarding(void) stdio_forward_port, in, out)) == NULL) fatal("%s: channel_connect_stdio_fwd failed", __func__); channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); + channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL); } static void @@ -1353,18 +1534,18 @@ ssh_init_forwarding(void) for (i = 0; i < options.num_local_forwards; i++) { debug("Local connections to %.200s:%d forwarded to remote " "address %.200s:%d", + (options.local_forwards[i].listen_path != NULL) ? + options.local_forwards[i].listen_path : (options.local_forwards[i].listen_host == NULL) ? - (options.gateway_ports ? "*" : "LOCALHOST") : + (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : options.local_forwards[i].listen_host, options.local_forwards[i].listen_port, + (options.local_forwards[i].connect_path != NULL) ? + options.local_forwards[i].connect_path : options.local_forwards[i].connect_host, options.local_forwards[i].connect_port); success += channel_setup_local_fwd_listener( - options.local_forwards[i].listen_host, - options.local_forwards[i].listen_port, - options.local_forwards[i].connect_host, - options.local_forwards[i].connect_port, - options.gateway_ports); + &options.local_forwards[i], &options.fwd_opts); } if (i > 0 && success != i && options.exit_on_forward_failure) fatal("Could not request local forwarding."); @@ -1375,17 +1556,18 @@ ssh_init_forwarding(void) for (i = 0; i < options.num_remote_forwards; i++) { debug("Remote connections from %.200s:%d forwarded to " "local address %.200s:%d", + (options.remote_forwards[i].listen_path != NULL) ? + options.remote_forwards[i].listen_path : (options.remote_forwards[i].listen_host == NULL) ? "LOCALHOST" : options.remote_forwards[i].listen_host, options.remote_forwards[i].listen_port, + (options.remote_forwards[i].connect_path != NULL) ? + options.remote_forwards[i].connect_path : options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_port); options.remote_forwards[i].handle = channel_request_remote_forwarding( - options.remote_forwards[i].listen_host, - options.remote_forwards[i].listen_port, - options.remote_forwards[i].connect_host, - options.remote_forwards[i].connect_port); + &options.remote_forwards[i]); if (options.remote_forwards[i].handle < 0) { if (options.exit_on_forward_failure) fatal("Could not request remote forwarding."); @@ -1413,10 +1595,16 @@ ssh_init_forwarding(void) static void check_agent_present(void) { + int r; + if (options.forward_agent) { /* Clear agent forwarding if we don't have an agent. */ - if (!ssh_agent_present()) + if ((r = ssh_get_authentication_socket(NULL)) != 0) { options.forward_agent = 0; + if (r != SSH_ERR_AGENT_NOT_PRESENT) + debug("ssh_get_authentication_socket: %s", + ssh_err(r)); + } } } @@ -1497,6 +1685,8 @@ ssh_session(void) } /* Request X11 forwarding if enabled and DISPLAY is set. */ display = getenv("DISPLAY"); + if (display == NULL && options.forward_x11) + debug("X11 forwarding requested but DISPLAY not set"); if (options.forward_x11 && display != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ @@ -1598,6 +1788,8 @@ ssh_session2_setup(int id, int success, void *arg) return; /* No need for error message, channels code sens one */ display = getenv("DISPLAY"); + if (display == NULL && options.forward_x11) + debug("X11 forwarding requested but DISPLAY not set"); if (options.forward_x11 && display != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ @@ -1753,9 +1945,6 @@ ssh_session2(void) fork_postauth(); } - if (options.use_roaming) - request_roaming(); - return client_loop(tty_flag, tty_flag ? options.escape_char : SSH_ESCAPECHAR_NONE, id); } diff --git a/crypto/openssh/ssh.h b/crypto/openssh/ssh.h index c94633b..39c7e18 100644 --- a/crypto/openssh/ssh.h +++ b/crypto/openssh/ssh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.h,v 1.79 2010/06/25 07:14:46 djm Exp $ */ +/* $OpenBSD: ssh.h,v 1.81 2015/08/04 05:23:06 djm Exp $ */ /* * Author: Tatu Ylonen diff --git a/crypto/openssh/ssh_api.c b/crypto/openssh/ssh_api.c new file mode 100644 index 0000000..6c71258 --- /dev/null +++ b/crypto/openssh/ssh_api.c @@ -0,0 +1,537 @@ +/* $OpenBSD: ssh_api.c,v 1.4 2015/02/16 22:13:32 djm Exp $ */ +/* + * Copyright (c) 2012 Markus Friedl. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include "ssh1.h" /* For SSH_MSG_NONE */ +#include "ssh_api.h" +#include "compat.h" +#include "log.h" +#include "authfile.h" +#include "sshkey.h" +#include "misc.h" +#include "ssh1.h" +#include "ssh2.h" +#include "version.h" +#include "myproposal.h" +#include "ssherr.h" +#include "sshbuf.h" + +#include + +int _ssh_exchange_banner(struct ssh *); +int _ssh_send_banner(struct ssh *, char **); +int _ssh_read_banner(struct ssh *, char **); +int _ssh_order_hostkeyalgs(struct ssh *); +int _ssh_verify_host_key(struct sshkey *, struct ssh *); +struct sshkey *_ssh_host_public_key(int, int, struct ssh *); +struct sshkey *_ssh_host_private_key(int, int, struct ssh *); +int _ssh_host_key_sign(struct sshkey *, struct sshkey *, u_char **, + size_t *, const u_char *, size_t, u_int); + +/* + * stubs for the server side implementation of kex. + * disable privsep so our stubs will never be called. + */ +int use_privsep = 0; +int mm_sshkey_sign(struct sshkey *, u_char **, u_int *, + u_char *, u_int, u_int); +DH *mm_choose_dh(int, int, int); + +/* Define these two variables here so that they are part of the library */ +u_char *session_id2 = NULL; +u_int session_id2_len = 0; + +int +mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen, u_int compat) +{ + return (-1); +} + +DH * +mm_choose_dh(int min, int nbits, int max) +{ + return (NULL); +} + +/* API */ + +int +ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) +{ + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + struct ssh *ssh; + char **proposal; + static int called; + int r; + + if (!called) { +#ifdef WITH_OPENSSL + OpenSSL_add_all_algorithms(); +#endif /* WITH_OPENSSL */ + called = 1; + } + + if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (is_server) + ssh_packet_set_server(ssh); + + /* Initialize key exchange */ + proposal = kex_params ? kex_params->proposal : myproposal; + if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) { + ssh_free(ssh); + return r; + } + ssh->kex->server = is_server; + if (is_server) { +#ifdef WITH_OPENSSL + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; + ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; +# ifdef OPENSSL_HAS_ECC + ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; +# endif +#endif /* WITH_OPENSSL */ + ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server; + ssh->kex->load_host_public_key=&_ssh_host_public_key; + ssh->kex->load_host_private_key=&_ssh_host_private_key; + ssh->kex->sign=&_ssh_host_key_sign; + } else { +#ifdef WITH_OPENSSL + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; + ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; +# ifdef OPENSSL_HAS_ECC + ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; +# endif +#endif /* WITH_OPENSSL */ + ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->verify_host_key =&_ssh_verify_host_key; + } + *sshp = ssh; + return 0; +} + +void +ssh_free(struct ssh *ssh) +{ + struct key_entry *k; + + ssh_packet_close(ssh); + /* + * we've only created the public keys variants in case we + * are a acting as a server. + */ + while ((k = TAILQ_FIRST(&ssh->public_keys)) != NULL) { + TAILQ_REMOVE(&ssh->public_keys, k, next); + if (ssh->kex && ssh->kex->server) + sshkey_free(k->key); + free(k); + } + while ((k = TAILQ_FIRST(&ssh->private_keys)) != NULL) { + TAILQ_REMOVE(&ssh->private_keys, k, next); + free(k); + } + if (ssh->kex) + kex_free(ssh->kex); + free(ssh); +} + +void +ssh_set_app_data(struct ssh *ssh, void *app_data) +{ + ssh->app_data = app_data; +} + +void * +ssh_get_app_data(struct ssh *ssh) +{ + return ssh->app_data; +} + +/* Returns < 0 on error, 0 otherwise */ +int +ssh_add_hostkey(struct ssh *ssh, struct sshkey *key) +{ + struct sshkey *pubkey = NULL; + struct key_entry *k = NULL, *k_prv = NULL; + int r; + + if (ssh->kex->server) { + if ((r = sshkey_from_private(key, &pubkey)) != 0) + return r; + if ((k = malloc(sizeof(*k))) == NULL || + (k_prv = malloc(sizeof(*k_prv))) == NULL) { + free(k); + sshkey_free(pubkey); + return SSH_ERR_ALLOC_FAIL; + } + k_prv->key = key; + TAILQ_INSERT_TAIL(&ssh->private_keys, k_prv, next); + + /* add the public key, too */ + k->key = pubkey; + TAILQ_INSERT_TAIL(&ssh->public_keys, k, next); + r = 0; + } else { + if ((k = malloc(sizeof(*k))) == NULL) + return SSH_ERR_ALLOC_FAIL; + k->key = key; + TAILQ_INSERT_TAIL(&ssh->public_keys, k, next); + r = 0; + } + + return r; +} + +int +ssh_set_verify_host_key_callback(struct ssh *ssh, + int (*cb)(struct sshkey *, struct ssh *)) +{ + if (cb == NULL || ssh->kex == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + ssh->kex->verify_host_key = cb; + + return 0; +} + +int +ssh_input_append(struct ssh *ssh, const u_char *data, size_t len) +{ + return sshbuf_put(ssh_packet_get_input(ssh), data, len); +} + +int +ssh_packet_next(struct ssh *ssh, u_char *typep) +{ + int r; + u_int32_t seqnr; + u_char type; + + /* + * Try to read a packet. Return SSH_MSG_NONE if no packet or not + * enough data. + */ + *typep = SSH_MSG_NONE; + if (ssh->kex->client_version_string == NULL || + ssh->kex->server_version_string == NULL) + return _ssh_exchange_banner(ssh); + /* + * If we enough data and a dispatch function then + * call the function and get the next packet. + * Otherwise return the packet type to the caller so it + * can decide how to go on. + * + * We will only call the dispatch function for: + * 20-29 Algorithm negotiation + * 30-49 Key exchange method specific (numbers can be reused for + * different authentication methods) + */ + for (;;) { + if ((r = ssh_packet_read_poll2(ssh, &type, &seqnr)) != 0) + return r; + if (type > 0 && type < DISPATCH_MAX && + type >= SSH2_MSG_KEXINIT && type <= SSH2_MSG_TRANSPORT_MAX && + ssh->dispatch[type] != NULL) { + if ((r = (*ssh->dispatch[type])(type, seqnr, ssh)) != 0) + return r; + } else { + *typep = type; + return 0; + } + } +} + +const u_char * +ssh_packet_payload(struct ssh *ssh, size_t *lenp) +{ + return sshpkt_ptr(ssh, lenp); +} + +int +ssh_packet_put(struct ssh *ssh, int type, const u_char *data, size_t len) +{ + int r; + + if ((r = sshpkt_start(ssh, type)) != 0 || + (r = sshpkt_put(ssh, data, len)) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; + return 0; +} + +const u_char * +ssh_output_ptr(struct ssh *ssh, size_t *len) +{ + struct sshbuf *output = ssh_packet_get_output(ssh); + + *len = sshbuf_len(output); + return sshbuf_ptr(output); +} + +int +ssh_output_consume(struct ssh *ssh, size_t len) +{ + return sshbuf_consume(ssh_packet_get_output(ssh), len); +} + +int +ssh_output_space(struct ssh *ssh, size_t len) +{ + return (0 == sshbuf_check_reserve(ssh_packet_get_output(ssh), len)); +} + +int +ssh_input_space(struct ssh *ssh, size_t len) +{ + return (0 == sshbuf_check_reserve(ssh_packet_get_input(ssh), len)); +} + +/* Read other side's version identification. */ +int +_ssh_read_banner(struct ssh *ssh, char **bannerp) +{ + struct sshbuf *input; + const char *s; + char buf[256], remote_version[256]; /* must be same size! */ + const char *mismatch = "Protocol mismatch.\r\n"; + int r, remote_major, remote_minor; + size_t i, n, j, len; + + *bannerp = NULL; + input = ssh_packet_get_input(ssh); + len = sshbuf_len(input); + s = (const char *)sshbuf_ptr(input); + for (j = n = 0;;) { + for (i = 0; i < sizeof(buf) - 1; i++) { + if (j >= len) + return (0); + buf[i] = s[j++]; + if (buf[i] == '\r') { + buf[i] = '\n'; + buf[i + 1] = 0; + continue; /**XXX wait for \n */ + } + if (buf[i] == '\n') { + buf[i + 1] = 0; + break; + } + } + buf[sizeof(buf) - 1] = 0; + if (strncmp(buf, "SSH-", 4) == 0) + break; + debug("ssh_exchange_identification: %s", buf); + if (ssh->kex->server || ++n > 65536) { + if ((r = sshbuf_put(ssh_packet_get_output(ssh), + mismatch, strlen(mismatch))) != 0) + return r; + return SSH_ERR_NO_PROTOCOL_VERSION; + } + } + if ((r = sshbuf_consume(input, j)) != 0) + return r; + + /* + * Check that the versions match. In future this might accept + * several versions and set appropriate flags to handle them. + */ + if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", + &remote_major, &remote_minor, remote_version) != 3) + return SSH_ERR_INVALID_FORMAT; + debug("Remote protocol version %d.%d, remote software version %.100s", + remote_major, remote_minor, remote_version); + + ssh->compat = compat_datafellows(remote_version); + if (remote_major == 1 && remote_minor == 99) { + remote_major = 2; + remote_minor = 0; + } + if (remote_major != 2) + return SSH_ERR_PROTOCOL_MISMATCH; + enable_compat20(); + chop(buf); + debug("Remote version string %.100s", buf); + if ((*bannerp = strdup(buf)) == NULL) + return SSH_ERR_ALLOC_FAIL; + return 0; +} + +/* Send our own protocol version identification. */ +int +_ssh_send_banner(struct ssh *ssh, char **bannerp) +{ + char buf[256]; + int r; + + snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION); + if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0) + return r; + chop(buf); + debug("Local version string %.100s", buf); + if ((*bannerp = strdup(buf)) == NULL) + return SSH_ERR_ALLOC_FAIL; + return 0; +} + +int +_ssh_exchange_banner(struct ssh *ssh) +{ + struct kex *kex = ssh->kex; + int r; + + /* + * if _ssh_read_banner() cannot parse a full version string + * it will return NULL and we end up calling it again. + */ + + r = 0; + if (kex->server) { + if (kex->server_version_string == NULL) + r = _ssh_send_banner(ssh, &kex->server_version_string); + if (r == 0 && + kex->server_version_string != NULL && + kex->client_version_string == NULL) + r = _ssh_read_banner(ssh, &kex->client_version_string); + } else { + if (kex->server_version_string == NULL) + r = _ssh_read_banner(ssh, &kex->server_version_string); + if (r == 0 && + kex->server_version_string != NULL && + kex->client_version_string == NULL) + r = _ssh_send_banner(ssh, &kex->client_version_string); + } + if (r != 0) + return r; + /* start initial kex as soon as we have exchanged the banners */ + if (kex->server_version_string != NULL && + kex->client_version_string != NULL) { + if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 || + (r = kex_send_kexinit(ssh)) != 0) + return r; + } + return 0; +} + +struct sshkey * +_ssh_host_public_key(int type, int nid, struct ssh *ssh) +{ + struct key_entry *k; + + debug3("%s: need %d", __func__, type); + TAILQ_FOREACH(k, &ssh->public_keys, next) { + debug3("%s: check %s", __func__, sshkey_type(k->key)); + if (k->key->type == type && + (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) + return (k->key); + } + return (NULL); +} + +struct sshkey * +_ssh_host_private_key(int type, int nid, struct ssh *ssh) +{ + struct key_entry *k; + + debug3("%s: need %d", __func__, type); + TAILQ_FOREACH(k, &ssh->private_keys, next) { + debug3("%s: check %s", __func__, sshkey_type(k->key)); + if (k->key->type == type && + (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) + return (k->key); + } + return (NULL); +} + +int +_ssh_verify_host_key(struct sshkey *hostkey, struct ssh *ssh) +{ + struct key_entry *k; + + debug3("%s: need %s", __func__, sshkey_type(hostkey)); + TAILQ_FOREACH(k, &ssh->public_keys, next) { + debug3("%s: check %s", __func__, sshkey_type(k->key)); + if (sshkey_equal_public(hostkey, k->key)) + return (0); /* ok */ + } + return (-1); /* failed */ +} + +/* offer hostkey algorithms in kexinit depending on registered keys */ +int +_ssh_order_hostkeyalgs(struct ssh *ssh) +{ + struct key_entry *k; + char *orig, *avail, *oavail = NULL, *alg, *replace = NULL; + char **proposal; + size_t maxlen; + int ktype, r; + + /* XXX we de-serialize ssh->kex->my, modify it, and change it */ + if ((r = kex_buf2prop(ssh->kex->my, NULL, &proposal)) != 0) + return r; + orig = proposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; + if ((oavail = avail = strdup(orig)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + maxlen = strlen(avail) + 1; + if ((replace = calloc(1, maxlen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + *replace = '\0'; + while ((alg = strsep(&avail, ",")) && *alg != '\0') { + if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) + continue; + TAILQ_FOREACH(k, &ssh->public_keys, next) { + if (k->key->type == ktype || + (sshkey_is_cert(k->key) && k->key->type == + sshkey_type_plain(ktype))) { + if (*replace != '\0') + strlcat(replace, ",", maxlen); + strlcat(replace, alg, maxlen); + break; + } + } + } + if (*replace != '\0') { + debug2("%s: orig/%d %s", __func__, ssh->kex->server, orig); + debug2("%s: replace/%d %s", __func__, ssh->kex->server, replace); + free(orig); + proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = replace; + replace = NULL; /* owned by proposal */ + r = kex_prop2buf(ssh->kex->my, proposal); + } + out: + free(oavail); + free(replace); + kex_prop_free(proposal); + return r; +} + +int +_ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey, + u_char **signature, size_t *slen, + const u_char *data, size_t dlen, u_int compat) +{ + return sshkey_sign(privkey, signature, slen, data, dlen, compat); +} diff --git a/crypto/openssh/ssh_api.h b/crypto/openssh/ssh_api.h new file mode 100644 index 0000000..642acd5 --- /dev/null +++ b/crypto/openssh/ssh_api.h @@ -0,0 +1,137 @@ +/* $OpenBSD: ssh_api.h,v 1.1 2015/01/19 20:30:23 markus Exp $ */ +/* + * Copyright (c) 2012 Markus Friedl. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef API_H +#define API_H + +#include +#include + +#include "openbsd-compat/sys-queue.h" + +#include "cipher.h" +#include "sshkey.h" +#include "kex.h" +#include "ssh.h" +#include "ssh2.h" +#include "packet.h" + +struct kex_params { + char *proposal[PROPOSAL_MAX]; +}; + +/* public SSH API functions */ + +/* + * ssh_init() create a ssh connection object with given (optional) + * key exchange parameters. + */ +int ssh_init(struct ssh **, int is_server, struct kex_params *kex_params); + +/* + * release ssh connection state. + */ +void ssh_free(struct ssh *); + +/* + * attach application specific data to the connection state + */ +void ssh_set_app_data(struct ssh *, void *); +void *ssh_get_app_data(struct ssh *); + +/* + * ssh_add_hostkey() registers a private/public hostkey for an ssh + * connection. + * ssh_add_hostkey() needs to be called before a key exchange is + * initiated with ssh_packet_next(). + * private hostkeys are required if we need to act as a server. + * public hostkeys are used to verify the servers hostkey. + */ +int ssh_add_hostkey(struct ssh *ssh, struct sshkey *key); + +/* + * ssh_set_verify_host_key_callback() registers a callback function + * which should be called instead of the default verification. The + * function given must return 0 if the hostkey is ok, -1 if the + * verification has failed. + */ +int ssh_set_verify_host_key_callback(struct ssh *ssh, + int (*cb)(struct sshkey *, struct ssh *)); + +/* + * ssh_packet_next() advances to the next input packet and returns + * the packet type in typep. + * ssh_packet_next() works by processing an input byte-stream, + * decrypting the received data and hiding the key-exchange from + * the caller. + * ssh_packet_next() sets typep if there is no new packet available. + * in this case the caller must fill the input byte-stream by passing + * the data received over network to ssh_input_append(). + * additinally, the caller needs to send the resulting output + * byte-stream back over the network. otherwise the key exchange + * would not proceed. the output byte-stream is accessed through + * ssh_output_ptr(). + */ +int ssh_packet_next(struct ssh *ssh, u_char *typep); + +/* + * ssh_packet_payload() returns a pointer to the raw payload data of + * the current input packet and the length of this payload. + * the payload is accessible until ssh_packet_next() is called again. + */ +const u_char *ssh_packet_payload(struct ssh *ssh, size_t *lenp); + +/* + * ssh_packet_put() creates an encrypted packet with the given type + * and payload. + * the encrypted packet is appended to the output byte-stream. + */ +int ssh_packet_put(struct ssh *ssh, int type, const u_char *data, + size_t len); + +/* + * ssh_input_space() checks if 'len' bytes can be appended to the + * input byte-stream. + */ +int ssh_input_space(struct ssh *ssh, size_t len); + +/* + * ssh_input_append() appends data to the input byte-stream. + */ +int ssh_input_append(struct ssh *ssh, const u_char *data, size_t len); + +/* + * ssh_output_space() checks if 'len' bytes can be appended to the + * output byte-stream. XXX + */ +int ssh_output_space(struct ssh *ssh, size_t len); + +/* + * ssh_output_ptr() retrieves both a pointer and the length of the + * current output byte-stream. the bytes need to be sent over the + * network. the number of bytes that have been successfully sent can + * be removed from the output byte-stream with ssh_output_consume(). + */ +const u_char *ssh_output_ptr(struct ssh *ssh, size_t *len); + +/* + * ssh_output_consume() removes the given number of bytes from + * the output byte-stream. + */ +int ssh_output_consume(struct ssh *ssh, size_t len); + +#endif diff --git a/crypto/openssh/ssh_config b/crypto/openssh/ssh_config index 459f4ef..4700407 100644 --- a/crypto/openssh/ssh_config +++ b/crypto/openssh/ssh_config @@ -48,4 +48,4 @@ # ProxyCommand ssh -q -W %h:%p gateway.example.com # RekeyLimit 1G 1h # VerifyHostKeyDNS yes -# VersionAddendum FreeBSD-20160124 +# VersionAddendum FreeBSD-20160125 diff --git a/crypto/openssh/ssh_config.0 b/crypto/openssh/ssh_config.0 deleted file mode 100644 index 6fbd10d..0000000 --- a/crypto/openssh/ssh_config.0 +++ /dev/null @@ -1,889 +0,0 @@ -SSH_CONFIG(5) OpenBSD Programmer's Manual SSH_CONFIG(5) - -NAME - ssh_config - OpenSSH SSH client configuration files - -SYNOPSIS - ~/.ssh/config - /etc/ssh/ssh_config - -DESCRIPTION - ssh(1) obtains configuration data from the following sources in the - following order: - - 1. command-line options - 2. user's configuration file (~/.ssh/config) - 3. system-wide configuration file (/etc/ssh/ssh_config) - - For each parameter, the first obtained value will be used. The - configuration files contain sections separated by ``Host'' - specifications, and that section is only applied for hosts that match one - of the patterns given in the specification. The matched host name is the - one given on the command line. - - Since the first obtained value for each parameter is used, more host- - specific declarations should be given near the beginning of the file, and - general defaults at the end. - - The configuration file has the following format: - - Empty lines and lines starting with `#' are comments. Otherwise a line - is of the format ``keyword arguments''. Configuration options may be - separated by whitespace or optional whitespace and exactly one `='; the - latter format is useful to avoid the need to quote whitespace when - specifying configuration options using the ssh, scp, and sftp -o option. - Arguments may optionally be enclosed in double quotes (") in order to - represent arguments containing spaces. - - The possible keywords and their meanings are as follows (note that - keywords are case-insensitive and arguments are case-sensitive): - - Host Restricts the following declarations (up to the next Host or - Match keyword) to be only for those hosts that match one of the - patterns given after the keyword. If more than one pattern is - provided, they should be separated by whitespace. A single `*' - as a pattern can be used to provide global defaults for all - hosts. The host is the hostname argument given on the command - line (i.e. the name is not converted to a canonicalized host name - before matching). - - A pattern entry may be negated by prefixing it with an - exclamation mark (`!'). If a negated entry is matched, then the - Host entry is ignored, regardless of whether any other patterns - on the line match. Negated matches are therefore useful to - provide exceptions for wildcard matches. - - See PATTERNS for more information on patterns. - - Match Restricts the following declarations (up to the next Host or - Match keyword) to be used only when the conditions following the - Match keyword are satisfied. Match conditions are specified - using one or more keyword/criteria pairs or the single token all - which matches all criteria. The available keywords are: exec, - host, originalhost, user, and localuser. - - The exec keyword executes the specified command under the user's - shell. If the command returns a zero exit status then the - condition is considered true. Commands containing whitespace - characters must be quoted. The following character sequences in - the command will be expanded prior to execution: `%L' will be - substituted by the first component of the local host name, `%l' - will be substituted by the local host name (including any domain - name), `%h' will be substituted by the target host name, `%n' - will be substituted by the original target host name specified on - the command-line, `%p' the destination port, `%r' by the remote - login username, and `%u' by the username of the user running - ssh(1). - - The other keywords' criteria must be single entries or comma- - separated lists and may use the wildcard and negation operators - described in the PATTERNS section. The criteria for the host - keyword are matched against the target hostname, after any - substitution by the Hostname option. The originalhost keyword - matches against the hostname as it was specified on the command- - line. The user keyword matches against the target username on - the remote host. The localuser keyword matches against the name - of the local user running ssh(1) (this keyword may be useful in - system-wide ssh_config files). - - AddressFamily - Specifies which address family to use when connecting. Valid - arguments are ``any'', ``inet'' (use IPv4 only), or ``inet6'' - (use IPv6 only). - - BatchMode - If set to ``yes'', passphrase/password querying will be disabled. - This option is useful in scripts and other batch jobs where no - user is present to supply the password. The argument must be - ``yes'' or ``no''. The default is ``no''. - - BindAddress - Use the specified address on the local machine as the source - address of the connection. Only useful on systems with more than - one address. Note that this option does not work if - UsePrivilegedPort is set to ``yes''. - - CanonicalDomains - When CanonicalizeHostname is enabled, this option specifies the - list of domain suffixes in which to search for the specified - destination host. - - CanonicalizeFallbackLocal - Specifies whether to fail with an error when hostname - canonicalization fails. The default, ``yes'', will attempt to - look up the unqualified hostname using the system resolver's - search rules. A value of ``no'' will cause ssh(1) to fail - instantly if CanonicalizeHostname is enabled and the target - hostname cannot be found in any of the domains specified by - CanonicalDomains. - - CanonicalizeHostname - Controls whether explicit hostname canonicalization is performed. - The default, ``no'', is not to perform any name rewriting and let - the system resolver handle all hostname lookups. If set to - ``yes'' then, for connections that do not use a ProxyCommand, - ssh(1) will attempt to canonicalize the hostname specified on the - command line using the CanonicalDomains suffixes and - CanonicalizePermittedCNAMEs rules. If CanonicalizeHostname is - set to ``always'', then canonicalization is applied to proxied - connections too. - - If this option is enabled and canonicalisation results in the - target hostname changing, then the configuration files are - processed again using the new target name to pick up any new - configuration in matching Host stanzas. - - CanonicalizeMaxDots - Specifies the maximum number of dot characters in a hostname - before canonicalization is disabled. The default, ``1'', allows - a single dot (i.e. hostname.subdomain). - - CanonicalizePermittedCNAMEs - Specifies rules to determine whether CNAMEs should be followed - when canonicalizing hostnames. The rules consist of one or more - arguments of source_domain_list:target_domain_list, where - source_domain_list is a pattern-list of domains that may follow - CNAMEs in canonicalization, and target_domain_list is a pattern- - list of domains that they may resolve to. - - For example, ``*.a.example.com:*.b.example.com,*.c.example.com'' - will allow hostnames matching ``*.a.example.com'' to be - canonicalized to names in the ``*.b.example.com'' or - ``*.c.example.com'' domains. - - ChallengeResponseAuthentication - Specifies whether to use challenge-response authentication. The - argument to this keyword must be ``yes'' or ``no''. The default - is ``yes''. - - CheckHostIP - If this flag is set to ``yes'', ssh(1) will additionally check - the host IP address in the known_hosts file. This allows ssh to - detect if a host key changed due to DNS spoofing. If the option - is set to ``no'', the check will not be executed. The default is - ``yes''. - - Cipher Specifies the cipher to use for encrypting the session in - protocol version 1. Currently, ``blowfish'', ``3des'', and - ``des'' are supported. des is only supported in the ssh(1) - client for interoperability with legacy protocol 1 - implementations that do not support the 3des cipher. Its use is - strongly discouraged due to cryptographic weaknesses. The - default is ``3des''. - - Ciphers - Specifies the ciphers allowed for protocol version 2 in order of - preference. Multiple ciphers must be comma-separated. The - supported ciphers are: - - ``3des-cbc'', ``aes128-cbc'', ``aes192-cbc'', ``aes256-cbc'', - ``aes128-ctr'', ``aes192-ctr'', ``aes256-ctr'', - ``aes128-gcm@openssh.com'', ``aes256-gcm@openssh.com'', - ``arcfour128'', ``arcfour256'', ``arcfour'', ``blowfish-cbc'', - ``cast128-cbc'', and ``chacha20-poly1305@openssh.com''. - - The default is: - - aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, - aes128-gcm@openssh.com,aes256-gcm@openssh.com, - chacha20-poly1305@openssh.com, - aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, - aes256-cbc,arcfour - - The list of available ciphers may also be obtained using the -Q - option of ssh(1). - - ClearAllForwardings - Specifies that all local, remote, and dynamic port forwardings - specified in the configuration files or on the command line be - cleared. This option is primarily useful when used from the - ssh(1) command line to clear port forwardings set in - configuration files, and is automatically set by scp(1) and - sftp(1). The argument must be ``yes'' or ``no''. The default is - ``no''. - - Compression - Specifies whether to use compression. The argument must be - ``yes'' or ``no''. The default is ``no''. - - CompressionLevel - Specifies the compression level to use if compression is enabled. - The argument must be an integer from 1 (fast) to 9 (slow, best). - The default level is 6, which is good for most applications. The - meaning of the values is the same as in gzip(1). Note that this - option applies to protocol version 1 only. - - ConnectionAttempts - Specifies the number of tries (one per second) to make before - exiting. The argument must be an integer. This may be useful in - scripts if the connection sometimes fails. The default is 1. - - ConnectTimeout - Specifies the timeout (in seconds) used when connecting to the - SSH server, instead of using the default system TCP timeout. - This value is used only when the target is down or really - unreachable, not when it refuses the connection. - - ControlMaster - Enables the sharing of multiple sessions over a single network - connection. When set to ``yes'', ssh(1) will listen for - connections on a control socket specified using the ControlPath - argument. Additional sessions can connect to this socket using - the same ControlPath with ControlMaster set to ``no'' (the - default). These sessions will try to reuse the master instance's - network connection rather than initiating new ones, but will fall - back to connecting normally if the control socket does not exist, - or is not listening. - - Setting this to ``ask'' will cause ssh to listen for control - connections, but require confirmation using the SSH_ASKPASS - program before they are accepted (see ssh-add(1) for details). - If the ControlPath cannot be opened, ssh will continue without - connecting to a master instance. - - X11 and ssh-agent(1) forwarding is supported over these - multiplexed connections, however the display and agent forwarded - will be the one belonging to the master connection i.e. it is not - possible to forward multiple displays or agents. - - Two additional options allow for opportunistic multiplexing: try - to use a master connection but fall back to creating a new one if - one does not already exist. These options are: ``auto'' and - ``autoask''. The latter requires confirmation like the ``ask'' - option. - - ControlPath - Specify the path to the control socket used for connection - sharing as described in the ControlMaster section above or the - string ``none'' to disable connection sharing. In the path, `%L' - will be substituted by the first component of the local host - name, `%l' will be substituted by the local host name (including - any domain name), `%h' will be substituted by the target host - name, `%n' will be substituted by the original target host name - specified on the command line, `%p' the destination port, `%r' by - the remote login username, and `%u' by the username of the user - running ssh(1). It is recommended that any ControlPath used for - opportunistic connection sharing include at least %h, %p, and %r. - This ensures that shared connections are uniquely identified. - - ControlPersist - When used in conjunction with ControlMaster, specifies that the - master connection should remain open in the background (waiting - for future client connections) after the initial client - connection has been closed. If set to ``no'', then the master - connection will not be placed into the background, and will close - as soon as the initial client connection is closed. If set to - ``yes'', then the master connection will remain in the background - indefinitely (until killed or closed via a mechanism such as the - ssh(1) ``-O exit'' option). If set to a time in seconds, or a - time in any of the formats documented in sshd_config(5), then the - backgrounded master connection will automatically terminate after - it has remained idle (with no client connections) for the - specified time. - - DynamicForward - Specifies that a TCP port on the local machine be forwarded over - the secure channel, and the application protocol is then used to - determine where to connect to from the remote machine. - - The argument must be [bind_address:]port. IPv6 addresses can be - specified by enclosing addresses in square brackets. By default, - the local port is bound in accordance with the GatewayPorts - setting. However, an explicit bind_address may be used to bind - the connection to a specific address. The bind_address of - ``localhost'' indicates that the listening port be bound for - local use only, while an empty address or `*' indicates that the - port should be available from all interfaces. - - Currently the SOCKS4 and SOCKS5 protocols are supported, and - ssh(1) will act as a SOCKS server. Multiple forwardings may be - specified, and additional forwardings can be given on the command - line. Only the superuser can forward privileged ports. - - EnableSSHKeysign - Setting this option to ``yes'' in the global client configuration - file /etc/ssh/ssh_config enables the use of the helper program - ssh-keysign(8) during HostbasedAuthentication. The argument must - be ``yes'' or ``no''. The default is ``no''. This option should - be placed in the non-hostspecific section. See ssh-keysign(8) - for more information. - - EscapeChar - Sets the escape character (default: `~'). The escape character - can also be set on the command line. The argument should be a - single character, `^' followed by a letter, or ``none'' to - disable the escape character entirely (making the connection - transparent for binary data). - - ExitOnForwardFailure - Specifies whether ssh(1) should terminate the connection if it - cannot set up all requested dynamic, tunnel, local, and remote - port forwardings. The argument must be ``yes'' or ``no''. The - default is ``no''. - - ForwardAgent - Specifies whether the connection to the authentication agent (if - any) will be forwarded to the remote machine. The argument must - be ``yes'' or ``no''. The default is ``no''. - - Agent forwarding should be enabled with caution. Users with the - ability to bypass file permissions on the remote host (for the - agent's Unix-domain socket) can access the local agent through - the forwarded connection. An attacker cannot obtain key material - from the agent, however they can perform operations on the keys - that enable them to authenticate using the identities loaded into - the agent. - - ForwardX11 - Specifies whether X11 connections will be automatically - redirected over the secure channel and DISPLAY set. The argument - must be ``yes'' or ``no''. The default is ``no''. - - X11 forwarding should be enabled with caution. Users with the - ability to bypass file permissions on the remote host (for the - user's X11 authorization database) can access the local X11 - display through the forwarded connection. An attacker may then - be able to perform activities such as keystroke monitoring if the - ForwardX11Trusted option is also enabled. - - ForwardX11Timeout - Specify a timeout for untrusted X11 forwarding using the format - described in the TIME FORMATS section of sshd_config(5). X11 - connections received by ssh(1) after this time will be refused. - The default is to disable untrusted X11 forwarding after twenty - minutes has elapsed. - - ForwardX11Trusted - If this option is set to ``yes'', remote X11 clients will have - full access to the original X11 display. - - If this option is set to ``no'', remote X11 clients will be - considered untrusted and prevented from stealing or tampering - with data belonging to trusted X11 clients. Furthermore, the - xauth(1) token used for the session will be set to expire after - 20 minutes. Remote clients will be refused access after this - time. - - The default is ``no''. - - See the X11 SECURITY extension specification for full details on - the restrictions imposed on untrusted clients. - - GatewayPorts - Specifies whether remote hosts are allowed to connect to local - forwarded ports. By default, ssh(1) binds local port forwardings - to the loopback address. This prevents other remote hosts from - connecting to forwarded ports. GatewayPorts can be used to - specify that ssh should bind local port forwardings to the - wildcard address, thus allowing remote hosts to connect to - forwarded ports. The argument must be ``yes'' or ``no''. The - default is ``no''. - - GlobalKnownHostsFile - Specifies one or more files to use for the global host key - database, separated by whitespace. The default is - /etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2. - - GSSAPIAuthentication - Specifies whether user authentication based on GSSAPI is allowed. - The default is ``no''. Note that this option applies to protocol - version 2 only. - - GSSAPIDelegateCredentials - Forward (delegate) credentials to the server. The default is - ``no''. Note that this option applies to protocol version 2 - only. - - HashKnownHosts - Indicates that ssh(1) should hash host names and addresses when - they are added to ~/.ssh/known_hosts. These hashed names may be - used normally by ssh(1) and sshd(8), but they do not reveal - identifying information should the file's contents be disclosed. - The default is ``no''. Note that existing names and addresses in - known hosts files will not be converted automatically, but may be - manually hashed using ssh-keygen(1). - - HostbasedAuthentication - Specifies whether to try rhosts based authentication with public - key authentication. The argument must be ``yes'' or ``no''. The - default is ``no''. This option applies to protocol version 2 - only and is similar to RhostsRSAAuthentication. - - HostKeyAlgorithms - Specifies the protocol version 2 host key algorithms that the - client wants to use in order of preference. The default for this - option is: - - ecdsa-sha2-nistp256-cert-v01@openssh.com, - ecdsa-sha2-nistp384-cert-v01@openssh.com, - ecdsa-sha2-nistp521-cert-v01@openssh.com, - ssh-ed25519-cert-v01@openssh.com, - ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com, - ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com, - ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - ssh-ed25519,ssh-rsa,ssh-dss - - If hostkeys are known for the destination host then this default - is modified to prefer their algorithms. - - HostKeyAlias - Specifies an alias that should be used instead of the real host - name when looking up or saving the host key in the host key - database files. This option is useful for tunneling SSH - connections or for multiple servers running on a single host. - - HostName - Specifies the real host name to log into. This can be used to - specify nicknames or abbreviations for hosts. If the hostname - contains the character sequence `%h', then this will be replaced - with the host name specified on the command line (this is useful - for manipulating unqualified names). The default is the name - given on the command line. Numeric IP addresses are also - permitted (both on the command line and in HostName - specifications). - - IdentitiesOnly - Specifies that ssh(1) should only use the authentication identity - files configured in the ssh_config files, even if ssh-agent(1) or - a PKCS11Provider offers more identities. The argument to this - keyword must be ``yes'' or ``no''. This option is intended for - situations where ssh-agent offers many different identities. The - default is ``no''. - - IdentityFile - Specifies a file from which the user's DSA, ECDSA, ED25519 or RSA - authentication identity is read. The default is ~/.ssh/identity - for protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, - ~/.ssh/id_ed25519 and ~/.ssh/id_rsa for protocol version 2. - Additionally, any identities represented by the authentication - agent will be used for authentication unless IdentitiesOnly is - set. ssh(1) will try to load certificate information from the - filename obtained by appending -cert.pub to the path of a - specified IdentityFile. - - The file name may use the tilde syntax to refer to a user's home - directory or one of the following escape characters: `%d' (local - user's home directory), `%u' (local user name), `%l' (local host - name), `%h' (remote host name) or `%r' (remote user name). - - It is possible to have multiple identity files specified in - configuration files; all these identities will be tried in - sequence. Multiple IdentityFile directives will add to the list - of identities tried (this behaviour differs from that of other - configuration directives). - - IdentityFile may be used in conjunction with IdentitiesOnly to - select which identities in an agent are offered during - authentication. - - IgnoreUnknown - Specifies a pattern-list of unknown options to be ignored if they - are encountered in configuration parsing. This may be used to - suppress errors if ssh_config contains options that are - unrecognised by ssh(1). It is recommended that IgnoreUnknown be - listed early in the configuration file as it will not be applied - to unknown options that appear before it. - - IPQoS Specifies the IPv4 type-of-service or DSCP class for connections. - Accepted values are ``af11'', ``af12'', ``af13'', ``af21'', - ``af22'', ``af23'', ``af31'', ``af32'', ``af33'', ``af41'', - ``af42'', ``af43'', ``cs0'', ``cs1'', ``cs2'', ``cs3'', ``cs4'', - ``cs5'', ``cs6'', ``cs7'', ``ef'', ``lowdelay'', ``throughput'', - ``reliability'', or a numeric value. This option may take one or - two arguments, separated by whitespace. If one argument is - specified, it is used as the packet class unconditionally. If - two values are specified, the first is automatically selected for - interactive sessions and the second for non-interactive sessions. - The default is ``lowdelay'' for interactive sessions and - ``throughput'' for non-interactive sessions. - - KbdInteractiveAuthentication - Specifies whether to use keyboard-interactive authentication. - The argument to this keyword must be ``yes'' or ``no''. The - default is ``yes''. - - KbdInteractiveDevices - Specifies the list of methods to use in keyboard-interactive - authentication. Multiple method names must be comma-separated. - The default is to use the server specified list. The methods - available vary depending on what the server supports. For an - OpenSSH server, it may be zero or more of: ``bsdauth'', ``pam'', - and ``skey''. - - KexAlgorithms - Specifies the available KEX (Key Exchange) algorithms. Multiple - algorithms must be comma-separated. The default is: - - curve25519-sha256@libssh.org, - ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, - diffie-hellman-group-exchange-sha256, - diffie-hellman-group-exchange-sha1, - diffie-hellman-group14-sha1, - diffie-hellman-group1-sha1 - - LocalCommand - Specifies a command to execute on the local machine after - successfully connecting to the server. The command string - extends to the end of the line, and is executed with the user's - shell. The following escape character substitutions will be - performed: `%d' (local user's home directory), `%h' (remote host - name), `%l' (local host name), `%n' (host name as provided on the - command line), `%p' (remote port), `%r' (remote user name) or - `%u' (local user name). - - The command is run synchronously and does not have access to the - session of the ssh(1) that spawned it. It should not be used for - interactive commands. - - This directive is ignored unless PermitLocalCommand has been - enabled. - - LocalForward - Specifies that a TCP port on the local machine be forwarded over - the secure channel to the specified host and port from the remote - machine. The first argument must be [bind_address:]port and the - second argument must be host:hostport. IPv6 addresses can be - specified by enclosing addresses in square brackets. Multiple - forwardings may be specified, and additional forwardings can be - given on the command line. Only the superuser can forward - privileged ports. By default, the local port is bound in - accordance with the GatewayPorts setting. However, an explicit - bind_address may be used to bind the connection to a specific - address. The bind_address of ``localhost'' indicates that the - listening port be bound for local use only, while an empty - address or `*' indicates that the port should be available from - all interfaces. - - LogLevel - Gives the verbosity level that is used when logging messages from - ssh(1). The possible values are: QUIET, FATAL, ERROR, INFO, - VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. - DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify - higher levels of verbose output. - - MACs Specifies the MAC (message authentication code) algorithms in - order of preference. The MAC algorithm is used in protocol - version 2 for data integrity protection. Multiple algorithms - must be comma-separated. The algorithms that contain ``-etm'' - calculate the MAC after encryption (encrypt-then-mac). These are - considered safer and their use recommended. The default is: - - hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, - umac-64-etm@openssh.com,umac-128-etm@openssh.com, - hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, - hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, - hmac-md5-96-etm@openssh.com, - hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, - hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, - hmac-sha1-96,hmac-md5-96 - - NoHostAuthenticationForLocalhost - This option can be used if the home directory is shared across - machines. In this case localhost will refer to a different - machine on each of the machines and the user will get many - warnings about changed host keys. However, this option disables - host authentication for localhost. The argument to this keyword - must be ``yes'' or ``no''. The default is to check the host key - for localhost. - - NumberOfPasswordPrompts - Specifies the number of password prompts before giving up. The - argument to this keyword must be an integer. The default is 3. - - PasswordAuthentication - Specifies whether to use password authentication. The argument - to this keyword must be ``yes'' or ``no''. The default is - ``yes''. - - PermitLocalCommand - Allow local command execution via the LocalCommand option or - using the !command escape sequence in ssh(1). The argument must - be ``yes'' or ``no''. The default is ``no''. - - PKCS11Provider - Specifies which PKCS#11 provider to use. The argument to this - keyword is the PKCS#11 shared library ssh(1) should use to - communicate with a PKCS#11 token providing the user's private RSA - key. - - Port Specifies the port number to connect on the remote host. The - default is 22. - - PreferredAuthentications - Specifies the order in which the client should try protocol 2 - authentication methods. This allows a client to prefer one - method (e.g. keyboard-interactive) over another method (e.g. - password). The default is: - - gssapi-with-mic,hostbased,publickey, - keyboard-interactive,password - - Protocol - Specifies the protocol versions ssh(1) should support in order of - preference. The possible values are `1' and `2'. Multiple - versions must be comma-separated. When this option is set to - ``2,1'' ssh will try version 2 and fall back to version 1 if - version 2 is not available. The default is `2'. - - ProxyCommand - Specifies the command to use to connect to the server. The - command string extends to the end of the line, and is executed - with the user's shell. In the command string, any occurrence of - `%h' will be substituted by the host name to connect, `%p' by the - port, and `%r' by the remote user name. The command can be - basically anything, and should read from its standard input and - write to its standard output. It should eventually connect an - sshd(8) server running on some machine, or execute sshd -i - somewhere. Host key management will be done using the HostName - of the host being connected (defaulting to the name typed by the - user). Setting the command to ``none'' disables this option - entirely. Note that CheckHostIP is not available for connects - with a proxy command. - - This directive is useful in conjunction with nc(1) and its proxy - support. For example, the following directive would connect via - an HTTP proxy at 192.0.2.0: - - ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p - - ProxyUseFdpass - Specifies that ProxyCommand will pass a connected file descriptor - back to ssh(1) instead of continuing to execute and pass data. - The default is ``no''. - - PubkeyAuthentication - Specifies whether to try public key authentication. The argument - to this keyword must be ``yes'' or ``no''. The default is - ``yes''. This option applies to protocol version 2 only. - - RekeyLimit - Specifies the maximum amount of data that may be transmitted - before the session key is renegotiated, optionally followed a - maximum amount of time that may pass before the session key is - renegotiated. The first argument is specified in bytes and may - have a suffix of `K', `M', or `G' to indicate Kilobytes, - Megabytes, or Gigabytes, respectively. The default is between - `1G' and `4G', depending on the cipher. The optional second - value is specified in seconds and may use any of the units - documented in the TIME FORMATS section of sshd_config(5). The - default value for RekeyLimit is ``default none'', which means - that rekeying is performed after the cipher's default amount of - data has been sent or received and no time based rekeying is - done. This option applies to protocol version 2 only. - - RemoteForward - Specifies that a TCP port on the remote machine be forwarded over - the secure channel to the specified host and port from the local - machine. The first argument must be [bind_address:]port and the - second argument must be host:hostport. IPv6 addresses can be - specified by enclosing addresses in square brackets. Multiple - forwardings may be specified, and additional forwardings can be - given on the command line. Privileged ports can be forwarded - only when logging in as root on the remote machine. - - If the port argument is `0', the listen port will be dynamically - allocated on the server and reported to the client at run time. - - If the bind_address is not specified, the default is to only bind - to loopback addresses. If the bind_address is `*' or an empty - string, then the forwarding is requested to listen on all - interfaces. Specifying a remote bind_address will only succeed - if the server's GatewayPorts option is enabled (see - sshd_config(5)). - - RequestTTY - Specifies whether to request a pseudo-tty for the session. The - argument may be one of: ``no'' (never request a TTY), ``yes'' - (always request a TTY when standard input is a TTY), ``force'' - (always request a TTY) or ``auto'' (request a TTY when opening a - login session). This option mirrors the -t and -T flags for - ssh(1). - - RhostsRSAAuthentication - Specifies whether to try rhosts based authentication with RSA - host authentication. The argument must be ``yes'' or ``no''. - The default is ``no''. This option applies to protocol version 1 - only and requires ssh(1) to be setuid root. - - RSAAuthentication - Specifies whether to try RSA authentication. The argument to - this keyword must be ``yes'' or ``no''. RSA authentication will - only be attempted if the identity file exists, or an - authentication agent is running. The default is ``yes''. Note - that this option applies to protocol version 1 only. - - SendEnv - Specifies what variables from the local environ(7) should be sent - to the server. Note that environment passing is only supported - for protocol 2. The server must also support it, and the server - must be configured to accept these environment variables. Refer - to AcceptEnv in sshd_config(5) for how to configure the server. - Variables are specified by name, which may contain wildcard - characters. Multiple environment variables may be separated by - whitespace or spread across multiple SendEnv directives. The - default is not to send any environment variables. - - See PATTERNS for more information on patterns. - - ServerAliveCountMax - Sets the number of server alive messages (see below) which may be - sent without ssh(1) receiving any messages back from the server. - If this threshold is reached while server alive messages are - being sent, ssh will disconnect from the server, terminating the - session. It is important to note that the use of server alive - messages is very different from TCPKeepAlive (below). The server - alive messages are sent through the encrypted channel and - therefore will not be spoofable. The TCP keepalive option - enabled by TCPKeepAlive is spoofable. The server alive mechanism - is valuable when the client or server depend on knowing when a - connection has become inactive. - - The default value is 3. If, for example, ServerAliveInterval - (see below) is set to 15 and ServerAliveCountMax is left at the - default, if the server becomes unresponsive, ssh will disconnect - after approximately 45 seconds. This option applies to protocol - version 2 only. - - ServerAliveInterval - Sets a timeout interval in seconds after which if no data has - been received from the server, ssh(1) will send a message through - the encrypted channel to request a response from the server. The - default is 0, indicating that these messages will not be sent to - the server. This option applies to protocol version 2 only. - - StrictHostKeyChecking - If this flag is set to ``yes'', ssh(1) will never automatically - add host keys to the ~/.ssh/known_hosts file, and refuses to - connect to hosts whose host key has changed. This provides - maximum protection against trojan horse attacks, though it can be - annoying when the /etc/ssh/ssh_known_hosts file is poorly - maintained or when connections to new hosts are frequently made. - This option forces the user to manually add all new hosts. If - this flag is set to ``no'', ssh will automatically add new host - keys to the user known hosts files. If this flag is set to - ``ask'', new host keys will be added to the user known host files - only after the user has confirmed that is what they really want - to do, and ssh will refuse to connect to hosts whose host key has - changed. The host keys of known hosts will be verified - automatically in all cases. The argument must be ``yes'', - ``no'', or ``ask''. The default is ``ask''. - - TCPKeepAlive - Specifies whether the system should send TCP keepalive messages - to the other side. If they are sent, death of the connection or - crash of one of the machines will be properly noticed. However, - this means that connections will die if the route is down - temporarily, and some people find it annoying. - - The default is ``yes'' (to send TCP keepalive messages), and the - client will notice if the network goes down or the remote host - dies. This is important in scripts, and many users want it too. - - To disable TCP keepalive messages, the value should be set to - ``no''. - - Tunnel Request tun(4) device forwarding between the client and the - server. The argument must be ``yes'', ``point-to-point'' (layer - 3), ``ethernet'' (layer 2), or ``no''. Specifying ``yes'' - requests the default tunnel mode, which is ``point-to-point''. - The default is ``no''. - - TunnelDevice - Specifies the tun(4) devices to open on the client (local_tun) - and the server (remote_tun). - - The argument must be local_tun[:remote_tun]. The devices may be - specified by numerical ID or the keyword ``any'', which uses the - next available tunnel device. If remote_tun is not specified, it - defaults to ``any''. The default is ``any:any''. - - UsePrivilegedPort - Specifies whether to use a privileged port for outgoing - connections. The argument must be ``yes'' or ``no''. The - default is ``no''. If set to ``yes'', ssh(1) must be setuid - root. Note that this option must be set to ``yes'' for - RhostsRSAAuthentication with older servers. - - User Specifies the user to log in as. This can be useful when a - different user name is used on different machines. This saves - the trouble of having to remember to give the user name on the - command line. - - UserKnownHostsFile - Specifies one or more files to use for the user host key - database, separated by whitespace. The default is - ~/.ssh/known_hosts, ~/.ssh/known_hosts2. - - VerifyHostKeyDNS - Specifies whether to verify the remote key using DNS and SSHFP - resource records. If this option is set to ``yes'', the client - will implicitly trust keys that match a secure fingerprint from - DNS. Insecure fingerprints will be handled as if this option was - set to ``ask''. If this option is set to ``ask'', information on - fingerprint match will be displayed, but the user will still need - to confirm new host keys according to the StrictHostKeyChecking - option. The argument must be ``yes'', ``no'', or ``ask''. The - default is ``no''. Note that this option applies to protocol - version 2 only. - - See also VERIFYING HOST KEYS in ssh(1). - - VisualHostKey - If this flag is set to ``yes'', an ASCII art representation of - the remote host key fingerprint is printed in addition to the hex - fingerprint string at login and for unknown host keys. If this - flag is set to ``no'', no fingerprint strings are printed at - login and only the hex fingerprint string will be printed for - unknown host keys. The default is ``no''. - - XAuthLocation - Specifies the full pathname of the xauth(1) program. The default - is /usr/X11R6/bin/xauth. - -PATTERNS - A pattern consists of zero or more non-whitespace characters, `*' (a - wildcard that matches zero or more characters), or `?' (a wildcard that - matches exactly one character). For example, to specify a set of - declarations for any host in the ``.co.uk'' set of domains, the following - pattern could be used: - - Host *.co.uk - - The following pattern would match any host in the 192.168.0.[0-9] network - range: - - Host 192.168.0.? - - A pattern-list is a comma-separated list of patterns. Patterns within - pattern-lists may be negated by preceding them with an exclamation mark - (`!'). For example, to allow a key to be used from anywhere within an - organization except from the ``dialup'' pool, the following entry (in - authorized_keys) could be used: - - from="!*.dialup.example.com,*.example.com" - -FILES - ~/.ssh/config - This is the per-user configuration file. The format of this file - is described above. This file is used by the SSH client. - Because of the potential for abuse, this file must have strict - permissions: read/write for the user, and not accessible by - others. - - /etc/ssh/ssh_config - Systemwide configuration file. This file provides defaults for - those values that are not specified in the user's configuration - file, and for those users who do not have a configuration file. - This file must be world-readable. - -SEE ALSO - ssh(1) - -AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by - Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. - -OpenBSD 5.5 February 23, 2014 OpenBSD 5.5 diff --git a/crypto/openssh/ssh_config.5 b/crypto/openssh/ssh_config.5 index fec66d2..2f6d0dc 100644 --- a/crypto/openssh/ssh_config.5 +++ b/crypto/openssh/ssh_config.5 @@ -33,9 +33,9 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.185 2014/02/23 20:11:36 djm Exp $ +.\" $OpenBSD: ssh_config.5,v 1.215 2015/08/14 15:32:41 jmc Exp $ .\" $FreeBSD$ -.Dd $Mdocdate: February 23 2014 $ +.Dd $Mdocdate: August 14 2015 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -66,7 +66,10 @@ The configuration files contain sections separated by .Dq Host specifications, and that section is only applied for hosts that match one of the patterns given in the specification. -The matched host name is the one given on the command line. +The matched host name is usually the one given on the command line +(see the +.Cm CanonicalizeHostname +option for exceptions.) .Pp Since the first obtained value for each parameter is used, more host-specific declarations should be given near the beginning of the @@ -110,10 +113,12 @@ A single .Ql * as a pattern can be used to provide global defaults for all hosts. -The host is the +The host is usually the .Ar hostname -argument given on the command line (i.e. the name is not converted to -a canonicalized host name before matching). +argument given on the command line +(see the +.Cm CanonicalizeHostname +option for exceptions.) .Pp A pattern entry may be negated by prefixing it with an exclamation mark .Pq Sq !\& . @@ -135,19 +140,40 @@ or keyword) to be used only when the conditions following the .Cm Match keyword are satisfied. -Match conditions are specified using one or more keyword/criteria pairs +Match conditions are specified using one or more critera or the single token .Cm all -which matches all criteria. -The available keywords are: +which always matches. +The available criteria keywords are: +.Cm canonical , .Cm exec , .Cm host , .Cm originalhost , .Cm user , and .Cm localuser . +The +.Cm all +criteria must appear alone or immediately after +.Cm canonical . +Other criteria may be combined arbitrarily. +All criteria but +.Cm all +and +.Cm canonical +require an argument. +Criteria may be negated by prepending an exclamation mark +.Pq Sq !\& . .Pp The +.Cm canonical +keyword matches only when the configuration file is being re-parsed +after hostname canonicalization (see the +.Cm CanonicalizeHostname +option.) +This may be useful to specify conditions that work with canonical host +names only. +The .Cm exec keyword executes the specified command under the user's shell. If the command returns a zero exit status then the condition is considered true. @@ -180,7 +206,9 @@ The criteria for the keyword are matched against the target hostname, after any substitution by the .Cm Hostname -option. +or +.Cm CanonicalizeHostname +options. The .Cm originalhost keyword matches against the hostname as it was specified on the command-line. @@ -265,10 +293,11 @@ is set to .Dq always , then canonicalization is applied to proxied connections too. .Pp -If this option is enabled and canonicalisation results in the target hostname -changing, then the configuration files are processed again using the new -target name to pick up any new configuration in matching +If this option is enabled, then the configuration files are processed +again using the new target name to pick up any new configuration in matching .Cm Host +and +.Cm Match stanzas. .It Cm CanonicalizeMaxDots Specifies the maximum number of dot characters in a hostname before @@ -312,7 +341,11 @@ If this flag is set to will additionally check the host IP address in the .Pa known_hosts file. -This allows ssh to detect if a host key changed due to DNS spoofing. +This allows ssh to detect if a host key changed due to DNS spoofing +and will add addresses of destination hosts to +.Pa ~/.ssh/known_hosts +in the process, regardless of the setting of +.Cm StrictHostKeyChecking . If the option is set to .Dq no , the check will not be executed. @@ -341,38 +374,62 @@ The default is Specifies the ciphers allowed for protocol version 2 in order of preference. Multiple ciphers must be comma-separated. +If the specified value begins with a +.Sq + +character, then the specified ciphers will be appended to the default set +instead of replacing them. +.Pp The supported ciphers are: .Pp -.Dq 3des-cbc , -.Dq aes128-cbc , -.Dq aes192-cbc , -.Dq aes256-cbc , -.Dq aes128-ctr , -.Dq aes192-ctr , -.Dq aes256-ctr , -.Dq aes128-gcm@openssh.com , -.Dq aes256-gcm@openssh.com , -.Dq arcfour128 , -.Dq arcfour256 , -.Dq arcfour , -.Dq blowfish-cbc , -.Dq cast128-cbc , -and -.Dq chacha20-poly1305@openssh.com . +.Bl -item -compact -offset indent +.It +3des-cbc +.It +aes128-cbc +.It +aes192-cbc +.It +aes256-cbc +.It +aes128-ctr +.It +aes192-ctr +.It +aes256-ctr +.It +aes128-gcm@openssh.com +.It +aes256-gcm@openssh.com +.It +arcfour +.It +arcfour128 +.It +arcfour256 +.It +blowfish-cbc +.It +cast128-cbc +.It +chacha20-poly1305@openssh.com +.El .Pp The default is: -.Bd -literal -offset 3n -aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, -aes128-gcm@openssh.com,aes256-gcm@openssh.com, +.Bd -literal -offset indent chacha20-poly1305@openssh.com, -aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, -aes256-cbc,arcfour +aes128-ctr,aes192-ctr,aes256-ctr, +aes128-gcm@openssh.com,aes256-gcm@openssh.com, +arcfour256,arcfour128, +aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc, +aes192-cbc,aes256-cbc,arcfour .Ed .Pp The list of available ciphers may also be obtained using the .Fl Q option of -.Xr ssh 1 . +.Xr ssh 1 +with an argument of +.Dq cipher . .It Cm ClearAllForwardings Specifies that all local, remote, and dynamic port forwardings specified in the configuration files or on the command line be @@ -437,11 +494,8 @@ if the control socket does not exist, or is not listening. Setting this to .Dq ask will cause ssh -to listen for control connections, but require confirmation using the -.Ev SSH_ASKPASS -program before they are accepted (see -.Xr ssh-add 1 -for details). +to listen for control connections, but require confirmation using +.Xr ssh-askpass 1 . If the .Cm ControlPath cannot be opened, @@ -483,14 +537,17 @@ specified on the command line, .Ql %p the destination port, .Ql %r -by the remote login username, and +by the remote login username, .Ql %u by the username of the user running -.Xr ssh 1 . +.Xr ssh 1 , and +.Ql \&%C +by a hash of the concatenation: %l%h%p%r. It is recommended that any .Cm ControlPath used for opportunistic connection sharing include -at least %h, %p, and %r. +at least %h, %p, and %r (or alternatively %C) and be placed in a directory +that is not writable by other users. This ensures that shared connections are uniquely identified. .It Cm ControlPersist When used in conjunction with @@ -503,7 +560,9 @@ If set to then the master connection will not be placed into the background, and will close as soon as the initial client connection is closed. If set to -.Dq yes , +.Dq yes +or +.Dq 0 , then the master connection will remain in the background indefinitely (until killed or closed via a mechanism such as the .Xr ssh 1 @@ -588,6 +647,14 @@ or .Dq no . The default is .Dq no . +.It Cm FingerprintHash +Specifies the hash algorithm used when displaying key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . .It Cm ForwardAgent Specifies whether the connection to the authentication agent (if any) will be forwarded to the remote machine. @@ -717,23 +784,60 @@ The default is This option applies to protocol version 2 only and is similar to .Cm RhostsRSAAuthentication . +.It Cm HostbasedKeyTypes +Specifies the key types that will be used for hostbased authentication +as a comma-separated pattern list. +Alternately if the specified value begins with a +.Sq + +character, then the specified key types will be appended to the default set +instead of replacing them. +The default for this option is: +.Bd -literal -offset 3n +ecdsa-sha2-nistp256-cert-v01@openssh.com, +ecdsa-sha2-nistp384-cert-v01@openssh.com, +ecdsa-sha2-nistp521-cert-v01@openssh.com, +ssh-ed25519-cert-v01@openssh.com, +ssh-rsa-cert-v01@openssh.com, +ssh-dss-cert-v01@openssh.com, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384, +ecdsa-sha2-nistp521,ssh-ed25519, +ssh-rsa,ssh-dss +.Ed +.Pp +The +.Fl Q +option of +.Xr ssh 1 +may be used to list supported key types. .It Cm HostKeyAlgorithms Specifies the protocol version 2 host key algorithms that the client wants to use in order of preference. +Alternately if the specified value begins with a +.Sq + +character, then the specified key types will be appended to the default set +instead of replacing them. The default for this option is: .Bd -literal -offset 3n ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, ssh-ed25519-cert-v01@openssh.com, -ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com, -ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com, -ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -ssh-ed25519,ssh-rsa,ssh-dss +ssh-rsa-cert-v01@openssh.com, +ssh-dss-cert-v01@openssh.com, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384, +ecdsa-sha2-nistp521,ssh-ed25519, +ssh-rsa,ssh-dss .Ed .Pp If hostkeys are known for the destination host then this default is modified to prefer their algorithms. +.Pp +The list of available key types may also be obtained using the +.Fl Q +option of +.Xr ssh 1 +with an argument of +.Dq key . .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key @@ -747,6 +851,12 @@ If the hostname contains the character sequence .Ql %h , then this will be replaced with the host name specified on the command line (this is useful for manipulating unqualified names). +The character sequence +.Ql %% +will be replaced by a single +.Ql % +character, which may be used when specifying IPv6 link-local addresses. +.Pp The default is the name given on the command line. Numeric IP addresses are also permitted (both on the command line and in .Cm HostName @@ -771,7 +881,7 @@ offers many different identities. The default is .Dq no . .It Cm IdentityFile -Specifies a file from which the user's DSA, ECDSA, ED25519 or RSA authentication +Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA authentication identity is read. The default is .Pa ~/.ssh/identity @@ -889,15 +999,25 @@ and .It Cm KexAlgorithms Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must be comma-separated. +Alternately if the specified value begins with a +.Sq + +character, then the specified methods will be appended to the default set +instead of replacing them. The default is: .Bd -literal -offset indent curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, -diffie-hellman-group14-sha1, -diffie-hellman-group1-sha1 +diffie-hellman-group14-sha1 .Ed +.Pp +The list of available key exchange algorithms may also be obtained using the +.Fl Q +option of +.Xr ssh 1 +with an argument of +.Dq kex . .It Cm LocalCommand Specifies a command to execute on the local machine after successfully connecting to the server. @@ -917,7 +1037,9 @@ The following escape character substitutions will be performed: .Ql %r (remote user name) or .Ql %u -(local user name). +(local user name) or +.Ql \&%C +by a hash of the concatenation: %l%h%p%r. .Pp The command is run synchronously and does not have access to the session of the @@ -969,21 +1091,35 @@ in order of preference. The MAC algorithm is used in protocol version 2 for data integrity protection. Multiple algorithms must be comma-separated. +If the specified value begins with a +.Sq + +character, then the specified algorithms will be appended to the default set +instead of replacing them. +.Pp The algorithms that contain .Dq -etm calculate the MAC after encryption (encrypt-then-mac). These are considered safer and their use recommended. +.Pp The default is: .Bd -literal -offset indent -hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, umac-64-etm@openssh.com,umac-128-etm@openssh.com, hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, -hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, -hmac-md5-96-etm@openssh.com, -hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, -hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, +umac-64@openssh.com,umac-128@openssh.com, +hmac-sha2-256,hmac-sha2-512, +hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, +hmac-ripemd160-etm@openssh.com, +hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com, +hmac-md5,hmac-sha1,hmac-ripemd160, hmac-sha1-96,hmac-md5-96 .Ed +.Pp +The list of available MAC algorithms may also be obtained using the +.Fl Q +option of +.Xr ssh 1 +with an argument of +.Dq mac . .It Cm NoHostAuthenticationForLocalhost This option can be used if the home directory is shared across machines. In this case localhost will refer to a different machine on each of @@ -1059,8 +1195,11 @@ The default is .It Cm ProxyCommand Specifies the command to use to connect to the server. The command -string extends to the end of the line, and is executed with -the user's shell. +string extends to the end of the line, and is executed +using the user's shell +.Ql exec +directive to avoid a lingering shell process. +.Pp In the command string, any occurrence of .Ql %h will be substituted by the host name to @@ -1102,6 +1241,31 @@ will pass a connected file descriptor back to instead of continuing to execute and pass data. The default is .Dq no . +.It Cm PubkeyAcceptedKeyTypes +Specifies the key types that will be used for public key authentication +as a comma-separated pattern list. +Alternately if the specified value begins with a +.Sq + +character, then the key types after it will be appended to the default +instead of replacing it. +The default for this option is: +.Bd -literal -offset 3n +ecdsa-sha2-nistp256-cert-v01@openssh.com, +ecdsa-sha2-nistp384-cert-v01@openssh.com, +ecdsa-sha2-nistp521-cert-v01@openssh.com, +ssh-ed25519-cert-v01@openssh.com, +ssh-rsa-cert-v01@openssh.com, +ssh-dss-cert-v01@openssh.com, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384, +ecdsa-sha2-nistp521,ssh-ed25519, +ssh-rsa,ssh-dss +.Ed +.Pp +The +.Fl Q +option of +.Xr ssh 1 +may be used to list supported key types. .It Cm PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be @@ -1191,6 +1355,16 @@ and .Fl T flags for .Xr ssh 1 . +.It Cm RevokedHostKeys +Specifies revoked host public keys. +Keys listed in this file will be refused for host authentication. +Note that if this file does not exist or is not readable, +then host authentication will be refused for all hosts. +Keys may be specified as a text file, listing one public key per line, or as +an OpenSSH Key Revocation List (KRL) as generated by +.Xr ssh-keygen 1 . +For more information on KRLs, see the KEY REVOCATION LISTS section in +.Xr ssh-keygen 1 . .It Cm RhostsRSAAuthentication Specifies whether to try rhosts based authentication with RSA host authentication. @@ -1222,6 +1396,10 @@ should be sent to the server. Note that environment passing is only supported for protocol 2. The server must also support it, and the server must be configured to accept these environment variables. +Note that the +.Ev TERM +environment variable is always sent whenever a +pseudo-terminal is requested as it is required by the protocol. Refer to .Cm AcceptEnv in @@ -1273,6 +1451,33 @@ channel to request a response from the server. The default is 0, indicating that these messages will not be sent to the server. This option applies to protocol version 2 only. +.It Cm StreamLocalBindMask +Sets the octal file creation mode mask +.Pq umask +used when creating a Unix-domain socket file for local or remote +port forwarding. +This option is only used for port forwarding to a Unix-domain socket file. +.Pp +The default value is 0177, which creates a Unix-domain socket file that is +readable and writable only by the owner. +Note that not all operating systems honor the file mode on Unix-domain +socket files. +.It Cm StreamLocalBindUnlink +Specifies whether to remove an existing Unix-domain socket file for local +or remote port forwarding before creating a new one. +If the socket file already exists and +.Cm StreamLocalBindUnlink +is not enabled, +.Nm ssh +will be unable to forward the port to the Unix-domain socket file. +This option is only used for port forwarding to a Unix-domain socket file. +.Pp +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . .It Cm StrictHostKeyChecking If this flag is set to .Dq yes , @@ -1362,6 +1567,36 @@ is not specified, it defaults to .Dq any . The default is .Dq any:any . +.It Cm UpdateHostKeys +Specifies whether +.Xr ssh 1 +should accept notifications of additional hostkeys from the server sent +after authentication has completed and add them to +.Cm UserKnownHostsFile . +The argument must be +.Dq yes , +.Dq no +(the default) or +.Dq ask . +Enabling this option allows learning alternate hostkeys for a server +and supports graceful key rotation by allowing a server to send replacement +public keys before old ones are removed. +Additional hostkeys are only accepted if the key used to authenticate the +host was already trusted or explicity accepted by the user. +If +.Cm UpdateHostKeys +is set to +.Dq ask , +then the user is asked to confirm the modifications to the known_hosts file. +Confirmation is currently incompatible with +.Cm ControlPersist , +and will be disabled if it is enabled. +.Pp +Presently, only +.Xr sshd 8 +from OpenSSH 6.8 and greater support the +.Dq hostkeys@openssh.com +protocol extension used to inform the client of all the server's hostkeys. .It Cm UsePrivilegedPort Specifies whether to use a privileged port for outgoing connections. The argument must be @@ -1423,7 +1658,7 @@ See also VERIFYING HOST KEYS in Specifies a string to append to the regular version string to identify OS- or site-specific modifications. The default is -.Dq FreeBSD-20160124 . +.Dq FreeBSD-20160125 . The value .Dq none may be used to disable this. @@ -1431,12 +1666,12 @@ may be used to disable this. If this flag is set to .Dq yes , an ASCII art representation of the remote host key fingerprint is -printed in addition to the hex fingerprint string at login and +printed in addition to the fingerprint string at login and for unknown host keys. If this flag is set to .Dq no , no fingerprint strings are printed at login and -only the hex fingerprint string will be printed for unknown host keys. +only the fingerprint string will be printed for unknown host keys. The default is .Dq no . .It Cm XAuthLocation diff --git a/crypto/openssh/ssh_namespace.h b/crypto/openssh/ssh_namespace.h index 8b5e416..edbda73 100644 --- a/crypto/openssh/ssh_namespace.h +++ b/crypto/openssh/ssh_namespace.h @@ -1,6 +1,6 @@ /* * Namespace munging inspired by an equivalent hack in NetBSD's tree: add - * the "ssh_" prefix to every symbol in libssh which doesn't already have + * the "Fssh_" prefix to every symbol in libssh which doesn't already have * it. This prevents collisions between symbols in libssh and symbols in * other libraries or applications which link with libssh, either directly * or indirectly (e.g. through PAM loading pam_ssh). @@ -8,652 +8,918 @@ * A list of symbols which need munging is obtained as follows: * # nm libprivatessh.a | LC_ALL=C awk ' - /^[0-9a-z]+ [Tt] [A-Za-z_][0-9A-Za-z_]*$/ && $3 !~ /^ssh_/ { - printf("#define %-39s ssh_%s\n", $3, $3) + /^[0-9a-z]+ [Tt] [A-Za-z_][0-9A-Za-z_]*$/ && $3 !~ /^Fssh_/ { + printf("#define %-39s Fssh_%s\n", $3, $3) }' | unexpand -a | LC_ALL=C sort -u * * $FreeBSD$ */ -#define Blowfish_decipher ssh_Blowfish_decipher -#define Blowfish_encipher ssh_Blowfish_encipher -#define Blowfish_expand0state ssh_Blowfish_expand0state -#define Blowfish_expandstate ssh_Blowfish_expandstate -#define Blowfish_initstate ssh_Blowfish_initstate -#define Blowfish_stream2word ssh_Blowfish_stream2word -#define a2port ssh_a2port -#define a2tun ssh_a2tun -#define add_host_to_hostfile ssh_add_host_to_hostfile -#define add_p1p1 ssh_add_p1p1 -#define addargs ssh_addargs -#define addr_match_cidr_list ssh_addr_match_cidr_list -#define addr_match_list ssh_addr_match_list -#define addr_netmatch ssh_addr_netmatch -#define addr_pton ssh_addr_pton -#define addr_pton_cidr ssh_addr_pton_cidr -#define ask_permission ssh_ask_permission -#define atomicio ssh_atomicio -#define atomicio6 ssh_atomicio6 -#define atomiciov ssh_atomiciov -#define atomiciov6 ssh_atomiciov6 -#define auth_request_forwarding ssh_auth_request_forwarding -#define bandwidth_limit ssh_bandwidth_limit -#define bandwidth_limit_init ssh_bandwidth_limit_init -#define barrett_reduce ssh_barrett_reduce -#define bcrypt_hash ssh_bcrypt_hash -#define bcrypt_pbkdf ssh_bcrypt_pbkdf -#define bf_ssh1_cipher ssh_bf_ssh1_cipher -#define blf_cbc_decrypt ssh_blf_cbc_decrypt -#define blf_cbc_encrypt ssh_blf_cbc_encrypt -#define blf_dec ssh_blf_dec -#define blf_ecb_decrypt ssh_blf_ecb_decrypt -#define blf_ecb_encrypt ssh_blf_ecb_encrypt -#define blf_enc ssh_blf_enc -#define blf_key ssh_blf_key -#define buffer_append ssh_buffer_append -#define buffer_append_space ssh_buffer_append_space -#define buffer_check_alloc ssh_buffer_check_alloc -#define buffer_clear ssh_buffer_clear -#define buffer_compress ssh_buffer_compress -#define buffer_compress_init_recv ssh_buffer_compress_init_recv -#define buffer_compress_init_send ssh_buffer_compress_init_send -#define buffer_compress_uninit ssh_buffer_compress_uninit -#define buffer_consume ssh_buffer_consume -#define buffer_consume_end ssh_buffer_consume_end -#define buffer_consume_end_ret ssh_buffer_consume_end_ret -#define buffer_consume_ret ssh_buffer_consume_ret -#define buffer_dump ssh_buffer_dump -#define buffer_free ssh_buffer_free -#define buffer_get ssh_buffer_get -#define buffer_get_bignum ssh_buffer_get_bignum -#define buffer_get_bignum2 ssh_buffer_get_bignum2 -#define buffer_get_bignum2_as_string ssh_buffer_get_bignum2_as_string -#define buffer_get_bignum2_as_string_ret ssh_buffer_get_bignum2_as_string_ret -#define buffer_get_bignum2_ret ssh_buffer_get_bignum2_ret -#define buffer_get_bignum_ret ssh_buffer_get_bignum_ret -#define buffer_get_char ssh_buffer_get_char -#define buffer_get_char_ret ssh_buffer_get_char_ret -#define buffer_get_cstring ssh_buffer_get_cstring -#define buffer_get_cstring_ret ssh_buffer_get_cstring_ret -#define buffer_get_ecpoint ssh_buffer_get_ecpoint -#define buffer_get_ecpoint_ret ssh_buffer_get_ecpoint_ret -#define buffer_get_int ssh_buffer_get_int -#define buffer_get_int64 ssh_buffer_get_int64 -#define buffer_get_int64_ret ssh_buffer_get_int64_ret -#define buffer_get_int_ret ssh_buffer_get_int_ret -#define buffer_get_ret ssh_buffer_get_ret -#define buffer_get_short ssh_buffer_get_short -#define buffer_get_short_ret ssh_buffer_get_short_ret -#define buffer_get_string ssh_buffer_get_string -#define buffer_get_string_ptr ssh_buffer_get_string_ptr -#define buffer_get_string_ptr_ret ssh_buffer_get_string_ptr_ret -#define buffer_get_string_ret ssh_buffer_get_string_ret -#define buffer_init ssh_buffer_init -#define buffer_len ssh_buffer_len -#define buffer_ptr ssh_buffer_ptr -#define buffer_put_bignum ssh_buffer_put_bignum -#define buffer_put_bignum2 ssh_buffer_put_bignum2 -#define buffer_put_bignum2_from_string ssh_buffer_put_bignum2_from_string -#define buffer_put_bignum2_ret ssh_buffer_put_bignum2_ret -#define buffer_put_bignum_ret ssh_buffer_put_bignum_ret -#define buffer_put_char ssh_buffer_put_char -#define buffer_put_cstring ssh_buffer_put_cstring -#define buffer_put_ecpoint ssh_buffer_put_ecpoint -#define buffer_put_ecpoint_ret ssh_buffer_put_ecpoint_ret -#define buffer_put_int ssh_buffer_put_int -#define buffer_put_int64 ssh_buffer_put_int64 -#define buffer_put_short ssh_buffer_put_short -#define buffer_put_string ssh_buffer_put_string -#define buffer_uncompress ssh_buffer_uncompress -#define cert_free ssh_cert_free -#define chacha_encrypt_bytes ssh_chacha_encrypt_bytes -#define chacha_ivsetup ssh_chacha_ivsetup -#define chacha_keysetup ssh_chacha_keysetup -#define chachapoly_crypt ssh_chachapoly_crypt -#define chachapoly_get_length ssh_chachapoly_get_length -#define chachapoly_init ssh_chachapoly_init -#define chan_ibuf_empty ssh_chan_ibuf_empty -#define chan_is_dead ssh_chan_is_dead -#define chan_mark_dead ssh_chan_mark_dead -#define chan_obuf_empty ssh_chan_obuf_empty -#define chan_rcvd_eow ssh_chan_rcvd_eow -#define chan_rcvd_ieof ssh_chan_rcvd_ieof -#define chan_rcvd_oclose ssh_chan_rcvd_oclose -#define chan_read_failed ssh_chan_read_failed -#define chan_send_eof2 ssh_chan_send_eof2 -#define chan_send_oclose1 ssh_chan_send_oclose1 -#define chan_shutdown_read ssh_chan_shutdown_read -#define chan_shutdown_write ssh_chan_shutdown_write -#define chan_write_failed ssh_chan_write_failed -#define channel_add_adm_permitted_opens ssh_channel_add_adm_permitted_opens -#define channel_add_permitted_opens ssh_channel_add_permitted_opens -#define channel_after_select ssh_channel_after_select -#define channel_by_id ssh_channel_by_id -#define channel_cancel_cleanup ssh_channel_cancel_cleanup -#define channel_cancel_lport_listener ssh_channel_cancel_lport_listener -#define channel_cancel_rport_listener ssh_channel_cancel_rport_listener -#define channel_clear_adm_permitted_opens ssh_channel_clear_adm_permitted_opens -#define channel_clear_permitted_opens ssh_channel_clear_permitted_opens -#define channel_close_all ssh_channel_close_all -#define channel_close_fd ssh_channel_close_fd -#define channel_close_fds ssh_channel_close_fds -#define channel_connect_by_listen_address ssh_channel_connect_by_listen_address -#define channel_connect_stdio_fwd ssh_channel_connect_stdio_fwd -#define channel_connect_to ssh_channel_connect_to -#define channel_disable_adm_local_opens ssh_channel_disable_adm_local_opens -#define channel_find_open ssh_channel_find_open -#define channel_free ssh_channel_free -#define channel_free_all ssh_channel_free_all -#define channel_fwd_bind_addr ssh_channel_fwd_bind_addr -#define channel_handler ssh_channel_handler -#define channel_input_close ssh_channel_input_close -#define channel_input_close_confirmation ssh_channel_input_close_confirmation -#define channel_input_data ssh_channel_input_data -#define channel_input_extended_data ssh_channel_input_extended_data -#define channel_input_ieof ssh_channel_input_ieof -#define channel_input_oclose ssh_channel_input_oclose -#define channel_input_open_confirmation ssh_channel_input_open_confirmation -#define channel_input_open_failure ssh_channel_input_open_failure -#define channel_input_port_forward_request ssh_channel_input_port_forward_request -#define channel_input_port_open ssh_channel_input_port_open -#define channel_input_status_confirm ssh_channel_input_status_confirm -#define channel_input_window_adjust ssh_channel_input_window_adjust -#define channel_lookup ssh_channel_lookup -#define channel_new ssh_channel_new -#define channel_not_very_much_buffered_data ssh_channel_not_very_much_buffered_data -#define channel_open_message ssh_channel_open_message -#define channel_output_poll ssh_channel_output_poll -#define channel_permit_all_opens ssh_channel_permit_all_opens -#define channel_post_auth_listener ssh_channel_post_auth_listener -#define channel_post_connecting ssh_channel_post_connecting -#define channel_post_mux_client ssh_channel_post_mux_client -#define channel_post_mux_listener ssh_channel_post_mux_listener -#define channel_post_open ssh_channel_post_open -#define channel_post_output_drain_13 ssh_channel_post_output_drain_13 -#define channel_post_port_listener ssh_channel_post_port_listener -#define channel_post_x11_listener ssh_channel_post_x11_listener -#define channel_pre_connecting ssh_channel_pre_connecting -#define channel_pre_dynamic ssh_channel_pre_dynamic -#define channel_pre_input_draining ssh_channel_pre_input_draining -#define channel_pre_listener ssh_channel_pre_listener -#define channel_pre_mux_client ssh_channel_pre_mux_client -#define channel_pre_open ssh_channel_pre_open -#define channel_pre_open_13 ssh_channel_pre_open_13 -#define channel_pre_output_draining ssh_channel_pre_output_draining -#define channel_pre_x11_open ssh_channel_pre_x11_open -#define channel_pre_x11_open_13 ssh_channel_pre_x11_open_13 -#define channel_prepare_select ssh_channel_prepare_select -#define channel_print_adm_permitted_opens ssh_channel_print_adm_permitted_opens -#define channel_register_cleanup ssh_channel_register_cleanup -#define channel_register_fds ssh_channel_register_fds -#define channel_register_filter ssh_channel_register_filter -#define channel_register_open_confirm ssh_channel_register_open_confirm -#define channel_register_status_confirm ssh_channel_register_status_confirm -#define channel_request_remote_forwarding ssh_channel_request_remote_forwarding -#define channel_request_rforward_cancel ssh_channel_request_rforward_cancel -#define channel_request_start ssh_channel_request_start -#define channel_send_open ssh_channel_send_open -#define channel_send_window_changes ssh_channel_send_window_changes -#define channel_set_af ssh_channel_set_af -#define channel_set_fds ssh_channel_set_fds -#define channel_setup_fwd_listener ssh_channel_setup_fwd_listener -#define channel_setup_local_fwd_listener ssh_channel_setup_local_fwd_listener -#define channel_setup_remote_fwd_listener ssh_channel_setup_remote_fwd_listener -#define channel_still_open ssh_channel_still_open -#define channel_stop_listening ssh_channel_stop_listening -#define channel_update_permitted_opens ssh_channel_update_permitted_opens -#define check_crc ssh_check_crc -#define check_hostkeys_by_key_or_type ssh_check_hostkeys_by_key_or_type -#define check_key_in_hostkeys ssh_check_key_in_hostkeys -#define choose_dh ssh_choose_dh -#define choose_t ssh_choose_t -#define chop ssh_chop -#define cipher_alg_list ssh_cipher_alg_list -#define cipher_authlen ssh_cipher_authlen -#define cipher_blocksize ssh_cipher_blocksize -#define cipher_by_name ssh_cipher_by_name -#define cipher_by_number ssh_cipher_by_number -#define cipher_cleanup ssh_cipher_cleanup -#define cipher_crypt ssh_cipher_crypt -#define cipher_get_keycontext ssh_cipher_get_keycontext -#define cipher_get_keyiv ssh_cipher_get_keyiv -#define cipher_get_keyiv_len ssh_cipher_get_keyiv_len -#define cipher_get_length ssh_cipher_get_length -#define cipher_get_number ssh_cipher_get_number -#define cipher_init ssh_cipher_init -#define cipher_is_cbc ssh_cipher_is_cbc -#define cipher_ivlen ssh_cipher_ivlen -#define cipher_keylen ssh_cipher_keylen -#define cipher_mask_ssh1 ssh_cipher_mask_ssh1 -#define cipher_name ssh_cipher_name -#define cipher_number ssh_cipher_number -#define cipher_seclen ssh_cipher_seclen -#define cipher_set_key_string ssh_cipher_set_key_string -#define cipher_set_keycontext ssh_cipher_set_keycontext -#define cipher_set_keyiv ssh_cipher_set_keyiv -#define ciphers_valid ssh_ciphers_valid -#define cleanhostname ssh_cleanhostname -#define cleanup_exit ssh_cleanup_exit -#define clear_cached_addr ssh_clear_cached_addr -#define colon ssh_colon -#define compare ssh_compare -#define compare_gps ssh_compare_gps -#define compat_cipher_proposal ssh_compat_cipher_proposal -#define compat_datafellows ssh_compat_datafellows -#define compat_kex_proposal ssh_compat_kex_proposal -#define compat_pkalg_proposal ssh_compat_pkalg_proposal -#define connect_next ssh_connect_next -#define connect_to ssh_connect_to -#define convtime ssh_convtime -#define crypto_hash_sha512 ssh_crypto_hash_sha512 -#define crypto_hashblocks_sha512 ssh_crypto_hashblocks_sha512 -#define crypto_sign_ed25519 ssh_crypto_sign_ed25519 -#define crypto_sign_ed25519_keypair ssh_crypto_sign_ed25519_keypair -#define crypto_sign_ed25519_open ssh_crypto_sign_ed25519_open -#define crypto_sign_ed25519_ref_double_scalarmult_vartime ssh_crypto_sign_ed25519_ref_double_scalarmult_vartime -#define crypto_sign_ed25519_ref_fe25519_add ssh_crypto_sign_ed25519_ref_fe25519_add -#define crypto_sign_ed25519_ref_fe25519_cmov ssh_crypto_sign_ed25519_ref_fe25519_cmov -#define crypto_sign_ed25519_ref_fe25519_freeze ssh_crypto_sign_ed25519_ref_fe25519_freeze -#define crypto_sign_ed25519_ref_fe25519_getparity ssh_crypto_sign_ed25519_ref_fe25519_getparity -#define crypto_sign_ed25519_ref_fe25519_invert ssh_crypto_sign_ed25519_ref_fe25519_invert -#define crypto_sign_ed25519_ref_fe25519_iseq_vartime ssh_crypto_sign_ed25519_ref_fe25519_iseq_vartime -#define crypto_sign_ed25519_ref_fe25519_iszero ssh_crypto_sign_ed25519_ref_fe25519_iszero -#define crypto_sign_ed25519_ref_fe25519_mul ssh_crypto_sign_ed25519_ref_fe25519_mul -#define crypto_sign_ed25519_ref_fe25519_neg ssh_crypto_sign_ed25519_ref_fe25519_neg -#define crypto_sign_ed25519_ref_fe25519_pack ssh_crypto_sign_ed25519_ref_fe25519_pack -#define crypto_sign_ed25519_ref_fe25519_pow2523 ssh_crypto_sign_ed25519_ref_fe25519_pow2523 -#define crypto_sign_ed25519_ref_fe25519_setone ssh_crypto_sign_ed25519_ref_fe25519_setone -#define crypto_sign_ed25519_ref_fe25519_setzero ssh_crypto_sign_ed25519_ref_fe25519_setzero -#define crypto_sign_ed25519_ref_fe25519_square ssh_crypto_sign_ed25519_ref_fe25519_square -#define crypto_sign_ed25519_ref_fe25519_sub ssh_crypto_sign_ed25519_ref_fe25519_sub -#define crypto_sign_ed25519_ref_fe25519_unpack ssh_crypto_sign_ed25519_ref_fe25519_unpack -#define crypto_sign_ed25519_ref_isneutral_vartime ssh_crypto_sign_ed25519_ref_isneutral_vartime -#define crypto_sign_ed25519_ref_pack ssh_crypto_sign_ed25519_ref_pack -#define crypto_sign_ed25519_ref_sc25519_2interleave2 ssh_crypto_sign_ed25519_ref_sc25519_2interleave2 -#define crypto_sign_ed25519_ref_sc25519_add ssh_crypto_sign_ed25519_ref_sc25519_add -#define crypto_sign_ed25519_ref_sc25519_from32bytes ssh_crypto_sign_ed25519_ref_sc25519_from32bytes -#define crypto_sign_ed25519_ref_sc25519_from64bytes ssh_crypto_sign_ed25519_ref_sc25519_from64bytes -#define crypto_sign_ed25519_ref_sc25519_from_shortsc ssh_crypto_sign_ed25519_ref_sc25519_from_shortsc -#define crypto_sign_ed25519_ref_sc25519_isshort_vartime ssh_crypto_sign_ed25519_ref_sc25519_isshort_vartime -#define crypto_sign_ed25519_ref_sc25519_iszero_vartime ssh_crypto_sign_ed25519_ref_sc25519_iszero_vartime -#define crypto_sign_ed25519_ref_sc25519_lt_vartime ssh_crypto_sign_ed25519_ref_sc25519_lt_vartime -#define crypto_sign_ed25519_ref_sc25519_mul ssh_crypto_sign_ed25519_ref_sc25519_mul -#define crypto_sign_ed25519_ref_sc25519_mul_shortsc ssh_crypto_sign_ed25519_ref_sc25519_mul_shortsc -#define crypto_sign_ed25519_ref_sc25519_sub_nored ssh_crypto_sign_ed25519_ref_sc25519_sub_nored -#define crypto_sign_ed25519_ref_sc25519_to32bytes ssh_crypto_sign_ed25519_ref_sc25519_to32bytes -#define crypto_sign_ed25519_ref_sc25519_window3 ssh_crypto_sign_ed25519_ref_sc25519_window3 -#define crypto_sign_ed25519_ref_sc25519_window5 ssh_crypto_sign_ed25519_ref_sc25519_window5 -#define crypto_sign_ed25519_ref_scalarmult_base ssh_crypto_sign_ed25519_ref_scalarmult_base -#define crypto_sign_ed25519_ref_shortsc25519_from16bytes ssh_crypto_sign_ed25519_ref_shortsc25519_from16bytes -#define crypto_sign_ed25519_ref_unpackneg_vartime ssh_crypto_sign_ed25519_ref_unpackneg_vartime -#define crypto_verify_32 ssh_crypto_verify_32 -#define dbl_p1p1 ssh_dbl_p1p1 -#define debug ssh_debug -#define debug2 ssh_debug2 -#define debug3 ssh_debug3 -#define decode_reply ssh_decode_reply -#define deny_input_open ssh_deny_input_open -#define derive_ssh1_session_id ssh_derive_ssh1_session_id -#define detect_attack ssh_detect_attack -#define dh_estimate ssh_dh_estimate -#define dh_gen_key ssh_dh_gen_key -#define dh_new_group ssh_dh_new_group -#define dh_new_group1 ssh_dh_new_group1 -#define dh_new_group14 ssh_dh_new_group14 -#define dh_new_group_asc ssh_dh_new_group_asc -#define dh_pub_is_valid ssh_dh_pub_is_valid -#define dispatch_init ssh_dispatch_init -#define dispatch_protocol_error ssh_dispatch_protocol_error -#define dispatch_protocol_ignore ssh_dispatch_protocol_ignore -#define dispatch_range ssh_dispatch_range -#define dispatch_run ssh_dispatch_run -#define dispatch_set ssh_dispatch_set -#define do_log ssh_do_log -#define do_log2 ssh_do_log2 -#define dump_base64 ssh_dump_base64 -#define enable_compat13 ssh_enable_compat13 -#define enable_compat20 ssh_enable_compat20 -#define error ssh_error -#define evp_ssh1_3des ssh_evp_ssh1_3des -#define evp_ssh1_bf ssh_evp_ssh1_bf -#define explicit_bzero ssh_explicit_bzero -#define export_dns_rr ssh_export_dns_rr -#define fatal ssh_fatal -#define filter_proposal ssh_filter_proposal -#define fmt_scaled ssh_fmt_scaled -#define free_hostkeys ssh_free_hostkeys -#define freeargs ssh_freeargs -#define freerrset ssh_freerrset -#define gen_candidates ssh_gen_candidates -#define get_canonical_hostname ssh_get_canonical_hostname -#define get_local_ipaddr ssh_get_local_ipaddr -#define get_local_name ssh_get_local_name -#define get_local_port ssh_get_local_port -#define get_peer_ipaddr ssh_get_peer_ipaddr -#define get_peer_port ssh_get_peer_port -#define get_remote_ipaddr ssh_get_remote_ipaddr -#define get_remote_name_or_ip ssh_get_remote_name_or_ip -#define get_remote_port ssh_get_remote_port -#define get_sock_port ssh_get_sock_port -#define get_socket_address ssh_get_socket_address -#define get_u16 ssh_get_u16 -#define get_u32 ssh_get_u32 -#define get_u64 ssh_get_u64 -#define getrrsetbyname ssh_getrrsetbyname -#define glob ssh_glob -#define glob0 ssh_glob0 -#define glob2 ssh_glob2 -#define globexp1 ssh_globexp1 -#define globextend ssh_globextend -#define globfree ssh_globfree -#define host_hash ssh_host_hash -#define hostfile_read_key ssh_hostfile_read_key -#define hpdelim ssh_hpdelim -#define init_hostkeys ssh_init_hostkeys -#define iptos2str ssh_iptos2str -#define ipv64_normalise_mapped ssh_ipv64_normalise_mapped -#define is_key_revoked ssh_is_key_revoked -#define kex_alg_by_name ssh_kex_alg_by_name -#define kex_alg_list ssh_kex_alg_list -#define kex_buf2prop ssh_kex_buf2prop -#define kex_c25519_hash ssh_kex_c25519_hash -#define kex_derive_keys ssh_kex_derive_keys -#define kex_derive_keys_bn ssh_kex_derive_keys_bn -#define kex_dh_hash ssh_kex_dh_hash -#define kex_ecdh_hash ssh_kex_ecdh_hash -#define kex_finish ssh_kex_finish -#define kex_get_newkeys ssh_kex_get_newkeys -#define kex_input_kexinit ssh_kex_input_kexinit -#define kex_names_valid ssh_kex_names_valid -#define kex_prop_free ssh_kex_prop_free -#define kex_protocol_error ssh_kex_protocol_error -#define kex_send_kexinit ssh_kex_send_kexinit -#define kex_setup ssh_kex_setup -#define kexc25519_client ssh_kexc25519_client -#define kexc25519_keygen ssh_kexc25519_keygen -#define kexc25519_shared_key ssh_kexc25519_shared_key -#define kexdh_client ssh_kexdh_client -#define kexecdh_client ssh_kexecdh_client -#define kexgex_client ssh_kexgex_client -#define kexgex_hash ssh_kexgex_hash -#define key_add_private ssh_key_add_private -#define key_alg_list ssh_key_alg_list -#define key_cert_check_authority ssh_key_cert_check_authority -#define key_cert_copy ssh_key_cert_copy -#define key_cert_is_legacy ssh_key_cert_is_legacy -#define key_cert_type ssh_key_cert_type -#define key_certify ssh_key_certify -#define key_curve_name_to_nid ssh_key_curve_name_to_nid -#define key_curve_nid_to_bits ssh_key_curve_nid_to_bits -#define key_curve_nid_to_name ssh_key_curve_nid_to_name -#define key_demote ssh_key_demote -#define key_drop_cert ssh_key_drop_cert -#define key_ec_nid_to_hash_alg ssh_key_ec_nid_to_hash_alg -#define key_ec_validate_private ssh_key_ec_validate_private -#define key_ec_validate_public ssh_key_ec_validate_public -#define key_ecdsa_bits_to_nid ssh_key_ecdsa_bits_to_nid -#define key_ecdsa_key_to_nid ssh_key_ecdsa_key_to_nid -#define key_ecdsa_nid_from_name ssh_key_ecdsa_nid_from_name -#define key_equal ssh_key_equal -#define key_equal_public ssh_key_equal_public -#define key_fingerprint ssh_key_fingerprint -#define key_fingerprint_raw ssh_key_fingerprint_raw -#define key_free ssh_key_free -#define key_from_blob ssh_key_from_blob -#define key_from_blob2 ssh_key_from_blob2 -#define key_from_private ssh_key_from_private -#define key_generate ssh_key_generate -#define key_in_file ssh_key_in_file -#define key_is_cert ssh_key_is_cert -#define key_load_cert ssh_key_load_cert -#define key_load_file ssh_key_load_file -#define key_load_private ssh_key_load_private -#define key_load_private_cert ssh_key_load_private_cert -#define key_load_private_pem ssh_key_load_private_pem -#define key_load_private_type ssh_key_load_private_type -#define key_load_public ssh_key_load_public -#define key_load_public_type ssh_key_load_public_type -#define key_names_valid2 ssh_key_names_valid2 -#define key_new ssh_key_new -#define key_new_private ssh_key_new_private -#define key_parse_private ssh_key_parse_private -#define key_parse_private2 ssh_key_parse_private2 -#define key_parse_private_pem ssh_key_parse_private_pem -#define key_parse_private_type ssh_key_parse_private_type -#define key_parse_public_rsa1 ssh_key_parse_public_rsa1 -#define key_perm_ok ssh_key_perm_ok -#define key_private_deserialize ssh_key_private_deserialize -#define key_private_serialize ssh_key_private_serialize -#define key_private_to_blob2 ssh_key_private_to_blob2 -#define key_read ssh_key_read -#define key_save_private ssh_key_save_private -#define key_sign ssh_key_sign -#define key_size ssh_key_size -#define key_ssh_name ssh_key_ssh_name -#define key_ssh_name_plain ssh_key_ssh_name_plain -#define key_to_blob ssh_key_to_blob -#define key_to_certified ssh_key_to_certified -#define key_try_load_public ssh_key_try_load_public -#define key_type ssh_key_type -#define key_type_from_name ssh_key_type_from_name -#define key_type_is_cert ssh_key_type_is_cert -#define key_type_plain ssh_key_type_plain -#define key_verify ssh_key_verify -#define key_write ssh_key_write -#define load_hostkeys ssh_load_hostkeys -#define log_change_level ssh_log_change_level -#define log_facility_name ssh_log_facility_name -#define log_facility_number ssh_log_facility_number -#define log_init ssh_log_init -#define log_is_on_stderr ssh_log_is_on_stderr -#define log_level_name ssh_log_level_name -#define log_level_number ssh_log_level_number -#define log_redirect_stderr_to ssh_log_redirect_stderr_to -#define logit ssh_logit -#define lookup_key_in_hostkeys_by_type ssh_lookup_key_in_hostkeys_by_type -#define lowercase ssh_lowercase -#define mac_alg_list ssh_mac_alg_list -#define mac_clear ssh_mac_clear -#define mac_compute ssh_mac_compute -#define mac_init ssh_mac_init -#define mac_setup ssh_mac_setup -#define mac_valid ssh_mac_valid -#define match ssh_match -#define match_host_and_ip ssh_match_host_and_ip -#define match_hostname ssh_match_hostname -#define match_list ssh_match_list -#define match_pattern ssh_match_pattern -#define match_pattern_list ssh_match_pattern_list -#define match_user ssh_match_user -#define mktemp_proto ssh_mktemp_proto -#define mm_receive_fd ssh_mm_receive_fd -#define mm_send_fd ssh_mm_send_fd -#define monotime ssh_monotime -#define ms_subtract_diff ssh_ms_subtract_diff -#define ms_to_timeval ssh_ms_to_timeval -#define mult ssh_mult -#define mysignal ssh_mysignal -#define nh_aux ssh_nh_aux -#define nh_final ssh_nh_final -#define packet_add_padding ssh_packet_add_padding -#define packet_backup_state ssh_packet_backup_state -#define packet_close ssh_packet_close -#define packet_connection_is_on_socket ssh_packet_connection_is_on_socket -#define packet_disconnect ssh_packet_disconnect -#define packet_enable_delayed_compress ssh_packet_enable_delayed_compress -#define packet_get_bignum ssh_packet_get_bignum -#define packet_get_bignum2 ssh_packet_get_bignum2 -#define packet_get_char ssh_packet_get_char -#define packet_get_connection_in ssh_packet_get_connection_in -#define packet_get_connection_out ssh_packet_get_connection_out -#define packet_get_cstring ssh_packet_get_cstring -#define packet_get_ecpoint ssh_packet_get_ecpoint -#define packet_get_encryption_key ssh_packet_get_encryption_key -#define packet_get_input ssh_packet_get_input -#define packet_get_int ssh_packet_get_int -#define packet_get_int64 ssh_packet_get_int64 -#define packet_get_keycontext ssh_packet_get_keycontext -#define packet_get_keyiv ssh_packet_get_keyiv -#define packet_get_keyiv_len ssh_packet_get_keyiv_len -#define packet_get_maxsize ssh_packet_get_maxsize -#define packet_get_newkeys ssh_packet_get_newkeys -#define packet_get_output ssh_packet_get_output -#define packet_get_protocol_flags ssh_packet_get_protocol_flags -#define packet_get_raw ssh_packet_get_raw -#define packet_get_rekey_timeout ssh_packet_get_rekey_timeout -#define packet_get_ssh1_cipher ssh_packet_get_ssh1_cipher -#define packet_get_state ssh_packet_get_state -#define packet_get_string ssh_packet_get_string -#define packet_get_string_ptr ssh_packet_get_string_ptr -#define packet_have_data_to_write ssh_packet_have_data_to_write -#define packet_inc_alive_timeouts ssh_packet_inc_alive_timeouts -#define packet_is_interactive ssh_packet_is_interactive -#define packet_need_rekeying ssh_packet_need_rekeying -#define packet_not_very_much_data_to_write ssh_packet_not_very_much_data_to_write -#define packet_process_incoming ssh_packet_process_incoming -#define packet_put_bignum ssh_packet_put_bignum -#define packet_put_bignum2 ssh_packet_put_bignum2 -#define packet_put_char ssh_packet_put_char -#define packet_put_cstring ssh_packet_put_cstring -#define packet_put_ecpoint ssh_packet_put_ecpoint -#define packet_put_int ssh_packet_put_int -#define packet_put_int64 ssh_packet_put_int64 -#define packet_put_raw ssh_packet_put_raw -#define packet_put_string ssh_packet_put_string -#define packet_read ssh_packet_read -#define packet_read_expect ssh_packet_read_expect -#define packet_read_poll_seqnr ssh_packet_read_poll_seqnr -#define packet_read_seqnr ssh_packet_read_seqnr -#define packet_remaining ssh_packet_remaining -#define packet_restore_state ssh_packet_restore_state -#define packet_send ssh_packet_send -#define packet_send2_wrapped ssh_packet_send2_wrapped -#define packet_send_debug ssh_packet_send_debug -#define packet_send_ignore ssh_packet_send_ignore -#define packet_set_alive_timeouts ssh_packet_set_alive_timeouts -#define packet_set_authenticated ssh_packet_set_authenticated -#define packet_set_connection ssh_packet_set_connection -#define packet_set_encryption_key ssh_packet_set_encryption_key -#define packet_set_interactive ssh_packet_set_interactive -#define packet_set_iv ssh_packet_set_iv -#define packet_set_keycontext ssh_packet_set_keycontext -#define packet_set_maxsize ssh_packet_set_maxsize -#define packet_set_nonblocking ssh_packet_set_nonblocking -#define packet_set_protocol_flags ssh_packet_set_protocol_flags -#define packet_set_rekey_limits ssh_packet_set_rekey_limits -#define packet_set_server ssh_packet_set_server -#define packet_set_state ssh_packet_set_state -#define packet_set_timeout ssh_packet_set_timeout -#define packet_start ssh_packet_start -#define packet_start_compression ssh_packet_start_compression -#define packet_start_discard ssh_packet_start_discard -#define packet_stop_discard ssh_packet_stop_discard -#define packet_write_poll ssh_packet_write_poll -#define packet_write_wait ssh_packet_write_wait -#define parse_ipqos ssh_parse_ipqos -#define parse_prime ssh_parse_prime -#define percent_expand ssh_percent_expand -#define permanently_drop_suid ssh_permanently_drop_suid -#define permanently_set_uid ssh_permanently_set_uid -#define permitopen_port ssh_permitopen_port -#define pkcs11_add_provider ssh_pkcs11_add_provider -#define pkcs11_del_provider ssh_pkcs11_del_provider -#define pkcs11_fetch_keys_filter ssh_pkcs11_fetch_keys_filter -#define pkcs11_find ssh_pkcs11_find -#define pkcs11_init ssh_pkcs11_init -#define pkcs11_provider_finalize ssh_pkcs11_provider_finalize -#define pkcs11_provider_unref ssh_pkcs11_provider_unref -#define pkcs11_rsa_finish ssh_pkcs11_rsa_finish -#define pkcs11_rsa_private_decrypt ssh_pkcs11_rsa_private_decrypt -#define pkcs11_rsa_private_encrypt ssh_pkcs11_rsa_private_encrypt -#define pkcs11_terminate ssh_pkcs11_terminate -#define plain_key_blob ssh_plain_key_blob -#define poly1305_auth ssh_poly1305_auth -#define poly64 ssh_poly64 -#define poly_hash ssh_poly_hash -#define port_open_helper ssh_port_open_helper -#define prime_test ssh_prime_test -#define proto_spec ssh_proto_spec -#define put_host_port ssh_put_host_port -#define put_u16 ssh_put_u16 -#define put_u32 ssh_put_u32 -#define put_u64 ssh_put_u64 -#define pwcopy ssh_pwcopy -#define qfileout ssh_qfileout -#define read_keyfile_line ssh_read_keyfile_line -#define read_mux ssh_read_mux -#define read_passphrase ssh_read_passphrase -#define reduce_add_sub ssh_reduce_add_sub -#define refresh_progress_meter ssh_refresh_progress_meter -#define replacearg ssh_replacearg -#define restore_uid ssh_restore_uid -#define revoke_blob ssh_revoke_blob -#define revoked_blob_tree_RB_REMOVE ssh_revoked_blob_tree_RB_REMOVE -#define revoked_certs_for_ca_key ssh_revoked_certs_for_ca_key -#define revoked_serial_tree_RB_REMOVE ssh_revoked_serial_tree_RB_REMOVE -#define rijndaelKeySetupEnc ssh_rijndaelKeySetupEnc -#define rijndael_decrypt ssh_rijndael_decrypt -#define rijndael_encrypt ssh_rijndael_encrypt -#define rijndael_set_key ssh_rijndael_set_key -#define rsa_generate_additional_parameters ssh_rsa_generate_additional_parameters -#define rsa_private_decrypt ssh_rsa_private_decrypt -#define rsa_public_encrypt ssh_rsa_public_encrypt -#define sanitise_stdfd ssh_sanitise_stdfd -#define scan_scaled ssh_scan_scaled -#define seed_rng ssh_seed_rng -#define set_log_handler ssh_set_log_handler -#define set_newkeys ssh_set_newkeys -#define set_nodelay ssh_set_nodelay -#define set_nonblock ssh_set_nonblock -#define shadow_pw ssh_shadow_pw -#define sieve_large ssh_sieve_large -#define sig_winch ssh_sig_winch -#define sigdie ssh_sigdie -#define sock_set_v6only ssh_sock_set_v6only -#define square ssh_square -#define ssh1_3des_cbc ssh_ssh1_3des_cbc -#define ssh1_3des_cleanup ssh_ssh1_3des_cleanup -#define ssh1_3des_init ssh_ssh1_3des_init -#define ssh1_3des_iv ssh_ssh1_3des_iv -#define start_progress_meter ssh_start_progress_meter -#define stop_progress_meter ssh_stop_progress_meter -#define strdelim ssh_strdelim -#define strnvis ssh_strnvis -#define strvis ssh_strvis -#define strvisx ssh_strvisx -#define sys_tun_open ssh_sys_tun_open -#define temporarily_use_uid ssh_temporarily_use_uid -#define tilde_expand_filename ssh_tilde_expand_filename -#define timingsafe_bcmp ssh_timingsafe_bcmp -#define to_blob ssh_to_blob -#define tohex ssh_tohex -#define tty_make_modes ssh_tty_make_modes -#define tty_parse_modes ssh_tty_parse_modes -#define tun_open ssh_tun_open -#define umac128_delete ssh_umac128_delete -#define umac128_final ssh_umac128_final -#define umac128_new ssh_umac128_new -#define umac128_update ssh_umac128_update -#define umac_delete ssh_umac_delete -#define umac_final ssh_umac_final -#define umac_new ssh_umac_new -#define umac_update ssh_umac_update -#define unset_nonblock ssh_unset_nonblock -#define update_progress_meter ssh_update_progress_meter -#define uudecode ssh_uudecode -#define uuencode ssh_uuencode -#define verbose ssh_verbose -#define verify_host_key_dns ssh_verify_host_key_dns -#define vis ssh_vis -#define x11_connect_display ssh_x11_connect_display -#define x11_create_display_inet ssh_x11_create_display_inet -#define x11_input_open ssh_x11_input_open -#define x11_open_helper ssh_x11_open_helper -#define x11_request_forwarding_with_spoofing ssh_x11_request_forwarding_with_spoofing -#define xasprintf ssh_xasprintf -#define xcalloc ssh_xcalloc -#define xcrypt ssh_xcrypt -#define xmalloc ssh_xmalloc -#define xmmap ssh_xmmap -#define xrealloc ssh_xrealloc -#define xstrdup ssh_xstrdup +#define Blowfish_decipher Fssh_Blowfish_decipher +#define Blowfish_encipher Fssh_Blowfish_encipher +#define Blowfish_expand0state Fssh_Blowfish_expand0state +#define Blowfish_expandstate Fssh_Blowfish_expandstate +#define Blowfish_initstate Fssh_Blowfish_initstate +#define Blowfish_stream2word Fssh_Blowfish_stream2word +#define _ssh_compat_realpath Fssh__ssh_compat_realpath +#define _ssh_exchange_banner Fssh__ssh_exchange_banner +#define _ssh_host_key_sign Fssh__ssh_host_key_sign +#define _ssh_host_private_key Fssh__ssh_host_private_key +#define _ssh_host_public_key Fssh__ssh_host_public_key +#define _ssh_order_hostkeyalgs Fssh__ssh_order_hostkeyalgs +#define _ssh_read_banner Fssh__ssh_read_banner +#define _ssh_send_banner Fssh__ssh_send_banner +#define _ssh_verify_host_key Fssh__ssh_verify_host_key +#define a2port Fssh_a2port +#define a2tun Fssh_a2tun +#define add_host_to_hostfile Fssh_add_host_to_hostfile +#define add_p1p1 Fssh_add_p1p1 +#define addargs Fssh_addargs +#define addr_match_cidr_list Fssh_addr_match_cidr_list +#define addr_match_list Fssh_addr_match_list +#define addr_netmatch Fssh_addr_netmatch +#define addr_pton Fssh_addr_pton +#define addr_pton_cidr Fssh_addr_pton_cidr +#define ask_permission Fssh_ask_permission +#define atomicio Fssh_atomicio +#define atomicio6 Fssh_atomicio6 +#define atomiciov Fssh_atomiciov +#define atomiciov6 Fssh_atomiciov6 +#define auth_request_forwarding Fssh_auth_request_forwarding +#define bandwidth_limit Fssh_bandwidth_limit +#define bandwidth_limit_init Fssh_bandwidth_limit_init +#define barrett_reduce Fssh_barrett_reduce +#define bcrypt_hash Fssh_bcrypt_hash +#define bcrypt_pbkdf Fssh_bcrypt_pbkdf +#define bf_ssh1_cipher Fssh_bf_ssh1_cipher +#define bitmap_clear_bit Fssh_bitmap_clear_bit +#define bitmap_free Fssh_bitmap_free +#define bitmap_from_string Fssh_bitmap_from_string +#define bitmap_nbits Fssh_bitmap_nbits +#define bitmap_nbytes Fssh_bitmap_nbytes +#define bitmap_new Fssh_bitmap_new +#define bitmap_set_bit Fssh_bitmap_set_bit +#define bitmap_test_bit Fssh_bitmap_test_bit +#define bitmap_to_string Fssh_bitmap_to_string +#define bitmap_zero Fssh_bitmap_zero +#define blf_cbc_decrypt Fssh_blf_cbc_decrypt +#define blf_cbc_encrypt Fssh_blf_cbc_encrypt +#define blf_dec Fssh_blf_dec +#define blf_ecb_decrypt Fssh_blf_ecb_decrypt +#define blf_ecb_encrypt Fssh_blf_ecb_encrypt +#define blf_enc Fssh_blf_enc +#define blf_key Fssh_blf_key +#define buffer_append Fssh_buffer_append +#define buffer_append_space Fssh_buffer_append_space +#define buffer_check_alloc Fssh_buffer_check_alloc +#define buffer_consume Fssh_buffer_consume +#define buffer_consume_end Fssh_buffer_consume_end +#define buffer_consume_end_ret Fssh_buffer_consume_end_ret +#define buffer_consume_ret Fssh_buffer_consume_ret +#define buffer_get Fssh_buffer_get +#define buffer_get_bignum Fssh_buffer_get_bignum +#define buffer_get_bignum2 Fssh_buffer_get_bignum2 +#define buffer_get_bignum2_ret Fssh_buffer_get_bignum2_ret +#define buffer_get_bignum_ret Fssh_buffer_get_bignum_ret +#define buffer_get_char Fssh_buffer_get_char +#define buffer_get_char_ret Fssh_buffer_get_char_ret +#define buffer_get_cstring Fssh_buffer_get_cstring +#define buffer_get_cstring_ret Fssh_buffer_get_cstring_ret +#define buffer_get_ecpoint Fssh_buffer_get_ecpoint +#define buffer_get_ecpoint_ret Fssh_buffer_get_ecpoint_ret +#define buffer_get_int Fssh_buffer_get_int +#define buffer_get_int64 Fssh_buffer_get_int64 +#define buffer_get_int64_ret Fssh_buffer_get_int64_ret +#define buffer_get_int_ret Fssh_buffer_get_int_ret +#define buffer_get_ret Fssh_buffer_get_ret +#define buffer_get_short Fssh_buffer_get_short +#define buffer_get_short_ret Fssh_buffer_get_short_ret +#define buffer_get_string Fssh_buffer_get_string +#define buffer_get_string_ptr Fssh_buffer_get_string_ptr +#define buffer_get_string_ptr_ret Fssh_buffer_get_string_ptr_ret +#define buffer_get_string_ret Fssh_buffer_get_string_ret +#define buffer_put_bignum Fssh_buffer_put_bignum +#define buffer_put_bignum2 Fssh_buffer_put_bignum2 +#define buffer_put_bignum2_from_string Fssh_buffer_put_bignum2_from_string +#define buffer_put_bignum2_ret Fssh_buffer_put_bignum2_ret +#define buffer_put_bignum_ret Fssh_buffer_put_bignum_ret +#define buffer_put_char Fssh_buffer_put_char +#define buffer_put_cstring Fssh_buffer_put_cstring +#define buffer_put_ecpoint Fssh_buffer_put_ecpoint +#define buffer_put_ecpoint_ret Fssh_buffer_put_ecpoint_ret +#define buffer_put_int Fssh_buffer_put_int +#define buffer_put_int64 Fssh_buffer_put_int64 +#define buffer_put_short Fssh_buffer_put_short +#define buffer_put_string Fssh_buffer_put_string +#define cert_free Fssh_cert_free +#define cert_new Fssh_cert_new +#define chacha_encrypt_bytes Fssh_chacha_encrypt_bytes +#define chacha_ivsetup Fssh_chacha_ivsetup +#define chacha_keysetup Fssh_chacha_keysetup +#define chachapoly_crypt Fssh_chachapoly_crypt +#define chachapoly_get_length Fssh_chachapoly_get_length +#define chachapoly_init Fssh_chachapoly_init +#define chan_ibuf_empty Fssh_chan_ibuf_empty +#define chan_is_dead Fssh_chan_is_dead +#define chan_mark_dead Fssh_chan_mark_dead +#define chan_obuf_empty Fssh_chan_obuf_empty +#define chan_rcvd_eow Fssh_chan_rcvd_eow +#define chan_rcvd_ieof Fssh_chan_rcvd_ieof +#define chan_rcvd_oclose Fssh_chan_rcvd_oclose +#define chan_read_failed Fssh_chan_read_failed +#define chan_send_eof2 Fssh_chan_send_eof2 +#define chan_send_ieof1 Fssh_chan_send_ieof1 +#define chan_send_oclose1 Fssh_chan_send_oclose1 +#define chan_shutdown_read Fssh_chan_shutdown_read +#define chan_shutdown_write Fssh_chan_shutdown_write +#define chan_write_failed Fssh_chan_write_failed +#define channel_add_adm_permitted_opens Fssh_channel_add_adm_permitted_opens +#define channel_add_permitted_opens Fssh_channel_add_permitted_opens +#define channel_after_select Fssh_channel_after_select +#define channel_by_id Fssh_channel_by_id +#define channel_cancel_cleanup Fssh_channel_cancel_cleanup +#define channel_cancel_lport_listener Fssh_channel_cancel_lport_listener +#define channel_cancel_rport_listener Fssh_channel_cancel_rport_listener +#define channel_clear_adm_permitted_opens Fssh_channel_clear_adm_permitted_opens +#define channel_clear_permitted_opens Fssh_channel_clear_permitted_opens +#define channel_close_all Fssh_channel_close_all +#define channel_close_fd Fssh_channel_close_fd +#define channel_close_fds Fssh_channel_close_fds +#define channel_connect_by_listen_address Fssh_channel_connect_by_listen_address +#define channel_connect_by_listen_path Fssh_channel_connect_by_listen_path +#define channel_connect_stdio_fwd Fssh_channel_connect_stdio_fwd +#define channel_connect_to_path Fssh_channel_connect_to_path +#define channel_connect_to_port Fssh_channel_connect_to_port +#define channel_disable_adm_local_opens Fssh_channel_disable_adm_local_opens +#define channel_find_open Fssh_channel_find_open +#define channel_free Fssh_channel_free +#define channel_free_all Fssh_channel_free_all +#define channel_fwd_bind_addr Fssh_channel_fwd_bind_addr +#define channel_handler Fssh_channel_handler +#define channel_input_close Fssh_channel_input_close +#define channel_input_close_confirmation Fssh_channel_input_close_confirmation +#define channel_input_data Fssh_channel_input_data +#define channel_input_extended_data Fssh_channel_input_extended_data +#define channel_input_ieof Fssh_channel_input_ieof +#define channel_input_oclose Fssh_channel_input_oclose +#define channel_input_open_confirmation Fssh_channel_input_open_confirmation +#define channel_input_open_failure Fssh_channel_input_open_failure +#define channel_input_port_forward_request Fssh_channel_input_port_forward_request +#define channel_input_port_open Fssh_channel_input_port_open +#define channel_input_status_confirm Fssh_channel_input_status_confirm +#define channel_input_window_adjust Fssh_channel_input_window_adjust +#define channel_lookup Fssh_channel_lookup +#define channel_new Fssh_channel_new +#define channel_not_very_much_buffered_data Fssh_channel_not_very_much_buffered_data +#define channel_open_message Fssh_channel_open_message +#define channel_output_poll Fssh_channel_output_poll +#define channel_permit_all_opens Fssh_channel_permit_all_opens +#define channel_post_auth_listener Fssh_channel_post_auth_listener +#define channel_post_connecting Fssh_channel_post_connecting +#define channel_post_mux_client Fssh_channel_post_mux_client +#define channel_post_mux_listener Fssh_channel_post_mux_listener +#define channel_post_open Fssh_channel_post_open +#define channel_post_output_drain_13 Fssh_channel_post_output_drain_13 +#define channel_post_port_listener Fssh_channel_post_port_listener +#define channel_post_x11_listener Fssh_channel_post_x11_listener +#define channel_pre_connecting Fssh_channel_pre_connecting +#define channel_pre_dynamic Fssh_channel_pre_dynamic +#define channel_pre_input_draining Fssh_channel_pre_input_draining +#define channel_pre_listener Fssh_channel_pre_listener +#define channel_pre_mux_client Fssh_channel_pre_mux_client +#define channel_pre_open Fssh_channel_pre_open +#define channel_pre_open_13 Fssh_channel_pre_open_13 +#define channel_pre_output_draining Fssh_channel_pre_output_draining +#define channel_pre_x11_open Fssh_channel_pre_x11_open +#define channel_pre_x11_open_13 Fssh_channel_pre_x11_open_13 +#define channel_prepare_select Fssh_channel_prepare_select +#define channel_print_adm_permitted_opens Fssh_channel_print_adm_permitted_opens +#define channel_register_cleanup Fssh_channel_register_cleanup +#define channel_register_fds Fssh_channel_register_fds +#define channel_register_filter Fssh_channel_register_filter +#define channel_register_open_confirm Fssh_channel_register_open_confirm +#define channel_register_status_confirm Fssh_channel_register_status_confirm +#define channel_request_remote_forwarding Fssh_channel_request_remote_forwarding +#define channel_request_rforward_cancel Fssh_channel_request_rforward_cancel +#define channel_request_start Fssh_channel_request_start +#define channel_send_open Fssh_channel_send_open +#define channel_send_window_changes Fssh_channel_send_window_changes +#define channel_set_af Fssh_channel_set_af +#define channel_set_fds Fssh_channel_set_fds +#define channel_set_x11_refuse_time Fssh_channel_set_x11_refuse_time +#define channel_setup_fwd_listener_streamlocal Fssh_channel_setup_fwd_listener_streamlocal +#define channel_setup_fwd_listener_tcpip Fssh_channel_setup_fwd_listener_tcpip +#define channel_setup_local_fwd_listener Fssh_channel_setup_local_fwd_listener +#define channel_setup_remote_fwd_listener Fssh_channel_setup_remote_fwd_listener +#define channel_still_open Fssh_channel_still_open +#define channel_stop_listening Fssh_channel_stop_listening +#define channel_update_permitted_opens Fssh_channel_update_permitted_opens +#define check_crc Fssh_check_crc +#define check_hostkeys_by_key_or_type Fssh_check_hostkeys_by_key_or_type +#define check_key_in_hostkeys Fssh_check_key_in_hostkeys +#define choose_dh Fssh_choose_dh +#define choose_t Fssh_choose_t +#define chop Fssh_chop +#define cipher_alg_list Fssh_cipher_alg_list +#define cipher_authlen Fssh_cipher_authlen +#define cipher_blocksize Fssh_cipher_blocksize +#define cipher_by_name Fssh_cipher_by_name +#define cipher_by_number Fssh_cipher_by_number +#define cipher_cleanup Fssh_cipher_cleanup +#define cipher_crypt Fssh_cipher_crypt +#define cipher_get_keycontext Fssh_cipher_get_keycontext +#define cipher_get_keyiv Fssh_cipher_get_keyiv +#define cipher_get_keyiv_len Fssh_cipher_get_keyiv_len +#define cipher_get_length Fssh_cipher_get_length +#define cipher_get_number Fssh_cipher_get_number +#define cipher_init Fssh_cipher_init +#define cipher_is_cbc Fssh_cipher_is_cbc +#define cipher_ivlen Fssh_cipher_ivlen +#define cipher_keylen Fssh_cipher_keylen +#define cipher_mask_ssh1 Fssh_cipher_mask_ssh1 +#define cipher_name Fssh_cipher_name +#define cipher_number Fssh_cipher_number +#define cipher_seclen Fssh_cipher_seclen +#define cipher_set_key_string Fssh_cipher_set_key_string +#define cipher_set_keycontext Fssh_cipher_set_keycontext +#define cipher_set_keyiv Fssh_cipher_set_keyiv +#define cipher_warning_message Fssh_cipher_warning_message +#define ciphers_valid Fssh_ciphers_valid +#define cleanhostname Fssh_cleanhostname +#define cleanup_exit Fssh_cleanup_exit +#define clear_cached_addr Fssh_clear_cached_addr +#define colon Fssh_colon +#define compare Fssh_compare +#define compare_gps Fssh_compare_gps +#define compat_cipher_proposal Fssh_compat_cipher_proposal +#define compat_datafellows Fssh_compat_datafellows +#define compat_kex_proposal Fssh_compat_kex_proposal +#define compat_pkalg_proposal Fssh_compat_pkalg_proposal +#define compress_buffer Fssh_compress_buffer +#define connect_next Fssh_connect_next +#define connect_to Fssh_connect_to +#define convtime Fssh_convtime +#define crypto_hash_sha512 Fssh_crypto_hash_sha512 +#define crypto_hashblocks_sha512 Fssh_crypto_hashblocks_sha512 +#define crypto_scalarmult_curve25519 Fssh_crypto_scalarmult_curve25519 +#define crypto_sign_ed25519 Fssh_crypto_sign_ed25519 +#define crypto_sign_ed25519_keypair Fssh_crypto_sign_ed25519_keypair +#define crypto_sign_ed25519_open Fssh_crypto_sign_ed25519_open +#define crypto_sign_ed25519_ref_double_scalarmult_vartime Fssh_crypto_sign_ed25519_ref_double_scalarmult_vartime +#define crypto_sign_ed25519_ref_fe25519_add Fssh_crypto_sign_ed25519_ref_fe25519_add +#define crypto_sign_ed25519_ref_fe25519_cmov Fssh_crypto_sign_ed25519_ref_fe25519_cmov +#define crypto_sign_ed25519_ref_fe25519_freeze Fssh_crypto_sign_ed25519_ref_fe25519_freeze +#define crypto_sign_ed25519_ref_fe25519_getparity Fssh_crypto_sign_ed25519_ref_fe25519_getparity +#define crypto_sign_ed25519_ref_fe25519_invert Fssh_crypto_sign_ed25519_ref_fe25519_invert +#define crypto_sign_ed25519_ref_fe25519_iseq_vartime Fssh_crypto_sign_ed25519_ref_fe25519_iseq_vartime +#define crypto_sign_ed25519_ref_fe25519_iszero Fssh_crypto_sign_ed25519_ref_fe25519_iszero +#define crypto_sign_ed25519_ref_fe25519_mul Fssh_crypto_sign_ed25519_ref_fe25519_mul +#define crypto_sign_ed25519_ref_fe25519_neg Fssh_crypto_sign_ed25519_ref_fe25519_neg +#define crypto_sign_ed25519_ref_fe25519_pack Fssh_crypto_sign_ed25519_ref_fe25519_pack +#define crypto_sign_ed25519_ref_fe25519_pow2523 Fssh_crypto_sign_ed25519_ref_fe25519_pow2523 +#define crypto_sign_ed25519_ref_fe25519_setone Fssh_crypto_sign_ed25519_ref_fe25519_setone +#define crypto_sign_ed25519_ref_fe25519_setzero Fssh_crypto_sign_ed25519_ref_fe25519_setzero +#define crypto_sign_ed25519_ref_fe25519_square Fssh_crypto_sign_ed25519_ref_fe25519_square +#define crypto_sign_ed25519_ref_fe25519_sub Fssh_crypto_sign_ed25519_ref_fe25519_sub +#define crypto_sign_ed25519_ref_fe25519_unpack Fssh_crypto_sign_ed25519_ref_fe25519_unpack +#define crypto_sign_ed25519_ref_isneutral_vartime Fssh_crypto_sign_ed25519_ref_isneutral_vartime +#define crypto_sign_ed25519_ref_pack Fssh_crypto_sign_ed25519_ref_pack +#define crypto_sign_ed25519_ref_sc25519_2interleave2 Fssh_crypto_sign_ed25519_ref_sc25519_2interleave2 +#define crypto_sign_ed25519_ref_sc25519_add Fssh_crypto_sign_ed25519_ref_sc25519_add +#define crypto_sign_ed25519_ref_sc25519_from32bytes Fssh_crypto_sign_ed25519_ref_sc25519_from32bytes +#define crypto_sign_ed25519_ref_sc25519_from64bytes Fssh_crypto_sign_ed25519_ref_sc25519_from64bytes +#define crypto_sign_ed25519_ref_sc25519_from_shortsc Fssh_crypto_sign_ed25519_ref_sc25519_from_shortsc +#define crypto_sign_ed25519_ref_sc25519_isshort_vartime Fssh_crypto_sign_ed25519_ref_sc25519_isshort_vartime +#define crypto_sign_ed25519_ref_sc25519_iszero_vartime Fssh_crypto_sign_ed25519_ref_sc25519_iszero_vartime +#define crypto_sign_ed25519_ref_sc25519_lt_vartime Fssh_crypto_sign_ed25519_ref_sc25519_lt_vartime +#define crypto_sign_ed25519_ref_sc25519_mul Fssh_crypto_sign_ed25519_ref_sc25519_mul +#define crypto_sign_ed25519_ref_sc25519_mul_shortsc Fssh_crypto_sign_ed25519_ref_sc25519_mul_shortsc +#define crypto_sign_ed25519_ref_sc25519_sub_nored Fssh_crypto_sign_ed25519_ref_sc25519_sub_nored +#define crypto_sign_ed25519_ref_sc25519_to32bytes Fssh_crypto_sign_ed25519_ref_sc25519_to32bytes +#define crypto_sign_ed25519_ref_sc25519_window3 Fssh_crypto_sign_ed25519_ref_sc25519_window3 +#define crypto_sign_ed25519_ref_sc25519_window5 Fssh_crypto_sign_ed25519_ref_sc25519_window5 +#define crypto_sign_ed25519_ref_scalarmult_base Fssh_crypto_sign_ed25519_ref_scalarmult_base +#define crypto_sign_ed25519_ref_shortsc25519_from16bytes Fssh_crypto_sign_ed25519_ref_shortsc25519_from16bytes +#define crypto_sign_ed25519_ref_unpackneg_vartime Fssh_crypto_sign_ed25519_ref_unpackneg_vartime +#define crypto_verify_32 Fssh_crypto_verify_32 +#define dbl_p1p1 Fssh_dbl_p1p1 +#define deattack_init Fssh_deattack_init +#define debug Fssh_debug +#define debug2 Fssh_debug2 +#define debug3 Fssh_debug3 +#define deny_input_open Fssh_deny_input_open +#define derive_ssh1_session_id Fssh_derive_ssh1_session_id +#define detect_attack Fssh_detect_attack +#define dh_estimate Fssh_dh_estimate +#define dh_gen_key Fssh_dh_gen_key +#define dh_new_group Fssh_dh_new_group +#define dh_new_group1 Fssh_dh_new_group1 +#define dh_new_group14 Fssh_dh_new_group14 +#define dh_new_group_asc Fssh_dh_new_group_asc +#define dh_new_group_fallback Fssh_dh_new_group_fallback +#define dh_pub_is_valid Fssh_dh_pub_is_valid +#define dispatch_protocol_error Fssh_dispatch_protocol_error +#define dispatch_protocol_ignore Fssh_dispatch_protocol_ignore +#define dns_read_key Fssh_dns_read_key +#define do_log Fssh_do_log +#define do_log2 Fssh_do_log2 +#define dump_base64 Fssh_dump_base64 +#define enable_compat13 Fssh_enable_compat13 +#define enable_compat20 Fssh_enable_compat20 +#define error Fssh_error +#define evp_ssh1_3des Fssh_evp_ssh1_3des +#define evp_ssh1_bf Fssh_evp_ssh1_bf +#define explicit_bzero Fssh_explicit_bzero +#define export_dns_rr Fssh_export_dns_rr +#define fatal Fssh_fatal +#define filter_proposal Fssh_filter_proposal +#define fingerprint_b64 Fssh_fingerprint_b64 +#define fingerprint_hex Fssh_fingerprint_hex +#define fmt_scaled Fssh_fmt_scaled +#define free_hostkeys Fssh_free_hostkeys +#define freeargs Fssh_freeargs +#define freerrset Fssh_freerrset +#define gen_candidates Fssh_gen_candidates +#define get_canonical_hostname Fssh_get_canonical_hostname +#define get_local_ipaddr Fssh_get_local_ipaddr +#define get_local_name Fssh_get_local_name +#define get_local_port Fssh_get_local_port +#define get_peer_ipaddr Fssh_get_peer_ipaddr +#define get_peer_port Fssh_get_peer_port +#define get_remote_ipaddr Fssh_get_remote_ipaddr +#define get_remote_name_or_ip Fssh_get_remote_name_or_ip +#define get_remote_port Fssh_get_remote_port +#define get_sock_port Fssh_get_sock_port +#define get_socket_address Fssh_get_socket_address +#define get_u16 Fssh_get_u16 +#define get_u32 Fssh_get_u32 +#define get_u32_le Fssh_get_u32_le +#define get_u64 Fssh_get_u64 +#define getrrsetbyname Fssh_getrrsetbyname +#define glob Fssh_glob +#define glob0 Fssh_glob0 +#define glob2 Fssh_glob2 +#define globexp1 Fssh_globexp1 +#define globextend Fssh_globextend +#define globfree Fssh_globfree +#define host_delete Fssh_host_delete +#define host_hash Fssh_host_hash +#define hostfile_read_key Fssh_hostfile_read_key +#define hostfile_replace_entries Fssh_hostfile_replace_entries +#define hostkeys_foreach Fssh_hostkeys_foreach +#define hpdelim Fssh_hpdelim +#define init_hostkeys Fssh_init_hostkeys +#define input_kex_c25519_init Fssh_input_kex_c25519_init +#define input_kex_c25519_reply Fssh_input_kex_c25519_reply +#define input_kex_dh Fssh_input_kex_dh +#define input_kex_dh_gex_group Fssh_input_kex_dh_gex_group +#define input_kex_dh_gex_init Fssh_input_kex_dh_gex_init +#define input_kex_dh_gex_reply Fssh_input_kex_dh_gex_reply +#define input_kex_dh_gex_request Fssh_input_kex_dh_gex_request +#define input_kex_dh_init Fssh_input_kex_dh_init +#define input_kex_ecdh_init Fssh_input_kex_ecdh_init +#define input_kex_ecdh_reply Fssh_input_kex_ecdh_reply +#define iptos2str Fssh_iptos2str +#define ipv64_normalise_mapped Fssh_ipv64_normalise_mapped +#define is_key_revoked Fssh_is_key_revoked +#define kex_alg_list Fssh_kex_alg_list +#define kex_assemble_names Fssh_kex_assemble_names +#define kex_buf2prop Fssh_kex_buf2prop +#define kex_c25519_hash Fssh_kex_c25519_hash +#define kex_derive_keys Fssh_kex_derive_keys +#define kex_derive_keys_bn Fssh_kex_derive_keys_bn +#define kex_dh_hash Fssh_kex_dh_hash +#define kex_ecdh_hash Fssh_kex_ecdh_hash +#define kex_free Fssh_kex_free +#define kex_free_newkeys Fssh_kex_free_newkeys +#define kex_input_kexinit Fssh_kex_input_kexinit +#define kex_input_newkeys Fssh_kex_input_newkeys +#define kex_names_cat Fssh_kex_names_cat +#define kex_names_valid Fssh_kex_names_valid +#define kex_new Fssh_kex_new +#define kex_prop2buf Fssh_kex_prop2buf +#define kex_prop_free Fssh_kex_prop_free +#define kex_protocol_error Fssh_kex_protocol_error +#define kex_send_kexinit Fssh_kex_send_kexinit +#define kex_send_newkeys Fssh_kex_send_newkeys +#define kex_setup Fssh_kex_setup +#define kexc25519_client Fssh_kexc25519_client +#define kexc25519_keygen Fssh_kexc25519_keygen +#define kexc25519_server Fssh_kexc25519_server +#define kexc25519_shared_key Fssh_kexc25519_shared_key +#define kexdh_client Fssh_kexdh_client +#define kexdh_server Fssh_kexdh_server +#define kexecdh_client Fssh_kexecdh_client +#define kexecdh_server Fssh_kexecdh_server +#define kexgex_client Fssh_kexgex_client +#define kexgex_hash Fssh_kexgex_hash +#define kexgex_server Fssh_kexgex_server +#define key_add_private Fssh_key_add_private +#define key_alg_list Fssh_key_alg_list +#define key_cert_check_authority Fssh_key_cert_check_authority +#define key_cert_copy Fssh_key_cert_copy +#define key_certify Fssh_key_certify +#define key_demote Fssh_key_demote +#define key_drop_cert Fssh_key_drop_cert +#define key_ec_validate_private Fssh_key_ec_validate_private +#define key_ec_validate_public Fssh_key_ec_validate_public +#define key_from_blob Fssh_key_from_blob +#define key_from_private Fssh_key_from_private +#define key_generate Fssh_key_generate +#define key_load_cert Fssh_key_load_cert +#define key_load_file Fssh_key_load_file +#define key_load_private Fssh_key_load_private +#define key_load_private_cert Fssh_key_load_private_cert +#define key_load_private_type Fssh_key_load_private_type +#define key_load_public Fssh_key_load_public +#define key_new_private Fssh_key_new_private +#define key_perm_ok Fssh_key_perm_ok +#define key_private_deserialize Fssh_key_private_deserialize +#define key_private_serialize Fssh_key_private_serialize +#define key_read Fssh_key_read +#define key_save_private Fssh_key_save_private +#define key_sign Fssh_key_sign +#define key_to_blob Fssh_key_to_blob +#define key_to_certified Fssh_key_to_certified +#define key_verify Fssh_key_verify +#define key_write Fssh_key_write +#define load_hostkeys Fssh_load_hostkeys +#define log_change_level Fssh_log_change_level +#define log_facility_name Fssh_log_facility_name +#define log_facility_number Fssh_log_facility_number +#define log_init Fssh_log_init +#define log_is_on_stderr Fssh_log_is_on_stderr +#define log_level_name Fssh_log_level_name +#define log_level_number Fssh_log_level_number +#define log_redirect_stderr_to Fssh_log_redirect_stderr_to +#define logit Fssh_logit +#define lookup_key_in_hostkeys_by_type Fssh_lookup_key_in_hostkeys_by_type +#define lowercase Fssh_lowercase +#define mac_alg_list Fssh_mac_alg_list +#define mac_clear Fssh_mac_clear +#define mac_compute Fssh_mac_compute +#define mac_init Fssh_mac_init +#define mac_setup Fssh_mac_setup +#define mac_valid Fssh_mac_valid +#define match Fssh_match +#define match_host_and_ip Fssh_match_host_and_ip +#define match_hostname Fssh_match_hostname +#define match_list Fssh_match_list +#define match_maybe_hashed Fssh_match_maybe_hashed +#define match_pattern Fssh_match_pattern +#define match_pattern_list Fssh_match_pattern_list +#define match_user Fssh_match_user +#define mktemp_proto Fssh_mktemp_proto +#define mm_choose_dh Fssh_mm_choose_dh +#define mm_receive_fd Fssh_mm_receive_fd +#define mm_send_fd Fssh_mm_send_fd +#define mm_sshkey_sign Fssh_mm_sshkey_sign +#define monotime Fssh_monotime +#define ms_subtract_diff Fssh_ms_subtract_diff +#define ms_to_timeval Fssh_ms_to_timeval +#define mult Fssh_mult +#define mysignal Fssh_mysignal +#define newkeys_from_blob Fssh_newkeys_from_blob +#define newkeys_to_blob Fssh_newkeys_to_blob +#define nh_aux Fssh_nh_aux +#define nh_final Fssh_nh_final +#define nh_update Fssh_nh_update +#define packet_backup_state Fssh_packet_backup_state +#define packet_close Fssh_packet_close +#define packet_disconnect Fssh_packet_disconnect +#define packet_get_char Fssh_packet_get_char +#define packet_get_int Fssh_packet_get_int +#define packet_process_incoming Fssh_packet_process_incoming +#define packet_read_expect Fssh_packet_read_expect +#define packet_read_poll_seqnr Fssh_packet_read_poll_seqnr +#define packet_read_seqnr Fssh_packet_read_seqnr +#define packet_restore_state Fssh_packet_restore_state +#define packet_send_debug Fssh_packet_send_debug +#define packet_set_connection Fssh_packet_set_connection +#define packet_write_poll Fssh_packet_write_poll +#define packet_write_wait Fssh_packet_write_wait +#define parse_ipqos Fssh_parse_ipqos +#define parse_prime Fssh_parse_prime +#define percent_expand Fssh_percent_expand +#define permanently_drop_suid Fssh_permanently_drop_suid +#define permanently_set_uid Fssh_permanently_set_uid +#define permitopen_port Fssh_permitopen_port +#define pkcs11_add_provider Fssh_pkcs11_add_provider +#define pkcs11_del_provider Fssh_pkcs11_del_provider +#define pkcs11_fetch_keys_filter Fssh_pkcs11_fetch_keys_filter +#define pkcs11_find Fssh_pkcs11_find +#define pkcs11_init Fssh_pkcs11_init +#define pkcs11_provider_finalize Fssh_pkcs11_provider_finalize +#define pkcs11_provider_unref Fssh_pkcs11_provider_unref +#define pkcs11_rsa_finish Fssh_pkcs11_rsa_finish +#define pkcs11_rsa_private_decrypt Fssh_pkcs11_rsa_private_decrypt +#define pkcs11_rsa_private_encrypt Fssh_pkcs11_rsa_private_encrypt +#define pkcs11_terminate Fssh_pkcs11_terminate +#define plain_key_blob Fssh_plain_key_blob +#define poly1305_auth Fssh_poly1305_auth +#define poly64 Fssh_poly64 +#define poly_hash Fssh_poly_hash +#define port_open_helper Fssh_port_open_helper +#define prime_test Fssh_prime_test +#define proto_spec Fssh_proto_spec +#define put_bitmap Fssh_put_bitmap +#define put_host_port Fssh_put_host_port +#define put_u16 Fssh_put_u16 +#define put_u32 Fssh_put_u32 +#define put_u32_le Fssh_put_u32_le +#define put_u64 Fssh_put_u64 +#define pwcopy Fssh_pwcopy +#define qfileout Fssh_qfileout +#define read_keyfile_line Fssh_read_keyfile_line +#define read_mux Fssh_read_mux +#define read_passphrase Fssh_read_passphrase +#define reallocarray Fssh_reallocarray +#define record_hostkey Fssh_record_hostkey +#define reduce_add_sub Fssh_reduce_add_sub +#define refresh_progress_meter Fssh_refresh_progress_meter +#define replacearg Fssh_replacearg +#define restore_uid Fssh_restore_uid +#define revoke_blob Fssh_revoke_blob +#define revoked_blob_tree_RB_REMOVE Fssh_revoked_blob_tree_RB_REMOVE +#define revoked_certs_for_ca_key Fssh_revoked_certs_for_ca_key +#define revoked_serial_tree_RB_REMOVE Fssh_revoked_serial_tree_RB_REMOVE +#define rijndaelEncrypt Fssh_rijndaelEncrypt +#define rijndaelKeySetupEnc Fssh_rijndaelKeySetupEnc +#define rsa_generate_additional_parameters Fssh_rsa_generate_additional_parameters +#define rsa_private_decrypt Fssh_rsa_private_decrypt +#define rsa_public_encrypt Fssh_rsa_public_encrypt +#define sanitise_stdfd Fssh_sanitise_stdfd +#define scan_scaled Fssh_scan_scaled +#define seed_rng Fssh_seed_rng +#define set_log_handler Fssh_set_log_handler +#define set_nodelay Fssh_set_nodelay +#define set_nonblock Fssh_set_nonblock +#define shadow_pw Fssh_shadow_pw +#define sieve_large Fssh_sieve_large +#define sig_winch Fssh_sig_winch +#define sigdie Fssh_sigdie +#define sock_set_v6only Fssh_sock_set_v6only +#define square Fssh_square +#define ssh1_3des_cbc Fssh_ssh1_3des_cbc +#define ssh1_3des_cleanup Fssh_ssh1_3des_cleanup +#define ssh1_3des_init Fssh_ssh1_3des_init +#define ssh1_3des_iv Fssh_ssh1_3des_iv +#define ssh_OpenSSL_add_all_algorithms Fssh_ssh_OpenSSL_add_all_algorithms +#define ssh_add_hostkey Fssh_ssh_add_hostkey +#define ssh_add_identity_constrained Fssh_ssh_add_identity_constrained +#define ssh_agent_sign Fssh_ssh_agent_sign +#define ssh_alloc_session_state Fssh_ssh_alloc_session_state +#define ssh_close_authentication_socket Fssh_ssh_close_authentication_socket +#define ssh_compatible_openssl Fssh_ssh_compatible_openssl +#define ssh_crc32 Fssh_ssh_crc32 +#define ssh_decrypt_challenge Fssh_ssh_decrypt_challenge +#define ssh_digest_alg_by_name Fssh_ssh_digest_alg_by_name +#define ssh_digest_alg_name Fssh_ssh_digest_alg_name +#define ssh_digest_blocksize Fssh_ssh_digest_blocksize +#define ssh_digest_buffer Fssh_ssh_digest_buffer +#define ssh_digest_bytes Fssh_ssh_digest_bytes +#define ssh_digest_copy_state Fssh_ssh_digest_copy_state +#define ssh_digest_final Fssh_ssh_digest_final +#define ssh_digest_free Fssh_ssh_digest_free +#define ssh_digest_memory Fssh_ssh_digest_memory +#define ssh_digest_start Fssh_ssh_digest_start +#define ssh_digest_update Fssh_ssh_digest_update +#define ssh_digest_update_buffer Fssh_ssh_digest_update_buffer +#define ssh_dispatch_init Fssh_ssh_dispatch_init +#define ssh_dispatch_range Fssh_ssh_dispatch_range +#define ssh_dispatch_run Fssh_ssh_dispatch_run +#define ssh_dispatch_run_fatal Fssh_ssh_dispatch_run_fatal +#define ssh_dispatch_set Fssh_ssh_dispatch_set +#define ssh_dss_sign Fssh_ssh_dss_sign +#define ssh_dss_verify Fssh_ssh_dss_verify +#define ssh_ecdsa_sign Fssh_ssh_ecdsa_sign +#define ssh_ecdsa_verify Fssh_ssh_ecdsa_verify +#define ssh_ed25519_sign Fssh_ssh_ed25519_sign +#define ssh_ed25519_verify Fssh_ssh_ed25519_verify +#define ssh_err Fssh_ssh_err +#define ssh_fetch_identitylist Fssh_ssh_fetch_identitylist +#define ssh_free Fssh_ssh_free +#define ssh_free_identitylist Fssh_ssh_free_identitylist +#define ssh_gai_strerror Fssh_ssh_gai_strerror +#define ssh_get_app_data Fssh_ssh_get_app_data +#define ssh_get_authentication_socket Fssh_ssh_get_authentication_socket +#define ssh_get_progname Fssh_ssh_get_progname +#define ssh_hmac_bytes Fssh_ssh_hmac_bytes +#define ssh_hmac_final Fssh_ssh_hmac_final +#define ssh_hmac_free Fssh_ssh_hmac_free +#define ssh_hmac_init Fssh_ssh_hmac_init +#define ssh_hmac_start Fssh_ssh_hmac_start +#define ssh_hmac_update Fssh_ssh_hmac_update +#define ssh_hmac_update_buffer Fssh_ssh_hmac_update_buffer +#define ssh_init Fssh_ssh_init +#define ssh_input_append Fssh_ssh_input_append +#define ssh_input_space Fssh_ssh_input_space +#define ssh_krl_check_key Fssh_ssh_krl_check_key +#define ssh_krl_file_contains_key Fssh_ssh_krl_file_contains_key +#define ssh_krl_free Fssh_ssh_krl_free +#define ssh_krl_from_blob Fssh_ssh_krl_from_blob +#define ssh_krl_init Fssh_ssh_krl_init +#define ssh_krl_revoke_cert_by_key_id Fssh_ssh_krl_revoke_cert_by_key_id +#define ssh_krl_revoke_cert_by_serial Fssh_ssh_krl_revoke_cert_by_serial +#define ssh_krl_revoke_cert_by_serial_range Fssh_ssh_krl_revoke_cert_by_serial_range +#define ssh_krl_revoke_key Fssh_ssh_krl_revoke_key +#define ssh_krl_revoke_key_explicit Fssh_ssh_krl_revoke_key_explicit +#define ssh_krl_revoke_key_sha1 Fssh_ssh_krl_revoke_key_sha1 +#define ssh_krl_set_comment Fssh_ssh_krl_set_comment +#define ssh_krl_set_version Fssh_ssh_krl_set_version +#define ssh_krl_to_blob Fssh_ssh_krl_to_blob +#define ssh_lock_agent Fssh_ssh_lock_agent +#define ssh_msg_recv Fssh_ssh_msg_recv +#define ssh_msg_send Fssh_ssh_msg_send +#define ssh_output_consume Fssh_ssh_output_consume +#define ssh_output_ptr Fssh_ssh_output_ptr +#define ssh_output_space Fssh_ssh_output_space +#define ssh_packet_backup_state Fssh_ssh_packet_backup_state +#define ssh_packet_close Fssh_ssh_packet_close +#define ssh_packet_connection_af Fssh_ssh_packet_connection_af +#define ssh_packet_connection_is_on_socket Fssh_ssh_packet_connection_is_on_socket +#define ssh_packet_disconnect Fssh_ssh_packet_disconnect +#define ssh_packet_enable_delayed_compress Fssh_ssh_packet_enable_delayed_compress +#define ssh_packet_get_bignum Fssh_ssh_packet_get_bignum +#define ssh_packet_get_bignum2 Fssh_ssh_packet_get_bignum2 +#define ssh_packet_get_bytes Fssh_ssh_packet_get_bytes +#define ssh_packet_get_char Fssh_ssh_packet_get_char +#define ssh_packet_get_connection_in Fssh_ssh_packet_get_connection_in +#define ssh_packet_get_connection_out Fssh_ssh_packet_get_connection_out +#define ssh_packet_get_cstring Fssh_ssh_packet_get_cstring +#define ssh_packet_get_ecpoint Fssh_ssh_packet_get_ecpoint +#define ssh_packet_get_input Fssh_ssh_packet_get_input +#define ssh_packet_get_int Fssh_ssh_packet_get_int +#define ssh_packet_get_int64 Fssh_ssh_packet_get_int64 +#define ssh_packet_get_maxsize Fssh_ssh_packet_get_maxsize +#define ssh_packet_get_output Fssh_ssh_packet_get_output +#define ssh_packet_get_protocol_flags Fssh_ssh_packet_get_protocol_flags +#define ssh_packet_get_rekey_timeout Fssh_ssh_packet_get_rekey_timeout +#define ssh_packet_get_state Fssh_ssh_packet_get_state +#define ssh_packet_get_string Fssh_ssh_packet_get_string +#define ssh_packet_get_string_ptr Fssh_ssh_packet_get_string_ptr +#define ssh_packet_have_data_to_write Fssh_ssh_packet_have_data_to_write +#define ssh_packet_inc_alive_timeouts Fssh_ssh_packet_inc_alive_timeouts +#define ssh_packet_is_interactive Fssh_ssh_packet_is_interactive +#define ssh_packet_need_rekeying Fssh_ssh_packet_need_rekeying +#define ssh_packet_next Fssh_ssh_packet_next +#define ssh_packet_not_very_much_data_to_write Fssh_ssh_packet_not_very_much_data_to_write +#define ssh_packet_payload Fssh_ssh_packet_payload +#define ssh_packet_process_incoming Fssh_ssh_packet_process_incoming +#define ssh_packet_put Fssh_ssh_packet_put +#define ssh_packet_put_bignum Fssh_ssh_packet_put_bignum +#define ssh_packet_put_bignum2 Fssh_ssh_packet_put_bignum2 +#define ssh_packet_put_char Fssh_ssh_packet_put_char +#define ssh_packet_put_cstring Fssh_ssh_packet_put_cstring +#define ssh_packet_put_ecpoint Fssh_ssh_packet_put_ecpoint +#define ssh_packet_put_int Fssh_ssh_packet_put_int +#define ssh_packet_put_int64 Fssh_ssh_packet_put_int64 +#define ssh_packet_put_raw Fssh_ssh_packet_put_raw +#define ssh_packet_put_string Fssh_ssh_packet_put_string +#define ssh_packet_read Fssh_ssh_packet_read +#define ssh_packet_read_expect Fssh_ssh_packet_read_expect +#define ssh_packet_read_poll1 Fssh_ssh_packet_read_poll1 +#define ssh_packet_read_poll2 Fssh_ssh_packet_read_poll2 +#define ssh_packet_read_poll_seqnr Fssh_ssh_packet_read_poll_seqnr +#define ssh_packet_read_seqnr Fssh_ssh_packet_read_seqnr +#define ssh_packet_remaining Fssh_ssh_packet_remaining +#define ssh_packet_restore_state Fssh_ssh_packet_restore_state +#define ssh_packet_send Fssh_ssh_packet_send +#define ssh_packet_send1 Fssh_ssh_packet_send1 +#define ssh_packet_send2 Fssh_ssh_packet_send2 +#define ssh_packet_send2_wrapped Fssh_ssh_packet_send2_wrapped +#define ssh_packet_send_debug Fssh_ssh_packet_send_debug +#define ssh_packet_send_ignore Fssh_ssh_packet_send_ignore +#define ssh_packet_set_alive_timeouts Fssh_ssh_packet_set_alive_timeouts +#define ssh_packet_set_authenticated Fssh_ssh_packet_set_authenticated +#define ssh_packet_set_compress_hooks Fssh_ssh_packet_set_compress_hooks +#define ssh_packet_set_connection Fssh_ssh_packet_set_connection +#define ssh_packet_set_encryption_key Fssh_ssh_packet_set_encryption_key +#define ssh_packet_set_interactive Fssh_ssh_packet_set_interactive +#define ssh_packet_set_maxsize Fssh_ssh_packet_set_maxsize +#define ssh_packet_set_nonblocking Fssh_ssh_packet_set_nonblocking +#define ssh_packet_set_protocol_flags Fssh_ssh_packet_set_protocol_flags +#define ssh_packet_set_rekey_limits Fssh_ssh_packet_set_rekey_limits +#define ssh_packet_set_server Fssh_ssh_packet_set_server +#define ssh_packet_set_state Fssh_ssh_packet_set_state +#define ssh_packet_set_timeout Fssh_ssh_packet_set_timeout +#define ssh_packet_set_tos Fssh_ssh_packet_set_tos +#define ssh_packet_start Fssh_ssh_packet_start +#define ssh_packet_start_compression Fssh_ssh_packet_start_compression +#define ssh_packet_start_discard Fssh_ssh_packet_start_discard +#define ssh_packet_stop_discard Fssh_ssh_packet_stop_discard +#define ssh_packet_write_poll Fssh_ssh_packet_write_poll +#define ssh_packet_write_wait Fssh_ssh_packet_write_wait +#define ssh_remote_ipaddr Fssh_ssh_remote_ipaddr +#define ssh_remove_all_identities Fssh_ssh_remove_all_identities +#define ssh_remove_identity Fssh_ssh_remove_identity +#define ssh_request_reply Fssh_ssh_request_reply +#define ssh_rsa_sign Fssh_ssh_rsa_sign +#define ssh_rsa_verify Fssh_ssh_rsa_verify +#define ssh_set_app_data Fssh_ssh_set_app_data +#define ssh_set_newkeys Fssh_ssh_set_newkeys +#define ssh_set_verify_host_key_callback Fssh_ssh_set_verify_host_key_callback +#define ssh_update_card Fssh_ssh_update_card +#define sshbuf_alloc Fssh_sshbuf_alloc +#define sshbuf_avail Fssh_sshbuf_avail +#define sshbuf_b64tod Fssh_sshbuf_b64tod +#define sshbuf_check_reserve Fssh_sshbuf_check_reserve +#define sshbuf_consume Fssh_sshbuf_consume +#define sshbuf_consume_end Fssh_sshbuf_consume_end +#define sshbuf_dtob16 Fssh_sshbuf_dtob16 +#define sshbuf_dtob64 Fssh_sshbuf_dtob64 +#define sshbuf_dump Fssh_sshbuf_dump +#define sshbuf_dump_data Fssh_sshbuf_dump_data +#define sshbuf_free Fssh_sshbuf_free +#define sshbuf_from Fssh_sshbuf_from +#define sshbuf_fromb Fssh_sshbuf_fromb +#define sshbuf_froms Fssh_sshbuf_froms +#define sshbuf_get Fssh_sshbuf_get +#define sshbuf_get_bignum1 Fssh_sshbuf_get_bignum1 +#define sshbuf_get_bignum2 Fssh_sshbuf_get_bignum2 +#define sshbuf_get_bignum2_bytes_direct Fssh_sshbuf_get_bignum2_bytes_direct +#define sshbuf_get_cstring Fssh_sshbuf_get_cstring +#define sshbuf_get_ec Fssh_sshbuf_get_ec +#define sshbuf_get_eckey Fssh_sshbuf_get_eckey +#define sshbuf_get_string Fssh_sshbuf_get_string +#define sshbuf_get_string_direct Fssh_sshbuf_get_string_direct +#define sshbuf_get_stringb Fssh_sshbuf_get_stringb +#define sshbuf_get_u16 Fssh_sshbuf_get_u16 +#define sshbuf_get_u32 Fssh_sshbuf_get_u32 +#define sshbuf_get_u64 Fssh_sshbuf_get_u64 +#define sshbuf_get_u8 Fssh_sshbuf_get_u8 +#define sshbuf_init Fssh_sshbuf_init +#define sshbuf_len Fssh_sshbuf_len +#define sshbuf_max_size Fssh_sshbuf_max_size +#define sshbuf_mutable_ptr Fssh_sshbuf_mutable_ptr +#define sshbuf_new Fssh_sshbuf_new +#define sshbuf_parent Fssh_sshbuf_parent +#define sshbuf_peek_string_direct Fssh_sshbuf_peek_string_direct +#define sshbuf_ptr Fssh_sshbuf_ptr +#define sshbuf_put Fssh_sshbuf_put +#define sshbuf_put_bignum1 Fssh_sshbuf_put_bignum1 +#define sshbuf_put_bignum2 Fssh_sshbuf_put_bignum2 +#define sshbuf_put_bignum2_bytes Fssh_sshbuf_put_bignum2_bytes +#define sshbuf_put_cstring Fssh_sshbuf_put_cstring +#define sshbuf_put_ec Fssh_sshbuf_put_ec +#define sshbuf_put_eckey Fssh_sshbuf_put_eckey +#define sshbuf_put_string Fssh_sshbuf_put_string +#define sshbuf_put_stringb Fssh_sshbuf_put_stringb +#define sshbuf_put_u16 Fssh_sshbuf_put_u16 +#define sshbuf_put_u32 Fssh_sshbuf_put_u32 +#define sshbuf_put_u64 Fssh_sshbuf_put_u64 +#define sshbuf_put_u8 Fssh_sshbuf_put_u8 +#define sshbuf_putb Fssh_sshbuf_putb +#define sshbuf_putf Fssh_sshbuf_putf +#define sshbuf_putfv Fssh_sshbuf_putfv +#define sshbuf_refcount Fssh_sshbuf_refcount +#define sshbuf_reserve Fssh_sshbuf_reserve +#define sshbuf_reset Fssh_sshbuf_reset +#define sshbuf_set_max_size Fssh_sshbuf_set_max_size +#define sshbuf_set_parent Fssh_sshbuf_set_parent +#define sshkey_add_private Fssh_sshkey_add_private +#define sshkey_cert_check_authority Fssh_sshkey_cert_check_authority +#define sshkey_cert_copy Fssh_sshkey_cert_copy +#define sshkey_cert_type Fssh_sshkey_cert_type +#define sshkey_certify Fssh_sshkey_certify +#define sshkey_check_revoked Fssh_sshkey_check_revoked +#define sshkey_curve_name_to_nid Fssh_sshkey_curve_name_to_nid +#define sshkey_curve_nid_to_bits Fssh_sshkey_curve_nid_to_bits +#define sshkey_curve_nid_to_name Fssh_sshkey_curve_nid_to_name +#define sshkey_demote Fssh_sshkey_demote +#define sshkey_drop_cert Fssh_sshkey_drop_cert +#define sshkey_dump_ec_key Fssh_sshkey_dump_ec_key +#define sshkey_dump_ec_point Fssh_sshkey_dump_ec_point +#define sshkey_ec_nid_to_hash_alg Fssh_sshkey_ec_nid_to_hash_alg +#define sshkey_ec_validate_private Fssh_sshkey_ec_validate_private +#define sshkey_ec_validate_public Fssh_sshkey_ec_validate_public +#define sshkey_ecdsa_bits_to_nid Fssh_sshkey_ecdsa_bits_to_nid +#define sshkey_ecdsa_key_to_nid Fssh_sshkey_ecdsa_key_to_nid +#define sshkey_ecdsa_nid_from_name Fssh_sshkey_ecdsa_nid_from_name +#define sshkey_equal Fssh_sshkey_equal +#define sshkey_equal_public Fssh_sshkey_equal_public +#define sshkey_fingerprint Fssh_sshkey_fingerprint +#define sshkey_fingerprint_raw Fssh_sshkey_fingerprint_raw +#define sshkey_free Fssh_sshkey_free +#define sshkey_from_blob Fssh_sshkey_from_blob +#define sshkey_from_blob_internal Fssh_sshkey_from_blob_internal +#define sshkey_from_private Fssh_sshkey_from_private +#define sshkey_fromb Fssh_sshkey_fromb +#define sshkey_froms Fssh_sshkey_froms +#define sshkey_generate Fssh_sshkey_generate +#define sshkey_in_file Fssh_sshkey_in_file +#define sshkey_is_cert Fssh_sshkey_is_cert +#define sshkey_load_cert Fssh_sshkey_load_cert +#define sshkey_load_file Fssh_sshkey_load_file +#define sshkey_load_private Fssh_sshkey_load_private +#define sshkey_load_private_cert Fssh_sshkey_load_private_cert +#define sshkey_load_private_type Fssh_sshkey_load_private_type +#define sshkey_load_private_type_fd Fssh_sshkey_load_private_type_fd +#define sshkey_load_public Fssh_sshkey_load_public +#define sshkey_names_valid2 Fssh_sshkey_names_valid2 +#define sshkey_new Fssh_sshkey_new +#define sshkey_new_private Fssh_sshkey_new_private +#define sshkey_parse_private2 Fssh_sshkey_parse_private2 +#define sshkey_parse_private_fileblob Fssh_sshkey_parse_private_fileblob +#define sshkey_parse_private_fileblob_type Fssh_sshkey_parse_private_fileblob_type +#define sshkey_parse_private_pem_fileblob Fssh_sshkey_parse_private_pem_fileblob +#define sshkey_parse_public_rsa1_fileblob Fssh_sshkey_parse_public_rsa1_fileblob +#define sshkey_perm_ok Fssh_sshkey_perm_ok +#define sshkey_plain_to_blob Fssh_sshkey_plain_to_blob +#define sshkey_private_deserialize Fssh_sshkey_private_deserialize +#define sshkey_private_serialize Fssh_sshkey_private_serialize +#define sshkey_private_to_blob2 Fssh_sshkey_private_to_blob2 +#define sshkey_private_to_fileblob Fssh_sshkey_private_to_fileblob +#define sshkey_putb Fssh_sshkey_putb +#define sshkey_putb_plain Fssh_sshkey_putb_plain +#define sshkey_puts Fssh_sshkey_puts +#define sshkey_read Fssh_sshkey_read +#define sshkey_save_private Fssh_sshkey_save_private +#define sshkey_sign Fssh_sshkey_sign +#define sshkey_size Fssh_sshkey_size +#define sshkey_ssh_name Fssh_sshkey_ssh_name +#define sshkey_ssh_name_plain Fssh_sshkey_ssh_name_plain +#define sshkey_to_base64 Fssh_sshkey_to_base64 +#define sshkey_to_blob Fssh_sshkey_to_blob +#define sshkey_to_certified Fssh_sshkey_to_certified +#define sshkey_try_load_public Fssh_sshkey_try_load_public +#define sshkey_type Fssh_sshkey_type +#define sshkey_type_from_name Fssh_sshkey_type_from_name +#define sshkey_type_is_cert Fssh_sshkey_type_is_cert +#define sshkey_type_plain Fssh_sshkey_type_plain +#define sshkey_verify Fssh_sshkey_verify +#define sshkey_write Fssh_sshkey_write +#define sshpkt_add_padding Fssh_sshpkt_add_padding +#define sshpkt_disconnect Fssh_sshpkt_disconnect +#define sshpkt_fatal Fssh_sshpkt_fatal +#define sshpkt_get Fssh_sshpkt_get +#define sshpkt_get_bignum1 Fssh_sshpkt_get_bignum1 +#define sshpkt_get_bignum2 Fssh_sshpkt_get_bignum2 +#define sshpkt_get_cstring Fssh_sshpkt_get_cstring +#define sshpkt_get_ec Fssh_sshpkt_get_ec +#define sshpkt_get_end Fssh_sshpkt_get_end +#define sshpkt_get_string Fssh_sshpkt_get_string +#define sshpkt_get_string_direct Fssh_sshpkt_get_string_direct +#define sshpkt_get_u32 Fssh_sshpkt_get_u32 +#define sshpkt_get_u64 Fssh_sshpkt_get_u64 +#define sshpkt_get_u8 Fssh_sshpkt_get_u8 +#define sshpkt_ptr Fssh_sshpkt_ptr +#define sshpkt_put Fssh_sshpkt_put +#define sshpkt_put_bignum1 Fssh_sshpkt_put_bignum1 +#define sshpkt_put_bignum2 Fssh_sshpkt_put_bignum2 +#define sshpkt_put_cstring Fssh_sshpkt_put_cstring +#define sshpkt_put_ec Fssh_sshpkt_put_ec +#define sshpkt_put_string Fssh_sshpkt_put_string +#define sshpkt_put_stringb Fssh_sshpkt_put_stringb +#define sshpkt_put_u32 Fssh_sshpkt_put_u32 +#define sshpkt_put_u64 Fssh_sshpkt_put_u64 +#define sshpkt_put_u8 Fssh_sshpkt_put_u8 +#define sshpkt_putb Fssh_sshpkt_putb +#define sshpkt_send Fssh_sshpkt_send +#define sshpkt_start Fssh_sshpkt_start +#define start_progress_meter Fssh_start_progress_meter +#define stop_progress_meter Fssh_stop_progress_meter +#define strdelim Fssh_strdelim +#define strnvis Fssh_strnvis +#define strvis Fssh_strvis +#define strvisx Fssh_strvisx +#define sys_tun_open Fssh_sys_tun_open +#define temporarily_use_uid Fssh_temporarily_use_uid +#define tilde_expand_filename Fssh_tilde_expand_filename +#define timingsafe_bcmp Fssh_timingsafe_bcmp +#define to_blob Fssh_to_blob +#define to_blob_buf Fssh_to_blob_buf +#define tohex Fssh_tohex +#define tty_make_modes Fssh_tty_make_modes +#define tty_parse_modes Fssh_tty_parse_modes +#define tun_open Fssh_tun_open +#define umac128_delete Fssh_umac128_delete +#define umac128_final Fssh_umac128_final +#define umac128_new Fssh_umac128_new +#define umac128_update Fssh_umac128_update +#define umac_delete Fssh_umac_delete +#define umac_final Fssh_umac_final +#define umac_new Fssh_umac_new +#define umac_update Fssh_umac_update +#define uncompress_buffer Fssh_uncompress_buffer +#define unix_listener Fssh_unix_listener +#define unset_nonblock Fssh_unset_nonblock +#define update_progress_meter Fssh_update_progress_meter +#define uudecode Fssh_uudecode +#define uuencode Fssh_uuencode +#define verbose Fssh_verbose +#define verify_host_key_dns Fssh_verify_host_key_dns +#define vis Fssh_vis +#define write_host_entry Fssh_write_host_entry +#define x11_connect_display Fssh_x11_connect_display +#define x11_create_display_inet Fssh_x11_create_display_inet +#define x11_input_open Fssh_x11_input_open +#define x11_open_helper Fssh_x11_open_helper +#define x11_request_forwarding_with_spoofing Fssh_x11_request_forwarding_with_spoofing +#define xasprintf Fssh_xasprintf +#define xcalloc Fssh_xcalloc +#define xcrypt Fssh_xcrypt +#define xmalloc Fssh_xmalloc +#define xmmap Fssh_xmmap +#define xreallocarray Fssh_xreallocarray +#define xstrdup Fssh_xstrdup diff --git a/crypto/openssh/sshbuf-getput-basic.c b/crypto/openssh/sshbuf-getput-basic.c new file mode 100644 index 0000000..8ff8a0a --- /dev/null +++ b/crypto/openssh/sshbuf-getput-basic.c @@ -0,0 +1,462 @@ +/* $OpenBSD: sshbuf-getput-basic.c,v 1.4 2015/01/14 15:02:39 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define SSHBUF_INTERNAL +#include "includes.h" + +#include +#include +#include +#include + +#include "ssherr.h" +#include "sshbuf.h" + +int +sshbuf_get(struct sshbuf *buf, void *v, size_t len) +{ + const u_char *p = sshbuf_ptr(buf); + int r; + + if ((r = sshbuf_consume(buf, len)) < 0) + return r; + if (v != NULL && len != 0) + memcpy(v, p, len); + return 0; +} + +int +sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp) +{ + const u_char *p = sshbuf_ptr(buf); + int r; + + if ((r = sshbuf_consume(buf, 8)) < 0) + return r; + if (valp != NULL) + *valp = PEEK_U64(p); + return 0; +} + +int +sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp) +{ + const u_char *p = sshbuf_ptr(buf); + int r; + + if ((r = sshbuf_consume(buf, 4)) < 0) + return r; + if (valp != NULL) + *valp = PEEK_U32(p); + return 0; +} + +int +sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp) +{ + const u_char *p = sshbuf_ptr(buf); + int r; + + if ((r = sshbuf_consume(buf, 2)) < 0) + return r; + if (valp != NULL) + *valp = PEEK_U16(p); + return 0; +} + +int +sshbuf_get_u8(struct sshbuf *buf, u_char *valp) +{ + const u_char *p = sshbuf_ptr(buf); + int r; + + if ((r = sshbuf_consume(buf, 1)) < 0) + return r; + if (valp != NULL) + *valp = (u_int8_t)*p; + return 0; +} + +int +sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp) +{ + const u_char *val; + size_t len; + int r; + + if (valp != NULL) + *valp = NULL; + if (lenp != NULL) + *lenp = 0; + if ((r = sshbuf_get_string_direct(buf, &val, &len)) < 0) + return r; + if (valp != NULL) { + if ((*valp = malloc(len + 1)) == NULL) { + SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); + return SSH_ERR_ALLOC_FAIL; + } + if (len != 0) + memcpy(*valp, val, len); + (*valp)[len] = '\0'; + } + if (lenp != NULL) + *lenp = len; + return 0; +} + +int +sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp) +{ + size_t len; + const u_char *p; + int r; + + if (valp != NULL) + *valp = NULL; + if (lenp != NULL) + *lenp = 0; + if ((r = sshbuf_peek_string_direct(buf, &p, &len)) < 0) + return r; + if (valp != 0) + *valp = p; + if (lenp != NULL) + *lenp = len; + if (sshbuf_consume(buf, len + 4) != 0) { + /* Shouldn't happen */ + SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); + SSHBUF_ABORT(); + return SSH_ERR_INTERNAL_ERROR; + } + return 0; +} + +int +sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, + size_t *lenp) +{ + u_int32_t len; + const u_char *p = sshbuf_ptr(buf); + + if (valp != NULL) + *valp = NULL; + if (lenp != NULL) + *lenp = 0; + if (sshbuf_len(buf) < 4) { + SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); + return SSH_ERR_MESSAGE_INCOMPLETE; + } + len = PEEK_U32(p); + if (len > SSHBUF_SIZE_MAX - 4) { + SSHBUF_DBG(("SSH_ERR_STRING_TOO_LARGE")); + return SSH_ERR_STRING_TOO_LARGE; + } + if (sshbuf_len(buf) - 4 < len) { + SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); + return SSH_ERR_MESSAGE_INCOMPLETE; + } + if (valp != 0) + *valp = p + 4; + if (lenp != NULL) + *lenp = len; + return 0; +} + +int +sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp) +{ + size_t len; + const u_char *p, *z; + int r; + + if (valp != NULL) + *valp = NULL; + if (lenp != NULL) + *lenp = 0; + if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0) + return r; + /* Allow a \0 only at the end of the string */ + if (len > 0 && + (z = memchr(p , '\0', len)) != NULL && z < p + len - 1) { + SSHBUF_DBG(("SSH_ERR_INVALID_FORMAT")); + return SSH_ERR_INVALID_FORMAT; + } + if ((r = sshbuf_skip_string(buf)) != 0) + return -1; + if (valp != NULL) { + if ((*valp = malloc(len + 1)) == NULL) { + SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); + return SSH_ERR_ALLOC_FAIL; + } + if (len != 0) + memcpy(*valp, p, len); + (*valp)[len] = '\0'; + } + if (lenp != NULL) + *lenp = (size_t)len; + return 0; +} + +int +sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v) +{ + u_int32_t len; + u_char *p; + int r; + + /* + * Use sshbuf_peek_string_direct() to figure out if there is + * a complete string in 'buf' and copy the string directly + * into 'v'. + */ + if ((r = sshbuf_peek_string_direct(buf, NULL, NULL)) != 0 || + (r = sshbuf_get_u32(buf, &len)) != 0 || + (r = sshbuf_reserve(v, len, &p)) != 0 || + (r = sshbuf_get(buf, p, len)) != 0) + return r; + return 0; +} + +int +sshbuf_put(struct sshbuf *buf, const void *v, size_t len) +{ + u_char *p; + int r; + + if ((r = sshbuf_reserve(buf, len, &p)) < 0) + return r; + if (len != 0) + memcpy(p, v, len); + return 0; +} + +int +sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v) +{ + return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v)); +} + +int +sshbuf_putf(struct sshbuf *buf, const char *fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = sshbuf_putfv(buf, fmt, ap); + va_end(ap); + return r; +} + +int +sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap) +{ + va_list ap2; + int r, len; + u_char *p; + + va_copy(ap2, ap); + if ((len = vsnprintf(NULL, 0, fmt, ap2)) < 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if (len == 0) { + r = 0; + goto out; /* Nothing to do */ + } + va_end(ap2); + va_copy(ap2, ap); + if ((r = sshbuf_reserve(buf, (size_t)len + 1, &p)) < 0) + goto out; + if ((r = vsnprintf((char *)p, len + 1, fmt, ap2)) != len) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; /* Shouldn't happen */ + } + /* Consume terminating \0 */ + if ((r = sshbuf_consume_end(buf, 1)) != 0) + goto out; + r = 0; + out: + va_end(ap2); + return r; +} + +int +sshbuf_put_u64(struct sshbuf *buf, u_int64_t val) +{ + u_char *p; + int r; + + if ((r = sshbuf_reserve(buf, 8, &p)) < 0) + return r; + POKE_U64(p, val); + return 0; +} + +int +sshbuf_put_u32(struct sshbuf *buf, u_int32_t val) +{ + u_char *p; + int r; + + if ((r = sshbuf_reserve(buf, 4, &p)) < 0) + return r; + POKE_U32(p, val); + return 0; +} + +int +sshbuf_put_u16(struct sshbuf *buf, u_int16_t val) +{ + u_char *p; + int r; + + if ((r = sshbuf_reserve(buf, 2, &p)) < 0) + return r; + POKE_U16(p, val); + return 0; +} + +int +sshbuf_put_u8(struct sshbuf *buf, u_char val) +{ + u_char *p; + int r; + + if ((r = sshbuf_reserve(buf, 1, &p)) < 0) + return r; + p[0] = val; + return 0; +} + +int +sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len) +{ + u_char *d; + int r; + + if (len > SSHBUF_SIZE_MAX - 4) { + SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE")); + return SSH_ERR_NO_BUFFER_SPACE; + } + if ((r = sshbuf_reserve(buf, len + 4, &d)) < 0) + return r; + POKE_U32(d, len); + if (len != 0) + memcpy(d + 4, v, len); + return 0; +} + +int +sshbuf_put_cstring(struct sshbuf *buf, const char *v) +{ + return sshbuf_put_string(buf, (u_char *)v, v == NULL ? 0 : strlen(v)); +} + +int +sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v) +{ + return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v)); +} + +int +sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp) +{ + const u_char *p; + size_t len; + struct sshbuf *ret; + int r; + + if (buf == NULL || bufp == NULL) + return SSH_ERR_INVALID_ARGUMENT; + *bufp = NULL; + if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0) + return r; + if ((ret = sshbuf_from(p, len)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_consume(buf, len + 4)) != 0 || /* Shouldn't happen */ + (r = sshbuf_set_parent(ret, buf)) != 0) { + sshbuf_free(ret); + return r; + } + *bufp = ret; + return 0; +} + +int +sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len) +{ + u_char *d; + const u_char *s = (const u_char *)v; + int r, prepend; + + if (len > SSHBUF_SIZE_MAX - 5) { + SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE")); + return SSH_ERR_NO_BUFFER_SPACE; + } + /* Skip leading zero bytes */ + for (; len > 0 && *s == 0; len--, s++) + ; + /* + * If most significant bit is set then prepend a zero byte to + * avoid interpretation as a negative number. + */ + prepend = len > 0 && (s[0] & 0x80) != 0; + if ((r = sshbuf_reserve(buf, len + 4 + prepend, &d)) < 0) + return r; + POKE_U32(d, len + prepend); + if (prepend) + d[4] = 0; + if (len != 0) + memcpy(d + 4 + prepend, s, len); + return 0; +} + +int +sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf, + const u_char **valp, size_t *lenp) +{ + const u_char *d; + size_t len, olen; + int r; + + if ((r = sshbuf_peek_string_direct(buf, &d, &olen)) < 0) + return r; + len = olen; + /* Refuse negative (MSB set) bignums */ + if ((len != 0 && (*d & 0x80) != 0)) + return SSH_ERR_BIGNUM_IS_NEGATIVE; + /* Refuse overlong bignums, allow prepended \0 to avoid MSB set */ + if (len > SSHBUF_MAX_BIGNUM + 1 || + (len == SSHBUF_MAX_BIGNUM + 1 && *d != 0)) + return SSH_ERR_BIGNUM_TOO_LARGE; + /* Trim leading zeros */ + while (len > 0 && *d == 0x00) { + d++; + len--; + } + if (valp != 0) + *valp = d; + if (lenp != NULL) + *lenp = len; + if (sshbuf_consume(buf, olen + 4) != 0) { + /* Shouldn't happen */ + SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); + SSHBUF_ABORT(); + return SSH_ERR_INTERNAL_ERROR; + } + return 0; +} diff --git a/crypto/openssh/sshbuf-getput-crypto.c b/crypto/openssh/sshbuf-getput-crypto.c new file mode 100644 index 0000000..d0d791b --- /dev/null +++ b/crypto/openssh/sshbuf-getput-crypto.c @@ -0,0 +1,224 @@ +/* $OpenBSD: sshbuf-getput-crypto.c,v 1.5 2016/01/12 23:42:54 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define SSHBUF_INTERNAL +#include "includes.h" + +#include +#include +#include +#include + +#include +#ifdef OPENSSL_HAS_ECC +# include +#endif /* OPENSSL_HAS_ECC */ + +#include "ssherr.h" +#include "sshbuf.h" + +int +sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v) +{ + const u_char *d; + size_t len; + int r; + + if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0) + return r; + if (v != NULL && BN_bin2bn(d, len, v) == NULL) + return SSH_ERR_ALLOC_FAIL; + return 0; +} + +int +sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v) +{ + const u_char *d = sshbuf_ptr(buf); + u_int16_t len_bits; + size_t len_bytes; + + /* Length in bits */ + if (sshbuf_len(buf) < 2) + return SSH_ERR_MESSAGE_INCOMPLETE; + len_bits = PEEK_U16(d); + len_bytes = (len_bits + 7) >> 3; + if (len_bytes > SSHBUF_MAX_BIGNUM) + return SSH_ERR_BIGNUM_TOO_LARGE; + if (sshbuf_len(buf) < 2 + len_bytes) + return SSH_ERR_MESSAGE_INCOMPLETE; + if (v != NULL && BN_bin2bn(d + 2, len_bytes, v) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (sshbuf_consume(buf, 2 + len_bytes) != 0) { + SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); + SSHBUF_ABORT(); + return SSH_ERR_INTERNAL_ERROR; + } + return 0; +} + +#ifdef OPENSSL_HAS_ECC +static int +get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g) +{ + /* Refuse overlong bignums */ + if (len == 0 || len > SSHBUF_MAX_ECPOINT) + return SSH_ERR_ECPOINT_TOO_LARGE; + /* Only handle uncompressed points */ + if (*d != POINT_CONVERSION_UNCOMPRESSED) + return SSH_ERR_INVALID_FORMAT; + if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1) + return SSH_ERR_INVALID_FORMAT; /* XXX assumption */ + return 0; +} + +int +sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g) +{ + const u_char *d; + size_t len; + int r; + + if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) + return r; + if ((r = get_ec(d, len, v, g)) != 0) + return r; + /* Skip string */ + if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { + /* Shouldn't happen */ + SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); + SSHBUF_ABORT(); + return SSH_ERR_INTERNAL_ERROR; + } + return 0; +} + +int +sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v) +{ + EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v)); + int r; + const u_char *d; + size_t len; + + if (pt == NULL) { + SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); + return SSH_ERR_ALLOC_FAIL; + } + if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) { + EC_POINT_free(pt); + return r; + } + if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) { + EC_POINT_free(pt); + return r; + } + if (EC_KEY_set_public_key(v, pt) != 1) { + EC_POINT_free(pt); + return SSH_ERR_ALLOC_FAIL; /* XXX assumption */ + } + EC_POINT_free(pt); + /* Skip string */ + if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { + /* Shouldn't happen */ + SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); + SSHBUF_ABORT(); + return SSH_ERR_INTERNAL_ERROR; + } + return 0; +} +#endif /* OPENSSL_HAS_ECC */ + +int +sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v) +{ + u_char d[SSHBUF_MAX_BIGNUM + 1]; + int len = BN_num_bytes(v), prepend = 0, r; + + if (len < 0 || len > SSHBUF_MAX_BIGNUM) + return SSH_ERR_INVALID_ARGUMENT; + *d = '\0'; + if (BN_bn2bin(v, d + 1) != len) + return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ + /* If MSB is set, prepend a \0 */ + if (len > 0 && (d[1] & 0x80) != 0) + prepend = 1; + if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) { + explicit_bzero(d, sizeof(d)); + return r; + } + explicit_bzero(d, sizeof(d)); + return 0; +} + +int +sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v) +{ + int r, len_bits = BN_num_bits(v); + size_t len_bytes = (len_bits + 7) / 8; + u_char d[SSHBUF_MAX_BIGNUM], *dp; + + if (len_bits < 0 || len_bytes > SSHBUF_MAX_BIGNUM) + return SSH_ERR_INVALID_ARGUMENT; + if (BN_bn2bin(v, d) != (int)len_bytes) + return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ + if ((r = sshbuf_reserve(buf, len_bytes + 2, &dp)) < 0) { + explicit_bzero(d, sizeof(d)); + return r; + } + POKE_U16(dp, len_bits); + if (len_bytes != 0) + memcpy(dp + 2, d, len_bytes); + explicit_bzero(d, sizeof(d)); + return 0; +} + +#ifdef OPENSSL_HAS_ECC +int +sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g) +{ + u_char d[SSHBUF_MAX_ECPOINT]; + BN_CTX *bn_ctx; + size_t len; + int ret; + + if ((bn_ctx = BN_CTX_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, bn_ctx)) > SSHBUF_MAX_ECPOINT) { + BN_CTX_free(bn_ctx); + return SSH_ERR_INVALID_ARGUMENT; + } + if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, + d, len, bn_ctx) != len) { + BN_CTX_free(bn_ctx); + return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ + } + BN_CTX_free(bn_ctx); + ret = sshbuf_put_string(buf, d, len); + explicit_bzero(d, len); + return ret; +} + +int +sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v) +{ + return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v), + EC_KEY_get0_group(v)); +} +#endif /* OPENSSL_HAS_ECC */ + diff --git a/crypto/openssh/sshbuf-misc.c b/crypto/openssh/sshbuf-misc.c new file mode 100644 index 0000000..3da4b80 --- /dev/null +++ b/crypto/openssh/sshbuf-misc.c @@ -0,0 +1,138 @@ +/* $OpenBSD: sshbuf-misc.c,v 1.5 2015/10/05 17:11:21 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include +#include +#include +#include + +#include "ssherr.h" +#define SSHBUF_INTERNAL +#include "sshbuf.h" + +void +sshbuf_dump_data(const void *s, size_t len, FILE *f) +{ + size_t i, j; + const u_char *p = (const u_char *)s; + + for (i = 0; i < len; i += 16) { + fprintf(f, "%.4zu: ", i); + for (j = i; j < i + 16; j++) { + if (j < len) + fprintf(f, "%02x ", p[j]); + else + fprintf(f, " "); + } + fprintf(f, " "); + for (j = i; j < i + 16; j++) { + if (j < len) { + if (isascii(p[j]) && isprint(p[j])) + fprintf(f, "%c", p[j]); + else + fprintf(f, "."); + } + } + fprintf(f, "\n"); + } +} + +void +sshbuf_dump(struct sshbuf *buf, FILE *f) +{ + fprintf(f, "buffer %p len = %zu\n", buf, sshbuf_len(buf)); + sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f); +} + +char * +sshbuf_dtob16(struct sshbuf *buf) +{ + size_t i, j, len = sshbuf_len(buf); + const u_char *p = sshbuf_ptr(buf); + char *ret; + const char hex[] = "0123456789abcdef"; + + if (len == 0) + return strdup(""); + if (SIZE_MAX / 2 <= len || (ret = malloc(len * 2 + 1)) == NULL) + return NULL; + for (i = j = 0; i < len; i++) { + ret[j++] = hex[(p[i] >> 4) & 0xf]; + ret[j++] = hex[p[i] & 0xf]; + } + ret[j] = '\0'; + return ret; +} + +char * +sshbuf_dtob64(struct sshbuf *buf) +{ + size_t len = sshbuf_len(buf), plen; + const u_char *p = sshbuf_ptr(buf); + char *ret; + int r; + + if (len == 0) + return strdup(""); + plen = ((len + 2) / 3) * 4 + 1; + if (SIZE_MAX / 2 <= len || (ret = malloc(plen)) == NULL) + return NULL; + if ((r = b64_ntop(p, len, ret, plen)) == -1) { + explicit_bzero(ret, plen); + free(ret); + return NULL; + } + return ret; +} + +int +sshbuf_b64tod(struct sshbuf *buf, const char *b64) +{ + size_t plen = strlen(b64); + int nlen, r; + u_char *p; + + if (plen == 0) + return 0; + if ((p = malloc(plen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((nlen = b64_pton(b64, p, plen)) < 0) { + explicit_bzero(p, plen); + free(p); + return SSH_ERR_INVALID_FORMAT; + } + if ((r = sshbuf_put(buf, p, nlen)) < 0) { + explicit_bzero(p, plen); + free(p); + return r; + } + explicit_bzero(p, plen); + free(p); + return 0; +} + diff --git a/crypto/openssh/sshbuf.c b/crypto/openssh/sshbuf.c new file mode 100644 index 0000000..19e162c --- /dev/null +++ b/crypto/openssh/sshbuf.c @@ -0,0 +1,406 @@ +/* $OpenBSD: sshbuf.c,v 1.4 2015/10/05 17:11:21 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define SSHBUF_INTERNAL +#include "includes.h" + +#include /* roundup */ +#include +#include +#include +#include +#include + +#include "ssherr.h" +#include "sshbuf.h" + +static inline int +sshbuf_check_sanity(const struct sshbuf *buf) +{ + SSHBUF_TELL("sanity"); + if (__predict_false(buf == NULL || + (!buf->readonly && buf->d != buf->cd) || + buf->refcount < 1 || buf->refcount > SSHBUF_REFS_MAX || + buf->cd == NULL || + (buf->dont_free && (buf->readonly || buf->parent != NULL)) || + buf->max_size > SSHBUF_SIZE_MAX || + buf->alloc > buf->max_size || + buf->size > buf->alloc || + buf->off > buf->size)) { + /* Do not try to recover from corrupted buffer internals */ + SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); + signal(SIGSEGV, SIG_DFL); + raise(SIGSEGV); + return SSH_ERR_INTERNAL_ERROR; + } + return 0; +} + +static void +sshbuf_maybe_pack(struct sshbuf *buf, int force) +{ + SSHBUF_DBG(("force %d", force)); + SSHBUF_TELL("pre-pack"); + if (buf->off == 0 || buf->readonly || buf->refcount > 1) + return; + if (force || + (buf->off >= SSHBUF_PACK_MIN && buf->off >= buf->size / 2)) { + memmove(buf->d, buf->d + buf->off, buf->size - buf->off); + buf->size -= buf->off; + buf->off = 0; + SSHBUF_TELL("packed"); + } +} + +struct sshbuf * +sshbuf_new(void) +{ + struct sshbuf *ret; + + if ((ret = calloc(sizeof(*ret), 1)) == NULL) + return NULL; + ret->alloc = SSHBUF_SIZE_INIT; + ret->max_size = SSHBUF_SIZE_MAX; + ret->readonly = 0; + ret->refcount = 1; + ret->parent = NULL; + if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) { + free(ret); + return NULL; + } + return ret; +} + +struct sshbuf * +sshbuf_from(const void *blob, size_t len) +{ + struct sshbuf *ret; + + if (blob == NULL || len > SSHBUF_SIZE_MAX || + (ret = calloc(sizeof(*ret), 1)) == NULL) + return NULL; + ret->alloc = ret->size = ret->max_size = len; + ret->readonly = 1; + ret->refcount = 1; + ret->parent = NULL; + ret->cd = blob; + ret->d = NULL; + return ret; +} + +int +sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent) +{ + int r; + + if ((r = sshbuf_check_sanity(child)) != 0 || + (r = sshbuf_check_sanity(parent)) != 0) + return r; + child->parent = parent; + child->parent->refcount++; + return 0; +} + +struct sshbuf * +sshbuf_fromb(struct sshbuf *buf) +{ + struct sshbuf *ret; + + if (sshbuf_check_sanity(buf) != 0) + return NULL; + if ((ret = sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf))) == NULL) + return NULL; + if (sshbuf_set_parent(ret, buf) != 0) { + sshbuf_free(ret); + return NULL; + } + return ret; +} + +void +sshbuf_init(struct sshbuf *ret) +{ + explicit_bzero(ret, sizeof(*ret)); + ret->alloc = SSHBUF_SIZE_INIT; + ret->max_size = SSHBUF_SIZE_MAX; + ret->readonly = 0; + ret->dont_free = 1; + ret->refcount = 1; + if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) + ret->alloc = 0; +} + +void +sshbuf_free(struct sshbuf *buf) +{ + int dont_free = 0; + + if (buf == NULL) + return; + /* + * The following will leak on insane buffers, but this is the safest + * course of action - an invalid pointer or already-freed pointer may + * have been passed to us and continuing to scribble over memory would + * be bad. + */ + if (sshbuf_check_sanity(buf) != 0) + return; + /* + * If we are a child, the free our parent to decrement its reference + * count and possibly free it. + */ + if (buf->parent != NULL) { + sshbuf_free(buf->parent); + buf->parent = NULL; + } + /* + * If we are a parent with still-extant children, then don't free just + * yet. The last child's call to sshbuf_free should decrement our + * refcount to 0 and trigger the actual free. + */ + buf->refcount--; + if (buf->refcount > 0) + return; + dont_free = buf->dont_free; + if (!buf->readonly) { + explicit_bzero(buf->d, buf->alloc); + free(buf->d); + } + explicit_bzero(buf, sizeof(*buf)); + if (!dont_free) + free(buf); +} + +void +sshbuf_reset(struct sshbuf *buf) +{ + u_char *d; + + if (buf->readonly || buf->refcount > 1) { + /* Nonsensical. Just make buffer appear empty */ + buf->off = buf->size; + return; + } + if (sshbuf_check_sanity(buf) == 0) + explicit_bzero(buf->d, buf->alloc); + buf->off = buf->size = 0; + if (buf->alloc != SSHBUF_SIZE_INIT) { + if ((d = realloc(buf->d, SSHBUF_SIZE_INIT)) != NULL) { + buf->cd = buf->d = d; + buf->alloc = SSHBUF_SIZE_INIT; + } + } +} + +size_t +sshbuf_max_size(const struct sshbuf *buf) +{ + return buf->max_size; +} + +size_t +sshbuf_alloc(const struct sshbuf *buf) +{ + return buf->alloc; +} + +const struct sshbuf * +sshbuf_parent(const struct sshbuf *buf) +{ + return buf->parent; +} + +u_int +sshbuf_refcount(const struct sshbuf *buf) +{ + return buf->refcount; +} + +int +sshbuf_set_max_size(struct sshbuf *buf, size_t max_size) +{ + size_t rlen; + u_char *dp; + int r; + + SSHBUF_DBG(("set max buf = %p len = %zu", buf, max_size)); + if ((r = sshbuf_check_sanity(buf)) != 0) + return r; + if (max_size == buf->max_size) + return 0; + if (buf->readonly || buf->refcount > 1) + return SSH_ERR_BUFFER_READ_ONLY; + if (max_size > SSHBUF_SIZE_MAX) + return SSH_ERR_NO_BUFFER_SPACE; + /* pack and realloc if necessary */ + sshbuf_maybe_pack(buf, max_size < buf->size); + if (max_size < buf->alloc && max_size > buf->size) { + if (buf->size < SSHBUF_SIZE_INIT) + rlen = SSHBUF_SIZE_INIT; + else + rlen = roundup(buf->size, SSHBUF_SIZE_INC); + if (rlen > max_size) + rlen = max_size; + explicit_bzero(buf->d + buf->size, buf->alloc - buf->size); + SSHBUF_DBG(("new alloc = %zu", rlen)); + if ((dp = realloc(buf->d, rlen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + buf->cd = buf->d = dp; + buf->alloc = rlen; + } + SSHBUF_TELL("new-max"); + if (max_size < buf->alloc) + return SSH_ERR_NO_BUFFER_SPACE; + buf->max_size = max_size; + return 0; +} + +size_t +sshbuf_len(const struct sshbuf *buf) +{ + if (sshbuf_check_sanity(buf) != 0) + return 0; + return buf->size - buf->off; +} + +size_t +sshbuf_avail(const struct sshbuf *buf) +{ + if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) + return 0; + return buf->max_size - (buf->size - buf->off); +} + +const u_char * +sshbuf_ptr(const struct sshbuf *buf) +{ + if (sshbuf_check_sanity(buf) != 0) + return NULL; + return buf->cd + buf->off; +} + +u_char * +sshbuf_mutable_ptr(const struct sshbuf *buf) +{ + if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1) + return NULL; + return buf->d + buf->off; +} + +int +sshbuf_check_reserve(const struct sshbuf *buf, size_t len) +{ + int r; + + if ((r = sshbuf_check_sanity(buf)) != 0) + return r; + if (buf->readonly || buf->refcount > 1) + return SSH_ERR_BUFFER_READ_ONLY; + SSHBUF_TELL("check"); + /* Check that len is reasonable and that max_size + available < len */ + if (len > buf->max_size || buf->max_size - len < buf->size - buf->off) + return SSH_ERR_NO_BUFFER_SPACE; + return 0; +} + +int +sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp) +{ + size_t rlen, need; + u_char *dp; + int r; + + if (dpp != NULL) + *dpp = NULL; + + SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len)); + if ((r = sshbuf_check_reserve(buf, len)) != 0) + return r; + /* + * If the requested allocation appended would push us past max_size + * then pack the buffer, zeroing buf->off. + */ + sshbuf_maybe_pack(buf, buf->size + len > buf->max_size); + SSHBUF_TELL("reserve"); + if (len + buf->size > buf->alloc) { + /* + * Prefer to alloc in SSHBUF_SIZE_INC units, but + * allocate less if doing so would overflow max_size. + */ + need = len + buf->size - buf->alloc; + rlen = roundup(buf->alloc + need, SSHBUF_SIZE_INC); + SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen)); + if (rlen > buf->max_size) + rlen = buf->alloc + need; + SSHBUF_DBG(("adjusted rlen %zu", rlen)); + if ((dp = realloc(buf->d, rlen)) == NULL) { + SSHBUF_DBG(("realloc fail")); + if (dpp != NULL) + *dpp = NULL; + return SSH_ERR_ALLOC_FAIL; + } + buf->alloc = rlen; + buf->cd = buf->d = dp; + if ((r = sshbuf_check_reserve(buf, len)) < 0) { + /* shouldn't fail */ + if (dpp != NULL) + *dpp = NULL; + return r; + } + } + dp = buf->d + buf->size; + buf->size += len; + SSHBUF_TELL("done"); + if (dpp != NULL) + *dpp = dp; + return 0; +} + +int +sshbuf_consume(struct sshbuf *buf, size_t len) +{ + int r; + + SSHBUF_DBG(("len = %zu", len)); + if ((r = sshbuf_check_sanity(buf)) != 0) + return r; + if (len == 0) + return 0; + if (len > sshbuf_len(buf)) + return SSH_ERR_MESSAGE_INCOMPLETE; + buf->off += len; + SSHBUF_TELL("done"); + return 0; +} + +int +sshbuf_consume_end(struct sshbuf *buf, size_t len) +{ + int r; + + SSHBUF_DBG(("len = %zu", len)); + if ((r = sshbuf_check_sanity(buf)) != 0) + return r; + if (len == 0) + return 0; + if (len > sshbuf_len(buf)) + return SSH_ERR_MESSAGE_INCOMPLETE; + buf->size -= len; + SSHBUF_TELL("done"); + return 0; +} + diff --git a/crypto/openssh/sshbuf.h b/crypto/openssh/sshbuf.h new file mode 100644 index 0000000..eb0d92e --- /dev/null +++ b/crypto/openssh/sshbuf.h @@ -0,0 +1,338 @@ +/* $OpenBSD: sshbuf.h,v 1.4 2015/01/14 15:02:39 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SSHBUF_H +#define _SSHBUF_H + +#include +#include +#include +#ifdef WITH_OPENSSL +# include +# ifdef OPENSSL_HAS_ECC +# include +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + +#define SSHBUF_SIZE_MAX 0x8000000 /* Hard maximum size */ +#define SSHBUF_REFS_MAX 0x100000 /* Max child buffers */ +#define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */ +#define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */ + +/* + * NB. do not depend on the internals of this. It will be made opaque + * one day. + */ +struct sshbuf { + u_char *d; /* Data */ + const u_char *cd; /* Const data */ + size_t off; /* First available byte is buf->d + buf->off */ + size_t size; /* Last byte is buf->d + buf->size - 1 */ + size_t max_size; /* Maximum size of buffer */ + size_t alloc; /* Total bytes allocated to buf->d */ + int readonly; /* Refers to external, const data */ + int dont_free; /* Kludge to support sshbuf_init */ + u_int refcount; /* Tracks self and number of child buffers */ + struct sshbuf *parent; /* If child, pointer to parent */ +}; + +#ifndef SSHBUF_NO_DEPREACTED +/* + * NB. Please do not use sshbuf_init() in new code. Please use sshbuf_new() + * instead. sshbuf_init() is deprectated and will go away soon (it is + * only included to allow compat with buffer_* in OpenSSH) + */ +void sshbuf_init(struct sshbuf *buf); +#endif + +/* + * Create a new sshbuf buffer. + * Returns pointer to buffer on success, or NULL on allocation failure. + */ +struct sshbuf *sshbuf_new(void); + +/* + * Create a new, read-only sshbuf buffer from existing data. + * Returns pointer to buffer on success, or NULL on allocation failure. + */ +struct sshbuf *sshbuf_from(const void *blob, size_t len); + +/* + * Create a new, read-only sshbuf buffer from the contents of an existing + * buffer. The contents of "buf" must not change in the lifetime of the + * resultant buffer. + * Returns pointer to buffer on success, or NULL on allocation failure. + */ +struct sshbuf *sshbuf_fromb(struct sshbuf *buf); + +/* + * Create a new, read-only sshbuf buffer from the contents of a string in + * an existing buffer (the string is consumed in the process). + * The contents of "buf" must not change in the lifetime of the resultant + * buffer. + * Returns pointer to buffer on success, or NULL on allocation failure. + */ +int sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp); + +/* + * Clear and free buf + */ +void sshbuf_free(struct sshbuf *buf); + +/* + * Reset buf, clearing its contents. NB. max_size is preserved. + */ +void sshbuf_reset(struct sshbuf *buf); + +/* + * Return the maximum size of buf + */ +size_t sshbuf_max_size(const struct sshbuf *buf); + +/* + * Set the maximum size of buf + * Returns 0 on success, or a negative SSH_ERR_* error code on failure. + */ +int sshbuf_set_max_size(struct sshbuf *buf, size_t max_size); + +/* + * Returns the length of data in buf + */ +size_t sshbuf_len(const struct sshbuf *buf); + +/* + * Returns number of bytes left in buffer before hitting max_size. + */ +size_t sshbuf_avail(const struct sshbuf *buf); + +/* + * Returns a read-only pointer to the start of the the data in buf + */ +const u_char *sshbuf_ptr(const struct sshbuf *buf); + +/* + * Returns a mutable pointer to the start of the the data in buf, or + * NULL if the buffer is read-only. + */ +u_char *sshbuf_mutable_ptr(const struct sshbuf *buf); + +/* + * Check whether a reservation of size len will succeed in buf + * Safer to use than direct comparisons again sshbuf_avail as it copes + * with unsigned overflows correctly. + * Returns 0 on success, or a negative SSH_ERR_* error code on failure. + */ +int sshbuf_check_reserve(const struct sshbuf *buf, size_t len); + +/* + * Reserve len bytes in buf. + * Returns 0 on success and a pointer to the first reserved byte via the + * optional dpp parameter or a negative * SSH_ERR_* error code on failure. + */ +int sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp); + +/* + * Consume len bytes from the start of buf + * Returns 0 on success, or a negative SSH_ERR_* error code on failure. + */ +int sshbuf_consume(struct sshbuf *buf, size_t len); + +/* + * Consume len bytes from the end of buf + * Returns 0 on success, or a negative SSH_ERR_* error code on failure. + */ +int sshbuf_consume_end(struct sshbuf *buf, size_t len); + +/* Extract or deposit some bytes */ +int sshbuf_get(struct sshbuf *buf, void *v, size_t len); +int sshbuf_put(struct sshbuf *buf, const void *v, size_t len); +int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v); + +/* Append using a printf(3) format */ +int sshbuf_putf(struct sshbuf *buf, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +int sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap); + +/* Functions to extract or store big-endian words of various sizes */ +int sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp); +int sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp); +int sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp); +int sshbuf_get_u8(struct sshbuf *buf, u_char *valp); +int sshbuf_put_u64(struct sshbuf *buf, u_int64_t val); +int sshbuf_put_u32(struct sshbuf *buf, u_int32_t val); +int sshbuf_put_u16(struct sshbuf *buf, u_int16_t val); +int sshbuf_put_u8(struct sshbuf *buf, u_char val); + +/* + * Functions to extract or store SSH wire encoded strings (u32 len || data) + * The "cstring" variants admit no \0 characters in the string contents. + * Caller must free *valp. + */ +int sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp); +int sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp); +int sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v); +int sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len); +int sshbuf_put_cstring(struct sshbuf *buf, const char *v); +int sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v); + +/* + * "Direct" variant of sshbuf_get_string, returns pointer into the sshbuf to + * avoid an malloc+memcpy. The pointer is guaranteed to be valid until the + * next sshbuf-modifying function call. Caller does not free. + */ +int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, + size_t *lenp); + +/* Skip past a string */ +#define sshbuf_skip_string(buf) sshbuf_get_string_direct(buf, NULL, NULL) + +/* Another variant: "peeks" into the buffer without modifying it */ +int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, + size_t *lenp); + +/* + * Functions to extract or store SSH wire encoded bignums and elliptic + * curve points. + */ +int sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len); +int sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf, + const u_char **valp, size_t *lenp); +#ifdef WITH_OPENSSL +int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v); +int sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v); +int sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v); +int sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v); +# ifdef OPENSSL_HAS_ECC +int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g); +int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v); +int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g); +int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v); +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + +/* Dump the contents of the buffer in a human-readable format */ +void sshbuf_dump(struct sshbuf *buf, FILE *f); + +/* Dump specified memory in a human-readable format */ +void sshbuf_dump_data(const void *s, size_t len, FILE *f); + +/* Return the hexadecimal representation of the contents of the buffer */ +char *sshbuf_dtob16(struct sshbuf *buf); + +/* Encode the contents of the buffer as base64 */ +char *sshbuf_dtob64(struct sshbuf *buf); + +/* Decode base64 data and append it to the buffer */ +int sshbuf_b64tod(struct sshbuf *buf, const char *b64); + +/* Macros for decoding/encoding integers */ +#define PEEK_U64(p) \ + (((u_int64_t)(((u_char *)(p))[0]) << 56) | \ + ((u_int64_t)(((u_char *)(p))[1]) << 48) | \ + ((u_int64_t)(((u_char *)(p))[2]) << 40) | \ + ((u_int64_t)(((u_char *)(p))[3]) << 32) | \ + ((u_int64_t)(((u_char *)(p))[4]) << 24) | \ + ((u_int64_t)(((u_char *)(p))[5]) << 16) | \ + ((u_int64_t)(((u_char *)(p))[6]) << 8) | \ + (u_int64_t)(((u_char *)(p))[7])) +#define PEEK_U32(p) \ + (((u_int32_t)(((u_char *)(p))[0]) << 24) | \ + ((u_int32_t)(((u_char *)(p))[1]) << 16) | \ + ((u_int32_t)(((u_char *)(p))[2]) << 8) | \ + (u_int32_t)(((u_char *)(p))[3])) +#define PEEK_U16(p) \ + (((u_int16_t)(((u_char *)(p))[0]) << 8) | \ + (u_int16_t)(((u_char *)(p))[1])) + +#define POKE_U64(p, v) \ + do { \ + ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 56) & 0xff; \ + ((u_char *)(p))[1] = (((u_int64_t)(v)) >> 48) & 0xff; \ + ((u_char *)(p))[2] = (((u_int64_t)(v)) >> 40) & 0xff; \ + ((u_char *)(p))[3] = (((u_int64_t)(v)) >> 32) & 0xff; \ + ((u_char *)(p))[4] = (((u_int64_t)(v)) >> 24) & 0xff; \ + ((u_char *)(p))[5] = (((u_int64_t)(v)) >> 16) & 0xff; \ + ((u_char *)(p))[6] = (((u_int64_t)(v)) >> 8) & 0xff; \ + ((u_char *)(p))[7] = ((u_int64_t)(v)) & 0xff; \ + } while (0) +#define POKE_U32(p, v) \ + do { \ + ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 24) & 0xff; \ + ((u_char *)(p))[1] = (((u_int64_t)(v)) >> 16) & 0xff; \ + ((u_char *)(p))[2] = (((u_int64_t)(v)) >> 8) & 0xff; \ + ((u_char *)(p))[3] = ((u_int64_t)(v)) & 0xff; \ + } while (0) +#define POKE_U16(p, v) \ + do { \ + ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 8) & 0xff; \ + ((u_char *)(p))[1] = ((u_int64_t)(v)) & 0xff; \ + } while (0) + +/* Internal definitions follow. Exposed for regress tests */ +#ifdef SSHBUF_INTERNAL + +/* + * Return the allocation size of buf + */ +size_t sshbuf_alloc(const struct sshbuf *buf); + +/* + * Increment the reference count of buf. + */ +int sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent); + +/* + * Return the parent buffer of buf, or NULL if it has no parent. + */ +const struct sshbuf *sshbuf_parent(const struct sshbuf *buf); + +/* + * Return the reference count of buf + */ +u_int sshbuf_refcount(const struct sshbuf *buf); + +# define SSHBUF_SIZE_INIT 256 /* Initial allocation */ +# define SSHBUF_SIZE_INC 256 /* Preferred increment length */ +# define SSHBUF_PACK_MIN 8192 /* Minimim packable offset */ + +/* # define SSHBUF_ABORT abort */ +/* # define SSHBUF_DEBUG */ + +# ifndef SSHBUF_ABORT +# define SSHBUF_ABORT() +# endif + +# ifdef SSHBUF_DEBUG +# define SSHBUF_TELL(what) do { \ + printf("%s:%d %s: %s size %zu alloc %zu off %zu max %zu\n", \ + __FILE__, __LINE__, __func__, what, \ + buf->size, buf->alloc, buf->off, buf->max_size); \ + fflush(stdout); \ + } while (0) +# define SSHBUF_DBG(x) do { \ + printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ + printf x; \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +# else +# define SSHBUF_TELL(what) +# define SSHBUF_DBG(x) +# endif +#endif /* SSHBUF_INTERNAL */ + +#endif /* _SSHBUF_H */ diff --git a/crypto/openssh/sshconnect.c b/crypto/openssh/sshconnect.c index 3384de6..11a9cf6 100644 --- a/crypto/openssh/sshconnect.c +++ b/crypto/openssh/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.246 2014/02/06 22:21:01 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.263 2015/08/20 22:32:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -16,6 +16,7 @@ #include "includes.h" __RCSID("$FreeBSD$"); +#include /* roundup */ #include #include #include @@ -56,17 +57,20 @@ __RCSID("$FreeBSD$"); #include "sshconnect.h" #include "hostfile.h" #include "log.h" +#include "misc.h" #include "readconf.h" #include "atomicio.h" -#include "misc.h" #include "dns.h" #include "roaming.h" #include "monitor_fdpass.h" #include "ssh2.h" #include "version.h" +#include "authfile.h" +#include "ssherr.h" char *client_version_string = NULL; char *server_version_string = NULL; +Key *previous_host_key = NULL; static int matching_host_key_dns = 0; @@ -354,7 +358,7 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, goto done; } - fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS), + fdset = xcalloc(howmany(sockfd + 1, NFDBITS), sizeof(fd_mask)); FD_SET(sockfd, fdset); ms_to_timeval(&tv, *timeoutp); @@ -625,7 +629,7 @@ ssh_exchange_identification(int timeout_ms) debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); - compat_datafellows(remote_version); + active_state->compat = compat_datafellows(remote_version); mismatch = 0; switch (remote_major) { @@ -710,7 +714,7 @@ check_host_cert(const char *host, const Key *host_key) error("%s", reason); return 0; } - if (buffer_len(&host_key->cert->critical) != 0) { + if (buffer_len(host_key->cert->critical) != 0) { error("Certificate for %s contains unsupported " "critical options(s)", host); return 0; @@ -767,7 +771,7 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, if (options.proxy_command == NULL) { if (getnameinfo(hostaddr, addrlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) - fatal("check_host_key: getnameinfo failed"); + fatal("%s: getnameinfo failed", __func__); *hostfile_ipaddr = put_host_port(ntop, port); } else { *hostfile_ipaddr = xstrdup("key, SSH_FP_MD5, SSH_FP_HEX); - ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART); + fp = sshkey_fingerprint(found->key, + options.fingerprint_hash, SSH_FP_DEFAULT); + ra = sshkey_fingerprint(found->key, + options.fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); logit("WARNING: %s key found for host %s\n" "in %s:%lu\n" "%s key fingerprint %s.", @@ -1360,7 +1431,10 @@ warn_changed_key(Key *host_key) { char *fp; - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); + fp = sshkey_fingerprint(host_key, options.fingerprint_hash, + SSH_FP_DEFAULT); + if (fp == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); diff --git a/crypto/openssh/sshconnect1.c b/crypto/openssh/sshconnect1.c index 921408e..016abbc 100644 --- a/crypto/openssh/sshconnect1.c +++ b/crypto/openssh/sshconnect1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect1.c,v 1.74 2014/02/02 03:44:32 djm Exp $ */ +/* $OpenBSD: sshconnect1.c,v 1.77 2015/01/14 20:05:27 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -15,11 +15,14 @@ #include "includes.h" +#ifdef WITH_SSH1 + #include #include #include +#include #include #include #include @@ -38,15 +41,16 @@ #include "kex.h" #include "uidswap.h" #include "log.h" +#include "misc.h" #include "readconf.h" #include "authfd.h" #include "sshconnect.h" #include "authfile.h" -#include "misc.h" #include "canohost.h" #include "hostfile.h" #include "auth.h" #include "digest.h" +#include "ssherr.h" /* Session id for the current session. */ u_char session_id[16]; @@ -62,33 +66,38 @@ extern char *__progname; static int try_agent_authentication(void) { - int type; - char *comment; - AuthenticationConnection *auth; + int r, type, agent_fd, ret = 0; u_char response[16]; - u_int i; - Key *key; + size_t i; BIGNUM *challenge; + struct ssh_identitylist *idlist = NULL; /* Get connection to the agent. */ - auth = ssh_get_authentication_connection(); - if (!auth) + if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { + if (r != SSH_ERR_AGENT_NOT_PRESENT) + debug("%s: ssh_get_authentication_socket: %s", + __func__, ssh_err(r)); return 0; + } if ((challenge = BN_new()) == NULL) fatal("try_agent_authentication: BN_new failed"); - /* Loop through identities served by the agent. */ - for (key = ssh_get_first_identity(auth, &comment, 1); - key != NULL; - key = ssh_get_next_identity(auth, &comment, 1)) { + /* Loop through identities served by the agent. */ + if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) { + if (r != SSH_ERR_AGENT_NO_IDENTITIES) + debug("%s: ssh_fetch_identitylist: %s", + __func__, ssh_err(r)); + goto out; + } + for (i = 0; i < idlist->nkeys; i++) { /* Try this identity. */ - debug("Trying RSA authentication via agent with '%.100s'", comment); - free(comment); + debug("Trying RSA authentication via agent with '%.100s'", + idlist->comments[i]); /* Tell the server that we are willing to authenticate using this key. */ packet_start(SSH_CMSG_AUTH_RSA); - packet_put_bignum(key->rsa->n); + packet_put_bignum(idlist->keys[i]->rsa->n); packet_send(); packet_write_wait(); @@ -99,7 +108,6 @@ try_agent_authentication(void) does not support RSA authentication. */ if (type == SSH_SMSG_FAILURE) { debug("Server refused our key."); - key_free(key); continue; } /* Otherwise it should have sent a challenge. */ @@ -113,16 +121,17 @@ try_agent_authentication(void) debug("Received RSA challenge from server."); /* Ask the agent to decrypt the challenge. */ - if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) { + if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i], + challenge, session_id, response)) != 0) { /* * The agent failed to authenticate this identifier * although it advertised it supports this. Just * return a wrong value. */ - logit("Authentication agent failed to decrypt challenge."); + logit("Authentication agent failed to decrypt " + "challenge: %s", ssh_err(r)); explicit_bzero(response, sizeof(response)); } - key_free(key); debug("Sending response to RSA challenge."); /* Send the decrypted challenge back to the server. */ @@ -135,22 +144,25 @@ try_agent_authentication(void) /* Wait for response from the server. */ type = packet_read(); - /* The server returns success if it accepted the authentication. */ + /* + * The server returns success if it accepted the + * authentication. + */ if (type == SSH_SMSG_SUCCESS) { - ssh_close_authentication_connection(auth); - BN_clear_free(challenge); debug("RSA authentication accepted by server."); - return 1; - } - /* Otherwise it should return failure. */ - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error waiting RSA auth response: %d", - type); + ret = 1; + break; + } else if (type != SSH_SMSG_FAILURE) + packet_disconnect("Protocol error waiting RSA auth " + "response: %d", type); } - ssh_close_authentication_connection(auth); + if (ret != 1) + debug("RSA authentication using agent refused."); + out: + ssh_free_identitylist(idlist); + ssh_close_authentication_socket(agent_fd); BN_clear_free(challenge); - debug("RSA authentication using agent refused."); - return 0; + return ret; } /* @@ -166,7 +178,7 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv) /* Decrypt the challenge using the private key. */ /* XXX think about Bleichenbacher, too */ - if (rsa_private_decrypt(challenge, challenge, prv) <= 0) + if (rsa_private_decrypt(challenge, challenge, prv) != 0) packet_disconnect( "respond_to_rsa_challenge: rsa_private_decrypt failed"); @@ -253,7 +265,7 @@ try_rsa_authentication(int idx) * load the private key. Try first with empty passphrase; if it * fails, ask for a passphrase. */ - if (public->flags & KEY_FLAG_EXT) + if (public->flags & SSHKEY_FLAG_EXT) private = public; else private = key_load_private_type(KEY_RSA1, authfile, "", NULL, @@ -302,7 +314,7 @@ try_rsa_authentication(int idx) respond_to_rsa_challenge(challenge, private->rsa); /* Destroy the private key unless it in external hardware. */ - if (!(private->flags & KEY_FLAG_EXT)) + if (!(private->flags & SSHKEY_FLAG_EXT)) key_free(private); /* We no longer need the challenge. */ @@ -592,8 +604,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr) BN_num_bits(server_key->rsa->n), SSH_KEY_BITS_RESERVED); } - rsa_public_encrypt(key, key, server_key->rsa); - rsa_public_encrypt(key, key, host_key->rsa); + if (rsa_public_encrypt(key, key, server_key->rsa) != 0 || + rsa_public_encrypt(key, key, host_key->rsa) != 0) + fatal("%s: rsa_public_encrypt failed", __func__); } else { /* Host key has smaller modulus (or they are equal). */ if (BN_num_bits(server_key->rsa->n) < @@ -604,8 +617,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr) BN_num_bits(host_key->rsa->n), SSH_KEY_BITS_RESERVED); } - rsa_public_encrypt(key, key, host_key->rsa); - rsa_public_encrypt(key, key, server_key->rsa); + if (rsa_public_encrypt(key, key, host_key->rsa) != 0 || + rsa_public_encrypt(key, key, server_key->rsa) != 0) + fatal("%s: rsa_public_encrypt failed", __func__); } /* Destroy the public keys since we no longer need them. */ @@ -753,3 +767,5 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, success: return; /* need statement after label */ } + +#endif /* WITH_SSH1 */ diff --git a/crypto/openssh/sshconnect2.c b/crypto/openssh/sshconnect2.c index ec3ad6a..7751031 100644 --- a/crypto/openssh/sshconnect2.c +++ b/crypto/openssh/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.204 2014/02/02 03:44:32 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.226 2015/07/30 00:01:34 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -61,8 +61,8 @@ #include "dh.h" #include "authfd.h" #include "log.h" -#include "readconf.h" #include "misc.h" +#include "readconf.h" #include "match.h" #include "dispatch.h" #include "canohost.h" @@ -70,6 +70,7 @@ #include "pathnames.h" #include "uidswap.h" #include "hostfile.h" +#include "ssherr.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -90,10 +91,8 @@ u_int session_id2_len = 0; char *xxx_host; struct sockaddr *xxx_hostaddr; -Kex *xxx_kex = NULL; - static int -verify_host_key_callback(Key *hostkey) +verify_host_key_callback(Key *hostkey, struct ssh *ssh) { if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) fatal("Host key verification failed."); @@ -131,16 +130,17 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) } while (0) while ((alg = strsep(&avail, ",")) && *alg != '\0') { - if ((ktype = key_type_from_name(alg)) == KEY_UNSPEC) + if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) fatal("%s: unknown alg %s", __func__, alg); if (lookup_key_in_hostkeys_by_type(hostkeys, - key_type_plain(ktype), NULL)) + sshkey_type_plain(ktype), NULL)) ALG_APPEND(first, alg); else ALG_APPEND(last, alg); } #undef ALG_APPEND - xasprintf(&ret, "%s%s%s", first, *first == '\0' ? "" : ",", last); + xasprintf(&ret, "%s%s%s", first, + (*first == '\0' || *last == '\0') ? "" : ",", last); if (*first != '\0') debug3("%s: prefer hostkeyalgs: %s", __func__, first); @@ -156,23 +156,19 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) void ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) { - Kex *kex; + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + struct kex *kex; + int r; xxx_host = host; xxx_hostaddr = hostaddr; - if (options.ciphers == (char *)-1) { - logit("No valid ciphers for protocol version 2 given, using defaults."); - options.ciphers = NULL; - } - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; - } + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( + options.kex_algorithms); myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); + compat_cipher_proposal(options.ciphers); myproposal[PROPOSAL_ENC_ALGS_STOC] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); + compat_cipher_proposal(options.ciphers); if (options.compression) { myproposal[PROPOSAL_COMP_ALGS_CTOS] = myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib@openssh.com,zlib,none"; @@ -180,43 +176,46 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) myproposal[PROPOSAL_COMP_ALGS_CTOS] = myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com,zlib"; } - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; - } - if (options.hostkeyalgorithms != NULL) + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; + if (options.hostkeyalgorithms != NULL) { + if (kex_assemble_names(KEX_DEFAULT_PK_ALG, + &options.hostkeyalgorithms) != 0) + fatal("%s: kex_assemble_namelist", __func__); myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(options.hostkeyalgorithms); - else { + } else { + /* Enforce default */ + options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG); /* Prefer algorithms that we already have keys for */ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( order_hostkeyalgs(host, hostaddr, port)); } - if (options.kex_algorithms != NULL) - myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; - myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( - myproposal[PROPOSAL_KEX_ALGS]); if (options.rekey_limit || options.rekey_interval) packet_set_rekey_limits((u_int32_t)options.rekey_limit, (time_t)options.rekey_interval); /* start key exchange */ - kex = kex_setup(myproposal); + if ((r = kex_setup(active_state, myproposal)) != 0) + fatal("kex_setup: %s", ssh_err(r)); + kex = active_state->kex; +#ifdef WITH_OPENSSL kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; +# ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kexecdh_client; +# endif +#endif kex->kex[KEX_C25519_SHA256] = kexc25519_client; kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; kex->verify_host_key=&verify_host_key_callback; - xxx_kex = kex; - - dispatch_run(DISPATCH_BLOCK, &kex->done, kex); + dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); if (options.use_roaming && !kex->roaming) { debug("Roaming not allowed by server"); @@ -239,15 +238,15 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) * Authenticate user */ -typedef struct Authctxt Authctxt; -typedef struct Authmethod Authmethod; +typedef struct cauthctxt Authctxt; +typedef struct cauthmethod Authmethod; typedef struct identity Identity; typedef struct idlist Idlist; struct identity { TAILQ_ENTRY(identity) next; - AuthenticationConnection *ac; /* set if agent supports key */ - Key *key; /* public/private key */ + int agent_fd; /* >=0 if agent supports key */ + struct sshkey *key; /* public/private key */ char *filename; /* comment for agent-only keys */ int tried; int isprivate; /* key points to the private key */ @@ -255,25 +254,29 @@ struct identity { }; TAILQ_HEAD(idlist, identity); -struct Authctxt { +struct cauthctxt { const char *server_user; const char *local_user; const char *host; const char *service; - Authmethod *method; + struct cauthmethod *method; sig_atomic_t success; char *authlist; + int attempt; /* pubkey */ - Idlist keys; - AuthenticationConnection *agent; + struct idlist keys; + int agent_fd; /* hostbased */ Sensitive *sensitive; + char *oktypes, *ktypes; + const char *active_ktype; /* kbd-interactive */ int info_req_seen; /* generic */ void *methoddata; }; -struct Authmethod { + +struct cauthmethod { char *name; /* string to compare against server's list */ int (*userauth)(Authctxt *authctxt); void (*cleanup)(Authctxt *authctxt); @@ -281,14 +284,14 @@ struct Authmethod { int *batch_flag; /* flag in option struct that disables method */ }; -void input_userauth_success(int, u_int32_t, void *); -void input_userauth_success_unexpected(int, u_int32_t, void *); -void input_userauth_failure(int, u_int32_t, void *); -void input_userauth_banner(int, u_int32_t, void *); -void input_userauth_error(int, u_int32_t, void *); -void input_userauth_info_req(int, u_int32_t, void *); -void input_userauth_pk_ok(int, u_int32_t, void *); -void input_userauth_passwd_changereq(int, u_int32_t, void *); +int input_userauth_success(int, u_int32_t, void *); +int input_userauth_success_unexpected(int, u_int32_t, void *); +int input_userauth_failure(int, u_int32_t, void *); +int input_userauth_banner(int, u_int32_t, void *); +int input_userauth_error(int, u_int32_t, void *); +int input_userauth_info_req(int, u_int32_t, void *); +int input_userauth_pk_ok(int, u_int32_t, void *); +int input_userauth_passwd_changereq(int, u_int32_t, void *); int userauth_none(Authctxt *); int userauth_pubkey(Authctxt *); @@ -298,11 +301,11 @@ int userauth_hostbased(Authctxt *); #ifdef GSSAPI int userauth_gssapi(Authctxt *authctxt); -void input_gssapi_response(int type, u_int32_t, void *); -void input_gssapi_token(int type, u_int32_t, void *); -void input_gssapi_hash(int type, u_int32_t, void *); -void input_gssapi_error(int, u_int32_t, void *); -void input_gssapi_errtok(int, u_int32_t, void *); +int input_gssapi_response(int type, u_int32_t, void *); +int input_gssapi_token(int type, u_int32_t, void *); +int input_gssapi_hash(int type, u_int32_t, void *); +int input_gssapi_error(int, u_int32_t, void *); +int input_gssapi_errtok(int, u_int32_t, void *); #endif void userauth(Authctxt *, char *); @@ -395,7 +398,9 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, authctxt.authlist = NULL; authctxt.methoddata = NULL; authctxt.sensitive = sensitive; + authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; authctxt.info_req_seen = 0; + authctxt.agent_fd = -1; if (authctxt.method == NULL) fatal("ssh_userauth2: internal error: cannot send userauth none request"); @@ -450,15 +455,16 @@ userauth(Authctxt *authctxt, char *authlist) } /* ARGSUSED */ -void +int input_userauth_error(int type, u_int32_t seq, void *ctxt) { fatal("input_userauth_error: bad message during authentication: " "type %d", type); + return 0; } /* ARGSUSED */ -void +int input_userauth_banner(int type, u_int32_t seq, void *ctxt) { char *msg, *raw, *lang; @@ -477,10 +483,11 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) } free(raw); free(lang); + return 0; } /* ARGSUSED */ -void +int input_userauth_success(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; @@ -494,9 +501,10 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt) free(authctxt->methoddata); authctxt->methoddata = NULL; authctxt->success = 1; /* break out */ + return 0; } -void +int input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; @@ -506,10 +514,11 @@ input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt) fatal("Unexpected authentication success during %s.", authctxt->method->name); + return 0; } /* ARGSUSED */ -void +int input_userauth_failure(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; @@ -532,10 +541,11 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt) debug("Authentications that can continue: %s", authlist); userauth(authctxt, authlist); + return 0; } /* ARGSUSED */ -void +int input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; @@ -579,7 +589,9 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) key->type, pktype); goto done; } - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + goto done; debug2("input_userauth_pk_ok: fp %s", fp); free(fp); @@ -603,6 +615,7 @@ done: /* try another method if we did not send a packet */ if (sent == 0) userauth(authctxt, NULL); + return 0; } #ifdef GSSAPI @@ -718,7 +731,7 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok) } /* ARGSUSED */ -void +int input_gssapi_response(int type, u_int32_t plen, void *ctxt) { Authctxt *authctxt = ctxt; @@ -739,7 +752,7 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) free(oidv); debug("Badly encoded mechanism OID received"); userauth(authctxt, NULL); - return; + return 0; } if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2)) @@ -753,12 +766,13 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) /* Start again with next method on list */ debug("Trying to start again"); userauth(authctxt, NULL); - return; + return 0; } + return 0; } /* ARGSUSED */ -void +int input_gssapi_token(int type, u_int32_t plen, void *ctxt) { Authctxt *authctxt = ctxt; @@ -781,12 +795,13 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) if (GSS_ERROR(status)) { /* Start again with the next method in the list */ userauth(authctxt, NULL); - return; + return 0; } + return 0; } /* ARGSUSED */ -void +int input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) { Authctxt *authctxt = ctxt; @@ -813,10 +828,11 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) gss_release_buffer(&ms, &send_tok); /* Server will be returning a failed packet after this one */ + return 0; } /* ARGSUSED */ -void +int input_gssapi_error(int type, u_int32_t plen, void *ctxt) { char *msg; @@ -832,6 +848,7 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt) debug("Server GSSAPI Error:\n%s", msg); free(msg); free(lang); + return 0; } #endif /* GSSAPI */ @@ -886,7 +903,7 @@ userauth_passwd(Authctxt *authctxt) * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST */ /* ARGSUSED */ -void +int input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) { Authctxt *authctxt = ctxt; @@ -927,7 +944,7 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) password = read_passphrase(prompt, RP_ALLOW_EOF); if (password == NULL) { /* bail out */ - return; + return 0; } snprintf(prompt, sizeof(prompt), "Retype %.30s@%.128s's new password: ", @@ -950,30 +967,33 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, &input_userauth_passwd_changereq); + return 0; } static int -identity_sign(Identity *id, u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) +identity_sign(struct identity *id, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) { Key *prv; int ret; /* the agent supports this key */ - if (id->ac) - return (ssh_agent_sign(id->ac, id->key, sigp, lenp, - data, datalen)); + if (id->agent_fd) + return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, + data, datalen, compat); + /* * we have already loaded the private key or * the private key is stored in external hardware */ - if (id->isprivate || (id->key->flags & KEY_FLAG_EXT)) - return (key_sign(id->key, sigp, lenp, data, datalen)); + if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)) + return (sshkey_sign(id->key, sigp, lenp, data, datalen, + compat)); /* load the private key from the file */ if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL) - return (-1); - ret = key_sign(prv, sigp, lenp, data, datalen); - key_free(prv); + return (-1); /* XXX return decent error code */ + ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat); + sshkey_free(prv); return (ret); } @@ -982,13 +1002,16 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) { Buffer b; u_char *blob, *signature; - u_int bloblen, slen; + u_int bloblen; + size_t slen; u_int skip = 0; int ret = -1; int have_sig = 1; char *fp; - fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); + if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + return 0; debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); free(fp); @@ -1023,8 +1046,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) /* generate signature */ ret = identity_sign(id, &signature, &slen, - buffer_ptr(&b), buffer_len(&b)); - if (ret == -1) { + buffer_ptr(&b), buffer_len(&b), datafellows); + if (ret != 0) { free(blob); buffer_free(&b); return 0; @@ -1099,7 +1122,7 @@ load_identity_file(char *filename, int userprovided) { Key *private; char prompt[300], *passphrase; - int perm_ok = 0, quit, i; + int r, perm_ok = 0, quit = 0, i; struct stat st; if (stat(filename, &st) < 0) { @@ -1107,33 +1130,50 @@ load_identity_file(char *filename, int userprovided) filename, strerror(errno)); return NULL; } - private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok); - if (!perm_ok) { - if (private != NULL) - key_free(private); - return NULL; - } - if (private == NULL) { - if (options.batch_mode) - return NULL; - snprintf(prompt, sizeof prompt, - "Enter passphrase for key '%.100s': ", filename); - for (i = 0; i < options.number_of_password_prompts; i++) { + snprintf(prompt, sizeof prompt, + "Enter passphrase for key '%.100s': ", filename); + for (i = 0; i <= options.number_of_password_prompts; i++) { + if (i == 0) + passphrase = ""; + else { passphrase = read_passphrase(prompt, 0); - if (strcmp(passphrase, "") != 0) { - private = key_load_private_type(KEY_UNSPEC, - filename, passphrase, NULL, NULL); - quit = 0; - } else { + if (*passphrase == '\0') { debug2("no passphrase given, try next key"); + free(passphrase); + break; + } + } + switch ((r = sshkey_load_private_type(KEY_UNSPEC, filename, + passphrase, &private, NULL, &perm_ok))) { + case 0: + break; + case SSH_ERR_KEY_WRONG_PASSPHRASE: + if (options.batch_mode) { + quit = 1; + break; + } + if (i != 0) + debug2("bad passphrase given, try again..."); + break; + case SSH_ERR_SYSTEM_ERROR: + if (errno == ENOENT) { + debug2("Load key \"%s\": %s", + filename, ssh_err(r)); quit = 1; + break; } + /* FALLTHROUGH */ + default: + error("Load key \"%s\": %s", filename, ssh_err(r)); + quit = 1; + break; + } + if (i > 0) { explicit_bzero(passphrase, strlen(passphrase)); free(passphrase); - if (private != NULL || quit) - break; - debug2("bad passphrase given, try again..."); } + if (private != NULL || quit) + break; } return private; } @@ -1147,12 +1187,12 @@ load_identity_file(char *filename, int userprovided) static void pubkey_prepare(Authctxt *authctxt) { - Identity *id, *id2, *tmp; - Idlist agent, files, *preferred; - Key *key; - AuthenticationConnection *ac; - char *comment; - int i, found; + struct identity *id, *id2, *tmp; + struct idlist agent, files, *preferred; + struct sshkey *key; + int agent_fd, i, r, found; + size_t j; + struct ssh_identitylist *idlist; TAILQ_INIT(&agent); /* keys from the agent */ TAILQ_INIT(&files); /* keys from the config file */ @@ -1175,14 +1215,14 @@ pubkey_prepare(Authctxt *authctxt) } /* Prefer PKCS11 keys that are explicitly listed */ TAILQ_FOREACH_SAFE(id, &files, next, tmp) { - if (id->key == NULL || (id->key->flags & KEY_FLAG_EXT) == 0) + if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0) continue; found = 0; TAILQ_FOREACH(id2, &files, next) { if (id2->key == NULL || - (id2->key->flags & KEY_FLAG_EXT) != 0) + (id2->key->flags & SSHKEY_FLAG_EXT) == 0) continue; - if (key_equal(id->key, id2->key)) { + if (sshkey_equal(id->key, id2->key)) { TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); found = 1; @@ -1197,37 +1237,48 @@ pubkey_prepare(Authctxt *authctxt) } } /* list of keys supported by the agent */ - if ((ac = ssh_get_authentication_connection())) { - for (key = ssh_get_first_identity(ac, &comment, 2); - key != NULL; - key = ssh_get_next_identity(ac, &comment, 2)) { + if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { + if (r != SSH_ERR_AGENT_NOT_PRESENT) + debug("%s: ssh_get_authentication_socket: %s", + __func__, ssh_err(r)); + } else if ((r = ssh_fetch_identitylist(agent_fd, 2, &idlist)) != 0) { + if (r != SSH_ERR_AGENT_NO_IDENTITIES) + debug("%s: ssh_fetch_identitylist: %s", + __func__, ssh_err(r)); + } else { + for (j = 0; j < idlist->nkeys; j++) { found = 0; TAILQ_FOREACH(id, &files, next) { - /* agent keys from the config file are preferred */ - if (key_equal(key, id->key)) { - key_free(key); - free(comment); + /* + * agent keys from the config file are + * preferred + */ + if (sshkey_equal(idlist->keys[j], id->key)) { TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); - id->ac = ac; + id->agent_fd = agent_fd; found = 1; break; } } if (!found && !options.identities_only) { id = xcalloc(1, sizeof(*id)); - id->key = key; - id->filename = comment; - id->ac = ac; + /* XXX "steals" key/comment from idlist */ + id->key = idlist->keys[j]; + id->filename = idlist->comments[j]; + idlist->keys[j] = NULL; + idlist->comments[j] = NULL; + id->agent_fd = agent_fd; TAILQ_INSERT_TAIL(&agent, id, next); } } + ssh_free_identitylist(idlist); /* append remaining agent keys */ for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) { TAILQ_REMOVE(&agent, id, next); TAILQ_INSERT_TAIL(preferred, id, next); } - authctxt->agent = ac; + authctxt->agent_fd = agent_fd; } /* append remaining keys from the config file */ for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) { @@ -1245,18 +1296,38 @@ pubkey_cleanup(Authctxt *authctxt) { Identity *id; - if (authctxt->agent != NULL) - ssh_close_authentication_connection(authctxt->agent); + if (authctxt->agent_fd != -1) + ssh_close_authentication_socket(authctxt->agent_fd); for (id = TAILQ_FIRST(&authctxt->keys); id; id = TAILQ_FIRST(&authctxt->keys)) { TAILQ_REMOVE(&authctxt->keys, id, next); if (id->key) - key_free(id->key); + sshkey_free(id->key); free(id->filename); free(id); } } +static int +try_identity(Identity *id) +{ + if (!id->key) + return (0); + if (match_pattern_list(sshkey_ssh_name(id->key), + options.pubkey_key_types, 0) != 1) { + debug("Skipping %s key %s for not in PubkeyAcceptedKeyTypes", + sshkey_ssh_name(id->key), id->filename); + return (0); + } + if (key_type_plain(id->key->type) == KEY_RSA && + (datafellows & SSH_BUG_RSASIGMD5) != 0) { + debug("Skipped %s key %s for RSA/MD5 server", + key_type(id->key), id->filename); + return (0); + } + return (id->key->type != KEY_RSA1); +} + int userauth_pubkey(Authctxt *authctxt) { @@ -1275,11 +1346,7 @@ userauth_pubkey(Authctxt *authctxt) * private key instead */ if (id->key != NULL) { - if (key_type_plain(id->key->type) == KEY_RSA && - (datafellows & SSH_BUG_RSASIGMD5) != 0) { - debug("Skipped %s key %s for RSA/MD5 server", - key_type(id->key), id->filename); - } else if (id->key->type != KEY_RSA1) { + if (try_identity(id)) { debug("Offering %s public key: %s", key_type(id->key), id->filename); sent = send_pubkey_test(authctxt, id); @@ -1289,13 +1356,8 @@ userauth_pubkey(Authctxt *authctxt) id->key = load_identity_file(id->filename, id->userprovided); if (id->key != NULL) { - id->isprivate = 1; - if (key_type_plain(id->key->type) == KEY_RSA && - (datafellows & SSH_BUG_RSASIGMD5) != 0) { - debug("Skipped %s key %s for RSA/MD5 " - "server", key_type(id->key), - id->filename); - } else { + if (try_identity(id)) { + id->isprivate = 1; sent = sign_and_send_pubkey( authctxt, id); } @@ -1343,7 +1405,7 @@ userauth_kbdint(Authctxt *authctxt) /* * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ -void +int input_userauth_info_req(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; @@ -1395,81 +1457,120 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt) packet_add_padding(64); packet_send(); + return 0; } static int -ssh_keysign(Key *key, u_char **sigp, u_int *lenp, - u_char *data, u_int datalen) +ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen) { - Buffer b; + struct sshbuf *b; struct stat st; pid_t pid; - int to[2], from[2], status, version = 2; + int i, r, to[2], from[2], status, sock = packet_get_connection_in(); + u_char rversion = 0, version = 2; + void (*osigchld)(int); - debug2("ssh_keysign called"); + *sigp = NULL; + *lenp = 0; if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) { - error("ssh_keysign: not installed: %s", strerror(errno)); + error("%s: not installed: %s", __func__, strerror(errno)); + return -1; + } + if (fflush(stdout) != 0) { + error("%s: fflush: %s", __func__, strerror(errno)); return -1; } - if (fflush(stdout) != 0) - error("ssh_keysign: fflush: %s", strerror(errno)); if (pipe(to) < 0) { - error("ssh_keysign: pipe: %s", strerror(errno)); + error("%s: pipe: %s", __func__, strerror(errno)); return -1; } if (pipe(from) < 0) { - error("ssh_keysign: pipe: %s", strerror(errno)); + error("%s: pipe: %s", __func__, strerror(errno)); return -1; } if ((pid = fork()) < 0) { - error("ssh_keysign: fork: %s", strerror(errno)); + error("%s: fork: %s", __func__, strerror(errno)); return -1; } + osigchld = signal(SIGCHLD, SIG_DFL); if (pid == 0) { /* keep the socket on exec */ - fcntl(packet_get_connection_in(), F_SETFD, 0); + fcntl(sock, F_SETFD, 0); permanently_drop_suid(getuid()); close(from[0]); if (dup2(from[1], STDOUT_FILENO) < 0) - fatal("ssh_keysign: dup2: %s", strerror(errno)); + fatal("%s: dup2: %s", __func__, strerror(errno)); close(to[1]); if (dup2(to[0], STDIN_FILENO) < 0) - fatal("ssh_keysign: dup2: %s", strerror(errno)); + fatal("%s: dup2: %s", __func__, strerror(errno)); close(from[1]); close(to[0]); + /* Close everything but stdio and the socket */ + for (i = STDERR_FILENO + 1; i < sock; i++) + close(i); + closefrom(sock + 1); + debug3("%s: [child] pid=%ld, exec %s", + __func__, (long)getpid(), _PATH_SSH_KEY_SIGN); execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); - fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN, + fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN, strerror(errno)); } close(from[1]); close(to[0]); - buffer_init(&b); - buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */ - buffer_put_string(&b, data, datalen); - if (ssh_msg_send(to[1], version, &b) == -1) - fatal("ssh_keysign: couldn't send request"); - - if (ssh_msg_recv(from[0], &b) < 0) { - error("ssh_keysign: no reply"); - buffer_free(&b); - return -1; - } + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + /* send # of sock, data to be signed */ + if ((r = sshbuf_put_u32(b, sock) != 0) || + (r = sshbuf_put_string(b, data, datalen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if (ssh_msg_send(to[1], version, b) == -1) + fatal("%s: couldn't send request", __func__); + sshbuf_reset(b); + r = ssh_msg_recv(from[0], b); close(from[0]); close(to[1]); + if (r < 0) { + error("%s: no reply", __func__); + goto fail; + } - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - break; - - if (buffer_get_char(&b) != version) { - error("ssh_keysign: bad version"); - buffer_free(&b); + errno = 0; + while (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) { + error("%s: waitpid %ld: %s", + __func__, (long)pid, strerror(errno)); + goto fail; + } + } + if (!WIFEXITED(status)) { + error("%s: exited abnormally", __func__); + goto fail; + } + if (WEXITSTATUS(status) != 0) { + error("%s: exited with status %d", + __func__, WEXITSTATUS(status)); + goto fail; + } + if ((r = sshbuf_get_u8(b, &rversion)) != 0) { + error("%s: buffer error: %s", __func__, ssh_err(r)); + goto fail; + } + if (rversion != version) { + error("%s: bad version", __func__); + goto fail; + } + if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { + error("%s: buffer error: %s", __func__, ssh_err(r)); + fail: + signal(SIGCHLD, osigchld); + sshbuf_free(b); return -1; } - *sigp = buffer_get_string(&b, lenp); - buffer_free(&b); + signal(SIGCHLD, osigchld); + sshbuf_free(b); return 0; } @@ -1477,94 +1578,148 @@ ssh_keysign(Key *key, u_char **sigp, u_int *lenp, int userauth_hostbased(Authctxt *authctxt) { - Key *private = NULL; - Sensitive *sensitive = authctxt->sensitive; - Buffer b; - u_char *signature, *blob; - char *chost, *pkalg, *p; + struct ssh *ssh = active_state; + struct sshkey *private = NULL; + struct sshbuf *b = NULL; const char *service; - u_int blen, slen; - int ok, i, found = 0; - - /* check for a useful key */ - for (i = 0; i < sensitive->nkeys; i++) { - private = sensitive->keys[i]; - if (private && private->type != KEY_RSA1) { - found = 1; + u_char *sig = NULL, *keyblob = NULL; + char *fp = NULL, *chost = NULL, *lname = NULL; + size_t siglen = 0, keylen = 0; + int i, r, success = 0; + + if (authctxt->ktypes == NULL) { + authctxt->oktypes = xstrdup(options.hostbased_key_types); + authctxt->ktypes = authctxt->oktypes; + } + + /* + * Work through each listed type pattern in HostbasedKeyTypes, + * trying each hostkey that matches the type in turn. + */ + for (;;) { + if (authctxt->active_ktype == NULL) + authctxt->active_ktype = strsep(&authctxt->ktypes, ","); + if (authctxt->active_ktype == NULL || + *authctxt->active_ktype == '\0') + break; + debug3("%s: trying key type %s", __func__, + authctxt->active_ktype); + + /* check for a useful key */ + private = NULL; + for (i = 0; i < authctxt->sensitive->nkeys; i++) { + if (authctxt->sensitive->keys[i] == NULL || + authctxt->sensitive->keys[i]->type == KEY_RSA1 || + authctxt->sensitive->keys[i]->type == KEY_UNSPEC) + continue; + if (match_pattern_list( + sshkey_ssh_name(authctxt->sensitive->keys[i]), + authctxt->active_ktype, 0) != 1) + continue; /* we take and free the key */ - sensitive->keys[i] = NULL; + private = authctxt->sensitive->keys[i]; + authctxt->sensitive->keys[i] = NULL; break; } + /* Found one */ + if (private != NULL) + break; + /* No more keys of this type; advance */ + authctxt->active_ktype = NULL; } - if (!found) { + if (private == NULL) { + free(authctxt->oktypes); + authctxt->oktypes = authctxt->ktypes = NULL; + authctxt->active_ktype = NULL; debug("No more client hostkeys for hostbased authentication."); - return 0; + goto out; } - if (key_to_blob(private, &blob, &blen) == 0) { - key_free(private); - return 0; + + if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) { + error("%s: sshkey_fingerprint failed", __func__); + goto out; } + debug("%s: trying hostkey %s %s", + __func__, sshkey_ssh_name(private), fp); + /* figure out a name for the client host */ - p = get_local_name(packet_get_connection_in()); - if (p == NULL) { - error("userauth_hostbased: cannot get local ipaddr/name"); - key_free(private); - free(blob); - return 0; + if ((lname = get_local_name(packet_get_connection_in())) == NULL) { + error("%s: cannot get local ipaddr/name", __func__); + goto out; } - xasprintf(&chost, "%s.", p); - debug2("userauth_hostbased: chost %s", chost); - free(p); + + /* XXX sshbuf_put_stringf? */ + xasprintf(&chost, "%s.", lname); + debug2("%s: chost %s", __func__, chost); service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : authctxt->service; - pkalg = xstrdup(key_ssh_name(private)); - buffer_init(&b); + /* construct data */ - buffer_put_string(&b, session_id2, session_id2_len); - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->server_user); - buffer_put_cstring(&b, service); - buffer_put_cstring(&b, authctxt->method->name); - buffer_put_cstring(&b, pkalg); - buffer_put_string(&b, blob, blen); - buffer_put_cstring(&b, chost); - buffer_put_cstring(&b, authctxt->local_user); + if ((b = sshbuf_new()) == NULL) { + error("%s: sshbuf_new failed", __func__); + goto out; + } + if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { + error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); + goto out; + } + if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || + (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || + (r = sshbuf_put_cstring(b, service)) != 0 || + (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || + (r = sshbuf_put_cstring(b, key_ssh_name(private))) != 0 || + (r = sshbuf_put_string(b, keyblob, keylen)) != 0 || + (r = sshbuf_put_cstring(b, chost)) != 0 || + (r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { + error("%s: buffer error: %s", __func__, ssh_err(r)); + goto out; + } + #ifdef DEBUG_PK - buffer_dump(&b); + sshbuf_dump(b, stderr); #endif - if (sensitive->external_keysign) - ok = ssh_keysign(private, &signature, &slen, - buffer_ptr(&b), buffer_len(&b)); - else - ok = key_sign(private, &signature, &slen, - buffer_ptr(&b), buffer_len(&b)); - key_free(private); - buffer_free(&b); - if (ok != 0) { - error("key_sign failed"); - free(chost); - free(pkalg); - free(blob); - return 0; + if (authctxt->sensitive->external_keysign) + r = ssh_keysign(private, &sig, &siglen, + sshbuf_ptr(b), sshbuf_len(b)); + else if ((r = sshkey_sign(private, &sig, &siglen, + sshbuf_ptr(b), sshbuf_len(b), datafellows)) != 0) + debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); + if (r != 0) { + error("sign using hostkey %s %s failed", + sshkey_ssh_name(private), fp); + goto out; } - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_put_cstring(pkalg); - packet_put_string(blob, blen); - packet_put_cstring(chost); - packet_put_cstring(authctxt->local_user); - packet_put_string(signature, slen); - explicit_bzero(signature, slen); - free(signature); + if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || + (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || + (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || + (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || + (r = sshpkt_put_cstring(ssh, key_ssh_name(private))) != 0 || + (r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 || + (r = sshpkt_put_cstring(ssh, chost)) != 0 || + (r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || + (r = sshpkt_put_string(ssh, sig, siglen)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + error("%s: packet error: %s", __func__, ssh_err(r)); + goto out; + } + success = 1; + + out: + if (sig != NULL) { + explicit_bzero(sig, siglen); + free(sig); + } + free(keyblob); + free(lname); + free(fp); free(chost); - free(pkalg); - free(blob); + sshkey_free(private); + sshbuf_free(b); - packet_send(); - return 1; + return success; } /* find auth method */ diff --git a/crypto/openssh/sshd.0 b/crypto/openssh/sshd.0 deleted file mode 100644 index c61d515..0000000 --- a/crypto/openssh/sshd.0 +++ /dev/null @@ -1,643 +0,0 @@ -SSHD(8) OpenBSD System Manager's Manual SSHD(8) - -NAME - sshd - OpenSSH SSH daemon - -SYNOPSIS - sshd [-46DdeiqTt] [-b bits] [-C connection_spec] - [-c host_certificate_file] [-E log_file] [-f config_file] - [-g login_grace_time] [-h host_key_file] [-k key_gen_time] - [-o option] [-p port] [-u len] - -DESCRIPTION - sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these - programs replace rlogin(1) and rsh(1), and provide secure encrypted - communications between two untrusted hosts over an insecure network. - - sshd listens for connections from clients. It is normally started at - boot from /etc/rc. It forks a new daemon for each incoming connection. - The forked daemons handle key exchange, encryption, authentication, - command execution, and data exchange. - - sshd can be configured using command-line options or a configuration file - (by default sshd_config(5)); command-line options override values - specified in the configuration file. sshd rereads its configuration file - when it receives a hangup signal, SIGHUP, by executing itself with the - name and options it was started with, e.g. /usr/sbin/sshd. - - The options are as follows: - - -4 Forces sshd to use IPv4 addresses only. - - -6 Forces sshd to use IPv6 addresses only. - - -b bits - Specifies the number of bits in the ephemeral protocol version 1 - server key (default 1024). - - -C connection_spec - Specify the connection parameters to use for the -T extended test - mode. If provided, any Match directives in the configuration - file that would apply to the specified user, host, and address - will be set before the configuration is written to standard - output. The connection parameters are supplied as keyword=value - pairs. The keywords are ``user'', ``host'', ``laddr'', - ``lport'', and ``addr''. All are required and may be supplied in - any order, either with multiple -C options or as a comma- - separated list. - - -c host_certificate_file - Specifies a path to a certificate file to identify sshd during - key exchange. The certificate file must match a host key file - specified using the -h option or the HostKey configuration - directive. - - -D When this option is specified, sshd will not detach and does not - become a daemon. This allows easy monitoring of sshd. - - -d Debug mode. The server sends verbose debug output to standard - error, and does not put itself in the background. The server - also will not fork and will only process one connection. This - option is only intended for debugging for the server. Multiple - -d options increase the debugging level. Maximum is 3. - - -E log_file - Append debug logs to log_file instead of the system log. - - -e Write debug logs to standard error instead of the system log. - - -f config_file - Specifies the name of the configuration file. The default is - /etc/ssh/sshd_config. sshd refuses to start if there is no - configuration file. - - -g login_grace_time - Gives the grace time for clients to authenticate themselves - (default 120 seconds). If the client fails to authenticate the - user within this many seconds, the server disconnects and exits. - A value of zero indicates no limit. - - -h host_key_file - Specifies a file from which a host key is read. This option must - be given if sshd is not run as root (as the normal host key files - are normally not readable by anyone but root). The default is - /etc/ssh/ssh_host_key for protocol version 1, and - /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_ecdsa_key. - /etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key for - protocol version 2. It is possible to have multiple host key - files for the different protocol versions and host key - algorithms. - - -i Specifies that sshd is being run from inetd(8). sshd is normally - not run from inetd because it needs to generate the server key - before it can respond to the client, and this may take tens of - seconds. Clients would have to wait too long if the key was - regenerated every time. However, with small key sizes (e.g. 512) - using sshd from inetd may be feasible. - - -k key_gen_time - Specifies how often the ephemeral protocol version 1 server key - is regenerated (default 3600 seconds, or one hour). The - motivation for regenerating the key fairly often is that the key - is not stored anywhere, and after about an hour it becomes - impossible to recover the key for decrypting intercepted - communications even if the machine is cracked into or physically - seized. A value of zero indicates that the key will never be - regenerated. - - -o option - Can be used to give options in the format used in the - configuration file. This is useful for specifying options for - which there is no separate command-line flag. For full details - of the options, and their values, see sshd_config(5). - - -p port - Specifies the port on which the server listens for connections - (default 22). Multiple port options are permitted. Ports - specified in the configuration file with the Port option are - ignored when a command-line port is specified. Ports specified - using the ListenAddress option override command-line ports. - - -q Quiet mode. Nothing is sent to the system log. Normally the - beginning, authentication, and termination of each connection is - logged. - - -T Extended test mode. Check the validity of the configuration - file, output the effective configuration to stdout and then exit. - Optionally, Match rules may be applied by specifying the - connection parameters using one or more -C options. - - -t Test mode. Only check the validity of the configuration file and - sanity of the keys. This is useful for updating sshd reliably as - configuration options may change. - - -u len This option is used to specify the size of the field in the utmp - structure that holds the remote host name. If the resolved host - name is longer than len, the dotted decimal value will be used - instead. This allows hosts with very long host names that - overflow this field to still be uniquely identified. Specifying - -u0 indicates that only dotted decimal addresses should be put - into the utmp file. -u0 may also be used to prevent sshd from - making DNS requests unless the authentication mechanism or - configuration requires it. Authentication mechanisms that may - require DNS include RhostsRSAAuthentication, - HostbasedAuthentication, and using a from="pattern-list" option - in a key file. Configuration options that require DNS include - using a USER@HOST pattern in AllowUsers or DenyUsers. - -AUTHENTICATION - The OpenSSH SSH daemon supports SSH protocols 1 and 2. The default is to - use protocol 2 only, though this can be changed via the Protocol option - in sshd_config(5). Protocol 2 supports DSA, ECDSA, ED25519 and RSA keys; - protocol 1 only supports RSA keys. For both protocols, each host has a - host-specific key, normally 2048 bits, used to identify the host. - - Forward security for protocol 1 is provided through an additional server - key, normally 768 bits, generated when the server starts. This key is - normally regenerated every hour if it has been used, and is never stored - on disk. Whenever a client connects, the daemon responds with its public - host and server keys. The client compares the RSA host key against its - own database to verify that it has not changed. The client then - generates a 256-bit random number. It encrypts this random number using - both the host key and the server key, and sends the encrypted number to - the server. Both sides then use this random number as a session key - which is used to encrypt all further communications in the session. The - rest of the session is encrypted using a conventional cipher, currently - Blowfish or 3DES, with 3DES being used by default. The client selects - the encryption algorithm to use from those offered by the server. - - For protocol 2, forward security is provided through a Diffie-Hellman key - agreement. This key agreement results in a shared session key. The rest - of the session is encrypted using a symmetric cipher, currently 128-bit - AES, Blowfish, 3DES, CAST128, Arcfour, 192-bit AES, or 256-bit AES. The - client selects the encryption algorithm to use from those offered by the - server. Additionally, session integrity is provided through a - cryptographic message authentication code (hmac-md5, hmac-sha1, umac-64, - umac-128, hmac-ripemd160, hmac-sha2-256 or hmac-sha2-512). - - Finally, the server and the client enter an authentication dialog. The - client tries to authenticate itself using host-based authentication, - public key authentication, challenge-response authentication, or password - authentication. - - Regardless of the authentication type, the account is checked to ensure - that it is accessible. An account is not accessible if it is locked, - listed in DenyUsers or its group is listed in DenyGroups . The - definition of a locked account is system dependant. Some platforms have - their own account database (eg AIX) and some modify the passwd field ( - `*LK*' on Solaris and UnixWare, `*' on HP-UX, containing `Nologin' on - Tru64, a leading `*LOCKED*' on FreeBSD and a leading `!' on most - Linuxes). If there is a requirement to disable password authentication - for the account while allowing still public-key, then the passwd field - should be set to something other than these values (eg `NP' or `*NP*' ). - - If the client successfully authenticates itself, a dialog for preparing - the session is entered. At this time the client may request things like - allocating a pseudo-tty, forwarding X11 connections, forwarding TCP - connections, or forwarding the authentication agent connection over the - secure channel. - - After this, the client either requests a shell or execution of a command. - The sides then enter session mode. In this mode, either side may send - data at any time, and such data is forwarded to/from the shell or command - on the server side, and the user terminal in the client side. - - When the user program terminates and all forwarded X11 and other - connections have been closed, the server sends command exit status to the - client, and both sides exit. - -LOGIN PROCESS - When a user successfully logs in, sshd does the following: - - 1. If the login is on a tty, and no command has been specified, - prints last login time and /etc/motd (unless prevented in the - configuration file or by ~/.hushlogin; see the FILES section). - - 2. If the login is on a tty, records login time. - - 3. Checks /etc/nologin; if it exists, prints contents and quits - (unless root). - - 4. Changes to run with normal user privileges. - - 5. Sets up basic environment. - - 6. Reads the file ~/.ssh/environment, if it exists, and users are - allowed to change their environment. See the - PermitUserEnvironment option in sshd_config(5). - - 7. Changes to user's home directory. - - 8. If ~/.ssh/rc exists, runs it; else if /etc/ssh/sshrc exists, - runs it; otherwise runs xauth. The ``rc'' files are given the - X11 authentication protocol and cookie in standard input. See - SSHRC, below. - - 9. Runs user's shell or command. - -SSHRC - If the file ~/.ssh/rc exists, sh(1) runs it after reading the environment - files but before starting the user's shell or command. It must not - produce any output on stdout; stderr must be used instead. If X11 - forwarding is in use, it will receive the "proto cookie" pair in its - standard input (and DISPLAY in its environment). The script must call - xauth(1) because sshd will not run xauth automatically to add X11 - cookies. - - The primary purpose of this file is to run any initialization routines - which may be needed before the user's home directory becomes accessible; - AFS is a particular example of such an environment. - - This file will probably contain some initialization code followed by - something similar to: - - if read proto cookie && [ -n "$DISPLAY" ]; then - if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then - # X11UseLocalhost=yes - echo add unix:`echo $DISPLAY | - cut -c11-` $proto $cookie - else - # X11UseLocalhost=no - echo add $DISPLAY $proto $cookie - fi | xauth -q - - fi - - If this file does not exist, /etc/ssh/sshrc is run, and if that does not - exist either, xauth is used to add the cookie. - -AUTHORIZED_KEYS FILE FORMAT - AuthorizedKeysFile specifies the files containing public keys for public - key authentication; if none is specified, the default is - ~/.ssh/authorized_keys and ~/.ssh/authorized_keys2. Each line of the - file contains one key (empty lines and lines starting with a `#' are - ignored as comments). Protocol 1 public keys consist of the following - space-separated fields: options, bits, exponent, modulus, comment. - Protocol 2 public key consist of: options, keytype, base64-encoded key, - comment. The options field is optional; its presence is determined by - whether the line starts with a number or not (the options field never - starts with a number). The bits, exponent, modulus, and comment fields - give the RSA key for protocol version 1; the comment field is not used - for anything (but may be convenient for the user to identify the key). - For protocol version 2 the keytype is ``ecdsa-sha2-nistp256'', - ``ecdsa-sha2-nistp384'', ``ecdsa-sha2-nistp521'', ``ssh-ed25519'', - ``ssh-dss'' or ``ssh-rsa''. - - Note that lines in this file are usually several hundred bytes long - (because of the size of the public key encoding) up to a limit of 8 - kilobytes, which permits DSA keys up to 8 kilobits and RSA keys up to 16 - kilobits. You don't want to type them in; instead, copy the - identity.pub, id_dsa.pub, id_ecdsa.pub, id_ed25519.pub, or the id_rsa.pub - file and edit it. - - sshd enforces a minimum RSA key modulus size for protocol 1 and protocol - 2 keys of 768 bits. - - The options (if present) consist of comma-separated option - specifications. No spaces are permitted, except within double quotes. - The following option specifications are supported (note that option - keywords are case-insensitive): - - cert-authority - Specifies that the listed key is a certification authority (CA) - that is trusted to validate signed certificates for user - authentication. - - Certificates may encode access restrictions similar to these key - options. If both certificate restrictions and key options are - present, the most restrictive union of the two is applied. - - command="command" - Specifies that the command is executed whenever this key is used - for authentication. The command supplied by the user (if any) is - ignored. The command is run on a pty if the client requests a - pty; otherwise it is run without a tty. If an 8-bit clean - channel is required, one must not request a pty or should specify - no-pty. A quote may be included in the command by quoting it - with a backslash. This option might be useful to restrict - certain public keys to perform just a specific operation. An - example might be a key that permits remote backups but nothing - else. Note that the client may specify TCP and/or X11 forwarding - unless they are explicitly prohibited. The command originally - supplied by the client is available in the SSH_ORIGINAL_COMMAND - environment variable. Note that this option applies to shell, - command or subsystem execution. Also note that this command may - be superseded by either a sshd_config(5) ForceCommand directive - or a command embedded in a certificate. - - environment="NAME=value" - Specifies that the string is to be added to the environment when - logging in using this key. Environment variables set this way - override other default environment values. Multiple options of - this type are permitted. Environment processing is disabled by - default and is controlled via the PermitUserEnvironment option. - This option is automatically disabled if UseLogin is enabled. - - from="pattern-list" - Specifies that in addition to public key authentication, either - the canonical name of the remote host or its IP address must be - present in the comma-separated list of patterns. See PATTERNS in - ssh_config(5) for more information on patterns. - - In addition to the wildcard matching that may be applied to - hostnames or addresses, a from stanza may match IP addresses - using CIDR address/masklen notation. - - The purpose of this option is to optionally increase security: - public key authentication by itself does not trust the network or - name servers or anything (but the key); however, if somebody - somehow steals the key, the key permits an intruder to log in - from anywhere in the world. This additional option makes using a - stolen key more difficult (name servers and/or routers would have - to be compromised in addition to just the key). - - no-agent-forwarding - Forbids authentication agent forwarding when this key is used for - authentication. - - no-port-forwarding - Forbids TCP forwarding when this key is used for authentication. - Any port forward requests by the client will return an error. - This might be used, e.g. in connection with the command option. - - no-pty Prevents tty allocation (a request to allocate a pty will fail). - - no-user-rc - Disables execution of ~/.ssh/rc. - - no-X11-forwarding - Forbids X11 forwarding when this key is used for authentication. - Any X11 forward requests by the client will return an error. - - permitopen="host:port" - Limit local ``ssh -L'' port forwarding such that it may only - connect to the specified host and port. IPv6 addresses can be - specified by enclosing the address in square brackets. Multiple - permitopen options may be applied separated by commas. No - pattern matching is performed on the specified hostnames, they - must be literal domains or addresses. A port specification of * - matches any port. - - principals="principals" - On a cert-authority line, specifies allowed principals for - certificate authentication as a comma-separated list. At least - one name from the list must appear in the certificate's list of - principals for the certificate to be accepted. This option is - ignored for keys that are not marked as trusted certificate - signers using the cert-authority option. - - tunnel="n" - Force a tun(4) device on the server. Without this option, the - next available device will be used if the client requests a - tunnel. - - An example authorized_keys file: - - # Comments allowed at start of line - ssh-rsa AAAAB3Nza...LiPk== user@example.net - from="*.sales.example.net,!pc.sales.example.net" ssh-rsa - AAAAB2...19Q== john@example.net - command="dump /home",no-pty,no-port-forwarding ssh-dss - AAAAC3...51R== example.net - permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-dss - AAAAB5...21S== - tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...== - jane@example.net - -SSH_KNOWN_HOSTS FILE FORMAT - The /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts files contain host - public keys for all known hosts. The global file should be prepared by - the administrator (optional), and the per-user file is maintained - automatically: whenever the user connects from an unknown host, its key - is added to the per-user file. - - Each line in these files contains the following fields: markers - (optional), hostnames, bits, exponent, modulus, comment. The fields are - separated by spaces. - - The marker is optional, but if it is present then it must be one of - ``@cert-authority'', to indicate that the line contains a certification - authority (CA) key, or ``@revoked'', to indicate that the key contained - on the line is revoked and must not ever be accepted. Only one marker - should be used on a key line. - - Hostnames is a comma-separated list of patterns (`*' and `?' act as - wildcards); each pattern in turn is matched against the canonical host - name (when authenticating a client) or against the user-supplied name - (when authenticating a server). A pattern may also be preceded by `!' to - indicate negation: if the host name matches a negated pattern, it is not - accepted (by that line) even if it matched another pattern on the line. - A hostname or address may optionally be enclosed within `[' and `]' - brackets then followed by `:' and a non-standard port number. - - Alternately, hostnames may be stored in a hashed form which hides host - names and addresses should the file's contents be disclosed. Hashed - hostnames start with a `|' character. Only one hashed hostname may - appear on a single line and none of the above negation or wildcard - operators may be applied. - - Bits, exponent, and modulus are taken directly from the RSA host key; - they can be obtained, for example, from /etc/ssh/ssh_host_key.pub. The - optional comment field continues to the end of the line, and is not used. - - Lines starting with `#' and empty lines are ignored as comments. - - When performing host authentication, authentication is accepted if any - matching line has the proper key; either one that matches exactly or, if - the server has presented a certificate for authentication, the key of the - certification authority that signed the certificate. For a key to be - trusted as a certification authority, it must use the ``@cert-authority'' - marker described above. - - The known hosts file also provides a facility to mark keys as revoked, - for example when it is known that the associated private key has been - stolen. Revoked keys are specified by including the ``@revoked'' marker - at the beginning of the key line, and are never accepted for - authentication or as certification authorities, but instead will produce - a warning from ssh(1) when they are encountered. - - It is permissible (but not recommended) to have several lines or - different host keys for the same names. This will inevitably happen when - short forms of host names from different domains are put in the file. It - is possible that the files contain conflicting information; - authentication is accepted if valid information can be found from either - file. - - Note that the lines in these files are typically hundreds of characters - long, and you definitely don't want to type in the host keys by hand. - Rather, generate them by a script, ssh-keyscan(1) or by taking - /etc/ssh/ssh_host_key.pub and adding the host names at the front. - ssh-keygen(1) also offers some basic automated editing for - ~/.ssh/known_hosts including removing hosts matching a host name and - converting all host names to their hashed representations. - - An example ssh_known_hosts file: - - # Comments allowed at start of line - closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net - cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....= - # A hashed hostname - |1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa - AAAA1234.....= - # A revoked key - @revoked * ssh-rsa AAAAB5W... - # A CA key, accepted for any host in *.mydomain.com or *.mydomain.org - @cert-authority *.mydomain.org,*.mydomain.com ssh-rsa AAAAB5W... - -FILES - ~/.hushlogin - This file is used to suppress printing the last login time and - /etc/motd, if PrintLastLog and PrintMotd, respectively, are - enabled. It does not suppress printing of the banner specified - by Banner. - - ~/.rhosts - This file is used for host-based authentication (see ssh(1) for - more information). On some machines this file may need to be - world-readable if the user's home directory is on an NFS - partition, because sshd reads it as root. Additionally, this - file must be owned by the user, and must not have write - permissions for anyone else. The recommended permission for most - machines is read/write for the user, and not accessible by - others. - - ~/.shosts - This file is used in exactly the same way as .rhosts, but allows - host-based authentication without permitting login with - rlogin/rsh. - - ~/.ssh/ - This directory is the default location for all user-specific - configuration and authentication information. There is no - general requirement to keep the entire contents of this directory - secret, but the recommended permissions are read/write/execute - for the user, and not accessible by others. - - ~/.ssh/authorized_keys - Lists the public keys (DSA, ECDSA, ED25519, RSA) that can be used - for logging in as this user. The format of this file is - described above. The content of the file is not highly - sensitive, but the recommended permissions are read/write for the - user, and not accessible by others. - - If this file, the ~/.ssh directory, or the user's home directory - are writable by other users, then the file could be modified or - replaced by unauthorized users. In this case, sshd will not - allow it to be used unless the StrictModes option has been set to - ``no''. - - ~/.ssh/environment - This file is read into the environment at login (if it exists). - It can only contain empty lines, comment lines (that start with - `#'), and assignment lines of the form name=value. The file - should be writable only by the user; it need not be readable by - anyone else. Environment processing is disabled by default and - is controlled via the PermitUserEnvironment option. - - ~/.ssh/known_hosts - Contains a list of host keys for all hosts the user has logged - into that are not already in the systemwide list of known host - keys. The format of this file is described above. This file - should be writable only by root/the owner and can, but need not - be, world-readable. - - ~/.ssh/rc - Contains initialization routines to be run before the user's home - directory becomes accessible. This file should be writable only - by the user, and need not be readable by anyone else. - - /etc/hosts.allow - /etc/hosts.deny - Access controls that should be enforced by tcp-wrappers are - defined here. Further details are described in hosts_access(5). - - /etc/hosts.equiv - This file is for host-based authentication (see ssh(1)). It - should only be writable by root. - - /etc/moduli - Contains Diffie-Hellman groups used for the "Diffie-Hellman Group - Exchange". The file format is described in moduli(5). - - /etc/motd - See motd(5). - - /etc/nologin - If this file exists, sshd refuses to let anyone except root log - in. The contents of the file are displayed to anyone trying to - log in, and non-root connections are refused. The file should be - world-readable. - - /etc/shosts.equiv - This file is used in exactly the same way as hosts.equiv, but - allows host-based authentication without permitting login with - rlogin/rsh. - - /etc/ssh/ssh_host_key - /etc/ssh/ssh_host_dsa_key - /etc/ssh/ssh_host_ecdsa_key - /etc/ssh/ssh_host_ed25519_key - /etc/ssh/ssh_host_rsa_key - These files contain the private parts of the host keys. These - files should only be owned by root, readable only by root, and - not accessible to others. Note that sshd does not start if these - files are group/world-accessible. - - /etc/ssh/ssh_host_key.pub - /etc/ssh/ssh_host_dsa_key.pub - /etc/ssh/ssh_host_ecdsa_key.pub - /etc/ssh/ssh_host_ed25519_key.pub - /etc/ssh/ssh_host_rsa_key.pub - These files contain the public parts of the host keys. These - files should be world-readable but writable only by root. Their - contents should match the respective private parts. These files - are not really used for anything; they are provided for the - convenience of the user so their contents can be copied to known - hosts files. These files are created using ssh-keygen(1). - - /etc/ssh/ssh_known_hosts - Systemwide list of known host keys. This file should be prepared - by the system administrator to contain the public host keys of - all machines in the organization. The format of this file is - described above. This file should be writable only by root/the - owner and should be world-readable. - - /etc/ssh/sshd_config - Contains configuration data for sshd. The file format and - configuration options are described in sshd_config(5). - - /etc/ssh/sshrc - Similar to ~/.ssh/rc, it can be used to specify machine-specific - login-time initializations globally. This file should be - writable only by root, and should be world-readable. - - /var/empty - chroot(2) directory used by sshd during privilege separation in - the pre-authentication phase. The directory should not contain - any files and must be owned by root and not group or world- - writable. - - /var/run/sshd.pid - Contains the process ID of the sshd listening for connections (if - there are several daemons running concurrently for different - ports, this contains the process ID of the one started last). - The content of this file is not sensitive; it can be world- - readable. - -SEE ALSO - scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), - ssh-keyscan(1), chroot(2), hosts_access(5), login.conf(5), moduli(5), - sshd_config(5), inetd(8), sftp-server(8) - -AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by - Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support - for privilege separation. - -CAVEATS - System security is not improved unless rshd, rlogind, and rexecd are - disabled (thus completely disabling rlogin and rsh into the machine). - -OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 diff --git a/crypto/openssh/sshd.8 b/crypto/openssh/sshd.8 index 56aa37c..517ecbd 100644 --- a/crypto/openssh/sshd.8 +++ b/crypto/openssh/sshd.8 @@ -33,9 +33,9 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.273 2013/12/07 11:58:46 naddy Exp $ +.\" $OpenBSD: sshd.8,v 1.280 2015/07/03 03:49:45 djm Exp $ .\" $FreeBSD$ -.Dd $Mdocdate: December 7 2013 $ +.Dd $Mdocdate: July 3 2015 $ .Dt SSHD 8 .Os .Sh NAME @@ -61,10 +61,7 @@ .Nm (OpenSSH Daemon) is the daemon program for .Xr ssh 1 . -Together these programs replace -.Xr rlogin 1 -and -.Xr rsh 1 , +Together these programs replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network. .Pp @@ -188,15 +185,12 @@ Specifies that .Nm is being run from .Xr inetd 8 . +If SSH protocol 1 is enabled, .Nm -is normally not run +should not normally be run from inetd because it needs to generate the server key before it can -respond to the client, and this may take tens of seconds. -Clients would have to wait too long if the key was regenerated every time. -However, with small key sizes (e.g. 512) using -.Nm -from inetd may -be feasible. +respond to the client, and this may take some time. +Clients may have to wait too long if the key was regenerated every time. .It Fl k Ar key_gen_time Specifies how often the ephemeral protocol version 1 server key is regenerated (default 3600 seconds, or one hour). @@ -282,7 +276,7 @@ though this can be changed via the .Cm Protocol option in .Xr sshd_config 5 . -Protocol 2 supports DSA, ECDSA, ED25519 and RSA keys; +Protocol 2 supports DSA, ECDSA, Ed25519 and RSA keys; protocol 1 only supports RSA keys. For both protocols, each host has a host-specific key, @@ -291,7 +285,7 @@ used to identify the host. .Pp Forward security for protocol 1 is provided through an additional server key, -normally 768 bits, +normally 1024 bits, generated when the server starts. This key is normally regenerated every hour if it has been used, and is never stored on disk. @@ -413,7 +407,10 @@ Changes to user's home directory. .It If .Pa ~/.ssh/rc -exists, runs it; else if +exists and the +.Xr sshd_config 5 +.Cm PermitUserRC +option is set, runs it; else if .Pa /etc/ssh/sshrc exists, runs it; otherwise runs @@ -427,6 +424,8 @@ See below. .It Runs user's shell or command. +All commands are run under the user's login shell as specified in the +system password database. .El .Sh SSHRC If the file @@ -607,10 +606,10 @@ Disables execution of Forbids X11 forwarding when this key is used for authentication. Any X11 forward requests by the client will return an error. .It Cm permitopen="host:port" -Limit local -.Li ``ssh -L'' -port forwarding such that it may only connect to the specified host and -port. +Limit local port forwarding with +.Xr ssh 1 +.Fl L +such that it may only connect to the specified host and port. IPv6 addresses can be specified by enclosing the address in square brackets. Multiple .Cm permitopen @@ -811,7 +810,7 @@ secret, but the recommended permissions are read/write/execute for the user, and not accessible by others. .Pp .It Pa ~/.ssh/authorized_keys -Lists the public keys (DSA, ECDSA, ED25519, RSA) +Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used for logging in as this user. The format of this file is described above. The content of the file is not highly sensitive, but the recommended @@ -980,14 +979,3 @@ Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. -.Sh CAVEATS -System security is not improved unless -.Nm rshd , -.Nm rlogind , -and -.Nm rexecd -are disabled (thus completely disabling -.Xr rlogin -and -.Xr rsh -into the machine). diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c index 838ed89..3db3551 100644 --- a/crypto/openssh/sshd.c +++ b/crypto/openssh/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.420 2014/02/26 21:53:37 markus Exp $ */ +/* $OpenBSD: sshd.c,v 1.458 2015/08/20 22:32:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -73,11 +73,14 @@ __RCSID("$FreeBSD$"); #include #include #include +#include +#ifdef WITH_OPENSSL #include #include #include #include "openbsd-compat/openssl-compat.h" +#endif #ifdef HAVE_SECUREWARE #include @@ -102,6 +105,8 @@ __RCSID("$FreeBSD$"); #include "packet.h" #include "log.h" #include "buffer.h" +#include "misc.h" +#include "match.h" #include "servconf.h" #include "uidswap.h" #include "compat.h" @@ -109,7 +114,6 @@ __RCSID("$FreeBSD$"); #include "digest.h" #include "key.h" #include "kex.h" -#include "dh.h" #include "myproposal.h" #include "authfile.h" #include "pathnames.h" @@ -118,7 +122,6 @@ __RCSID("$FreeBSD$"); #include "hostfile.h" #include "auth.h" #include "authfd.h" -#include "misc.h" #include "msg.h" #include "dispatch.h" #include "channels.h" @@ -132,6 +135,7 @@ __RCSID("$FreeBSD$"); #include "roaming.h" #include "ssh-sandbox.h" #include "version.h" +#include "ssherr.h" #ifdef LIBWRAP #include @@ -203,11 +207,8 @@ int num_listen_socks = 0; char *client_version_string = NULL; char *server_version_string = NULL; -/* for rekeying XXX fixme */ -Kex *xxx_kex; - /* Daemon's agent connection */ -AuthenticationConnection *auth_conn = NULL; +int auth_sock = -1; int have_agent = 0; /* @@ -247,7 +248,7 @@ u_char *session_id2 = NULL; u_int session_id2_len = 0; /* record remote hostname or ip */ -u_int utmp_len = MAXHOSTNAMELEN; +u_int utmp_len = HOST_NAME_MAX+1; /* options.max_startup sized array of fd ints */ int *startup_pipes = NULL; @@ -274,7 +275,9 @@ struct passwd *privsep_pw = NULL; void destroy_sensitive_data(void); void demote_sensitive_data(void); +#ifdef WITH_SSH1 static void do_ssh1_kex(void); +#endif static void do_ssh2_kex(void); /* @@ -501,7 +504,7 @@ sshd_exchange_identification(int sock_in, int sock_out) debug("Client protocol version %d.%d; client software version %.100s", remote_major, remote_minor, remote_version); - compat_datafellows(remote_version); + active_state->compat = compat_datafellows(remote_version); if ((datafellows & SSH_BUG_PROBE) != 0) { logit("probed from %s with %s. Don't panic.", @@ -637,7 +640,11 @@ privsep_preauth_child(void) arc4random_stir(); arc4random_buf(rnd, sizeof(rnd)); +#ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); + if ((RAND_bytes((u_char *)rnd, 1)) != 1) + fatal("%s: RAND_bytes failed", __func__); +#endif explicit_bzero(rnd, sizeof(rnd)); /* Demote the private keys to public keys. */ @@ -667,14 +674,14 @@ privsep_preauth_child(void) static int privsep_preauth(Authctxt *authctxt) { - int status; + int status, r; pid_t pid; struct ssh_sandbox *box = NULL; /* Set up unprivileged child process to deal with network data */ pmonitor = monitor_init(); /* Store a pointer to the kex for later rekeying */ - pmonitor->m_pkex = &xxx_kex; + pmonitor->m_pkex = &active_state->kex; if (use_privsep == PRIVSEP_ON) box = ssh_sandbox_init(pmonitor); @@ -685,8 +692,14 @@ privsep_preauth(Authctxt *authctxt) debug2("Network child is on pid %ld", (long)pid); pmonitor->m_pid = pid; - if (have_agent) - auth_conn = ssh_get_authentication_connection(); + if (have_agent) { + r = ssh_get_authentication_socket(&auth_sock); + if (r != 0) { + error("Could not get agent socket: %s", + ssh_err(r)); + have_agent = 0; + } + } if (box != NULL) ssh_sandbox_parent_preauth(box, pid); monitor_child_preauth(authctxt, pmonitor); @@ -772,7 +785,11 @@ privsep_postauth(Authctxt *authctxt) arc4random_stir(); arc4random_buf(rnd, sizeof(rnd)); +#ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); + if ((RAND_bytes((u_char *)rnd, 1)) != 1) + fatal("%s: RAND_bytes failed", __func__); +#endif explicit_bzero(rnd, sizeof(rnd)); /* Drop privileges */ @@ -803,8 +820,15 @@ list_hostkey_types(void) key = sensitive_data.host_keys[i]; if (key == NULL) key = sensitive_data.host_pubkeys[i]; - if (key == NULL) + if (key == NULL || key->type == KEY_RSA1) continue; + /* Check that the key is accepted in HostkeyAlgorithms */ + if (match_pattern_list(sshkey_ssh_name(key), + options.hostkeyalgorithms, 0) != 1) { + debug3("%s: %s key not permitted by HostkeyAlgorithms", + __func__, sshkey_ssh_name(key)); + continue; + } switch (key->type) { case KEY_RSA: case KEY_DSA: @@ -821,8 +845,6 @@ list_hostkey_types(void) if (key == NULL) continue; switch (key->type) { - case KEY_RSA_CERT_V00: - case KEY_DSA_CERT_V00: case KEY_RSA_CERT: case KEY_DSA_CERT: case KEY_ECDSA_CERT: @@ -842,15 +864,13 @@ list_hostkey_types(void) } static Key * -get_hostkey_by_type(int type, int need_private) +get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) { int i; Key *key; for (i = 0; i < options.num_host_key_files; i++) { switch (type) { - case KEY_RSA_CERT_V00: - case KEY_DSA_CERT_V00: case KEY_RSA_CERT: case KEY_DSA_CERT: case KEY_ECDSA_CERT: @@ -863,7 +883,8 @@ get_hostkey_by_type(int type, int need_private) key = sensitive_data.host_pubkeys[i]; break; } - if (key != NULL && key->type == type) + if (key != NULL && key->type == type && + (key->type != KEY_ECDSA || key->ecdsa_nid == nid)) return need_private ? sensitive_data.host_keys[i] : key; } @@ -871,15 +892,15 @@ get_hostkey_by_type(int type, int need_private) } Key * -get_hostkey_public_by_type(int type) +get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) { - return get_hostkey_by_type(type, 0); + return get_hostkey_by_type(type, nid, 0, ssh); } Key * -get_hostkey_private_by_type(int type) +get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) { - return get_hostkey_by_type(type, 1); + return get_hostkey_by_type(type, nid, 1, ssh); } Key * @@ -891,7 +912,7 @@ get_hostkey_by_index(int ind) } Key * -get_hostkey_public_by_index(int ind) +get_hostkey_public_by_index(int ind, struct ssh *ssh) { if (ind < 0 || ind >= options.num_host_key_files) return (NULL); @@ -899,24 +920,75 @@ get_hostkey_public_by_index(int ind) } int -get_hostkey_index(Key *key) +get_hostkey_index(Key *key, int compare, struct ssh *ssh) { int i; for (i = 0; i < options.num_host_key_files; i++) { if (key_is_cert(key)) { - if (key == sensitive_data.host_certificates[i]) + if (key == sensitive_data.host_certificates[i] || + (compare && sensitive_data.host_certificates[i] && + sshkey_equal(key, + sensitive_data.host_certificates[i]))) return (i); } else { - if (key == sensitive_data.host_keys[i]) + if (key == sensitive_data.host_keys[i] || + (compare && sensitive_data.host_keys[i] && + sshkey_equal(key, sensitive_data.host_keys[i]))) return (i); - if (key == sensitive_data.host_pubkeys[i]) + if (key == sensitive_data.host_pubkeys[i] || + (compare && sensitive_data.host_pubkeys[i] && + sshkey_equal(key, sensitive_data.host_pubkeys[i]))) return (i); } } return (-1); } +/* Inform the client of all hostkeys */ +static void +notify_hostkeys(struct ssh *ssh) +{ + struct sshbuf *buf; + struct sshkey *key; + int i, nkeys, r; + char *fp; + + /* Some clients cannot cope with the hostkeys message, skip those. */ + if (datafellows & SSH_BUG_HOSTKEYS) + return; + + if ((buf = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + for (i = nkeys = 0; i < options.num_host_key_files; i++) { + key = get_hostkey_public_by_index(i, ssh); + if (key == NULL || key->type == KEY_UNSPEC || + key->type == KEY_RSA1 || sshkey_is_cert(key)) + continue; + fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT); + debug3("%s: key %d: %s %s", __func__, i, + sshkey_ssh_name(key), fp); + free(fp); + if (nkeys == 0) { + packet_start(SSH2_MSG_GLOBAL_REQUEST); + packet_put_cstring("hostkeys-00@openssh.com"); + packet_put_char(0); /* want-reply */ + } + sshbuf_reset(buf); + if ((r = sshkey_putb(key, buf)) != 0) + fatal("%s: couldn't put hostkey %d: %s", + __func__, i, ssh_err(r)); + packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf)); + nkeys++; + } + debug3("%s: sent %d hostkeys", __func__, nkeys); + if (nkeys == 0) + fatal("%s: no hostkeys", __func__); + packet_send(); + sshbuf_free(buf); +} + /* * returns 1 if connection should be dropped, 0 otherwise. * dropping starts at connection #max_startups_begin with a probability @@ -951,10 +1023,10 @@ usage(void) if (options.version_addendum && *options.version_addendum != '\0') fprintf(stderr, "%s %s, %s\n", SSH_RELEASE, - options.version_addendum, SSLeay_version(SSLEAY_VERSION)); + options.version_addendum, OPENSSL_VERSION); else fprintf(stderr, "%s, %s\n", - SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); + SSH_RELEASE, OPENSSL_VERSION); fprintf(stderr, "usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n" " [-E log_file] [-f config_file] [-g login_grace_time]\n" @@ -987,6 +1059,7 @@ send_rexec_state(int fd, Buffer *conf) buffer_init(&m); buffer_put_cstring(&m, buffer_ptr(conf)); +#ifdef WITH_SSH1 if (sensitive_data.server_key != NULL && sensitive_data.server_key->type == KEY_RSA1) { buffer_put_int(&m, 1); @@ -997,9 +1070,10 @@ send_rexec_state(int fd, Buffer *conf) buffer_put_bignum(&m, sensitive_data.server_key->rsa->p); buffer_put_bignum(&m, sensitive_data.server_key->rsa->q); } else +#endif buffer_put_int(&m, 0); -#ifndef OPENSSL_PRNG_ONLY +#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) rexec_send_rng_seed(&m); #endif @@ -1033,6 +1107,7 @@ recv_rexec_state(int fd, Buffer *conf) free(cp); if (buffer_get_int(&m)) { +#ifdef WITH_SSH1 if (sensitive_data.server_key != NULL) key_free(sensitive_data.server_key); sensitive_data.server_key = key_new_private(KEY_RSA1); @@ -1042,11 +1117,14 @@ recv_rexec_state(int fd, Buffer *conf) buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); - rsa_generate_additional_parameters( - sensitive_data.server_key->rsa); + if (rsa_generate_additional_parameters( + sensitive_data.server_key->rsa) != 0) + fatal("%s: rsa_generate_additional_parameters " + "error", __func__); +#endif } -#ifndef OPENSSL_PRNG_ONLY +#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) rexec_recv_rng_seed(&m); #endif @@ -1202,7 +1280,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) sighup_restart(); if (fdset != NULL) free(fdset); - fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS), + fdset = xcalloc(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask)); for (i = 0; i < num_listen_socks; i++) @@ -1219,7 +1297,8 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) logit("Received signal %d; terminating.", (int) received_sigterm); close_listen_socks(); - unlink(options.pid_file); + if (options.pid_file != NULL) + unlink(options.pid_file); exit(received_sigterm == SIGTERM ? 0 : 255); } if (key_used && key_do_regen) { @@ -1382,7 +1461,11 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) */ arc4random_stir(); arc4random_buf(rnd, sizeof(rnd)); +#ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); + if ((RAND_bytes((u_char *)rnd, 1)) != 1) + fatal("%s: RAND_bytes failed", __func__); +#endif explicit_bzero(rnd, sizeof(rnd)); } @@ -1401,11 +1484,11 @@ main(int ac, char **av) { extern char *optarg; extern int optind; - int opt, i, j, on = 1; + int r, opt, i, j, on = 1; int sock_in = -1, sock_out = -1, newsock = -1; const char *remote_ip; int remote_port; - char *line, *logfile = NULL; + char *fp, *line, *laddr, *logfile = NULL; int config_s[2] = { -1 , -1 }; u_int n; u_int64_t ibytes, obytes; @@ -1445,7 +1528,8 @@ main(int ac, char **av) initialize_server_options(&options); /* Parse command-line arguments. */ - while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeE:iqrtQRT46")) != -1) { + while ((opt = getopt(ac, av, + "C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrt")) != -1) { switch (opt) { case '4': options.address_family = AF_INET; @@ -1544,8 +1628,8 @@ main(int ac, char **av) exit(1); break; case 'u': - utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL); - if (utmp_len > MAXHOSTNAMELEN) { + utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL); + if (utmp_len > HOST_NAME_MAX+1) { fprintf(stderr, "Invalid utmp length.\n"); exit(1); } @@ -1572,7 +1656,9 @@ main(int ac, char **av) else closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); +#ifdef WITH_OPENSSL OpenSSL_add_all_algorithms(); +#endif /* If requested, redirect the logs to the specified logfile. */ if (logfile != NULL) { @@ -1625,7 +1711,7 @@ main(int ac, char **av) buffer_init(&cfg); if (rexeced_flag) recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg); - else + else if (strcasecmp(config_file_name, "none") != 0) load_server_config(config_file_name, &cfg); parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, @@ -1646,6 +1732,11 @@ main(int ac, char **av) strcasecmp(options.authorized_keys_command, "none") != 0)) fatal("AuthorizedKeysCommand set without " "AuthorizedKeysCommandUser"); + if (options.authorized_principals_command_user == NULL && + (options.authorized_principals_command != NULL && + strcasecmp(options.authorized_principals_command, "none") != 0)) + fatal("AuthorizedPrincipalsCommand set without " + "AuthorizedPrincipalsCommandUser"); /* * Check whether there is any path through configured auth methods. @@ -1677,7 +1768,12 @@ main(int ac, char **av) } debug("sshd version %s, %s", SSH_VERSION, - SSLeay_version(SSLEAY_VERSION)); +#ifdef WITH_OPENSSL + SSLeay_version(SSLEAY_VERSION) +#else + "without OpenSSL" +#endif + ); /* Store privilege separation user for later use if required. */ if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { @@ -1698,21 +1794,25 @@ main(int ac, char **av) sizeof(Key *)); sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, sizeof(Key *)); - for (i = 0; i < options.num_host_key_files; i++) { - sensitive_data.host_keys[i] = NULL; - sensitive_data.host_pubkeys[i] = NULL; - } if (options.host_key_agent) { if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) setenv(SSH_AUTHSOCKET_ENV_NAME, options.host_key_agent, 1); - have_agent = ssh_agent_present(); + if ((r = ssh_get_authentication_socket(NULL)) == 0) + have_agent = 1; + else + error("Could not connect to agent \"%s\": %s", + options.host_key_agent, ssh_err(r)); } for (i = 0; i < options.num_host_key_files; i++) { + if (options.host_key_files[i] == NULL) + continue; key = key_load_private(options.host_key_files[i], "", NULL); pubkey = key_load_public(options.host_key_files[i], NULL); + if (pubkey == NULL && key != NULL) + pubkey = key_demote(key); sensitive_data.host_keys[i] = key; sensitive_data.host_pubkeys[i] = pubkey; @@ -1740,11 +1840,17 @@ main(int ac, char **av) case KEY_DSA: case KEY_ECDSA: case KEY_ED25519: - sensitive_data.have_ssh2_key = 1; + if (have_agent || key != NULL) + sensitive_data.have_ssh2_key = 1; break; } - debug("private host key: #%d type %d %s", i, keytype, - key_type(key ? key : pubkey)); + if ((fp = sshkey_fingerprint(pubkey, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + fatal("sshkey_fingerprint failed"); + debug("%s host key #%d: %s %s", + key ? "private" : "agent", i, keytype == KEY_RSA1 ? + sshkey_type(pubkey) : sshkey_ssh_name(pubkey), fp); + free(fp); } if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { logit("Disabling protocol version 1. Could not load host key"); @@ -1769,6 +1875,8 @@ main(int ac, char **av) sensitive_data.host_certificates[i] = NULL; for (i = 0; i < options.num_host_cert_files; i++) { + if (options.host_cert_files[i] == NULL) + continue; key = key_load_public(options.host_cert_files[i], NULL); if (key == NULL) { error("Could not load host certificate: %s", @@ -1799,10 +1907,12 @@ main(int ac, char **av) debug("host certificate: #%d type %d %s", j, key->type, key_type(key)); } + +#ifdef WITH_SSH1 /* Check certain values for sanity. */ if (options.protocol & SSH_PROTO_1) { - if (options.server_key_bits < 512 || - options.server_key_bits > 32768) { + if (options.server_key_bits < SSH_RSA_MINIMUM_MODULUS_SIZE || + options.server_key_bits > OPENSSL_RSA_MAX_MODULUS_BITS) { fprintf(stderr, "Bad server key size.\n"); exit(1); } @@ -1823,6 +1933,7 @@ main(int ac, char **av) options.server_key_bits); } } +#endif if (use_privsep) { struct stat st; @@ -1937,7 +2048,7 @@ main(int ac, char **av) * Write out the pid file after the sigterm handler * is setup and the listen sockets are bound */ - if (!debug_flag) { + if (options.pid_file != NULL && !debug_flag) { FILE *f = fopen(options.pid_file, "w"); if (f == NULL) { @@ -2103,9 +2214,10 @@ main(int ac, char **av) #endif /* LIBWRAP */ /* Log the connection. */ + laddr = get_local_ipaddr(sock_in); verbose("Connection from %s port %d on %s port %d", - remote_ip, remote_port, - get_local_ipaddr(sock_in), get_local_port()); + remote_ip, remote_port, laddr, get_local_port()); + free(laddr); /* * We don't want to listen forever unless the other side @@ -2142,8 +2254,12 @@ main(int ac, char **av) if (use_privsep) { if (privsep_preauth(authctxt) == 1) goto authenticated; - } else if (compat20 && have_agent) - auth_conn = ssh_get_authentication_connection(); + } else if (compat20 && have_agent) { + if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { + error("Unable to get agent socket: %s", ssh_err(r)); + have_agent = 0; + } + } /* perform the key exchange */ /* authenticate user and start session */ @@ -2151,8 +2267,12 @@ main(int ac, char **av) do_ssh2_kex(); do_authentication2(authctxt); } else { +#ifdef WITH_SSH1 do_ssh1_kex(); do_authentication(authctxt); +#else + fatal("ssh1 not supported"); +#endif } /* * If we use privilege separation, the unprivileged child transfers @@ -2208,12 +2328,15 @@ main(int ac, char **av) packet_set_timeout(options.client_alive_interval, options.client_alive_count_max); + /* Try to send all our hostkeys to the client */ + if (compat20) + notify_hostkeys(active_state); + /* Start session. */ do_authenticated(authctxt); /* The connection has been terminated. */ - packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); - packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); + packet_get_bytes(&ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); @@ -2236,6 +2359,7 @@ main(int ac, char **av) exit(0); } +#ifdef WITH_SSH1 /* * Decrypt session_key_int using our private server key and private host key * (key with larger modulus first). @@ -2259,10 +2383,10 @@ ssh1_session_key(BIGNUM *session_key_int) SSH_KEY_BITS_RESERVED); } if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) <= 0) + sensitive_data.server_key->rsa) != 0) rsafail++; if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) <= 0) + sensitive_data.ssh1_host_key->rsa) != 0) rsafail++; } else { /* Host key has bigger modulus (or they are equal). */ @@ -2277,14 +2401,15 @@ ssh1_session_key(BIGNUM *session_key_int) SSH_KEY_BITS_RESERVED); } if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) < 0) + sensitive_data.ssh1_host_key->rsa) != 0) rsafail++; if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) < 0) + sensitive_data.server_key->rsa) != 0) rsafail++; } return (rsafail); } + /* * SSH1 key exchange */ @@ -2293,8 +2418,10 @@ do_ssh1_kex(void) { int i, len; int rsafail = 0; - BIGNUM *session_key_int; + BIGNUM *session_key_int, *fake_key_int, *real_key_int; u_char session_key[SSH_SESSION_KEY_LENGTH]; + u_char fake_key_bytes[4096 / 8]; + size_t fake_key_len; u_char cookie[8]; u_int cipher_type, auth_mask, protocol_flags; @@ -2372,74 +2499,61 @@ do_ssh1_kex(void) debug("Encryption type: %.200s", cipher_name(cipher_type)); /* Get the encrypted integer. */ - if ((session_key_int = BN_new()) == NULL) + if ((real_key_int = BN_new()) == NULL) fatal("do_ssh1_kex: BN_new failed"); - packet_get_bignum(session_key_int); + packet_get_bignum(real_key_int); protocol_flags = packet_get_int(); packet_set_protocol_flags(protocol_flags); packet_check_eom(); - /* Decrypt session_key_int using host/server keys */ - rsafail = PRIVSEP(ssh1_session_key(session_key_int)); + /* Setup a fake key in case RSA decryption fails */ + if ((fake_key_int = BN_new()) == NULL) + fatal("do_ssh1_kex: BN_new failed"); + fake_key_len = BN_num_bytes(real_key_int); + if (fake_key_len > sizeof(fake_key_bytes)) + fake_key_len = sizeof(fake_key_bytes); + arc4random_buf(fake_key_bytes, fake_key_len); + if (BN_bin2bn(fake_key_bytes, fake_key_len, fake_key_int) == NULL) + fatal("do_ssh1_kex: BN_bin2bn failed"); + + /* Decrypt real_key_int using host/server keys */ + rsafail = PRIVSEP(ssh1_session_key(real_key_int)); + /* If decryption failed, use the fake key. Else, the real key. */ + if (rsafail) + session_key_int = fake_key_int; + else + session_key_int = real_key_int; /* * Extract session key from the decrypted integer. The key is in the * least significant 256 bits of the integer; the first byte of the * key is in the highest bits. */ - if (!rsafail) { - (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); - len = BN_num_bytes(session_key_int); - if (len < 0 || (u_int)len > sizeof(session_key)) { - error("do_ssh1_kex: bad session key len from %s: " - "session_key_int %d > sizeof(session_key) %lu", - get_remote_ipaddr(), len, (u_long)sizeof(session_key)); - rsafail++; - } else { - explicit_bzero(session_key, sizeof(session_key)); - BN_bn2bin(session_key_int, - session_key + sizeof(session_key) - len); - - derive_ssh1_session_id( - sensitive_data.ssh1_host_key->rsa->n, - sensitive_data.server_key->rsa->n, - cookie, session_id); - /* - * Xor the first 16 bytes of the session key with the - * session id. - */ - for (i = 0; i < 16; i++) - session_key[i] ^= session_id[i]; - } - } - if (rsafail) { - int bytes = BN_num_bytes(session_key_int); - u_char *buf = xmalloc(bytes); - struct ssh_digest_ctx *md; - - logit("do_connection: generating a fake encryption key"); - BN_bn2bin(session_key_int, buf); - if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || - ssh_digest_update(md, buf, bytes) < 0 || - ssh_digest_update(md, sensitive_data.ssh1_cookie, - SSH_SESSION_KEY_LENGTH) < 0 || - ssh_digest_final(md, session_key, sizeof(session_key)) < 0) - fatal("%s: md5 failed", __func__); - ssh_digest_free(md); - if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || - ssh_digest_update(md, session_key, 16) < 0 || - ssh_digest_update(md, sensitive_data.ssh1_cookie, - SSH_SESSION_KEY_LENGTH) < 0 || - ssh_digest_final(md, session_key + 16, - sizeof(session_key) - 16) < 0) - fatal("%s: md5 failed", __func__); - ssh_digest_free(md); - explicit_bzero(buf, bytes); - free(buf); + (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); + len = BN_num_bytes(session_key_int); + if (len < 0 || (u_int)len > sizeof(session_key)) { + error("do_ssh1_kex: bad session key len from %s: " + "session_key_int %d > sizeof(session_key) %lu", + get_remote_ipaddr(), len, (u_long)sizeof(session_key)); + rsafail++; + } else { + explicit_bzero(session_key, sizeof(session_key)); + BN_bn2bin(session_key_int, + session_key + sizeof(session_key) - len); + + derive_ssh1_session_id( + sensitive_data.ssh1_host_key->rsa->n, + sensitive_data.server_key->rsa->n, + cookie, session_id); + /* + * Xor the first 16 bytes of the session key with the + * session id. + */ for (i = 0; i < 16; i++) - session_id[i] = session_key[i] ^ session_key[i + 16]; + session_key[i] ^= session_id[i]; } + /* Destroy the private and public keys. No longer. */ destroy_sensitive_data(); @@ -2447,7 +2561,8 @@ do_ssh1_kex(void) mm_ssh1_session_id(session_id); /* Destroy the decrypted integer. It is no longer needed. */ - BN_clear_free(session_key_int); + BN_clear_free(real_key_int); + BN_clear_free(fake_key_int); /* Set the session key. From this on all communications will be encrypted. */ packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type); @@ -2462,45 +2577,51 @@ do_ssh1_kex(void) packet_send(); packet_write_wait(); } +#endif -void -sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, - u_char *data, u_int dlen) +int +sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen, + const u_char *data, size_t dlen, u_int flag) { + int r; + u_int xxx_slen, xxx_dlen = dlen; + if (privkey) { - if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0)) + if (PRIVSEP(key_sign(privkey, signature, &xxx_slen, data, xxx_dlen) < 0)) fatal("%s: key_sign failed", __func__); + if (slen) + *slen = xxx_slen; } else if (use_privsep) { - if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0) + if (mm_key_sign(pubkey, signature, &xxx_slen, data, xxx_dlen) < 0) fatal("%s: pubkey_sign failed", __func__); + if (slen) + *slen = xxx_slen; } else { - if (ssh_agent_sign(auth_conn, pubkey, signature, slen, data, - dlen)) - fatal("%s: ssh_agent_sign failed", __func__); + if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slen, + data, dlen, datafellows)) != 0) + fatal("%s: ssh_agent_sign failed: %s", + __func__, ssh_err(r)); } + return 0; } -/* - * SSH2 key exchange: diffie-hellman-group1-sha1 - */ +/* SSH2 key exchange */ static void do_ssh2_kex(void) { - Kex *kex; + char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; + struct kex *kex; + int r; + + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( + options.kex_algorithms); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal( + options.ciphers); + myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal( + options.ciphers); + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); - myproposal[PROPOSAL_ENC_ALGS_STOC] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); - - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; - } if (options.compression == COMP_NONE) { myproposal[PROPOSAL_COMP_ALGS_CTOS] = myproposal[PROPOSAL_COMP_ALGS_STOC] = "none"; @@ -2508,11 +2629,6 @@ do_ssh2_kex(void) myproposal[PROPOSAL_COMP_ALGS_CTOS] = myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com"; } - if (options.kex_algorithms != NULL) - myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; - - myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( - myproposal[PROPOSAL_KEX_ALGS]); if (options.rekey_limit || options.rekey_interval) packet_set_rekey_limits((u_int32_t)options.rekey_limit, @@ -2522,12 +2638,18 @@ do_ssh2_kex(void) list_hostkey_types()); /* start key exchange */ - kex = kex_setup(myproposal); + if ((r = kex_setup(active_state, myproposal)) != 0) + fatal("kex_setup: %s", ssh_err(r)); + kex = active_state->kex; +#ifdef WITH_OPENSSL kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; +# ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kexecdh_server; +# endif +#endif kex->kex[KEX_C25519_SHA256] = kexc25519_server; kex->server = 1; kex->client_version_string=client_version_string; @@ -2537,9 +2659,7 @@ do_ssh2_kex(void) kex->host_key_index=&get_hostkey_index; kex->sign = sshd_hostkey_sign; - xxx_kex = kex; - - dispatch_run(DISPATCH_BLOCK, &kex->done, kex); + dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); session_id2 = kex->session_id; session_id2_len = kex->session_id_len; @@ -2560,7 +2680,8 @@ cleanup_exit(int i) { if (the_authctxt) { do_cleanup(the_authctxt); - if (use_privsep && privsep_is_preauth && pmonitor->m_pid > 1) { + if (use_privsep && privsep_is_preauth && + pmonitor != NULL && pmonitor->m_pid > 1) { debug("Killing privsep child %d", pmonitor->m_pid); if (kill(pmonitor->m_pid, SIGKILL) != 0 && errno != ESRCH) diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config index 011c714..4901e30 100644 --- a/crypto/openssh/sshd_config +++ b/crypto/openssh/sshd_config @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.93 2014/01/10 05:59:19 djm Exp $ +# $OpenBSD: sshd_config,v 1.97 2015/08/06 14:53:21 deraadt Exp $ # $FreeBSD$ # This is the sshd server system-wide configuration file. See @@ -120,7 +120,7 @@ #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none -#VersionAddendum FreeBSD-20160124 +#VersionAddendum FreeBSD-20160125 # no default banner path #Banner none diff --git a/crypto/openssh/sshd_config.0 b/crypto/openssh/sshd_config.0 deleted file mode 100644 index 413c260..0000000 --- a/crypto/openssh/sshd_config.0 +++ /dev/null @@ -1,835 +0,0 @@ -SSHD_CONFIG(5) OpenBSD Programmer's Manual SSHD_CONFIG(5) - -NAME - sshd_config - OpenSSH SSH daemon configuration file - -SYNOPSIS - /etc/ssh/sshd_config - -DESCRIPTION - sshd(8) reads configuration data from /etc/ssh/sshd_config (or the file - specified with -f on the command line). The file contains keyword- - argument pairs, one per line. Lines starting with `#' and empty lines - are interpreted as comments. Arguments may optionally be enclosed in - double quotes (") in order to represent arguments containing spaces. - - The possible keywords and their meanings are as follows (note that - keywords are case-insensitive and arguments are case-sensitive): - - AcceptEnv - Specifies what environment variables sent by the client will be - copied into the session's environ(7). See SendEnv in - ssh_config(5) for how to configure the client. Note that - environment passing is only supported for protocol 2. Variables - are specified by name, which may contain the wildcard characters - `*' and `?'. Multiple environment variables may be separated by - whitespace or spread across multiple AcceptEnv directives. Be - warned that some environment variables could be used to bypass - restricted user environments. For this reason, care should be - taken in the use of this directive. The default is not to accept - any environment variables. - - AddressFamily - Specifies which address family should be used by sshd(8). Valid - arguments are ``any'', ``inet'' (use IPv4 only), or ``inet6'' - (use IPv6 only). The default is ``any''. - - AllowAgentForwarding - Specifies whether ssh-agent(1) forwarding is permitted. The - default is ``yes''. Note that disabling agent forwarding does - not improve security unless users are also denied shell access, - as they can always install their own forwarders. - - AllowGroups - This keyword can be followed by a list of group name patterns, - separated by spaces. If specified, login is allowed only for - users whose primary group or supplementary group list matches one - of the patterns. Only group names are valid; a numerical group - ID is not recognized. By default, login is allowed for all - groups. The allow/deny directives are processed in the following - order: DenyUsers, AllowUsers, DenyGroups, and finally - AllowGroups. - - See PATTERNS in ssh_config(5) for more information on patterns. - - AllowTcpForwarding - Specifies whether TCP forwarding is permitted. The available - options are ``yes'' or ``all'' to allow TCP forwarding, ``no'' to - prevent all TCP forwarding, ``local'' to allow local (from the - perspective of ssh(1)) forwarding only or ``remote'' to allow - remote forwarding only. The default is ``yes''. Note that - disabling TCP forwarding does not improve security unless users - are also denied shell access, as they can always install their - own forwarders. - - AllowUsers - This keyword can be followed by a list of user name patterns, - separated by spaces. If specified, login is allowed only for - user names that match one of the patterns. Only user names are - valid; a numerical user ID is not recognized. By default, login - is allowed for all users. If the pattern takes the form - USER@HOST then USER and HOST are separately checked, restricting - logins to particular users from particular hosts. The allow/deny - directives are processed in the following order: DenyUsers, - AllowUsers, DenyGroups, and finally AllowGroups. - - See PATTERNS in ssh_config(5) for more information on patterns. - - AuthenticationMethods - Specifies the authentication methods that must be successfully - completed for a user to be granted access. This option must be - followed by one or more comma-separated lists of authentication - method names. Successful authentication requires completion of - every method in at least one of these lists. - - For example, an argument of ``publickey,password - publickey,keyboard-interactive'' would require the user to - complete public key authentication, followed by either password - or keyboard interactive authentication. Only methods that are - next in one or more lists are offered at each stage, so for this - example, it would not be possible to attempt password or - keyboard-interactive authentication before public key. - - For keyboard interactive authentication it is also possible to - restrict authentication to a specific device by appending a colon - followed by the device identifier ``bsdauth'', ``pam'', or - ``skey'', depending on the server configuration. For example, - ``keyboard-interactive:bsdauth'' would restrict keyboard - interactive authentication to the ``bsdauth'' device. - - This option is only available for SSH protocol 2 and will yield a - fatal error if enabled if protocol 1 is also enabled. Note that - each authentication method listed should also be explicitly - enabled in the configuration. The default is not to require - multiple authentication; successful completion of a single - authentication method is sufficient. - - AuthorizedKeysCommand - Specifies a program to be used to look up the user's public keys. - The program must be owned by root and not writable by group or - others. It will be invoked with a single argument of the - username being authenticated, and should produce on standard - output zero or more lines of authorized_keys output (see - AUTHORIZED_KEYS in sshd(8)). If a key supplied by - AuthorizedKeysCommand does not successfully authenticate and - authorize the user then public key authentication continues using - the usual AuthorizedKeysFile files. By default, no - AuthorizedKeysCommand is run. - - AuthorizedKeysCommandUser - Specifies the user under whose account the AuthorizedKeysCommand - is run. It is recommended to use a dedicated user that has no - other role on the host than running authorized keys commands. - - AuthorizedKeysFile - Specifies the file that contains the public keys that can be used - for user authentication. The format is described in the - AUTHORIZED_KEYS FILE FORMAT section of sshd(8). - AuthorizedKeysFile may contain tokens of the form %T which are - substituted during connection setup. The following tokens are - defined: %% is replaced by a literal '%', %h is replaced by the - home directory of the user being authenticated, and %u is - replaced by the username of that user. After expansion, - AuthorizedKeysFile is taken to be an absolute path or one - relative to the user's home directory. Multiple files may be - listed, separated by whitespace. The default is - ``.ssh/authorized_keys .ssh/authorized_keys2''. - - AuthorizedPrincipalsFile - Specifies a file that lists principal names that are accepted for - certificate authentication. When using certificates signed by a - key listed in TrustedUserCAKeys, this file lists names, one of - which must appear in the certificate for it to be accepted for - authentication. Names are listed one per line preceded by key - options (as described in AUTHORIZED_KEYS FILE FORMAT in sshd(8)). - Empty lines and comments starting with `#' are ignored. - - AuthorizedPrincipalsFile may contain tokens of the form %T which - are substituted during connection setup. The following tokens - are defined: %% is replaced by a literal '%', %h is replaced by - the home directory of the user being authenticated, and %u is - replaced by the username of that user. After expansion, - AuthorizedPrincipalsFile is taken to be an absolute path or one - relative to the user's home directory. - - The default is ``none'', i.e. not to use a principals file - in - this case, the username of the user must appear in a - certificate's principals list for it to be accepted. Note that - AuthorizedPrincipalsFile is only used when authentication - proceeds using a CA listed in TrustedUserCAKeys and is not - consulted for certification authorities trusted via - ~/.ssh/authorized_keys, though the principals= key option offers - a similar facility (see sshd(8) for details). - - Banner The contents of the specified file are sent to the remote user - before authentication is allowed. If the argument is ``none'' - then no banner is displayed. This option is only available for - protocol version 2. By default, no banner is displayed. - - ChallengeResponseAuthentication - Specifies whether challenge-response authentication is allowed - (e.g. via PAM or though authentication styles supported in - login.conf(5)) The default is ``yes''. - - ChrootDirectory - Specifies the pathname of a directory to chroot(2) to after - authentication. All components of the pathname must be root- - owned directories that are not writable by any other user or - group. After the chroot, sshd(8) changes the working directory - to the user's home directory. - - The pathname may contain the following tokens that are expanded - at runtime once the connecting user has been authenticated: %% is - replaced by a literal '%', %h is replaced by the home directory - of the user being authenticated, and %u is replaced by the - username of that user. - - The ChrootDirectory must contain the necessary files and - directories to support the user's session. For an interactive - session this requires at least a shell, typically sh(1), and - basic /dev nodes such as null(4), zero(4), stdin(4), stdout(4), - stderr(4), arandom(4) and tty(4) devices. For file transfer - sessions using ``sftp'', no additional configuration of the - environment is necessary if the in-process sftp server is used, - though sessions which use logging do require /dev/log inside the - chroot directory (see sftp-server(8) for details). - - The default is not to chroot(2). - - Ciphers - Specifies the ciphers allowed for protocol version 2. Multiple - ciphers must be comma-separated. The supported ciphers are: - - ``3des-cbc'', ``aes128-cbc'', ``aes192-cbc'', ``aes256-cbc'', - ``aes128-ctr'', ``aes192-ctr'', ``aes256-ctr'', - ``aes128-gcm@openssh.com'', ``aes256-gcm@openssh.com'', - ``arcfour128'', ``arcfour256'', ``arcfour'', ``blowfish-cbc'', - ``cast128-cbc'', and ``chacha20-poly1305@openssh.com''. - - The default is: - - aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, - aes128-gcm@openssh.com,aes256-gcm@openssh.com, - chacha20-poly1305@openssh.com, - aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, - aes256-cbc,arcfour - - The list of available ciphers may also be obtained using the -Q - option of ssh(1). - - ClientAliveCountMax - Sets the number of client alive messages (see below) which may be - sent without sshd(8) receiving any messages back from the client. - If this threshold is reached while client alive messages are - being sent, sshd will disconnect the client, terminating the - session. It is important to note that the use of client alive - messages is very different from TCPKeepAlive (below). The client - alive messages are sent through the encrypted channel and - therefore will not be spoofable. The TCP keepalive option - enabled by TCPKeepAlive is spoofable. The client alive mechanism - is valuable when the client or server depend on knowing when a - connection has become inactive. - - The default value is 3. If ClientAliveInterval (see below) is - set to 15, and ClientAliveCountMax is left at the default, - unresponsive SSH clients will be disconnected after approximately - 45 seconds. This option applies to protocol version 2 only. - - ClientAliveInterval - Sets a timeout interval in seconds after which if no data has - been received from the client, sshd(8) will send a message - through the encrypted channel to request a response from the - client. The default is 0, indicating that these messages will - not be sent to the client. This option applies to protocol - version 2 only. - - Compression - Specifies whether compression is allowed, or delayed until the - user has authenticated successfully. The argument must be - ``yes'', ``delayed'', or ``no''. The default is ``delayed''. - - DenyGroups - This keyword can be followed by a list of group name patterns, - separated by spaces. Login is disallowed for users whose primary - group or supplementary group list matches one of the patterns. - Only group names are valid; a numerical group ID is not - recognized. By default, login is allowed for all groups. The - allow/deny directives are processed in the following order: - DenyUsers, AllowUsers, DenyGroups, and finally AllowGroups. - - See PATTERNS in ssh_config(5) for more information on patterns. - - DenyUsers - This keyword can be followed by a list of user name patterns, - separated by spaces. Login is disallowed for user names that - match one of the patterns. Only user names are valid; a - numerical user ID is not recognized. By default, login is - allowed for all users. If the pattern takes the form USER@HOST - then USER and HOST are separately checked, restricting logins to - particular users from particular hosts. The allow/deny - directives are processed in the following order: DenyUsers, - AllowUsers, DenyGroups, and finally AllowGroups. - - See PATTERNS in ssh_config(5) for more information on patterns. - - ForceCommand - Forces the execution of the command specified by ForceCommand, - ignoring any command supplied by the client and ~/.ssh/rc if - present. The command is invoked by using the user's login shell - with the -c option. This applies to shell, command, or subsystem - execution. It is most useful inside a Match block. The command - originally supplied by the client is available in the - SSH_ORIGINAL_COMMAND environment variable. Specifying a command - of ``internal-sftp'' will force the use of an in-process sftp - server that requires no support files when used with - ChrootDirectory. - - GatewayPorts - Specifies whether remote hosts are allowed to connect to ports - forwarded for the client. By default, sshd(8) binds remote port - forwardings to the loopback address. This prevents other remote - hosts from connecting to forwarded ports. GatewayPorts can be - used to specify that sshd should allow remote port forwardings to - bind to non-loopback addresses, thus allowing other hosts to - connect. The argument may be ``no'' to force remote port - forwardings to be available to the local host only, ``yes'' to - force remote port forwardings to bind to the wildcard address, or - ``clientspecified'' to allow the client to select the address to - which the forwarding is bound. The default is ``no''. - - GSSAPIAuthentication - Specifies whether user authentication based on GSSAPI is allowed. - The default is ``no''. Note that this option applies to protocol - version 2 only. - - GSSAPICleanupCredentials - Specifies whether to automatically destroy the user's credentials - cache on logout. The default is ``yes''. Note that this option - applies to protocol version 2 only. - - HostbasedAuthentication - Specifies whether rhosts or /etc/hosts.equiv authentication - together with successful public key client host authentication is - allowed (host-based authentication). This option is similar to - RhostsRSAAuthentication and applies to protocol version 2 only. - The default is ``no''. - - HostbasedUsesNameFromPacketOnly - Specifies whether or not the server will attempt to perform a - reverse name lookup when matching the name in the ~/.shosts, - ~/.rhosts, and /etc/hosts.equiv files during - HostbasedAuthentication. A setting of ``yes'' means that sshd(8) - uses the name supplied by the client rather than attempting to - resolve the name from the TCP connection itself. The default is - ``no''. - - HostCertificate - Specifies a file containing a public host certificate. The - certificate's public key must match a private host key already - specified by HostKey. The default behaviour of sshd(8) is not to - load any certificates. - - HostKey - Specifies a file containing a private host key used by SSH. The - default is /etc/ssh/ssh_host_key for protocol version 1, and - /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_ecdsa_key, - /etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key for - protocol version 2. Note that sshd(8) will refuse to use a file - if it is group/world-accessible. It is possible to have multiple - host key files. ``rsa1'' keys are used for version 1 and - ``dsa'', ``ecdsa'', ``ed25519'' or ``rsa'' are used for version 2 - of the SSH protocol. It is also possible to specify public host - key files instead. In this case operations on the private key - will be delegated to an ssh-agent(1). - - HostKeyAgent - Identifies the UNIX-domain socket used to communicate with an - agent that has access to the private host keys. If - ``SSH_AUTH_SOCK'' is specified, the location of the socket will - be read from the SSH_AUTH_SOCK environment variable. - - IgnoreRhosts - Specifies that .rhosts and .shosts files will not be used in - RhostsRSAAuthentication or HostbasedAuthentication. - - /etc/hosts.equiv and /etc/shosts.equiv are still used. The - default is ``yes''. - - IgnoreUserKnownHosts - Specifies whether sshd(8) should ignore the user's - ~/.ssh/known_hosts during RhostsRSAAuthentication or - HostbasedAuthentication. The default is ``no''. - - IPQoS Specifies the IPv4 type-of-service or DSCP class for the - connection. Accepted values are ``af11'', ``af12'', ``af13'', - ``af21'', ``af22'', ``af23'', ``af31'', ``af32'', ``af33'', - ``af41'', ``af42'', ``af43'', ``cs0'', ``cs1'', ``cs2'', ``cs3'', - ``cs4'', ``cs5'', ``cs6'', ``cs7'', ``ef'', ``lowdelay'', - ``throughput'', ``reliability'', or a numeric value. This option - may take one or two arguments, separated by whitespace. If one - argument is specified, it is used as the packet class - unconditionally. If two values are specified, the first is - automatically selected for interactive sessions and the second - for non-interactive sessions. The default is ``lowdelay'' for - interactive sessions and ``throughput'' for non-interactive - sessions. - - KbdInteractiveAuthentication - Specifies whether to allow keyboard-interactive authentication. - The argument to this keyword must be ``yes'' or ``no''. The - default is to use whatever value ChallengeResponseAuthentication - is set to (by default ``yes''). - - KerberosAuthentication - Specifies whether the password provided by the user for - PasswordAuthentication will be validated through the Kerberos - KDC. To use this option, the server needs a Kerberos servtab - which allows the verification of the KDC's identity. The default - is ``no''. - - KerberosGetAFSToken - If AFS is active and the user has a Kerberos 5 TGT, attempt to - acquire an AFS token before accessing the user's home directory. - The default is ``no''. - - KerberosOrLocalPasswd - If password authentication through Kerberos fails then the - password will be validated via any additional local mechanism - such as /etc/passwd. The default is ``yes''. - - KerberosTicketCleanup - Specifies whether to automatically destroy the user's ticket - cache file on logout. The default is ``yes''. - - KexAlgorithms - Specifies the available KEX (Key Exchange) algorithms. Multiple - algorithms must be comma-separated. The default is - - curve25519-sha256@libssh.org, - ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, - diffie-hellman-group-exchange-sha256, - diffie-hellman-group-exchange-sha1, - diffie-hellman-group14-sha1, - diffie-hellman-group1-sha1 - - KeyRegenerationInterval - In protocol version 1, the ephemeral server key is automatically - regenerated after this many seconds (if it has been used). The - purpose of regeneration is to prevent decrypting captured - sessions by later breaking into the machine and stealing the - keys. The key is never stored anywhere. If the value is 0, the - key is never regenerated. The default is 3600 (seconds). - - ListenAddress - Specifies the local addresses sshd(8) should listen on. The - following forms may be used: - - ListenAddress host|IPv4_addr|IPv6_addr - ListenAddress host|IPv4_addr:port - ListenAddress [host|IPv6_addr]:port - - If port is not specified, sshd will listen on the address and all - prior Port options specified. The default is to listen on all - local addresses. Multiple ListenAddress options are permitted. - Additionally, any Port options must precede this option for non- - port qualified addresses. - - LoginGraceTime - The server disconnects after this time if the user has not - successfully logged in. If the value is 0, there is no time - limit. The default is 120 seconds. - - LogLevel - Gives the verbosity level that is used when logging messages from - sshd(8). The possible values are: QUIET, FATAL, ERROR, INFO, - VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. - DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify - higher levels of debugging output. Logging with a DEBUG level - violates the privacy of users and is not recommended. - - MACs Specifies the available MAC (message authentication code) - algorithms. The MAC algorithm is used in protocol version 2 for - data integrity protection. Multiple algorithms must be comma- - separated. The algorithms that contain ``-etm'' calculate the - MAC after encryption (encrypt-then-mac). These are considered - safer and their use recommended. The default is: - - hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, - umac-64-etm@openssh.com,umac-128-etm@openssh.com, - hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, - hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, - hmac-md5-96-etm@openssh.com, - hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, - hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, - hmac-sha1-96,hmac-md5-96 - - Match Introduces a conditional block. If all of the criteria on the - Match line are satisfied, the keywords on the following lines - override those set in the global section of the config file, - until either another Match line or the end of the file. If a - keyword appears in multiple Match blocks that are satisified, - only the first instance of the keyword is applied. - - The arguments to Match are one or more criteria-pattern pairs or - the single token All which matches all criteria. The available - criteria are User, Group, Host, LocalAddress, LocalPort, and - Address. The match patterns may consist of single entries or - comma-separated lists and may use the wildcard and negation - operators described in the PATTERNS section of ssh_config(5). - - The patterns in an Address criteria may additionally contain - addresses to match in CIDR address/masklen format, e.g. - ``192.0.2.0/24'' or ``3ffe:ffff::/32''. Note that the mask - length provided must be consistent with the address - it is an - error to specify a mask length that is too long for the address - or one with bits set in this host portion of the address. For - example, ``192.0.2.0/33'' and ``192.0.2.0/8'' respectively. - - Only a subset of keywords may be used on the lines following a - Match keyword. Available keywords are AcceptEnv, - AllowAgentForwarding, AllowGroups, AllowTcpForwarding, - AllowUsers, AuthenticationMethods, AuthorizedKeysCommand, - AuthorizedKeysCommandUser, AuthorizedKeysFile, - AuthorizedPrincipalsFile, Banner, ChrootDirectory, DenyGroups, - DenyUsers, ForceCommand, GatewayPorts, GSSAPIAuthentication, - HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, - KbdInteractiveAuthentication, KerberosAuthentication, - MaxAuthTries, MaxSessions, PasswordAuthentication, - PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTTY, - PermitTunnel, PubkeyAuthentication, RekeyLimit, - RhostsRSAAuthentication, RSAAuthentication, X11DisplayOffset, - X11Forwarding and X11UseLocalHost. - - MaxAuthTries - Specifies the maximum number of authentication attempts permitted - per connection. Once the number of failures reaches half this - value, additional failures are logged. The default is 6. - - MaxSessions - Specifies the maximum number of open sessions permitted per - network connection. The default is 10. - - MaxStartups - Specifies the maximum number of concurrent unauthenticated - connections to the SSH daemon. Additional connections will be - dropped until authentication succeeds or the LoginGraceTime - expires for a connection. The default is 10:30:100. - - Alternatively, random early drop can be enabled by specifying the - three colon separated values ``start:rate:full'' (e.g. - "10:30:60"). sshd(8) will refuse connection attempts with a - probability of ``rate/100'' (30%) if there are currently - ``start'' (10) unauthenticated connections. The probability - increases linearly and all connection attempts are refused if the - number of unauthenticated connections reaches ``full'' (60). - - PasswordAuthentication - Specifies whether password authentication is allowed. The - default is ``yes''. - - PermitEmptyPasswords - When password authentication is allowed, it specifies whether the - server allows login to accounts with empty password strings. The - default is ``no''. - - PermitOpen - Specifies the destinations to which TCP port forwarding is - permitted. The forwarding specification must be one of the - following forms: - - PermitOpen host:port - PermitOpen IPv4_addr:port - PermitOpen [IPv6_addr]:port - - Multiple forwards may be specified by separating them with - whitespace. An argument of ``any'' can be used to remove all - restrictions and permit any forwarding requests. An argument of - ``none'' can be used to prohibit all forwarding requests. By - default all port forwarding requests are permitted. - - PermitRootLogin - Specifies whether root can log in using ssh(1). The argument - must be ``yes'', ``without-password'', ``forced-commands-only'', - or ``no''. The default is ``yes''. - - If this option is set to ``without-password'', password - authentication is disabled for root. - - If this option is set to ``forced-commands-only'', root login - with public key authentication will be allowed, but only if the - command option has been specified (which may be useful for taking - remote backups even if root login is normally not allowed). All - other authentication methods are disabled for root. - - If this option is set to ``no'', root is not allowed to log in. - - PermitTunnel - Specifies whether tun(4) device forwarding is allowed. The - argument must be ``yes'', ``point-to-point'' (layer 3), - ``ethernet'' (layer 2), or ``no''. Specifying ``yes'' permits - both ``point-to-point'' and ``ethernet''. The default is ``no''. - - PermitTTY - Specifies whether pty(4) allocation is permitted. The default is - ``yes''. - - PermitUserEnvironment - Specifies whether ~/.ssh/environment and environment= options in - ~/.ssh/authorized_keys are processed by sshd(8). The default is - ``no''. Enabling environment processing may enable users to - bypass access restrictions in some configurations using - mechanisms such as LD_PRELOAD. - - PidFile - Specifies the file that contains the process ID of the SSH - daemon. The default is /var/run/sshd.pid. - - Port Specifies the port number that sshd(8) listens on. The default - is 22. Multiple options of this type are permitted. See also - ListenAddress. - - PrintLastLog - Specifies whether sshd(8) should print the date and time of the - last user login when a user logs in interactively. The default - is ``yes''. - - PrintMotd - Specifies whether sshd(8) should print /etc/motd when a user logs - in interactively. (On some systems it is also printed by the - shell, /etc/profile, or equivalent.) The default is ``yes''. - - Protocol - Specifies the protocol versions sshd(8) supports. The possible - values are `1' and `2'. Multiple versions must be comma- - separated. The default is `2'. Note that the order of the - protocol list does not indicate preference, because the client - selects among multiple protocol versions offered by the server. - Specifying ``2,1'' is identical to ``1,2''. - - PubkeyAuthentication - Specifies whether public key authentication is allowed. The - default is ``yes''. Note that this option applies to protocol - version 2 only. - - RekeyLimit - Specifies the maximum amount of data that may be transmitted - before the session key is renegotiated, optionally followed a - maximum amount of time that may pass before the session key is - renegotiated. The first argument is specified in bytes and may - have a suffix of `K', `M', or `G' to indicate Kilobytes, - Megabytes, or Gigabytes, respectively. The default is between - `1G' and `4G', depending on the cipher. The optional second - value is specified in seconds and may use any of the units - documented in the TIME FORMATS section. The default value for - RekeyLimit is ``default none'', which means that rekeying is - performed after the cipher's default amount of data has been sent - or received and no time based rekeying is done. This option - applies to protocol version 2 only. - - RevokedKeys - Specifies revoked public keys. Keys listed in this file will be - refused for public key authentication. Note that if this file is - not readable, then public key authentication will be refused for - all users. Keys may be specified as a text file, listing one - public key per line, or as an OpenSSH Key Revocation List (KRL) - as generated by ssh-keygen(1). For more information on KRLs, see - the KEY REVOCATION LISTS section in ssh-keygen(1). - - RhostsRSAAuthentication - Specifies whether rhosts or /etc/hosts.equiv authentication - together with successful RSA host authentication is allowed. The - default is ``no''. This option applies to protocol version 1 - only. - - RSAAuthentication - Specifies whether pure RSA authentication is allowed. The - default is ``yes''. This option applies to protocol version 1 - only. - - ServerKeyBits - Defines the number of bits in the ephemeral protocol version 1 - server key. The minimum value is 512, and the default is 1024. - - StrictModes - Specifies whether sshd(8) should check file modes and ownership - of the user's files and home directory before accepting login. - This is normally desirable because novices sometimes accidentally - leave their directory or files world-writable. The default is - ``yes''. Note that this does not apply to ChrootDirectory, whose - permissions and ownership are checked unconditionally. - - Subsystem - Configures an external subsystem (e.g. file transfer daemon). - Arguments should be a subsystem name and a command (with optional - arguments) to execute upon subsystem request. - - The command sftp-server(8) implements the ``sftp'' file transfer - subsystem. - - Alternately the name ``internal-sftp'' implements an in-process - ``sftp'' server. This may simplify configurations using - ChrootDirectory to force a different filesystem root on clients. - - By default no subsystems are defined. Note that this option - applies to protocol version 2 only. - - SyslogFacility - Gives the facility code that is used when logging messages from - sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, - LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The - default is AUTH. - - TCPKeepAlive - Specifies whether the system should send TCP keepalive messages - to the other side. If they are sent, death of the connection or - crash of one of the machines will be properly noticed. However, - this means that connections will die if the route is down - temporarily, and some people find it annoying. On the other - hand, if TCP keepalives are not sent, sessions may hang - indefinitely on the server, leaving ``ghost'' users and consuming - server resources. - - The default is ``yes'' (to send TCP keepalive messages), and the - server will notice if the network goes down or the client host - crashes. This avoids infinitely hanging sessions. - - To disable TCP keepalive messages, the value should be set to - ``no''. - - TrustedUserCAKeys - Specifies a file containing public keys of certificate - authorities that are trusted to sign user certificates for - authentication. Keys are listed one per line; empty lines and - comments starting with `#' are allowed. If a certificate is - presented for authentication and has its signing CA key listed in - this file, then it may be used for authentication for any user - listed in the certificate's principals list. Note that - certificates that lack a list of principals will not be permitted - for authentication using TrustedUserCAKeys. For more details on - certificates, see the CERTIFICATES section in ssh-keygen(1). - - UseDNS Specifies whether sshd(8) should look up the remote host name and - check that the resolved host name for the remote IP address maps - back to the very same IP address. The default is ``yes''. - - UseLogin - Specifies whether login(1) is used for interactive login - sessions. The default is ``no''. Note that login(1) is never - used for remote command execution. Note also, that if this is - enabled, X11Forwarding will be disabled because login(1) does not - know how to handle xauth(1) cookies. If UsePrivilegeSeparation - is specified, it will be disabled after authentication. - - UsePAM Enables the Pluggable Authentication Module interface. If set to - ``yes'' this will enable PAM authentication using - ChallengeResponseAuthentication and PasswordAuthentication in - addition to PAM account and session module processing for all - authentication types. - - Because PAM challenge-response authentication usually serves an - equivalent role to password authentication, you should disable - either PasswordAuthentication or ChallengeResponseAuthentication. - - If UsePAM is enabled, you will not be able to run sshd(8) as a - non-root user. The default is ``no''. - - UsePrivilegeSeparation - Specifies whether sshd(8) separates privileges by creating an - unprivileged child process to deal with incoming network traffic. - After successful authentication, another process will be created - that has the privilege of the authenticated user. The goal of - privilege separation is to prevent privilege escalation by - containing any corruption within the unprivileged processes. The - default is ``yes''. If UsePrivilegeSeparation is set to - ``sandbox'' then the pre-authentication unprivileged process is - subject to additional restrictions. - - VersionAddendum - Optionally specifies additional text to append to the SSH - protocol banner sent by the server upon connection. The default - is ``none''. - - X11DisplayOffset - Specifies the first display number available for sshd(8)'s X11 - forwarding. This prevents sshd from interfering with real X11 - servers. The default is 10. - - X11Forwarding - Specifies whether X11 forwarding is permitted. The argument must - be ``yes'' or ``no''. The default is ``no''. - - When X11 forwarding is enabled, there may be additional exposure - to the server and to client displays if the sshd(8) proxy display - is configured to listen on the wildcard address (see - X11UseLocalhost below), though this is not the default. - Additionally, the authentication spoofing and authentication data - verification and substitution occur on the client side. The - security risk of using X11 forwarding is that the client's X11 - display server may be exposed to attack when the SSH client - requests forwarding (see the warnings for ForwardX11 in - ssh_config(5)). A system administrator may have a stance in - which they want to protect clients that may expose themselves to - attack by unwittingly requesting X11 forwarding, which can - warrant a ``no'' setting. - - Note that disabling X11 forwarding does not prevent users from - forwarding X11 traffic, as users can always install their own - forwarders. X11 forwarding is automatically disabled if UseLogin - is enabled. - - X11UseLocalhost - Specifies whether sshd(8) should bind the X11 forwarding server - to the loopback address or to the wildcard address. By default, - sshd binds the forwarding server to the loopback address and sets - the hostname part of the DISPLAY environment variable to - ``localhost''. This prevents remote hosts from connecting to the - proxy display. However, some older X11 clients may not function - with this configuration. X11UseLocalhost may be set to ``no'' to - specify that the forwarding server should be bound to the - wildcard address. The argument must be ``yes'' or ``no''. The - default is ``yes''. - - XAuthLocation - Specifies the full pathname of the xauth(1) program. The default - is /usr/X11R6/bin/xauth. - -TIME FORMATS - sshd(8) command-line arguments and configuration file options that - specify time may be expressed using a sequence of the form: - time[qualifier], where time is a positive integer value and qualifier is - one of the following: - - seconds - s | S seconds - m | M minutes - h | H hours - d | D days - w | W weeks - - Each member of the sequence is added together to calculate the total time - value. - - Time format examples: - - 600 600 seconds (10 minutes) - 10m 10 minutes - 1h30m 1 hour 30 minutes (90 minutes) - -FILES - /etc/ssh/sshd_config - Contains configuration data for sshd(8). This file should be - writable by root only, but it is recommended (though not - necessary) that it be world-readable. - -SEE ALSO - sshd(8) - -AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by - Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support - for privilege separation. - -OpenBSD 5.5 February 27, 2014 OpenBSD 5.5 diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index 6796b9d..cedd493 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -33,9 +33,9 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.172 2014/02/27 22:47:07 djm Exp $ +.\" $OpenBSD: sshd_config.5,v 1.211 2015/08/14 15:32:41 jmc Exp $ .\" $FreeBSD$ -.Dd $Mdocdate: February 27 2014 $ +.Dd $Mdocdate: August 14 2015 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -71,7 +71,11 @@ See in .Xr ssh_config 5 for how to configure the client. -Note that environment passing is only supported for protocol 2. +Note that environment passing is only supported for protocol 2, and +that the +.Ev TERM +environment variable is always sent whenever the client +requests a pseudo-terminal as it is required by the protocol. Variables are specified by name, which may contain the wildcard characters .Ql * and @@ -141,6 +145,26 @@ The default is Note that disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. +.It Cm AllowStreamLocalForwarding +Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted. +The available options are +.Dq yes +or +.Dq all +to allow StreamLocal forwarding, +.Dq no +to prevent all StreamLocal forwarding, +.Dq local +to allow local (from the perspective of +.Xr ssh 1 ) +forwarding only or +.Dq remote +to allow remote forwarding only. +The default is +.Dq yes . +Note that disabling StreamLocal forwarding does not improve security unless +users are also denied shell access, as they can always install their +own forwarders. .It Cm AllowUsers This keyword can be followed by a list of user name patterns, separated by spaces. @@ -191,6 +215,18 @@ would restrict keyboard interactive authentication to the .Dq bsdauth device. .Pp +If the +.Dq publickey +method is listed more than once, +.Xr sshd 8 +verifies that keys that have been used successfully are not reused for +subsequent authentications. +For example, an +.Cm AuthenticationMethods +of +.Dq publickey,publickey +will require successful authentication using two different public keys. +.Pp This option is only available for SSH protocol 2 and will yield a fatal error if enabled if protocol 1 is also enabled. Note that each authentication method listed should also be explicitly enabled @@ -199,9 +235,21 @@ The default is not to require multiple authentication; successful completion of a single authentication method is sufficient. .It Cm AuthorizedKeysCommand Specifies a program to be used to look up the user's public keys. -The program must be owned by root and not writable by group or others. -It will be invoked with a single argument of the username -being authenticated, and should produce on standard output zero or +The program must be owned by root, not writable by group or others and +specified by an absolute path. +.Pp +Arguments to +.Cm AuthorizedKeysCommand +may be provided using the following tokens, which will be expanded +at runtime: %% is replaced by a literal '%', %u is replaced by the +username being authenticated, %h is replaced by the home directory +of the user being authenticated, %t is replaced with the key type +offered for authentication, %f is replaced with the fingerprint of +the key, and %k is replaced with the key being offered for authentication. +If no arguments are specified then the username of the target user +will be supplied. +.Pp +The program should produce on standard output zero or more lines of authorized_keys output (see AUTHORIZED_KEYS in .Xr sshd 8 ) . If a key supplied by AuthorizedKeysCommand does not successfully authenticate @@ -213,6 +261,13 @@ By default, no AuthorizedKeysCommand is run. Specifies the user under whose account the AuthorizedKeysCommand is run. It is recommended to use a dedicated user that has no other role on the host than running authorized keys commands. +If +.Cm AuthorizedKeysCommand +is specified but +.Cm AuthorizedKeysCommandUser +is not, then +.Xr sshd 8 +will refuse to start. .It Cm AuthorizedKeysFile Specifies the file that contains the public keys that can be used for user authentication. @@ -233,6 +288,42 @@ directory. Multiple files may be listed, separated by whitespace. The default is .Dq .ssh/authorized_keys .ssh/authorized_keys2 . +.It Cm AuthorizedPrincipalsCommand +Specifies a program to be used to generate the list of allowed +certificate principals as per +.Cm AuthorizedPrincipalsFile . +The program must be owned by root, not writable by group or others and +specified by an absolute path. +.Pp +Arguments to +.Cm AuthorizedPrincipalsCommand +may be provided using the following tokens, which will be expanded +at runtime: %% is replaced by a literal '%', %u is replaced by the +username being authenticated and %h is replaced by the home directory +of the user being authenticated. +.Pp +The program should produce on standard output zero or +more lines of +.Cm AuthorizedPrincipalsFile +output. +If either +.Cm AuthorizedPrincipalsCommand +or +.Cm AuthorizedPrincipalsFile +is specified, then certificates offered by the client for authentication +must contain a principal that is listed. +By default, no AuthorizedPrincipalsCommand is run. +.It Cm AuthorizedPrincipalsCommandUser +Specifies the user under whose account the AuthorizedPrincipalsCommand is run. +It is recommended to use a dedicated user that has no other role on the host +than running authorized principals commands. +If +.Cm AuthorizedPrincipalsCommand +is specified but +.Cm AuthorizedPrincipalsCommandUser +is not, then +.Xr sshd 8 +will refuse to start. .It Cm AuthorizedPrincipalsFile Specifies a file that lists principal names that are accepted for certificate authentication. @@ -284,7 +375,7 @@ This option is only available for protocol version 2. By default, no banner is displayed. .It Cm ChallengeResponseAuthentication Specifies whether challenge-response authentication is allowed (e.g. via -PAM or though authentication styles supported in +PAM or through authentication styles supported in .Xr login.conf 5 ) The default is .Dq yes . @@ -292,8 +383,10 @@ The default is Specifies the pathname of a directory to .Xr chroot 2 to after authentication. -All components of the pathname must be root-owned directories that are -not writable by any other user or group. +At session startup +.Xr sshd 8 +checks that all components of the pathname are root-owned directories +which are not writable by any other user or group. After the chroot, .Xr sshd 8 changes the working directory to the user's home directory. @@ -317,7 +410,6 @@ nodes such as .Xr stdin 4 , .Xr stdout 4 , .Xr stderr 4 , -.Xr arandom 4 and .Xr tty 4 devices. @@ -325,49 +417,77 @@ For file transfer sessions using .Dq sftp , no additional configuration of the environment is necessary if the in-process sftp server is used, -though sessions which use logging do require +though sessions which use logging may require .Pa /dev/log -inside the chroot directory (see +inside the chroot directory on some operating systems (see .Xr sftp-server 8 for details). .Pp +For safety, it is very important that the directory hierarchy be +prevented from modification by other processes on the system (especially +those outside the jail). +Misconfiguration can lead to unsafe environments which +.Xr sshd 8 +cannot detect. +.Pp The default is not to .Xr chroot 2 . .It Cm Ciphers Specifies the ciphers allowed for protocol version 2. Multiple ciphers must be comma-separated. +If the specified value begins with a +.Sq + +character, then the specified ciphers will be appended to the default set +instead of replacing them. +.Pp The supported ciphers are: .Pp -.Dq 3des-cbc , -.Dq aes128-cbc , -.Dq aes192-cbc , -.Dq aes256-cbc , -.Dq aes128-ctr , -.Dq aes192-ctr , -.Dq aes256-ctr , -.Dq aes128-gcm@openssh.com , -.Dq aes256-gcm@openssh.com , -.Dq arcfour128 , -.Dq arcfour256 , -.Dq arcfour , -.Dq blowfish-cbc , -.Dq cast128-cbc , -and -.Dq chacha20-poly1305@openssh.com . +.Bl -item -compact -offset indent +.It +3des-cbc +.It +aes128-cbc +.It +aes192-cbc +.It +aes256-cbc +.It +aes128-ctr +.It +aes192-ctr +.It +aes256-ctr +.It +aes128-gcm@openssh.com +.It +aes256-gcm@openssh.com +.It +arcfour +.It +arcfour128 +.It +arcfour256 +.It +blowfish-cbc +.It +cast128-cbc +.It +chacha20-poly1305@openssh.com +.El .Pp The default is: -.Bd -literal -offset 3n -aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, -aes128-gcm@openssh.com,aes256-gcm@openssh.com, +.Bd -literal -offset indent chacha20-poly1305@openssh.com, -aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, -aes256-cbc,arcfour +aes128-ctr,aes192-ctr,aes256-ctr, +aes128-gcm@openssh.com,aes256-gcm@openssh.com .Ed .Pp The list of available ciphers may also be obtained using the .Fl Q option of -.Xr ssh 1 . +.Xr ssh 1 +with an argument of +.Dq cipher . .It Cm ClientAliveCountMax Sets the number of client alive messages (see below) which may be sent without @@ -450,6 +570,14 @@ and finally See PATTERNS in .Xr ssh_config 5 for more information on patterns. +.It Cm FingerprintHash +Specifies the hash algorithm used when logging key fingerprints. +Valid options are: +.Dq md5 +and +.Dq sha256 . +The default is +.Dq sha256 . .It Cm ForceCommand Forces the execution of the command specified by .Cm ForceCommand , @@ -500,6 +628,46 @@ on logout. The default is .Dq yes . Note that this option applies to protocol version 2 only. +.It Cm GSSAPIStrictAcceptorCheck +Determines whether to be strict about the identity of the GSSAPI acceptor +a client authenticates against. +If set to +.Dq yes +then the client must authenticate against the +.Pa host +service on the current hostname. +If set to +.Dq no +then the client may authenticate against any service key stored in the +machine's default store. +This facility is provided to assist with operation on multi homed machines. +The default is +.Dq yes . +.It Cm HostbasedAcceptedKeyTypes +Specifies the key types that will be accepted for hostbased authentication +as a comma-separated pattern list. +Alternately if the specified value begins with a +.Sq + +character, then the specified key types will be appended to the default set +instead of replacing them. +The default for this option is: +.Bd -literal -offset 3n +ecdsa-sha2-nistp256-cert-v01@openssh.com, +ecdsa-sha2-nistp384-cert-v01@openssh.com, +ecdsa-sha2-nistp521-cert-v01@openssh.com, +ssh-ed25519-cert-v01@openssh.com, +ssh-rsa-cert-v01@openssh.com, +ssh-dss-cert-v01@openssh.com, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384, +ecdsa-sha2-nistp521,ssh-ed25519, +ssh-rsa,ssh-dss +.Ed +.Pp +The +.Fl Q +option of +.Xr ssh 1 +may be used to list supported key types. .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed @@ -546,9 +714,15 @@ for protocol version 1, and and .Pa /etc/ssh/ssh_host_rsa_key for protocol version 2. +.Pp Note that .Xr sshd 8 -will refuse to use a file if it is group/world-accessible. +will refuse to use a file if it is group/world-accessible +and that the +.Cm HostKeyAlgorithms +option restricts which of the keys are actually used by +.Xr sshd 8 . +.Pp It is possible to have multiple host key files. .Dq rsa1 keys are used for version 1 and @@ -570,6 +744,28 @@ If is specified, the location of the socket will be read from the .Ev SSH_AUTH_SOCK environment variable. +.It Cm HostKeyAlgorithms +Specifies the protocol version 2 host key algorithms +that the server offers. +The default for this option is: +.Bd -literal -offset 3n +ecdsa-sha2-nistp256-cert-v01@openssh.com, +ecdsa-sha2-nistp384-cert-v01@openssh.com, +ecdsa-sha2-nistp521-cert-v01@openssh.com, +ssh-ed25519-cert-v01@openssh.com, +ssh-rsa-cert-v01@openssh.com, +ssh-dss-cert-v01@openssh.com, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384, +ecdsa-sha2-nistp521,ssh-ed25519, +ssh-rsa,ssh-dss +.Ed +.Pp +The list of available key types may also be obtained using the +.Fl Q +option of +.Xr ssh 1 +with an argument of +.Dq key . .It Cm IgnoreRhosts Specifies that .Pa .rhosts @@ -673,15 +869,45 @@ The default is .It Cm KexAlgorithms Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must be comma-separated. -The default is +Alternately if the specified value begins with a +.Sq + +character, then the specified methods will be appended to the default set +instead of replacing them. +The supported algorithms are: +.Pp +.Bl -item -compact -offset indent +.It +curve25519-sha256@libssh.org +.It +diffie-hellman-group1-sha1 +.It +diffie-hellman-group14-sha1 +.It +diffie-hellman-group-exchange-sha1 +.It +diffie-hellman-group-exchange-sha256 +.It +ecdh-sha2-nistp256 +.It +ecdh-sha2-nistp384 +.It +ecdh-sha2-nistp521 +.El +.Pp +The default is: .Bd -literal -offset indent curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, -diffie-hellman-group-exchange-sha1, -diffie-hellman-group14-sha1, -diffie-hellman-group1-sha1 +diffie-hellman-group14-sha1 .Ed +.Pp +The list of available key exchange algorithms may also be obtained using the +.Fl Q +option of +.Xr ssh 1 +with an argument of +.Dq kex . .It Cm KeyRegenerationInterval In protocol version 1, the ephemeral server key is automatically regenerated after this many seconds (if it has been used). @@ -701,34 +927,31 @@ The following forms may be used: .It .Cm ListenAddress .Sm off -.Ar host No | Ar IPv4_addr No | Ar IPv6_addr +.Ar host | Ar IPv4_addr | Ar IPv6_addr .Sm on .It .Cm ListenAddress .Sm off -.Ar host No | Ar IPv4_addr No : Ar port +.Ar host | Ar IPv4_addr : Ar port .Sm on .It .Cm ListenAddress .Sm off .Oo -.Ar host No | Ar IPv6_addr Oc : Ar port +.Ar host | Ar IPv6_addr Oc : Ar port .Sm on .El .Pp If .Ar port is not specified, -sshd will listen on the address and all prior +sshd will listen on the address and all .Cm Port options specified. The default is to listen on all local addresses. Multiple .Cm ListenAddress options are permitted. -Additionally, any -.Cm Port -options must precede this option for non-port qualified addresses. .It Cm LoginGraceTime The server disconnects after this time if the user has not successfully logged in. @@ -748,21 +971,70 @@ Specifies the available MAC (message authentication code) algorithms. The MAC algorithm is used in protocol version 2 for data integrity protection. Multiple algorithms must be comma-separated. +If the specified value begins with a +.Sq + +character, then the specified algorithms will be appended to the default set +instead of replacing them. +.Pp The algorithms that contain .Dq -etm calculate the MAC after encryption (encrypt-then-mac). These are considered safer and their use recommended. +The supported MACs are: +.Pp +.Bl -item -compact -offset indent +.It +hmac-md5 +.It +hmac-md5-96 +.It +hmac-ripemd160 +.It +hmac-sha1 +.It +hmac-sha1-96 +.It +hmac-sha2-256 +.It +hmac-sha2-512 +.It +umac-64@openssh.com +.It +umac-128@openssh.com +.It +hmac-md5-etm@openssh.com +.It +hmac-md5-96-etm@openssh.com +.It +hmac-ripemd160-etm@openssh.com +.It +hmac-sha1-etm@openssh.com +.It +hmac-sha1-96-etm@openssh.com +.It +hmac-sha2-256-etm@openssh.com +.It +hmac-sha2-512-etm@openssh.com +.It +umac-64-etm@openssh.com +.It +umac-128-etm@openssh.com +.El +.Pp The default is: .Bd -literal -offset indent -hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, umac-64-etm@openssh.com,umac-128-etm@openssh.com, hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, -hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, -hmac-md5-96-etm@openssh.com, -hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, -hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, -hmac-sha1-96,hmac-md5-96 +umac-64@openssh.com,umac-128@openssh.com, +hmac-sha2-256,hmac-sha2-512 .Ed +.Pp +The list of available MAC algorithms may also be obtained using the +.Fl Q +option of +.Xr ssh 1 +with an argument of +.Dq mac . .It Cm Match Introduces a conditional block. If all of the criteria on the @@ -773,7 +1045,7 @@ set in the global section of the config file, until either another line or the end of the file. If a keyword appears in multiple .Cm Match -blocks that are satisified, only the first instance of the keyword is +blocks that are satisfied, only the first instance of the keyword is applied. .Pp The arguments to @@ -817,6 +1089,7 @@ Available keywords are .Cm AcceptEnv , .Cm AllowAgentForwarding , .Cm AllowGroups , +.Cm AllowStreamLocalForwarding , .Cm AllowTcpForwarding , .Cm AllowUsers , .Cm AuthenticationMethods , @@ -831,8 +1104,10 @@ Available keywords are .Cm ForceCommand , .Cm GatewayPorts , .Cm GSSAPIAuthentication , +.Cm HostbasedAcceptedKeyTypes , .Cm HostbasedAuthentication , .Cm HostbasedUsesNameFromPacketOnly , +.Cm IPQoS , .Cm KbdInteractiveAuthentication , .Cm KerberosAuthentication , .Cm MaxAuthTries , @@ -843,10 +1118,16 @@ Available keywords are .Cm PermitRootLogin , .Cm PermitTTY , .Cm PermitTunnel , +.Cm PermitUserRC , +.Cm PubkeyAcceptedKeyTypes , .Cm PubkeyAuthentication , .Cm RekeyLimit , +.Cm RevokedKeys , .Cm RhostsRSAAuthentication , .Cm RSAAuthentication , +.Cm StreamLocalBindMask , +.Cm StreamLocalBindUnlink , +.Cm TrustedUserCAKeys , .Cm X11DisplayOffset , .Cm X11Forwarding and @@ -930,6 +1211,7 @@ Specifies whether root can log in using .Xr ssh 1 . The argument must be .Dq yes , +.Dq prohibit-password , .Dq without-password , .Dq forced-commands-only , or @@ -945,8 +1227,10 @@ the root user may be allowed in with its password even if .Dq without-password . .Pp If this option is set to +.Dq prohibit-password +or .Dq without-password , -password authentication is disabled for root. +password and keyboard-interactive authentication are disabled for root. .Pp If this option is set to .Dq forced-commands-only , @@ -980,6 +1264,10 @@ and .Dq ethernet . The default is .Dq no . +.Pp +Independent of this setting, the permissions of the selected +.Xr tun 4 +device must allow access to the user. .It Cm PermitTTY Specifies whether .Xr pty 4 @@ -1000,9 +1288,17 @@ The default is Enabling environment processing may enable users to bypass access restrictions in some configurations using mechanisms such as .Ev LD_PRELOAD . +.It Cm PermitUserRC +Specifies whether any +.Pa ~/.ssh/rc +file is executed. +The default is +.Dq yes . .It Cm PidFile Specifies the file that contains the process ID of the -SSH daemon. +SSH daemon, or +.Dq none +to not write one. The default is .Pa /var/run/sshd.pid . .It Cm Port @@ -1049,6 +1345,31 @@ Specifying .Dq 2,1 is identical to .Dq 1,2 . +.It Cm PubkeyAcceptedKeyTypes +Specifies the key types that will be accepted for public key authentication +as a comma-separated pattern list. +Alternately if the specified value begins with a +.Sq + +character, then the specified key types will be appended to the default set +instead of replacing them. +The default for this option is: +.Bd -literal -offset 3n +ecdsa-sha2-nistp256-cert-v01@openssh.com, +ecdsa-sha2-nistp384-cert-v01@openssh.com, +ecdsa-sha2-nistp521-cert-v01@openssh.com, +ssh-ed25519-cert-v01@openssh.com, +ssh-rsa-cert-v01@openssh.com, +ssh-dss-cert-v01@openssh.com, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384, +ecdsa-sha2-nistp521,ssh-ed25519, +ssh-rsa,ssh-dss +.Ed +.Pp +The +.Fl Q +option of +.Xr ssh 1 +may be used to list supported key types. .It Cm PubkeyAuthentication Specifies whether public key authentication is allowed. The default is @@ -1081,7 +1402,9 @@ which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. This option applies to protocol version 2 only. .It Cm RevokedKeys -Specifies revoked public keys. +Specifies revoked public keys file, or +.Dq none +to not use one. Keys listed in this file will be refused for public key authentication. Note that if this file is not readable, then public key authentication will be refused for all users. @@ -1105,7 +1428,34 @@ The default is This option applies to protocol version 1 only. .It Cm ServerKeyBits Defines the number of bits in the ephemeral protocol version 1 server key. -The minimum value is 512, and the default is 1024. +The default and minimum value is 1024. +.It Cm StreamLocalBindMask +Sets the octal file creation mode mask +.Pq umask +used when creating a Unix-domain socket file for local or remote +port forwarding. +This option is only used for port forwarding to a Unix-domain socket file. +.Pp +The default value is 0177, which creates a Unix-domain socket file that is +readable and writable only by the owner. +Note that not all operating systems honor the file mode on Unix-domain +socket files. +.It Cm StreamLocalBindUnlink +Specifies whether to remove an existing Unix-domain socket file for local +or remote port forwarding before creating a new one. +If the socket file already exists and +.Cm StreamLocalBindUnlink +is not enabled, +.Nm sshd +will be unable to forward the port to the Unix-domain socket file. +This option is only used for port forwarding to a Unix-domain socket file. +.Pp +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq no . .It Cm StrictModes Specifies whether .Xr sshd 8 @@ -1169,7 +1519,9 @@ To disable TCP keepalive messages, the value should be set to .Dq no . .It Cm TrustedUserCAKeys Specifies a file containing public keys of certificate authorities that are -trusted to sign user certificates for authentication. +trusted to sign user certificates for authentication, or +.Dq none +to not use one. Keys are listed one per line; empty lines and comments starting with .Ql # are allowed. @@ -1184,9 +1536,20 @@ For more details on certificates, see the CERTIFICATES section in .It Cm UseDNS Specifies whether .Xr sshd 8 -should look up the remote host name and check that +should look up the remote host name, and to check that the resolved host name for the remote IP address maps back to the very same IP address. +.Pp +If this option is set to +.Dq no , +then only addresses and not host names may be used in +.Pa ~/.ssh/known_hosts +.Cm from +and +.Nm +.Cm Match +.Cm Host +directives. The default is .Dq yes . .It Cm UseLogin @@ -1253,7 +1616,7 @@ restrictions. Optionally specifies additional text to append to the SSH protocol banner sent by the server upon connection. The default is -.Dq FreeBSD-20160124 . +.Dq FreeBSD-20160125 . The value .Dq none may be used to disable this. @@ -1325,7 +1688,9 @@ The default is .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 -program. +program, or +.Dq none +to not use one. The default is .Pa /usr/local/bin/xauth . .El diff --git a/crypto/openssh/ssherr.c b/crypto/openssh/ssherr.c new file mode 100644 index 0000000..4ca7939 --- /dev/null +++ b/crypto/openssh/ssherr.c @@ -0,0 +1,141 @@ +/* $OpenBSD: ssherr.c,v 1.4 2015/02/16 22:13:32 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "ssherr.h" + +const char * +ssh_err(int n) +{ + switch (n) { + case SSH_ERR_SUCCESS: + return "success"; + case SSH_ERR_INTERNAL_ERROR: + return "unexpected internal error"; + case SSH_ERR_ALLOC_FAIL: + return "memory allocation failed"; + case SSH_ERR_MESSAGE_INCOMPLETE: + return "incomplete message"; + case SSH_ERR_INVALID_FORMAT: + return "invalid format"; + case SSH_ERR_BIGNUM_IS_NEGATIVE: + return "bignum is negative"; + case SSH_ERR_STRING_TOO_LARGE: + return "string is too large"; + case SSH_ERR_BIGNUM_TOO_LARGE: + return "bignum is too large"; + case SSH_ERR_ECPOINT_TOO_LARGE: + return "elliptic curve point is too large"; + case SSH_ERR_NO_BUFFER_SPACE: + return "insufficient buffer space"; + case SSH_ERR_INVALID_ARGUMENT: + return "invalid argument"; + case SSH_ERR_KEY_BITS_MISMATCH: + return "key bits do not match"; + case SSH_ERR_EC_CURVE_INVALID: + return "invalid elliptic curve"; + case SSH_ERR_KEY_TYPE_MISMATCH: + return "key type does not match"; + case SSH_ERR_KEY_TYPE_UNKNOWN: + return "unknown or unsupported key type"; + case SSH_ERR_EC_CURVE_MISMATCH: + return "elliptic curve does not match"; + case SSH_ERR_EXPECTED_CERT: + return "plain key provided where certificate required"; + case SSH_ERR_KEY_LACKS_CERTBLOB: + return "key lacks certificate data"; + case SSH_ERR_KEY_CERT_UNKNOWN_TYPE: + return "unknown/unsupported certificate type"; + case SSH_ERR_KEY_CERT_INVALID_SIGN_KEY: + return "invalid certificate signing key"; + case SSH_ERR_KEY_INVALID_EC_VALUE: + return "invalid elliptic curve value"; + case SSH_ERR_SIGNATURE_INVALID: + return "incorrect signature"; + case SSH_ERR_LIBCRYPTO_ERROR: + return "error in libcrypto"; /* XXX fetch and return */ + case SSH_ERR_UNEXPECTED_TRAILING_DATA: + return "unexpected bytes remain after decoding"; + case SSH_ERR_SYSTEM_ERROR: + return strerror(errno); + case SSH_ERR_KEY_CERT_INVALID: + return "invalid certificate"; + case SSH_ERR_AGENT_COMMUNICATION: + return "communication with agent failed"; + case SSH_ERR_AGENT_FAILURE: + return "agent refused operation"; + case SSH_ERR_DH_GEX_OUT_OF_RANGE: + return "DH GEX group out of range"; + case SSH_ERR_DISCONNECTED: + return "disconnected"; + case SSH_ERR_MAC_INVALID: + return "message authentication code incorrect"; + case SSH_ERR_NO_CIPHER_ALG_MATCH: + return "no matching cipher found"; + case SSH_ERR_NO_MAC_ALG_MATCH: + return "no matching MAC found"; + case SSH_ERR_NO_COMPRESS_ALG_MATCH: + return "no matching compression method found"; + case SSH_ERR_NO_KEX_ALG_MATCH: + return "no matching key exchange method found"; + case SSH_ERR_NO_HOSTKEY_ALG_MATCH: + return "no matching host key type found"; + case SSH_ERR_PROTOCOL_MISMATCH: + return "protocol version mismatch"; + case SSH_ERR_NO_PROTOCOL_VERSION: + return "could not read protocol version"; + case SSH_ERR_NO_HOSTKEY_LOADED: + return "could not load host key"; + case SSH_ERR_NEED_REKEY: + return "rekeying not supported by peer"; + case SSH_ERR_PASSPHRASE_TOO_SHORT: + return "passphrase is too short (minimum four characters)"; + case SSH_ERR_FILE_CHANGED: + return "file changed while reading"; + case SSH_ERR_KEY_UNKNOWN_CIPHER: + return "key encrypted using unsupported cipher"; + case SSH_ERR_KEY_WRONG_PASSPHRASE: + return "incorrect passphrase supplied to decrypt private key"; + case SSH_ERR_KEY_BAD_PERMISSIONS: + return "bad permissions"; + case SSH_ERR_KEY_CERT_MISMATCH: + return "certificate does not match key"; + case SSH_ERR_KEY_NOT_FOUND: + return "key not found"; + case SSH_ERR_AGENT_NOT_PRESENT: + return "agent not present"; + case SSH_ERR_AGENT_NO_IDENTITIES: + return "agent contains no identities"; + case SSH_ERR_BUFFER_READ_ONLY: + return "internal error: buffer is read-only"; + case SSH_ERR_KRL_BAD_MAGIC: + return "KRL file has invalid magic number"; + case SSH_ERR_KEY_REVOKED: + return "Key is revoked"; + case SSH_ERR_CONN_CLOSED: + return "Connection closed"; + case SSH_ERR_CONN_TIMEOUT: + return "Connection timed out"; + case SSH_ERR_CONN_CORRUPT: + return "Connection corrupted"; + case SSH_ERR_PROTOCOL_ERROR: + return "Protocol error"; + default: + return "unknown error"; + } +} diff --git a/crypto/openssh/ssherr.h b/crypto/openssh/ssherr.h new file mode 100644 index 0000000..6f771b4 --- /dev/null +++ b/crypto/openssh/ssherr.h @@ -0,0 +1,84 @@ +/* $OpenBSD: ssherr.h,v 1.3 2015/01/30 01:13:33 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SSHERR_H +#define _SSHERR_H + +/* XXX are these too granular? not granular enough? I can't decide - djm */ + +/* Error codes */ +#define SSH_ERR_SUCCESS 0 +#define SSH_ERR_INTERNAL_ERROR -1 +#define SSH_ERR_ALLOC_FAIL -2 +#define SSH_ERR_MESSAGE_INCOMPLETE -3 +#define SSH_ERR_INVALID_FORMAT -4 +#define SSH_ERR_BIGNUM_IS_NEGATIVE -5 +#define SSH_ERR_STRING_TOO_LARGE -6 +#define SSH_ERR_BIGNUM_TOO_LARGE -7 +#define SSH_ERR_ECPOINT_TOO_LARGE -8 +#define SSH_ERR_NO_BUFFER_SPACE -9 +#define SSH_ERR_INVALID_ARGUMENT -10 +#define SSH_ERR_KEY_BITS_MISMATCH -11 +#define SSH_ERR_EC_CURVE_INVALID -12 +#define SSH_ERR_KEY_TYPE_MISMATCH -13 +#define SSH_ERR_KEY_TYPE_UNKNOWN -14 /* XXX UNSUPPORTED? */ +#define SSH_ERR_EC_CURVE_MISMATCH -15 +#define SSH_ERR_EXPECTED_CERT -16 +#define SSH_ERR_KEY_LACKS_CERTBLOB -17 +#define SSH_ERR_KEY_CERT_UNKNOWN_TYPE -18 +#define SSH_ERR_KEY_CERT_INVALID_SIGN_KEY -19 +#define SSH_ERR_KEY_INVALID_EC_VALUE -20 +#define SSH_ERR_SIGNATURE_INVALID -21 +#define SSH_ERR_LIBCRYPTO_ERROR -22 +#define SSH_ERR_UNEXPECTED_TRAILING_DATA -23 +#define SSH_ERR_SYSTEM_ERROR -24 +#define SSH_ERR_KEY_CERT_INVALID -25 +#define SSH_ERR_AGENT_COMMUNICATION -26 +#define SSH_ERR_AGENT_FAILURE -27 +#define SSH_ERR_DH_GEX_OUT_OF_RANGE -28 +#define SSH_ERR_DISCONNECTED -29 +#define SSH_ERR_MAC_INVALID -30 +#define SSH_ERR_NO_CIPHER_ALG_MATCH -31 +#define SSH_ERR_NO_MAC_ALG_MATCH -32 +#define SSH_ERR_NO_COMPRESS_ALG_MATCH -33 +#define SSH_ERR_NO_KEX_ALG_MATCH -34 +#define SSH_ERR_NO_HOSTKEY_ALG_MATCH -35 +#define SSH_ERR_NO_HOSTKEY_LOADED -36 +#define SSH_ERR_PROTOCOL_MISMATCH -37 +#define SSH_ERR_NO_PROTOCOL_VERSION -38 +#define SSH_ERR_NEED_REKEY -39 +#define SSH_ERR_PASSPHRASE_TOO_SHORT -40 +#define SSH_ERR_FILE_CHANGED -41 +#define SSH_ERR_KEY_UNKNOWN_CIPHER -42 +#define SSH_ERR_KEY_WRONG_PASSPHRASE -43 +#define SSH_ERR_KEY_BAD_PERMISSIONS -44 +#define SSH_ERR_KEY_CERT_MISMATCH -45 +#define SSH_ERR_KEY_NOT_FOUND -46 +#define SSH_ERR_AGENT_NOT_PRESENT -47 +#define SSH_ERR_AGENT_NO_IDENTITIES -48 +#define SSH_ERR_BUFFER_READ_ONLY -49 +#define SSH_ERR_KRL_BAD_MAGIC -50 +#define SSH_ERR_KEY_REVOKED -51 +#define SSH_ERR_CONN_CLOSED -52 +#define SSH_ERR_CONN_TIMEOUT -53 +#define SSH_ERR_CONN_CORRUPT -54 +#define SSH_ERR_PROTOCOL_ERROR -55 + +/* Translate a numeric error code to a human-readable error string */ +const char *ssh_err(int n); + +#endif /* _SSHERR_H */ diff --git a/crypto/openssh/sshkey.c b/crypto/openssh/sshkey.c new file mode 100644 index 0000000..32dd8f2 --- /dev/null +++ b/crypto/openssh/sshkey.c @@ -0,0 +1,3895 @@ +/* $OpenBSD: sshkey.c,v 1.21 2015/08/19 23:19:01 djm Exp $ */ +/* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2008 Alexander von Gernler. All rights reserved. + * Copyright (c) 2010,2011 Damien Miller. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include /* MIN MAX */ +#include +#include + +#ifdef WITH_OPENSSL +#include +#include +#include +#endif + +#include "crypto_api.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_UTIL_H +#include +#endif /* HAVE_UTIL_H */ + +#include "ssh2.h" +#include "ssherr.h" +#include "misc.h" +#include "sshbuf.h" +#include "rsa.h" +#include "cipher.h" +#include "digest.h" +#define SSHKEY_INTERNAL +#include "sshkey.h" +#include "match.h" + +/* openssh private key file format */ +#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" +#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" +#define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1) +#define MARK_END_LEN (sizeof(MARK_END) - 1) +#define KDFNAME "bcrypt" +#define AUTH_MAGIC "openssh-key-v1" +#define SALT_LEN 16 +#define DEFAULT_CIPHERNAME "aes256-cbc" +#define DEFAULT_ROUNDS 16 + +/* Version identification string for SSH v1 identity files. */ +#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" + +static int sshkey_from_blob_internal(struct sshbuf *buf, + struct sshkey **keyp, int allow_cert); + +/* Supported key types */ +struct keytype { + const char *name; + const char *shortname; + int type; + int nid; + int cert; +}; +static const struct keytype keytypes[] = { + { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 }, + { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", + KEY_ED25519_CERT, 0, 1 }, +#ifdef WITH_OPENSSL + { NULL, "RSA1", KEY_RSA1, 0, 0 }, + { "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, + { "ssh-dss", "DSA", KEY_DSA, 0, 0 }, +# ifdef OPENSSL_HAS_ECC + { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, + { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, +# ifdef OPENSSL_HAS_NISTP521 + { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, +# endif /* OPENSSL_HAS_NISTP521 */ +# endif /* OPENSSL_HAS_ECC */ + { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 }, + { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 }, +# ifdef OPENSSL_HAS_ECC + { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", + KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 }, + { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", + KEY_ECDSA_CERT, NID_secp384r1, 1 }, +# ifdef OPENSSL_HAS_NISTP521 + { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", + KEY_ECDSA_CERT, NID_secp521r1, 1 }, +# endif /* OPENSSL_HAS_NISTP521 */ +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + { NULL, NULL, -1, -1, 0 } +}; + +const char * +sshkey_type(const struct sshkey *k) +{ + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->type == k->type) + return kt->shortname; + } + return "unknown"; +} + +static const char * +sshkey_ssh_name_from_type_nid(int type, int nid) +{ + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->type == type && (kt->nid == 0 || kt->nid == nid)) + return kt->name; + } + return "ssh-unknown"; +} + +int +sshkey_type_is_cert(int type) +{ + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->type == type) + return kt->cert; + } + return 0; +} + +const char * +sshkey_ssh_name(const struct sshkey *k) +{ + return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid); +} + +const char * +sshkey_ssh_name_plain(const struct sshkey *k) +{ + return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type), + k->ecdsa_nid); +} + +int +sshkey_type_from_name(const char *name) +{ + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { + /* Only allow shortname matches for plain key types */ + if ((kt->name != NULL && strcmp(name, kt->name) == 0) || + (!kt->cert && strcasecmp(kt->shortname, name) == 0)) + return kt->type; + } + return KEY_UNSPEC; +} + +int +sshkey_ecdsa_nid_from_name(const char *name) +{ + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) + continue; + if (kt->name != NULL && strcmp(name, kt->name) == 0) + return kt->nid; + } + return -1; +} + +char * +key_alg_list(int certs_only, int plain_only) +{ + char *tmp, *ret = NULL; + size_t nlen, rlen = 0; + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->name == NULL) + continue; + if ((certs_only && !kt->cert) || (plain_only && kt->cert)) + continue; + if (ret != NULL) + ret[rlen++] = '\n'; + nlen = strlen(kt->name); + if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { + free(ret); + return NULL; + } + ret = tmp; + memcpy(ret + rlen, kt->name, nlen + 1); + rlen += nlen; + } + return ret; +} + +int +sshkey_names_valid2(const char *names, int allow_wildcard) +{ + char *s, *cp, *p; + const struct keytype *kt; + int type; + + if (names == NULL || strcmp(names, "") == 0) + return 0; + if ((s = cp = strdup(names)) == NULL) + return 0; + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + type = sshkey_type_from_name(p); + if (type == KEY_RSA1) { + free(s); + return 0; + } + if (type == KEY_UNSPEC) { + if (allow_wildcard) { + /* + * Try matching key types against the string. + * If any has a positive or negative match then + * the component is accepted. + */ + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->type == KEY_RSA1) + continue; + if (match_pattern_list(kt->name, + p, 0) != 0) + break; + } + if (kt->type != -1) + continue; + } + free(s); + return 0; + } + } + free(s); + return 1; +} + +u_int +sshkey_size(const struct sshkey *k) +{ + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_RSA1: + case KEY_RSA: + case KEY_RSA_CERT: + return BN_num_bits(k->rsa->n); + case KEY_DSA: + case KEY_DSA_CERT: + return BN_num_bits(k->dsa->p); + case KEY_ECDSA: + case KEY_ECDSA_CERT: + return sshkey_curve_nid_to_bits(k->ecdsa_nid); +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + return 256; /* XXX */ + } + return 0; +} + +static int +sshkey_type_is_valid_ca(int type) +{ + switch (type) { + case KEY_RSA: + case KEY_DSA: + case KEY_ECDSA: + case KEY_ED25519: + return 1; + default: + return 0; + } +} + +int +sshkey_is_cert(const struct sshkey *k) +{ + if (k == NULL) + return 0; + return sshkey_type_is_cert(k->type); +} + +/* Return the cert-less equivalent to a certified key type */ +int +sshkey_type_plain(int type) +{ + switch (type) { + case KEY_RSA_CERT: + return KEY_RSA; + case KEY_DSA_CERT: + return KEY_DSA; + case KEY_ECDSA_CERT: + return KEY_ECDSA; + case KEY_ED25519_CERT: + return KEY_ED25519; + default: + return type; + } +} + +#ifdef WITH_OPENSSL +/* XXX: these are really begging for a table-driven approach */ +int +sshkey_curve_name_to_nid(const char *name) +{ + if (strcmp(name, "nistp256") == 0) + return NID_X9_62_prime256v1; + else if (strcmp(name, "nistp384") == 0) + return NID_secp384r1; +# ifdef OPENSSL_HAS_NISTP521 + else if (strcmp(name, "nistp521") == 0) + return NID_secp521r1; +# endif /* OPENSSL_HAS_NISTP521 */ + else + return -1; +} + +u_int +sshkey_curve_nid_to_bits(int nid) +{ + switch (nid) { + case NID_X9_62_prime256v1: + return 256; + case NID_secp384r1: + return 384; +# ifdef OPENSSL_HAS_NISTP521 + case NID_secp521r1: + return 521; +# endif /* OPENSSL_HAS_NISTP521 */ + default: + return 0; + } +} + +int +sshkey_ecdsa_bits_to_nid(int bits) +{ + switch (bits) { + case 256: + return NID_X9_62_prime256v1; + case 384: + return NID_secp384r1; +# ifdef OPENSSL_HAS_NISTP521 + case 521: + return NID_secp521r1; +# endif /* OPENSSL_HAS_NISTP521 */ + default: + return -1; + } +} + +const char * +sshkey_curve_nid_to_name(int nid) +{ + switch (nid) { + case NID_X9_62_prime256v1: + return "nistp256"; + case NID_secp384r1: + return "nistp384"; +# ifdef OPENSSL_HAS_NISTP521 + case NID_secp521r1: + return "nistp521"; +# endif /* OPENSSL_HAS_NISTP521 */ + default: + return NULL; + } +} + +int +sshkey_ec_nid_to_hash_alg(int nid) +{ + int kbits = sshkey_curve_nid_to_bits(nid); + + if (kbits <= 0) + return -1; + + /* RFC5656 section 6.2.1 */ + if (kbits <= 256) + return SSH_DIGEST_SHA256; + else if (kbits <= 384) + return SSH_DIGEST_SHA384; + else + return SSH_DIGEST_SHA512; +} +#endif /* WITH_OPENSSL */ + +static void +cert_free(struct sshkey_cert *cert) +{ + u_int i; + + if (cert == NULL) + return; + if (cert->certblob != NULL) + sshbuf_free(cert->certblob); + if (cert->critical != NULL) + sshbuf_free(cert->critical); + if (cert->extensions != NULL) + sshbuf_free(cert->extensions); + if (cert->key_id != NULL) + free(cert->key_id); + for (i = 0; i < cert->nprincipals; i++) + free(cert->principals[i]); + if (cert->principals != NULL) + free(cert->principals); + if (cert->signature_key != NULL) + sshkey_free(cert->signature_key); + explicit_bzero(cert, sizeof(*cert)); + free(cert); +} + +static struct sshkey_cert * +cert_new(void) +{ + struct sshkey_cert *cert; + + if ((cert = calloc(1, sizeof(*cert))) == NULL) + return NULL; + if ((cert->certblob = sshbuf_new()) == NULL || + (cert->critical = sshbuf_new()) == NULL || + (cert->extensions = sshbuf_new()) == NULL) { + cert_free(cert); + return NULL; + } + cert->key_id = NULL; + cert->principals = NULL; + cert->signature_key = NULL; + return cert; +} + +struct sshkey * +sshkey_new(int type) +{ + struct sshkey *k; +#ifdef WITH_OPENSSL + RSA *rsa; + DSA *dsa; +#endif /* WITH_OPENSSL */ + + if ((k = calloc(1, sizeof(*k))) == NULL) + return NULL; + k->type = type; + k->ecdsa = NULL; + k->ecdsa_nid = -1; + k->dsa = NULL; + k->rsa = NULL; + k->cert = NULL; + k->ed25519_sk = NULL; + k->ed25519_pk = NULL; + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_RSA1: + case KEY_RSA: + case KEY_RSA_CERT: + if ((rsa = RSA_new()) == NULL || + (rsa->n = BN_new()) == NULL || + (rsa->e = BN_new()) == NULL) { + if (rsa != NULL) + RSA_free(rsa); + free(k); + return NULL; + } + k->rsa = rsa; + break; + case KEY_DSA: + case KEY_DSA_CERT: + 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); + return NULL; + } + k->dsa = dsa; + break; + case KEY_ECDSA: + case KEY_ECDSA_CERT: + /* Cannot do anything until we know the group */ + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + /* no need to prealloc */ + break; + case KEY_UNSPEC: + break; + default: + free(k); + return NULL; + break; + } + + if (sshkey_is_cert(k)) { + if ((k->cert = cert_new()) == NULL) { + sshkey_free(k); + return NULL; + } + } + + return k; +} + +int +sshkey_add_private(struct sshkey *k) +{ + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_RSA1: + case KEY_RSA: + 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; + case KEY_DSA: + case KEY_DSA_CERT: + if (bn_maybe_alloc_failed(k->dsa->priv_key)) + return SSH_ERR_ALLOC_FAIL; + break; +#undef bn_maybe_alloc_failed + case KEY_ECDSA: + case KEY_ECDSA_CERT: + /* Cannot do anything until we know the group */ + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + /* no need to prealloc */ + break; + case KEY_UNSPEC: + break; + default: + return SSH_ERR_INVALID_ARGUMENT; + } + return 0; +} + +struct sshkey * +sshkey_new_private(int type) +{ + struct sshkey *k = sshkey_new(type); + + if (k == NULL) + return NULL; + if (sshkey_add_private(k) != 0) { + sshkey_free(k); + return NULL; + } + return k; +} + +void +sshkey_free(struct sshkey *k) +{ + if (k == NULL) + return; + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_RSA1: + case KEY_RSA: + case KEY_RSA_CERT: + if (k->rsa != NULL) + RSA_free(k->rsa); + k->rsa = NULL; + break; + case KEY_DSA: + case KEY_DSA_CERT: + if (k->dsa != NULL) + DSA_free(k->dsa); + k->dsa = NULL; + break; +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + case KEY_ECDSA_CERT: + if (k->ecdsa != NULL) + EC_KEY_free(k->ecdsa); + k->ecdsa = NULL; + break; +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + if (k->ed25519_pk) { + explicit_bzero(k->ed25519_pk, ED25519_PK_SZ); + free(k->ed25519_pk); + k->ed25519_pk = NULL; + } + if (k->ed25519_sk) { + explicit_bzero(k->ed25519_sk, ED25519_SK_SZ); + free(k->ed25519_sk); + k->ed25519_sk = NULL; + } + break; + case KEY_UNSPEC: + break; + default: + break; + } + if (sshkey_is_cert(k)) + cert_free(k->cert); + explicit_bzero(k, sizeof(*k)); + free(k); +} + +static int +cert_compare(struct sshkey_cert *a, struct sshkey_cert *b) +{ + if (a == NULL && b == NULL) + return 1; + if (a == NULL || b == NULL) + return 0; + if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob)) + return 0; + if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob), + sshbuf_len(a->certblob)) != 0) + return 0; + return 1; +} + +/* + * Compare public portions of key only, allowing comparisons between + * certificates and plain keys too. + */ +int +sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) +{ +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + BN_CTX *bnctx; +#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ + + if (a == NULL || b == NULL || + sshkey_type_plain(a->type) != sshkey_type_plain(b->type)) + return 0; + + switch (a->type) { +#ifdef WITH_OPENSSL + case KEY_RSA1: + case KEY_RSA_CERT: + case KEY_RSA: + return a->rsa != NULL && b->rsa != NULL && + BN_cmp(a->rsa->e, b->rsa->e) == 0 && + BN_cmp(a->rsa->n, b->rsa->n) == 0; + case KEY_DSA_CERT: + case KEY_DSA: + return a->dsa != NULL && b->dsa != NULL && + BN_cmp(a->dsa->p, b->dsa->p) == 0 && + BN_cmp(a->dsa->q, b->dsa->q) == 0 && + BN_cmp(a->dsa->g, b->dsa->g) == 0 && + BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_CERT: + case KEY_ECDSA: + if (a->ecdsa == NULL || b->ecdsa == NULL || + EC_KEY_get0_public_key(a->ecdsa) == NULL || + EC_KEY_get0_public_key(b->ecdsa) == NULL) + return 0; + if ((bnctx = BN_CTX_new()) == NULL) + return 0; + if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa), + EC_KEY_get0_group(b->ecdsa), bnctx) != 0 || + EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa), + EC_KEY_get0_public_key(a->ecdsa), + EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) { + BN_CTX_free(bnctx); + return 0; + } + BN_CTX_free(bnctx); + return 1; +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + return a->ed25519_pk != NULL && b->ed25519_pk != NULL && + memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0; + default: + return 0; + } + /* NOTREACHED */ +} + +int +sshkey_equal(const struct sshkey *a, const struct sshkey *b) +{ + if (a == NULL || b == NULL || a->type != b->type) + return 0; + if (sshkey_is_cert(a)) { + if (!cert_compare(a->cert, b->cert)) + return 0; + } + return sshkey_equal_public(a, b); +} + +static int +to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) +{ + int type, ret = SSH_ERR_INTERNAL_ERROR; + const char *typename; + + if (key == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + if (sshkey_is_cert(key)) { + if (key->cert == NULL) + return SSH_ERR_EXPECTED_CERT; + if (sshbuf_len(key->cert->certblob) == 0) + return SSH_ERR_KEY_LACKS_CERTBLOB; + } + type = force_plain ? sshkey_type_plain(key->type) : key->type; + typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid); + + switch (type) { +#ifdef WITH_OPENSSL + case KEY_DSA_CERT: + case KEY_ECDSA_CERT: + case KEY_RSA_CERT: +#endif /* WITH_OPENSSL */ + case KEY_ED25519_CERT: + /* Use the existing blob */ + /* XXX modified flag? */ + if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0) + return ret; + break; +#ifdef WITH_OPENSSL + case KEY_DSA: + if (key->dsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if ((ret = sshbuf_put_cstring(b, typename)) != 0 || + (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || + (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || + (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || + (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0) + return ret; + break; +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + if (key->ecdsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if ((ret = sshbuf_put_cstring(b, typename)) != 0 || + (ret = sshbuf_put_cstring(b, + sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || + (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0) + return ret; + break; +# endif + case KEY_RSA: + if (key->rsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if ((ret = sshbuf_put_cstring(b, typename)) != 0 || + (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || + (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0) + return ret; + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + if (key->ed25519_pk == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if ((ret = sshbuf_put_cstring(b, typename)) != 0 || + (ret = sshbuf_put_string(b, + key->ed25519_pk, ED25519_PK_SZ)) != 0) + return ret; + break; + default: + return SSH_ERR_KEY_TYPE_UNKNOWN; + } + return 0; +} + +int +sshkey_putb(const struct sshkey *key, struct sshbuf *b) +{ + return to_blob_buf(key, b, 0); +} + +int +sshkey_puts(const struct sshkey *key, struct sshbuf *b) +{ + struct sshbuf *tmp; + int r; + + if ((tmp = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + r = to_blob_buf(key, tmp, 0); + if (r == 0) + r = sshbuf_put_stringb(b, tmp); + sshbuf_free(tmp); + return r; +} + +int +sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b) +{ + return to_blob_buf(key, b, 1); +} + +static int +to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain) +{ + int ret = SSH_ERR_INTERNAL_ERROR; + size_t len; + struct sshbuf *b = NULL; + + if (lenp != NULL) + *lenp = 0; + if (blobp != NULL) + *blobp = NULL; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((ret = to_blob_buf(key, b, force_plain)) != 0) + goto out; + len = sshbuf_len(b); + if (lenp != NULL) + *lenp = len; + if (blobp != NULL) { + if ((*blobp = malloc(len)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + memcpy(*blobp, sshbuf_ptr(b), len); + } + ret = 0; + out: + sshbuf_free(b); + return ret; +} + +int +sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) +{ + return to_blob(key, blobp, lenp, 0); +} + +int +sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) +{ + return to_blob(key, blobp, lenp, 1); +} + +int +sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, + u_char **retp, size_t *lenp) +{ + u_char *blob = NULL, *ret = NULL; + size_t blob_len = 0; + int r = SSH_ERR_INTERNAL_ERROR; + + if (retp != NULL) + *retp = NULL; + if (lenp != NULL) + *lenp = 0; + if (ssh_digest_bytes(dgst_alg) == 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + + if (k->type == KEY_RSA1) { +#ifdef WITH_OPENSSL + int nlen = BN_num_bytes(k->rsa->n); + int elen = BN_num_bytes(k->rsa->e); + + blob_len = nlen + elen; + if (nlen >= INT_MAX - elen || + (blob = malloc(blob_len)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + BN_bn2bin(k->rsa->n, blob); + BN_bn2bin(k->rsa->e, blob + nlen); +#endif /* WITH_OPENSSL */ + } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0) + goto out; + if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = ssh_digest_memory(dgst_alg, blob, blob_len, + ret, SSH_DIGEST_MAX_LENGTH)) != 0) + goto out; + /* success */ + if (retp != NULL) { + *retp = ret; + ret = NULL; + } + if (lenp != NULL) + *lenp = ssh_digest_bytes(dgst_alg); + r = 0; + out: + free(ret); + if (blob != NULL) { + explicit_bzero(blob, blob_len); + free(blob); + } + return r; +} + +static char * +fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) +{ + char *ret; + size_t plen = strlen(alg) + 1; + size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1; + int r; + + if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL) + return NULL; + strlcpy(ret, alg, rlen); + strlcat(ret, ":", rlen); + if (dgst_raw_len == 0) + return ret; + if ((r = b64_ntop(dgst_raw, dgst_raw_len, + ret + plen, rlen - plen)) == -1) { + explicit_bzero(ret, rlen); + free(ret); + return NULL; + } + /* Trim padding characters from end */ + ret[strcspn(ret, "=")] = '\0'; + return ret; +} + +static char * +fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) +{ + char *retval, hex[5]; + size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2; + + if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL) + return NULL; + strlcpy(retval, alg, rlen); + strlcat(retval, ":", rlen); + for (i = 0; i < dgst_raw_len; i++) { + snprintf(hex, sizeof(hex), "%s%02x", + i > 0 ? ":" : "", dgst_raw[i]); + strlcat(retval, hex, rlen); + } + return retval; +} + +static char * +fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len) +{ + char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; + char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', + 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; + u_int i, j = 0, rounds, seed = 1; + char *retval; + + rounds = (dgst_raw_len / 2) + 1; + if ((retval = calloc(rounds, 6)) == NULL) + return NULL; + retval[j++] = 'x'; + for (i = 0; i < rounds; i++) { + u_int idx0, idx1, idx2, idx3, idx4; + if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { + idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + + seed) % 6; + idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; + idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + + (seed / 6)) % 6; + retval[j++] = vowels[idx0]; + retval[j++] = consonants[idx1]; + retval[j++] = vowels[idx2]; + if ((i + 1) < rounds) { + idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; + idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; + retval[j++] = consonants[idx3]; + retval[j++] = '-'; + retval[j++] = consonants[idx4]; + seed = ((seed * 5) + + ((((u_int)(dgst_raw[2 * i])) * 7) + + ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; + } + } else { + idx0 = seed % 6; + idx1 = 16; + idx2 = seed / 6; + retval[j++] = vowels[idx0]; + retval[j++] = consonants[idx1]; + retval[j++] = vowels[idx2]; + } + } + retval[j++] = 'x'; + retval[j++] = '\0'; + return retval; +} + +/* + * Draw an ASCII-Art representing the fingerprint so human brain can + * profit from its built-in pattern recognition ability. + * This technique is called "random art" and can be found in some + * scientific publications like this original paper: + * + * "Hash Visualization: a New Technique to improve Real-World Security", + * Perrig A. and Song D., 1999, International Workshop on Cryptographic + * Techniques and E-Commerce (CrypTEC '99) + * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf + * + * The subject came up in a talk by Dan Kaminsky, too. + * + * If you see the picture is different, the key is different. + * If the picture looks the same, you still know nothing. + * + * The algorithm used here is a worm crawling over a discrete plane, + * leaving a trace (augmenting the field) everywhere it goes. + * Movement is taken from dgst_raw 2bit-wise. Bumping into walls + * makes the respective movement vector be ignored for this turn. + * Graphs are not unambiguous, because circles in graphs can be + * walked in either direction. + */ + +/* + * Field sizes for the random art. Have to be odd, so the starting point + * can be in the exact middle of the picture, and FLDBASE should be >=8 . + * Else pictures would be too dense, and drawing the frame would + * fail, too, because the key type would not fit in anymore. + */ +#define FLDBASE 8 +#define FLDSIZE_Y (FLDBASE + 1) +#define FLDSIZE_X (FLDBASE * 2 + 1) +static char * +fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len, + const struct sshkey *k) +{ + /* + * Chars to be used after each other every time the worm + * intersects with itself. Matter of taste. + */ + char *augmentation_string = " .o+=*BOX@%&#/^SE"; + char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X]; + u_char field[FLDSIZE_X][FLDSIZE_Y]; + size_t i, tlen, hlen; + u_int b; + int x, y, r; + size_t len = strlen(augmentation_string) - 1; + + if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL) + return NULL; + + /* initialize field */ + memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); + x = FLDSIZE_X / 2; + y = FLDSIZE_Y / 2; + + /* process raw key */ + for (i = 0; i < dgst_raw_len; i++) { + int input; + /* each byte conveys four 2-bit move commands */ + input = dgst_raw[i]; + for (b = 0; b < 4; b++) { + /* evaluate 2 bit, rest is shifted later */ + x += (input & 0x1) ? 1 : -1; + y += (input & 0x2) ? 1 : -1; + + /* assure we are still in bounds */ + x = MAX(x, 0); + y = MAX(y, 0); + x = MIN(x, FLDSIZE_X - 1); + y = MIN(y, FLDSIZE_Y - 1); + + /* augment the field */ + if (field[x][y] < len - 2) + field[x][y]++; + input = input >> 2; + } + } + + /* mark starting point and end point*/ + field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; + field[x][y] = len; + + /* assemble title */ + r = snprintf(title, sizeof(title), "[%s %u]", + sshkey_type(k), sshkey_size(k)); + /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ + if (r < 0 || r > (int)sizeof(title)) + r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); + tlen = (r <= 0) ? 0 : strlen(title); + + /* assemble hash ID. */ + r = snprintf(hash, sizeof(hash), "[%s]", alg); + hlen = (r <= 0) ? 0 : strlen(hash); + + /* output upper border */ + p = retval; + *p++ = '+'; + for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++) + *p++ = '-'; + memcpy(p, title, tlen); + p += tlen; + for (i += tlen; i < FLDSIZE_X; i++) + *p++ = '-'; + *p++ = '+'; + *p++ = '\n'; + + /* output content */ + for (y = 0; y < FLDSIZE_Y; y++) { + *p++ = '|'; + for (x = 0; x < FLDSIZE_X; x++) + *p++ = augmentation_string[MIN(field[x][y], len)]; + *p++ = '|'; + *p++ = '\n'; + } + + /* output lower border */ + *p++ = '+'; + for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++) + *p++ = '-'; + memcpy(p, hash, hlen); + p += hlen; + for (i += hlen; i < FLDSIZE_X; i++) + *p++ = '-'; + *p++ = '+'; + + return retval; +} + +char * +sshkey_fingerprint(const struct sshkey *k, int dgst_alg, + enum sshkey_fp_rep dgst_rep) +{ + char *retval = NULL; + u_char *dgst_raw; + size_t dgst_raw_len; + + if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0) + return NULL; + switch (dgst_rep) { + case SSH_FP_DEFAULT: + if (dgst_alg == SSH_DIGEST_MD5) { + retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len); + } else { + retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len); + } + break; + case SSH_FP_HEX: + retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len); + break; + case SSH_FP_BASE64: + retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len); + break; + case SSH_FP_BUBBLEBABBLE: + retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len); + break; + case SSH_FP_RANDOMART: + retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg), + dgst_raw, dgst_raw_len, k); + break; + default: + explicit_bzero(dgst_raw, dgst_raw_len); + free(dgst_raw); + return NULL; + } + explicit_bzero(dgst_raw, dgst_raw_len); + free(dgst_raw); + return retval; +} + +#ifdef WITH_SSH1 +/* + * Reads a multiple-precision integer in decimal from the buffer, and advances + * the pointer. The integer must already be initialized. This function is + * permitted to modify the buffer. This leaves *cpp to point just beyond the + * last processed character. + */ +static int +read_decimal_bignum(char **cpp, BIGNUM *v) +{ + char *cp; + size_t e; + int skip = 1; /* skip white space */ + + cp = *cpp; + while (*cp == ' ' || *cp == '\t') + cp++; + e = strspn(cp, "0123456789"); + if (e == 0) + return SSH_ERR_INVALID_FORMAT; + if (e > SSHBUF_MAX_BIGNUM * 3) + return SSH_ERR_BIGNUM_TOO_LARGE; + if (cp[e] == '\0') + skip = 0; + else if (index(" \t\r\n", cp[e]) == NULL) + return SSH_ERR_INVALID_FORMAT; + cp[e] = '\0'; + if (BN_dec2bn(&v, cp) <= 0) + return SSH_ERR_INVALID_FORMAT; + *cpp = cp + e + skip; + return 0; +} +#endif /* WITH_SSH1 */ + +/* returns 0 ok, and < 0 error */ +int +sshkey_read(struct sshkey *ret, char **cpp) +{ + struct sshkey *k; + int retval = SSH_ERR_INVALID_FORMAT; + char *cp, *space; + int r, type, curve_nid = -1; + struct sshbuf *blob; +#ifdef WITH_SSH1 + char *ep; + u_long bits; +#endif /* WITH_SSH1 */ + + cp = *cpp; + + switch (ret->type) { + case KEY_RSA1: +#ifdef WITH_SSH1 + /* Get number of bits. */ + bits = strtoul(cp, &ep, 10); + if (*cp == '\0' || index(" \t\r\n", *ep) == NULL || + bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8) + return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */ + /* Get public exponent, public modulus. */ + if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0) + return r; + if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0) + return r; + *cpp = ep; + /* validate the claimed number of bits */ + if (BN_num_bits(ret->rsa->n) != (int)bits) + return SSH_ERR_KEY_BITS_MISMATCH; + retval = 0; +#endif /* WITH_SSH1 */ + break; + case KEY_UNSPEC: + case KEY_RSA: + case KEY_DSA: + case KEY_ECDSA: + case KEY_ED25519: + case KEY_DSA_CERT: + case KEY_ECDSA_CERT: + case KEY_RSA_CERT: + case KEY_ED25519_CERT: + space = strchr(cp, ' '); + if (space == NULL) + return SSH_ERR_INVALID_FORMAT; + *space = '\0'; + type = sshkey_type_from_name(cp); + if (sshkey_type_plain(type) == KEY_ECDSA && + (curve_nid = sshkey_ecdsa_nid_from_name(cp)) == -1) + return SSH_ERR_EC_CURVE_INVALID; + *space = ' '; + if (type == KEY_UNSPEC) + return SSH_ERR_INVALID_FORMAT; + cp = space+1; + if (*cp == '\0') + return SSH_ERR_INVALID_FORMAT; + if (ret->type != KEY_UNSPEC && ret->type != type) + return SSH_ERR_KEY_TYPE_MISMATCH; + if ((blob = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + /* trim comment */ + space = strchr(cp, ' '); + if (space) { + /* advance 'space': skip whitespace */ + *space++ = '\0'; + while (*space == ' ' || *space == '\t') + space++; + *cpp = space; + } else + *cpp = cp + strlen(cp); + if ((r = sshbuf_b64tod(blob, cp)) != 0) { + sshbuf_free(blob); + return r; + } + if ((r = sshkey_from_blob(sshbuf_ptr(blob), + sshbuf_len(blob), &k)) != 0) { + sshbuf_free(blob); + return r; + } + sshbuf_free(blob); + if (k->type != type) { + sshkey_free(k); + return SSH_ERR_KEY_TYPE_MISMATCH; + } + if (sshkey_type_plain(type) == KEY_ECDSA && + curve_nid != k->ecdsa_nid) { + sshkey_free(k); + return SSH_ERR_EC_CURVE_MISMATCH; + } + ret->type = type; + if (sshkey_is_cert(ret)) { + if (!sshkey_is_cert(k)) { + sshkey_free(k); + return SSH_ERR_EXPECTED_CERT; + } + if (ret->cert != NULL) + cert_free(ret->cert); + ret->cert = k->cert; + k->cert = NULL; + } +#ifdef WITH_OPENSSL + if (sshkey_type_plain(ret->type) == KEY_RSA) { + if (ret->rsa != NULL) + RSA_free(ret->rsa); + ret->rsa = k->rsa; + k->rsa = NULL; +#ifdef DEBUG_PK + RSA_print_fp(stderr, ret->rsa, 8); +#endif + } + if (sshkey_type_plain(ret->type) == KEY_DSA) { + if (ret->dsa != NULL) + DSA_free(ret->dsa); + ret->dsa = k->dsa; + k->dsa = NULL; +#ifdef DEBUG_PK + DSA_print_fp(stderr, ret->dsa, 8); +#endif + } +# ifdef OPENSSL_HAS_ECC + if (sshkey_type_plain(ret->type) == KEY_ECDSA) { + if (ret->ecdsa != NULL) + EC_KEY_free(ret->ecdsa); + ret->ecdsa = k->ecdsa; + ret->ecdsa_nid = k->ecdsa_nid; + k->ecdsa = NULL; + k->ecdsa_nid = -1; +#ifdef DEBUG_PK + sshkey_dump_ec_key(ret->ecdsa); +#endif + } +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + if (sshkey_type_plain(ret->type) == KEY_ED25519) { + free(ret->ed25519_pk); + ret->ed25519_pk = k->ed25519_pk; + k->ed25519_pk = NULL; +#ifdef DEBUG_PK + /* XXX */ +#endif + } + retval = 0; +/*XXXX*/ + sshkey_free(k); + if (retval != 0) + break; + break; + default: + return SSH_ERR_INVALID_ARGUMENT; + } + return retval; +} + +int +sshkey_to_base64(const struct sshkey *key, char **b64p) +{ + int r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; + char *uu = NULL; + + if (b64p != NULL) + *b64p = NULL; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_putb(key, b)) != 0) + goto out; + if ((uu = sshbuf_dtob64(b)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* Success */ + if (b64p != NULL) { + *b64p = uu; + uu = NULL; + } + r = 0; + out: + sshbuf_free(b); + free(uu); + return r; +} + +static int +sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b) +{ + int r = SSH_ERR_INTERNAL_ERROR; +#ifdef WITH_SSH1 + u_int bits = 0; + char *dec_e = NULL, *dec_n = NULL; + + if (key->rsa == NULL || key->rsa->e == NULL || + key->rsa->n == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || + (dec_n = BN_bn2dec(key->rsa->n)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* size of modulus 'n' */ + if ((bits = BN_num_bits(key->rsa->n)) <= 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((r = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0) + goto out; + + /* Success */ + r = 0; + out: + if (dec_e != NULL) + OPENSSL_free(dec_e); + if (dec_n != NULL) + OPENSSL_free(dec_n); +#endif /* WITH_SSH1 */ + + return r; +} + +static int +sshkey_format_text(const struct sshkey *key, struct sshbuf *b) +{ + int r = SSH_ERR_INTERNAL_ERROR; + char *uu = NULL; + + if (key->type == KEY_RSA1) { + if ((r = sshkey_format_rsa1(key, b)) != 0) + goto out; + } else { + /* Unsupported key types handled in sshkey_to_base64() */ + if ((r = sshkey_to_base64(key, &uu)) != 0) + goto out; + if ((r = sshbuf_putf(b, "%s %s", + sshkey_ssh_name(key), uu)) != 0) + goto out; + } + r = 0; + out: + free(uu); + return r; +} + +int +sshkey_write(const struct sshkey *key, FILE *f) +{ + struct sshbuf *b = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_format_text(key, b)) != 0) + goto out; + if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) { + if (feof(f)) + errno = EPIPE; + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + /* Success */ + r = 0; + out: + sshbuf_free(b); + return r; +} + +const char * +sshkey_cert_type(const struct sshkey *k) +{ + switch (k->cert->type) { + case SSH2_CERT_TYPE_USER: + return "user"; + case SSH2_CERT_TYPE_HOST: + return "host"; + default: + return "unknown"; + } +} + +#ifdef WITH_OPENSSL +static int +rsa_generate_private_key(u_int bits, RSA **rsap) +{ + RSA *private = NULL; + BIGNUM *f4 = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (rsap == NULL || + bits < SSH_RSA_MINIMUM_MODULUS_SIZE || + bits > SSHBUF_MAX_BIGNUM * 8) + return SSH_ERR_INVALID_ARGUMENT; + *rsap = NULL; + if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (!BN_set_word(f4, RSA_F4) || + !RSA_generate_key_ex(private, bits, f4, NULL)) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + *rsap = private; + private = NULL; + ret = 0; + out: + if (private != NULL) + RSA_free(private); + if (f4 != NULL) + BN_free(f4); + return ret; +} + +static int +dsa_generate_private_key(u_int bits, DSA **dsap) +{ + DSA *private; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (dsap == NULL || bits != 1024) + return SSH_ERR_INVALID_ARGUMENT; + if ((private = DSA_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + *dsap = NULL; + if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, + NULL, NULL) || !DSA_generate_key(private)) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + *dsap = private; + private = NULL; + ret = 0; + out: + if (private != NULL) + DSA_free(private); + return ret; +} + +# ifdef OPENSSL_HAS_ECC +int +sshkey_ecdsa_key_to_nid(EC_KEY *k) +{ + EC_GROUP *eg; + int nids[] = { + NID_X9_62_prime256v1, + NID_secp384r1, +# ifdef OPENSSL_HAS_NISTP521 + NID_secp521r1, +# endif /* OPENSSL_HAS_NISTP521 */ + -1 + }; + int nid; + u_int i; + BN_CTX *bnctx; + const EC_GROUP *g = EC_KEY_get0_group(k); + + /* + * The group may be stored in a ASN.1 encoded private key in one of two + * ways: as a "named group", which is reconstituted by ASN.1 object ID + * or explicit group parameters encoded into the key blob. Only the + * "named group" case sets the group NID for us, but we can figure + * it out for the other case by comparing against all the groups that + * are supported. + */ + if ((nid = EC_GROUP_get_curve_name(g)) > 0) + return nid; + if ((bnctx = BN_CTX_new()) == NULL) + return -1; + for (i = 0; nids[i] != -1; i++) { + if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) { + BN_CTX_free(bnctx); + return -1; + } + if (EC_GROUP_cmp(g, eg, bnctx) == 0) + break; + EC_GROUP_free(eg); + } + BN_CTX_free(bnctx); + if (nids[i] != -1) { + /* Use the group with the NID attached */ + EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE); + if (EC_KEY_set_group(k, eg) != 1) { + EC_GROUP_free(eg); + return -1; + } + } + return nids[i]; +} + +static int +ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) +{ + EC_KEY *private; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (nid == NULL || ecdsap == NULL || + (*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) + return SSH_ERR_INVALID_ARGUMENT; + *ecdsap = NULL; + if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_KEY_generate_key(private) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); + *ecdsap = private; + private = NULL; + ret = 0; + out: + if (private != NULL) + EC_KEY_free(private); + return ret; +} +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + +int +sshkey_generate(int type, u_int bits, struct sshkey **keyp) +{ + struct sshkey *k; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (keyp == NULL) + return SSH_ERR_INVALID_ARGUMENT; + *keyp = NULL; + if ((k = sshkey_new(KEY_UNSPEC)) == NULL) + return SSH_ERR_ALLOC_FAIL; + switch (type) { + case KEY_ED25519: + if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL || + (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + break; + } + crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); + ret = 0; + break; +#ifdef WITH_OPENSSL + case KEY_DSA: + ret = dsa_generate_private_key(bits, &k->dsa); + break; +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid, + &k->ecdsa); + break; +# endif /* OPENSSL_HAS_ECC */ + case KEY_RSA: + case KEY_RSA1: + ret = rsa_generate_private_key(bits, &k->rsa); + break; +#endif /* WITH_OPENSSL */ + default: + ret = SSH_ERR_INVALID_ARGUMENT; + } + if (ret == 0) { + k->type = type; + *keyp = k; + } else + sshkey_free(k); + return ret; +} + +int +sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) +{ + u_int i; + const struct sshkey_cert *from; + struct sshkey_cert *to; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (to_key->cert != NULL) { + cert_free(to_key->cert); + to_key->cert = NULL; + } + + if ((from = from_key->cert) == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + if ((to = to_key->cert = cert_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + + if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 || + (ret = sshbuf_putb(to->critical, from->critical)) != 0 || + (ret = sshbuf_putb(to->extensions, from->extensions) != 0)) + return ret; + + to->serial = from->serial; + to->type = from->type; + if (from->key_id == NULL) + to->key_id = NULL; + else if ((to->key_id = strdup(from->key_id)) == NULL) + return SSH_ERR_ALLOC_FAIL; + to->valid_after = from->valid_after; + to->valid_before = from->valid_before; + if (from->signature_key == NULL) + to->signature_key = NULL; + else if ((ret = sshkey_from_private(from->signature_key, + &to->signature_key)) != 0) + return ret; + + if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) + return SSH_ERR_INVALID_ARGUMENT; + if (from->nprincipals > 0) { + if ((to->principals = calloc(from->nprincipals, + sizeof(*to->principals))) == NULL) + return SSH_ERR_ALLOC_FAIL; + for (i = 0; i < from->nprincipals; i++) { + to->principals[i] = strdup(from->principals[i]); + if (to->principals[i] == NULL) { + to->nprincipals = i; + return SSH_ERR_ALLOC_FAIL; + } + } + } + to->nprincipals = from->nprincipals; + return 0; +} + +int +sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) +{ + struct sshkey *n = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (pkp != NULL) + *pkp = NULL; + + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_DSA: + case KEY_DSA_CERT: + if ((n = sshkey_new(k->type)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || + (BN_copy(n->dsa->q, k->dsa->q) == NULL) || + (BN_copy(n->dsa->g, k->dsa->g) == NULL) || + (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) { + sshkey_free(n); + return SSH_ERR_ALLOC_FAIL; + } + break; +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + case KEY_ECDSA_CERT: + if ((n = sshkey_new(k->type)) == NULL) + return SSH_ERR_ALLOC_FAIL; + n->ecdsa_nid = k->ecdsa_nid; + n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); + if (n->ecdsa == NULL) { + sshkey_free(n); + return SSH_ERR_ALLOC_FAIL; + } + if (EC_KEY_set_public_key(n->ecdsa, + EC_KEY_get0_public_key(k->ecdsa)) != 1) { + sshkey_free(n); + return SSH_ERR_LIBCRYPTO_ERROR; + } + break; +# endif /* OPENSSL_HAS_ECC */ + case KEY_RSA: + case KEY_RSA1: + case KEY_RSA_CERT: + if ((n = sshkey_new(k->type)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || + (BN_copy(n->rsa->e, k->rsa->e) == NULL)) { + sshkey_free(n); + return SSH_ERR_ALLOC_FAIL; + } + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + if ((n = sshkey_new(k->type)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (k->ed25519_pk != NULL) { + if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { + sshkey_free(n); + return SSH_ERR_ALLOC_FAIL; + } + memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); + } + break; + default: + return SSH_ERR_KEY_TYPE_UNKNOWN; + } + if (sshkey_is_cert(k)) { + if ((ret = sshkey_cert_copy(k, n)) != 0) { + sshkey_free(n); + return ret; + } + } + *pkp = n; + return 0; +} + +static int +cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) +{ + struct sshbuf *principals = NULL, *crit = NULL; + struct sshbuf *exts = NULL, *ca = NULL; + u_char *sig = NULL; + size_t signed_len = 0, slen = 0, kidlen = 0; + int ret = SSH_ERR_INTERNAL_ERROR; + + /* Copy the entire key blob for verification and later serialisation */ + if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0) + return ret; + + /* Parse body of certificate up to signature */ + if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 || + (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || + (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || + (ret = sshbuf_froms(b, &principals)) != 0 || + (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || + (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || + (ret = sshbuf_froms(b, &crit)) != 0 || + (ret = sshbuf_froms(b, &exts)) != 0 || + (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || + (ret = sshbuf_froms(b, &ca)) != 0) { + /* XXX debug print error for ret */ + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* Signature is left in the buffer so we can calculate this length */ + signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b); + + if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + + if (key->cert->type != SSH2_CERT_TYPE_USER && + key->cert->type != SSH2_CERT_TYPE_HOST) { + ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE; + goto out; + } + + /* Parse principals section */ + while (sshbuf_len(principals) > 0) { + char *principal = NULL; + char **oprincipals = NULL; + + if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((ret = sshbuf_get_cstring(principals, &principal, + NULL)) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + oprincipals = key->cert->principals; + key->cert->principals = reallocarray(key->cert->principals, + key->cert->nprincipals + 1, sizeof(*key->cert->principals)); + if (key->cert->principals == NULL) { + free(principal); + key->cert->principals = oprincipals; + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + key->cert->principals[key->cert->nprincipals++] = principal; + } + + /* + * Stash a copies of the critical options and extensions sections + * for later use. + */ + if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 || + (exts != NULL && + (ret = sshbuf_putb(key->cert->extensions, exts)) != 0)) + goto out; + + /* + * Validate critical options and extensions sections format. + */ + while (sshbuf_len(crit) != 0) { + if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 || + (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) { + sshbuf_reset(key->cert->critical); + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + } + while (exts != NULL && sshbuf_len(exts) != 0) { + if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 || + (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) { + sshbuf_reset(key->cert->extensions); + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + } + + /* Parse CA key and check signature */ + if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) { + ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; + goto out; + } + if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) { + ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; + goto out; + } + if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, + sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0) + goto out; + + /* Success */ + ret = 0; + out: + sshbuf_free(ca); + sshbuf_free(crit); + sshbuf_free(exts); + sshbuf_free(principals); + free(sig); + return ret; +} + +static int +sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + int allow_cert) +{ + int type, ret = SSH_ERR_INTERNAL_ERROR; + char *ktype = NULL, *curve = NULL; + struct sshkey *key = NULL; + size_t len; + u_char *pk = NULL; + struct sshbuf *copy; +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + EC_POINT *q = NULL; +#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ + +#ifdef DEBUG_PK /* XXX */ + sshbuf_dump(b, stderr); +#endif + *keyp = NULL; + if ((copy = sshbuf_fromb(b)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + + type = sshkey_type_from_name(ktype); + if (!allow_cert && sshkey_type_is_cert(type)) { + ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; + goto out; + } + switch (type) { +#ifdef WITH_OPENSSL + case KEY_RSA_CERT: + /* Skip nonce */ + if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* FALLTHROUGH */ + case KEY_RSA: + if ((key = sshkey_new(type)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (sshbuf_get_bignum2(b, key->rsa->e) != 0 || + sshbuf_get_bignum2(b, key->rsa->n) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } +#ifdef DEBUG_PK + RSA_print_fp(stderr, key->rsa, 8); +#endif + break; + case KEY_DSA_CERT: + /* Skip nonce */ + if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* FALLTHROUGH */ + case KEY_DSA: + if ((key = sshkey_new(type)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (sshbuf_get_bignum2(b, key->dsa->p) != 0 || + sshbuf_get_bignum2(b, key->dsa->q) != 0 || + sshbuf_get_bignum2(b, key->dsa->g) != 0 || + sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } +#ifdef DEBUG_PK + DSA_print_fp(stderr, key->dsa, 8); +#endif + break; + case KEY_ECDSA_CERT: + /* Skip nonce */ + if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* FALLTHROUGH */ +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + if ((key = sshkey_new(type)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype); + if (sshbuf_get_cstring(b, &curve, NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) { + ret = SSH_ERR_EC_CURVE_MISMATCH; + goto out; + } + if (key->ecdsa != NULL) + EC_KEY_free(key->ecdsa); + if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) + == NULL) { + ret = SSH_ERR_EC_CURVE_INVALID; + goto out; + } + if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), + q) != 0) { + ret = SSH_ERR_KEY_INVALID_EC_VALUE; + goto out; + } + if (EC_KEY_set_public_key(key->ecdsa, q) != 1) { + /* XXX assume it is a allocation error */ + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +#ifdef DEBUG_PK + sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); +#endif + break; +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + case KEY_ED25519_CERT: + /* Skip nonce */ + if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* FALLTHROUGH */ + case KEY_ED25519: + if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) + goto out; + if (len != ED25519_PK_SZ) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((key = sshkey_new(type)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + key->ed25519_pk = pk; + pk = NULL; + break; + case KEY_UNSPEC: + if ((key = sshkey_new(type)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + break; + default: + ret = SSH_ERR_KEY_TYPE_UNKNOWN; + goto out; + } + + /* Parse certificate potion */ + if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0) + goto out; + + if (key != NULL && sshbuf_len(b) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + ret = 0; + *keyp = key; + key = NULL; + out: + sshbuf_free(copy); + sshkey_free(key); + free(ktype); + free(curve); + free(pk); +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + if (q != NULL) + EC_POINT_free(q); +#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ + return ret; +} + +int +sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp) +{ + struct sshbuf *b; + int r; + + if ((b = sshbuf_from(blob, blen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + r = sshkey_from_blob_internal(b, keyp, 1); + sshbuf_free(b); + return r; +} + +int +sshkey_fromb(struct sshbuf *b, struct sshkey **keyp) +{ + return sshkey_from_blob_internal(b, keyp, 1); +} + +int +sshkey_froms(struct sshbuf *buf, struct sshkey **keyp) +{ + struct sshbuf *b; + int r; + + if ((r = sshbuf_froms(buf, &b)) != 0) + return r; + r = sshkey_from_blob_internal(b, keyp, 1); + sshbuf_free(b); + return r; +} + +int +sshkey_sign(const struct sshkey *key, + u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) +{ + if (sigp != NULL) + *sigp = NULL; + if (lenp != NULL) + *lenp = 0; + if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) + return SSH_ERR_INVALID_ARGUMENT; + switch (key->type) { +#ifdef WITH_OPENSSL + case KEY_DSA_CERT: + case KEY_DSA: + return ssh_dss_sign(key, sigp, lenp, data, datalen, compat); +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_CERT: + case KEY_ECDSA: + return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); +# endif /* OPENSSL_HAS_ECC */ + case KEY_RSA_CERT: + case KEY_RSA: + return ssh_rsa_sign(key, sigp, lenp, data, datalen, compat); +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat); + default: + return SSH_ERR_KEY_TYPE_UNKNOWN; + } +} + +/* + * ssh_key_verify returns 0 for a correct signature and < 0 on error. + */ +int +sshkey_verify(const struct sshkey *key, + const u_char *sig, size_t siglen, + const u_char *data, size_t dlen, u_int compat) +{ + if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) + return SSH_ERR_INVALID_ARGUMENT; + switch (key->type) { +#ifdef WITH_OPENSSL + case KEY_DSA_CERT: + case KEY_DSA: + return ssh_dss_verify(key, sig, siglen, data, dlen, compat); +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_CERT: + case KEY_ECDSA: + return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat); +# endif /* OPENSSL_HAS_ECC */ + case KEY_RSA_CERT: + case KEY_RSA: + return ssh_rsa_verify(key, sig, siglen, data, dlen, compat); +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat); + default: + return SSH_ERR_KEY_TYPE_UNKNOWN; + } +} + +/* Converts a private to a public key */ +int +sshkey_demote(const struct sshkey *k, struct sshkey **dkp) +{ + struct sshkey *pk; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (dkp != NULL) + *dkp = NULL; + + if ((pk = calloc(1, sizeof(*pk))) == NULL) + return SSH_ERR_ALLOC_FAIL; + pk->type = k->type; + pk->flags = k->flags; + pk->ecdsa_nid = k->ecdsa_nid; + pk->dsa = NULL; + pk->ecdsa = NULL; + pk->rsa = NULL; + pk->ed25519_pk = NULL; + pk->ed25519_sk = NULL; + + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_RSA_CERT: + if ((ret = sshkey_cert_copy(k, pk)) != 0) + goto fail; + /* FALLTHROUGH */ + case KEY_RSA1: + case KEY_RSA: + if ((pk->rsa = RSA_new()) == NULL || + (pk->rsa->e = BN_dup(k->rsa->e)) == NULL || + (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto fail; + } + break; + case KEY_DSA_CERT: + if ((ret = sshkey_cert_copy(k, pk)) != 0) + goto fail; + /* FALLTHROUGH */ + case KEY_DSA: + if ((pk->dsa = DSA_new()) == NULL || + (pk->dsa->p = BN_dup(k->dsa->p)) == NULL || + (pk->dsa->q = BN_dup(k->dsa->q)) == NULL || + (pk->dsa->g = BN_dup(k->dsa->g)) == NULL || + (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto fail; + } + break; + case KEY_ECDSA_CERT: + if ((ret = sshkey_cert_copy(k, pk)) != 0) + goto fail; + /* FALLTHROUGH */ +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid); + if (pk->ecdsa == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto fail; + } + if (EC_KEY_set_public_key(pk->ecdsa, + EC_KEY_get0_public_key(k->ecdsa)) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto fail; + } + break; +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + case KEY_ED25519_CERT: + if ((ret = sshkey_cert_copy(k, pk)) != 0) + goto fail; + /* FALLTHROUGH */ + case KEY_ED25519: + if (k->ed25519_pk != NULL) { + if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto fail; + } + memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); + } + break; + default: + ret = SSH_ERR_KEY_TYPE_UNKNOWN; + fail: + sshkey_free(pk); + return ret; + } + *dkp = pk; + return 0; +} + +/* Convert a plain key to their _CERT equivalent */ +int +sshkey_to_certified(struct sshkey *k) +{ + int newtype; + + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_RSA: + newtype = KEY_RSA_CERT; + break; + case KEY_DSA: + newtype = KEY_DSA_CERT; + break; + case KEY_ECDSA: + newtype = KEY_ECDSA_CERT; + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + newtype = KEY_ED25519_CERT; + break; + default: + return SSH_ERR_INVALID_ARGUMENT; + } + if ((k->cert = cert_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + k->type = newtype; + return 0; +} + +/* Convert a certificate to its raw key equivalent */ +int +sshkey_drop_cert(struct sshkey *k) +{ + if (!sshkey_type_is_cert(k->type)) + return SSH_ERR_KEY_TYPE_UNKNOWN; + cert_free(k->cert); + k->cert = NULL; + k->type = sshkey_type_plain(k->type); + return 0; +} + +/* Sign a certified key, (re-)generating the signed certblob. */ +int +sshkey_certify(struct sshkey *k, struct sshkey *ca) +{ + struct sshbuf *principals = NULL; + u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; + size_t i, ca_len, sig_len; + int ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *cert; + + if (k == NULL || k->cert == NULL || + k->cert->certblob == NULL || ca == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if (!sshkey_is_cert(k)) + return SSH_ERR_KEY_TYPE_UNKNOWN; + if (!sshkey_type_is_valid_ca(ca->type)) + return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; + + if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) + return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; + + cert = k->cert->certblob; /* for readability */ + sshbuf_reset(cert); + if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0) + goto out; + + /* -v01 certs put nonce first */ + arc4random_buf(&nonce, sizeof(nonce)); + if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0) + goto out; + + /* XXX this substantially duplicates to_blob(); refactor */ + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_DSA_CERT: + if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 || + (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 || + (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 || + (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0) + goto out; + break; +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_CERT: + if ((ret = sshbuf_put_cstring(cert, + sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 || + (ret = sshbuf_put_ec(cert, + EC_KEY_get0_public_key(k->ecdsa), + EC_KEY_get0_group(k->ecdsa))) != 0) + goto out; + break; +# endif /* OPENSSL_HAS_ECC */ + case KEY_RSA_CERT: + if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 || + (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0) + goto out; + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519_CERT: + if ((ret = sshbuf_put_string(cert, + k->ed25519_pk, ED25519_PK_SZ)) != 0) + goto out; + break; + default: + ret = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + + if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 || + (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 || + (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0) + goto out; + + if ((principals = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + for (i = 0; i < k->cert->nprincipals; i++) { + if ((ret = sshbuf_put_cstring(principals, + k->cert->principals[i])) != 0) + goto out; + } + if ((ret = sshbuf_put_stringb(cert, principals)) != 0 || + (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 || + (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 || + (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 || + (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 || + (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */ + (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0) + goto out; + + /* Sign the whole mess */ + if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), + sshbuf_len(cert), 0)) != 0) + goto out; + + /* Append signature and we are done */ + if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) + goto out; + ret = 0; + out: + if (ret != 0) + sshbuf_reset(cert); + if (sig_blob != NULL) + free(sig_blob); + if (ca_blob != NULL) + free(ca_blob); + if (principals != NULL) + sshbuf_free(principals); + return ret; +} + +int +sshkey_cert_check_authority(const struct sshkey *k, + int want_host, int require_principal, + const char *name, const char **reason) +{ + u_int i, principal_matches; + time_t now = time(NULL); + + if (reason != NULL) + *reason = NULL; + + if (want_host) { + if (k->cert->type != SSH2_CERT_TYPE_HOST) { + *reason = "Certificate invalid: not a host certificate"; + return SSH_ERR_KEY_CERT_INVALID; + } + } else { + if (k->cert->type != SSH2_CERT_TYPE_USER) { + *reason = "Certificate invalid: not a user certificate"; + return SSH_ERR_KEY_CERT_INVALID; + } + } + if (now < 0) { + /* yikes - system clock before epoch! */ + *reason = "Certificate invalid: not yet valid"; + return SSH_ERR_KEY_CERT_INVALID; + } + if ((u_int64_t)now < k->cert->valid_after) { + *reason = "Certificate invalid: not yet valid"; + return SSH_ERR_KEY_CERT_INVALID; + } + if ((u_int64_t)now >= k->cert->valid_before) { + *reason = "Certificate invalid: expired"; + return SSH_ERR_KEY_CERT_INVALID; + } + if (k->cert->nprincipals == 0) { + if (require_principal) { + *reason = "Certificate lacks principal list"; + return SSH_ERR_KEY_CERT_INVALID; + } + } else if (name != NULL) { + principal_matches = 0; + for (i = 0; i < k->cert->nprincipals; i++) { + if (strcmp(name, k->cert->principals[i]) == 0) { + principal_matches = 1; + break; + } + } + if (!principal_matches) { + *reason = "Certificate invalid: name is not a listed " + "principal"; + return SSH_ERR_KEY_CERT_INVALID; + } + } + return 0; +} + +int +sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) +{ + int r = SSH_ERR_INTERNAL_ERROR; + + if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) + goto out; + switch (key->type) { +#ifdef WITH_OPENSSL + case KEY_RSA: + if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) + goto out; + break; + case KEY_RSA_CERT: + if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || + (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) + goto out; + break; + case KEY_DSA: + if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || + (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || + (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || + (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 || + (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) + goto out; + break; + case KEY_DSA_CERT: + if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || + (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) + goto out; + break; +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + if ((r = sshbuf_put_cstring(b, + sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || + (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 || + (r = sshbuf_put_bignum2(b, + EC_KEY_get0_private_key(key->ecdsa))) != 0) + goto out; + break; + case KEY_ECDSA_CERT: + if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || + (r = sshbuf_put_bignum2(b, + EC_KEY_get0_private_key(key->ecdsa))) != 0) + goto out; + break; +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + if ((r = sshbuf_put_string(b, key->ed25519_pk, + ED25519_PK_SZ)) != 0 || + (r = sshbuf_put_string(b, key->ed25519_sk, + ED25519_SK_SZ)) != 0) + goto out; + break; + case KEY_ED25519_CERT: + if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || + (r = sshbuf_put_string(b, key->ed25519_pk, + ED25519_PK_SZ)) != 0 || + (r = sshbuf_put_string(b, key->ed25519_sk, + ED25519_SK_SZ)) != 0) + goto out; + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + /* success */ + r = 0; + out: + return r; +} + +int +sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) +{ + char *tname = NULL, *curve = NULL; + struct sshkey *k = NULL; + size_t pklen = 0, sklen = 0; + int type, r = SSH_ERR_INTERNAL_ERROR; + u_char *ed25519_pk = NULL, *ed25519_sk = NULL; +#ifdef WITH_OPENSSL + BIGNUM *exponent = NULL; +#endif /* WITH_OPENSSL */ + + if (kp != NULL) + *kp = NULL; + if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0) + goto out; + type = sshkey_type_from_name(tname); + switch (type) { +#ifdef WITH_OPENSSL + case KEY_DSA: + if ((k = sshkey_new_private(type)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 || + (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 || + (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 || + (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 || + (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) + goto out; + break; + case KEY_DSA_CERT: + if ((r = sshkey_froms(buf, &k)) != 0 || + (r = sshkey_add_private(k)) != 0 || + (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) + goto out; + break; +# ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + if ((k = sshkey_new_private(type)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0) + goto out; + if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) { + r = SSH_ERR_EC_CURVE_MISMATCH; + goto out; + } + k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); + if (k->ecdsa == NULL || (exponent = BN_new()) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || + (r = sshbuf_get_bignum2(buf, exponent))) + goto out; + if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa), + EC_KEY_get0_public_key(k->ecdsa)) != 0) || + (r = sshkey_ec_validate_private(k->ecdsa)) != 0) + goto out; + break; + case KEY_ECDSA_CERT: + if ((exponent = BN_new()) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if ((r = sshkey_froms(buf, &k)) != 0 || + (r = sshkey_add_private(k)) != 0 || + (r = sshbuf_get_bignum2(buf, exponent)) != 0) + goto out; + if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa), + EC_KEY_get0_public_key(k->ecdsa)) != 0) || + (r = sshkey_ec_validate_private(k->ecdsa)) != 0) + goto out; + break; +# endif /* OPENSSL_HAS_ECC */ + case KEY_RSA: + if ((k = sshkey_new_private(type)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 || + (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 || + (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || + (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || + (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || + (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || + (r = rsa_generate_additional_parameters(k->rsa)) != 0) + goto out; + break; + case KEY_RSA_CERT: + if ((r = sshkey_froms(buf, &k)) != 0 || + (r = sshkey_add_private(k)) != 0 || + (r = sshbuf_get_bignum2(buf, k->rsa->d) != 0) || + (r = sshbuf_get_bignum2(buf, k->rsa->iqmp) != 0) || + (r = sshbuf_get_bignum2(buf, k->rsa->p) != 0) || + (r = sshbuf_get_bignum2(buf, k->rsa->q) != 0) || + (r = rsa_generate_additional_parameters(k->rsa)) != 0) + goto out; + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + if ((k = sshkey_new_private(type)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || + (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) + goto out; + if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + k->ed25519_pk = ed25519_pk; + k->ed25519_sk = ed25519_sk; + ed25519_pk = ed25519_sk = NULL; + break; + case KEY_ED25519_CERT: + if ((r = sshkey_froms(buf, &k)) != 0 || + (r = sshkey_add_private(k)) != 0 || + (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || + (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) + goto out; + if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + k->ed25519_pk = ed25519_pk; + k->ed25519_sk = ed25519_sk; + ed25519_pk = ed25519_sk = NULL; + break; + default: + r = SSH_ERR_KEY_TYPE_UNKNOWN; + goto out; + } +#ifdef WITH_OPENSSL + /* enable blinding */ + switch (k->type) { + case KEY_RSA: + case KEY_RSA_CERT: + case KEY_RSA1: + if (RSA_blinding_on(k->rsa, NULL) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + break; + } +#endif /* WITH_OPENSSL */ + /* success */ + r = 0; + if (kp != NULL) { + *kp = k; + k = NULL; + } + out: + free(tname); + free(curve); +#ifdef WITH_OPENSSL + if (exponent != NULL) + BN_clear_free(exponent); +#endif /* WITH_OPENSSL */ + sshkey_free(k); + if (ed25519_pk != NULL) { + explicit_bzero(ed25519_pk, pklen); + free(ed25519_pk); + } + if (ed25519_sk != NULL) { + explicit_bzero(ed25519_sk, sklen); + free(ed25519_sk); + } + return r; +} + +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) +int +sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) +{ + BN_CTX *bnctx; + EC_POINT *nq = NULL; + BIGNUM *order, *x, *y, *tmp; + int ret = SSH_ERR_KEY_INVALID_EC_VALUE; + + if ((bnctx = BN_CTX_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + BN_CTX_start(bnctx); + + /* + * We shouldn't ever hit this case because bignum_get_ecpoint() + * refuses to load GF2m points. + */ + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != + NID_X9_62_prime_field) + goto out; + + /* Q != infinity */ + if (EC_POINT_is_at_infinity(group, public)) + goto out; + + if ((x = BN_CTX_get(bnctx)) == NULL || + (y = BN_CTX_get(bnctx)) == NULL || + (order = BN_CTX_get(bnctx)) == NULL || + (tmp = BN_CTX_get(bnctx)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + + /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ + if (EC_GROUP_get_order(group, order, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, public, + x, y, bnctx) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (BN_num_bits(x) <= BN_num_bits(order) / 2 || + BN_num_bits(y) <= BN_num_bits(order) / 2) + goto out; + + /* nQ == infinity (n == order of subgroup) */ + if ((nq = EC_POINT_new(group)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (EC_POINT_is_at_infinity(group, nq) != 1) + goto out; + + /* x < order - 1, y < order - 1 */ + if (!BN_sub(tmp, order, BN_value_one())) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0) + goto out; + ret = 0; + out: + BN_CTX_free(bnctx); + if (nq != NULL) + EC_POINT_free(nq); + return ret; +} + +int +sshkey_ec_validate_private(const EC_KEY *key) +{ + BN_CTX *bnctx; + BIGNUM *order, *tmp; + int ret = SSH_ERR_KEY_INVALID_EC_VALUE; + + if ((bnctx = BN_CTX_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + BN_CTX_start(bnctx); + + if ((order = BN_CTX_get(bnctx)) == NULL || + (tmp = BN_CTX_get(bnctx)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + + /* log2(private) > log2(order)/2 */ + if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (BN_num_bits(EC_KEY_get0_private_key(key)) <= + BN_num_bits(order) / 2) + goto out; + + /* private < order - 1 */ + if (!BN_sub(tmp, order, BN_value_one())) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) + goto out; + ret = 0; + out: + BN_CTX_free(bnctx); + return ret; +} + +void +sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) +{ + BIGNUM *x, *y; + BN_CTX *bnctx; + + if (point == NULL) { + fputs("point=(NULL)\n", stderr); + return; + } + if ((bnctx = BN_CTX_new()) == NULL) { + fprintf(stderr, "%s: BN_CTX_new failed\n", __func__); + return; + } + BN_CTX_start(bnctx); + if ((x = BN_CTX_get(bnctx)) == NULL || + (y = BN_CTX_get(bnctx)) == NULL) { + fprintf(stderr, "%s: BN_CTX_get failed\n", __func__); + return; + } + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != + NID_X9_62_prime_field) { + fprintf(stderr, "%s: group is not a prime field\n", __func__); + return; + } + if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, + bnctx) != 1) { + fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n", + __func__); + return; + } + fputs("x=", stderr); + BN_print_fp(stderr, x); + fputs("\ny=", stderr); + BN_print_fp(stderr, y); + fputs("\n", stderr); + BN_CTX_free(bnctx); +} + +void +sshkey_dump_ec_key(const EC_KEY *key) +{ + const BIGNUM *exponent; + + sshkey_dump_ec_point(EC_KEY_get0_group(key), + EC_KEY_get0_public_key(key)); + fputs("exponent=", stderr); + if ((exponent = EC_KEY_get0_private_key(key)) == NULL) + fputs("(NULL)", stderr); + else + BN_print_fp(stderr, EC_KEY_get0_private_key(key)); + fputs("\n", stderr); +} +#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ + +static int +sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob, + const char *passphrase, const char *comment, const char *ciphername, + int rounds) +{ + u_char *cp, *key = NULL, *pubkeyblob = NULL; + u_char salt[SALT_LEN]; + char *b64 = NULL; + size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; + u_int check; + int r = SSH_ERR_INTERNAL_ERROR; + struct sshcipher_ctx ciphercontext; + const struct sshcipher *cipher; + const char *kdfname = KDFNAME; + struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL; + + memset(&ciphercontext, 0, sizeof(ciphercontext)); + + if (rounds <= 0) + rounds = DEFAULT_ROUNDS; + if (passphrase == NULL || !strlen(passphrase)) { + ciphername = "none"; + kdfname = "none"; + } else if (ciphername == NULL) + ciphername = DEFAULT_CIPHERNAME; + else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((cipher = cipher_by_name(ciphername)) == NULL) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + + if ((kdf = sshbuf_new()) == NULL || + (encoded = sshbuf_new()) == NULL || + (encrypted = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + blocksize = cipher_blocksize(cipher); + keylen = cipher_keylen(cipher); + ivlen = cipher_ivlen(cipher); + authlen = cipher_authlen(cipher); + if ((key = calloc(1, keylen + ivlen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (strcmp(kdfname, "bcrypt") == 0) { + arc4random_buf(salt, SALT_LEN); + if (bcrypt_pbkdf(passphrase, strlen(passphrase), + salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 || + (r = sshbuf_put_u32(kdf, rounds)) != 0) + goto out; + } else if (strcmp(kdfname, "none") != 0) { + /* Unsupported KDF type */ + r = SSH_ERR_KEY_UNKNOWN_CIPHER; + goto out; + } + if ((r = cipher_init(&ciphercontext, cipher, key, keylen, + key + keylen, ivlen, 1)) != 0) + goto out; + + if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 || + (r = sshbuf_put_cstring(encoded, ciphername)) != 0 || + (r = sshbuf_put_cstring(encoded, kdfname)) != 0 || + (r = sshbuf_put_stringb(encoded, kdf)) != 0 || + (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */ + (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 || + (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0) + goto out; + + /* set up the buffer that will be encrypted */ + + /* Random check bytes */ + check = arc4random(); + if ((r = sshbuf_put_u32(encrypted, check)) != 0 || + (r = sshbuf_put_u32(encrypted, check)) != 0) + goto out; + + /* append private key and comment*/ + if ((r = sshkey_private_serialize(prv, encrypted)) != 0 || + (r = sshbuf_put_cstring(encrypted, comment)) != 0) + goto out; + + /* padding */ + i = 0; + while (sshbuf_len(encrypted) % blocksize) { + if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0) + goto out; + } + + /* length in destination buffer */ + if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0) + goto out; + + /* encrypt */ + if ((r = sshbuf_reserve(encoded, + sshbuf_len(encrypted) + authlen, &cp)) != 0) + goto out; + if ((r = cipher_crypt(&ciphercontext, 0, cp, + sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0) + goto out; + + /* uuencode */ + if ((b64 = sshbuf_dtob64(encoded)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + sshbuf_reset(blob); + if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0) + goto out; + for (i = 0; i < strlen(b64); i++) { + if ((r = sshbuf_put_u8(blob, b64[i])) != 0) + goto out; + /* insert line breaks */ + if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0) + goto out; + } + if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0) + goto out; + if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0) + goto out; + + /* success */ + r = 0; + + out: + sshbuf_free(kdf); + sshbuf_free(encoded); + sshbuf_free(encrypted); + cipher_cleanup(&ciphercontext); + explicit_bzero(salt, sizeof(salt)); + if (key != NULL) { + explicit_bzero(key, keylen + ivlen); + free(key); + } + if (pubkeyblob != NULL) { + explicit_bzero(pubkeyblob, pubkeylen); + free(pubkeyblob); + } + if (b64 != NULL) { + explicit_bzero(b64, strlen(b64)); + free(b64); + } + return r; +} + +static int +sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, + struct sshkey **keyp, char **commentp) +{ + char *comment = NULL, *ciphername = NULL, *kdfname = NULL; + const struct sshcipher *cipher = NULL; + const u_char *cp; + int r = SSH_ERR_INTERNAL_ERROR; + size_t encoded_len; + size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0; + struct sshbuf *encoded = NULL, *decoded = NULL; + struct sshbuf *kdf = NULL, *decrypted = NULL; + struct sshcipher_ctx ciphercontext; + struct sshkey *k = NULL; + u_char *key = NULL, *salt = NULL, *dp, pad, last; + u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; + + memset(&ciphercontext, 0, sizeof(ciphercontext)); + if (keyp != NULL) + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; + + if ((encoded = sshbuf_new()) == NULL || + (decoded = sshbuf_new()) == NULL || + (decrypted = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + /* check preamble */ + cp = sshbuf_ptr(blob); + encoded_len = sshbuf_len(blob); + if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) || + memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + cp += MARK_BEGIN_LEN; + encoded_len -= MARK_BEGIN_LEN; + + /* Look for end marker, removing whitespace as we go */ + while (encoded_len > 0) { + if (*cp != '\n' && *cp != '\r') { + if ((r = sshbuf_put_u8(encoded, *cp)) != 0) + goto out; + } + last = *cp; + encoded_len--; + cp++; + if (last == '\n') { + if (encoded_len >= MARK_END_LEN && + memcmp(cp, MARK_END, MARK_END_LEN) == 0) { + /* \0 terminate */ + if ((r = sshbuf_put_u8(encoded, 0)) != 0) + goto out; + break; + } + } + } + if (encoded_len == 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* decode base64 */ + if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0) + goto out; + + /* check magic */ + if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) || + memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* parse public portion of key */ + if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 || + (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 || + (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 || + (r = sshbuf_froms(decoded, &kdf)) != 0 || + (r = sshbuf_get_u32(decoded, &nkeys)) != 0 || + (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */ + (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) + goto out; + + if ((cipher = cipher_by_name(ciphername)) == NULL) { + r = SSH_ERR_KEY_UNKNOWN_CIPHER; + goto out; + } + if ((passphrase == NULL || strlen(passphrase) == 0) && + strcmp(ciphername, "none") != 0) { + /* passphrase required */ + r = SSH_ERR_KEY_WRONG_PASSPHRASE; + goto out; + } + if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) { + r = SSH_ERR_KEY_UNKNOWN_CIPHER; + goto out; + } + if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (nkeys != 1) { + /* XXX only one key supported */ + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* check size of encrypted key blob */ + blocksize = cipher_blocksize(cipher); + if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* setup key */ + keylen = cipher_keylen(cipher); + ivlen = cipher_ivlen(cipher); + authlen = cipher_authlen(cipher); + if ((key = calloc(1, keylen + ivlen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (strcmp(kdfname, "bcrypt") == 0) { + if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 || + (r = sshbuf_get_u32(kdf, &rounds)) != 0) + goto out; + if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, + key, keylen + ivlen, rounds) < 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + } + + /* check that an appropriate amount of auth data is present */ + if (sshbuf_len(decoded) < encrypted_len + authlen) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* decrypt private portion of key */ + if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 || + (r = cipher_init(&ciphercontext, cipher, key, keylen, + key + keylen, ivlen, 0)) != 0) + goto out; + if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded), + encrypted_len, 0, authlen)) != 0) { + /* an integrity error here indicates an incorrect passphrase */ + if (r == SSH_ERR_MAC_INVALID) + r = SSH_ERR_KEY_WRONG_PASSPHRASE; + goto out; + } + if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0) + goto out; + /* there should be no trailing data */ + if (sshbuf_len(decoded) != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* check check bytes */ + if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 || + (r = sshbuf_get_u32(decrypted, &check2)) != 0) + goto out; + if (check1 != check2) { + r = SSH_ERR_KEY_WRONG_PASSPHRASE; + goto out; + } + + /* Load the private key and comment */ + if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 || + (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0) + goto out; + + /* Check deterministic padding */ + i = 0; + while (sshbuf_len(decrypted)) { + if ((r = sshbuf_get_u8(decrypted, &pad)) != 0) + goto out; + if (pad != (++i & 0xff)) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + } + + /* XXX decode pubkey and check against private */ + + /* success */ + r = 0; + if (keyp != NULL) { + *keyp = k; + k = NULL; + } + if (commentp != NULL) { + *commentp = comment; + comment = NULL; + } + out: + pad = 0; + cipher_cleanup(&ciphercontext); + free(ciphername); + free(kdfname); + free(comment); + if (salt != NULL) { + explicit_bzero(salt, slen); + free(salt); + } + if (key != NULL) { + explicit_bzero(key, keylen + ivlen); + free(key); + } + sshbuf_free(encoded); + sshbuf_free(decoded); + sshbuf_free(kdf); + sshbuf_free(decrypted); + sshkey_free(k); + return r; +} + +#if WITH_SSH1 +/* + * Serialises the authentication (private) key to a blob, encrypting it with + * passphrase. The identification of the blob (lowest 64 bits of n) will + * precede the key to provide identification of the key without needing a + * passphrase. + */ +static int +sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob, + const char *passphrase, const char *comment) +{ + struct sshbuf *buffer = NULL, *encrypted = NULL; + u_char buf[8]; + int r, cipher_num; + struct sshcipher_ctx ciphercontext; + const struct sshcipher *cipher; + u_char *cp; + + /* + * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting + * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. + */ + cipher_num = (strcmp(passphrase, "") == 0) ? + SSH_CIPHER_NONE : SSH_CIPHER_3DES; + if ((cipher = cipher_by_number(cipher_num)) == NULL) + return SSH_ERR_INTERNAL_ERROR; + + /* This buffer is used to build the secret part of the private key. */ + if ((buffer = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + + /* Put checkbytes for checking passphrase validity. */ + if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0) + goto out; + arc4random_buf(cp, 2); + memcpy(cp + 2, cp, 2); + + /* + * Store the private key (n and e will not be stored because they + * will be stored in plain text, and storing them also in encrypted + * format would just give known plaintext). + * Note: q and p are stored in reverse order to SSL. + */ + if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 || + (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 || + (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 || + (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0) + goto out; + + /* Pad the part to be encrypted to a size that is a multiple of 8. */ + explicit_bzero(buf, 8); + if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0) + goto out; + + /* This buffer will be used to contain the data in the file. */ + if ((encrypted = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + /* First store keyfile id string. */ + if ((r = sshbuf_put(encrypted, LEGACY_BEGIN, + sizeof(LEGACY_BEGIN))) != 0) + goto out; + + /* Store cipher type and "reserved" field. */ + if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 || + (r = sshbuf_put_u32(encrypted, 0)) != 0) + goto out; + + /* Store public key. This will be in plain text. */ + if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 || + (r = sshbuf_put_bignum1(encrypted, key->rsa->n) != 0) || + (r = sshbuf_put_bignum1(encrypted, key->rsa->e) != 0) || + (r = sshbuf_put_cstring(encrypted, comment) != 0)) + goto out; + + /* Allocate space for the private part of the key in the buffer. */ + if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0) + goto out; + + if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, + CIPHER_ENCRYPT)) != 0) + goto out; + if ((r = cipher_crypt(&ciphercontext, 0, cp, + sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0) + goto out; + if ((r = cipher_cleanup(&ciphercontext)) != 0) + goto out; + + r = sshbuf_putb(blob, encrypted); + + out: + explicit_bzero(&ciphercontext, sizeof(ciphercontext)); + explicit_bzero(buf, sizeof(buf)); + if (buffer != NULL) + sshbuf_free(buffer); + if (encrypted != NULL) + sshbuf_free(encrypted); + + return r; +} +#endif /* WITH_SSH1 */ + +#ifdef WITH_OPENSSL +/* convert SSH v2 key in OpenSSL PEM format */ +static int +sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, + const char *_passphrase, const char *comment) +{ + int success, r; + int blen, len = strlen(_passphrase); + u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; +#if (OPENSSL_VERSION_NUMBER < 0x00907000L) + const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; +#else + const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; +#endif + const u_char *bptr; + BIO *bio = NULL; + + if (len > 0 && len <= 4) + return SSH_ERR_PASSPHRASE_TOO_SHORT; + if ((bio = BIO_new(BIO_s_mem())) == NULL) + return SSH_ERR_ALLOC_FAIL; + + switch (key->type) { + case KEY_DSA: + success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, + cipher, passphrase, len, NULL, NULL); + break; +#ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, + cipher, passphrase, len, NULL, NULL); + break; +#endif + case KEY_RSA: + success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, + cipher, passphrase, len, NULL, NULL); + break; + default: + success = 0; + break; + } + if (success == 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + if ((r = sshbuf_put(blob, bptr, blen)) != 0) + goto out; + r = 0; + out: + BIO_free(bio); + return r; +} +#endif /* WITH_OPENSSL */ + +/* Serialise "key" to buffer "blob" */ +int +sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, + const char *passphrase, const char *comment, + int force_new_format, const char *new_format_cipher, int new_format_rounds) +{ + switch (key->type) { +#ifdef WITH_SSH1 + case KEY_RSA1: + return sshkey_private_rsa1_to_blob(key, blob, + passphrase, comment); +#endif /* WITH_SSH1 */ +#ifdef WITH_OPENSSL + case KEY_DSA: + case KEY_ECDSA: + case KEY_RSA: + if (force_new_format) { + return sshkey_private_to_blob2(key, blob, passphrase, + comment, new_format_cipher, new_format_rounds); + } + return sshkey_private_pem_to_blob(key, blob, + passphrase, comment); +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + return sshkey_private_to_blob2(key, blob, passphrase, + comment, new_format_cipher, new_format_rounds); + default: + return SSH_ERR_KEY_TYPE_UNKNOWN; + } +} + +#ifdef WITH_SSH1 +/* + * Parse the public, unencrypted portion of a RSA1 key. + */ +int +sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, + struct sshkey **keyp, char **commentp) +{ + int r; + struct sshkey *pub = NULL; + struct sshbuf *copy = NULL; + + if (keyp != NULL) + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; + + /* Check that it is at least big enough to contain the ID string. */ + if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN)) + return SSH_ERR_INVALID_FORMAT; + + /* + * Make sure it begins with the id string. Consume the id string + * from the buffer. + */ + if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0) + return SSH_ERR_INVALID_FORMAT; + /* Make a working copy of the keyblob and skip past the magic */ + if ((copy = sshbuf_fromb(blob)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0) + goto out; + + /* Skip cipher type, reserved data and key bits. */ + if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */ + (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */ + (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */ + goto out; + + /* Read the public key from the buffer. */ + if ((pub = sshkey_new(KEY_RSA1)) == NULL || + (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 || + (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0) + goto out; + + /* Finally, the comment */ + if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0) + goto out; + + /* The encrypted private part is not parsed by this function. */ + + r = 0; + if (keyp != NULL) + *keyp = pub; + else + sshkey_free(pub); + pub = NULL; + + out: + if (copy != NULL) + sshbuf_free(copy); + if (pub != NULL) + sshkey_free(pub); + return r; +} + +static int +sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, + struct sshkey **keyp, char **commentp) +{ + int r; + u_int16_t check1, check2; + u_int8_t cipher_type; + struct sshbuf *decrypted = NULL, *copy = NULL; + u_char *cp; + char *comment = NULL; + struct sshcipher_ctx ciphercontext; + const struct sshcipher *cipher; + struct sshkey *prv = NULL; + + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; + + /* Check that it is at least big enough to contain the ID string. */ + if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN)) + return SSH_ERR_INVALID_FORMAT; + + /* + * Make sure it begins with the id string. Consume the id string + * from the buffer. + */ + if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0) + return SSH_ERR_INVALID_FORMAT; + + if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((copy = sshbuf_fromb(blob)) == NULL || + (decrypted = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0) + goto out; + + /* Read cipher type. */ + if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 || + (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */ + goto out; + + /* Read the public key and comment from the buffer. */ + if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */ + (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 || + (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 || + (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0) + goto out; + + /* Check that it is a supported cipher. */ + cipher = cipher_by_number(cipher_type); + if (cipher == NULL) { + r = SSH_ERR_KEY_UNKNOWN_CIPHER; + goto out; + } + /* Initialize space for decrypted data. */ + if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0) + goto out; + + /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ + if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, + CIPHER_DECRYPT)) != 0) + goto out; + if ((r = cipher_crypt(&ciphercontext, 0, cp, + sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) { + cipher_cleanup(&ciphercontext); + goto out; + } + if ((r = cipher_cleanup(&ciphercontext)) != 0) + goto out; + + if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 || + (r = sshbuf_get_u16(decrypted, &check2)) != 0) + goto out; + if (check1 != check2) { + r = SSH_ERR_KEY_WRONG_PASSPHRASE; + goto out; + } + + /* Read the rest of the private key. */ + if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 || + (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 || + (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 || + (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0) + goto out; + + /* calculate p-1 and q-1 */ + if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0) + goto out; + + /* enable blinding */ + if (RSA_blinding_on(prv->rsa, NULL) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + r = 0; + *keyp = prv; + prv = NULL; + if (commentp != NULL) { + *commentp = comment; + comment = NULL; + } + out: + explicit_bzero(&ciphercontext, sizeof(ciphercontext)); + if (comment != NULL) + free(comment); + if (prv != NULL) + sshkey_free(prv); + if (copy != NULL) + sshbuf_free(copy); + if (decrypted != NULL) + sshbuf_free(decrypted); + return r; +} +#endif /* WITH_SSH1 */ + +#ifdef WITH_OPENSSL +static int +sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, + const char *passphrase, struct sshkey **keyp) +{ + EVP_PKEY *pk = NULL; + struct sshkey *prv = NULL; + BIO *bio = NULL; + int r; + + *keyp = NULL; + + if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX) + return SSH_ERR_ALLOC_FAIL; + if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) != + (int)sshbuf_len(blob)) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, + (char *)passphrase)) == NULL) { + r = SSH_ERR_KEY_WRONG_PASSPHRASE; + goto out; + } + if (pk->type == EVP_PKEY_RSA && + (type == KEY_UNSPEC || type == KEY_RSA)) { + if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + prv->rsa = EVP_PKEY_get1_RSA(pk); + prv->type = KEY_RSA; +#ifdef DEBUG_PK + RSA_print_fp(stderr, prv->rsa, 8); +#endif + if (RSA_blinding_on(prv->rsa, NULL) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + } else if (pk->type == EVP_PKEY_DSA && + (type == KEY_UNSPEC || type == KEY_DSA)) { + if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + prv->dsa = EVP_PKEY_get1_DSA(pk); + prv->type = KEY_DSA; +#ifdef DEBUG_PK + DSA_print_fp(stderr, prv->dsa, 8); +#endif +#ifdef OPENSSL_HAS_ECC + } else if (pk->type == EVP_PKEY_EC && + (type == KEY_UNSPEC || type == KEY_ECDSA)) { + if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); + prv->type = KEY_ECDSA; + prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa); + if (prv->ecdsa_nid == -1 || + sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL || + sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), + EC_KEY_get0_public_key(prv->ecdsa)) != 0 || + sshkey_ec_validate_private(prv->ecdsa) != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } +# ifdef DEBUG_PK + if (prv != NULL && prv->ecdsa != NULL) + sshkey_dump_ec_key(prv->ecdsa); +# endif +#endif /* OPENSSL_HAS_ECC */ + } else { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + r = 0; + *keyp = prv; + prv = NULL; + out: + BIO_free(bio); + if (pk != NULL) + EVP_PKEY_free(pk); + if (prv != NULL) + sshkey_free(prv); + return r; +} +#endif /* WITH_OPENSSL */ + +int +sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, + const char *passphrase, struct sshkey **keyp, char **commentp) +{ + int r; + + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; + + switch (type) { +#ifdef WITH_SSH1 + case KEY_RSA1: + return sshkey_parse_private_rsa1(blob, passphrase, + keyp, commentp); +#endif /* WITH_SSH1 */ +#ifdef WITH_OPENSSL + case KEY_DSA: + case KEY_ECDSA: + case KEY_RSA: + return sshkey_parse_private_pem_fileblob(blob, type, + passphrase, keyp); +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + return sshkey_parse_private2(blob, type, passphrase, + keyp, commentp); + case KEY_UNSPEC: + if ((r = sshkey_parse_private2(blob, type, passphrase, keyp, + commentp)) == 0) + return 0; +#ifdef WITH_OPENSSL + return sshkey_parse_private_pem_fileblob(blob, type, + passphrase, keyp); +#else + return SSH_ERR_INVALID_FORMAT; +#endif /* WITH_OPENSSL */ + default: + return SSH_ERR_KEY_TYPE_UNKNOWN; + } +} + +int +sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, + const char *filename, struct sshkey **keyp, char **commentp) +{ + int r; + + if (keyp != NULL) + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; + +#ifdef WITH_SSH1 + /* it's a SSH v1 key if the public key part is readable */ + if ((r = sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL)) == 0) { + return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1, + passphrase, keyp, commentp); + } +#endif /* WITH_SSH1 */ + if ((r = sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, + passphrase, keyp, commentp)) == 0) + return 0; + return r; +} diff --git a/crypto/openssh/sshkey.h b/crypto/openssh/sshkey.h new file mode 100644 index 0000000..c8d3cdd --- /dev/null +++ b/crypto/openssh/sshkey.h @@ -0,0 +1,229 @@ +/* $OpenBSD: sshkey.h,v 1.9 2015/08/04 05:23:06 djm Exp $ */ + +/* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SSHKEY_H +#define SSHKEY_H + +#include + +#ifdef WITH_OPENSSL +#include +#include +# ifdef OPENSSL_HAS_ECC +# include +# else /* OPENSSL_HAS_ECC */ +# define EC_KEY void +# define EC_GROUP void +# define EC_POINT void +# endif /* OPENSSL_HAS_ECC */ +#else /* WITH_OPENSSL */ +# define RSA void +# define DSA void +# define EC_KEY void +# define EC_GROUP void +# define EC_POINT void +#endif /* WITH_OPENSSL */ + +#define SSH_RSA_MINIMUM_MODULUS_SIZE 768 +#define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) + +struct sshbuf; + +/* Key types */ +enum sshkey_types { + KEY_RSA1, + KEY_RSA, + KEY_DSA, + KEY_ECDSA, + KEY_ED25519, + KEY_RSA_CERT, + KEY_DSA_CERT, + KEY_ECDSA_CERT, + KEY_ED25519_CERT, + KEY_UNSPEC +}; + +/* Default fingerprint hash */ +#define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256 + +/* Fingerprint representation formats */ +enum sshkey_fp_rep { + SSH_FP_DEFAULT = 0, + SSH_FP_HEX, + SSH_FP_BASE64, + SSH_FP_BUBBLEBABBLE, + SSH_FP_RANDOMART +}; + +/* key is stored in external hardware */ +#define SSHKEY_FLAG_EXT 0x0001 + +#define SSHKEY_CERT_MAX_PRINCIPALS 256 +/* XXX opaquify? */ +struct sshkey_cert { + struct sshbuf *certblob; /* Kept around for use on wire */ + u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */ + u_int64_t serial; + char *key_id; + u_int nprincipals; + char **principals; + u_int64_t valid_after, valid_before; + struct sshbuf *critical; + struct sshbuf *extensions; + struct sshkey *signature_key; +}; + +/* XXX opaquify? */ +struct sshkey { + int type; + int flags; + RSA *rsa; + DSA *dsa; + int ecdsa_nid; /* NID of curve */ + EC_KEY *ecdsa; + u_char *ed25519_sk; + u_char *ed25519_pk; + struct sshkey_cert *cert; +}; + +#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES +#define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES + +struct sshkey *sshkey_new(int); +int sshkey_add_private(struct sshkey *); +struct sshkey *sshkey_new_private(int); +void sshkey_free(struct sshkey *); +int sshkey_demote(const struct sshkey *, struct sshkey **); +int sshkey_equal_public(const struct sshkey *, + const struct sshkey *); +int sshkey_equal(const struct sshkey *, const struct sshkey *); +char *sshkey_fingerprint(const struct sshkey *, + int, enum sshkey_fp_rep); +int sshkey_fingerprint_raw(const struct sshkey *k, + int, u_char **retp, size_t *lenp); +const char *sshkey_type(const struct sshkey *); +const char *sshkey_cert_type(const struct sshkey *); +int sshkey_write(const struct sshkey *, FILE *); +int sshkey_read(struct sshkey *, char **); +u_int sshkey_size(const struct sshkey *); + +int sshkey_generate(int type, u_int bits, struct sshkey **keyp); +int sshkey_from_private(const struct sshkey *, struct sshkey **); +int sshkey_type_from_name(const char *); +int sshkey_is_cert(const struct sshkey *); +int sshkey_type_is_cert(int); +int sshkey_type_plain(int); +int sshkey_to_certified(struct sshkey *); +int sshkey_drop_cert(struct sshkey *); +int sshkey_certify(struct sshkey *, struct sshkey *); +int sshkey_cert_copy(const struct sshkey *, struct sshkey *); +int sshkey_cert_check_authority(const struct sshkey *, int, int, + const char *, const char **); + +int sshkey_ecdsa_nid_from_name(const char *); +int sshkey_curve_name_to_nid(const char *); +const char * sshkey_curve_nid_to_name(int); +u_int sshkey_curve_nid_to_bits(int); +int sshkey_ecdsa_bits_to_nid(int); +int sshkey_ecdsa_key_to_nid(EC_KEY *); +int sshkey_ec_nid_to_hash_alg(int nid); +int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *); +int sshkey_ec_validate_private(const EC_KEY *); +const char *sshkey_ssh_name(const struct sshkey *); +const char *sshkey_ssh_name_plain(const struct sshkey *); +int sshkey_names_valid2(const char *, int); +char *key_alg_list(int, int); + +int sshkey_from_blob(const u_char *, size_t, struct sshkey **); +int sshkey_fromb(struct sshbuf *, struct sshkey **); +int sshkey_froms(struct sshbuf *, struct sshkey **); +int sshkey_to_blob(const struct sshkey *, u_char **, size_t *); +int sshkey_to_base64(const struct sshkey *, char **); +int sshkey_putb(const struct sshkey *, struct sshbuf *); +int sshkey_puts(const struct sshkey *, struct sshbuf *); +int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); +int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); + +int sshkey_sign(const struct sshkey *, u_char **, size_t *, + const u_char *, size_t, u_int); +int sshkey_verify(const struct sshkey *, const u_char *, size_t, + const u_char *, size_t, u_int); + +/* for debug */ +void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *); +void sshkey_dump_ec_key(const EC_KEY *); + +/* private key parsing and serialisation */ +int sshkey_private_serialize(const struct sshkey *key, struct sshbuf *buf); +int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp); + +/* private key file format parsing and serialisation */ +int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, + const char *passphrase, const char *comment, + int force_new_format, const char *new_format_cipher, int new_format_rounds); +int sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, + struct sshkey **keyp, char **commentp); +int sshkey_parse_private_fileblob(struct sshbuf *buffer, + const char *passphrase, const char *filename, struct sshkey **keyp, + char **commentp); +int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, + const char *passphrase, struct sshkey **keyp, char **commentp); + +#ifdef SSHKEY_INTERNAL +int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat); +int ssh_rsa_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat); +int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat); +int ssh_dss_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat); +int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat); +int ssh_ecdsa_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat); +int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat); +int ssh_ed25519_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat); +#endif + +#if !defined(WITH_OPENSSL) +# undef RSA +# undef DSA +# undef EC_KEY +# undef EC_GROUP +# undef EC_POINT +#elif !defined(OPENSSL_HAS_ECC) +# undef EC_KEY +# undef EC_GROUP +# undef EC_POINT +#endif + +#endif /* SSHKEY_H */ diff --git a/crypto/openssh/sshlogin.c b/crypto/openssh/sshlogin.c index e79ca9b..818312f 100644 --- a/crypto/openssh/sshlogin.c +++ b/crypto/openssh/sshlogin.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshlogin.c,v 1.28 2014/01/31 16:39:19 tedu Exp $ */ +/* $OpenBSD: sshlogin.c,v 1.31 2015/01/20 23:14:00 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -42,7 +42,6 @@ #include "includes.h" #include -#include #include #include @@ -54,10 +53,12 @@ #include #include #include +#include #include "loginrec.h" #include "log.h" #include "buffer.h" +#include "misc.h" #include "servconf.h" extern Buffer loginmsg; @@ -87,7 +88,7 @@ static void store_lastlog_message(const char *user, uid_t uid) { #ifndef NO_SSH_LASTLOG - char *time_string, hostname[MAXHOSTNAMELEN] = "", buf[512]; + char *time_string, hostname[HOST_NAME_MAX+1] = "", buf[512]; time_t last_login_time; if (!options.print_lastlog) diff --git a/crypto/openssh/sshpty.c b/crypto/openssh/sshpty.c index bbbc0fe..15da8c6 100644 --- a/crypto/openssh/sshpty.c +++ b/crypto/openssh/sshpty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshpty.c,v 1.28 2007/09/11 23:49:09 stevesk Exp $ */ +/* $OpenBSD: sshpty.c,v 1.30 2015/07/30 23:09:15 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -85,12 +85,12 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) void pty_release(const char *tty) { -#ifndef __APPLE_PRIVPTY__ +#if !defined(__APPLE_PRIVPTY__) && !defined(HAVE_OPENPTY) if (chown(tty, (uid_t) 0, (gid_t) 0) < 0) error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno)); if (chmod(tty, (mode_t) 0666) < 0) error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno)); -#endif /* __APPLE_PRIVPTY__ */ +#endif /* !__APPLE_PRIVPTY__ && !HAVE_OPENPTY */ } /* Makes the tty the process's controlling tty and sets it to sane modes. */ @@ -99,9 +99,6 @@ void pty_make_controlling_tty(int *ttyfd, const char *tty) { int fd; -#ifdef USE_VHANGUP - void *old; -#endif /* USE_VHANGUP */ #ifdef _UNICOS if (setsid() < 0) @@ -157,21 +154,11 @@ pty_make_controlling_tty(int *ttyfd, const char *tty) if (setpgrp(0,0) < 0) error("SETPGRP %s",strerror(errno)); #endif /* NEED_SETPGRP */ -#ifdef USE_VHANGUP - old = signal(SIGHUP, SIG_IGN); - vhangup(); - signal(SIGHUP, old); -#endif /* USE_VHANGUP */ fd = open(tty, O_RDWR); if (fd < 0) { error("%.100s: %.100s", tty, strerror(errno)); } else { -#ifdef USE_VHANGUP - close(*ttyfd); - *ttyfd = fd; -#else /* USE_VHANGUP */ close(fd); -#endif /* USE_VHANGUP */ } /* Verify that we now have a controlling tty. */ fd = open(_PATH_TTY, O_WRONLY); @@ -209,13 +196,8 @@ pty_setowner(struct passwd *pw, const char *tty) /* Determine the group to make the owner of the tty. */ grp = getgrnam("tty"); - if (grp) { - gid = grp->gr_gid; - mode = S_IRUSR | S_IWUSR | S_IWGRP; - } else { - gid = pw->pw_gid; - mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH; - } + gid = (grp != NULL) ? grp->gr_gid : pw->pw_gid; + mode = (grp != NULL) ? 0620 : 0600; /* * Change owner and mode of the tty as required. diff --git a/crypto/openssh/uidswap.c b/crypto/openssh/uidswap.c index 1f09d58..0702e1d 100644 --- a/crypto/openssh/uidswap.c +++ b/crypto/openssh/uidswap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uidswap.c,v 1.36 2013/11/08 11:15:19 dtucker Exp $ */ +/* $OpenBSD: uidswap.c,v 1.39 2015/06/24 01:49:19 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -14,11 +14,11 @@ #include "includes.h" -#include #include #include #include #include +#include #include #include @@ -86,7 +86,7 @@ temporarily_use_uid(struct passwd *pw) if (saved_egroupslen < 0) fatal("getgroups: %.100s", strerror(errno)); if (saved_egroupslen > 0) { - saved_egroups = xrealloc(saved_egroups, + saved_egroups = xreallocarray(saved_egroups, saved_egroupslen, sizeof(gid_t)); if (getgroups(saved_egroupslen, saved_egroups) < 0) fatal("getgroups: %.100s", strerror(errno)); @@ -104,7 +104,7 @@ temporarily_use_uid(struct passwd *pw) if (user_groupslen < 0) fatal("getgroups: %.100s", strerror(errno)); if (user_groupslen > 0) { - user_groups = xrealloc(user_groups, + user_groups = xreallocarray(user_groups, user_groupslen, sizeof(gid_t)); if (getgroups(user_groupslen, user_groups) < 0) fatal("getgroups: %.100s", strerror(errno)); diff --git a/crypto/openssh/umac.c b/crypto/openssh/umac.c index 0c62145..6eb55b2 100644 --- a/crypto/openssh/umac.c +++ b/crypto/openssh/umac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: umac.c,v 1.8 2013/11/08 00:39:15 djm Exp $ */ +/* $OpenBSD: umac.c,v 1.11 2014/07/22 07:13:42 guenther Exp $ */ /* ----------------------------------------------------------------------- * * umac.c -- C Implementation UMAC Message Authentication @@ -73,13 +73,15 @@ #include "includes.h" #include - -#include "xmalloc.h" -#include "umac.h" #include +#include #include #include +#include "xmalloc.h" +#include "umac.h" +#include "misc.h" + /* ---------------------------------------------------------------------- */ /* --- Primitive Data Types --- */ /* ---------------------------------------------------------------------- */ @@ -131,41 +133,17 @@ typedef unsigned int UWORD; /* Register */ /* --- Endian Conversion --- Forcing assembly on some platforms */ /* ---------------------------------------------------------------------- */ -#if HAVE_SWAP32 -#define LOAD_UINT32_REVERSED(p) (swap32(*(const UINT32 *)(p))) -#define STORE_UINT32_REVERSED(p,v) (*(UINT32 *)(p) = swap32(v)) -#else /* HAVE_SWAP32 */ - -static UINT32 LOAD_UINT32_REVERSED(const void *ptr) -{ - UINT32 temp = *(const UINT32 *)ptr; - temp = (temp >> 24) | ((temp & 0x00FF0000) >> 8 ) - | ((temp & 0x0000FF00) << 8 ) | (temp << 24); - return (UINT32)temp; -} - -# if (__LITTLE_ENDIAN__) -static void STORE_UINT32_REVERSED(void *ptr, UINT32 x) -{ - UINT32 i = (UINT32)x; - *(UINT32 *)ptr = (i >> 24) | ((i & 0x00FF0000) >> 8 ) - | ((i & 0x0000FF00) << 8 ) | (i << 24); -} -# endif /* __LITTLE_ENDIAN */ -#endif /* HAVE_SWAP32 */ - -/* The following definitions use the above reversal-primitives to do the right - * thing on endian specific load and stores. - */ - #if (__LITTLE_ENDIAN__) -#define LOAD_UINT32_LITTLE(ptr) (*(const UINT32 *)(ptr)) -#define STORE_UINT32_BIG(ptr,x) STORE_UINT32_REVERSED(ptr,x) +#define LOAD_UINT32_REVERSED(p) get_u32(p) +#define STORE_UINT32_REVERSED(p,v) put_u32(p,v) #else -#define LOAD_UINT32_LITTLE(ptr) LOAD_UINT32_REVERSED(ptr) -#define STORE_UINT32_BIG(ptr,x) (*(UINT32 *)(ptr) = (UINT32)(x)) +#define LOAD_UINT32_REVERSED(p) get_u32_le(p) +#define STORE_UINT32_REVERSED(p,v) put_u32_le(p,v) #endif +#define LOAD_UINT32_LITTLE(p) (get_u32_le(p)) +#define STORE_UINT32_BIG(p,v) put_u32(p, v) + /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* ----- Begin KDF & PDF Section ---------------------------------------- */ @@ -176,6 +154,7 @@ static void STORE_UINT32_REVERSED(void *ptr, UINT32 x) #define AES_BLOCK_LEN 16 /* OpenSSL's AES */ +#ifdef WITH_OPENSSL #include "openbsd-compat/openssl-compat.h" #ifndef USE_BUILTIN_RIJNDAEL # include @@ -185,6 +164,16 @@ typedef AES_KEY aes_int_key[1]; AES_encrypt((u_char *)(in),(u_char *)(out),(AES_KEY *)int_key) #define aes_key_setup(key,int_key) \ AES_set_encrypt_key((const u_char *)(key),UMAC_KEY_LEN*8,int_key) +#else +#include "rijndael.h" +#define AES_ROUNDS ((UMAC_KEY_LEN / 4) + 6) +typedef UINT8 aes_int_key[AES_ROUNDS+1][4][4]; /* AES internal */ +#define aes_encryption(in,out,int_key) \ + rijndaelEncrypt((u32 *)(int_key), AES_ROUNDS, (u8 *)(in), (u8 *)(out)) +#define aes_key_setup(key,int_key) \ + rijndaelKeySetupEnc((u32 *)(int_key), (const unsigned char *)(key), \ + UMAC_KEY_LEN*8) +#endif /* The user-supplied UMAC key is stretched using AES in a counter * mode to supply all random bits needed by UMAC. The kdf function takes diff --git a/crypto/openssh/uuencode.c b/crypto/openssh/uuencode.c index 294c743..7fc867a 100644 --- a/crypto/openssh/uuencode.c +++ b/crypto/openssh/uuencode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uuencode.c,v 1.27 2013/05/17 00:13:14 djm Exp $ */ +/* $OpenBSD: uuencode.c,v 1.28 2015/04/24 01:36:24 deraadt Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -82,7 +82,7 @@ dump_base64(FILE *fp, const u_char *data, u_int len) fprintf(fp, "dump_base64: len > 65536\n"); return; } - buf = xmalloc(2*len); + buf = xreallocarray(NULL, 2, len); n = uuencode(data, len, buf, 2*len); for (i = 0; i < n; i++) { fprintf(fp, "%c", buf[i]); diff --git a/crypto/openssh/version.h b/crypto/openssh/version.h index 0909146..3d26608 100644 --- a/crypto/openssh/version.h +++ b/crypto/openssh/version.h @@ -1,9 +1,15 @@ -/* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */ +/* $OpenBSD: version.h,v 1.75 2015/08/21 03:45:26 djm Exp $ */ /* $FreeBSD$ */ -#define SSH_VERSION "OpenSSH_6.6.1" +#define SSH_VERSION "OpenSSH_7.1" -#define SSH_PORTABLE "p1" +#define SSH_PORTABLE "p2" #define SSH_RELEASE SSH_VERSION SSH_PORTABLE -#define SSH_VERSION_FREEBSD "FreeBSD-20160124" +#define SSH_VERSION_FREEBSD "FreeBSD-20160125" + +#ifdef WITH_OPENSSL +#define OPENSSL_VERSION SSLeay_version(SSLEAY_VERSION) +#else +#define OPENSSL_VERSION "without OpenSSL" +#endif diff --git a/crypto/openssh/xmalloc.c b/crypto/openssh/xmalloc.c index 2f1cd23..98cbf87 100644 --- a/crypto/openssh/xmalloc.c +++ b/crypto/openssh/xmalloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.c,v 1.29 2014/01/04 17:50:55 tedu Exp $ */ +/* $OpenBSD: xmalloc.c,v 1.32 2015/04/24 01:36:01 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -15,8 +15,10 @@ #include "includes.h" -#include #include +#ifdef HAVE_STDINT_H +#include +#endif #include #include #include @@ -44,8 +46,8 @@ xcalloc(size_t nmemb, size_t size) if (size == 0 || nmemb == 0) fatal("xcalloc: zero size"); - if (SIZE_T_MAX / nmemb < size) - fatal("xcalloc: nmemb * size > SIZE_T_MAX"); + if (SIZE_MAX / nmemb < size) + fatal("xcalloc: nmemb * size > SIZE_MAX"); ptr = calloc(nmemb, size); if (ptr == NULL) fatal("xcalloc: out of memory (allocating %zu bytes)", @@ -54,22 +56,14 @@ xcalloc(size_t nmemb, size_t size) } void * -xrealloc(void *ptr, size_t nmemb, size_t size) +xreallocarray(void *ptr, size_t nmemb, size_t size) { void *new_ptr; - size_t new_size = nmemb * size; - if (new_size == 0) - fatal("xrealloc: zero size"); - if (SIZE_T_MAX / nmemb < size) - fatal("xrealloc: nmemb * size > SIZE_T_MAX"); - if (ptr == NULL) - new_ptr = malloc(new_size); - else - new_ptr = realloc(ptr, new_size); + new_ptr = reallocarray(ptr, nmemb, size); if (new_ptr == NULL) - fatal("xrealloc: out of memory (new_size %zu bytes)", - new_size); + fatal("xreallocarray: out of memory (%zu elements of %zu bytes)", + nmemb, size); return new_ptr; } diff --git a/crypto/openssh/xmalloc.h b/crypto/openssh/xmalloc.h index 261dfd6..2bec77b 100644 --- a/crypto/openssh/xmalloc.h +++ b/crypto/openssh/xmalloc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.h,v 1.14 2013/05/17 00:13:14 djm Exp $ */ +/* $OpenBSD: xmalloc.h,v 1.15 2015/04/24 01:36:01 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -18,7 +18,7 @@ void *xmalloc(size_t); void *xcalloc(size_t, size_t); -void *xrealloc(void *, size_t, size_t); +void *xreallocarray(void *, size_t, size_t); char *xstrdup(const char *); int xasprintf(char **, const char *, ...) __attribute__((__format__ (printf, 2, 3))) diff --git a/lib/libpam/modules/pam_ssh/pam_ssh.c b/lib/libpam/modules/pam_ssh/pam_ssh.c index 405dd6b..8fc68fd 100644 --- a/lib/libpam/modules/pam_ssh/pam_ssh.c +++ b/lib/libpam/modules/pam_ssh/pam_ssh.c @@ -321,12 +321,11 @@ pam_ssh_start_agent(pam_handle_t *pamh) static int pam_ssh_add_keys_to_agent(pam_handle_t *pamh) { - AuthenticationConnection *ac; const struct pam_ssh_key *psk; const char **kfn; const void *item; char **envlist, **env; - int pam_err; + int fd, pam_err; /* switch to PAM environment */ envlist = environ; @@ -336,7 +335,7 @@ pam_ssh_add_keys_to_agent(pam_handle_t *pamh) } /* get a connection to the agent */ - if ((ac = ssh_get_authentication_connection()) == NULL) { + if (ssh_get_authentication_socket(&fd) != 0) { openpam_log(PAM_LOG_DEBUG, "failed to connect to the agent"); pam_err = PAM_SYSTEM_ERR; goto end; @@ -347,7 +346,7 @@ pam_ssh_add_keys_to_agent(pam_handle_t *pamh) pam_err = pam_get_data(pamh, *kfn, &item); if (pam_err == PAM_SUCCESS && item != NULL) { psk = item; - if (ssh_add_identity(ac, psk->key, psk->comment)) + if (ssh_add_identity(fd, psk->key, psk->comment) == 0) openpam_log(PAM_LOG_DEBUG, "added %s to ssh agent", psk->comment); else @@ -358,11 +357,11 @@ pam_ssh_add_keys_to_agent(pam_handle_t *pamh) } } pam_err = PAM_SUCCESS; - end: + /* disconnect from agent */ - if (ac != NULL) - ssh_close_authentication_connection(ac); + ssh_close_authentication_socket(fd); + end: /* switch back to original environment */ for (env = environ; *env != NULL; ++env) free(*env); diff --git a/secure/lib/libssh/Makefile b/secure/lib/libssh/Makefile index 2f73b4c..0d3f05c 100644 --- a/secure/lib/libssh/Makefile +++ b/secure/lib/libssh/Makefile @@ -5,28 +5,32 @@ LIB= ssh PRIVATELIB= true SHLIB_MAJOR= 5 -SRCS= authfd.c authfile.c bufaux.c bufbn.c buffer.c \ - canohost.c channels.c cipher.c cipher-aes.c \ +SRCS= ssh_api.c ssherr.c sshbuf.c sshkey.c sshbuf-getput-basic.c \ + sshbuf-misc.c sshbuf-getput-crypto.c krl.c bitmap.c +SRCS+= authfd.c authfile.c bufaux.c bufbn.c bufec.c buffer.c \ + canohost.c channels.c cipher.c cipher-aes.c cipher-aesctr.c \ cipher-bf1.c cipher-ctr.c cipher-3des1.c cleanup.c \ - compat.c compress.c crc32.c deattack.c fatal.c hostfile.c \ - log.c match.c md-sha256.c moduli.c nchan.c packet.c \ + compat.c crc32.c deattack.c fatal.c hostfile.c \ + log.c match.c md-sha256.c moduli.c nchan.c packet.c opacket.c \ readpass.c rsa.c ttymodes.c xmalloc.c addrmatch.c \ - atomicio.c key.c dispatch.c kex.c mac.c uidswap.c uuencode.c misc.c \ + atomicio.c key.c dispatch.c mac.c uidswap.c uuencode.c misc.c \ monitor_fdpass.c rijndael.c ssh-dss.c ssh-ecdsa.c ssh-rsa.c dh.c \ - kexdh.c kexgex.c kexdhc.c kexgexc.c bufec.c kexecdh.c kexecdhc.c \ msg.c progressmeter.c dns.c entropy.c umac.c umac128.c \ - ssh-pkcs11.c krl.c smult_curve25519_ref.c \ - kexc25519.c kexc25519c.c poly1305.c chacha.c cipher-chachapoly.c \ - ssh-ed25519.c digest-openssl.c hmac.c \ - sc25519.c ge25519.c fe25519.c ed25519.c verify.c hash.c blocks.c + ssh-pkcs11.c smult_curve25519_ref.c \ + poly1305.c chacha.c cipher-chachapoly.c \ + ssh-ed25519.c digest-openssl.c digest-libc.c hmac.c \ + sc25519.c ge25519.c fe25519.c ed25519.c verify.c hash.c blocks.c \ + kex.c kexdh.c kexgex.c kexecdh.c kexc25519.c \ + kexdhc.c kexgexc.c kexecdhc.c kexc25519c.c \ + kexdhs.c kexgexs.c kexecdhs.c kexc25519s.c # gss-genr.c should be in $SRCS but causes linking problems, so it is # compiled directly into sshd instead. # Portability layer SRCS+= bcrypt_pbkdf.c blowfish.c bsd-misc.c explicit_bzero.c fmt_scaled.c \ - glob.c openssl-compat.c port-tun.c strtonum.c timingsafe_bcmp.c \ - vis.c xcrypt.c xmmap.c + glob.c openssl-compat.c port-tun.c reallocarray.c realpath.c strtonum.c \ + timingsafe_bcmp.c vis.c xcrypt.c xmmap.c .if ${MK_LDNS} == "no" SRCS+= getrrsetbyname.c diff --git a/secure/usr.sbin/sshd/Makefile b/secure/usr.sbin/sshd/Makefile index 7e7143a..5fb7084 100644 --- a/secure/usr.sbin/sshd/Makefile +++ b/secure/usr.sbin/sshd/Makefile @@ -10,8 +10,7 @@ SRCS= sshd.c auth-rhosts.c auth-passwd.c auth-rsa.c auth-rh-rsa.c \ auth-chall.c auth2-chall.c groupaccess.c \ auth-skey.c auth-bsdauth.c auth2-hostbased.c auth2-kbdint.c \ auth2-none.c auth2-passwd.c auth2-pubkey.c \ - monitor_mm.c monitor.c monitor_wrap.c kexdhs.c kexgexs.c kexecdhs.c \ - kexc25519s.c auth-krb5.c \ + monitor_mm.c monitor.c monitor_wrap.c auth-krb5.c \ auth2-gss.c gss-serv.c gss-serv-krb5.c \ loginrec.c auth-pam.c auth-shadow.c auth-sia.c md5crypt.c \ sftp-server.c sftp-common.c \ -- cgit v1.1 From f97dd8fd40358fe1b7b39c278fdc20fbd9bacfe2 Mon Sep 17 00:00:00 2001 From: ume Date: Sun, 7 Feb 2016 16:51:50 +0000 Subject: MFC r295234: Make sure to enable aliases for SHIFT_JIS. Approved by: re (marius) --- share/i18n/esdb/MISC/MISC.alias | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/share/i18n/esdb/MISC/MISC.alias b/share/i18n/esdb/MISC/MISC.alias index 90e2ccd..6ffad5d 100644 --- a/share/i18n/esdb/MISC/MISC.alias +++ b/share/i18n/esdb/MISC/MISC.alias @@ -29,10 +29,10 @@ JISX0208:1990 x0208 JOHAB cp1361 -SHIFT_JIS csshiftjis -SHIFT_JIS ms_kanji -SHIFT_JIS sjis +Shift_JIS csshiftjis +Shift_JIS ms_kanji +Shift_JIS sjis -SHIFT_JIS-2004 shift_jisx0213 +Shift_JIS-2004 shift_jisx0213 TDS565 iso-ir-230 -- cgit v1.1 From 6b0dbb3b46a79900978eaf6d04c03edb0c857e5b Mon Sep 17 00:00:00 2001 From: bz Date: Sun, 7 Feb 2016 22:53:03 +0000 Subject: MFC r295202: Try to fix a bug introduced in r228623 (head). We started to copy the ifa_msghdr as otherwise platforms with strict alignment would break. It is unclear to me if there's also a problem with access to the address list following the structure. However we never copied the address list after the structure and thus are pointing at random memory. For now just use a pointer to the original memory for accessing the address list making it at least work on platforms with weak memory access. PR: 195445 Reported by: wolfgang lyxys.ka.sub.org Tested by: wolfgang lyxys.ka.sub.org (x86) Approved by: re (marius) --- contrib/bsnmp/snmp_mibII/mibII.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c index d3fe27a..e47f453 100644 --- a/contrib/bsnmp/snmp_mibII/mibII.c +++ b/contrib/bsnmp/snmp_mibII/mibII.c @@ -969,7 +969,7 @@ handle_rtmsg(struct rt_msghdr *rtm) { struct sockaddr *addrs[RTAX_MAX]; struct if_msghdr *ifm; - struct ifa_msghdr ifam; + struct ifa_msghdr ifam, *ifamp; struct ifma_msghdr *ifmam; #ifdef RTM_IFANNOUNCE struct if_announcemsghdr *ifan; @@ -989,8 +989,9 @@ handle_rtmsg(struct rt_msghdr *rtm) switch (rtm->rtm_type) { case RTM_NEWADDR: - memcpy(&ifam, rtm, sizeof(ifam)); - mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs); + ifamp = (struct ifa_msghdr *)rtm; + memcpy(&ifam, ifamp, sizeof(ifam)); + mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs); if (addrs[RTAX_IFA] == NULL || addrs[RTAX_NETMASK] == NULL) break; @@ -1016,8 +1017,9 @@ handle_rtmsg(struct rt_msghdr *rtm) break; case RTM_DELADDR: - memcpy(&ifam, rtm, sizeof(ifam)); - mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs); + ifamp = (struct ifa_msghdr *)rtm; + memcpy(&ifam, ifamp, sizeof(ifam)); + mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs); if (addrs[RTAX_IFA] == NULL) break; -- cgit v1.1 From a16e63df01529e30d97fa89dc501264f6da0bf51 Mon Sep 17 00:00:00 2001 From: bz Date: Sun, 7 Feb 2016 23:42:36 +0000 Subject: MFC r294514: The variable is write once only and not used. Recover the vertical space. Sponsored by: The FreeBSD Foundation Obtained from: p4 CH=180830 Reviewed by: gnn, hiren Differential Revision:https://reviews.freebsd.org/D4898 Approved by: re (marius, gjb) --- sys/netinet/igmp.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 34a60a8..47f90ba 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -654,16 +654,12 @@ igmp_ifdetach(struct ifnet *ifp) void igmp_domifdetach(struct ifnet *ifp) { - struct igmp_ifinfo *igi; CTR3(KTR_IGMPV3, "%s: called for ifp %p(%s)", __func__, ifp, ifp->if_xname); IGMP_LOCK(); - - igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp; igi_delete_locked(ifp); - IGMP_UNLOCK(); } -- cgit v1.1 From 3078b388e3205a7974daa71624945c943dbe1273 Mon Sep 17 00:00:00 2001 From: bz Date: Mon, 8 Feb 2016 00:07:01 +0000 Subject: MFC r292601,292654: Since r256624 (head) we have been leaking routing table allocations on vnet enabled jail shutdown. Call the provided cleanup routines for IP versions 4 and 6 to plug these leaks. Sponsored by: The FreeBSD Foundation Reviewed by: gnn Differential Revision:https://reviews.freebsd.org/D4530 Approved by: re (gjb) --- sys/netinet/in_rmx.c | 2 +- sys/netinet6/in6_rmx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index 9b89fbd..80177e4 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -373,7 +373,7 @@ in_detachhead(void **head, int off) { callout_drain(&V_rtq_timer); - return (1); + return (rn_detachhead(head)); } #endif diff --git a/sys/netinet6/in6_rmx.c b/sys/netinet6/in6_rmx.c index 394cdb6..9179b7c 100644 --- a/sys/netinet6/in6_rmx.c +++ b/sys/netinet6/in6_rmx.c @@ -290,7 +290,7 @@ in6_detachhead(void **head, int off) { callout_drain(&V_rtq_mtutimer); - return (1); + return (rn_detachhead(head)); } #endif -- cgit v1.1 From bc0cc9f20c1e90100fdf972cce746b77614f3132 Mon Sep 17 00:00:00 2001 From: kib Date: Mon, 8 Feb 2016 11:15:36 +0000 Subject: MFC r294735: Don't allow opening the callout device when the callin device is already open (in disguise as the console device). Approved by: re (gjb) --- sys/kern/tty.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index a5a6690..76904a7 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -266,10 +266,10 @@ ttydev_open(struct cdev *dev, int oflags, int devtype __unused, /* * Make sure the "tty" and "cua" device cannot be opened at the - * same time. + * same time. The console is a "tty" device. */ if (TTY_CALLOUT(tp, dev)) { - if (tp->t_flags & TF_OPENED_IN) { + if (tp->t_flags & (TF_OPENED_CONS | TF_OPENED_IN)) { error = EBUSY; goto done; } @@ -322,6 +322,8 @@ ttydev_open(struct cdev *dev, int oflags, int devtype __unused, tp->t_flags |= TF_OPENED_OUT; else tp->t_flags |= TF_OPENED_IN; + MPASS((tp->t_flags & (TF_OPENED_CONS | TF_OPENED_IN)) == 0 || + (tp->t_flags & TF_OPENED_OUT) == 0); done: tp->t_flags &= ~TF_OPENCLOSE; cv_broadcast(&tp->t_dcdwait); @@ -342,7 +344,8 @@ ttydev_close(struct cdev *dev, int fflag, int devtype __unused, * Don't actually close the device if it is being used as the * console. */ - MPASS((tp->t_flags & TF_OPENED) != TF_OPENED); + MPASS((tp->t_flags & (TF_OPENED_CONS | TF_OPENED_IN)) == 0 || + (tp->t_flags & TF_OPENED_OUT) == 0); if (dev == dev_console) tp->t_flags &= ~TF_OPENED_CONS; else -- cgit v1.1 From a63a5c89b8b8639f94e24e902b6fbabf8d9e8021 Mon Sep 17 00:00:00 2001 From: kib Date: Mon, 8 Feb 2016 11:18:13 +0000 Subject: MFC r294732: Minor fixes for ddb tty-related commands. Approved by: re (gjb) --- sys/kern/tty.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 76904a7..ddde7b3 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -2153,9 +2153,11 @@ static const struct { }; #define TTY_FLAG_BITS \ - "\20\1NOPREFIX\2INITLOCK\3CALLOUT\4OPENED_IN\5OPENED_OUT\6GONE" \ - "\7OPENCLOSE\10ASYNC\11LITERAL\12HIWAT_IN\13HIWAT_OUT\14STOPPED" \ - "\15EXCLUDE\16BYPASS\17ZOMBIE\20HOOK" + "\20\1NOPREFIX\2INITLOCK\3CALLOUT\4OPENED_IN" \ + "\5OPENED_OUT\6OPENED_CONS\7GONE\10OPENCLOSE" \ + "\11ASYNC\12LITERAL\13HIWAT_IN\14HIWAT_OUT" \ + "\15STOPPED\16EXCLUDE\17BYPASS\20ZOMBIE" \ + "\21HOOK\22BUSY_IN\23BUSY_OUT" #define DB_PRINTSYM(name, addr) \ db_printf("%s " #name ": ", sep); \ @@ -2221,9 +2223,9 @@ DB_SHOW_COMMAND(tty, db_show_tty) } tp = (struct tty *)addr; - db_printf("0x%p: %s\n", tp, tty_devname(tp)); + db_printf("%p: %s\n", tp, tty_devname(tp)); db_printf("\tmtx: %p\n", tp->t_mtx); - db_printf("\tflags: %b\n", tp->t_flags, TTY_FLAG_BITS); + db_printf("\tflags: 0x%b\n", tp->t_flags, TTY_FLAG_BITS); db_printf("\trevokecnt: %u\n", tp->t_revokecnt); /* Buffering mechanisms. */ -- cgit v1.1 From 87ab639764a7d4ff24c9e2ecd1f21536e3b9ceb5 Mon Sep 17 00:00:00 2001 From: glebius Date: Mon, 8 Feb 2016 17:47:58 +0000 Subject: Merge r264915: fix NULL pointer derefernce with special sequence of DIOCADDADDR and DIOCADDRULE. PR: 206933 Approved by: re (marius) --- sys/netpfil/pf/pf_ioctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index d91c851..12c8be5 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -350,7 +350,9 @@ pf_empty_pool(struct pf_palist *poola) pfi_dynaddr_remove(pa->addr.p.dyn); break; case PF_ADDR_TABLE: - pfr_detach_table(pa->addr.p.tbl); + /* XXX: this could be unfinished pooladdr on pabuf */ + if (pa->addr.p.tbl != NULL) + pfr_detach_table(pa->addr.p.tbl); break; } if (pa->kif) -- cgit v1.1