From owner-freebsd-ports-bugs@FreeBSD.ORG Tue Jun 9 09:00:16 2009 Return-Path: Delivered-To: freebsd-ports-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 64C221065674 for ; Tue, 9 Jun 2009 09:00:16 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 311AE8FC20 for ; Tue, 9 Jun 2009 09:00:16 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n5990GFE094687 for ; Tue, 9 Jun 2009 09:00:16 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n5990GGL094681; Tue, 9 Jun 2009 09:00:16 GMT (envelope-from gnats) Resent-Date: Tue, 9 Jun 2009 09:00:16 GMT Resent-Message-Id: <200906090900.n5990GGL094681@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-ports-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Denis Barov Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id ED1031065672 for ; Tue, 9 Jun 2009 08:57:32 +0000 (UTC) (envelope-from dindin@sepulca.yandex.ru) Received: from relanium.yandex.ru (relanium.yandex.ru [77.88.58.132]) by mx1.freebsd.org (Postfix) with ESMTP id 84DE38FC1D for ; Tue, 9 Jun 2009 08:57:29 +0000 (UTC) (envelope-from dindin@sepulca.yandex.ru) Received: from sepulca.yandex.ru (dhcp170-57-red.yandex.net [95.108.170.57]) by relanium.yandex.ru (8.14.3/8.14.3) with ESMTP id n598vQGW001900 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 9 Jun 2009 12:57:27 +0400 (MSD) (envelope-from dindin@sepulca.yandex.ru) Received: from sepulca.yandex.ru (localhost [127.0.0.1]) by sepulca.yandex.ru (8.14.3/8.14.3) with ESMTP id n598vQOX015915 for ; Tue, 9 Jun 2009 12:57:26 +0400 (MSD) (envelope-from dindin@sepulca.yandex.ru) Received: (from root@localhost) by sepulca.yandex.ru (8.14.3/8.14.3/Submit) id n598vQQF015914; Tue, 9 Jun 2009 12:57:26 +0400 (MSD) (envelope-from dindin) Message-Id: <200906090857.n598vQQF015914@sepulca.yandex.ru> Date: Tue, 9 Jun 2009 12:57:26 +0400 (MSD) From: Denis Barov To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: ports/135407: [MAINTAINER] security/openssh-portable: update HPN and LPK patches to newer versions X-BeenThere: freebsd-ports-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Ports bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Jun 2009 09:00:16 -0000 >Number: 135407 >Category: ports >Synopsis: [MAINTAINER] security/openssh-portable: update HPN and LPK patches to newer versions >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: maintainer-update >Submitter-Id: current-users >Arrival-Date: Tue Jun 09 09:00:15 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Denis Barov >Release: FreeBSD 7.2-RELEASE i386 >Organization: Yandex >Environment: System: FreeBSD sepulca.yandex.ru 7.2-RELEASE FreeBSD 7.2-RELEASE #0: Tue Jun 2 19:57:10 MSD >Description: [DESCRIBE CHANGES] Added file(s): - files/contrib-openssh-5.1_p1-lpk-64bit.patch - files/contrib-openssh-lpk-5.1p1-0.3.10-servconf.c.patch - files/contrib-openssh-lpk-5.1p1-0.3.10.patch - files/lpk+hpn-servconf.c.patch - files/openssh-5.2p1-hpn13v6-servconf.c.diff - files/openssh-5.2p1-hpn13v6.diff Removed file(s): - files/openssh-5.2p1-hpn-servconf.patch - files/openssh-5.2p1-hpn.patch - files/openssh-lpk+hpn-servconf.patch - files/openssh-lpk-5.0p1-0.3.9-servconv.patch - files/openssh-lpk-5.0p1-0.3.9.patch - files/openssh-lpk-5.0p1-64bit.patch Generated with FreeBSD Port Tools 0.77 >How-To-Repeat: >Fix: --- openssh-portable-5.2.p1_2,1.patch begins here --- diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/Makefile /usr/home/dindin/workspace/openssh-portable/Makefile --- /usr/ports/security/openssh-portable/Makefile 2009-05-19 14:13:28.000000000 +0400 +++ /usr/home/dindin/workspace/openssh-portable/Makefile 2009-06-04 18:59:41.000000000 +0400 @@ -2,12 +2,12 @@ # Date created: 18 Mar 1999 # Whom: dwcjr@inethouston.net # -# $FreeBSD$ +# $FreeBSD: ports/security/openssh-portable/Makefile,v 1.136 2009/05/19 10:13:28 osa Exp $ # PORTNAME= openssh DISTVERSION= 5.2p1 -PORTREVISION= 1 +PORTREVISION= 2 PORTEPOCH= 1 CATEGORIES= security ipv6 .if defined(OPENSSH_SNAPSHOT) @@ -81,7 +81,7 @@ WITH_OVERWRITE_BASE= yes .endif -.if !defined(WITHOUT_PAM) && exists(/usr/include/security/pam_modules.h) +.if !defined(WITHOUT_PAM) && exists(${PREFIX}/security/pam_modules.h) CONFIGURE_ARGS+= --with-pam .endif @@ -142,12 +142,12 @@ .endif .if defined(WITH_HPN) -EXTRA_PATCHES+= ${FILESDIR}/openssh-5.2p1-hpn.patch +EXTRA_PATCHES+= ${FILESDIR}/openssh-5.2p1-hpn13v6.diff .endif # See http://dev.inversepath.com/trac/openssh-lpk .if defined(WITH_LPK) -EXTRA_PATCHES+= ${FILESDIR}/openssh-lpk-5.0p1-0.3.9.patch +EXTRA_PATCHES+= ${FILESDIR}/contrib-openssh-lpk-5.1p1-0.3.10.patch USE_OPENLDAP= yes CPPFLAGS+= "-I${LOCALBASE}/include -DWITH_LDAP_PUBKEY" CONFIGURE_ARGS+= --with-libs='-lldap' --with-ldflags='-L${LOCALBASE}/lib' \ @@ -157,15 +157,15 @@ # resolve some patches incompatibility between LPK and HPN patches .if defined(WITH_HPN) && defined(WITH_LPK) -EXTRA_PATCHES+= ${FILESDIR}/openssh-lpk+hpn-servconf.patch +EXTRA_PATCHES+= ${FILESDIR}/lpk+hpn-servconf.c.patch .elif defined(WITH_HPN) && !defined(WITH_LPK) -EXTRA_PATCHES+= ${FILESDIR}/openssh-5.2p1-hpn-servconf.patch +EXTRA_PATCHES+= ${FILESDIR}/openssh-5.2p1-hpn13v6-servconf.c.diff .elif defined(WITH_LPK) && !defined(WITH_HPN) -EXTRA_PATCHES+= ${FILESDIR}/openssh-lpk-5.0p1-0.3.9-servconv.patch +EXTRA_PATCHES+= ${FILESDIR}/contrib-openssh-lpk-5.1p1-0.3.10-servconf.c.patch .endif .if defined(WITH_LPK) && ${ARCH} == "amd64" -EXTRA_PATCHES+= ${FILESDIR}/openssh-lpk-5.0p1-64bit.patch +EXTRA_PATCHES+= ${FILESDIR}/contrib-openssh-5.1_p1-lpk-64bit.patch .endif # See http://www.roumenpetrov.info/openssh/ @@ -182,8 +182,7 @@ EMPTYDIR= /var/empty PREFIX= /usr ETCSSH= /etc/ssh -USE_RC_SUBR= yes -SUB_FILES+= openssh +USE_RC_SUBR= openssh PLIST_SUB+= NOTBASE="@comment " PLIST_SUB+= BASE="" PLIST_SUB+= BASEPREFIX="${PREFIX}" diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/distinfo /usr/home/dindin/workspace/openssh-portable/distinfo --- /usr/ports/security/openssh-portable/distinfo 2009-05-15 15:00:27.000000000 +0400 +++ /usr/home/dindin/workspace/openssh-portable/distinfo 2009-06-04 19:00:30.000000000 +0400 @@ -1,6 +1,3 @@ MD5 (openssh-5.2p1.tar.gz) = ada79c7328a8551bdf55c95e631e7dad SHA256 (openssh-5.2p1.tar.gz) = 4023710c37d0b3d79e6299cb79b6de2a31db7d581fe59e775a5351784034ecae SIZE (openssh-5.2p1.tar.gz) = 1016612 -MD5 (openssh-5.2p1+x509-6.2.diff.gz) = 8dbbfb743226864f6bb49b56e77776d9 -SHA256 (openssh-5.2p1+x509-6.2.diff.gz) = 72cfb1e232b6ae0a9df6e8539a9f6b53db7c0a2141cf2e4dd65b407748fa9f34 -SIZE (openssh-5.2p1+x509-6.2.diff.gz) = 153010 diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/contrib-openssh-5.1_p1-lpk-64bit.patch /usr/home/dindin/workspace/openssh-portable/files/contrib-openssh-5.1_p1-lpk-64bit.patch --- /usr/ports/security/openssh-portable/files/contrib-openssh-5.1_p1-lpk-64bit.patch 1970-01-01 03:00:00.000000000 +0300 +++ /usr/home/dindin/workspace/openssh-portable/files/contrib-openssh-5.1_p1-lpk-64bit.patch 2009-05-26 18:21:48.000000000 +0400 @@ -0,0 +1,44 @@ +diff -Nuar --exclude '*.rej' servconf.c.orig servconf.c +--- servconf.c.orig 2008-08-23 15:02:47.000000000 -0700 ++++ servconf.c 2008-08-23 15:04:21.000000000 -0700 +@@ -701,6 +701,7 @@ + int cmdline = 0, *intptr, value, n; + SyslogFacility *log_facility_ptr; + LogLevel *log_level_ptr; ++ unsigned long lvalue, *longptr; + ServerOpCodes opcode; + u_short port; + u_int i, flags = 0; +@@ -715,6 +716,7 @@ + if (!arg || !*arg || *arg == '#') + return 0; + intptr = NULL; ++ longptr = NULL; + charptr = NULL; + opcode = parse_token(arg, filename, linenum, &flags); + +@@ -1449,11 +1451,20 @@ + *intptr = value; + break; + case sBindTimeout: +- intptr = (int *) &options->lpk.b_timeout.tv_sec; +- goto parse_int; ++ longptr = (unsigned long *) &options->lpk.b_timeout.tv_sec; ++parse_ulong: ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing integer value.", ++ filename, linenum); ++ lvalue = atol(arg); ++ if (*activep && *longptr == -1) ++ *longptr = lvalue; ++ break; ++ + case sSearchTimeout: +- intptr = (int *) &options->lpk.s_timeout.tv_sec; +- goto parse_int; ++ longptr = (unsigned long *) &options->lpk.s_timeout.tv_sec; ++ goto parse_ulong; + break; + case sLdapConf: + arg = cp; diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/contrib-openssh-lpk-5.1p1-0.3.10-servconf.c.patch /usr/home/dindin/workspace/openssh-portable/files/contrib-openssh-lpk-5.1p1-0.3.10-servconf.c.patch --- /usr/ports/security/openssh-portable/files/contrib-openssh-lpk-5.1p1-0.3.10-servconf.c.patch 1970-01-01 03:00:00.000000000 +0300 +++ /usr/home/dindin/workspace/openssh-portable/files/contrib-openssh-lpk-5.1p1-0.3.10-servconf.c.patch 2009-05-26 19:19:54.000000000 +0400 @@ -0,0 +1,213 @@ +--- servconf.c.orig 2009-05-26 15:13:32.000000000 +0400 ++++ servconf.c 2009-05-26 15:24:39.000000000 +0400 +@@ -42,6 +42,10 @@ + #include "channels.h" + #include "groupaccess.h" + ++#ifdef WITH_LDAP_PUBKEY ++#include "ldapauth.h" ++#endif ++ + static void add_listen_addr(ServerOptions *, char *, int); + static void add_one_listen_addr(ServerOptions *, char *, int); + +@@ -128,6 +132,24 @@ + options->adm_forced_command = NULL; + options->chroot_directory = NULL; + options->zero_knowledge_password_authentication = -1; ++#ifdef WITH_LDAP_PUBKEY ++ /* XXX dirty */ ++ options->lpk.ld = NULL; ++ options->lpk.on = -1; ++ options->lpk.servers = NULL; ++ options->lpk.u_basedn = NULL; ++ options->lpk.g_basedn = NULL; ++ options->lpk.binddn = NULL; ++ options->lpk.bindpw = NULL; ++ options->lpk.sgroup = NULL; ++ options->lpk.filter = NULL; ++ options->lpk.fgroup = NULL; ++ options->lpk.l_conf = NULL; ++ options->lpk.tls = -1; ++ options->lpk.b_timeout.tv_sec = -1; ++ options->lpk.s_timeout.tv_sec = -1; ++ options->lpk.flags = FLAG_EMPTY; ++#endif + } + + void +@@ -265,6 +287,32 @@ + options->permit_tun = SSH_TUNMODE_NO; + if (options->zero_knowledge_password_authentication == -1) + options->zero_knowledge_password_authentication = 0; ++#ifdef WITH_LDAP_PUBKEY ++ if (options->lpk.on == -1) ++ options->lpk.on = _DEFAULT_LPK_ON; ++ if (options->lpk.servers == NULL) ++ options->lpk.servers = _DEFAULT_LPK_SERVERS; ++ if (options->lpk.u_basedn == NULL) ++ options->lpk.u_basedn = _DEFAULT_LPK_UDN; ++ if (options->lpk.g_basedn == NULL) ++ options->lpk.g_basedn = _DEFAULT_LPK_GDN; ++ if (options->lpk.binddn == NULL) ++ options->lpk.binddn = _DEFAULT_LPK_BINDDN; ++ if (options->lpk.bindpw == NULL) ++ options->lpk.bindpw = _DEFAULT_LPK_BINDPW; ++ if (options->lpk.sgroup == NULL) ++ options->lpk.sgroup = _DEFAULT_LPK_SGROUP; ++ if (options->lpk.filter == NULL) ++ options->lpk.filter = _DEFAULT_LPK_FILTER; ++ if (options->lpk.tls == -1) ++ options->lpk.tls = _DEFAULT_LPK_TLS; ++ if (options->lpk.b_timeout.tv_sec == -1) ++ options->lpk.b_timeout.tv_sec = _DEFAULT_LPK_BTIMEOUT; ++ if (options->lpk.s_timeout.tv_sec == -1) ++ options->lpk.s_timeout.tv_sec = _DEFAULT_LPK_STIMEOUT; ++ if (options->lpk.l_conf == NULL) ++ options->lpk.l_conf = _DEFAULT_LPK_LDP; ++#endif + + /* Turn privilege separation on by default */ + if (use_privsep == -1) +@@ -311,6 +359,12 @@ + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, + sDeprecated, sUnsupported ++#ifdef WITH_LDAP_PUBKEY ++ ,sLdapPublickey, sLdapServers, sLdapUserDN ++ ,sLdapGroupDN, sBindDN, sBindPw, sMyGroup ++ ,sLdapFilter, sForceTLS, sBindTimeout ++ ,sSearchTimeout, sLdapConf ++#endif + } ServerOpCodes; + + #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ +@@ -421,6 +475,20 @@ + { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, + { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, + { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, ++#ifdef WITH_LDAP_PUBKEY ++ { _DEFAULT_LPK_TOKEN, sLdapPublickey, SSHCFG_GLOBAL }, ++ { _DEFAULT_SRV_TOKEN, sLdapServers, SSHCFG_GLOBAL }, ++ { _DEFAULT_USR_TOKEN, sLdapUserDN, SSHCFG_GLOBAL }, ++ { _DEFAULT_GRP_TOKEN, sLdapGroupDN, SSHCFG_GLOBAL }, ++ { _DEFAULT_BDN_TOKEN, sBindDN, SSHCFG_GLOBAL }, ++ { _DEFAULT_BPW_TOKEN, sBindPw, SSHCFG_GLOBAL }, ++ { _DEFAULT_MYG_TOKEN, sMyGroup, SSHCFG_GLOBAL }, ++ { _DEFAULT_FIL_TOKEN, sLdapFilter, SSHCFG_GLOBAL }, ++ { _DEFAULT_TLS_TOKEN, sForceTLS, SSHCFG_GLOBAL }, ++ { _DEFAULT_BTI_TOKEN, sBindTimeout, SSHCFG_GLOBAL }, ++ { _DEFAULT_STI_TOKEN, sSearchTimeout, SSHCFG_GLOBAL }, ++ { _DEFAULT_LDP_TOKEN, sLdapConf, SSHCFG_GLOBAL }, ++#endif + { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, + { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, + { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL }, +@@ -1311,6 +1379,107 @@ + while (arg) + arg = strdelim(&cp); + break; ++#ifdef WITH_LDAP_PUBKEY ++ case sLdapPublickey: ++ intptr = &options->lpk.on; ++ goto parse_flag; ++ case sLdapServers: ++ /* arg = strdelim(&cp); */ ++ p = line; ++ while(*p++); ++ arg = p; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing ldap server",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ if ((options->lpk.servers = ldap_parse_servers(arg)) == NULL) ++ fatal("%s line %d: error in ldap servers", filename, linenum); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sLdapUserDN: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing ldap server",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.u_basedn = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sLdapGroupDN: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing ldap server",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.g_basedn = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sBindDN: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing binddn",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.binddn = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sBindPw: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing bindpw",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.bindpw = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sMyGroup: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing groupname",filename, linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.sgroup = xstrdup(arg); ++ if (options->lpk.sgroup) ++ options->lpk.fgroup = ldap_parse_groups(options->lpk.sgroup); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sLdapFilter: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing filter",filename, linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.filter = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sForceTLS: ++ intptr = &options->lpk.tls; ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing yes/no argument.", ++ filename, linenum); ++ value = 0; /* silence compiler */ ++ if (strcmp(arg, "yes") == 0) ++ value = 1; ++ else if (strcmp(arg, "no") == 0) ++ value = 0; ++ else if (strcmp(arg, "try") == 0) ++ value = -1; ++ else ++ fatal("%s line %d: Bad yes/no argument: %s", ++ filename, linenum, arg); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ case sBindTimeout: ++ intptr = (int *) &options->lpk.b_timeout.tv_sec; ++ goto parse_int; ++ case sSearchTimeout: ++ intptr = (int *) &options->lpk.s_timeout.tv_sec; ++ goto parse_int; ++ break; ++ case sLdapConf: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing LpkLdapConf", filename, linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.l_conf = xstrdup(arg); ++ memset(arg, 0, strlen(arg)); ++ break; ++#endif + + default: + fatal("%s line %d: Missing handler for opcode %s (%d)", diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/contrib-openssh-lpk-5.1p1-0.3.10.patch /usr/home/dindin/workspace/openssh-portable/files/contrib-openssh-lpk-5.1p1-0.3.10.patch --- /usr/ports/security/openssh-portable/files/contrib-openssh-lpk-5.1p1-0.3.10.patch 1970-01-01 03:00:00.000000000 +0300 +++ /usr/home/dindin/workspace/openssh-portable/files/contrib-openssh-lpk-5.1p1-0.3.10.patch 2009-05-26 14:17:48.000000000 +0400 @@ -0,0 +1,1682 @@ +This is a forward-port of the OpenSSH LPK support patch. + +It adds support for storing OpenSSH public keys in LDAP. It also supports +grouping of machines in the LDAP data to limit users to specific machines. + +The latest homepage for the LPK project is: +http://code.google.com/p/openssh-lpk/ + +The 0.3.10 version of the patch includes a fix for 64-bit platforms, as +discovered by Gentoo, where the bind timeout and search timeout values were not +being parsed correctly: http://bugs.gentoo.org/210110 + +Forward-ported-from: openssh-lpk-5.1p1-0.3.9.patch +Signed-off-by: Robin H. Johnson + +diff -Nuar --exclude '*.orig' --exclude '*.rej' auth2-pubkey.c auth2-pubkey.c +--- auth2-pubkey.c 2008-07-03 19:54:25.000000000 -0700 ++++ auth2-pubkey.c 2008-08-23 15:02:47.000000000 -0700 +@@ -55,6 +55,10 @@ + #include "monitor_wrap.h" + #include "misc.h" + ++#ifdef WITH_LDAP_PUBKEY ++#include "ldapauth.h" ++#endif ++ + /* import */ + extern ServerOptions options; + extern u_char *session_id2; +@@ -187,10 +191,79 @@ + u_long linenum = 0; + Key *found; + char *fp; ++#ifdef WITH_LDAP_PUBKEY ++ ldap_key_t * k; ++ unsigned int i = 0; ++#endif + + /* Temporarily use the user's uid. */ + temporarily_use_uid(pw); + ++#ifdef WITH_LDAP_PUBKEY ++ found_key = 0; ++ /* allocate a new key type */ ++ found = key_new(key->type); ++ ++ /* first check if the options is enabled, then try.. */ ++ if (options.lpk.on) { ++ debug("[LDAP] trying LDAP first uid=%s",pw->pw_name); ++ if (ldap_ismember(&options.lpk, pw->pw_name) > 0) { ++ if ((k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) { ++ /* Skip leading whitespace, empty and comment lines. */ ++ for (i = 0 ; i < k->num ; i++) { ++ /* dont forget if multiple keys to reset options */ ++ char *cp, *options = NULL; ++ ++ for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++) ++ ; ++ if (!*cp || *cp == '\n' || *cp == '#') ++ continue; ++ ++ if (key_read(found, &cp) != 1) { ++ /* no key? check if there are options for this key */ ++ int quoted = 0; ++ debug2("[LDAP] user_key_allowed: check options: '%s'", cp); ++ options = cp; ++ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { ++ if (*cp == '\\' && cp[1] == '"') ++ cp++; /* Skip both */ ++ else if (*cp == '"') ++ quoted = !quoted; ++ } ++ /* Skip remaining whitespace. */ ++ for (; *cp == ' ' || *cp == '\t'; cp++) ++ ; ++ if (key_read(found, &cp) != 1) { ++ debug2("[LDAP] user_key_allowed: advance: '%s'", cp); ++ /* still no key? advance to next line*/ ++ continue; ++ } ++ } ++ ++ if (key_equal(found, key) && ++ auth_parse_options(pw, options, file, linenum) == 1) { ++ found_key = 1; ++ debug("[LDAP] matching key found"); ++ fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); ++ verbose("[LDAP] Found matching %s key: %s", key_type(found), fp); ++ ++ /* restoring memory */ ++ ldap_keys_free(k); ++ xfree(fp); ++ restore_uid(); ++ key_free(found); ++ return found_key; ++ break; ++ } ++ }/* end of LDAP for() */ ++ } else { ++ logit("[LDAP] no keys found for '%s'!", pw->pw_name); ++ } ++ } else { ++ logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup); ++ } ++ } ++#endif + debug("trying public key file %s", file); + f = auth_openkeyfile(file, pw, options.strict_modes); + +diff -Nuar --exclude '*.orig' --exclude '*.rej' auth-rsa.c auth-rsa.c +--- auth-rsa.c 2008-07-02 05:37:30.000000000 -0700 ++++ auth-rsa.c 2008-08-23 15:02:47.000000000 -0700 +@@ -174,10 +174,96 @@ + FILE *f; + u_long linenum = 0; + Key *key; ++#ifdef WITH_LDAP_PUBKEY ++ ldap_key_t * k; ++ unsigned int i = 0; ++#endif + + /* Temporarily use the user's uid. */ + temporarily_use_uid(pw); + ++#ifdef WITH_LDAP_PUBKEY ++ /* here is the job */ ++ key = key_new(KEY_RSA1); ++ ++ if (options.lpk.on) { ++ debug("[LDAP] trying LDAP first uid=%s", pw->pw_name); ++ if ( ldap_ismember(&options.lpk, pw->pw_name) > 0) { ++ if ( (k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) { ++ for (i = 0 ; i < k->num ; i++) { ++ char *cp, *options = NULL; ++ ++ for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++) ++ ; ++ if (!*cp || *cp == '\n' || *cp == '#') ++ continue; ++ ++ /* ++ * Check if there are options for this key, and if so, ++ * save their starting address and skip the option part ++ * for now. If there are no options, set the starting ++ * address to NULL. ++ */ ++ if (*cp < '0' || *cp > '9') { ++ int quoted = 0; ++ options = cp; ++ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { ++ if (*cp == '\\' && cp[1] == '"') ++ cp++; /* Skip both */ ++ else if (*cp == '"') ++ quoted = !quoted; ++ } ++ } else ++ options = NULL; ++ ++ /* Parse the key from the line. */ ++ if (hostfile_read_key(&cp, &bits, key) == 0) { ++ debug("[LDAP] line %d: non ssh1 key syntax", i); ++ continue; ++ } ++ /* cp now points to the comment part. */ ++ ++ /* Check if the we have found the desired key (identified by its modulus). */ ++ if (BN_cmp(key->rsa->n, client_n) != 0) ++ continue; ++ ++ /* check the real bits */ ++ if (bits != (unsigned int)BN_num_bits(key->rsa->n)) ++ logit("[LDAP] Warning: ldap, line %lu: keysize mismatch: " ++ "actual %d vs. announced %d.", (unsigned long)i, BN_num_bits(key->rsa->n), bits); ++ ++ /* We have found the desired key. */ ++ /* ++ * If our options do not allow this key to be used, ++ * do not send challenge. ++ */ ++ if (!auth_parse_options(pw, options, "[LDAP]", (unsigned long) i)) ++ continue; ++ ++ /* break out, this key is allowed */ ++ allowed = 1; ++ ++ /* add the return stuff etc... */ ++ /* Restore the privileged uid. */ ++ restore_uid(); ++ ++ /* return key if allowed */ ++ if (allowed && rkey != NULL) ++ *rkey = key; ++ else ++ key_free(key); ++ ++ ldap_keys_free(k); ++ return (allowed); ++ } ++ } else { ++ logit("[LDAP] no keys found for '%s'!", pw->pw_name); ++ } ++ } else { ++ logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup); ++ } ++ } ++#endif + /* The authorized keys. */ + file = authorized_keys_file(pw); + debug("trying public RSA key file %s", file); +diff -Nuar --exclude '*.orig' --exclude '*.rej' config.h.in config.h.in +--- config.h.in 2008-07-21 01:30:49.000000000 -0700 ++++ config.h.in 2008-08-23 15:02:47.000000000 -0700 +@@ -560,6 +560,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_LINUX_IF_TUN_H + ++/* Define if you want LDAP support */ ++#undef WITH_LDAP_PUBKEY ++ + /* Define if your libraries define login() */ + #undef HAVE_LOGIN + +diff -Nuar --exclude '*.orig' --exclude '*.rej' configure configure +--- configure 2008-07-21 01:30:50.000000000 -0700 ++++ configure 2008-08-23 15:02:47.000000000 -0700 +@@ -1340,6 +1340,7 @@ + --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH) + --with-libedit[=PATH] Enable libedit support for sftp + --with-audit=module Enable EXPERIMENTAL audit support (modules=debug,bsm) ++ --with-ldap[=PATH] Enable LDAP pubkey support (optionally in PATH) + --with-ssl-dir=PATH Specify path to OpenSSL installation + --without-openssl-header-check Disable OpenSSL version consistency check + --with-ssl-engine Enable OpenSSL (hardware) ENGINE support +@@ -12568,6 +12569,85 @@ + fi + + ++# Check whether user wants LDAP support ++LDAP_MSG="no" ++ ++# Check whether --with-ldap was given. ++if test "${with_ldap+set}" = set; then ++ withval=$with_ldap; ++ if test "x$withval" != "xno" ; then ++ ++ if test "x$withval" != "xyes" ; then ++ CPPFLAGS="$CPPFLAGS -I${withval}/include" ++ LDFLAGS="$LDFLAGS -L${withval}/lib" ++ fi ++ ++ ++cat >>confdefs.h <<\_ACEOF ++#define WITH_LDAP_PUBKEY 1 ++_ACEOF ++ ++ LIBS="-lldap $LIBS" ++ LDAP_MSG="yes" ++ ++ { echo "$as_me:$LINENO: checking for LDAP support" >&5 ++echo $ECHO_N "checking for LDAP support... $ECHO_C" >&6; } ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++#include ++ #include ++int ++main () ++{ ++(void)ldap_init(0, 0); ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext ++if { (ac_try="$ac_compile" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 ++ (eval "$ac_compile") 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && { ++ test -z "$ac_c_werror_flag" || ++ test ! -s conftest.err ++ } && test -s conftest.$ac_objext; then ++ { echo "$as_me:$LINENO: result: yes" >&5 ++echo "${ECHO_T}yes" >&6; } ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ ++ { echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6; } ++ { { echo "$as_me:$LINENO: error: ** Incomplete or missing ldap libraries **" >&5 ++echo "$as_me: error: ** Incomplete or missing ldap libraries **" >&2;} ++ { (exit 1); exit 1; }; } ++ ++ ++fi ++ ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ fi ++ ++ ++fi ++ ++ + + + +@@ -30135,6 +30215,7 @@ + echo " Smartcard support: $SCARD_MSG" + echo " S/KEY support: $SKEY_MSG" + echo " TCP Wrappers support: $TCPW_MSG" ++echo " LDAP support: $LDAP_MSG" + echo " MD5 password support: $MD5_MSG" + echo " libedit support: $LIBEDIT_MSG" + echo " Solaris process contract support: $SPC_MSG" +diff -Nuar --exclude '*.orig' --exclude '*.rej' configure.ac configure.ac +--- configure.ac 2008-07-09 04:07:19.000000000 -0700 ++++ configure.ac 2008-08-23 15:02:47.000000000 -0700 +@@ -1299,6 +1299,37 @@ + esac ] + ) + ++# Check whether user wants LDAP support ++LDAP_MSG="no" ++AC_ARG_WITH(ldap, ++ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)], ++ [ ++ if test "x$withval" != "xno" ; then ++ ++ if test "x$withval" != "xyes" ; then ++ CPPFLAGS="$CPPFLAGS -I${withval}/include" ++ LDFLAGS="$LDFLAGS -L${withval}/lib" ++ fi ++ ++ AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support]) ++ LIBS="-lldap $LIBS" ++ LDAP_MSG="yes" ++ ++ AC_MSG_CHECKING([for LDAP support]) ++ AC_TRY_COMPILE( ++ [#include ++ #include ], ++ [(void)ldap_init(0, 0);], ++ [AC_MSG_RESULT(yes)], ++ [ ++ AC_MSG_RESULT(no) ++ AC_MSG_ERROR([** Incomplete or missing ldap libraries **]) ++ ] ++ ) ++ fi ++ ] ++) ++ + dnl Checks for library functions. Please keep in alphabetical order + AC_CHECK_FUNCS( \ + arc4random \ +@@ -4137,6 +4168,7 @@ + echo " Smartcard support: $SCARD_MSG" + echo " S/KEY support: $SKEY_MSG" + echo " TCP Wrappers support: $TCPW_MSG" ++echo " LDAP support: $LDAP_MSG" + echo " MD5 password support: $MD5_MSG" + echo " libedit support: $LIBEDIT_MSG" + echo " Solaris process contract support: $SPC_MSG" +diff -Nuar --exclude '*.orig' --exclude '*.rej' ldapauth.c ldapauth.c +--- ldapauth.c 1969-12-31 16:00:00.000000000 -0800 ++++ ldapauth.c 2008-08-23 15:02:47.000000000 -0700 +@@ -0,0 +1,575 @@ ++/* ++ * $Id: openssh-lpk-4.3p1-0.3.7.patch,v 1.3 2006/04/18 15:29:09 eau Exp $ ++ */ ++ ++/* ++ * ++ * Copyright (c) 2005, Eric AUGE ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: ++ * ++ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. ++ * 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. ++ * Neither the name of the phear.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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" ++ ++#ifdef WITH_LDAP_PUBKEY ++ ++#include ++#include ++#include ++#include ++ ++#include "ldapauth.h" ++#include "log.h" ++ ++static char *attrs[] = { ++ PUBKEYATTR, ++ NULL ++}; ++ ++/* filter building infos */ ++#define FILTER_GROUP_PREFIX "(&(objectclass=posixGroup)" ++#define FILTER_OR_PREFIX "(|" ++#define FILTER_OR_SUFFIX ")" ++#define FILTER_CN_PREFIX "(cn=" ++#define FILTER_CN_SUFFIX ")" ++#define FILTER_UID_FORMAT "(memberUid=%s)" ++#define FILTER_GROUP_SUFFIX ")" ++#define FILTER_GROUP_SIZE(group) (size_t) (strlen(group)+(ldap_count_group(group)*5)+52) ++ ++/* just filter building stuff */ ++#define REQUEST_GROUP_SIZE(filter, uid) (size_t) (strlen(filter)+strlen(uid)+1) ++#define REQUEST_GROUP(buffer, prefilter, pwname) \ ++ buffer = (char *) calloc(REQUEST_GROUP_SIZE(prefilter, pwname), sizeof(char)); \ ++ if (!buffer) { \ ++ perror("calloc()"); \ ++ return FAILURE; \ ++ } \ ++ snprintf(buffer, REQUEST_GROUP_SIZE(prefilter,pwname), prefilter, pwname) ++/* ++XXX OLD group building macros ++#define REQUEST_GROUP_SIZE(grp, uid) (size_t) (strlen(grp)+strlen(uid)+46) ++#define REQUEST_GROUP(buffer,pwname,grp) \ ++ buffer = (char *) calloc(REQUEST_GROUP_SIZE(grp, pwname), sizeof(char)); \ ++ if (!buffer) { \ ++ perror("calloc()"); \ ++ return FAILURE; \ ++ } \ ++ snprintf(buffer,REQUEST_GROUP_SIZE(grp,pwname),"(&(objectclass=posixGroup)(cn=%s)(memberUid=%s))",grp,pwname) ++ */ ++ ++/* ++XXX stock upstream version without extra filter support ++#define REQUEST_USER_SIZE(uid) (size_t) (strlen(uid)+64) ++#define REQUEST_USER(buffer, pwname) \ ++ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname), sizeof(char)); \ ++ if (!buffer) { \ ++ perror("calloc()"); \ ++ return NULL; \ ++ } \ ++ snprintf(buffer,REQUEST_USER_SIZE(pwname),"(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s))",pwname) ++ */ ++ ++#define REQUEST_USER_SIZE(uid, filter) (size_t) (strlen(uid)+64+(filter != NULL ? strlen(filter) : 0)) ++#define REQUEST_USER(buffer, pwname, customfilter) \ ++ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname, customfilter), sizeof(char)); \ ++ if (!buffer) { \ ++ perror("calloc()"); \ ++ return NULL; \ ++ } \ ++ snprintf(buffer, REQUEST_USER_SIZE(pwname, customfilter), \ ++ "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)", \ ++ pwname, (customfilter != NULL ? customfilter : "")) ++ ++/* some portable and working tokenizer, lame though */ ++static int tokenize(char ** o, size_t size, char * input) { ++ unsigned int i = 0, num; ++ const char * charset = " \t"; ++ char * ptr = input; ++ ++ /* leading white spaces are ignored */ ++ num = strspn(ptr, charset); ++ ptr += num; ++ ++ while ((num = strcspn(ptr, charset))) { ++ if (i < size-1) { ++ o[i++] = ptr; ++ ptr += num; ++ if (*ptr) ++ *ptr++ = '\0'; ++ } ++ } ++ o[i] = NULL; ++ return SUCCESS; ++} ++ ++void ldap_close(ldap_opt_t * ldap) { ++ ++ if (!ldap) ++ return; ++ ++ if ( ldap_unbind_ext(ldap->ld, NULL, NULL) < 0) ++ ldap_perror(ldap->ld, "ldap_unbind()"); ++ ++ ldap->ld = NULL; ++ FLAG_SET_DISCONNECTED(ldap->flags); ++ ++ return; ++} ++ ++/* init && bind */ ++int ldap_connect(ldap_opt_t * ldap) { ++ int version = LDAP_VERSION3; ++ ++ if (!ldap->servers) ++ return FAILURE; ++ ++ /* Connection Init and setup */ ++ ldap->ld = ldap_init(ldap->servers, LDAP_PORT); ++ if (!ldap->ld) { ++ ldap_perror(ldap->ld, "ldap_init()"); ++ return FAILURE; ++ } ++ ++ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) { ++ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)"); ++ return FAILURE; ++ } ++ ++ /* Timeouts setup */ ++ if (ldap_set_option(ldap->ld, LDAP_OPT_NETWORK_TIMEOUT, &ldap->b_timeout) != LDAP_SUCCESS) { ++ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT)"); ++ } ++ if (ldap_set_option(ldap->ld, LDAP_OPT_TIMEOUT, &ldap->s_timeout) != LDAP_SUCCESS) { ++ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_TIMEOUT)"); ++ } ++ ++ /* TLS support */ ++ if ( (ldap->tls == -1) || (ldap->tls == 1) ) { ++ if (ldap_start_tls_s(ldap->ld, NULL, NULL ) != LDAP_SUCCESS) { ++ /* failed then reinit the initial connect */ ++ ldap_perror(ldap->ld, "ldap_connect: (TLS) ldap_start_tls()"); ++ if (ldap->tls == 1) ++ return FAILURE; ++ ++ ldap->ld = ldap_init(ldap->servers, LDAP_PORT); ++ if (!ldap->ld) { ++ ldap_perror(ldap->ld, "ldap_init()"); ++ return FAILURE; ++ } ++ ++ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) { ++ ldap_perror(ldap->ld, "ldap_set_option()"); ++ return FAILURE; ++ } ++ } ++ } ++ ++ ++ if ( ldap_simple_bind_s(ldap->ld, ldap->binddn, ldap->bindpw) != LDAP_SUCCESS) { ++ ldap_perror(ldap->ld, "ldap_simple_bind_s()"); ++ return FAILURE; ++ } ++ ++ /* says it is connected */ ++ FLAG_SET_CONNECTED(ldap->flags); ++ ++ return SUCCESS; ++} ++ ++/* must free allocated ressource */ ++static char * ldap_build_host(char *host, int port) { ++ unsigned int size = strlen(host)+11; ++ char * h = (char *) calloc (size, sizeof(char)); ++ int rc; ++ if (!h) ++ return NULL; ++ ++ rc = snprintf(h, size, "%s:%d ", host, port); ++ if (rc == -1) ++ return NULL; ++ return h; ++} ++ ++static int ldap_count_group(const char * input) { ++ const char * charset = " \t"; ++ const char * ptr = input; ++ unsigned int count = 0; ++ unsigned int num; ++ ++ num = strspn(ptr, charset); ++ ptr += num; ++ ++ while ((num = strcspn(ptr, charset))) { ++ count++; ++ ptr += num; ++ ptr++; ++ } ++ ++ return count; ++} ++ ++/* format filter */ ++char * ldap_parse_groups(const char * groups) { ++ unsigned int buffer_size = FILTER_GROUP_SIZE(groups); ++ char * buffer = (char *) calloc(buffer_size, sizeof(char)); ++ char * g = NULL; ++ char * garray[32]; ++ unsigned int i = 0; ++ ++ if ((!groups)||(!buffer)) ++ return NULL; ++ ++ g = strdup(groups); ++ if (!g) { ++ free(buffer); ++ return NULL; ++ } ++ ++ /* first separate into n tokens */ ++ if ( tokenize(garray, sizeof(garray)/sizeof(*garray), g) < 0) { ++ free(g); ++ free(buffer); ++ return NULL; ++ } ++ ++ /* build the final filter format */ ++ strlcat(buffer, FILTER_GROUP_PREFIX, buffer_size); ++ strlcat(buffer, FILTER_OR_PREFIX, buffer_size); ++ i = 0; ++ while (garray[i]) { ++ strlcat(buffer, FILTER_CN_PREFIX, buffer_size); ++ strlcat(buffer, garray[i], buffer_size); ++ strlcat(buffer, FILTER_CN_SUFFIX, buffer_size); ++ i++; ++ } ++ strlcat(buffer, FILTER_OR_SUFFIX, buffer_size); ++ strlcat(buffer, FILTER_UID_FORMAT, buffer_size); ++ strlcat(buffer, FILTER_GROUP_SUFFIX, buffer_size); ++ ++ free(g); ++ return buffer; ++} ++ ++/* a bit dirty but leak free */ ++char * ldap_parse_servers(const char * servers) { ++ char * s = NULL; ++ char * tmp = NULL, *urls[32]; ++ unsigned int num = 0 , i = 0 , asize = 0; ++ LDAPURLDesc *urld[32]; ++ ++ if (!servers) ++ return NULL; ++ ++ /* local copy of the arg */ ++ s = strdup(servers); ++ if (!s) ++ return NULL; ++ ++ /* first separate into URL tokens */ ++ if ( tokenize(urls, sizeof(urls)/sizeof(*urls), s) < 0) ++ return NULL; ++ ++ i = 0; ++ while (urls[i]) { ++ if (! ldap_is_ldap_url(urls[i]) || ++ (ldap_url_parse(urls[i], &urld[i]) != 0)) { ++ return NULL; ++ } ++ i++; ++ } ++ ++ /* now free(s) */ ++ free (s); ++ ++ /* how much memory do we need */ ++ num = i; ++ for (i = 0 ; i < num ; i++) ++ asize += strlen(urld[i]->lud_host)+11; ++ ++ /* alloc */ ++ s = (char *) calloc( asize+1 , sizeof(char)); ++ if (!s) { ++ for (i = 0 ; i < num ; i++) ++ ldap_free_urldesc(urld[i]); ++ return NULL; ++ } ++ ++ /* then build the final host string */ ++ for (i = 0 ; i < num ; i++) { ++ /* built host part */ ++ tmp = ldap_build_host(urld[i]->lud_host, urld[i]->lud_port); ++ strncat(s, tmp, strlen(tmp)); ++ ldap_free_urldesc(urld[i]); ++ free(tmp); ++ } ++ ++ return s; ++} ++ ++void ldap_options_print(ldap_opt_t * ldap) { ++ debug("ldap options:"); ++ debug("servers: %s", ldap->servers); ++ if (ldap->u_basedn) ++ debug("user basedn: %s", ldap->u_basedn); ++ if (ldap->g_basedn) ++ debug("group basedn: %s", ldap->g_basedn); ++ if (ldap->binddn) ++ debug("binddn: %s", ldap->binddn); ++ if (ldap->bindpw) ++ debug("bindpw: %s", ldap->bindpw); ++ if (ldap->sgroup) ++ debug("group: %s", ldap->sgroup); ++ if (ldap->filter) ++ debug("filter: %s", ldap->filter); ++} ++ ++void ldap_options_free(ldap_opt_t * l) { ++ if (!l) ++ return; ++ if (l->servers) ++ free(l->servers); ++ if (l->u_basedn) ++ free(l->u_basedn); ++ if (l->g_basedn) ++ free(l->g_basedn); ++ if (l->binddn) ++ free(l->binddn); ++ if (l->bindpw) ++ free(l->bindpw); ++ if (l->sgroup) ++ free(l->sgroup); ++ if (l->fgroup) ++ free(l->fgroup); ++ if (l->filter) ++ free(l->filter); ++ if (l->l_conf) ++ free(l->l_conf); ++ free(l); ++} ++ ++/* free keys */ ++void ldap_keys_free(ldap_key_t * k) { ++ ldap_value_free_len(k->keys); ++ free(k); ++ return; ++} ++ ++ldap_key_t * ldap_getuserkey(ldap_opt_t *l, const char * user) { ++ ldap_key_t * k = (ldap_key_t *) calloc (1, sizeof(ldap_key_t)); ++ LDAPMessage *res, *e; ++ char * filter; ++ int i; ++ ++ if ((!k) || (!l)) ++ return NULL; ++ ++ /* Am i still connected ? RETRY n times */ ++ /* XXX TODO: setup some conf value for retrying */ ++ if (!(l->flags & FLAG_CONNECTED)) ++ for (i = 0 ; i < 2 ; i++) ++ if (ldap_connect(l) == 0) ++ break; ++ ++ /* quick check for attempts to be evil */ ++ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || ++ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) ++ return NULL; ++ ++ /* build filter for LDAP request */ ++ REQUEST_USER(filter, user, l->filter); ++ ++ if ( ldap_search_st( l->ld, ++ l->u_basedn, ++ LDAP_SCOPE_SUBTREE, ++ filter, ++ attrs, 0, &l->s_timeout, &res ) != LDAP_SUCCESS) { ++ ++ ldap_perror(l->ld, "ldap_search_st()"); ++ ++ free(filter); ++ free(k); ++ ++ /* XXX error on search, timeout etc.. close ask for reconnect */ ++ ldap_close(l); ++ ++ return NULL; ++ } ++ ++ /* free */ ++ free(filter); ++ ++ /* check if any results */ ++ i = ldap_count_entries(l->ld,res); ++ if (i <= 0) { ++ ldap_msgfree(res); ++ free(k); ++ return NULL; ++ } ++ ++ if (i > 1) ++ debug("[LDAP] duplicate entries, using the FIRST entry returned"); ++ ++ e = ldap_first_entry(l->ld, res); ++ k->keys = ldap_get_values_len(l->ld, e, PUBKEYATTR); ++ k->num = ldap_count_values_len(k->keys); ++ ++ ldap_msgfree(res); ++ return k; ++} ++ ++ ++/* -1 if trouble ++ 0 if user is NOT member of current server group ++ 1 if user IS MEMBER of current server group ++ */ ++int ldap_ismember(ldap_opt_t * l, const char * user) { ++ LDAPMessage *res; ++ char * filter; ++ int i; ++ ++ if ((!l->sgroup) || !(l->g_basedn)) ++ return 1; ++ ++ /* Am i still connected ? RETRY n times */ ++ /* XXX TODO: setup some conf value for retrying */ ++ if (!(l->flags & FLAG_CONNECTED)) ++ for (i = 0 ; i < 2 ; i++) ++ if (ldap_connect(l) == 0) ++ break; ++ ++ /* quick check for attempts to be evil */ ++ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || ++ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) ++ return FAILURE; ++ ++ /* build filter for LDAP request */ ++ REQUEST_GROUP(filter, l->fgroup, user); ++ ++ if (ldap_search_st( l->ld, ++ l->g_basedn, ++ LDAP_SCOPE_SUBTREE, ++ filter, ++ NULL, 0, &l->s_timeout, &res) != LDAP_SUCCESS) { ++ ++ ldap_perror(l->ld, "ldap_search_st()"); ++ ++ free(filter); ++ ++ /* XXX error on search, timeout etc.. close ask for reconnect */ ++ ldap_close(l); ++ ++ return FAILURE; ++ } ++ ++ free(filter); ++ ++ /* check if any results */ ++ if (ldap_count_entries(l->ld, res) > 0) { ++ ldap_msgfree(res); ++ return 1; ++ } ++ ++ ldap_msgfree(res); ++ return 0; ++} ++ ++/* ++ * ldap.conf simple parser ++ * XXX TODO: sanity checks ++ * must either ++ * - free the previous ldap_opt_before replacing entries ++ * - free each necessary previously parsed elements ++ * ret: ++ * -1 on FAILURE, 0 on SUCCESS ++ */ ++int ldap_parse_lconf(ldap_opt_t * l) { ++ FILE * lcd; /* ldap.conf descriptor */ ++ char buf[BUFSIZ]; ++ char * s = NULL, * k = NULL, * v = NULL; ++ int li, len; ++ ++ lcd = fopen (l->l_conf, "r"); ++ if (lcd == NULL) { ++ /* debug("Cannot open %s", l->l_conf); */ ++ perror("ldap_parse_lconf()"); ++ return FAILURE; ++ } ++ ++ while (fgets (buf, sizeof (buf), lcd) != NULL) { ++ ++ if (*buf == '\n' || *buf == '#') ++ continue; ++ ++ k = buf; ++ v = k; ++ while (*v != '\0' && *v != ' ' && *v != '\t') ++ v++; ++ ++ if (*v == '\0') ++ continue; ++ ++ *(v++) = '\0'; ++ ++ while (*v == ' ' || *v == '\t') ++ v++; ++ ++ li = strlen (v) - 1; ++ while (v[li] == ' ' || v[li] == '\t' || v[li] == '\n') ++ --li; ++ v[li + 1] = '\0'; ++ ++ if (!strcasecmp (k, "uri")) { ++ if ((l->servers = ldap_parse_servers(v)) == NULL) { ++ fatal("error in ldap servers"); ++ return FAILURE; ++ } ++ ++ } ++ else if (!strcasecmp (k, "base")) { ++ s = strchr (v, '?'); ++ if (s != NULL) { ++ len = s - v; ++ l->u_basedn = malloc (len + 1); ++ strncpy (l->u_basedn, v, len); ++ l->u_basedn[len] = '\0'; ++ } else { ++ l->u_basedn = strdup (v); ++ } ++ } ++ else if (!strcasecmp (k, "binddn")) { ++ l->binddn = strdup (v); ++ } ++ else if (!strcasecmp (k, "bindpw")) { ++ l->bindpw = strdup (v); ++ } ++ else if (!strcasecmp (k, "timelimit")) { ++ l->s_timeout.tv_sec = atoi (v); ++ } ++ else if (!strcasecmp (k, "bind_timelimit")) { ++ l->b_timeout.tv_sec = atoi (v); ++ } ++ else if (!strcasecmp (k, "ssl")) { ++ if (!strcasecmp (v, "start_tls")) ++ l->tls = 1; ++ } ++ } ++ ++ fclose (lcd); ++ return SUCCESS; ++} ++ ++#endif /* WITH_LDAP_PUBKEY */ +diff -Nuar --exclude '*.orig' --exclude '*.rej' ldapauth.h ldapauth.h +--- ldapauth.h 1969-12-31 16:00:00.000000000 -0800 ++++ ldapauth.h 2008-08-23 15:02:47.000000000 -0700 +@@ -0,0 +1,124 @@ ++/* ++ * $Id: openssh-lpk-4.3p1-0.3.7.patch,v 1.3 2006/04/18 15:29:09 eau Exp $ ++ */ ++ ++/* ++ * ++ * Copyright (c) 2005, Eric AUGE ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: ++ * ++ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. ++ * 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. ++ * Neither the name of the phear.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 LDAPAUTH_H ++#define LDAPAUTH_H ++ ++#define LDAP_DEPRECATED 1 ++ ++#include ++#include ++#include ++#include ++ ++/* tokens in use for config */ ++#define _DEFAULT_LPK_TOKEN "UseLPK" ++#define _DEFAULT_SRV_TOKEN "LpkServers" ++#define _DEFAULT_USR_TOKEN "LpkUserDN" ++#define _DEFAULT_GRP_TOKEN "LpkGroupDN" ++#define _DEFAULT_BDN_TOKEN "LpkBindDN" ++#define _DEFAULT_BPW_TOKEN "LpkBindPw" ++#define _DEFAULT_MYG_TOKEN "LpkServerGroup" ++#define _DEFAULT_FIL_TOKEN "LpkFilter" ++#define _DEFAULT_TLS_TOKEN "LpkForceTLS" ++#define _DEFAULT_BTI_TOKEN "LpkBindTimelimit" ++#define _DEFAULT_STI_TOKEN "LpkSearchTimelimit" ++#define _DEFAULT_LDP_TOKEN "LpkLdapConf" ++ ++/* default options */ ++#define _DEFAULT_LPK_ON 0 ++#define _DEFAULT_LPK_SERVERS NULL ++#define _DEFAULT_LPK_UDN NULL ++#define _DEFAULT_LPK_GDN NULL ++#define _DEFAULT_LPK_BINDDN NULL ++#define _DEFAULT_LPK_BINDPW NULL ++#define _DEFAULT_LPK_SGROUP NULL ++#define _DEFAULT_LPK_FILTER NULL ++#define _DEFAULT_LPK_TLS -1 ++#define _DEFAULT_LPK_BTIMEOUT 10 ++#define _DEFAULT_LPK_STIMEOUT 10 ++#define _DEFAULT_LPK_LDP NULL ++ ++/* flags */ ++#define FLAG_EMPTY 0x00000000 ++#define FLAG_CONNECTED 0x00000001 ++ ++/* flag macros */ ++#define FLAG_SET_EMPTY(x) x&=(FLAG_EMPTY) ++#define FLAG_SET_CONNECTED(x) x|=(FLAG_CONNECTED) ++#define FLAG_SET_DISCONNECTED(x) x&=~(FLAG_CONNECTED) ++ ++/* defines */ ++#define FAILURE -1 ++#define SUCCESS 0 ++#define PUBKEYATTR "sshPublicKey" ++ ++/* ++ * ++ * defined files path ++ * (should be relocated to pathnames.h, ++ * if one day it's included within the tree) ++ * ++ */ ++#define _PATH_LDAP_CONFIG_FILE "/etc/ldap.conf" ++ ++/* structures */ ++typedef struct ldap_options { ++ int on; /* Use it or NOT */ ++ LDAP * ld; /* LDAP file desc */ ++ char * servers; /* parsed servers for ldaplib failover handling */ ++ char * u_basedn; /* user basedn */ ++ char * g_basedn; /* group basedn */ ++ char * binddn; /* binddn */ ++ char * bindpw; /* bind password */ ++ char * sgroup; /* server group */ ++ char * fgroup; /* group filter */ ++ char * filter; /* additional filter */ ++ char * l_conf; /* use ldap.conf */ ++ int tls; /* TLS only */ ++ struct timeval b_timeout; /* bind timeout */ ++ struct timeval s_timeout; /* search timeout */ ++ unsigned int flags; /* misc flags (reconnection, future use?) */ ++} ldap_opt_t; ++ ++typedef struct ldap_keys { ++ struct berval ** keys; /* the public keys retrieved */ ++ unsigned int num; /* number of keys */ ++} ldap_key_t; ++ ++ ++/* function headers */ ++void ldap_close(ldap_opt_t *); ++int ldap_connect(ldap_opt_t *); ++char * ldap_parse_groups(const char *); ++char * ldap_parse_servers(const char *); ++void ldap_options_print(ldap_opt_t *); ++void ldap_options_free(ldap_opt_t *); ++void ldap_keys_free(ldap_key_t *); ++int ldap_parse_lconf(ldap_opt_t *); ++ldap_key_t * ldap_getuserkey(ldap_opt_t *, const char *); ++int ldap_ismember(ldap_opt_t *, const char *); ++ ++#endif +diff -Nuar --exclude '*.orig' --exclude '*.rej' lpk-user-example.txt lpk-user-example.txt +--- lpk-user-example.txt 1969-12-31 16:00:00.000000000 -0800 ++++ lpk-user-example.txt 2008-08-23 15:02:47.000000000 -0700 +@@ -0,0 +1,117 @@ ++ ++Post to ML -> User Made Quick Install Doc. ++Contribution from John Lane ++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ ++OpenSSH LDAP keystore Patch ++=========================== ++ ++NOTE: these notes are a transcript of a specific installation ++ they work for me, your specifics may be different! ++ from John Lane March 17th 2005 john@lane.uk.net ++ ++This is a patch to OpenSSH 4.0p1 to allow it to obtain users' public keys ++from their LDAP record as an alternative to ~/.ssh/authorized_keys. ++ ++(Assuming here that necessary build stuff is in $BUILD) ++ ++cd $BUILD/openssh-4.0p1 ++patch -Np1 -i $BUILD/openssh-lpk-4.0p1-0.3.patch ++mkdir -p /var/empty && ++./configure --prefix=/usr --sysconfdir=/etc/ssh \ ++ --libexecdir=/usr/sbin --with-md5-passwords --with-pam \ ++ --with-libs="-lldap" --with-cppflags="-DWITH_LDAP_PUBKEY" ++Now do. ++make && ++make install ++ ++Add the following config to /etc/ssh/ssh_config ++UseLPK yes ++LpkServers ldap://myhost.mydomain.com ++LpkUserDN ou=People,dc=mydomain,dc=com ++ ++We need to tell sshd about the SSL keys during boot, as root's ++environment does not exist at that time. Edit /etc/rc.d/init.d/sshd. ++Change the startup code from this: ++ echo "Starting SSH Server..." ++ loadproc /usr/sbin/sshd ++ ;; ++to this: ++ echo "Starting SSH Server..." ++ LDAPRC="/root/.ldaprc" loadproc /usr/sbin/sshd ++ ;; ++ ++Re-start the sshd daemon: ++/etc/rc.d/init.d/sshd restart ++ ++Install the additional LDAP schema ++cp $BUILD/openssh-lpk-0.2.schema /etc/openldap/schema/openssh.schema ++ ++Now add the openSSH LDAP schema to /etc/openldap/slapd.conf: ++Add the following to the end of the existing block of schema includes ++include /etc/openldap/schema/openssh.schema ++ ++Re-start the LDAP server: ++/etc/rc.d/init.d/slapd restart ++ ++To add one or more public keys to a user, eg "testuser" : ++ldapsearch -x -W -Z -LLL -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D ++"uid=testuser,ou=People,dc=mydomain,dc=com" > /tmp/testuser ++ ++append the following to this /tmp/testuser file ++objectclass: ldapPublicKey ++sshPublicKey: ssh-rsa ++AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KS ++qIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z8XwSsuAoR1t86t+5dlI ++7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key ++ ++Then do a modify: ++ldapmodify -x -D "uid=testuser,ou=People,dc=mydomain,dc=com" -W -f ++/tmp/testuser -Z ++Enter LDAP Password: ++modifying entry "uid=testuser,ou=People,dc=mydomain,dc=com" ++And check the modify is ok: ++ldapsearch -x -W -Z -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D ++"uid=testuser,ou=People,dc=mydomain,dc=com" ++Enter LDAP Password: ++# extended LDIF ++# ++# LDAPv3 ++# base with scope sub ++# filter: (objectclass=*) ++# requesting: ALL ++# ++ ++# testuser, People, mydomain.com ++dn: uid=testuser,ou=People,dc=mydomain,dc=com ++uid: testuser ++cn: testuser ++objectClass: account ++objectClass: posixAccount ++objectClass: top ++objectClass: shadowAccount ++objectClass: ldapPublicKey ++shadowLastChange: 12757 ++shadowMax: 99999 ++shadowWarning: 7 ++loginShell: /bin/bash ++uidNumber: 9999 ++gidNumber: 501 ++homeDirectory: /home/testuser ++userPassword:: e1NTSEF9UDgwV1hnM1VjUDRJK0k1YnFiL1d4ZUJObXlZZ3Z3UTU= ++sshPublicKey: ssh-rsa ++AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KSqIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z ++8XwSsuAoR1t86t+5dlI7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key ++ ++# search result ++search: 3 ++result: 0 Success ++ ++# numResponses: 2 ++# numEntries: 1 ++ ++Now start a ssh session to user "testuser" from usual ssh client (e.g. ++puTTY). Login should succeed. ++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +diff -Nuar --exclude '*.orig' --exclude '*.rej' Makefile.in Makefile.in +--- Makefile.in 2008-07-08 07:21:12.000000000 -0700 ++++ Makefile.in 2008-08-23 15:02:47.000000000 -0700 +@@ -86,7 +86,7 @@ + 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 \ +- audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o ++ audit.o audit-bsm.o platform.o ldapauth.o sftp-server.o sftp-common.o + + MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out + MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5 +diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-lpk_openldap.schema openssh-lpk_openldap.schema +--- openssh-lpk_openldap.schema 1969-12-31 16:00:00.000000000 -0800 ++++ openssh-lpk_openldap.schema 2008-08-23 15:02:47.000000000 -0700 +@@ -0,0 +1,19 @@ ++# ++# LDAP Public Key Patch schema for use with openssh-ldappubkey ++# Author: Eric AUGE ++# ++# Based on the proposal of : Mark Ruijter ++# ++ ++ ++# octetString SYNTAX ++attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' ++ DESC 'MANDATORY: OpenSSH Public key' ++ EQUALITY octetStringMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) ++ ++# printableString SYNTAX yes|no ++objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY ++ DESC 'MANDATORY: OpenSSH LPK objectclass' ++ MUST ( sshPublicKey $ uid ) ++ ) +diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-lpk_sun.schema openssh-lpk_sun.schema +--- openssh-lpk_sun.schema 1969-12-31 16:00:00.000000000 -0800 ++++ openssh-lpk_sun.schema 2008-08-23 15:02:47.000000000 -0700 +@@ -0,0 +1,21 @@ ++# ++# LDAP Public Key Patch schema for use with openssh-ldappubkey ++# Author: Eric AUGE ++# ++# Schema for Sun Directory Server. ++# Based on the original schema, modified by Stefan Fischer. ++# ++ ++dn: cn=schema ++ ++# octetString SYNTAX ++attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' ++ DESC 'MANDATORY: OpenSSH Public key' ++ EQUALITY octetStringMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) ++ ++# printableString SYNTAX yes|no ++objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY ++ DESC 'MANDATORY: OpenSSH LPK objectclass' ++ MUST ( sshPublicKey $ uid ) ++ ) +diff -Nuar --exclude '*.orig' --exclude '*.rej' README.lpk README.lpk +--- README.lpk 1969-12-31 16:00:00.000000000 -0800 ++++ README.lpk 2008-08-23 15:02:47.000000000 -0700 +@@ -0,0 +1,267 @@ ++OpenSSH LDAP PUBLIC KEY PATCH ++Copyright (c) 2003 Eric AUGE (eau@phear.org) ++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. ++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. ++ ++purposes of this patch: ++ ++This patch would help to have authentication centralization policy ++using ssh public key authentication. ++This patch could be an alternative to other "secure" authentication system ++working in a similar way (Kerberos, SecurID, etc...), except the fact ++that it's based on OpenSSH and its public key abilities. ++ ++>> FYI: << ++'uid': means unix accounts existing on the current server ++'lpkServerGroup:' mean server group configured on the current server ('lpkServerGroup' in sshd_config) ++ ++example schema: ++ ++ ++ server1 (uid: eau,rival,toto) (lpkServerGroup: unix) ++ ___________ / ++ / \ --- - server3 (uid: eau, titi) (lpkServerGroup: unix) ++ | LDAP Server | \ ++ | eau ,rival | server2 (uid: rival, eau) (lpkServerGroup: unix) ++ | titi ,toto | ++ | userx,.... | server5 (uid: eau) (lpkServerGroup: mail) ++ \___________/ \ / ++ ----- - server4 (uid: eau, rival) (no group configured) ++ \ ++ etc... ++ ++- WHAT WE NEED : ++ ++ * configured LDAP server somewhere on the network (i.e. OpenLDAP) ++ * patched sshd (with this patch ;) ++ * LDAP user(/group) entry (look at users.ldif (& groups.ldif)): ++ User entry: ++ - attached to the 'ldapPublicKey' objectclass ++ - attached to the 'posixAccount' objectclass ++ - with a filled 'sshPublicKey' attribute ++ Example: ++ dn: uid=eau,ou=users,dc=cuckoos,dc=net ++ objectclass: top ++ objectclass: person ++ objectclass: organizationalPerson ++ objectclass: posixAccount ++ objectclass: ldapPublicKey ++ description: Eric AUGE Account ++ userPassword: blah ++ cn: Eric AUGE ++ sn: Eric AUGE ++ uid: eau ++ uidNumber: 1034 ++ gidNumber: 1 ++ homeDirectory: /export/home/eau ++ sshPublicKey: ssh-dss AAAAB3... ++ sshPublicKey: ssh-dss AAAAM5... ++ ++ Group entry: ++ - attached to the 'posixGroup' objectclass ++ - with a 'cn' groupname attribute ++ - with multiple 'memberUid' attributes filled with usernames allowed in this group ++ Example: ++ # few members ++ dn: cn=unix,ou=groups,dc=cuckoos,dc=net ++ objectclass: top ++ objectclass: posixGroup ++ description: Unix based servers group ++ cn: unix ++ gidNumber: 1002 ++ memberUid: eau ++ memberUid: user1 ++ memberUid: user2 ++ ++ ++- HOW IT WORKS : ++ ++ * without patch ++ If a user wants to authenticate to log in a server the sshd, will first look for authentication method allowed (RSAauth,kerberos,etc..) ++ and if RSAauth and tickets based auth fails, it will fallback to standard password authentication (if enabled). ++ ++ * with the patch ++ If a user want to authenticate to log in a server, the sshd will first look for auth method including LDAP pubkey, if the ldappubkey options is enabled. ++ It will do an ldapsearch to get the public key directly from the LDAP instead of reading it from the server filesystem. ++ (usually in $HOME/.ssh/authorized_keys) ++ ++ If groups are enabled, it will also check if the user that wants to login is in the group of the server he is trying to log into. ++ If it fails, it falls back on RSA auth files ($HOME/.ssh/authorized_keys), etc.. and finally to standard password authentication (if enabled). ++ ++ 7 tokens are added to sshd_config : ++ # here is the new patched ldap related tokens ++ # entries in your LDAP must be posixAccount & strongAuthenticationUser & posixGroup ++ UseLPK yes # look the pub key into LDAP ++ LpkServers ldap://10.31.32.5/ ldap://10.31.32.4 ldap://10.31.32.3 # which LDAP server for users ? (URL format) ++ LpkUserDN ou=users,dc=foobar,dc=net # which base DN for users ? ++ LpkGroupDN ou=groups,dc=foobar,dc=net # which base DN for groups ? ++ LpkBindDN cn=manager,dc=foobar,dc=net # which bind DN ? ++ LpkBindPw asecret # bind DN credidentials ++ LpkServerGroup agroupname # the group the server is part of ++ ++ Right now i'm using anonymous binding to get public keys, because getting public keys of someone doesn't impersonate him¸ but there is some ++ flaws you have to take care of. ++ ++- HOW TO INSERT A USER/KEY INTO AN LDAP ENTRY ++ ++ * my way (there is plenty :) ++ - create ldif file (i.e. users.ldif) ++ - cat ~/.ssh/id_dsa.pub OR cat ~/.ssh/id_rsa.pub OR cat ~/.ssh/identity.pub ++ - my way in 4 steps : ++ Example: ++ ++ # you add this to the user entry in the LDIF file : ++ [...] ++ objectclass: posixAccount ++ objectclass: ldapPublicKey ++ [...] ++ sshPubliKey: ssh-dss AAAABDh12DDUR2... ++ [...] ++ ++ # insert your entry and you're done :) ++ ldapadd -D balblabla -w bleh < file.ldif ++ ++ all standard options can be present in the 'sshPublicKey' attribute. ++ ++- WHY : ++ ++ Simply because, i was looking for a way to centralize all sysadmins authentication, easily, without completely using LDAP ++ as authentication method (like pam_ldap etc..). ++ ++ After looking into Kerberos, SecurID, and other centralized secure authentications systems, the use of RSA and LDAP to get ++ public key for authentication allows us to control who has access to which server (the user needs an account and to be in 'strongAuthenticationUser' ++ objectclass within LDAP and part of the group the SSH server is in). ++ ++ Passwords update are no longer a nightmare for a server farm (key pair passphrase is stored on each user's box and private key is locally encrypted using his passphrase ++ so each user can change it as much as he wants). ++ ++ Blocking a user account can be done directly from the LDAP (if sshd is using RSAAuth + ldap only). ++ ++- RULES : ++ Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' which are defined in core.schema. ++ and the additionnal lpk.schema. ++ ++ This patch could allow a smooth transition between standard auth (/etc/passwd) and complete LDAP based authentication ++ (pamldap, nss_ldap, etc..). ++ ++ This can be an alternative to other (old?/expensive?) authentication methods (Kerberos/SecurID/..). ++ ++ Referring to schema at the beginning of this file if user 'eau' is only in group 'unix' ++ 'eau' would ONLY access 'server1', 'server2', 'server3' AND 'server4' BUT NOT 'server5'. ++ If you then modify the LDAP 'mail' group entry to add 'memberUid: eau' THEN user 'eau' would be able ++ to log in 'server5' (i hope you got the idea, my english is bad :). ++ ++ Each server's sshd is patched and configured to ask the public key and the group infos in the LDAP ++ server. ++ When you want to allow a new user to have access to the server parc, you just add him an account on ++ your servers, you add his public key into his entry on the LDAP server, it's done. ++ ++ Because sshds are looking public keys into the LDAP directly instead of a file ($HOME/.ssh/authorized_keys). ++ ++ When the user needs to change his passphrase he can do it directly from his workstation by changing ++ his own key set lock passphrase, and all servers are automatically aware. ++ ++ With a CAREFUL LDAP server configuration you could allow a user to add/delete/modify his own entry himself ++ so he can add/modify/delete himself his public key when needed. ++ ++­ FLAWS : ++ LDAP must be well configured, getting the public key of some user is not a problem, but if anonymous LDAP ++ allow write to users dn, somebody could replace someuser's public key by its own and impersonate some ++ of your users in all your server farm be VERY CAREFUL. ++ ++ MITM attack when sshd is requesting the public key, could lead to a compromise of your servers allowing login ++ as the impersonnated user. ++ ++ If LDAP server is down then, fallback on passwd auth. ++ ++ the ldap code part has not been well audited yet. ++ ++- LDAP USER ENTRY EXAMPLES (LDIF Format, look in users.ldif) ++ --- CUT HERE --- ++ dn: uid=jdoe,ou=users,dc=foobar,dc=net ++ objectclass: top ++ objectclass: person ++ objectclass: organizationalPerson ++ objectclass: posixAccount ++ objectclass: ldapPublicKey ++ description: My account ++ cn: John Doe ++ sn: John Doe ++ uid: jdoe ++ uidNumber: 100 ++ gidNumber: 100 ++ homeDirectory: /home/jdoe ++ sshPublicKey: ssh-dss AAAAB3NzaC1kc3MAAAEBAOvL8pREUg9wSy/8+hQJ54YF3AXkB0OZrXB.... ++ [...] ++ --- CUT HERE --- ++ ++- LDAP GROUP ENTRY EXAMPLES (LDIF Format, look in groups.ldif) ++ --- CUT HERE --- ++ dn: cn=unix,ou=groups,dc=cuckoos,dc=net ++ objectclass: top ++ objectclass: posixGroup ++ description: Unix based servers group ++ cn: unix ++ gidNumber: 1002 ++ memberUid: jdoe ++ memberUid: user1 ++ memberUid: user2 ++ [...] ++ --- CUT HERE --- ++ ++>> FYI: << ++Multiple 'sshPublicKey' in a user entry are allowed, as well as multiple 'memberUid' attributes in a group entry ++ ++- COMPILING: ++ 1. Apply the patch ++ 2. ./configure --with-your-options --with-ldap=/prefix/to/ldap_libs_and_includes ++ 3. make ++ 4. it's done. ++ ++- BLA : ++ I hope this could help, and i hope to be clear enough,, or give ideas. questions/comments/improvements are welcome. ++ ++- TODO : ++ Redesign differently. ++ ++- DOCS/LINK : ++ http://pacsec.jp/core05/psj05-barisani-en.pdf ++ http://fritz.potsdam.edu/projects/openssh-lpk/ ++ http://fritz.potsdam.edu/projects/sshgate/ ++ http://dev.inversepath.com/trac/openssh-lpk ++ http://lam.sf.net/ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm ) ++ ++- CONTRIBUTORS/IDEAS/GREETS : ++ - Falk Siemonsmeier. ++ - Jacob Rief. ++ - Michael Durchgraf. ++ - frederic peters. ++ - Finlay dobbie. ++ - Stefan Fisher. ++ - Robin H. Johnson. ++ - Adrian Bridgett. ++ ++- CONTACT : ++ - Eric AUGE ++ - Andrea Barisani + +diff -Nuar --exclude '*.orig' --exclude '*.rej' servconf.h servconf.h +--- servconf.h 2008-06-10 06:01:51.000000000 -0700 ++++ servconf.h 2008-08-23 15:02:47.000000000 -0700 +@@ -16,6 +16,10 @@ + #ifndef SERVCONF_H + #define SERVCONF_H + ++#ifdef WITH_LDAP_PUBKEY ++#include "ldapauth.h" ++#endif ++ + #define MAX_PORTS 256 /* Max # ports. */ + + #define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ +@@ -145,6 +149,9 @@ + int use_pam; /* Enable auth via PAM */ + + int permit_tun; ++#ifdef WITH_LDAP_PUBKEY ++ ldap_opt_t lpk; ++#endif + + int num_permitted_opens; + +diff -Nuar --exclude '*.orig' --exclude '*.rej' sshd.c sshd.c +--- sshd.c 2008-07-11 00:36:49.000000000 -0700 ++++ sshd.c 2008-08-23 15:02:47.000000000 -0700 +@@ -127,6 +127,10 @@ + int deny_severity; + #endif /* LIBWRAP */ + ++#ifdef WITH_LDAP_PUBKEY ++#include "ldapauth.h" ++#endif ++ + #ifndef O_NOCTTY + #define O_NOCTTY 0 + #endif +@@ -1484,6 +1488,16 @@ + exit(1); + } + ++#ifdef WITH_LDAP_PUBKEY ++ /* ldap_options_print(&options.lpk); */ ++ /* XXX initialize/check ldap connection and set *LD */ ++ if (options.lpk.on) { ++ if (options.lpk.l_conf && (ldap_parse_lconf(&options.lpk) < 0) ) ++ error("[LDAP] could not parse %s", options.lpk.l_conf); ++ if (ldap_connect(&options.lpk) < 0) ++ error("[LDAP] could not initialize ldap connection"); ++ } ++#endif + debug("sshd version %.100s", SSH_RELEASE); + + /* Store privilege separation user for later use if required. */ +diff -Nuar --exclude '*.orig' --exclude '*.rej' sshd_config sshd_config +--- sshd_config 2008-07-02 05:35:43.000000000 -0700 ++++ sshd_config 2008-08-23 15:02:47.000000000 -0700 +@@ -109,6 +109,21 @@ + # no default banner path + #Banner none + ++# here are the new patched ldap related tokens ++# entries in your LDAP must have posixAccount & ldapPublicKey objectclass ++#UseLPK yes ++#LpkLdapConf /etc/ldap.conf ++#LpkServers ldap://10.1.7.1/ ldap://10.1.7.2/ ++#LpkUserDN ou=users,dc=phear,dc=org ++#LpkGroupDN ou=groups,dc=phear,dc=org ++#LpkBindDN cn=Manager,dc=phear,dc=org ++#LpkBindPw secret ++#LpkServerGroup mail ++#LpkFilter (hostAccess=master.phear.org) ++#LpkForceTLS no ++#LpkSearchTimelimit 3 ++#LpkBindTimelimit 3 ++ + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + +diff -Nuar --exclude '*.orig' --exclude '*.rej' sshd_config.5 sshd_config.5 +--- sshd_config.5 2008-07-02 05:35:43.000000000 -0700 ++++ sshd_config.5 2008-08-23 15:02:47.000000000 -0700 +@@ -1003,6 +1003,62 @@ + program. + The default is + .Pa /usr/X11R6/bin/xauth . ++.It Cm UseLPK ++Specifies whether LDAP public key retrieval must be used or not. It allow ++an easy centralisation of public keys within an LDAP directory. The argument must be ++.Dq yes ++or ++.Dq no . ++.It Cm LpkLdapConf ++Specifies whether LDAP Public keys should parse the specified ldap.conf file ++instead of sshd_config Tokens. The argument must be a valid path to an ldap.conf ++file like ++.Pa /etc/ldap.conf ++.It Cm LpkServers ++Specifies LDAP one or more [:space:] separated server's url the following form may be used: ++.Pp ++LpkServers ldaps://127.0.0.1 ldap://127.0.0.2 ldap://127.0.0.3 ++.It Cm LpkUserDN ++Specifies the LDAP user DN. ++.Pp ++LpkUserDN ou=users,dc=phear,dc=org ++.It Cm LpkGroupDN ++Specifies the LDAP groups DN. ++.Pp ++LpkGroupDN ou=groups,dc=phear,dc=org ++.It Cm LpkBindDN ++Specifies the LDAP bind DN to use if necessary. ++.Pp ++LpkBindDN cn=Manager,dc=phear,dc=org ++.It Cm LpkBindPw ++Specifies the LDAP bind credential. ++.Pp ++LpkBindPw secret ++.It Cm LpkServerGroup ++Specifies one or more [:space:] separated group the server is part of. ++.Pp ++LpkServerGroup unix mail prod ++.It Cm LpkFilter ++Specifies an additional LDAP filter to use for finding SSH keys ++.Pp ++LpkFilter (hostAccess=master.phear.org) ++.It Cm LpkForceTLS ++Specifies if the LDAP server connection must be tried, forced or not used. The argument must be ++.Dq yes ++or ++.Dq no ++or ++.Dq try . ++.It Cm LpkSearchTimelimit ++Sepcifies the search time limit before the search is considered over. value is ++in seconds. ++.Pp ++LpkSearchTimelimit 3 ++.It Cm LpkBindTimelimit ++Sepcifies the bind time limit before the connection is considered dead. value is ++in seconds. ++.Pp ++LpkBindTimelimit 3 + .El + .Sh TIME FORMATS + .Xr sshd 8 diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/lpk+hpn-servconf.c.patch /usr/home/dindin/workspace/openssh-portable/files/lpk+hpn-servconf.c.patch --- /usr/ports/security/openssh-portable/files/lpk+hpn-servconf.c.patch 1970-01-01 03:00:00.000000000 +0300 +++ /usr/home/dindin/workspace/openssh-portable/files/lpk+hpn-servconf.c.patch 2009-05-26 18:10:08.000000000 +0400 @@ -0,0 +1,307 @@ +--- servconf.c.orig 2009-05-26 15:13:32.000000000 +0400 ++++ servconf.c 2009-05-26 18:09:30.000000000 +0400 +@@ -42,6 +42,10 @@ + #include "channels.h" + #include "groupaccess.h" + ++#ifdef WITH_LDAP_PUBKEY ++#include "ldapauth.h" ++#endif ++ + static void add_listen_addr(ServerOptions *, char *, int); + static void add_one_listen_addr(ServerOptions *, char *, int); + +@@ -128,11 +132,38 @@ + options->adm_forced_command = NULL; + options->chroot_directory = NULL; + options->zero_knowledge_password_authentication = -1; ++ options->none_enabled = -1; ++ options->tcp_rcv_buf_poll = -1; ++ options->hpn_disabled = -1; ++ options->hpn_buffer_size = -1; ++#ifdef WITH_LDAP_PUBKEY ++ /* XXX dirty */ ++ options->lpk.ld = NULL; ++ options->lpk.on = -1; ++ options->lpk.servers = NULL; ++ options->lpk.u_basedn = NULL; ++ options->lpk.g_basedn = NULL; ++ options->lpk.binddn = NULL; ++ options->lpk.bindpw = NULL; ++ options->lpk.sgroup = NULL; ++ options->lpk.filter = NULL; ++ options->lpk.fgroup = NULL; ++ options->lpk.l_conf = NULL; ++ options->lpk.tls = -1; ++ options->lpk.b_timeout.tv_sec = -1; ++ options->lpk.s_timeout.tv_sec = -1; ++ options->lpk.flags = FLAG_EMPTY; ++#endif + } + + void + fill_default_server_options(ServerOptions *options) + { ++ /* needed for hpn socket tests */ ++ int sock; ++ int socksize; ++ int socksizelen = sizeof(int); ++ + /* Portable-specific options */ + if (options->use_pam == -1) + options->use_pam = 1; +@@ -265,6 +296,68 @@ + options->permit_tun = SSH_TUNMODE_NO; + if (options->zero_knowledge_password_authentication == -1) + options->zero_knowledge_password_authentication = 0; ++ if (options->hpn_disabled == -1) ++ options->hpn_disabled = 0; ++ ++ if (options->hpn_buffer_size == -1) { ++ /* option not explicitly set. Now we have to figure out */ ++ /* what value to use */ ++ if (options->hpn_disabled == 1) { ++ options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; ++ } else { ++ /* get the current RCV size and set it to that */ ++ /*create a socket but don't connect it */ ++ /* we use that the get the rcv socket size */ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ options->hpn_buffer_size = socksize; ++ debug ("HPN Buffer Size: %d", options->hpn_buffer_size); ++ ++ } ++ } else { ++ /* we have to do this incase the user sets both values in a contradictory */ ++ /* manner. hpn_disabled overrrides hpn_buffer_size*/ ++ if (options->hpn_disabled <= 0) { ++ if (options->hpn_buffer_size == 0) ++ options->hpn_buffer_size = 1; ++ /* limit the maximum buffer to 64MB */ ++ if (options->hpn_buffer_size > 64*1024) { ++ options->hpn_buffer_size = 64*1024*1024; ++ } else { ++ options->hpn_buffer_size *= 1024; ++ } ++ } else ++ options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; ++ } ++ ++#ifdef WITH_LDAP_PUBKEY ++ if (options->lpk.on == -1) ++ options->lpk.on = _DEFAULT_LPK_ON; ++ if (options->lpk.servers == NULL) ++ options->lpk.servers = _DEFAULT_LPK_SERVERS; ++ if (options->lpk.u_basedn == NULL) ++ options->lpk.u_basedn = _DEFAULT_LPK_UDN; ++ if (options->lpk.g_basedn == NULL) ++ options->lpk.g_basedn = _DEFAULT_LPK_GDN; ++ if (options->lpk.binddn == NULL) ++ options->lpk.binddn = _DEFAULT_LPK_BINDDN; ++ if (options->lpk.bindpw == NULL) ++ options->lpk.bindpw = _DEFAULT_LPK_BINDPW; ++ if (options->lpk.sgroup == NULL) ++ options->lpk.sgroup = _DEFAULT_LPK_SGROUP; ++ if (options->lpk.filter == NULL) ++ options->lpk.filter = _DEFAULT_LPK_FILTER; ++ if (options->lpk.tls == -1) ++ options->lpk.tls = _DEFAULT_LPK_TLS; ++ if (options->lpk.b_timeout.tv_sec == -1) ++ options->lpk.b_timeout.tv_sec = _DEFAULT_LPK_BTIMEOUT; ++ if (options->lpk.s_timeout.tv_sec == -1) ++ options->lpk.s_timeout.tv_sec = _DEFAULT_LPK_STIMEOUT; ++ if (options->lpk.l_conf == NULL) ++ options->lpk.l_conf = _DEFAULT_LPK_LDP; ++#endif + + /* Turn privilege separation on by default */ + if (use_privsep == -1) +@@ -310,7 +403,14 @@ + sMatch, sPermitOpen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, ++ sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, + sDeprecated, sUnsupported ++#ifdef WITH_LDAP_PUBKEY ++ ,sLdapPublickey, sLdapServers, sLdapUserDN ++ ,sLdapGroupDN, sBindDN, sBindPw, sMyGroup ++ ,sLdapFilter, sForceTLS, sBindTimeout ++ ,sSearchTimeout, sLdapConf ++#endif + } ServerOpCodes; + + #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ +@@ -421,6 +521,20 @@ + { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, + { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, + { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, ++#ifdef WITH_LDAP_PUBKEY ++ { _DEFAULT_LPK_TOKEN, sLdapPublickey, SSHCFG_GLOBAL }, ++ { _DEFAULT_SRV_TOKEN, sLdapServers, SSHCFG_GLOBAL }, ++ { _DEFAULT_USR_TOKEN, sLdapUserDN, SSHCFG_GLOBAL }, ++ { _DEFAULT_GRP_TOKEN, sLdapGroupDN, SSHCFG_GLOBAL }, ++ { _DEFAULT_BDN_TOKEN, sBindDN, SSHCFG_GLOBAL }, ++ { _DEFAULT_BPW_TOKEN, sBindPw, SSHCFG_GLOBAL }, ++ { _DEFAULT_MYG_TOKEN, sMyGroup, SSHCFG_GLOBAL }, ++ { _DEFAULT_FIL_TOKEN, sLdapFilter, SSHCFG_GLOBAL }, ++ { _DEFAULT_TLS_TOKEN, sForceTLS, SSHCFG_GLOBAL }, ++ { _DEFAULT_BTI_TOKEN, sBindTimeout, SSHCFG_GLOBAL }, ++ { _DEFAULT_STI_TOKEN, sSearchTimeout, SSHCFG_GLOBAL }, ++ { _DEFAULT_LDP_TOKEN, sLdapConf, SSHCFG_GLOBAL }, ++#endif + { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, + { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, + { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL }, +@@ -428,6 +542,10 @@ + { "permitopen", sPermitOpen, SSHCFG_ALL }, + { "forcecommand", sForceCommand, SSHCFG_ALL }, + { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, ++ { "noneenabled", sNoneEnabled }, ++ { "hpndisabled", sHPNDisabled }, ++ { "hpnbuffersize", sHPNBufferSize }, ++ { "tcprcvbufpoll", sTcpRcvBufPoll }, + { NULL, sBadOption, 0 } + }; + +@@ -454,6 +572,7 @@ + + for (i = 0; keywords[i].name; i++) + if (strcasecmp(cp, keywords[i].name) == 0) { ++ debug ("Config token is %s", keywords[i].name); + *flags = keywords[i].flags; + return keywords[i].opcode; + } +@@ -851,6 +970,22 @@ + *intptr = value; + break; + ++ case sNoneEnabled: ++ intptr = &options->none_enabled; ++ goto parse_flag; ++ ++ case sTcpRcvBufPoll: ++ intptr = &options->tcp_rcv_buf_poll; ++ goto parse_flag; ++ ++ case sHPNDisabled: ++ intptr = &options->hpn_disabled; ++ goto parse_flag; ++ ++ case sHPNBufferSize: ++ intptr = &options->hpn_buffer_size; ++ goto parse_int; ++ + case sIgnoreUserKnownHosts: + intptr = &options->ignore_user_known_hosts; + goto parse_flag; +@@ -1311,6 +1446,107 @@ + while (arg) + arg = strdelim(&cp); + break; ++#ifdef WITH_LDAP_PUBKEY ++ case sLdapPublickey: ++ intptr = &options->lpk.on; ++ goto parse_flag; ++ case sLdapServers: ++ /* arg = strdelim(&cp); */ ++ p = line; ++ while(*p++); ++ arg = p; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing ldap server",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ if ((options->lpk.servers = ldap_parse_servers(arg)) == NULL) ++ fatal("%s line %d: error in ldap servers", filename, linenum); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sLdapUserDN: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing ldap server",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.u_basedn = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sLdapGroupDN: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing ldap server",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.g_basedn = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sBindDN: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing binddn",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.binddn = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sBindPw: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing bindpw",filename,linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.bindpw = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sMyGroup: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing groupname",filename, linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.sgroup = xstrdup(arg); ++ if (options->lpk.sgroup) ++ options->lpk.fgroup = ldap_parse_groups(options->lpk.sgroup); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sLdapFilter: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing filter",filename, linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.filter = xstrdup(arg); ++ memset(arg,0,strlen(arg)); ++ break; ++ case sForceTLS: ++ intptr = &options->lpk.tls; ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing yes/no argument.", ++ filename, linenum); ++ value = 0; /* silence compiler */ ++ if (strcmp(arg, "yes") == 0) ++ value = 1; ++ else if (strcmp(arg, "no") == 0) ++ value = 0; ++ else if (strcmp(arg, "try") == 0) ++ value = -1; ++ else ++ fatal("%s line %d: Bad yes/no argument: %s", ++ filename, linenum, arg); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ case sBindTimeout: ++ intptr = (int *) &options->lpk.b_timeout.tv_sec; ++ goto parse_int; ++ case sSearchTimeout: ++ intptr = (int *) &options->lpk.s_timeout.tv_sec; ++ goto parse_int; ++ break; ++ case sLdapConf: ++ arg = cp; ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing LpkLdapConf", filename, linenum); ++ arg[strlen(arg)] = '\0'; ++ options->lpk.l_conf = xstrdup(arg); ++ memset(arg, 0, strlen(arg)); ++ break; ++#endif + + default: + fatal("%s line %d: Missing handler for opcode %s (%d)", diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/openssh-5.2p1-hpn-servconf.patch /usr/home/dindin/workspace/openssh-portable/files/openssh-5.2p1-hpn-servconf.patch --- /usr/ports/security/openssh-portable/files/openssh-5.2p1-hpn-servconf.patch 2009-05-15 15:00:27.000000000 +0400 +++ /usr/home/dindin/workspace/openssh-portable/files/openssh-5.2p1-hpn-servconf.patch 1970-01-01 03:00:00.000000000 +0300 @@ -1,32 +0,0 @@ ---- servconf.c.orig 2009-05-02 18:22:38.000000000 +0400 -+++ servconf.c 2009-05-02 18:24:15.000000000 +0400 -@@ -127,12 +127,21 @@ - options->num_permitted_opens = -1; - options->adm_forced_command = NULL; - options->chroot_directory = NULL; -+ options->none_enabled = -1; -+ options->tcp_rcv_buf_poll = -1; -+ options->hpn_disabled = -1; -+ options->hpn_buffer_size = -1; - options->zero_knowledge_password_authentication = -1; - } - - void - fill_default_server_options(ServerOptions *options) - { -+ /* needed for hpn socket tests */ -+ int sock; -+ int socksize; -+ int socksizelen = sizeof(int); -+ - /* Portable-specific options */ - if (options->use_pam == -1) - options->use_pam = 1; -@@ -345,6 +354,7 @@ - sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, - sMatch, sPermitOpen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, -+ sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, - sZeroKnowledgePasswordAuthentication, - sDeprecated, sUnsupported - } ServerOpCodes; diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/openssh-5.2p1-hpn.patch /usr/home/dindin/workspace/openssh-portable/files/openssh-5.2p1-hpn.patch --- /usr/ports/security/openssh-portable/files/openssh-5.2p1-hpn.patch 2009-05-17 07:00:11.000000000 +0400 +++ /usr/home/dindin/workspace/openssh-portable/files/openssh-5.2p1-hpn.patch 1970-01-01 03:00:00.000000000 +0300 @@ -1,2196 +0,0 @@ -diff -urN HPN-README HPN-README ---- HPN-README 1970-01-01 03:00:00.000000000 +0300 -+++ HPN-README 2009-05-02 17:38:18.000000000 +0400 -@@ -0,0 +1,128 @@ -+Notes: -+ -+MULTI-THREADED CIPHER: -+The AES cipher in CTR mode has been multithreaded (MTR-AES-CTR). This will allow ssh installations -+on hosts with multiple cores to use more than one processing core during encryption. -+Tests have show significant throughput performance increases when using MTR-AES-CTR up -+to and including a full gigabit per second on quad core systems. It should be possible to -+achieve full line rate on dual core systems but OS and data management overhead makes this -+more difficult to achieve. The cipher stream from MTR-AES-CTR is entirely compatible with single -+thread AES-CTR (ST-AES-CTR) implementations and should be 100% backward compatible. Optimal -+performance requires the MTR-AES-CTR mode be enabled on both ends of the connection. -+The MTR-AES-CTR replaces ST-AES-CTR and is used in exactly the same way with the same -+nomenclature. -+Use examples: ssh -caes128-ctr you@host.com -+ scp -oCipher=aes256-ctr file you@host.com:~/file -+ -+NONE CIPHER: -+To use the NONE option you must have the NoneEnabled switch set on the server and -+you *must* have *both* NoneEnabled and NoneSwitch set to yes on the client. The NONE -+feature works with ALL ssh subsystems (as far as we can tell) *AS LONG AS* a tty is not -+spawned. If a user uses the -T switch to prevent a tty being created the NONE cipher will -+be disabled. -+ -+The performance increase will only be as good as the network and TCP stack tuning -+on the reciever side of the connection allows. As a rule of thumb a user will need -+at least 10Mb/s connection with a 100ms RTT to see a doubling of performance. The -+HPN-SSH home page describes this in greater detail. -+ -+http://www.psc.edu/networking/projects/hpn-ssh -+ -+BUFFER SIZES: -+ -+If HPN is disabled the receive buffer size will be set to the -+OpenSSH default of 64K. -+ -+If an HPN system connects to a nonHPN system the receive buffer will -+be set to the HPNBufferSize value. The default is 2MB but user adjustable. -+ -+If an HPN to HPN connection is established a number of different things might -+happen based on the user options and conditions. -+ -+Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set -+HPN Buffer Size = up to 64MB -+This is the default state. The HPN buffer size will grow to a maximum of 64MB -+as the TCP receive buffer grows. The maximum HPN Buffer size of 64MB is -+geared towards 10GigE transcontinental connections. -+ -+Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set -+HPN Buffer Size = TCP receive buffer value. -+Users on non-autotuning systesm should disable TCPRcvBufPoll in the -+ssh_cofig and sshd_config -+ -+Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set -+HPN Buffer Size = minmum of TCP receive buffer and HPNBufferSize. -+This would be the system defined TCP receive buffer (RWIN). -+ -+Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf SET -+HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. -+Generally there is no need to set both. -+ -+Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set -+HPN Buffer Size = grows to HPNBufferSize -+The buffer will grow up to the maximum size specified here. -+ -+Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf SET -+HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. -+Generally there is no need to set both of these, especially on autotuning -+systems. However, if the users wishes to override the autotuning this would be -+one way to do it. -+ -+Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf SET -+HPN Buffer Size = TCPRcvBuf. -+This will override autotuning and set the TCP recieve buffer to the user defined -+value. -+ -+ -+HPN Specific Configuration options -+ -+TcpRcvBuf=[int]KB client -+ set the TCP socket receive buffer to n Kilobytes. It can be set up to the -+maximum socket size allowed by the system. This is useful in situations where -+the tcp receive window is set low but the maximum buffer size is set -+higher (as is typical). This works on a per TCP connection basis. You can also -+use this to artifically limit the transfer rate of the connection. In these -+cases the throughput will be no more than n/RTT. The minimum buffer size is 1KB. -+Default is the current system wide tcp receive buffer size. -+ -+TcpRcvBufPoll=[yes/no] client/server -+ enable of disable the polling of the tcp receive buffer through the life -+of the connection. You would want to make sure that this option is enabled -+for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista) -+default is yes. -+ -+NoneEnabled=[yes/no] client/server -+ enable or disable the use of the None cipher. Care must always be used -+when enabling this as it will allow users to send data in the clear. However, -+it is important to note that authentication information remains encrypted -+even if this option is enabled. Set to no by default. -+ -+NoneSwitch=[yes/no] client -+ Switch the encryption cipher being used to the None cipher after -+authentication takes place. NoneEnabled must be enabled on both the client -+and server side of the connection. When the connection switches to the NONE -+cipher a warning is sent to STDERR. The connection attempt will fail with an -+error if a client requests a NoneSwitch from the server that does not explicitly -+have NoneEnabled set to yes. Note: The NONE cipher cannot be used in -+interactive (shell) sessions and it will fail silently. Set to no by default. -+ -+HPNDisabled=[yes/no] client/server -+ In some situations, such as transfers on a local area network, the impact -+of the HPN code produces a net decrease in performance. In these cases it is -+helpful to disable the HPN functionality. By default HPNDisabled is set to no. -+ -+HPNBufferSize=[int]KB client/server -+ This is the default buffer size the HPN functionality uses when interacting -+with nonHPN SSH installations. Conceptually this is similar to the TcpRcvBuf -+option as applied to the internal SSH flow control. This value can range from -+1KB to 64MB (1-65536). Use of oversized or undersized buffers can cause performance -+problems depending on the length of the network path. The default size of this buffer -+is 2MB. -+ -+ -+Credits: This patch was conceived, designed, and led by Chris Rapier (rapier@psc.edu) -+ The majority of the actual coding for versions up to HPN12v1 was performed -+ by Michael Stevens (mstevens@andrew.cmu.edu). The MT-AES-CTR cipher was -+ implemented by Ben Bennet (ben@psc.edu). This work was financed, in part, -+ by Cisco System, Inc., the National Library of Medicine, -+ and the National Science Foundation. -diff -urN Makefile.in Makefile.in ---- Makefile.in 2009-05-02 17:37:11.000000000 +0400 -+++ Makefile.in 2009-05-02 17:38:18.000000000 +0400 -@@ -43,7 +43,7 @@ - LD=@LD@ - CFLAGS=@CFLAGS@ - CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ --LIBS=@LIBS@ -+LIBS=@LIBS@ -lpthread - SSHDLIBS=@SSHDLIBS@ - LIBEDIT=@LIBEDIT@ - AR=@AR@ -@@ -64,7 +64,7 @@ - - LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ - canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ -- cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ -+ cipher-bf1.o cipher-ctr.o cipher-ctr-mt.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 \ - readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ -diff -urN auth2.c auth2.c ---- auth2.c 2009-05-02 17:37:11.000000000 +0400 -+++ auth2.c 2009-05-02 17:38:18.000000000 +0400 -@@ -50,6 +50,7 @@ - #include "dispatch.h" - #include "pathnames.h" - #include "buffer.h" -+#include "canohost.h" - - #ifdef GSSAPI - #include "ssh-gss.h" -@@ -76,6 +77,9 @@ - extern Authmethod method_jpake; - #endif - -+static int log_flag = 0; -+ -+ - Authmethod *authmethods[] = { - &method_none, - &method_pubkey, -@@ -233,6 +237,11 @@ - service = packet_get_string(NULL); - method = packet_get_string(NULL); - debug("userauth-request for user %s service %s method %s", user, service, method); -+ if (!log_flag) { -+ logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", -+ get_remote_ipaddr(), get_remote_port(), user); -+ log_flag = 1; -+ } - debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); - - if ((style = strchr(user, ':')) != NULL) -diff -urN buffer.c buffer.c ---- buffer.c 2006-08-05 06:39:39.000000000 +0400 -+++ buffer.c 2009-05-02 17:38:18.000000000 +0400 -@@ -127,7 +127,7 @@ - - /* Increase the size of the buffer and retry. */ - newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ); -- if (newlen > BUFFER_MAX_LEN) -+ if (newlen > BUFFER_MAX_LEN_HPN) - fatal("buffer_append_space: alloc %u not supported", - newlen); - buffer->buf = xrealloc(buffer->buf, 1, newlen); -diff -urN buffer.h buffer.h ---- buffer.h 2008-05-19 08:59:37.000000000 +0400 -+++ buffer.h 2009-05-02 17:38:18.000000000 +0400 -@@ -16,6 +16,9 @@ - #ifndef BUFFER_H - #define BUFFER_H - -+/* move the following to a more appropriate place and name */ -+#define BUFFER_MAX_LEN_HPN 0x4000000 /* 64MB */ -+ - typedef struct { - u_char *buf; /* Buffer for data. */ - u_int alloc; /* Number of bytes allocated for data. */ -diff -urN channels.c channels.c ---- channels.c 2009-02-14 08:28:21.000000000 +0300 -+++ channels.c 2009-05-02 17:41:46.000000000 +0400 -@@ -169,8 +169,14 @@ - static int connect_next(struct channel_connect *); - static void channel_connect_ctx_free(struct channel_connect *); - -+ -+static int hpn_disabled = 0; -+static int hpn_buffer_size = 2 * 1024 * 1024; -+ - /* -- channel core */ - -+ -+ - Channel * - channel_by_id(int id) - { -@@ -308,6 +314,7 @@ - c->local_window_max = window; - c->local_consumed = 0; - c->local_maxpacket = maxpack; -+ c->dynamic_window = 0; - c->remote_id = -1; - c->remote_name = xstrdup(remote_name); - c->remote_window = 0; -@@ -798,11 +805,35 @@ - FD_SET(c->sock, writeset); - } - -+int channel_tcpwinsz () { -+ u_int32_t tcpwinsz = 0; -+ socklen_t optsz = sizeof(tcpwinsz); -+ int ret = -1; -+ -+ /* if we aren't on a socket return 128KB*/ -+ if(!packet_connection_is_on_socket()) -+ return(128*1024); -+ ret = getsockopt(packet_get_connection_in(), -+ SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); -+ /* return no more than 64MB */ -+ if ((ret == 0) && tcpwinsz > BUFFER_MAX_LEN_HPN) -+ tcpwinsz = BUFFER_MAX_LEN_HPN; -+ debug2("tcpwinsz: %d for connection: %d", tcpwinsz, -+ packet_get_connection_in()); -+ return(tcpwinsz); -+} -+ - static void - channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) - { - u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); - -+ /* check buffer limits */ -+ if ((!c->tcpwinsz) || (c->dynamic_window > 0)) -+ c->tcpwinsz = channel_tcpwinsz(); -+ -+ limit = MIN(limit, 2 * c->tcpwinsz); -+ - if (c->istate == CHAN_INPUT_OPEN && - limit > 0 && - buffer_len(&c->input) < limit && -@@ -1759,14 +1790,21 @@ - c->local_maxpacket*3) || - c->local_window < c->local_window_max/2) && - c->local_consumed > 0) { -+ u_int addition = 0; -+ /* adjust max window size if we are in a dynamic environment */ -+ if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) { -+ /* grow the window somewhat aggressively to maintain pressure */ -+ addition = 1.5*(c->tcpwinsz - c->local_window_max); -+ c->local_window_max += addition; -+ } - packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); - packet_put_int(c->remote_id); -- packet_put_int(c->local_consumed); -+ packet_put_int(c->local_consumed + addition); - packet_send(); - debug2("channel %d: window %d sent adjust %d", - c->self, c->local_window, - c->local_consumed); -- c->local_window += c->local_consumed; -+ c->local_window += c->local_consumed + addition; - c->local_consumed = 0; - } - return 1; -@@ -1969,11 +2007,12 @@ - - - /* If there is data to send to the connection, enqueue some of it now. */ --void -+int - channel_output_poll(void) - { - Channel *c; - u_int i, len; -+ int packet_length = 0; - - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; -@@ -2013,7 +2052,7 @@ - packet_start(SSH2_MSG_CHANNEL_DATA); - packet_put_int(c->remote_id); - packet_put_string(data, dlen); -- packet_send(); -+ packet_length = packet_send(); - c->remote_window -= dlen + 4; - xfree(data); - } -@@ -2043,7 +2082,7 @@ - SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA); - packet_put_int(c->remote_id); - packet_put_string(buffer_ptr(&c->input), len); -- packet_send(); -+ packet_length = packet_send(); - buffer_consume(&c->input, len); - c->remote_window -= len; - } -@@ -2078,12 +2117,13 @@ - packet_put_int(c->remote_id); - packet_put_int(SSH2_EXTENDED_DATA_STDERR); - packet_put_string(buffer_ptr(&c->extended), len); -- packet_send(); -+ packet_length = packet_send(); - buffer_consume(&c->extended, len); - c->remote_window -= len; - debug2("channel %d: sent ext data %d", c->self, len); - } - } -+ return (packet_length); - } - - -@@ -2459,6 +2499,15 @@ - IPv4or6 = af; - } - -+ -+void -+channel_set_hpn(int external_hpn_disabled, int external_hpn_buffer_size) -+{ -+ hpn_disabled = external_hpn_disabled; -+ hpn_buffer_size = external_hpn_buffer_size; -+ debug("HPN Disabled: %d, HPN Buffer Size: %d", hpn_disabled, hpn_buffer_size); -+} -+ - static int - channel_setup_fwd_listener(int type, const char *listen_addr, - u_short listen_port, int *allocated_listen_port, -@@ -2610,9 +2659,15 @@ - } - - /* Allocate a channel number for the socket. */ -+ /* explicitly test for hpn disabled option. if true use smaller window size */ -+ if (hpn_disabled) - c = channel_new("port listener", type, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, - 0, "port listener", 1); -+ else -+ c = channel_new("port listener", type, sock, sock, -1, -+ hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, -+ 0, "port listener", 1); - c->path = xstrdup(host); - c->host_port = port_to_connect; - c->listening_port = listen_port; -@@ -3151,10 +3206,17 @@ - *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); - for (n = 0; n < num_socks; n++) { - sock = socks[n]; -+ /* Is this really necassary? */ -+ if (hpn_disabled) - nc = channel_new("x11 listener", - SSH_CHANNEL_X11_LISTENER, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, - 0, "X11 inet listener", 1); -+ else -+ nc = channel_new("x11 listener", -+ SSH_CHANNEL_X11_LISTENER, sock, sock, -1, -+ hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, -+ 0, "X11 inet listener", 1); - nc->single_connection = single_connection; - (*chanids)[n] = nc->self; - } -diff -urN channels.h channels.h ---- channels.h 2009-02-14 08:28:21.000000000 +0300 -+++ channels.h 2009-05-02 17:38:18.000000000 +0400 -@@ -115,8 +115,10 @@ - u_int local_window_max; - u_int local_consumed; - u_int local_maxpacket; -+ int dynamic_window; - int extended_usage; - int single_connection; -+ u_int tcpwinsz; - - char *ctype; /* type */ - -@@ -146,9 +148,11 @@ - - /* default window/packet sizes for tcp/x11-fwd-channel */ - #define CHAN_SES_PACKET_DEFAULT (32*1024) --#define CHAN_SES_WINDOW_DEFAULT (64*CHAN_SES_PACKET_DEFAULT) -+#define CHAN_SES_WINDOW_DEFAULT (4*CHAN_SES_PACKET_DEFAULT) -+ - #define CHAN_TCP_PACKET_DEFAULT (32*1024) --#define CHAN_TCP_WINDOW_DEFAULT (64*CHAN_TCP_PACKET_DEFAULT) -+#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT) -+ - #define CHAN_X11_PACKET_DEFAULT (16*1024) - #define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) - -@@ -221,7 +225,7 @@ - - void channel_prepare_select(fd_set **, fd_set **, int *, u_int*, int); - void channel_after_select(fd_set *, fd_set *); --void channel_output_poll(void); -+int channel_output_poll(void); - - int channel_not_very_much_buffered_data(void); - void channel_close_all(void); -@@ -277,4 +281,7 @@ - void chan_write_failed(Channel *); - void chan_obuf_empty(Channel *); - -+/* hpn handler */ -+void channel_set_hpn(int, int); -+ - #endif -diff -urN cipher-ctr-mt.c cipher-ctr-mt.c ---- cipher-ctr-mt.c 1970-01-01 03:00:00.000000000 +0300 -+++ cipher-ctr-mt.c 2009-05-02 17:38:18.000000000 +0400 -@@ -0,0 +1,473 @@ -+/* -+ * OpenSSH Multi-threaded AES-CTR Cipher -+ * -+ * Author: Benjamin Bennett -+ * Copyright (c) 2008 Pittsburgh Supercomputing Center. All rights reserved. -+ * -+ * Based on original OpenSSH AES-CTR cipher. Small portions remain unchanged, -+ * Copyright (c) 2003 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. -+ */ -+#include "includes.h" -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+#include "xmalloc.h" -+#include "log.h" -+ -+/* compatibility with old or broken OpenSSL versions */ -+#include "openbsd-compat/openssl-compat.h" -+ -+#ifndef USE_BUILTIN_RIJNDAEL -+#include -+#endif -+ -+#include -+ -+/*-------------------- TUNABLES --------------------*/ -+/* Number of pregen threads to use */ -+#define CIPHER_THREADS 2 -+ -+/* Number of keystream queues */ -+#define NUMKQ (CIPHER_THREADS + 2) -+ -+/* Length of a keystream queue */ -+#define KQLEN 4096 -+ -+/* Processor cacheline length */ -+#define CACHELINE_LEN 64 -+ -+/* Collect thread stats and print at cancellation when in debug mode */ -+/* #define CIPHER_THREAD_STATS */ -+ -+/* Use single-byte XOR instead of 8-byte XOR */ -+/* #define CIPHER_BYTE_XOR */ -+/*-------------------- END TUNABLES --------------------*/ -+ -+ -+const EVP_CIPHER *evp_aes_ctr_mt(void); -+ -+#ifdef CIPHER_THREAD_STATS -+/* -+ * Struct to collect thread stats -+ */ -+struct thread_stats { -+ u_int fills; -+ u_int skips; -+ u_int waits; -+ u_int drains; -+}; -+ -+/* -+ * Debug print the thread stats -+ * Use with pthread_cleanup_push for displaying at thread cancellation -+ */ -+static void -+thread_loop_stats(void *x) -+{ -+ struct thread_stats *s = x; -+ -+ debug("tid %lu - %u fills, %u skips, %u waits", pthread_self(), -+ s->fills, s->skips, s->waits); -+} -+ -+ #define STATS_STRUCT(s) struct thread_stats s -+ #define STATS_INIT(s) { memset(&s, 0, sizeof(s)); } -+ #define STATS_FILL(s) { s.fills++; } -+ #define STATS_SKIP(s) { s.skips++; } -+ #define STATS_WAIT(s) { s.waits++; } -+ #define STATS_DRAIN(s) { s.drains++; } -+#else -+ #define STATS_STRUCT(s) -+ #define STATS_INIT(s) -+ #define STATS_FILL(s) -+ #define STATS_SKIP(s) -+ #define STATS_WAIT(s) -+ #define STATS_DRAIN(s) -+#endif -+ -+/* Keystream Queue state */ -+enum { -+ KQINIT, -+ KQEMPTY, -+ KQFILLING, -+ KQFULL, -+ KQDRAINING -+}; -+ -+/* Keystream Queue struct */ -+struct kq { -+ u_char keys[KQLEN][AES_BLOCK_SIZE]; -+ u_char ctr[AES_BLOCK_SIZE]; -+ u_char pad0[CACHELINE_LEN]; -+ volatile int qstate; -+ pthread_mutex_t lock; -+ pthread_cond_t cond; -+ u_char pad1[CACHELINE_LEN]; -+}; -+ -+/* Context struct */ -+struct ssh_aes_ctr_ctx -+{ -+ struct kq q[NUMKQ]; -+ AES_KEY aes_ctx; -+ STATS_STRUCT(stats); -+ u_char aes_counter[AES_BLOCK_SIZE]; -+ pthread_t tid[CIPHER_THREADS]; -+ int state; -+ int qidx; -+ int ridx; -+}; -+ -+/* -+ * 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 void -+ssh_ctr_inc(u_char *ctr, u_int len) -+{ -+ int i; -+ -+ for (i = len - 1; i >= 0; i--) -+ if (++ctr[i]) /* continue on overflow */ -+ return; -+} -+ -+/* -+ * Add num to counter 'ctr' -+ */ -+static void -+ssh_ctr_add(u_char *ctr, uint32_t num, u_int len) -+{ -+ int i; -+ uint16_t n; -+ -+ for (n = 0, i = len - 1; i >= 0 && (num || n); i--) { -+ n = ctr[i] + (num & 0xff) + n; -+ num >>= 8; -+ ctr[i] = n & 0xff; -+ n >>= 8; -+ } -+} -+ -+/* -+ * Threads may be cancelled in a pthread_cond_wait, we must free the mutex -+ */ -+static void -+thread_loop_cleanup(void *x) -+{ -+ pthread_mutex_unlock((pthread_mutex_t *)x); -+} -+ -+/* -+ * The life of a pregen thread: -+ * Find empty keystream queues and fill them using their counter. -+ * When done, update counter for the next fill. -+ */ -+static void * -+thread_loop(void *x) -+{ -+ AES_KEY key; -+ STATS_STRUCT(stats); -+ struct ssh_aes_ctr_ctx *c = x; -+ struct kq *q; -+ int i; -+ int qidx; -+ -+ /* Threads stats on cancellation */ -+ STATS_INIT(stats); -+#ifdef CIPHER_THREAD_STATS -+ pthread_cleanup_push(thread_loop_stats, &stats); -+#endif -+ -+ /* Thread local copy of AES key */ -+ memcpy(&key, &c->aes_ctx, sizeof(key)); -+ -+ /* -+ * Handle the special case of startup, one thread must fill -+ * the first KQ then mark it as draining. Lock held throughout. -+ */ -+ if (pthread_equal(pthread_self(), c->tid[0])) { -+ q = &c->q[0]; -+ pthread_mutex_lock(&q->lock); -+ if (q->qstate == KQINIT) { -+ for (i = 0; i < KQLEN; i++) { -+ AES_encrypt(q->ctr, q->keys[i], &key); -+ ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); -+ } -+ ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE); -+ q->qstate = KQDRAINING; -+ STATS_FILL(stats); -+ pthread_cond_broadcast(&q->cond); -+ } -+ pthread_mutex_unlock(&q->lock); -+ } -+ else -+ STATS_SKIP(stats); -+ -+ /* -+ * Normal case is to find empty queues and fill them, skipping over -+ * queues already filled by other threads and stopping to wait for -+ * a draining queue to become empty. -+ * -+ * Multiple threads may be waiting on a draining queue and awoken -+ * when empty. The first thread to wake will mark it as filling, -+ * others will move on to fill, skip, or wait on the next queue. -+ */ -+ for (qidx = 1;; qidx = (qidx + 1) % NUMKQ) { -+ /* Check if I was cancelled, also checked in cond_wait */ -+ pthread_testcancel(); -+ -+ /* Lock queue and block if its draining */ -+ q = &c->q[qidx]; -+ pthread_mutex_lock(&q->lock); -+ pthread_cleanup_push(thread_loop_cleanup, &q->lock); -+ while (q->qstate == KQDRAINING || q->qstate == KQINIT) { -+ STATS_WAIT(stats); -+ pthread_cond_wait(&q->cond, &q->lock); -+ } -+ pthread_cleanup_pop(0); -+ -+ /* If filling or full, somebody else got it, skip */ -+ if (q->qstate != KQEMPTY) { -+ pthread_mutex_unlock(&q->lock); -+ STATS_SKIP(stats); -+ continue; -+ } -+ -+ /* -+ * Empty, let's fill it. -+ * Queue lock is relinquished while we do this so others -+ * can see that it's being filled. -+ */ -+ q->qstate = KQFILLING; -+ pthread_mutex_unlock(&q->lock); -+ for (i = 0; i < KQLEN; i++) { -+ AES_encrypt(q->ctr, q->keys[i], &key); -+ ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); -+ } -+ -+ /* Re-lock, mark full and signal consumer */ -+ pthread_mutex_lock(&q->lock); -+ ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE); -+ q->qstate = KQFULL; -+ STATS_FILL(stats); -+ pthread_cond_signal(&q->cond); -+ pthread_mutex_unlock(&q->lock); -+ } -+ -+#ifdef CIPHER_THREAD_STATS -+ /* Stats */ -+ pthread_cleanup_pop(1); -+#endif -+ -+ return NULL; -+} -+ -+static int -+ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, -+ u_int len) -+{ -+ struct ssh_aes_ctr_ctx *c; -+ struct kq *q, *oldq; -+ int ridx; -+ u_char *buf; -+ -+ if (len == 0) -+ return (1); -+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) -+ return (0); -+ -+ q = &c->q[c->qidx]; -+ ridx = c->ridx; -+ -+ /* src already padded to block multiple */ -+ while (len > 0) { -+ buf = q->keys[ridx]; -+ -+#ifdef CIPHER_BYTE_XOR -+ dest[0] = src[0] ^ buf[0]; -+ dest[1] = src[1] ^ buf[1]; -+ dest[2] = src[2] ^ buf[2]; -+ dest[3] = src[3] ^ buf[3]; -+ dest[4] = src[4] ^ buf[4]; -+ dest[5] = src[5] ^ buf[5]; -+ dest[6] = src[6] ^ buf[6]; -+ dest[7] = src[7] ^ buf[7]; -+ dest[8] = src[8] ^ buf[8]; -+ dest[9] = src[9] ^ buf[9]; -+ dest[10] = src[10] ^ buf[10]; -+ dest[11] = src[11] ^ buf[11]; -+ dest[12] = src[12] ^ buf[12]; -+ dest[13] = src[13] ^ buf[13]; -+ dest[14] = src[14] ^ buf[14]; -+ dest[15] = src[15] ^ buf[15]; -+#else -+ *(uint64_t *)dest = *(uint64_t *)src ^ *(uint64_t *)buf; -+ *(uint64_t *)(dest + 8) = *(uint64_t *)(src + 8) ^ -+ *(uint64_t *)(buf + 8); -+#endif -+ -+ dest += 16; -+ src += 16; -+ len -= 16; -+ ssh_ctr_inc(ctx->iv, AES_BLOCK_SIZE); -+ -+ /* Increment read index, switch queues on rollover */ -+ if ((ridx = (ridx + 1) % KQLEN) == 0) { -+ oldq = q; -+ -+ /* Mark next queue draining, may need to wait */ -+ c->qidx = (c->qidx + 1) % NUMKQ; -+ q = &c->q[c->qidx]; -+ pthread_mutex_lock(&q->lock); -+ while (q->qstate != KQFULL) { -+ STATS_WAIT(c->stats); -+ pthread_cond_wait(&q->cond, &q->lock); -+ } -+ q->qstate = KQDRAINING; -+ pthread_mutex_unlock(&q->lock); -+ -+ /* Mark consumed queue empty and signal producers */ -+ pthread_mutex_lock(&oldq->lock); -+ oldq->qstate = KQEMPTY; -+ STATS_DRAIN(c->stats); -+ pthread_cond_broadcast(&oldq->cond); -+ pthread_mutex_unlock(&oldq->lock); -+ } -+ } -+ c->ridx = ridx; -+ return (1); -+} -+ -+#define HAVE_NONE 0 -+#define HAVE_KEY 1 -+#define HAVE_IV 2 -+static int -+ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, -+ int enc) -+{ -+ struct ssh_aes_ctr_ctx *c; -+ int i; -+ -+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { -+ c = xmalloc(sizeof(*c)); -+ -+ c->state = HAVE_NONE; -+ for (i = 0; i < NUMKQ; i++) { -+ pthread_mutex_init(&c->q[i].lock, NULL); -+ pthread_cond_init(&c->q[i].cond, NULL); -+ } -+ -+ STATS_INIT(c->stats); -+ -+ EVP_CIPHER_CTX_set_app_data(ctx, c); -+ } -+ -+ if (c->state == (HAVE_KEY | HAVE_IV)) { -+ /* Cancel pregen threads */ -+ for (i = 0; i < CIPHER_THREADS; i++) -+ pthread_cancel(c->tid[i]); -+ for (i = 0; i < CIPHER_THREADS; i++) -+ pthread_join(c->tid[i], NULL); -+ /* Start over getting key & iv */ -+ c->state = HAVE_NONE; -+ } -+ -+ if (key != NULL) { -+ AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, -+ &c->aes_ctx); -+ c->state |= HAVE_KEY; -+ } -+ -+ if (iv != NULL) { -+ memcpy(ctx->iv, iv, AES_BLOCK_SIZE); -+ c->state |= HAVE_IV; -+ } -+ -+ if (c->state == (HAVE_KEY | HAVE_IV)) { -+ /* Clear queues */ -+ memcpy(c->q[0].ctr, ctx->iv, AES_BLOCK_SIZE); -+ c->q[0].qstate = KQINIT; -+ for (i = 1; i < NUMKQ; i++) { -+ memcpy(c->q[i].ctr, ctx->iv, AES_BLOCK_SIZE); -+ ssh_ctr_add(c->q[i].ctr, i * KQLEN, AES_BLOCK_SIZE); -+ c->q[i].qstate = KQEMPTY; -+ } -+ c->qidx = 0; -+ c->ridx = 0; -+ -+ /* Start threads */ -+ for (i = 0; i < CIPHER_THREADS; i++) { -+ pthread_create(&c->tid[i], NULL, thread_loop, c); -+ } -+ pthread_mutex_lock(&c->q[0].lock); -+ while (c->q[0].qstate != KQDRAINING) -+ pthread_cond_wait(&c->q[0].cond, &c->q[0].lock); -+ pthread_mutex_unlock(&c->q[0].lock); -+ -+ } -+ return (1); -+} -+ -+static int -+ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) -+{ -+ struct ssh_aes_ctr_ctx *c; -+ int i; -+ -+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { -+#ifdef CIPHER_THREAD_STATS -+ debug("main thread: %u drains, %u waits", c->stats.drains, -+ c->stats.waits); -+#endif -+ /* Cancel pregen threads */ -+ for (i = 0; i < CIPHER_THREADS; i++) -+ pthread_cancel(c->tid[i]); -+ for (i = 0; i < CIPHER_THREADS; i++) -+ pthread_join(c->tid[i], NULL); -+ -+ memset(c, 0, sizeof(*c)); -+ xfree(c); -+ EVP_CIPHER_CTX_set_app_data(ctx, NULL); -+ } -+ return (1); -+} -+ -+/* */ -+const EVP_CIPHER * -+evp_aes_ctr_mt(void) -+{ -+ static EVP_CIPHER aes_ctr; -+ -+ memset(&aes_ctr, 0, sizeof(EVP_CIPHER)); -+ aes_ctr.nid = NID_undef; -+ aes_ctr.block_size = AES_BLOCK_SIZE; -+ aes_ctr.iv_len = AES_BLOCK_SIZE; -+ aes_ctr.key_len = 16; -+ aes_ctr.init = ssh_aes_ctr_init; -+ aes_ctr.cleanup = ssh_aes_ctr_cleanup; -+ aes_ctr.do_cipher = ssh_aes_ctr; -+#ifndef SSH_OLD_EVP -+ aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -+#endif -+ return (&aes_ctr); -+} -diff -urN cipher.c cipher.c ---- cipher.c 2009-01-28 08:38:41.000000000 +0300 -+++ cipher.c 2009-05-02 17:43:11.000000000 +0400 -@@ -55,6 +55,7 @@ - extern const EVP_CIPHER *evp_ssh1_3des(void); - extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); - extern const EVP_CIPHER *evp_aes_128_ctr(void); -+extern const EVP_CIPHER *evp_aes_ctr_mt(void); - extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); - - struct Cipher { -@@ -82,9 +83,9 @@ - { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, - { "rijndael-cbc@lysator.liu.se", - SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, -- { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr }, -- { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr }, -- { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr }, -+ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_ctr_mt }, -+ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_ctr_mt }, -+ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_ctr_mt }, - #ifdef USE_CIPHER_ACSS - { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss }, - #endif -@@ -163,7 +164,8 @@ - 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) { -+ if (c == NULL || (c->number != SSH_CIPHER_SSH2 && -+c->number != SSH_CIPHER_NONE)) { - debug("bad cipher %s [%s]", p, names); - xfree(cipher_list); - return 0; -@@ -337,6 +339,7 @@ - int evplen; - - switch (c->number) { -+ case SSH_CIPHER_NONE: - case SSH_CIPHER_SSH2: - case SSH_CIPHER_DES: - case SSH_CIPHER_BLOWFISH: -@@ -371,6 +374,7 @@ - int evplen = 0; - - switch (c->number) { -+ case SSH_CIPHER_NONE: - case SSH_CIPHER_SSH2: - case SSH_CIPHER_DES: - case SSH_CIPHER_BLOWFISH: -diff -urN clientloop.c clientloop.c ---- clientloop.c 2009-02-14 08:28:21.000000000 +0300 -+++ clientloop.c 2009-05-02 17:38:18.000000000 +0400 -@@ -1688,9 +1688,15 @@ - sock = x11_connect_display(); - if (sock < 0) - return NULL; -+ /* again is this really necessary for X11? */ -+ if (options.hpn_disabled) - c = channel_new("x11", - SSH_CHANNEL_X11_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); -+ else -+ c = channel_new("x11", -+ SSH_CHANNEL_X11_OPEN, sock, sock, -1, -+ options.hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); - c->force_drain = 1; - return c; - } -@@ -1710,9 +1716,15 @@ - sock = ssh_get_authentication_socket(); - if (sock < 0) - return NULL; -+ if (options.hpn_disabled) - c = channel_new("authentication agent connection", - SSH_CHANNEL_OPEN, sock, sock, -1, -- CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, -+ CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, -+ "authentication agent connection", 1); -+ else -+ c = channel_new("authentication agent connection", -+ SSH_CHANNEL_OPEN, sock, sock, -1, -+ options.hpn_buffer_size, options.hpn_buffer_size, 0, - "authentication agent connection", 1); - c->force_drain = 1; - return c; -@@ -1740,10 +1752,18 @@ - return -1; - } - -+ if(options.hpn_disabled) -+ c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, -+ CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, -+ 0, "tun", 1); -+ else - c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, -- CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); -+ options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, -+ 0, "tun", 1); - c->datagram = 1; - -+ -+ - #if defined(SSH_TUN_FILTER) - if (options.tun_open == SSH_TUNMODE_POINTOPOINT) - channel_register_filter(c->self, sys_tun_infilter, -diff -urN compat.c compat.c ---- compat.c 2008-11-03 11:20:14.000000000 +0300 -+++ compat.c 2009-05-02 17:38:18.000000000 +0400 -@@ -170,6 +170,15 @@ - strlen(check[i].pat), 0) == 1) { - debug("match: %s pat %s", version, check[i].pat); - datafellows = check[i].bugs; -+ /* Check to see if the remote side is OpenSSH and not HPN */ -+ if(strstr(version,"OpenSSH") != NULL) -+ { -+ if (strstr(version,"hpn") == NULL) -+ { -+ datafellows |= SSH_BUG_LARGEWINDOW; -+ debug("Remote is NON-HPN aware"); -+ } -+ } - return; - } - } -diff -urN compat.h compat.h ---- compat.h 2008-11-03 11:20:14.000000000 +0300 -+++ compat.h 2009-05-02 17:40:04.000000000 +0400 -@@ -58,6 +58,7 @@ - #define SSH_OLD_FORWARD_ADDR 0x01000000 - #define SSH_BUG_RFWD_ADDR 0x02000000 - #define SSH_NEW_OPENSSH 0x04000000 -+#define SSH_BUG_LARGEWINDOW 0x08000000 - - void enable_compat13(void); - void enable_compat20(void); -diff -urN kex.c kex.c ---- kex.c 2008-11-03 11:19:12.000000000 +0300 -+++ kex.c 2009-05-02 17:38:18.000000000 +0400 -@@ -48,6 +48,7 @@ - #include "match.h" - #include "dispatch.h" - #include "monitor.h" -+#include "canohost.h" - - #define KEX_COOKIE_LEN 16 - -@@ -64,7 +65,8 @@ - static void kex_choose_conf(Kex *); - - /* put algorithm proposal into buffer */ --static void -+/* used in sshconnect.c as well as kex.c */ -+void - kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) - { - u_int i; -@@ -376,6 +378,13 @@ - int nenc, nmac, ncomp; - u_int mode, ctos, need; - int first_kex_follows, type; -+ int log_flag = 0; -+ -+ int auth_flag; -+ -+ auth_flag = packet_authentication_state(); -+ -+ debug ("AUTH STATE IS %d", auth_flag); - - my = kex_buf2prop(&kex->my, NULL); - peer = kex_buf2prop(&kex->peer, &first_kex_follows); -@@ -400,11 +409,34 @@ - choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]); - choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]); - choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); -+ debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); -+ if (strcmp(newkeys->enc.name, "none") == 0) { -+ debug("Requesting NONE. Authflag is %d", auth_flag); -+ if (auth_flag == 1) { -+ debug("None requested post authentication."); -+ } else { -+ fatal("Pre-authentication none cipher requests are not allowed."); -+ } -+ } - debug("kex: %s %s %s %s", - ctos ? "client->server" : "server->client", - newkeys->enc.name, - newkeys->mac.name, - newkeys->comp.name); -+ /* client starts withctos = 0 && log flag = 0 and no log*/ -+ /* 2nd client pass ctos=1 and flag = 1 so no log*/ -+ /* server starts with ctos =1 && log_flag = 0 so log */ -+ /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/ -+ /* -cjr*/ -+ if (ctos && !log_flag) { -+ logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s", -+ get_remote_ipaddr(), -+ get_remote_port(), -+ newkeys->enc.name, -+ newkeys->mac.name, -+ newkeys->comp.name); -+ } -+ log_flag = 1; - } - choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); - choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], -diff -urN kex.h kex.h ---- kex.h 2007-06-11 08:01:42.000000000 +0400 -+++ kex.h 2009-05-02 17:38:18.000000000 +0400 -@@ -127,6 +127,8 @@ - void (*kex[KEX_MAX])(Kex *); - }; - -+void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]); -+ - Kex *kex_setup(char *[PROPOSAL_MAX]); - void kex_finish(Kex *); - -diff -urN myproposal.h myproposal.h ---- myproposal.h 2009-01-28 08:33:31.000000000 +0300 -+++ myproposal.h 2009-05-02 17:45:01.000000000 +0400 -@@ -47,6 +47,8 @@ - "arcfour256,arcfour128," \ - "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ - "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" -+#define KEX_ENCRYPT_INCLUDE_NONE KEX_DEFAULT_ENCRYPT \ -+ ",none" - #define KEX_DEFAULT_MAC \ - "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160," \ - "hmac-ripemd160@openssh.com," \ -diff -urN packet.c packet.c ---- packet.c 2009-02-14 08:35:01.000000000 +0300 -+++ packet.c 2009-05-02 17:38:18.000000000 +0400 -@@ -775,7 +775,7 @@ - /* - * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) - */ --static void -+static int - packet_send2_wrapped(void) - { - u_char type, *cp, *macbuf = NULL; -@@ -888,11 +888,13 @@ - set_newkeys(MODE_OUT); - else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side) - packet_enable_delayed_compress(); -+ return(packet_length); - } - --static void -+static int - packet_send2(void) - { -+ static int packet_length = 0; - static int rekeying = 0; - struct packet *p; - u_char type, *cp; -@@ -910,7 +912,7 @@ - memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); - buffer_init(&outgoing_packet); - TAILQ_INSERT_TAIL(&outgoing, p, next); -- return; -+ return(sizeof(Buffer)); - } - } - -@@ -918,7 +920,7 @@ - if (type == SSH2_MSG_KEXINIT) - rekeying = 1; - -- packet_send2_wrapped(); -+ packet_length = packet_send2_wrapped(); - - /* after a NEWKEYS message we can send the complete queue */ - if (type == SSH2_MSG_NEWKEYS) { -@@ -931,19 +933,22 @@ - sizeof(Buffer)); - TAILQ_REMOVE(&outgoing, p, next); - xfree(p); -- packet_send2_wrapped(); -+ packet_length += packet_send2_wrapped(); - } - } -+ return(packet_length); - } - --void -+int - packet_send(void) - { -+ int packet_len = 0; - if (compat20) -- packet_send2(); -+ packet_len = packet_send2(); - else - packet_send1(); - DBG(debug("packet_send done")); -+ return(packet_len); - } - - /* -@@ -1544,23 +1549,25 @@ - - /* Checks if there is any buffered output, and tries to write some of the output. */ - --void -+int - packet_write_poll(void) - { -- int len = buffer_len(&output); -+ int len = 0; -+ len = buffer_len(&output); - - if (len > 0) { - len = write(connection_out, buffer_ptr(&output), len); - if (len == -1) { - if (errno == EINTR || errno == EAGAIN || - errno == EWOULDBLOCK) -- return; -+ return (0); - fatal("Write failed: %.100s", strerror(errno)); - } - if (len == 0) - fatal("Write connection closed"); - buffer_consume(&output, len); - } -+ return(len); - } - - -@@ -1569,16 +1576,17 @@ - * written. - */ - --void -+int - packet_write_wait(void) - { - fd_set *setp; - int ret, ms_remain; - struct timeval start, timeout, *timeoutp = NULL; -+ u_int bytes_sent = 0; - - setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), - sizeof(fd_mask)); -- packet_write_poll(); -+ bytes_sent += packet_write_poll(); - while (packet_have_data_to_write()) { - memset(setp, 0, howmany(connection_out + 1, NFDBITS) * - sizeof(fd_mask)); -@@ -1612,7 +1620,7 @@ - "waiting to write", get_remote_ipaddr()); - cleanup_exit(255); - } -- packet_write_poll(); -+ bytes_sent += packet_write_poll(); - } - xfree(setp); - } -@@ -1736,12 +1744,24 @@ - } - } - -+int rekey_requested = 0; -+void -+packet_request_rekeying(void) -+{ -+ rekey_requested = 1; -+} -+ - #define MAX_PACKETS (1U<<31) - int - packet_need_rekeying(void) - { - if (datafellows & SSH_BUG_NOREKEY) - return 0; -+ if (rekey_requested == 1) -+ { -+ rekey_requested = 0; -+ return 1; -+ } - return - (p_send.packets > MAX_PACKETS) || - (p_read.packets > MAX_PACKETS) || -@@ -1766,3 +1786,9 @@ - { - after_authentication = 1; - } -+ -+int -+packet_authentication_state(void) -+{ -+ return(after_authentication); -+} -diff -urN packet.h packet.h ---- packet.h 2008-07-11 11:36:48.000000000 +0400 -+++ packet.h 2009-05-02 17:38:18.000000000 +0400 -@@ -20,6 +20,9 @@ - - #include - -+void -+packet_request_rekeying(void); -+ - void packet_set_connection(int, int); - void packet_set_timeout(int, int); - void packet_set_nonblocking(void); -@@ -35,6 +38,7 @@ - int packet_is_interactive(void); - void packet_set_server(void); - void packet_set_authenticated(void); -+int packet_authentication_state(void); - - void packet_start(u_char); - void packet_put_char(int ch); -@@ -44,7 +48,7 @@ - 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_send(void); - - int packet_read(void); - void packet_read_expect(int type); -@@ -73,8 +77,8 @@ - int packet_get_ssh1_cipher(void); - void packet_set_iv(int, u_char *); - --void packet_write_poll(void); --void packet_write_wait(void); -+int packet_write_poll(void); -+int packet_write_wait(void); - int packet_have_data_to_write(void); - int packet_not_very_much_data_to_write(void); - -diff -urN progressmeter.c progressmeter.c ---- progressmeter.c 2006-08-05 06:39:40.000000000 +0400 -+++ progressmeter.c 2009-05-02 17:38:18.000000000 +0400 -@@ -68,6 +68,8 @@ - static char *file; /* name of the file being transferred */ - static off_t end_pos; /* ending position of transfer */ - static off_t cur_pos; /* transfer position as of last refresh */ -+static off_t last_pos; -+static off_t max_delta_pos = 0; - static volatile off_t *counter; /* progress counter */ - static long stalled; /* how long we have been stalled */ - static int bytes_per_second; /* current speed in bytes per second */ -@@ -128,12 +130,17 @@ - int hours, minutes, seconds; - int i, len; - int file_len; -+ off_t delta_pos; - - transferred = *counter - cur_pos; - cur_pos = *counter; - now = time(NULL); - bytes_left = end_pos - cur_pos; - -+ delta_pos = cur_pos - last_pos; -+ if (delta_pos > max_delta_pos) -+ max_delta_pos = delta_pos; -+ - if (bytes_left > 0) - elapsed = now - last_update; - else { -@@ -158,7 +165,7 @@ - - /* filename */ - buf[0] = '\0'; -- file_len = win_size - 35; -+ file_len = win_size - 45; - if (file_len > 0) { - len = snprintf(buf, file_len + 1, "\r%s", file); - if (len < 0) -@@ -175,7 +182,8 @@ - percent = ((float)cur_pos / end_pos) * 100; - else - percent = 100; -- snprintf(buf + strlen(buf), win_size - strlen(buf), -+ -+ snprintf(buf + strlen(buf), win_size - strlen(buf-8), - " %3d%% ", percent); - - /* amount transferred */ -@@ -188,6 +196,15 @@ - (off_t)bytes_per_second); - strlcat(buf, "/s ", win_size); - -+ /* instantaneous rate */ -+ if (bytes_left > 0) -+ format_rate(buf + strlen(buf), win_size - strlen(buf), -+ delta_pos); -+ else -+ format_rate(buf + strlen(buf), win_size - strlen(buf), -+ max_delta_pos); -+ strlcat(buf, "/s ", win_size); -+ - /* ETA */ - if (!transferred) - stalled += elapsed; -@@ -224,6 +241,7 @@ - - atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); - last_update = now; -+ last_pos = cur_pos; - } - - /*ARGSUSED*/ -diff -urN readconf.c readconf.c ---- readconf.c 2009-05-02 17:37:11.000000000 +0400 -+++ readconf.c 2009-05-02 17:47:56.000000000 +0400 -@@ -131,6 +131,8 @@ - oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, - oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, - oVisualHostKey, oZeroKnowledgePasswordAuthentication, -+ oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled, -+ oHPNBufferSize, - oDeprecated, oUnsupported - } OpCodes; - -@@ -228,6 +230,12 @@ - { "localcommand", oLocalCommand }, - { "permitlocalcommand", oPermitLocalCommand }, - { "visualhostkey", oVisualHostKey }, -+ { "noneenabled", oNoneEnabled }, -+ { "tcprcvbufpoll", oTcpRcvBufPoll }, -+ { "tcprcvbuf", oTcpRcvBuf }, -+ { "noneswitch", oNoneSwitch }, -+ { "hpndisabled", oHPNDisabled }, -+ { "hpnbuffersize", oHPNBufferSize }, - #ifdef JPAKE - { "zeroknowledgepasswordauthentication", - oZeroKnowledgePasswordAuthentication }, -@@ -465,6 +473,37 @@ - intptr = &options->check_host_ip; - goto parse_flag; - -+ case oNoneEnabled: -+ intptr = &options->none_enabled; -+ goto parse_flag; -+ -+ /* we check to see if the command comes from the */ -+ /* command line or not. If it does then enable it */ -+ /* otherwise fail. NONE should never be a default configuration */ -+ case oNoneSwitch: -+ if(strcmp(filename,"command-line")==0) -+ { -+ intptr = &options->none_switch; -+ goto parse_flag; -+ } else { -+ error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename); -+ error("Continuing..."); -+ debug("NoneSwitch directive found in %.200s.", filename); -+ return 0; -+ } -+ -+ case oHPNDisabled: -+ intptr = &options->hpn_disabled; -+ goto parse_flag; -+ -+ case oHPNBufferSize: -+ intptr = &options->hpn_buffer_size; -+ goto parse_int; -+ -+ case oTcpRcvBufPoll: -+ intptr = &options->tcp_rcv_buf_poll; -+ goto parse_flag; -+ - case oVerifyHostKeyDNS: - intptr = &options->verify_host_key_dns; - goto parse_yesnoask; -@@ -643,6 +682,10 @@ - intptr = &options->connection_attempts; - goto parse_int; - -+ case oTcpRcvBuf: -+ intptr = &options->tcp_rcv_buf; -+ goto parse_int; -+ - case oCipher: - intptr = &options->cipher; - arg = strdelim(&s); -@@ -1065,6 +1108,12 @@ - options->permit_local_command = -1; - options->visual_host_key = -1; - options->zero_knowledge_password_authentication = -1; -+ options->none_switch = -1; -+ options->none_enabled = -1; -+ options->hpn_disabled = -1; -+ options->hpn_buffer_size = -1; -+ options->tcp_rcv_buf_poll = -1; -+ options->tcp_rcv_buf = -1; - } - - /* -@@ -1187,6 +1236,29 @@ - options->server_alive_interval = 0; - if (options->server_alive_count_max == -1) - options->server_alive_count_max = 3; -+ if (options->none_switch == -1) -+ options->none_switch = 0; -+ if (options->hpn_disabled == -1) -+ options->hpn_disabled = 0; -+ if (options->hpn_buffer_size > -1) -+ { -+ /* if a user tries to set the size to 0 set it to 1KB */ -+ if (options->hpn_buffer_size == 0) -+ options->hpn_buffer_size = 1024; -+ /*limit the buffer to 64MB*/ -+ if (options->hpn_buffer_size > 65536) -+ { -+ options->hpn_buffer_size = 65536*1024; -+ debug("User requested buffer larger than 64MB. Request reverted to 64MB"); -+ } -+ debug("hpn_buffer_size set to %d", options->hpn_buffer_size); -+ } -+ if (options->tcp_rcv_buf == 0) -+ options->tcp_rcv_buf = 1; -+ if (options->tcp_rcv_buf > -1) -+ options->tcp_rcv_buf *=1024; -+ if (options->tcp_rcv_buf_poll == -1) -+ options->tcp_rcv_buf_poll = 1; - if (options->control_master == -1) - options->control_master = 0; - if (options->hash_known_hosts == -1) -diff -urN readconf.h readconf.h ---- readconf.h 2009-02-14 08:28:21.000000000 +0300 -+++ readconf.h 2009-05-02 17:38:19.000000000 +0400 -@@ -57,6 +57,11 @@ - int compression_level; /* Compression level 1 (fast) to 9 - * (best). */ - int tcp_keep_alive; /* Set SO_KEEPALIVE. */ -+ int tcp_rcv_buf; /* user switch to set tcp recv buffer */ -+ int tcp_rcv_buf_poll; /* Option to poll recv buf every window transfer */ -+ int hpn_disabled; /* Switch to disable HPN buffer management */ -+ int hpn_buffer_size; /* User definable size for HPN buffer window */ -+ - LogLevel log_level; /* Level for logging. */ - - int port; /* Port to connect. */ -@@ -102,6 +107,8 @@ - - int enable_ssh_keysign; - int64_t rekey_limit; -+ int none_switch; /* Use none cipher */ -+ int none_enabled; /* Allow none to be used */ - int no_host_authentication_for_localhost; - int identities_only; - int server_alive_interval; -diff -urN scp.c scp.c ---- scp.c 2008-11-03 11:23:45.000000000 +0300 -+++ scp.c 2009-05-02 17:38:19.000000000 +0400 -@@ -632,7 +632,7 @@ - off_t i, statbytes; - size_t amt; - int fd = -1, haderr, indx; -- char *last, *name, buf[2048], encname[MAXPATHLEN]; -+ char *last, *name, buf[16384], encname[MAXPATHLEN]; - int len; - - for (indx = 0; indx < argc; ++indx) { -@@ -868,7 +868,7 @@ - mode_t mode, omode, mask; - off_t size, statbytes; - int setimes, targisdir, wrerrno = 0; -- char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; -+ char ch, *cp, *np, *targ, *why, *vect[1], buf[16384]; - struct timeval tv[2]; - - #define atime tv[0] -diff -urN servconf.c servconf.c ---- servconf.c 2009-05-02 17:37:11.000000000 +0400 -+++ servconf.c 2009-05-02 17:38:19.000000000 +0400 -@@ -266,6 +266,42 @@ - if (options->zero_knowledge_password_authentication == -1) - options->zero_knowledge_password_authentication = 0; - -+ if (options->hpn_disabled == -1) -+ options->hpn_disabled = 0; -+ -+ if (options->hpn_buffer_size == -1) { -+ /* option not explicitly set. Now we have to figure out */ -+ /* what value to use */ -+ if (options->hpn_disabled == 1) { -+ options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; -+ } else { -+ /* get the current RCV size and set it to that */ -+ /*create a socket but don't connect it */ -+ /* we use that the get the rcv socket size */ -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, -+ &socksize, &socksizelen); -+ close(sock); -+ options->hpn_buffer_size = socksize; -+ debug ("HPN Buffer Size: %d", options->hpn_buffer_size); -+ -+ } -+ } else { -+ /* we have to do this incase the user sets both values in a contradictory */ -+ /* manner. hpn_disabled overrrides hpn_buffer_size*/ -+ if (options->hpn_disabled <= 0) { -+ if (options->hpn_buffer_size == 0) -+ options->hpn_buffer_size = 1; -+ /* limit the maximum buffer to 64MB */ -+ if (options->hpn_buffer_size > 64*1024) { -+ options->hpn_buffer_size = 64*1024*1024; -+ } else { -+ options->hpn_buffer_size *= 1024; -+ } -+ } else -+ options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; -+ } -+ - /* Turn privilege separation on by default */ - if (use_privsep == -1) - use_privsep = 1; -@@ -428,6 +464,10 @@ - { "permitopen", sPermitOpen, SSHCFG_ALL }, - { "forcecommand", sForceCommand, SSHCFG_ALL }, - { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, -+ { "noneenabled", sNoneEnabled }, -+ { "hpndisabled", sHPNDisabled }, -+ { "hpnbuffersize", sHPNBufferSize }, -+ { "tcprcvbufpoll", sTcpRcvBufPoll }, - { NULL, sBadOption, 0 } - }; - -@@ -454,6 +494,7 @@ - - for (i = 0; keywords[i].name; i++) - if (strcasecmp(cp, keywords[i].name) == 0) { -+ debug ("Config token is %s", keywords[i].name); - *flags = keywords[i].flags; - return keywords[i].opcode; - } -@@ -851,6 +892,22 @@ - *intptr = value; - break; - -+ case sNoneEnabled: -+ intptr = &options->none_enabled; -+ goto parse_flag; -+ -+ case sTcpRcvBufPoll: -+ intptr = &options->tcp_rcv_buf_poll; -+ goto parse_flag; -+ -+ case sHPNDisabled: -+ intptr = &options->hpn_disabled; -+ goto parse_flag; -+ -+ case sHPNBufferSize: -+ intptr = &options->hpn_buffer_size; -+ goto parse_int; -+ - case sIgnoreUserKnownHosts: - intptr = &options->ignore_user_known_hosts; - goto parse_flag; -diff -urN servconf.h servconf.h ---- servconf.h 2009-01-28 08:31:23.000000000 +0300 -+++ servconf.h 2009-05-02 17:38:19.000000000 +0400 -@@ -145,6 +145,10 @@ - char *adm_forced_command; - - int use_pam; /* Enable auth via PAM */ -+ int none_enabled; /* enable NONE cipher switch */ -+ int tcp_rcv_buf_poll; /* poll tcp rcv window in autotuning kernels*/ -+ int hpn_disabled; /* disable hpn functionality. false by default */ -+ int hpn_buffer_size; /* set the hpn buffer size - default 3MB */ - - int permit_tun; - -diff -urN serverloop.c serverloop.c ---- serverloop.c 2009-02-14 08:33:09.000000000 +0300 -+++ serverloop.c 2009-05-02 17:38:19.000000000 +0400 -@@ -93,10 +93,10 @@ - static int fdout; /* Descriptor for stdout (for reading); - May be same number as fdin. */ - static int fderr; /* Descriptor for stderr. May be -1. */ --static long stdin_bytes = 0; /* Number of bytes written to stdin. */ --static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ --static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ --static long fdout_bytes = 0; /* Number of stdout bytes read from program. */ -+static u_long stdin_bytes = 0; /* Number of bytes written to stdin. */ -+static u_long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ -+static u_long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ -+static u_long fdout_bytes = 0; /* Number of stdout bytes read from program. */ - static int stdin_eof = 0; /* EOF message received from client. */ - static int fdout_eof = 0; /* EOF encountered reading from fdout. */ - static int fderr_eof = 0; /* EOF encountered readung from fderr. */ -@@ -121,6 +121,20 @@ - static void server_init_dispatch(void); - - /* -+ * Returns current time in seconds from Jan 1, 1970 with the maximum -+ * available resolution. -+ */ -+ -+static double -+get_current_time(void) -+{ -+ struct timeval tv; -+ gettimeofday(&tv, NULL); -+ return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; -+} -+ -+ -+/* - * we write to this pipe if a SIGCHLD is caught in order to avoid - * the race between select() and child_terminated - */ -@@ -410,6 +424,7 @@ - } else { - /* Buffer any received data. */ - packet_process_incoming(buf, len); -+ fdout_bytes += len; - } - } - if (compat20) -@@ -432,6 +447,7 @@ - } else { - buffer_append(&stdout_buffer, buf, len); - fdout_bytes += len; -+ debug ("FD out now: %ld", fdout_bytes); - } - } - /* Read and buffer any available stderr data from the program. */ -@@ -499,7 +515,7 @@ - } - /* Send any buffered packet data to the client. */ - if (FD_ISSET(connection_out, writeset)) -- packet_write_poll(); -+ stdin_bytes += packet_write_poll(); - } - - /* -@@ -816,8 +832,10 @@ - { - fd_set *readset = NULL, *writeset = NULL; - int rekeying = 0, max_fd, nalloc = 0; -+ double start_time, total_time; - - debug("Entering interactive session for SSH2."); -+ start_time = get_current_time(); - - mysignal(SIGCHLD, sigchld_handler); - child_terminated = 0; -@@ -879,6 +897,11 @@ - - /* free remaining sessions, e.g. remove wtmp entries */ - session_destroy_all(NULL); -+ total_time = get_current_time() - start_time; -+ logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f", -+ get_remote_ipaddr(), get_remote_port(), -+ stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time, -+ fdout_bytes / total_time); - } - - static void -@@ -994,8 +1017,12 @@ - sock = tun_open(tun, mode); - if (sock < 0) - goto done; -+ if (options.hpn_disabled) - c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); -+ else -+ c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, -+ options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); - c->datagram = 1; - #if defined(SSH_TUN_FILTER) - if (mode == SSH_TUNMODE_POINTOPOINT) -@@ -1031,6 +1058,8 @@ - c = channel_new("session", SSH_CHANNEL_LARVAL, - -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, - 0, "server-session", 1); -+ if ((options.tcp_rcv_buf_poll) && (!options.hpn_disabled)) -+ c->dynamic_window = 1; - if (session_open(the_authctxt, c->self) != 1) { - debug("session open failed, free channel %d", c->self); - channel_free(c); -diff -urN session.c session.c ---- session.c 2009-05-02 17:37:11.000000000 +0400 -+++ session.c 2009-05-02 17:38:19.000000000 +0400 -@@ -230,6 +230,7 @@ - } - - /* Allocate a channel for the authentication agent socket. */ -+ /* this shouldn't matter if its hpn or not - cjr */ - nc = channel_new("auth socket", - SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, -@@ -2351,10 +2352,16 @@ - */ - if (s->chanid == -1) - fatal("no channel for session %d", s->self); -+ if (options.hpn_disabled) - channel_set_fds(s->chanid, - fdout, fdin, fderr, - fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, - 1, is_tty, CHAN_SES_WINDOW_DEFAULT); -+ else -+ channel_set_fds(s->chanid, -+ fdout, fdin, fderr, -+ fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, -+ 1, is_tty, options.hpn_buffer_size); - } - - /* -diff -urN sftp.1 sftp.1 ---- sftp.1 2009-01-28 08:14:09.000000000 +0300 -+++ sftp.1 2009-05-02 17:38:19.000000000 +0400 -@@ -203,7 +203,8 @@ - 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. -+The default is 256 outstanding requests providing for 8MB -+of outstanding data with a 32KB buffer. - .It Fl S Ar program - Name of the - .Ar program -diff -urN sftp.c sftp.c ---- sftp.c 2009-02-14 08:26:19.000000000 +0300 -+++ sftp.c 2009-05-02 17:38:19.000000000 +0400 -@@ -75,7 +75,7 @@ - size_t copy_buffer_len = 32768; - - /* Number of concurrent outstanding requests */ --size_t num_requests = 64; -+size_t num_requests = 256; - - /* PID of ssh transport process */ - static pid_t sshpid = -1; -diff -urN ssh.c ssh.c ---- ssh.c 2009-05-02 17:37:11.000000000 +0400 -+++ ssh.c 2009-05-02 17:38:19.000000000 +0400 -@@ -492,9 +492,6 @@ - no_shell_flag = 1; - no_tty_flag = 1; - break; -- case 'T': -- no_tty_flag = 1; -- break; - case 'o': - dummy = 1; - line = xstrdup(optarg); -@@ -503,6 +500,13 @@ - exit(255); - xfree(line); - break; -+ case 'T': -+ no_tty_flag = 1; -+ /* ensure that the user doesn't try to backdoor a */ -+ /* null cipher switch on an interactive session */ -+ /* so explicitly disable it no matter what */ -+ options.none_switch=0; -+ break; - case 's': - subsystem_flag = 1; - break; -@@ -1159,6 +1163,9 @@ - { - Channel *c; - int window, packetmax, in, out, err; -+ int sock; -+ int socksize; -+ int socksizelen = sizeof(int); - - if (stdin_null_flag) { - in = open(_PATH_DEVNULL, O_RDONLY); -@@ -1179,9 +1186,75 @@ - if (!isatty(err)) - set_nonblock(err); - -- window = CHAN_SES_WINDOW_DEFAULT; -+ /* we need to check to see if what they want to do about buffer */ -+ /* sizes here. In a hpn to nonhpn connection we want to limit */ -+ /* the window size to something reasonable in case the far side */ -+ /* has the large window bug. In hpn to hpn connection we want to */ -+ /* use the max window size but allow the user to override it */ -+ /* lastly if they disabled hpn then use the ssh std window size */ -+ -+ /* so why don't we just do a getsockopt() here and set the */ -+ /* ssh window to that? In the case of a autotuning receive */ -+ /* window the window would get stuck at the initial buffer */ -+ /* size generally less than 96k. Therefore we need to set the */ -+ /* maximum ssh window size to the maximum hpn buffer size */ -+ /* unless the user has specifically set the tcprcvbufpoll */ -+ /* to no. In which case we *can* just set the window to the */ -+ /* minimum of the hpn buffer size and tcp receive buffer size */ -+ -+ if (tty_flag) -+ options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; -+ else -+ options.hpn_buffer_size = 2*1024*1024; -+ -+ if (datafellows & SSH_BUG_LARGEWINDOW) -+ { -+ debug("HPN to Non-HPN Connection"); -+ } -+ else -+ { -+ if (options.tcp_rcv_buf_poll <= 0) -+ { -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, -+ &socksize, &socksizelen); -+ close(sock); -+ debug("socksize %d", socksize); -+ options.hpn_buffer_size = socksize; -+ debug ("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size); -+ } -+ else -+ { -+ if (options.tcp_rcv_buf > 0) -+ { -+ /*create a socket but don't connect it */ -+ /* we use that the get the rcv socket size */ -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ /* if they are using the tcp_rcv_buf option */ -+ /* attempt to set the buffer size to that */ -+ if (options.tcp_rcv_buf) -+ setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&options.tcp_rcv_buf, -+ sizeof(options.tcp_rcv_buf)); -+ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, -+ &socksize, &socksizelen); -+ close(sock); -+ debug("socksize %d", socksize); -+ options.hpn_buffer_size = socksize; -+ debug ("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size); -+ } -+ } -+ -+ } -+ -+ debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); -+ -+ window = options.hpn_buffer_size; -+ -+ channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); -+ - packetmax = CHAN_SES_PACKET_DEFAULT; - if (tty_flag) { -+ window = 4*CHAN_SES_PACKET_DEFAULT; - window >>= 1; - packetmax >>= 1; - } -@@ -1189,7 +1262,10 @@ - "session", SSH_CHANNEL_OPENING, in, out, err, - window, packetmax, CHAN_EXTENDED_WRITE, - "client-session", /*nonblock*/0); -- -+ if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) { -+ c->dynamic_window = 1; -+ debug ("Enabled Dynamic Window Scaling\n"); -+ } - debug3("ssh_session2_open: channel_new: %d", c->self); - - channel_send_open(c->self); -diff -urN sshconnect.c sshconnect.c ---- sshconnect.c 2009-02-01 14:19:54.000000000 +0300 -+++ sshconnect.c 2009-05-02 17:38:19.000000000 +0400 -@@ -165,6 +165,31 @@ - } - - /* -+ * Set TCP receive buffer if requested. -+ * Note: tuning needs to happen after the socket is -+ * created but before the connection happens -+ * so winscale is negotiated properly -cjr -+ */ -+static void -+ssh_set_socket_recvbuf(int sock) -+{ -+ void *buf = (void *)&options.tcp_rcv_buf; -+ int sz = sizeof(options.tcp_rcv_buf); -+ int socksize; -+ int socksizelen = sizeof(int); -+ -+ debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf); -+ if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) { -+ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); -+ debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); -+ } -+ else -+ error("Couldn't set socket receive buffer to %d: %.100s", -+ options.tcp_rcv_buf, strerror(errno)); -+} -+ -+ -+/* - * Creates a (possibly privileged) socket for use as the ssh connection. - */ - static int -@@ -187,12 +212,18 @@ - strerror(errno)); - else - debug("Allocated local port %d.", p); -+ -+ if (options.tcp_rcv_buf > 0) -+ ssh_set_socket_recvbuf(sock); - return sock; - } - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock < 0) - error("socket: %.100s", strerror(errno)); - -+ if (options.tcp_rcv_buf > 0) -+ ssh_set_socket_recvbuf(sock); -+ - /* Bind the socket to an alternative local IP address */ - if (options.bind_address == NULL) - return sock; -@@ -536,7 +567,7 @@ - snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", - compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, - compat20 ? PROTOCOL_MINOR_2 : minor1, -- SSH_VERSION, compat20 ? "\r\n" : "\n"); -+ SSH_RELEASE, compat20 ? "\r\n" : "\n"); - if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) - fatal("write: %.100s", strerror(errno)); - client_version_string = xstrdup(buf); -diff -urN sshconnect2.c sshconnect2.c ---- sshconnect2.c 2008-11-05 08:20:47.000000000 +0300 -+++ sshconnect2.c 2009-05-02 17:38:19.000000000 +0400 -@@ -78,6 +78,12 @@ - extern char *client_version_string; - extern char *server_version_string; - extern Options options; -+extern Kex *xxx_kex; -+ -+/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ -+/* if it is set then prevent the switch to the null cipher */ -+ -+extern int tty_flag; - - /* - * SSH2 key exchange -@@ -350,6 +356,28 @@ - pubkey_cleanup(&authctxt); - dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); - -+ /* if the user wants to use the none cipher do it */ -+ /* post authentication and only if the right conditions are met */ -+ /* both of the NONE commands must be true and there must be no */ -+ /* tty allocated */ -+ if ((options.none_switch == 1) && (options.none_enabled == 1)) -+ { -+ if (!tty_flag) /* no null on tty sessions */ -+ { -+ debug("Requesting none rekeying..."); -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = "none"; -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none"; -+ kex_prop2buf(&xxx_kex->my,myproposal); -+ packet_request_rekeying(); -+ fprintf(stderr, "WARNING: ENABLED NONE CIPHER\n"); -+ } -+ else -+ { -+ /* requested NONE cipher when in a tty */ -+ debug("Cannot switch to NONE cipher with tty allocated"); -+ fprintf(stderr, "NONE cipher switch disabled when a TTY is allocated\n"); -+ } -+ } - debug("Authentication succeeded (%s).", authctxt.method->name); - } - -diff -urN sshd.c sshd.c ---- sshd.c 2009-05-02 17:37:11.000000000 +0400 -+++ sshd.c 2009-05-02 17:38:19.000000000 +0400 -@@ -143,6 +143,9 @@ - #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) - #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) - -+int myflag = 0; -+ -+ - extern char *__progname; - - /* Server configuration options. */ -@@ -422,7 +425,7 @@ - minor = PROTOCOL_MINOR_1; - } - snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor, -- SSH_VERSION, newline); -+ SSH_RELEASE, newline); - server_version_string = xstrdup(buf); - - /* Send our protocol version identification. */ -@@ -473,6 +476,9 @@ - } - debug("Client protocol version %d.%d; client software version %.100s", - remote_major, remote_minor, remote_version); -+ logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s", -+ get_remote_ipaddr(), get_remote_port(), -+ remote_major, remote_minor, remote_version); - - compat_datafellows(remote_version); - -@@ -951,6 +957,8 @@ - int ret, listen_sock, on = 1; - struct addrinfo *ai; - char ntop[NI_MAXHOST], strport[NI_MAXSERV]; -+ int socksize; -+ int socksizelen = sizeof(int); - - for (ai = options.listen_addrs; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) -@@ -997,6 +1005,11 @@ - - debug("Bind to port %s on %s.", strport, ntop); - -+ getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, -+ &socksize, &socksizelen); -+ debug("Server TCP RWIN socket size: %d", socksize); -+ debug("HPN Buffer Size: %d", options.hpn_buffer_size); -+ - /* Bind the socket to the desired port. */ - if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { - error("Bind to port %s on %s failed: %.200s.", -@@ -1847,6 +1860,9 @@ - /* Log the connection. */ - verbose("Connection from %.500s port %d", remote_ip, remote_port); - -+ /* set the HPN options for the child */ -+ channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); -+ - /* - * We don't want to listen forever unless the other side - * successfully authenticates itself. So we set up an alarm which is -@@ -2201,9 +2217,15 @@ - { - Kex *kex; - -+ myflag++; -+ debug ("MYFLAG IS %d", myflag); - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (options.none_enabled == 1) { -+ debug ("WARNING: None cipher enabled"); -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_ENCRYPT_INCLUDE_NONE; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -diff -urN sshd_config sshd_config ---- sshd_config 2009-05-02 17:37:11.000000000 +0400 -+++ sshd_config 2009-05-02 17:38:19.000000000 +0400 -@@ -112,6 +112,20 @@ - # override default of no subsystems - Subsystem sftp /usr/libexec/sftp-server - -+# the following are HPN related configuration options -+# tcp receive buffer polling. disable in non autotuning kernels -+#TcpRcvBufPoll yes -+ -+# allow the use of the none cipher -+#NoneEnabled no -+ -+# disable hpn performance boosts. -+#HPNDisabled no -+ -+# buffer size for hpn to non-hpn connections -+#HPNBufferSize 2048 -+ -+ - # Example of overriding settings on a per-user basis - #Match User anoncvs - # X11Forwarding no ---- version.h.orig 2009-02-23 03:09:26.000000000 +0300 -+++ version.h 2009-05-02 18:53:20.000000000 +0400 -@@ -3,4 +3,5 @@ - #define SSH_VERSION "OpenSSH_5.2" - - #define SSH_PORTABLE "p1" --#define SSH_RELEASE SSH_VERSION SSH_PORTABLE -+#define SSH_HPN "-hpn13v5" -+#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/openssh-5.2p1-hpn13v6-servconf.c.diff /usr/home/dindin/workspace/openssh-portable/files/openssh-5.2p1-hpn13v6-servconf.c.diff --- /usr/ports/security/openssh-portable/files/openssh-5.2p1-hpn13v6-servconf.c.diff 1970-01-01 03:00:00.000000000 +0300 +++ /usr/home/dindin/workspace/openssh-portable/files/openssh-5.2p1-hpn13v6-servconf.c.diff 2009-05-26 15:34:24.000000000 +0400 @@ -0,0 +1,117 @@ +diff -NupwB servconf.c servconf.c +--- servconf.c 2009-01-28 00:31:23.000000000 -0500 ++++ servconf.c 2009-05-14 12:36:10.000000000 -0400 +@@ -128,11 +128,20 @@ initialize_server_options(ServerOptions + options->adm_forced_command = NULL; + options->chroot_directory = NULL; + options->zero_knowledge_password_authentication = -1; ++ options->none_enabled = -1; ++ options->tcp_rcv_buf_poll = -1; ++ options->hpn_disabled = -1; ++ options->hpn_buffer_size = -1; + } + + void + fill_default_server_options(ServerOptions *options) + { ++ /* needed for hpn socket tests */ ++ int sock; ++ int socksize; ++ int socksizelen = sizeof(int); ++ + /* Portable-specific options */ + if (options->use_pam == -1) + options->use_pam = 0; +@@ -262,6 +271,42 @@ fill_default_server_options(ServerOption + if (options->zero_knowledge_password_authentication == -1) + options->zero_knowledge_password_authentication = 0; + ++ if (options->hpn_disabled == -1) ++ options->hpn_disabled = 0; ++ ++ if (options->hpn_buffer_size == -1) { ++ /* option not explicitly set. Now we have to figure out */ ++ /* what value to use */ ++ if (options->hpn_disabled == 1) { ++ options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; ++ } else { ++ /* get the current RCV size and set it to that */ ++ /*create a socket but don't connect it */ ++ /* we use that the get the rcv socket size */ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ options->hpn_buffer_size = socksize; ++ debug ("HPN Buffer Size: %d", options->hpn_buffer_size); ++ ++ } ++ } else { ++ /* we have to do this incase the user sets both values in a contradictory */ ++ /* manner. hpn_disabled overrrides hpn_buffer_size*/ ++ if (options->hpn_disabled <= 0) { ++ if (options->hpn_buffer_size == 0) ++ options->hpn_buffer_size = 1; ++ /* limit the maximum buffer to 64MB */ ++ if (options->hpn_buffer_size > 64*1024) { ++ options->hpn_buffer_size = 64*1024*1024; ++ } else { ++ options->hpn_buffer_size *= 1024; ++ } ++ } else ++ options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; ++ } ++ + /* Turn privilege separation on by default */ + if (use_privsep == -1) + use_privsep = 1; +@@ -306,6 +351,7 @@ typedef enum { + sMatch, sPermitOpen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, ++ sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -424,6 +470,10 @@ static struct { + { "permitopen", sPermitOpen, SSHCFG_ALL }, + { "forcecommand", sForceCommand, SSHCFG_ALL }, + { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, ++ { "noneenabled", sNoneEnabled }, ++ { "hpndisabled", sHPNDisabled }, ++ { "hpnbuffersize", sHPNBufferSize }, ++ { "tcprcvbufpoll", sTcpRcvBufPoll }, + { NULL, sBadOption, 0 } + }; + +@@ -450,6 +500,7 @@ parse_token(const char *cp, const char * + + for (i = 0; keywords[i].name; i++) + if (strcasecmp(cp, keywords[i].name) == 0) { ++ debug ("Config token is %s", keywords[i].name); + *flags = keywords[i].flags; + return keywords[i].opcode; + } +@@ -847,6 +898,22 @@ process_server_config_line(ServerOptions + *intptr = value; + break; + ++ case sNoneEnabled: ++ intptr = &options->none_enabled; ++ goto parse_flag; ++ ++ case sTcpRcvBufPoll: ++ intptr = &options->tcp_rcv_buf_poll; ++ goto parse_flag; ++ ++ case sHPNDisabled: ++ intptr = &options->hpn_disabled; ++ goto parse_flag; ++ ++ case sHPNBufferSize: ++ intptr = &options->hpn_buffer_size; ++ goto parse_int; ++ + case sIgnoreUserKnownHosts: + intptr = &options->ignore_user_known_hosts; + goto parse_flag; diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/openssh-5.2p1-hpn13v6.diff /usr/home/dindin/workspace/openssh-portable/files/openssh-5.2p1-hpn13v6.diff --- /usr/ports/security/openssh-portable/files/openssh-5.2p1-hpn13v6.diff 1970-01-01 03:00:00.000000000 +0300 +++ /usr/home/dindin/workspace/openssh-portable/files/openssh-5.2p1-hpn13v6.diff 2009-05-26 15:34:08.000000000 +0400 @@ -0,0 +1,3576 @@ +diff -NupwB auth2.c auth2.c +--- auth2.c 2008-11-05 00:20:46.000000000 -0500 ++++ auth2.c 2009-05-14 12:36:10.000000000 -0400 +@@ -49,6 +49,7 @@ + #include "dispatch.h" + #include "pathnames.h" + #include "buffer.h" ++#include "canohost.h" + + #ifdef GSSAPI + #include "ssh-gss.h" +@@ -75,6 +76,9 @@ extern Authmethod method_gssapi; + extern Authmethod method_jpake; + #endif + ++static int log_flag = 0; ++ ++ + Authmethod *authmethods[] = { + &method_none, + &method_pubkey, +@@ -225,6 +229,11 @@ input_userauth_request(int type, u_int32 + service = packet_get_string(NULL); + method = packet_get_string(NULL); + debug("userauth-request for user %s service %s method %s", user, service, method); ++ if (!log_flag) { ++ logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", ++ get_remote_ipaddr(), get_remote_port(), user); ++ log_flag = 1; ++ } + debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); + + if ((style = strchr(user, ':')) != NULL) +diff -NupwB buffer.c buffer.c +--- buffer.c 2006-08-04 22:39:39.000000000 -0400 ++++ buffer.c 2009-05-14 12:36:10.000000000 -0400 +@@ -127,7 +127,7 @@ restart: + + /* Increase the size of the buffer and retry. */ + newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ); +- if (newlen > BUFFER_MAX_LEN) ++ if (newlen > BUFFER_MAX_LEN_HPN) + fatal("buffer_append_space: alloc %u not supported", + newlen); + buffer->buf = xrealloc(buffer->buf, 1, newlen); +diff -NupwB buffer.h buffer.h +--- buffer.h 2008-05-19 00:59:37.000000000 -0400 ++++ buffer.h 2009-05-14 12:36:10.000000000 -0400 +@@ -16,6 +16,9 @@ + #ifndef BUFFER_H + #define BUFFER_H + ++/* move the following to a more appropriate place and name */ ++#define BUFFER_MAX_LEN_HPN 0x4000000 /* 64MB */ ++ + typedef struct { + u_char *buf; /* Buffer for data. */ + u_int alloc; /* Number of bytes allocated for data. */ +diff -NupwB channels.c channels.c +--- channels.c 2009-02-14 00:28:21.000000000 -0500 ++++ channels.c 2009-05-14 12:36:10.000000000 -0400 +@@ -169,8 +169,14 @@ static void port_open_helper(Channel *c, + static int connect_next(struct channel_connect *); + static void channel_connect_ctx_free(struct channel_connect *); + ++ ++static int hpn_disabled = 0; ++static int hpn_buffer_size = 2 * 1024 * 1024; ++ + /* -- channel core */ + ++ ++ + Channel * + channel_by_id(int id) + { +@@ -308,6 +314,7 @@ channel_new(char *ctype, int type, int r + c->local_window_max = window; + c->local_consumed = 0; + c->local_maxpacket = maxpack; ++ c->dynamic_window = 0; + c->remote_id = -1; + c->remote_name = xstrdup(remote_name); + c->remote_window = 0; +@@ -798,11 +805,35 @@ channel_pre_open_13(Channel *c, fd_set * + FD_SET(c->sock, writeset); + } + ++int channel_tcpwinsz () { ++ u_int32_t tcpwinsz = 0; ++ socklen_t optsz = sizeof(tcpwinsz); ++ int ret = -1; ++ ++ /* if we aren't on a socket return 128KB*/ ++ if(!packet_connection_is_on_socket()) ++ return(128*1024); ++ ret = getsockopt(packet_get_connection_in(), ++ SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); ++ /* return no more than 64MB */ ++ if ((ret == 0) && tcpwinsz > BUFFER_MAX_LEN_HPN) ++ tcpwinsz = BUFFER_MAX_LEN_HPN; ++ debug2("tcpwinsz: %d for connection: %d", tcpwinsz, ++ packet_get_connection_in()); ++ return(tcpwinsz); ++} ++ + static void + channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) + { + u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); + ++ /* check buffer limits */ ++ if ((!c->tcpwinsz) || (c->dynamic_window > 0)) ++ c->tcpwinsz = channel_tcpwinsz(); ++ ++ limit = MIN(limit, 2 * c->tcpwinsz); ++ + if (c->istate == CHAN_INPUT_OPEN && + limit > 0 && + buffer_len(&c->input) < limit && +@@ -1759,14 +1790,21 @@ channel_check_window(Channel *c) + c->local_maxpacket*3) || + c->local_window < c->local_window_max/2) && + c->local_consumed > 0) { ++ u_int addition = 0; ++ /* adjust max window size if we are in a dynamic environment */ ++ if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) { ++ /* grow the window somewhat aggressively to maintain pressure */ ++ addition = 1.5*(c->tcpwinsz - c->local_window_max); ++ c->local_window_max += addition; ++ } + packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); + packet_put_int(c->remote_id); +- packet_put_int(c->local_consumed); ++ packet_put_int(c->local_consumed + addition); + packet_send(); + debug2("channel %d: window %d sent adjust %d", + c->self, c->local_window, + c->local_consumed); +- c->local_window += c->local_consumed; ++ c->local_window += c->local_consumed + addition; + c->local_consumed = 0; + } + return 1; +@@ -1969,11 +2007,12 @@ channel_after_select(fd_set *readset, fd + + + /* If there is data to send to the connection, enqueue some of it now. */ +-void ++int + channel_output_poll(void) + { + Channel *c; + u_int i, len; ++ int packet_length = 0; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; +@@ -2013,7 +2052,7 @@ channel_output_poll(void) + packet_start(SSH2_MSG_CHANNEL_DATA); + packet_put_int(c->remote_id); + packet_put_string(data, dlen); +- packet_send(); ++ packet_length = packet_send(); + c->remote_window -= dlen + 4; + xfree(data); + } +@@ -2043,7 +2082,7 @@ channel_output_poll(void) + SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA); + packet_put_int(c->remote_id); + packet_put_string(buffer_ptr(&c->input), len); +- packet_send(); ++ packet_length = packet_send(); + buffer_consume(&c->input, len); + c->remote_window -= len; + } +@@ -2078,12 +2117,13 @@ channel_output_poll(void) + packet_put_int(c->remote_id); + packet_put_int(SSH2_EXTENDED_DATA_STDERR); + packet_put_string(buffer_ptr(&c->extended), len); +- packet_send(); ++ packet_length = packet_send(); + buffer_consume(&c->extended, len); + c->remote_window -= len; + debug2("channel %d: sent ext data %d", c->self, len); + } + } ++ return (packet_length); + } + + +@@ -2459,6 +2499,15 @@ channel_set_af(int af) + IPv4or6 = af; + } + ++ ++void ++channel_set_hpn(int external_hpn_disabled, int external_hpn_buffer_size) ++{ ++ hpn_disabled = external_hpn_disabled; ++ hpn_buffer_size = external_hpn_buffer_size; ++ debug("HPN Disabled: %d, HPN Buffer Size: %d", hpn_disabled, hpn_buffer_size); ++} ++ + static int + channel_setup_fwd_listener(int type, const char *listen_addr, + u_short listen_port, int *allocated_listen_port, +@@ -2610,9 +2659,15 @@ channel_setup_fwd_listener(int type, con + } + + /* Allocate a channel number for the socket. */ ++ /* explicitly test for hpn disabled option. if true use smaller window size */ ++ if (hpn_disabled) + c = channel_new("port listener", type, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, + 0, "port listener", 1); ++ else ++ c = channel_new("port listener", type, sock, sock, -1, ++ hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, ++ 0, "port listener", 1); + c->path = xstrdup(host); + c->host_port = port_to_connect; + c->listening_port = listen_port; +@@ -3151,10 +3206,17 @@ x11_create_display_inet(int x11_display_ + *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); + for (n = 0; n < num_socks; n++) { + sock = socks[n]; ++ /* Is this really necassary? */ ++ if (hpn_disabled) + nc = channel_new("x11 listener", + SSH_CHANNEL_X11_LISTENER, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, + 0, "X11 inet listener", 1); ++ else ++ nc = channel_new("x11 listener", ++ SSH_CHANNEL_X11_LISTENER, sock, sock, -1, ++ hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, ++ 0, "X11 inet listener", 1); + nc->single_connection = single_connection; + (*chanids)[n] = nc->self; + } +diff -NupwB channels.h channels.h +--- channels.h 2009-02-14 00:28:21.000000000 -0500 ++++ channels.h 2009-05-14 12:36:10.000000000 -0400 +@@ -115,8 +115,10 @@ struct Channel { + u_int local_window_max; + u_int local_consumed; + u_int local_maxpacket; ++ int dynamic_window; + int extended_usage; + int single_connection; ++ u_int tcpwinsz; + + char *ctype; /* type */ + +@@ -146,9 +148,11 @@ struct Channel { + + /* default window/packet sizes for tcp/x11-fwd-channel */ + #define CHAN_SES_PACKET_DEFAULT (32*1024) +-#define CHAN_SES_WINDOW_DEFAULT (64*CHAN_SES_PACKET_DEFAULT) ++#define CHAN_SES_WINDOW_DEFAULT (4*CHAN_SES_PACKET_DEFAULT) ++ + #define CHAN_TCP_PACKET_DEFAULT (32*1024) +-#define CHAN_TCP_WINDOW_DEFAULT (64*CHAN_TCP_PACKET_DEFAULT) ++#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT) ++ + #define CHAN_X11_PACKET_DEFAULT (16*1024) + #define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) + +@@ -221,7 +225,7 @@ void channel_input_status_confirm(int, + + void channel_prepare_select(fd_set **, fd_set **, int *, u_int*, int); + void channel_after_select(fd_set *, fd_set *); +-void channel_output_poll(void); ++int channel_output_poll(void); + + int channel_not_very_much_buffered_data(void); + void channel_close_all(void); +@@ -277,4 +281,7 @@ void chan_rcvd_ieof(Channel *); + void chan_write_failed(Channel *); + void chan_obuf_empty(Channel *); + ++/* hpn handler */ ++void channel_set_hpn(int, int); ++ + #endif +diff -NupwB cipher.c cipher.c +--- cipher.c 2009-01-28 00:38:41.000000000 -0500 ++++ cipher.c 2009-05-14 12:36:10.000000000 -0400 +@@ -55,6 +55,7 @@ extern const EVP_CIPHER *evp_ssh1_bf(voi + extern const EVP_CIPHER *evp_ssh1_3des(void); + extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); + extern const EVP_CIPHER *evp_aes_128_ctr(void); ++extern const EVP_CIPHER *evp_aes_ctr_mt(void); + extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); + + struct Cipher { +@@ -82,9 +83,9 @@ struct Cipher { + { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, + { "rijndael-cbc@lysator.liu.se", + SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, +- { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr }, +- { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr }, +- { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr }, ++ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_ctr_mt }, ++ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_ctr_mt }, ++ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_ctr_mt }, + #ifdef USE_CIPHER_ACSS + { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss }, + #endif +@@ -163,7 +164,8 @@ ciphers_valid(const char *names) + 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) { ++ if (c == NULL || (c->number != SSH_CIPHER_SSH2 && ++c->number != SSH_CIPHER_NONE)) { + debug("bad cipher %s [%s]", p, names); + xfree(cipher_list); + return 0; +@@ -337,6 +339,7 @@ cipher_get_keyiv(CipherContext *cc, u_ch + int evplen; + + switch (c->number) { ++ case SSH_CIPHER_NONE: + case SSH_CIPHER_SSH2: + case SSH_CIPHER_DES: + case SSH_CIPHER_BLOWFISH: +@@ -371,6 +374,7 @@ cipher_set_keyiv(CipherContext *cc, u_ch + int evplen = 0; + + switch (c->number) { ++ case SSH_CIPHER_NONE: + case SSH_CIPHER_SSH2: + case SSH_CIPHER_DES: + case SSH_CIPHER_BLOWFISH: +diff -NupwB cipher-ctr-mt.c cipher-ctr-mt.c +--- cipher-ctr-mt.c 1969-12-31 19:00:00.000000000 -0500 ++++ cipher-ctr-mt.c 2009-05-14 12:36:10.000000000 -0400 +@@ -0,0 +1,473 @@ ++/* ++ * OpenSSH Multi-threaded AES-CTR Cipher ++ * ++ * Author: Benjamin Bennett ++ * Copyright (c) 2008 Pittsburgh Supercomputing Center. All rights reserved. ++ * ++ * Based on original OpenSSH AES-CTR cipher. Small portions remain unchanged, ++ * Copyright (c) 2003 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. ++ */ ++#include "includes.h" ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "log.h" ++ ++/* compatibility with old or broken OpenSSL versions */ ++#include "openbsd-compat/openssl-compat.h" ++ ++#ifndef USE_BUILTIN_RIJNDAEL ++#include ++#endif ++ ++#include ++ ++/*-------------------- TUNABLES --------------------*/ ++/* Number of pregen threads to use */ ++#define CIPHER_THREADS 2 ++ ++/* Number of keystream queues */ ++#define NUMKQ (CIPHER_THREADS + 2) ++ ++/* Length of a keystream queue */ ++#define KQLEN 4096 ++ ++/* Processor cacheline length */ ++#define CACHELINE_LEN 64 ++ ++/* Collect thread stats and print at cancellation when in debug mode */ ++/* #define CIPHER_THREAD_STATS */ ++ ++/* Use single-byte XOR instead of 8-byte XOR */ ++/* #define CIPHER_BYTE_XOR */ ++/*-------------------- END TUNABLES --------------------*/ ++ ++ ++const EVP_CIPHER *evp_aes_ctr_mt(void); ++ ++#ifdef CIPHER_THREAD_STATS ++/* ++ * Struct to collect thread stats ++ */ ++struct thread_stats { ++ u_int fills; ++ u_int skips; ++ u_int waits; ++ u_int drains; ++}; ++ ++/* ++ * Debug print the thread stats ++ * Use with pthread_cleanup_push for displaying at thread cancellation ++ */ ++static void ++thread_loop_stats(void *x) ++{ ++ struct thread_stats *s = x; ++ ++ debug("tid %lu - %u fills, %u skips, %u waits", pthread_self(), ++ s->fills, s->skips, s->waits); ++} ++ ++ #define STATS_STRUCT(s) struct thread_stats s ++ #define STATS_INIT(s) { memset(&s, 0, sizeof(s)); } ++ #define STATS_FILL(s) { s.fills++; } ++ #define STATS_SKIP(s) { s.skips++; } ++ #define STATS_WAIT(s) { s.waits++; } ++ #define STATS_DRAIN(s) { s.drains++; } ++#else ++ #define STATS_STRUCT(s) ++ #define STATS_INIT(s) ++ #define STATS_FILL(s) ++ #define STATS_SKIP(s) ++ #define STATS_WAIT(s) ++ #define STATS_DRAIN(s) ++#endif ++ ++/* Keystream Queue state */ ++enum { ++ KQINIT, ++ KQEMPTY, ++ KQFILLING, ++ KQFULL, ++ KQDRAINING ++}; ++ ++/* Keystream Queue struct */ ++struct kq { ++ u_char keys[KQLEN][AES_BLOCK_SIZE]; ++ u_char ctr[AES_BLOCK_SIZE]; ++ u_char pad0[CACHELINE_LEN]; ++ volatile int qstate; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++ u_char pad1[CACHELINE_LEN]; ++}; ++ ++/* Context struct */ ++struct ssh_aes_ctr_ctx ++{ ++ struct kq q[NUMKQ]; ++ AES_KEY aes_ctx; ++ STATS_STRUCT(stats); ++ u_char aes_counter[AES_BLOCK_SIZE]; ++ pthread_t tid[CIPHER_THREADS]; ++ int state; ++ int qidx; ++ int ridx; ++}; ++ ++/* ++ * 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 void ++ssh_ctr_inc(u_char *ctr, u_int len) ++{ ++ int i; ++ ++ for (i = len - 1; i >= 0; i--) ++ if (++ctr[i]) /* continue on overflow */ ++ return; ++} ++ ++/* ++ * Add num to counter 'ctr' ++ */ ++static void ++ssh_ctr_add(u_char *ctr, uint32_t num, u_int len) ++{ ++ int i; ++ uint16_t n; ++ ++ for (n = 0, i = len - 1; i >= 0 && (num || n); i--) { ++ n = ctr[i] + (num & 0xff) + n; ++ num >>= 8; ++ ctr[i] = n & 0xff; ++ n >>= 8; ++ } ++} ++ ++/* ++ * Threads may be cancelled in a pthread_cond_wait, we must free the mutex ++ */ ++static void ++thread_loop_cleanup(void *x) ++{ ++ pthread_mutex_unlock((pthread_mutex_t *)x); ++} ++ ++/* ++ * The life of a pregen thread: ++ * Find empty keystream queues and fill them using their counter. ++ * When done, update counter for the next fill. ++ */ ++static void * ++thread_loop(void *x) ++{ ++ AES_KEY key; ++ STATS_STRUCT(stats); ++ struct ssh_aes_ctr_ctx *c = x; ++ struct kq *q; ++ int i; ++ int qidx; ++ ++ /* Threads stats on cancellation */ ++ STATS_INIT(stats); ++#ifdef CIPHER_THREAD_STATS ++ pthread_cleanup_push(thread_loop_stats, &stats); ++#endif ++ ++ /* Thread local copy of AES key */ ++ memcpy(&key, &c->aes_ctx, sizeof(key)); ++ ++ /* ++ * Handle the special case of startup, one thread must fill ++ * the first KQ then mark it as draining. Lock held throughout. ++ */ ++ if (pthread_equal(pthread_self(), c->tid[0])) { ++ q = &c->q[0]; ++ pthread_mutex_lock(&q->lock); ++ if (q->qstate == KQINIT) { ++ for (i = 0; i < KQLEN; i++) { ++ AES_encrypt(q->ctr, q->keys[i], &key); ++ ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); ++ } ++ ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE); ++ q->qstate = KQDRAINING; ++ STATS_FILL(stats); ++ pthread_cond_broadcast(&q->cond); ++ } ++ pthread_mutex_unlock(&q->lock); ++ } ++ else ++ STATS_SKIP(stats); ++ ++ /* ++ * Normal case is to find empty queues and fill them, skipping over ++ * queues already filled by other threads and stopping to wait for ++ * a draining queue to become empty. ++ * ++ * Multiple threads may be waiting on a draining queue and awoken ++ * when empty. The first thread to wake will mark it as filling, ++ * others will move on to fill, skip, or wait on the next queue. ++ */ ++ for (qidx = 1;; qidx = (qidx + 1) % NUMKQ) { ++ /* Check if I was cancelled, also checked in cond_wait */ ++ pthread_testcancel(); ++ ++ /* Lock queue and block if its draining */ ++ q = &c->q[qidx]; ++ pthread_mutex_lock(&q->lock); ++ pthread_cleanup_push(thread_loop_cleanup, &q->lock); ++ while (q->qstate == KQDRAINING || q->qstate == KQINIT) { ++ STATS_WAIT(stats); ++ pthread_cond_wait(&q->cond, &q->lock); ++ } ++ pthread_cleanup_pop(0); ++ ++ /* If filling or full, somebody else got it, skip */ ++ if (q->qstate != KQEMPTY) { ++ pthread_mutex_unlock(&q->lock); ++ STATS_SKIP(stats); ++ continue; ++ } ++ ++ /* ++ * Empty, let's fill it. ++ * Queue lock is relinquished while we do this so others ++ * can see that it's being filled. ++ */ ++ q->qstate = KQFILLING; ++ pthread_mutex_unlock(&q->lock); ++ for (i = 0; i < KQLEN; i++) { ++ AES_encrypt(q->ctr, q->keys[i], &key); ++ ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); ++ } ++ ++ /* Re-lock, mark full and signal consumer */ ++ pthread_mutex_lock(&q->lock); ++ ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE); ++ q->qstate = KQFULL; ++ STATS_FILL(stats); ++ pthread_cond_signal(&q->cond); ++ pthread_mutex_unlock(&q->lock); ++ } ++ ++#ifdef CIPHER_THREAD_STATS ++ /* Stats */ ++ pthread_cleanup_pop(1); ++#endif ++ ++ return NULL; ++} ++ ++static int ++ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, ++ u_int len) ++{ ++ struct ssh_aes_ctr_ctx *c; ++ struct kq *q, *oldq; ++ int ridx; ++ u_char *buf; ++ ++ if (len == 0) ++ return (1); ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) ++ return (0); ++ ++ q = &c->q[c->qidx]; ++ ridx = c->ridx; ++ ++ /* src already padded to block multiple */ ++ while (len > 0) { ++ buf = q->keys[ridx]; ++ ++#ifdef CIPHER_BYTE_XOR ++ dest[0] = src[0] ^ buf[0]; ++ dest[1] = src[1] ^ buf[1]; ++ dest[2] = src[2] ^ buf[2]; ++ dest[3] = src[3] ^ buf[3]; ++ dest[4] = src[4] ^ buf[4]; ++ dest[5] = src[5] ^ buf[5]; ++ dest[6] = src[6] ^ buf[6]; ++ dest[7] = src[7] ^ buf[7]; ++ dest[8] = src[8] ^ buf[8]; ++ dest[9] = src[9] ^ buf[9]; ++ dest[10] = src[10] ^ buf[10]; ++ dest[11] = src[11] ^ buf[11]; ++ dest[12] = src[12] ^ buf[12]; ++ dest[13] = src[13] ^ buf[13]; ++ dest[14] = src[14] ^ buf[14]; ++ dest[15] = src[15] ^ buf[15]; ++#else ++ *(uint64_t *)dest = *(uint64_t *)src ^ *(uint64_t *)buf; ++ *(uint64_t *)(dest + 8) = *(uint64_t *)(src + 8) ^ ++ *(uint64_t *)(buf + 8); ++#endif ++ ++ dest += 16; ++ src += 16; ++ len -= 16; ++ ssh_ctr_inc(ctx->iv, AES_BLOCK_SIZE); ++ ++ /* Increment read index, switch queues on rollover */ ++ if ((ridx = (ridx + 1) % KQLEN) == 0) { ++ oldq = q; ++ ++ /* Mark next queue draining, may need to wait */ ++ c->qidx = (c->qidx + 1) % NUMKQ; ++ q = &c->q[c->qidx]; ++ pthread_mutex_lock(&q->lock); ++ while (q->qstate != KQFULL) { ++ STATS_WAIT(c->stats); ++ pthread_cond_wait(&q->cond, &q->lock); ++ } ++ q->qstate = KQDRAINING; ++ pthread_mutex_unlock(&q->lock); ++ ++ /* Mark consumed queue empty and signal producers */ ++ pthread_mutex_lock(&oldq->lock); ++ oldq->qstate = KQEMPTY; ++ STATS_DRAIN(c->stats); ++ pthread_cond_broadcast(&oldq->cond); ++ pthread_mutex_unlock(&oldq->lock); ++ } ++ } ++ c->ridx = ridx; ++ return (1); ++} ++ ++#define HAVE_NONE 0 ++#define HAVE_KEY 1 ++#define HAVE_IV 2 ++static int ++ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, ++ int enc) ++{ ++ struct ssh_aes_ctr_ctx *c; ++ int i; ++ ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { ++ c = xmalloc(sizeof(*c)); ++ ++ c->state = HAVE_NONE; ++ for (i = 0; i < NUMKQ; i++) { ++ pthread_mutex_init(&c->q[i].lock, NULL); ++ pthread_cond_init(&c->q[i].cond, NULL); ++ } ++ ++ STATS_INIT(c->stats); ++ ++ EVP_CIPHER_CTX_set_app_data(ctx, c); ++ } ++ ++ if (c->state == (HAVE_KEY | HAVE_IV)) { ++ /* Cancel pregen threads */ ++ for (i = 0; i < CIPHER_THREADS; i++) ++ pthread_cancel(c->tid[i]); ++ for (i = 0; i < CIPHER_THREADS; i++) ++ pthread_join(c->tid[i], NULL); ++ /* Start over getting key & iv */ ++ c->state = HAVE_NONE; ++ } ++ ++ if (key != NULL) { ++ AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, ++ &c->aes_ctx); ++ c->state |= HAVE_KEY; ++ } ++ ++ if (iv != NULL) { ++ memcpy(ctx->iv, iv, AES_BLOCK_SIZE); ++ c->state |= HAVE_IV; ++ } ++ ++ if (c->state == (HAVE_KEY | HAVE_IV)) { ++ /* Clear queues */ ++ memcpy(c->q[0].ctr, ctx->iv, AES_BLOCK_SIZE); ++ c->q[0].qstate = KQINIT; ++ for (i = 1; i < NUMKQ; i++) { ++ memcpy(c->q[i].ctr, ctx->iv, AES_BLOCK_SIZE); ++ ssh_ctr_add(c->q[i].ctr, i * KQLEN, AES_BLOCK_SIZE); ++ c->q[i].qstate = KQEMPTY; ++ } ++ c->qidx = 0; ++ c->ridx = 0; ++ ++ /* Start threads */ ++ for (i = 0; i < CIPHER_THREADS; i++) { ++ pthread_create(&c->tid[i], NULL, thread_loop, c); ++ } ++ pthread_mutex_lock(&c->q[0].lock); ++ while (c->q[0].qstate != KQDRAINING) ++ pthread_cond_wait(&c->q[0].cond, &c->q[0].lock); ++ pthread_mutex_unlock(&c->q[0].lock); ++ ++ } ++ return (1); ++} ++ ++static int ++ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) ++{ ++ struct ssh_aes_ctr_ctx *c; ++ int i; ++ ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { ++#ifdef CIPHER_THREAD_STATS ++ debug("main thread: %u drains, %u waits", c->stats.drains, ++ c->stats.waits); ++#endif ++ /* Cancel pregen threads */ ++ for (i = 0; i < CIPHER_THREADS; i++) ++ pthread_cancel(c->tid[i]); ++ for (i = 0; i < CIPHER_THREADS; i++) ++ pthread_join(c->tid[i], NULL); ++ ++ memset(c, 0, sizeof(*c)); ++ xfree(c); ++ EVP_CIPHER_CTX_set_app_data(ctx, NULL); ++ } ++ return (1); ++} ++ ++/* */ ++const EVP_CIPHER * ++evp_aes_ctr_mt(void) ++{ ++ static EVP_CIPHER aes_ctr; ++ ++ memset(&aes_ctr, 0, sizeof(EVP_CIPHER)); ++ aes_ctr.nid = NID_undef; ++ aes_ctr.block_size = AES_BLOCK_SIZE; ++ aes_ctr.iv_len = AES_BLOCK_SIZE; ++ aes_ctr.key_len = 16; ++ aes_ctr.init = ssh_aes_ctr_init; ++ aes_ctr.cleanup = ssh_aes_ctr_cleanup; ++ aes_ctr.do_cipher = ssh_aes_ctr; ++#ifndef SSH_OLD_EVP ++ aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | ++ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; ++#endif ++ return (&aes_ctr); ++} +diff -NupwB clientloop.c clientloop.c +--- clientloop.c 2009-02-14 00:28:21.000000000 -0500 ++++ clientloop.c 2009-05-14 12:36:10.000000000 -0400 +@@ -1688,9 +1688,15 @@ client_request_x11(const char *request_t + sock = x11_connect_display(); + if (sock < 0) + return NULL; ++ /* again is this really necessary for X11? */ ++ if (options.hpn_disabled) + c = channel_new("x11", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); ++ else ++ c = channel_new("x11", ++ SSH_CHANNEL_X11_OPEN, sock, sock, -1, ++ options.hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); + c->force_drain = 1; + return c; + } +@@ -1710,9 +1716,15 @@ client_request_agent(const char *request + sock = ssh_get_authentication_socket(); + if (sock < 0) + return NULL; ++ if (options.hpn_disabled) + c = channel_new("authentication agent connection", + SSH_CHANNEL_OPEN, sock, sock, -1, +- CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, ++ CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, ++ "authentication agent connection", 1); ++ else ++ c = channel_new("authentication agent connection", ++ SSH_CHANNEL_OPEN, sock, sock, -1, ++ options.hpn_buffer_size, options.hpn_buffer_size, 0, + "authentication agent connection", 1); + c->force_drain = 1; + return c; +@@ -1740,10 +1752,18 @@ client_request_tun_fwd(int tun_mode, int + return -1; + } + ++ if(options.hpn_disabled) ++ c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, ++ CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, ++ 0, "tun", 1); ++ else + c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, +- CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); ++ options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, ++ 0, "tun", 1); + c->datagram = 1; + ++ ++ + #if defined(SSH_TUN_FILTER) + if (options.tun_open == SSH_TUNMODE_POINTOPOINT) + channel_register_filter(c->self, sys_tun_infilter, +diff -NupwB compat.c compat.c +--- compat.c 2008-11-03 03:20:14.000000000 -0500 ++++ compat.c 2009-05-14 12:36:10.000000000 -0400 +@@ -170,6 +170,15 @@ compat_datafellows(const char *version) + strlen(check[i].pat), 0) == 1) { + debug("match: %s pat %s", version, check[i].pat); + datafellows = check[i].bugs; ++ /* Check to see if the remote side is OpenSSH and not HPN */ ++ if(strstr(version,"OpenSSH") != NULL) ++ { ++ if (strstr(version,"hpn") == NULL) ++ { ++ datafellows |= SSH_BUG_LARGEWINDOW; ++ debug("Remote is NON-HPN aware"); ++ } ++ } + return; + } + } +diff -NupwB compat.h compat.h +--- compat.h 2008-11-03 03:20:14.000000000 -0500 ++++ compat.h 2009-05-14 12:36:10.000000000 -0400 +@@ -58,6 +58,7 @@ + #define SSH_OLD_FORWARD_ADDR 0x01000000 + #define SSH_BUG_RFWD_ADDR 0x02000000 + #define SSH_NEW_OPENSSH 0x04000000 ++#define SSH_BUG_LARGEWINDOW 0x08000000 + + void enable_compat13(void); + void enable_compat20(void); +Common subdirectories: contrib and contrib +diff -NupwB HPN-README HPN-README +--- HPN-README 1969-12-31 19:00:00.000000000 -0500 ++++ HPN-README 2009-05-14 12:36:10.000000000 -0400 +@@ -0,0 +1,128 @@ ++Notes: ++ ++MULTI-THREADED CIPHER: ++The AES cipher in CTR mode has been multithreaded (MTR-AES-CTR). This will allow ssh installations ++on hosts with multiple cores to use more than one processing core during encryption. ++Tests have show significant throughput performance increases when using MTR-AES-CTR up ++to and including a full gigabit per second on quad core systems. It should be possible to ++achieve full line rate on dual core systems but OS and data management overhead makes this ++more difficult to achieve. The cipher stream from MTR-AES-CTR is entirely compatible with single ++thread AES-CTR (ST-AES-CTR) implementations and should be 100% backward compatible. Optimal ++performance requires the MTR-AES-CTR mode be enabled on both ends of the connection. ++The MTR-AES-CTR replaces ST-AES-CTR and is used in exactly the same way with the same ++nomenclature. ++Use examples: ssh -caes128-ctr you@host.com ++ scp -oCipher=aes256-ctr file you@host.com:~/file ++ ++NONE CIPHER: ++To use the NONE option you must have the NoneEnabled switch set on the server and ++you *must* have *both* NoneEnabled and NoneSwitch set to yes on the client. The NONE ++feature works with ALL ssh subsystems (as far as we can tell) *AS LONG AS* a tty is not ++spawned. If a user uses the -T switch to prevent a tty being created the NONE cipher will ++be disabled. ++ ++The performance increase will only be as good as the network and TCP stack tuning ++on the reciever side of the connection allows. As a rule of thumb a user will need ++at least 10Mb/s connection with a 100ms RTT to see a doubling of performance. The ++HPN-SSH home page describes this in greater detail. ++ ++http://www.psc.edu/networking/projects/hpn-ssh ++ ++BUFFER SIZES: ++ ++If HPN is disabled the receive buffer size will be set to the ++OpenSSH default of 64K. ++ ++If an HPN system connects to a nonHPN system the receive buffer will ++be set to the HPNBufferSize value. The default is 2MB but user adjustable. ++ ++If an HPN to HPN connection is established a number of different things might ++happen based on the user options and conditions. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set ++HPN Buffer Size = up to 64MB ++This is the default state. The HPN buffer size will grow to a maximum of 64MB ++as the TCP receive buffer grows. The maximum HPN Buffer size of 64MB is ++geared towards 10GigE transcontinental connections. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set ++HPN Buffer Size = TCP receive buffer value. ++Users on non-autotuning systesm should disable TCPRcvBufPoll in the ++ssh_cofig and sshd_config ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set ++HPN Buffer Size = minmum of TCP receive buffer and HPNBufferSize. ++This would be the system defined TCP receive buffer (RWIN). ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf SET ++HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. ++Generally there is no need to set both. ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set ++HPN Buffer Size = grows to HPNBufferSize ++The buffer will grow up to the maximum size specified here. ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf SET ++HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. ++Generally there is no need to set both of these, especially on autotuning ++systems. However, if the users wishes to override the autotuning this would be ++one way to do it. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf SET ++HPN Buffer Size = TCPRcvBuf. ++This will override autotuning and set the TCP recieve buffer to the user defined ++value. ++ ++ ++HPN Specific Configuration options ++ ++TcpRcvBuf=[int]KB client ++ set the TCP socket receive buffer to n Kilobytes. It can be set up to the ++maximum socket size allowed by the system. This is useful in situations where ++the tcp receive window is set low but the maximum buffer size is set ++higher (as is typical). This works on a per TCP connection basis. You can also ++use this to artifically limit the transfer rate of the connection. In these ++cases the throughput will be no more than n/RTT. The minimum buffer size is 1KB. ++Default is the current system wide tcp receive buffer size. ++ ++TcpRcvBufPoll=[yes/no] client/server ++ enable of disable the polling of the tcp receive buffer through the life ++of the connection. You would want to make sure that this option is enabled ++for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista) ++default is yes. ++ ++NoneEnabled=[yes/no] client/server ++ enable or disable the use of the None cipher. Care must always be used ++when enabling this as it will allow users to send data in the clear. However, ++it is important to note that authentication information remains encrypted ++even if this option is enabled. Set to no by default. ++ ++NoneSwitch=[yes/no] client ++ Switch the encryption cipher being used to the None cipher after ++authentication takes place. NoneEnabled must be enabled on both the client ++and server side of the connection. When the connection switches to the NONE ++cipher a warning is sent to STDERR. The connection attempt will fail with an ++error if a client requests a NoneSwitch from the server that does not explicitly ++have NoneEnabled set to yes. Note: The NONE cipher cannot be used in ++interactive (shell) sessions and it will fail silently. Set to no by default. ++ ++HPNDisabled=[yes/no] client/server ++ In some situations, such as transfers on a local area network, the impact ++of the HPN code produces a net decrease in performance. In these cases it is ++helpful to disable the HPN functionality. By default HPNDisabled is set to no. ++ ++HPNBufferSize=[int]KB client/server ++ This is the default buffer size the HPN functionality uses when interacting ++with nonHPN SSH installations. Conceptually this is similar to the TcpRcvBuf ++option as applied to the internal SSH flow control. This value can range from ++1KB to 64MB (1-65536). Use of oversized or undersized buffers can cause performance ++problems depending on the length of the network path. The default size of this buffer ++is 2MB. ++ ++ ++Credits: This patch was conceived, designed, and led by Chris Rapier (rapier@psc.edu) ++ The majority of the actual coding for versions up to HPN12v1 was performed ++ by Michael Stevens (mstevens@andrew.cmu.edu). The MT-AES-CTR cipher was ++ implemented by Ben Bennet (ben@psc.edu). This work was financed, in part, ++ by Cisco System, Inc., the National Library of Medicine, ++ and the National Science Foundation. +diff -NupwB kex.c kex.c +--- kex.c 2008-11-03 03:19:12.000000000 -0500 ++++ kex.c 2009-05-14 12:36:10.000000000 -0400 +@@ -48,6 +48,7 @@ + #include "match.h" + #include "dispatch.h" + #include "monitor.h" ++#include "canohost.h" + + #define KEX_COOKIE_LEN 16 + +@@ -64,7 +65,8 @@ static void kex_kexinit_finish(Kex *); + static void kex_choose_conf(Kex *); + + /* put algorithm proposal into buffer */ +-static void ++/* used in sshconnect.c as well as kex.c */ ++void + kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) + { + u_int i; +@@ -376,6 +378,13 @@ kex_choose_conf(Kex *kex) + int nenc, nmac, ncomp; + u_int mode, ctos, need; + int first_kex_follows, type; ++ int log_flag = 0; ++ ++ int auth_flag; ++ ++ auth_flag = packet_authentication_state(); ++ ++ debug ("AUTH STATE IS %d", auth_flag); + + my = kex_buf2prop(&kex->my, NULL); + peer = kex_buf2prop(&kex->peer, &first_kex_follows); +@@ -400,11 +409,34 @@ kex_choose_conf(Kex *kex) + choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]); + choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]); + choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); ++ debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); ++ if (strcmp(newkeys->enc.name, "none") == 0) { ++ debug("Requesting NONE. Authflag is %d", auth_flag); ++ if (auth_flag == 1) { ++ debug("None requested post authentication."); ++ } else { ++ fatal("Pre-authentication none cipher requests are not allowed."); ++ } ++ } + debug("kex: %s %s %s %s", + ctos ? "client->server" : "server->client", + newkeys->enc.name, + newkeys->mac.name, + newkeys->comp.name); ++ /* client starts withctos = 0 && log flag = 0 and no log*/ ++ /* 2nd client pass ctos=1 and flag = 1 so no log*/ ++ /* server starts with ctos =1 && log_flag = 0 so log */ ++ /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/ ++ /* -cjr*/ ++ if (ctos && !log_flag) { ++ logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s", ++ get_remote_ipaddr(), ++ get_remote_port(), ++ newkeys->enc.name, ++ newkeys->mac.name, ++ newkeys->comp.name); ++ } ++ log_flag = 1; + } + choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); + choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], +diff -NupwB kex.h kex.h +--- kex.h 2007-06-11 00:01:42.000000000 -0400 ++++ kex.h 2009-05-14 12:36:10.000000000 -0400 +@@ -127,6 +127,8 @@ struct Kex { + void (*kex[KEX_MAX])(Kex *); + }; + ++void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]); ++ + Kex *kex_setup(char *[PROPOSAL_MAX]); + void kex_finish(Kex *); + +diff -NupwB Makefile.in Makefile.in +--- Makefile.in 2008-11-05 00:20:46.000000000 -0500 ++++ Makefile.in 2009-05-14 12:36:10.000000000 -0400 +@@ -43,7 +43,7 @@ CC=@CC@ + LD=@LD@ + CFLAGS=@CFLAGS@ + CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ +-LIBS=@LIBS@ ++LIBS=@LIBS@ -lpthread + SSHDLIBS=@SSHDLIBS@ + LIBEDIT=@LIBEDIT@ + AR=@AR@ +@@ -64,7 +64,7 @@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-a + + LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ + canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ +- cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ ++ cipher-bf1.o cipher-ctr.o cipher-ctr-mt.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 \ + readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ +diff -NupwB myproposal.h myproposal.h +--- myproposal.h 2009-01-28 00:33:31.000000000 -0500 ++++ myproposal.h 2009-05-14 12:36:10.000000000 -0400 +@@ -47,6 +47,8 @@ + "arcfour256,arcfour128," \ + "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ + "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" ++#define KEX_ENCRYPT_INCLUDE_NONE KEX_DEFAULT_ENCRYPT \ ++ ",none" + #define KEX_DEFAULT_MAC \ + "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160," \ + "hmac-ripemd160@openssh.com," \ +Common subdirectories: openbsd-compat and openbsd-compat +diff -NupwB packet.c packet.c +--- packet.c 2009-02-14 00:35:01.000000000 -0500 ++++ packet.c 2009-05-14 12:36:10.000000000 -0400 +@@ -775,7 +775,7 @@ packet_enable_delayed_compress(void) + /* + * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) + */ +-static void ++static int + packet_send2_wrapped(void) + { + u_char type, *cp, *macbuf = NULL; +@@ -888,11 +888,13 @@ packet_send2_wrapped(void) + set_newkeys(MODE_OUT); + else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side) + packet_enable_delayed_compress(); ++ return(packet_length); + } + +-static void ++static int + packet_send2(void) + { ++ static int packet_length = 0; + static int rekeying = 0; + struct packet *p; + u_char type, *cp; +@@ -910,7 +912,7 @@ packet_send2(void) + memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); + buffer_init(&outgoing_packet); + TAILQ_INSERT_TAIL(&outgoing, p, next); +- return; ++ return(sizeof(Buffer)); + } + } + +@@ -918,7 +920,7 @@ packet_send2(void) + if (type == SSH2_MSG_KEXINIT) + rekeying = 1; + +- packet_send2_wrapped(); ++ packet_length = packet_send2_wrapped(); + + /* after a NEWKEYS message we can send the complete queue */ + if (type == SSH2_MSG_NEWKEYS) { +@@ -931,19 +933,22 @@ packet_send2(void) + sizeof(Buffer)); + TAILQ_REMOVE(&outgoing, p, next); + xfree(p); +- packet_send2_wrapped(); ++ packet_length += packet_send2_wrapped(); + } + } ++ return(packet_length); + } + +-void ++int + packet_send(void) + { ++ int packet_len = 0; + if (compat20) +- packet_send2(); ++ packet_len = packet_send2(); + else + packet_send1(); + DBG(debug("packet_send done")); ++ return(packet_len); + } + + /* +@@ -1544,23 +1549,25 @@ packet_disconnect(const char *fmt,...) + + /* Checks if there is any buffered output, and tries to write some of the output. */ + +-void ++int + packet_write_poll(void) + { +- int len = buffer_len(&output); ++ int len = 0; ++ len = buffer_len(&output); + + if (len > 0) { + len = write(connection_out, buffer_ptr(&output), len); + if (len == -1) { + if (errno == EINTR || errno == EAGAIN || + errno == EWOULDBLOCK) +- return; ++ return (0); + fatal("Write failed: %.100s", strerror(errno)); + } + if (len == 0) + fatal("Write connection closed"); + buffer_consume(&output, len); + } ++ return(len); + } + + +@@ -1569,16 +1576,17 @@ packet_write_poll(void) + * written. + */ + +-void ++int + packet_write_wait(void) + { + fd_set *setp; + int ret, ms_remain; + struct timeval start, timeout, *timeoutp = NULL; ++ u_int bytes_sent = 0; + + setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), + sizeof(fd_mask)); +- packet_write_poll(); ++ bytes_sent += packet_write_poll(); + while (packet_have_data_to_write()) { + memset(setp, 0, howmany(connection_out + 1, NFDBITS) * + sizeof(fd_mask)); +@@ -1612,7 +1620,7 @@ packet_write_wait(void) + "waiting to write", get_remote_ipaddr()); + cleanup_exit(255); + } +- packet_write_poll(); ++ bytes_sent += packet_write_poll(); + } + xfree(setp); + } +@@ -1736,12 +1744,24 @@ packet_send_ignore(int nbytes) + } + } + ++int rekey_requested = 0; ++void ++packet_request_rekeying(void) ++{ ++ rekey_requested = 1; ++} ++ + #define MAX_PACKETS (1U<<31) + int + packet_need_rekeying(void) + { + if (datafellows & SSH_BUG_NOREKEY) + return 0; ++ if (rekey_requested == 1) ++ { ++ rekey_requested = 0; ++ return 1; ++ } + return + (p_send.packets > MAX_PACKETS) || + (p_read.packets > MAX_PACKETS) || +@@ -1766,3 +1786,9 @@ packet_set_authenticated(void) + { + after_authentication = 1; + } ++ ++int ++packet_authentication_state(void) ++{ ++ return(after_authentication); ++} +diff -NupwB packet.h packet.h +--- packet.h 2008-07-11 03:36:48.000000000 -0400 ++++ packet.h 2009-05-14 12:36:10.000000000 -0400 +@@ -20,6 +20,9 @@ + + #include + ++void ++packet_request_rekeying(void); ++ + void packet_set_connection(int, int); + void packet_set_timeout(int, int); + void packet_set_nonblocking(void); +@@ -35,6 +38,7 @@ void packet_set_interactive(int); + int packet_is_interactive(void); + void packet_set_server(void); + void packet_set_authenticated(void); ++int packet_authentication_state(void); + + void packet_start(u_char); + void packet_put_char(int ch); +@@ -44,7 +48,7 @@ void packet_put_bignum2(BIGNUM * val + 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_send(void); + + int packet_read(void); + void packet_read_expect(int type); +@@ -73,8 +77,8 @@ void packet_set_state(int, u_int32_t, u + int packet_get_ssh1_cipher(void); + void packet_set_iv(int, u_char *); + +-void packet_write_poll(void); +-void packet_write_wait(void); ++int packet_write_poll(void); ++int packet_write_wait(void); + int packet_have_data_to_write(void); + int packet_not_very_much_data_to_write(void); + +diff -NupwB progressmeter.c progressmeter.c +--- progressmeter.c 2006-08-04 22:39:40.000000000 -0400 ++++ progressmeter.c 2009-05-14 12:36:10.000000000 -0400 +@@ -68,6 +68,8 @@ static time_t last_update; /* last progr + static char *file; /* name of the file being transferred */ + static off_t end_pos; /* ending position of transfer */ + static off_t cur_pos; /* transfer position as of last refresh */ ++static off_t last_pos; ++static off_t max_delta_pos = 0; + static volatile off_t *counter; /* progress counter */ + static long stalled; /* how long we have been stalled */ + static int bytes_per_second; /* current speed in bytes per second */ +@@ -128,12 +130,17 @@ refresh_progress_meter(void) + int hours, minutes, seconds; + int i, len; + int file_len; ++ off_t delta_pos; + + transferred = *counter - cur_pos; + cur_pos = *counter; + now = time(NULL); + bytes_left = end_pos - cur_pos; + ++ delta_pos = cur_pos - last_pos; ++ if (delta_pos > max_delta_pos) ++ max_delta_pos = delta_pos; ++ + if (bytes_left > 0) + elapsed = now - last_update; + else { +@@ -158,7 +165,7 @@ refresh_progress_meter(void) + + /* filename */ + buf[0] = '\0'; +- file_len = win_size - 35; ++ file_len = win_size - 45; + if (file_len > 0) { + len = snprintf(buf, file_len + 1, "\r%s", file); + if (len < 0) +@@ -175,7 +182,8 @@ refresh_progress_meter(void) + percent = ((float)cur_pos / end_pos) * 100; + else + percent = 100; +- snprintf(buf + strlen(buf), win_size - strlen(buf), ++ ++ snprintf(buf + strlen(buf), win_size - strlen(buf-8), + " %3d%% ", percent); + + /* amount transferred */ +@@ -188,6 +196,15 @@ refresh_progress_meter(void) + (off_t)bytes_per_second); + strlcat(buf, "/s ", win_size); + ++ /* instantaneous rate */ ++ if (bytes_left > 0) ++ format_rate(buf + strlen(buf), win_size - strlen(buf), ++ delta_pos); ++ else ++ format_rate(buf + strlen(buf), win_size - strlen(buf), ++ max_delta_pos); ++ strlcat(buf, "/s ", win_size); ++ + /* ETA */ + if (!transferred) + stalled += elapsed; +@@ -224,6 +241,7 @@ refresh_progress_meter(void) + + atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); + last_update = now; ++ last_pos = cur_pos; + } + + /*ARGSUSED*/ +diff -NupwB readconf.c readconf.c +--- readconf.c 2009-02-14 00:28:21.000000000 -0500 ++++ readconf.c 2009-05-14 12:36:10.000000000 -0400 +@@ -131,6 +131,8 @@ typedef enum { + oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, + oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, + oVisualHostKey, oZeroKnowledgePasswordAuthentication, ++ oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled, ++ oHPNBufferSize, + oDeprecated, oUnsupported + } OpCodes; + +@@ -234,6 +236,12 @@ static struct { + #else + { "zeroknowledgepasswordauthentication", oUnsupported }, + #endif ++ { "noneenabled", oNoneEnabled }, ++ { "tcprcvbufpoll", oTcpRcvBufPoll }, ++ { "tcprcvbuf", oTcpRcvBuf }, ++ { "noneswitch", oNoneSwitch }, ++ { "hpndisabled", oHPNDisabled }, ++ { "hpnbuffersize", oHPNBufferSize }, + + { NULL, oBadOption } + }; +@@ -465,6 +473,37 @@ parse_flag: + intptr = &options->check_host_ip; + goto parse_flag; + ++ case oNoneEnabled: ++ intptr = &options->none_enabled; ++ goto parse_flag; ++ ++ /* we check to see if the command comes from the */ ++ /* command line or not. If it does then enable it */ ++ /* otherwise fail. NONE should never be a default configuration */ ++ case oNoneSwitch: ++ if(strcmp(filename,"command-line")==0) ++ { ++ intptr = &options->none_switch; ++ goto parse_flag; ++ } else { ++ error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename); ++ error("Continuing..."); ++ debug("NoneSwitch directive found in %.200s.", filename); ++ return 0; ++ } ++ ++ case oHPNDisabled: ++ intptr = &options->hpn_disabled; ++ goto parse_flag; ++ ++ case oHPNBufferSize: ++ intptr = &options->hpn_buffer_size; ++ goto parse_int; ++ ++ case oTcpRcvBufPoll: ++ intptr = &options->tcp_rcv_buf_poll; ++ goto parse_flag; ++ + case oVerifyHostKeyDNS: + intptr = &options->verify_host_key_dns; + goto parse_yesnoask; +@@ -643,6 +682,10 @@ parse_int: + intptr = &options->connection_attempts; + goto parse_int; + ++ case oTcpRcvBuf: ++ intptr = &options->tcp_rcv_buf; ++ goto parse_int; ++ + case oCipher: + intptr = &options->cipher; + arg = strdelim(&s); +@@ -1065,6 +1108,12 @@ initialize_options(Options * options) + options->permit_local_command = -1; + options->visual_host_key = -1; + options->zero_knowledge_password_authentication = -1; ++ options->none_switch = -1; ++ options->none_enabled = -1; ++ options->hpn_disabled = -1; ++ options->hpn_buffer_size = -1; ++ options->tcp_rcv_buf_poll = -1; ++ options->tcp_rcv_buf = -1; + } + + /* +@@ -1187,6 +1236,29 @@ fill_default_options(Options * options) + options->server_alive_interval = 0; + if (options->server_alive_count_max == -1) + options->server_alive_count_max = 3; ++ if (options->none_switch == -1) ++ options->none_switch = 0; ++ if (options->hpn_disabled == -1) ++ options->hpn_disabled = 0; ++ if (options->hpn_buffer_size > -1) ++ { ++ /* if a user tries to set the size to 0 set it to 1KB */ ++ if (options->hpn_buffer_size == 0) ++ options->hpn_buffer_size = 1024; ++ /*limit the buffer to 64MB*/ ++ if (options->hpn_buffer_size > 65536) ++ { ++ options->hpn_buffer_size = 65536*1024; ++ debug("User requested buffer larger than 64MB. Request reverted to 64MB"); ++ } ++ debug("hpn_buffer_size set to %d", options->hpn_buffer_size); ++ } ++ if (options->tcp_rcv_buf == 0) ++ options->tcp_rcv_buf = 1; ++ if (options->tcp_rcv_buf > -1) ++ options->tcp_rcv_buf *=1024; ++ if (options->tcp_rcv_buf_poll == -1) ++ options->tcp_rcv_buf_poll = 1; + if (options->control_master == -1) + options->control_master = 0; + if (options->hash_known_hosts == -1) +diff -NupwB readconf.c.orig readconf.c.orig +--- readconf.c.orig 1969-12-31 19:00:00.000000000 -0500 ++++ readconf.c.orig 2009-02-14 00:28:21.000000000 -0500 +@@ -0,0 +1,1310 @@ ++/* $OpenBSD: readconf.c,v 1.176 2009/02/12 03:00:56 djm Exp $ */ ++/* ++ * Author: Tatu Ylonen ++ * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland ++ * All rights reserved ++ * Functions for reading the configuration files. ++ * ++ * 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 ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xmalloc.h" ++#include "ssh.h" ++#include "compat.h" ++#include "cipher.h" ++#include "pathnames.h" ++#include "log.h" ++#include "key.h" ++#include "readconf.h" ++#include "match.h" ++#include "misc.h" ++#include "buffer.h" ++#include "kex.h" ++#include "mac.h" ++ ++/* Format of the configuration file: ++ ++ # Configuration data is parsed as follows: ++ # 1. command line options ++ # 2. user-specific file ++ # 3. system-wide file ++ # Any configuration value is only changed the first time it is set. ++ # Thus, host-specific definitions should be at the beginning of the ++ # configuration file, and defaults at the end. ++ ++ # Host-specific declarations. These may override anything above. A single ++ # host may match multiple declarations; these are processed in the order ++ # that they are given in. ++ ++ Host *.ngs.fi ngs.fi ++ User foo ++ ++ Host fake.com ++ HostName another.host.name.real.org ++ User blaah ++ Port 34289 ++ ForwardX11 no ++ ForwardAgent no ++ ++ Host books.com ++ RemoteForward 9999 shadows.cs.hut.fi:9999 ++ Cipher 3des ++ ++ Host fascist.blob.com ++ Port 23123 ++ User tylonen ++ PasswordAuthentication no ++ ++ Host puukko.hut.fi ++ User t35124p ++ ProxyCommand ssh-proxy %h %p ++ ++ Host *.fr ++ PublicKeyAuthentication no ++ ++ Host *.su ++ Cipher none ++ PasswordAuthentication no ++ ++ Host vpn.fake.com ++ Tunnel yes ++ TunnelDevice 3 ++ ++ # Defaults for various options ++ Host * ++ ForwardAgent no ++ ForwardX11 no ++ PasswordAuthentication yes ++ RSAAuthentication yes ++ RhostsRSAAuthentication yes ++ StrictHostKeyChecking yes ++ TcpKeepAlive no ++ IdentityFile ~/.ssh/identity ++ Port 22 ++ EscapeChar ~ ++ ++*/ ++ ++/* Keyword tokens. */ ++ ++typedef enum { ++ oBadOption, ++ oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, ++ oExitOnForwardFailure, ++ oPasswordAuthentication, oRSAAuthentication, ++ oChallengeResponseAuthentication, oXAuthLocation, ++ oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, ++ oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, ++ oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, ++ oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, ++ oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, ++ oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, ++ oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, ++ oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, ++ oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, ++ oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, ++ oClearAllForwardings, oNoHostAuthenticationForLocalhost, ++ oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, ++ oAddressFamily, oGssAuthentication, oGssDelegateCreds, ++ oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, ++ oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, ++ oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, ++ oVisualHostKey, oZeroKnowledgePasswordAuthentication, ++ oDeprecated, oUnsupported ++} OpCodes; ++ ++/* Textual representations of the tokens. */ ++ ++static struct { ++ const char *name; ++ OpCodes opcode; ++} keywords[] = { ++ { "forwardagent", oForwardAgent }, ++ { "forwardx11", oForwardX11 }, ++ { "forwardx11trusted", oForwardX11Trusted }, ++ { "exitonforwardfailure", oExitOnForwardFailure }, ++ { "xauthlocation", oXAuthLocation }, ++ { "gatewayports", oGatewayPorts }, ++ { "useprivilegedport", oUsePrivilegedPort }, ++ { "rhostsauthentication", oDeprecated }, ++ { "passwordauthentication", oPasswordAuthentication }, ++ { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, ++ { "kbdinteractivedevices", oKbdInteractiveDevices }, ++ { "rsaauthentication", oRSAAuthentication }, ++ { "pubkeyauthentication", oPubkeyAuthentication }, ++ { "dsaauthentication", oPubkeyAuthentication }, /* alias */ ++ { "rhostsrsaauthentication", oRhostsRSAAuthentication }, ++ { "hostbasedauthentication", oHostbasedAuthentication }, ++ { "challengeresponseauthentication", oChallengeResponseAuthentication }, ++ { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ ++ { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ ++ { "kerberosauthentication", oUnsupported }, ++ { "kerberostgtpassing", oUnsupported }, ++ { "afstokenpassing", oUnsupported }, ++#if defined(GSSAPI) ++ { "gssapiauthentication", oGssAuthentication }, ++ { "gssapidelegatecredentials", oGssDelegateCreds }, ++#else ++ { "gssapiauthentication", oUnsupported }, ++ { "gssapidelegatecredentials", oUnsupported }, ++#endif ++ { "fallbacktorsh", oDeprecated }, ++ { "usersh", oDeprecated }, ++ { "identityfile", oIdentityFile }, ++ { "identityfile2", oIdentityFile }, /* obsolete */ ++ { "identitiesonly", oIdentitiesOnly }, ++ { "hostname", oHostName }, ++ { "hostkeyalias", oHostKeyAlias }, ++ { "proxycommand", oProxyCommand }, ++ { "port", oPort }, ++ { "cipher", oCipher }, ++ { "ciphers", oCiphers }, ++ { "macs", oMacs }, ++ { "protocol", oProtocol }, ++ { "remoteforward", oRemoteForward }, ++ { "localforward", oLocalForward }, ++ { "user", oUser }, ++ { "host", oHost }, ++ { "escapechar", oEscapeChar }, ++ { "globalknownhostsfile", oGlobalKnownHostsFile }, ++ { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, /* obsolete */ ++ { "userknownhostsfile", oUserKnownHostsFile }, ++ { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ ++ { "connectionattempts", oConnectionAttempts }, ++ { "batchmode", oBatchMode }, ++ { "checkhostip", oCheckHostIP }, ++ { "stricthostkeychecking", oStrictHostKeyChecking }, ++ { "compression", oCompression }, ++ { "compressionlevel", oCompressionLevel }, ++ { "tcpkeepalive", oTCPKeepAlive }, ++ { "keepalive", oTCPKeepAlive }, /* obsolete */ ++ { "numberofpasswordprompts", oNumberOfPasswordPrompts }, ++ { "loglevel", oLogLevel }, ++ { "dynamicforward", oDynamicForward }, ++ { "preferredauthentications", oPreferredAuthentications }, ++ { "hostkeyalgorithms", oHostKeyAlgorithms }, ++ { "bindaddress", oBindAddress }, ++#ifdef SMARTCARD ++ { "smartcarddevice", oSmartcardDevice }, ++#else ++ { "smartcarddevice", oUnsupported }, ++#endif ++ { "clearallforwardings", oClearAllForwardings }, ++ { "enablesshkeysign", oEnableSSHKeysign }, ++ { "verifyhostkeydns", oVerifyHostKeyDNS }, ++ { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, ++ { "rekeylimit", oRekeyLimit }, ++ { "connecttimeout", oConnectTimeout }, ++ { "addressfamily", oAddressFamily }, ++ { "serveraliveinterval", oServerAliveInterval }, ++ { "serveralivecountmax", oServerAliveCountMax }, ++ { "sendenv", oSendEnv }, ++ { "controlpath", oControlPath }, ++ { "controlmaster", oControlMaster }, ++ { "hashknownhosts", oHashKnownHosts }, ++ { "tunnel", oTunnel }, ++ { "tunneldevice", oTunnelDevice }, ++ { "localcommand", oLocalCommand }, ++ { "permitlocalcommand", oPermitLocalCommand }, ++ { "visualhostkey", oVisualHostKey }, ++#ifdef JPAKE ++ { "zeroknowledgepasswordauthentication", ++ oZeroKnowledgePasswordAuthentication }, ++#else ++ { "zeroknowledgepasswordauthentication", oUnsupported }, ++#endif ++ ++ { NULL, oBadOption } ++}; ++ ++/* ++ * Adds a local TCP/IP port forward to options. Never returns if there is an ++ * error. ++ */ ++ ++void ++add_local_forward(Options *options, const Forward *newfwd) ++{ ++ Forward *fwd; ++#ifndef NO_IPPORT_RESERVED_CONCEPT ++ extern uid_t original_real_uid; ++ if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) ++ fatal("Privileged ports can only be forwarded by root."); ++#endif ++ if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) ++ fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); ++ fwd = &options->local_forwards[options->num_local_forwards++]; ++ ++ fwd->listen_host = newfwd->listen_host; ++ fwd->listen_port = newfwd->listen_port; ++ fwd->connect_host = newfwd->connect_host; ++ fwd->connect_port = newfwd->connect_port; ++} ++ ++/* ++ * Adds a remote TCP/IP port forward to options. Never returns if there is ++ * an error. ++ */ ++ ++void ++add_remote_forward(Options *options, const Forward *newfwd) ++{ ++ Forward *fwd; ++ if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) ++ fatal("Too many remote forwards (max %d).", ++ SSH_MAX_FORWARDS_PER_DIRECTION); ++ fwd = &options->remote_forwards[options->num_remote_forwards++]; ++ ++ fwd->listen_host = newfwd->listen_host; ++ fwd->listen_port = newfwd->listen_port; ++ fwd->connect_host = newfwd->connect_host; ++ fwd->connect_port = newfwd->connect_port; ++} ++ ++static void ++clear_forwardings(Options *options) ++{ ++ int i; ++ ++ for (i = 0; i < options->num_local_forwards; i++) { ++ if (options->local_forwards[i].listen_host != NULL) ++ xfree(options->local_forwards[i].listen_host); ++ xfree(options->local_forwards[i].connect_host); ++ } ++ options->num_local_forwards = 0; ++ for (i = 0; i < options->num_remote_forwards; i++) { ++ if (options->remote_forwards[i].listen_host != NULL) ++ xfree(options->remote_forwards[i].listen_host); ++ xfree(options->remote_forwards[i].connect_host); ++ } ++ options->num_remote_forwards = 0; ++ options->tun_open = SSH_TUNMODE_NO; ++} ++ ++/* ++ * Returns the number of the token pointed to by cp or oBadOption. ++ */ ++ ++static OpCodes ++parse_token(const char *cp, const char *filename, int linenum) ++{ ++ u_int i; ++ ++ for (i = 0; keywords[i].name; i++) ++ if (strcasecmp(cp, keywords[i].name) == 0) ++ return keywords[i].opcode; ++ ++ error("%s: line %d: Bad configuration option: %s", ++ filename, linenum, cp); ++ return oBadOption; ++} ++ ++/* ++ * Processes a single option line as used in the configuration files. This ++ * only sets those values that have not already been set. ++ */ ++#define WHITESPACE " \t\r\n" ++ ++int ++process_config_line(Options *options, const char *host, ++ char *line, const char *filename, int linenum, ++ int *activep) ++{ ++ char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; ++ int opcode, *intptr, value, value2, scale; ++ LogLevel *log_level_ptr; ++ long long orig, val64; ++ size_t len; ++ Forward fwd; ++ ++ /* Strip trailing whitespace */ ++ for (len = strlen(line) - 1; len > 0; len--) { ++ if (strchr(WHITESPACE, line[len]) == NULL) ++ break; ++ line[len] = '\0'; ++ } ++ ++ s = line; ++ /* Get the keyword. (Each line is supposed to begin with a keyword). */ ++ if ((keyword = strdelim(&s)) == NULL) ++ return 0; ++ /* Ignore leading whitespace. */ ++ if (*keyword == '\0') ++ keyword = strdelim(&s); ++ if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') ++ return 0; ++ ++ opcode = parse_token(keyword, filename, linenum); ++ ++ switch (opcode) { ++ case oBadOption: ++ /* don't panic, but count bad options */ ++ return -1; ++ /* NOTREACHED */ ++ case oConnectTimeout: ++ intptr = &options->connection_timeout; ++parse_time: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing time value.", ++ filename, linenum); ++ if ((value = convtime(arg)) == -1) ++ fatal("%s line %d: invalid time value.", ++ filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oForwardAgent: ++ intptr = &options->forward_agent; ++parse_flag: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) ++ value = 1; ++ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) ++ value = 0; ++ else ++ fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oForwardX11: ++ intptr = &options->forward_x11; ++ goto parse_flag; ++ ++ case oForwardX11Trusted: ++ intptr = &options->forward_x11_trusted; ++ goto parse_flag; ++ ++ case oGatewayPorts: ++ intptr = &options->gateway_ports; ++ goto parse_flag; ++ ++ case oExitOnForwardFailure: ++ intptr = &options->exit_on_forward_failure; ++ goto parse_flag; ++ ++ case oUsePrivilegedPort: ++ intptr = &options->use_privileged_port; ++ goto parse_flag; ++ ++ case oPasswordAuthentication: ++ intptr = &options->password_authentication; ++ goto parse_flag; ++ ++ case oZeroKnowledgePasswordAuthentication: ++ intptr = &options->zero_knowledge_password_authentication; ++ goto parse_flag; ++ ++ case oKbdInteractiveAuthentication: ++ intptr = &options->kbd_interactive_authentication; ++ goto parse_flag; ++ ++ case oKbdInteractiveDevices: ++ charptr = &options->kbd_interactive_devices; ++ goto parse_string; ++ ++ case oPubkeyAuthentication: ++ intptr = &options->pubkey_authentication; ++ goto parse_flag; ++ ++ case oRSAAuthentication: ++ intptr = &options->rsa_authentication; ++ goto parse_flag; ++ ++ case oRhostsRSAAuthentication: ++ intptr = &options->rhosts_rsa_authentication; ++ goto parse_flag; ++ ++ case oHostbasedAuthentication: ++ intptr = &options->hostbased_authentication; ++ goto parse_flag; ++ ++ case oChallengeResponseAuthentication: ++ intptr = &options->challenge_response_authentication; ++ goto parse_flag; ++ ++ case oGssAuthentication: ++ intptr = &options->gss_authentication; ++ goto parse_flag; ++ ++ case oGssDelegateCreds: ++ intptr = &options->gss_deleg_creds; ++ goto parse_flag; ++ ++ case oBatchMode: ++ intptr = &options->batch_mode; ++ goto parse_flag; ++ ++ case oCheckHostIP: ++ intptr = &options->check_host_ip; ++ goto parse_flag; ++ ++ case oVerifyHostKeyDNS: ++ intptr = &options->verify_host_key_dns; ++ goto parse_yesnoask; ++ ++ case oStrictHostKeyChecking: ++ intptr = &options->strict_host_key_checking; ++parse_yesnoask: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no/ask argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) ++ value = 1; ++ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) ++ value = 0; ++ else if (strcmp(arg, "ask") == 0) ++ value = 2; ++ else ++ fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oCompression: ++ intptr = &options->compression; ++ goto parse_flag; ++ ++ case oTCPKeepAlive: ++ intptr = &options->tcp_keep_alive; ++ goto parse_flag; ++ ++ case oNoHostAuthenticationForLocalhost: ++ intptr = &options->no_host_authentication_for_localhost; ++ goto parse_flag; ++ ++ case oNumberOfPasswordPrompts: ++ intptr = &options->number_of_password_prompts; ++ goto parse_int; ++ ++ case oCompressionLevel: ++ intptr = &options->compression_level; ++ goto parse_int; ++ ++ case oRekeyLimit: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (arg[0] < '0' || arg[0] > '9') ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ orig = val64 = strtoll(arg, &endofnumber, 10); ++ if (arg == endofnumber) ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ switch (toupper(*endofnumber)) { ++ case '\0': ++ scale = 1; ++ break; ++ case 'K': ++ scale = 1<<10; ++ break; ++ case 'M': ++ scale = 1<<20; ++ break; ++ case 'G': ++ scale = 1<<30; ++ break; ++ default: ++ fatal("%.200s line %d: Invalid RekeyLimit suffix", ++ filename, linenum); ++ } ++ val64 *= scale; ++ /* detect integer wrap and too-large limits */ ++ if ((val64 / scale) != orig || val64 > UINT_MAX) ++ fatal("%.200s line %d: RekeyLimit too large", ++ filename, linenum); ++ if (val64 < 16) ++ fatal("%.200s line %d: RekeyLimit too small", ++ filename, linenum); ++ if (*activep && options->rekey_limit == -1) ++ options->rekey_limit = (u_int32_t)val64; ++ break; ++ ++ case oIdentityFile: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (*activep) { ++ intptr = &options->num_identity_files; ++ if (*intptr >= SSH_MAX_IDENTITY_FILES) ++ fatal("%.200s line %d: Too many identity files specified (max %d).", ++ filename, linenum, SSH_MAX_IDENTITY_FILES); ++ charptr = &options->identity_files[*intptr]; ++ *charptr = xstrdup(arg); ++ *intptr = *intptr + 1; ++ } ++ break; ++ ++ case oXAuthLocation: ++ charptr=&options->xauth_location; ++ goto parse_string; ++ ++ case oUser: ++ charptr = &options->user; ++parse_string: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (*activep && *charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ ++ case oGlobalKnownHostsFile: ++ charptr = &options->system_hostfile; ++ goto parse_string; ++ ++ case oUserKnownHostsFile: ++ charptr = &options->user_hostfile; ++ goto parse_string; ++ ++ case oGlobalKnownHostsFile2: ++ charptr = &options->system_hostfile2; ++ goto parse_string; ++ ++ case oUserKnownHostsFile2: ++ charptr = &options->user_hostfile2; ++ goto parse_string; ++ ++ case oHostName: ++ charptr = &options->hostname; ++ goto parse_string; ++ ++ case oHostKeyAlias: ++ charptr = &options->host_key_alias; ++ goto parse_string; ++ ++ case oPreferredAuthentications: ++ charptr = &options->preferred_authentications; ++ goto parse_string; ++ ++ case oBindAddress: ++ charptr = &options->bind_address; ++ goto parse_string; ++ ++ case oSmartcardDevice: ++ charptr = &options->smartcard_device; ++ goto parse_string; ++ ++ case oProxyCommand: ++ charptr = &options->proxy_command; ++parse_command: ++ if (s == NULL) ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ len = strspn(s, WHITESPACE "="); ++ if (*activep && *charptr == NULL) ++ *charptr = xstrdup(s + len); ++ return 0; ++ ++ case oPort: ++ intptr = &options->port; ++parse_int: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (arg[0] < '0' || arg[0] > '9') ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ ++ /* Octal, decimal, or hex format? */ ++ value = strtol(arg, &endofnumber, 0); ++ if (arg == endofnumber) ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oConnectionAttempts: ++ intptr = &options->connection_attempts; ++ goto parse_int; ++ ++ case oCipher: ++ intptr = &options->cipher; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ value = cipher_number(arg); ++ if (value == -1) ++ fatal("%.200s line %d: Bad cipher '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oCiphers: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (!ciphers_valid(arg)) ++ fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->ciphers == NULL) ++ options->ciphers = xstrdup(arg); ++ break; ++ ++ case oMacs: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (!mac_valid(arg)) ++ fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->macs == NULL) ++ options->macs = xstrdup(arg); ++ break; ++ ++ case oHostKeyAlgorithms: ++ 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); ++ break; ++ ++ case oProtocol: ++ intptr = &options->protocol; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ value = proto_spec(arg); ++ if (value == SSH_PROTO_UNKNOWN) ++ fatal("%.200s line %d: Bad protocol spec '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && *intptr == SSH_PROTO_UNKNOWN) ++ *intptr = value; ++ break; ++ ++ case oLogLevel: ++ log_level_ptr = &options->log_level; ++ arg = strdelim(&s); ++ value = log_level_number(arg); ++ if (value == SYSLOG_LEVEL_NOT_SET) ++ fatal("%.200s line %d: unsupported log level '%s'", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) ++ *log_level_ptr = (LogLevel) value; ++ break; ++ ++ case oLocalForward: ++ case oRemoteForward: ++ case oDynamicForward: ++ arg = strdelim(&s); ++ if (arg == NULL || *arg == '\0') ++ fatal("%.200s line %d: Missing port argument.", ++ filename, linenum); ++ ++ if (opcode == oLocalForward || ++ opcode == oRemoteForward) { ++ arg2 = strdelim(&s); ++ if (arg2 == NULL || *arg2 == '\0') ++ fatal("%.200s line %d: Missing target argument.", ++ filename, linenum); ++ ++ /* construct a string for parse_forward */ ++ snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); ++ } else if (opcode == oDynamicForward) { ++ strlcpy(fwdarg, arg, sizeof(fwdarg)); ++ } ++ ++ if (parse_forward(&fwd, fwdarg, ++ opcode == oDynamicForward ? 1 : 0, ++ opcode == oRemoteForward ? 1 : 0) == 0) ++ fatal("%.200s line %d: Bad forwarding specification.", ++ filename, linenum); ++ ++ if (*activep) { ++ if (opcode == oLocalForward || ++ opcode == oDynamicForward) ++ add_local_forward(options, &fwd); ++ else if (opcode == oRemoteForward) ++ add_remote_forward(options, &fwd); ++ } ++ break; ++ ++ case oClearAllForwardings: ++ intptr = &options->clear_forwardings; ++ goto parse_flag; ++ ++ case oHost: ++ *activep = 0; ++ while ((arg = strdelim(&s)) != NULL && *arg != '\0') ++ if (match_pattern(host, arg)) { ++ debug("Applying options for %.100s", arg); ++ *activep = 1; ++ break; ++ } ++ /* Avoid garbage check below, as strdelim is done. */ ++ return 0; ++ ++ case oEscapeChar: ++ intptr = &options->escape_char; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ 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); ++ /* NOTREACHED */ ++ value = 0; /* Avoid compiler warning. */ ++ } ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oAddressFamily: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing address family.", ++ filename, linenum); ++ intptr = &options->address_family; ++ if (strcasecmp(arg, "inet") == 0) ++ value = AF_INET; ++ else if (strcasecmp(arg, "inet6") == 0) ++ value = AF_INET6; ++ else if (strcasecmp(arg, "any") == 0) ++ value = AF_UNSPEC; ++ else ++ fatal("Unsupported AddressFamily \"%s\"", arg); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oEnableSSHKeysign: ++ intptr = &options->enable_ssh_keysign; ++ goto parse_flag; ++ ++ case oIdentitiesOnly: ++ intptr = &options->identities_only; ++ goto parse_flag; ++ ++ case oServerAliveInterval: ++ intptr = &options->server_alive_interval; ++ goto parse_time; ++ ++ case oServerAliveCountMax: ++ intptr = &options->server_alive_count_max; ++ goto parse_int; ++ ++ case oSendEnv: ++ while ((arg = strdelim(&s)) != NULL && *arg != '\0') { ++ if (strchr(arg, '=') != NULL) ++ fatal("%s line %d: Invalid environment name.", ++ filename, linenum); ++ if (!*activep) ++ continue; ++ if (options->num_send_env >= MAX_SEND_ENV) ++ fatal("%s line %d: too many send env.", ++ filename, linenum); ++ options->send_env[options->num_send_env++] = ++ xstrdup(arg); ++ } ++ break; ++ ++ case oControlPath: ++ charptr = &options->control_path; ++ goto parse_string; ++ ++ case oControlMaster: ++ intptr = &options->control_master; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing ControlMaster argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) ++ value = SSHCTL_MASTER_YES; ++ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) ++ value = SSHCTL_MASTER_NO; ++ else if (strcmp(arg, "auto") == 0) ++ value = SSHCTL_MASTER_AUTO; ++ else if (strcmp(arg, "ask") == 0) ++ value = SSHCTL_MASTER_ASK; ++ else if (strcmp(arg, "autoask") == 0) ++ value = SSHCTL_MASTER_AUTO_ASK; ++ else ++ fatal("%.200s line %d: Bad ControlMaster argument.", ++ filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oHashKnownHosts: ++ intptr = &options->hash_known_hosts; ++ goto parse_flag; ++ ++ case oTunnel: ++ intptr = &options->tun_open; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: Missing yes/point-to-point/" ++ "ethernet/no argument.", filename, linenum); ++ value = 0; /* silence compiler */ ++ if (strcasecmp(arg, "ethernet") == 0) ++ value = SSH_TUNMODE_ETHERNET; ++ else if (strcasecmp(arg, "point-to-point") == 0) ++ value = SSH_TUNMODE_POINTOPOINT; ++ else if (strcasecmp(arg, "yes") == 0) ++ value = SSH_TUNMODE_DEFAULT; ++ else if (strcasecmp(arg, "no") == 0) ++ value = SSH_TUNMODE_NO; ++ else ++ fatal("%s line %d: Bad yes/point-to-point/ethernet/" ++ "no argument: %s", filename, linenum, arg); ++ if (*activep) ++ *intptr = value; ++ break; ++ ++ case oTunnelDevice: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ value = a2tun(arg, &value2); ++ if (value == SSH_TUNID_ERR) ++ fatal("%.200s line %d: Bad tun device.", filename, linenum); ++ if (*activep) { ++ options->tun_local = value; ++ options->tun_remote = value2; ++ } ++ break; ++ ++ case oLocalCommand: ++ charptr = &options->local_command; ++ goto parse_command; ++ ++ case oPermitLocalCommand: ++ intptr = &options->permit_local_command; ++ goto parse_flag; ++ ++ case oVisualHostKey: ++ intptr = &options->visual_host_key; ++ goto parse_flag; ++ ++ case oDeprecated: ++ debug("%s line %d: Deprecated option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ case oUnsupported: ++ error("%s line %d: Unsupported option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ default: ++ fatal("process_config_line: Unimplemented opcode %d", opcode); ++ } ++ ++ /* Check that there is no garbage at end of line. */ ++ if ((arg = strdelim(&s)) != NULL && *arg != '\0') { ++ fatal("%.200s line %d: garbage at end of line; \"%.200s\".", ++ filename, linenum, arg); ++ } ++ return 0; ++} ++ ++ ++/* ++ * Reads the config file and modifies the options accordingly. Options ++ * should already be initialized before this call. This never returns if ++ * there is an error. If the file does not exist, this returns 0. ++ */ ++ ++int ++read_config_file(const char *filename, const char *host, Options *options, ++ int checkperm) ++{ ++ FILE *f; ++ char line[1024]; ++ int active, linenum; ++ int bad_options = 0; ++ ++ if ((f = fopen(filename, "r")) == NULL) ++ return 0; ++ ++ if (checkperm) { ++ struct stat sb; ++ ++ if (fstat(fileno(f), &sb) == -1) ++ fatal("fstat %s: %s", filename, strerror(errno)); ++ if (((sb.st_uid != 0 && sb.st_uid != getuid()) || ++ (sb.st_mode & 022) != 0)) ++ fatal("Bad owner or permissions on %s", filename); ++ } ++ ++ debug("Reading configuration data %.200s", filename); ++ ++ /* ++ * Mark that we are now processing the options. This flag is turned ++ * on/off by Host specifications. ++ */ ++ active = 1; ++ linenum = 0; ++ while (fgets(line, sizeof(line), f)) { ++ /* Update line number counter. */ ++ linenum++; ++ if (process_config_line(options, host, line, filename, linenum, &active) != 0) ++ bad_options++; ++ } ++ fclose(f); ++ if (bad_options > 0) ++ fatal("%s: terminating, %d bad configuration options", ++ filename, bad_options); ++ return 1; ++} ++ ++/* ++ * Initializes options to special values that indicate that they have not yet ++ * been set. Read_config_file will only set options with this value. Options ++ * are processed in the following order: command line, user config file, ++ * system config file. Last, fill_default_options is called. ++ */ ++ ++void ++initialize_options(Options * options) ++{ ++ memset(options, 'X', sizeof(*options)); ++ options->forward_agent = -1; ++ options->forward_x11 = -1; ++ options->forward_x11_trusted = -1; ++ options->exit_on_forward_failure = -1; ++ options->xauth_location = NULL; ++ options->gateway_ports = -1; ++ options->use_privileged_port = -1; ++ options->rsa_authentication = -1; ++ options->pubkey_authentication = -1; ++ options->challenge_response_authentication = -1; ++ options->gss_authentication = -1; ++ options->gss_deleg_creds = -1; ++ options->password_authentication = -1; ++ options->kbd_interactive_authentication = -1; ++ options->kbd_interactive_devices = NULL; ++ options->rhosts_rsa_authentication = -1; ++ options->hostbased_authentication = -1; ++ options->batch_mode = -1; ++ options->check_host_ip = -1; ++ options->strict_host_key_checking = -1; ++ options->compression = -1; ++ options->tcp_keep_alive = -1; ++ options->compression_level = -1; ++ options->port = -1; ++ options->address_family = -1; ++ options->connection_attempts = -1; ++ options->connection_timeout = -1; ++ options->number_of_password_prompts = -1; ++ options->cipher = -1; ++ options->ciphers = NULL; ++ options->macs = NULL; ++ options->hostkeyalgorithms = NULL; ++ options->protocol = SSH_PROTO_UNKNOWN; ++ options->num_identity_files = 0; ++ options->hostname = NULL; ++ options->host_key_alias = NULL; ++ options->proxy_command = NULL; ++ options->user = NULL; ++ options->escape_char = -1; ++ options->system_hostfile = NULL; ++ options->user_hostfile = NULL; ++ options->system_hostfile2 = NULL; ++ options->user_hostfile2 = NULL; ++ options->num_local_forwards = 0; ++ options->num_remote_forwards = 0; ++ options->clear_forwardings = -1; ++ options->log_level = SYSLOG_LEVEL_NOT_SET; ++ options->preferred_authentications = NULL; ++ options->bind_address = NULL; ++ options->smartcard_device = NULL; ++ options->enable_ssh_keysign = - 1; ++ options->no_host_authentication_for_localhost = - 1; ++ options->identities_only = - 1; ++ options->rekey_limit = - 1; ++ options->verify_host_key_dns = -1; ++ options->server_alive_interval = -1; ++ options->server_alive_count_max = -1; ++ options->num_send_env = 0; ++ options->control_path = NULL; ++ options->control_master = -1; ++ options->hash_known_hosts = -1; ++ options->tun_open = -1; ++ options->tun_local = -1; ++ options->tun_remote = -1; ++ options->local_command = NULL; ++ options->permit_local_command = -1; ++ options->visual_host_key = -1; ++ options->zero_knowledge_password_authentication = -1; ++} ++ ++/* ++ * Called after processing other sources of option data, this fills those ++ * options for which no value has been specified with their default values. ++ */ ++ ++void ++fill_default_options(Options * options) ++{ ++ int len; ++ ++ if (options->forward_agent == -1) ++ options->forward_agent = 0; ++ if (options->forward_x11 == -1) ++ options->forward_x11 = 0; ++ if (options->forward_x11_trusted == -1) ++ options->forward_x11_trusted = 0; ++ if (options->exit_on_forward_failure == -1) ++ 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->use_privileged_port == -1) ++ options->use_privileged_port = 0; ++ if (options->rsa_authentication == -1) ++ options->rsa_authentication = 1; ++ if (options->pubkey_authentication == -1) ++ options->pubkey_authentication = 1; ++ if (options->challenge_response_authentication == -1) ++ options->challenge_response_authentication = 1; ++ if (options->gss_authentication == -1) ++ options->gss_authentication = 0; ++ if (options->gss_deleg_creds == -1) ++ options->gss_deleg_creds = 0; ++ if (options->password_authentication == -1) ++ options->password_authentication = 1; ++ if (options->kbd_interactive_authentication == -1) ++ options->kbd_interactive_authentication = 1; ++ if (options->rhosts_rsa_authentication == -1) ++ options->rhosts_rsa_authentication = 0; ++ if (options->hostbased_authentication == -1) ++ options->hostbased_authentication = 0; ++ if (options->batch_mode == -1) ++ options->batch_mode = 0; ++ if (options->check_host_ip == -1) ++ options->check_host_ip = 1; ++ if (options->strict_host_key_checking == -1) ++ options->strict_host_key_checking = 2; /* 2 is default */ ++ if (options->compression == -1) ++ options->compression = 0; ++ if (options->tcp_keep_alive == -1) ++ options->tcp_keep_alive = 1; ++ if (options->compression_level == -1) ++ options->compression_level = 6; ++ if (options->port == -1) ++ options->port = 0; /* Filled in ssh_connect. */ ++ if (options->address_family == -1) ++ options->address_family = AF_UNSPEC; ++ if (options->connection_attempts == -1) ++ options->connection_attempts = 1; ++ if (options->number_of_password_prompts == -1) ++ options->number_of_password_prompts = 3; ++ /* 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->hostkeyalgorithms, default set in myproposals.h */ ++ if (options->protocol == SSH_PROTO_UNKNOWN) ++ options->protocol = SSH_PROTO_1|SSH_PROTO_2; ++ if (options->num_identity_files == 0) { ++ if (options->protocol & SSH_PROTO_1) { ++ len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; ++ options->identity_files[options->num_identity_files] = ++ xmalloc(len); ++ snprintf(options->identity_files[options->num_identity_files++], ++ len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); ++ } ++ if (options->protocol & SSH_PROTO_2) { ++ len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; ++ options->identity_files[options->num_identity_files] = ++ xmalloc(len); ++ snprintf(options->identity_files[options->num_identity_files++], ++ len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); ++ ++ len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; ++ options->identity_files[options->num_identity_files] = ++ xmalloc(len); ++ snprintf(options->identity_files[options->num_identity_files++], ++ len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); ++ } ++ } ++ if (options->escape_char == -1) ++ options->escape_char = '~'; ++ if (options->system_hostfile == NULL) ++ options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; ++ if (options->user_hostfile == NULL) ++ options->user_hostfile = _PATH_SSH_USER_HOSTFILE; ++ if (options->system_hostfile2 == NULL) ++ options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; ++ if (options->user_hostfile2 == NULL) ++ options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; ++ if (options->log_level == SYSLOG_LEVEL_NOT_SET) ++ options->log_level = SYSLOG_LEVEL_INFO; ++ if (options->clear_forwardings == 1) ++ clear_forwardings(options); ++ if (options->no_host_authentication_for_localhost == - 1) ++ options->no_host_authentication_for_localhost = 0; ++ if (options->identities_only == -1) ++ options->identities_only = 0; ++ if (options->enable_ssh_keysign == -1) ++ options->enable_ssh_keysign = 0; ++ if (options->rekey_limit == -1) ++ options->rekey_limit = 0; ++ if (options->verify_host_key_dns == -1) ++ options->verify_host_key_dns = 0; ++ if (options->server_alive_interval == -1) ++ options->server_alive_interval = 0; ++ if (options->server_alive_count_max == -1) ++ options->server_alive_count_max = 3; ++ if (options->control_master == -1) ++ options->control_master = 0; ++ if (options->hash_known_hosts == -1) ++ options->hash_known_hosts = 0; ++ if (options->tun_open == -1) ++ options->tun_open = SSH_TUNMODE_NO; ++ if (options->tun_local == -1) ++ options->tun_local = SSH_TUNID_ANY; ++ if (options->tun_remote == -1) ++ options->tun_remote = SSH_TUNID_ANY; ++ if (options->permit_local_command == -1) ++ options->permit_local_command = 0; ++ if (options->visual_host_key == -1) ++ options->visual_host_key = 0; ++ if (options->zero_knowledge_password_authentication == -1) ++ options->zero_knowledge_password_authentication = 0; ++ /* options->local_command should not be set by default */ ++ /* options->proxy_command should not be set by default */ ++ /* 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 */ ++ /* options->preferred_authentications will be set in ssh */ ++} ++ ++/* ++ * parse_forward ++ * parses a string containing a port forwarding specification of the form: ++ * dynamicfwd == 0 ++ * [listenhost:]listenport:connecthost:connectport ++ * 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) ++{ ++ int i; ++ char *p, *cp, *fwdarg[4]; ++ ++ memset(fwd, '\0', sizeof(*fwd)); ++ ++ cp = p = xstrdup(fwdspec); ++ ++ /* skip leading spaces */ ++ while (isspace(*cp)) ++ cp++; ++ ++ for (i = 0; i < 4; ++i) ++ if ((fwdarg[i] = hpdelim(&cp)) == NULL) ++ break; ++ ++ /* Check for trailing garbage */ ++ if (cp != NULL) ++ i = 0; /* failure */ ++ ++ switch (i) { ++ case 1: ++ fwd->listen_host = NULL; ++ fwd->listen_port = a2port(fwdarg[0]); ++ 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"); ++ 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]); ++ 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]); ++ break; ++ default: ++ i = 0; /* failure */ ++ } ++ ++ xfree(p); ++ ++ if (dynamicfwd) { ++ if (!(i == 1 || i == 2)) ++ goto fail_free; ++ } else { ++ if (!(i == 3 || i == 4)) ++ goto fail_free; ++ if (fwd->connect_port <= 0) ++ goto fail_free; ++ } ++ ++ if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) ++ goto fail_free; ++ ++ if (fwd->connect_host != NULL && ++ strlen(fwd->connect_host) >= NI_MAXHOST) ++ goto fail_free; ++ if (fwd->listen_host != NULL && ++ strlen(fwd->listen_host) >= NI_MAXHOST) ++ goto fail_free; ++ ++ ++ return (i); ++ ++ fail_free: ++ if (fwd->connect_host != NULL) { ++ xfree(fwd->connect_host); ++ fwd->connect_host = NULL; ++ } ++ if (fwd->listen_host != NULL) { ++ xfree(fwd->listen_host); ++ fwd->listen_host = NULL; ++ } ++ return (0); ++} +diff -NupwB readconf.h readconf.h +--- readconf.h 2009-02-14 00:28:21.000000000 -0500 ++++ readconf.h 2009-05-14 12:36:10.000000000 -0400 +@@ -57,6 +57,11 @@ typedef struct { + int compression_level; /* Compression level 1 (fast) to 9 + * (best). */ + int tcp_keep_alive; /* Set SO_KEEPALIVE. */ ++ int tcp_rcv_buf; /* user switch to set tcp recv buffer */ ++ int tcp_rcv_buf_poll; /* Option to poll recv buf every window transfer */ ++ int hpn_disabled; /* Switch to disable HPN buffer management */ ++ int hpn_buffer_size; /* User definable size for HPN buffer window */ ++ + LogLevel log_level; /* Level for logging. */ + + int port; /* Port to connect. */ +@@ -102,6 +107,8 @@ typedef struct { + + int enable_ssh_keysign; + int64_t rekey_limit; ++ int none_switch; /* Use none cipher */ ++ int none_enabled; /* Allow none to be used */ + int no_host_authentication_for_localhost; + int identities_only; + int server_alive_interval; +diff -NupwB readconf.h.orig readconf.h.orig +--- readconf.h.orig 1969-12-31 19:00:00.000000000 -0500 ++++ readconf.h.orig 2009-02-14 00:28:21.000000000 -0500 +@@ -0,0 +1,145 @@ ++/* $OpenBSD: readconf.h,v 1.78 2009/02/12 03:00:56 djm Exp $ */ ++ ++/* ++ * Author: Tatu Ylonen ++ * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland ++ * All rights reserved ++ * Functions for reading the configuration file. ++ * ++ * 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 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. */ ++} Forward; ++/* Data structure for representing option data. */ ++ ++#define MAX_SEND_ENV 256 ++ ++typedef struct { ++ int forward_agent; /* Forward authentication agent. */ ++ int forward_x11; /* Forward X11 display. */ ++ 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. */ ++ int use_privileged_port; /* Don't use privileged port if false. */ ++ int rhosts_rsa_authentication; /* Try rhosts with RSA ++ * authentication. */ ++ int rsa_authentication; /* Try RSA authentication. */ ++ int pubkey_authentication; /* Try ssh2 pubkey authentication. */ ++ int hostbased_authentication; /* ssh2's rhosts_rsa */ ++ int challenge_response_authentication; ++ /* Try S/Key or TIS, authentication. */ ++ int gss_authentication; /* Try GSS authentication */ ++ int gss_deleg_creds; /* Delegate GSS credentials */ ++ int password_authentication; /* Try password ++ * authentication. */ ++ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ ++ char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ ++ int zero_knowledge_password_authentication; /* Try jpake */ ++ int batch_mode; /* Batch mode: do not ask for passwords. */ ++ int check_host_ip; /* Also keep track of keys for IP address */ ++ int strict_host_key_checking; /* Strict host key checking. */ ++ int compression; /* Compress packets in both directions. */ ++ int compression_level; /* Compression level 1 (fast) to 9 ++ * (best). */ ++ int tcp_keep_alive; /* Set SO_KEEPALIVE. */ ++ LogLevel log_level; /* Level for logging. */ ++ ++ int port; /* Port to connect. */ ++ int address_family; ++ int connection_attempts; /* Max attempts (seconds) before ++ * giving up */ ++ int connection_timeout; /* Max time (seconds) before ++ * aborting connection attempt */ ++ int number_of_password_prompts; /* Max number of password ++ * prompts. */ ++ int cipher; /* Cipher to use. */ ++ char *ciphers; /* SSH2 ciphers in order of preference. */ ++ char *macs; /* SSH2 macs in order of preference. */ ++ char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */ ++ int protocol; /* Protocol in order of preference. */ ++ char *hostname; /* Real host to connect. */ ++ char *host_key_alias; /* hostname alias for .ssh/known_hosts */ ++ char *proxy_command; /* Proxy command for connecting the host. */ ++ char *user; /* User to log in as. */ ++ int escape_char; /* Escape character; -2 = none */ ++ ++ char *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */ ++ char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */ ++ char *system_hostfile2; ++ char *user_hostfile2; ++ char *preferred_authentications; ++ char *bind_address; /* local socket address for connection to sshd */ ++ char *smartcard_device; /* Smartcard reader device */ ++ int verify_host_key_dns; /* Verify host key using DNS */ ++ ++ int num_identity_files; /* Number of files for RSA/DSA identities. */ ++ char *identity_files[SSH_MAX_IDENTITY_FILES]; ++ Key *identity_keys[SSH_MAX_IDENTITY_FILES]; ++ ++ /* Local TCP/IP forward requests. */ ++ int num_local_forwards; ++ Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; ++ ++ /* Remote TCP/IP forward requests. */ ++ int num_remote_forwards; ++ Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; ++ int clear_forwardings; ++ ++ int enable_ssh_keysign; ++ int64_t rekey_limit; ++ int no_host_authentication_for_localhost; ++ int identities_only; ++ int server_alive_interval; ++ int server_alive_count_max; ++ ++ int num_send_env; ++ char *send_env[MAX_SEND_ENV]; ++ ++ char *control_path; ++ int control_master; ++ ++ int hash_known_hosts; ++ ++ int tun_open; /* tun(4) */ ++ int tun_local; /* force tun device (optional) */ ++ int tun_remote; /* force tun device (optional) */ ++ ++ char *local_command; ++ int permit_local_command; ++ int visual_host_key; ++ ++} Options; ++ ++#define SSHCTL_MASTER_NO 0 ++#define SSHCTL_MASTER_YES 1 ++#define SSHCTL_MASTER_AUTO 2 ++#define SSHCTL_MASTER_ASK 3 ++#define SSHCTL_MASTER_AUTO_ASK 4 ++ ++void initialize_options(Options *); ++void fill_default_options(Options *); ++int read_config_file(const char *, const char *, Options *, int); ++int parse_forward(Forward *, const char *, int, int); ++ ++int ++process_config_line(Options *, const char *, char *, const char *, int, int *); ++ ++void add_local_forward(Options *, const Forward *); ++void add_remote_forward(Options *, const Forward *); ++ ++#endif /* READCONF_H */ +Common subdirectories: regress and regress +Common subdirectories: scard and scard +diff -NupwB scp.c scp.c +--- scp.c 2008-11-03 03:23:45.000000000 -0500 ++++ scp.c 2009-05-14 12:36:10.000000000 -0400 +@@ -632,7 +632,7 @@ source(int argc, char **argv) + off_t i, statbytes; + size_t amt; + int fd = -1, haderr, indx; +- char *last, *name, buf[2048], encname[MAXPATHLEN]; ++ char *last, *name, buf[16384], encname[MAXPATHLEN]; + int len; + + for (indx = 0; indx < argc; ++indx) { +@@ -868,7 +868,7 @@ sink(int argc, char **argv) + mode_t mode, omode, mask; + off_t size, statbytes; + int setimes, targisdir, wrerrno = 0; +- char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; ++ char ch, *cp, *np, *targ, *why, *vect[1], buf[16384]; + struct timeval tv[2]; + + #define atime tv[0] +diff -NupwB servconf.h servconf.h +--- servconf.h 2009-01-28 00:31:23.000000000 -0500 ++++ servconf.h 2009-05-14 12:36:10.000000000 -0400 +@@ -145,6 +145,10 @@ typedef struct { + char *adm_forced_command; + + int use_pam; /* Enable auth via PAM */ ++ int none_enabled; /* enable NONE cipher switch */ ++ int tcp_rcv_buf_poll; /* poll tcp rcv window in autotuning kernels*/ ++ int hpn_disabled; /* disable hpn functionality. false by default */ ++ int hpn_buffer_size; /* set the hpn buffer size - default 3MB */ + + int permit_tun; + +diff -NupwB serverloop.c serverloop.c +--- serverloop.c 2009-02-14 00:33:09.000000000 -0500 ++++ serverloop.c 2009-05-14 12:36:10.000000000 -0400 +@@ -93,10 +93,10 @@ static int fdin; /* Descriptor for stdi + static int fdout; /* Descriptor for stdout (for reading); + May be same number as fdin. */ + static int fderr; /* Descriptor for stderr. May be -1. */ +-static long stdin_bytes = 0; /* Number of bytes written to stdin. */ +-static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ +-static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ +-static long fdout_bytes = 0; /* Number of stdout bytes read from program. */ ++static u_long stdin_bytes = 0; /* Number of bytes written to stdin. */ ++static u_long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ ++static u_long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ ++static u_long fdout_bytes = 0; /* Number of stdout bytes read from program. */ + static int stdin_eof = 0; /* EOF message received from client. */ + static int fdout_eof = 0; /* EOF encountered reading from fdout. */ + static int fderr_eof = 0; /* EOF encountered readung from fderr. */ +@@ -121,6 +121,20 @@ static volatile sig_atomic_t received_si + static void server_init_dispatch(void); + + /* ++ * Returns current time in seconds from Jan 1, 1970 with the maximum ++ * available resolution. ++ */ ++ ++static double ++get_current_time(void) ++{ ++ struct timeval tv; ++ gettimeofday(&tv, NULL); ++ return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; ++} ++ ++ ++/* + * we write to this pipe if a SIGCHLD is caught in order to avoid + * the race between select() and child_terminated + */ +@@ -410,6 +424,7 @@ process_input(fd_set *readset) + } else { + /* Buffer any received data. */ + packet_process_incoming(buf, len); ++ fdout_bytes += len; + } + } + if (compat20) +@@ -432,6 +447,7 @@ process_input(fd_set *readset) + } else { + buffer_append(&stdout_buffer, buf, len); + fdout_bytes += len; ++ debug ("FD out now: %ld", fdout_bytes); + } + } + /* Read and buffer any available stderr data from the program. */ +@@ -499,7 +515,7 @@ process_output(fd_set *writeset) + } + /* Send any buffered packet data to the client. */ + if (FD_ISSET(connection_out, writeset)) +- packet_write_poll(); ++ stdin_bytes += packet_write_poll(); + } + + /* +@@ -816,8 +832,10 @@ server_loop2(Authctxt *authctxt) + { + fd_set *readset = NULL, *writeset = NULL; + int rekeying = 0, max_fd, nalloc = 0; ++ double start_time, total_time; + + debug("Entering interactive session for SSH2."); ++ start_time = get_current_time(); + + mysignal(SIGCHLD, sigchld_handler); + child_terminated = 0; +@@ -879,6 +897,11 @@ server_loop2(Authctxt *authctxt) + + /* free remaining sessions, e.g. remove wtmp entries */ + session_destroy_all(NULL); ++ total_time = get_current_time() - start_time; ++ logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f", ++ get_remote_ipaddr(), get_remote_port(), ++ stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time, ++ fdout_bytes / total_time); + } + + static void +@@ -994,8 +1017,12 @@ server_request_tun(void) + sock = tun_open(tun, mode); + if (sock < 0) + goto done; ++ if (options.hpn_disabled) + c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); ++ else ++ c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, ++ options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); + c->datagram = 1; + #if defined(SSH_TUN_FILTER) + if (mode == SSH_TUNMODE_POINTOPOINT) +@@ -1031,6 +1058,8 @@ server_request_session(void) + c = channel_new("session", SSH_CHANNEL_LARVAL, + -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, + 0, "server-session", 1); ++ if ((options.tcp_rcv_buf_poll) && (!options.hpn_disabled)) ++ c->dynamic_window = 1; + if (session_open(the_authctxt, c->self) != 1) { + debug("session open failed, free channel %d", c->self); + channel_free(c); +diff -NupwB session.c session.c +--- session.c 2009-01-28 00:29:49.000000000 -0500 ++++ session.c 2009-05-14 12:36:10.000000000 -0400 +@@ -230,6 +230,7 @@ auth_input_request_forwarding(struct pas + } + + /* Allocate a channel for the authentication agent socket. */ ++ /* this shouldn't matter if its hpn or not - cjr */ + nc = channel_new("auth socket", + SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, +@@ -2301,10 +2302,16 @@ session_set_fds(Session *s, int fdin, in + */ + if (s->chanid == -1) + fatal("no channel for session %d", s->self); ++ if (options.hpn_disabled) + channel_set_fds(s->chanid, + fdout, fdin, fderr, + fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, + 1, is_tty, CHAN_SES_WINDOW_DEFAULT); ++ else ++ channel_set_fds(s->chanid, ++ fdout, fdin, fderr, ++ fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, ++ 1, is_tty, options.hpn_buffer_size); + } + + /* +diff -NupwB sftp.1 sftp.1 +--- sftp.1 2009-01-28 00:14:09.000000000 -0500 ++++ sftp.1 2009-05-14 12:36:10.000000000 -0400 +@@ -203,7 +203,8 @@ This option may be useful in debugging t + 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. ++The default is 256 outstanding requests providing for 8MB ++of outstanding data with a 32KB buffer. + .It Fl S Ar program + Name of the + .Ar program +diff -NupwB sftp.c sftp.c +--- sftp.c 2009-02-14 00:26:19.000000000 -0500 ++++ sftp.c 2009-05-14 12:36:10.000000000 -0400 +@@ -75,7 +75,7 @@ int batchmode = 0; + size_t copy_buffer_len = 32768; + + /* Number of concurrent outstanding requests */ +-size_t num_requests = 64; ++size_t num_requests = 256; + + /* PID of ssh transport process */ + static pid_t sshpid = -1; +diff -NupwB ssh.c ssh.c +--- ssh.c 2009-02-14 00:28:21.000000000 -0500 ++++ ssh.c 2009-05-14 12:36:10.000000000 -0400 +@@ -492,9 +492,6 @@ main(int ac, char **av) + no_shell_flag = 1; + no_tty_flag = 1; + break; +- case 'T': +- no_tty_flag = 1; +- break; + case 'o': + dummy = 1; + line = xstrdup(optarg); +@@ -503,6 +500,13 @@ main(int ac, char **av) + exit(255); + xfree(line); + break; ++ case 'T': ++ no_tty_flag = 1; ++ /* ensure that the user doesn't try to backdoor a */ ++ /* null cipher switch on an interactive session */ ++ /* so explicitly disable it no matter what */ ++ options.none_switch=0; ++ break; + case 's': + subsystem_flag = 1; + break; +@@ -1142,6 +1146,9 @@ ssh_session2_open(void) + { + Channel *c; + int window, packetmax, in, out, err; ++ int sock; ++ int socksize; ++ int socksizelen = sizeof(int); + + if (stdin_null_flag) { + in = open(_PATH_DEVNULL, O_RDONLY); +@@ -1162,9 +1169,75 @@ ssh_session2_open(void) + if (!isatty(err)) + set_nonblock(err); + +- window = CHAN_SES_WINDOW_DEFAULT; ++ /* we need to check to see if what they want to do about buffer */ ++ /* sizes here. In a hpn to nonhpn connection we want to limit */ ++ /* the window size to something reasonable in case the far side */ ++ /* has the large window bug. In hpn to hpn connection we want to */ ++ /* use the max window size but allow the user to override it */ ++ /* lastly if they disabled hpn then use the ssh std window size */ ++ ++ /* so why don't we just do a getsockopt() here and set the */ ++ /* ssh window to that? In the case of a autotuning receive */ ++ /* window the window would get stuck at the initial buffer */ ++ /* size generally less than 96k. Therefore we need to set the */ ++ /* maximum ssh window size to the maximum hpn buffer size */ ++ /* unless the user has specifically set the tcprcvbufpoll */ ++ /* to no. In which case we *can* just set the window to the */ ++ /* minimum of the hpn buffer size and tcp receive buffer size */ ++ ++ if (tty_flag) ++ options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; ++ else ++ options.hpn_buffer_size = 2*1024*1024; ++ ++ if (datafellows & SSH_BUG_LARGEWINDOW) ++ { ++ debug("HPN to Non-HPN Connection"); ++ } ++ else ++ { ++ if (options.tcp_rcv_buf_poll <= 0) ++ { ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ debug("socksize %d", socksize); ++ options.hpn_buffer_size = socksize; ++ debug ("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size); ++ } ++ else ++ { ++ if (options.tcp_rcv_buf > 0) ++ { ++ /*create a socket but don't connect it */ ++ /* we use that the get the rcv socket size */ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ /* if they are using the tcp_rcv_buf option */ ++ /* attempt to set the buffer size to that */ ++ if (options.tcp_rcv_buf) ++ setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&options.tcp_rcv_buf, ++ sizeof(options.tcp_rcv_buf)); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ debug("socksize %d", socksize); ++ options.hpn_buffer_size = socksize; ++ debug ("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size); ++ } ++ } ++ ++ } ++ ++ debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); ++ ++ window = options.hpn_buffer_size; ++ ++ channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); ++ + packetmax = CHAN_SES_PACKET_DEFAULT; + if (tty_flag) { ++ window = 4*CHAN_SES_PACKET_DEFAULT; + window >>= 1; + packetmax >>= 1; + } +@@ -1172,7 +1245,10 @@ ssh_session2_open(void) + "session", SSH_CHANNEL_OPENING, in, out, err, + window, packetmax, CHAN_EXTENDED_WRITE, + "client-session", /*nonblock*/0); +- ++ if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) { ++ c->dynamic_window = 1; ++ debug ("Enabled Dynamic Window Scaling\n"); ++ } + debug3("ssh_session2_open: channel_new: %d", c->self); + + channel_send_open(c->self); +diff -NupwB sshconnect2.c sshconnect2.c +--- sshconnect2.c 2008-11-05 00:20:47.000000000 -0500 ++++ sshconnect2.c 2009-05-14 12:36:10.000000000 -0400 +@@ -78,6 +78,12 @@ + extern char *client_version_string; + extern char *server_version_string; + extern Options options; ++extern Kex *xxx_kex; ++ ++/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ ++/* if it is set then prevent the switch to the null cipher */ ++ ++extern int tty_flag; + + /* + * SSH2 key exchange +@@ -350,6 +356,28 @@ ssh_userauth2(const char *local_user, co + pubkey_cleanup(&authctxt); + dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); + ++ /* if the user wants to use the none cipher do it */ ++ /* post authentication and only if the right conditions are met */ ++ /* both of the NONE commands must be true and there must be no */ ++ /* tty allocated */ ++ if ((options.none_switch == 1) && (options.none_enabled == 1)) ++ { ++ if (!tty_flag) /* no null on tty sessions */ ++ { ++ debug("Requesting none rekeying..."); ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = "none"; ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none"; ++ kex_prop2buf(&xxx_kex->my,myproposal); ++ packet_request_rekeying(); ++ fprintf(stderr, "WARNING: ENABLED NONE CIPHER\n"); ++ } ++ else ++ { ++ /* requested NONE cipher when in a tty */ ++ debug("Cannot switch to NONE cipher with tty allocated"); ++ fprintf(stderr, "NONE cipher switch disabled when a TTY is allocated\n"); ++ } ++ } + debug("Authentication succeeded (%s).", authctxt.method->name); + } + +diff -NupwB sshconnect.c sshconnect.c +--- sshconnect.c 2009-02-01 06:19:54.000000000 -0500 ++++ sshconnect.c 2009-05-14 12:36:10.000000000 -0400 +@@ -165,6 +165,31 @@ ssh_proxy_connect(const char *host, u_sh + } + + /* ++ * Set TCP receive buffer if requested. ++ * Note: tuning needs to happen after the socket is ++ * created but before the connection happens ++ * so winscale is negotiated properly -cjr ++ */ ++static void ++ssh_set_socket_recvbuf(int sock) ++{ ++ void *buf = (void *)&options.tcp_rcv_buf; ++ int sz = sizeof(options.tcp_rcv_buf); ++ int socksize; ++ int socksizelen = sizeof(int); ++ ++ debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf); ++ if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) { ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); ++ debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); ++ } ++ else ++ error("Couldn't set socket receive buffer to %d: %.100s", ++ options.tcp_rcv_buf, strerror(errno)); ++} ++ ++ ++/* + * Creates a (possibly privileged) socket for use as the ssh connection. + */ + static int +@@ -187,12 +212,18 @@ ssh_create_socket(int privileged, struct + strerror(errno)); + else + debug("Allocated local port %d.", p); ++ ++ if (options.tcp_rcv_buf > 0) ++ ssh_set_socket_recvbuf(sock); + return sock; + } + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) + error("socket: %.100s", strerror(errno)); + ++ if (options.tcp_rcv_buf > 0) ++ ssh_set_socket_recvbuf(sock); ++ + /* Bind the socket to an alternative local IP address */ + if (options.bind_address == NULL) + return sock; +@@ -536,7 +567,7 @@ ssh_exchange_identification(int timeout_ + snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", + compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, + compat20 ? PROTOCOL_MINOR_2 : minor1, +- SSH_VERSION, compat20 ? "\r\n" : "\n"); ++ SSH_RELEASE, compat20 ? "\r\n" : "\n"); + if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) + fatal("write: %.100s", strerror(errno)); + client_version_string = xstrdup(buf); +diff -NupwB sshd.c sshd.c +--- sshd.c 2009-01-28 00:31:23.000000000 -0500 ++++ sshd.c 2009-05-14 12:36:10.000000000 -0400 +@@ -136,6 +136,9 @@ int deny_severity; + #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) + #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) + ++int myflag = 0; ++ ++ + extern char *__progname; + + /* Server configuration options. */ +@@ -415,7 +418,7 @@ sshd_exchange_identification(int sock_in + minor = PROTOCOL_MINOR_1; + } + snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor, +- SSH_VERSION, newline); ++ SSH_RELEASE, newline); + server_version_string = xstrdup(buf); + + /* Send our protocol version identification. */ +@@ -466,6 +469,9 @@ sshd_exchange_identification(int sock_in + } + debug("Client protocol version %d.%d; client software version %.100s", + remote_major, remote_minor, remote_version); ++ logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s", ++ get_remote_ipaddr(), get_remote_port(), ++ remote_major, remote_minor, remote_version); + + compat_datafellows(remote_version); + +@@ -944,6 +950,8 @@ server_listen(void) + int ret, listen_sock, on = 1; + struct addrinfo *ai; + char ntop[NI_MAXHOST], strport[NI_MAXSERV]; ++ int socksize; ++ int socksizelen = sizeof(int); + + for (ai = options.listen_addrs; ai; ai = ai->ai_next) { + if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) +@@ -990,6 +998,11 @@ server_listen(void) + + debug("Bind to port %s on %s.", strport, ntop); + ++ getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ debug("Server TCP RWIN socket size: %d", socksize); ++ debug("HPN Buffer Size: %d", options.hpn_buffer_size); ++ + /* Bind the socket to the desired port. */ + if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { + error("Bind to port %s on %s failed: %.200s.", +@@ -1817,6 +1830,9 @@ main(int ac, char **av) + /* Log the connection. */ + verbose("Connection from %.500s port %d", remote_ip, remote_port); + ++ /* set the HPN options for the child */ ++ channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); ++ + /* + * We don't want to listen forever unless the other side + * successfully authenticates itself. So we set up an alarm which is +@@ -2171,9 +2187,15 @@ do_ssh2_kex(void) + { + Kex *kex; + ++ myflag++; ++ debug ("MYFLAG IS %d", myflag); + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (options.none_enabled == 1) { ++ debug ("WARNING: None cipher enabled"); ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_ENCRYPT_INCLUDE_NONE; + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +diff -NupwB sshd_config sshd_config +--- sshd_config 2008-07-02 08:35:43.000000000 -0400 ++++ sshd_config 2009-05-14 12:36:10.000000000 -0400 +@@ -112,6 +112,20 @@ Protocol 2 + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + ++# the following are HPN related configuration options ++# tcp receive buffer polling. disable in non autotuning kernels ++#TcpRcvBufPoll yes ++ ++# allow the use of the none cipher ++#NoneEnabled no ++ ++# disable hpn performance boosts. ++#HPNDisabled no ++ ++# buffer size for hpn to non-hpn connections ++#HPNBufferSize 2048 ++ ++ + # Example of overriding settings on a per-user basis + #Match User anoncvs + # X11Forwarding no +diff -NupwB version.h version.h +--- version.h 2009-02-22 19:09:26.000000000 -0500 ++++ version.h 2009-05-14 12:42:05.000000000 -0400 +@@ -3,4 +3,5 @@ + #define SSH_VERSION "OpenSSH_5.2" + + #define SSH_PORTABLE "p1" +-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE ++#define SSH_HPN "-hpn13v6" ++#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/openssh-lpk+hpn-servconf.patch /usr/home/dindin/workspace/openssh-portable/files/openssh-lpk+hpn-servconf.patch --- /usr/ports/security/openssh-portable/files/openssh-lpk+hpn-servconf.patch 2009-05-15 15:00:27.000000000 +0400 +++ /usr/home/dindin/workspace/openssh-portable/files/openssh-lpk+hpn-servconf.patch 1970-01-01 03:00:00.000000000 +0300 @@ -1,240 +0,0 @@ ---- servconf.c.orig 2009-05-02 19:35:42.000000000 +0400 -+++ servconf.c 2009-05-02 19:37:13.000000000 +0400 -@@ -42,6 +42,10 @@ - #include "channels.h" - #include "groupaccess.h" - -+#ifdef WITH_LDAP_PUBKEY -+#include "ldapauth.h" -+#endif -+ - static void add_listen_addr(ServerOptions *, char *, int); - static void add_one_listen_addr(ServerOptions *, char *, int); - -@@ -74,7 +78,7 @@ - options->ignore_user_known_hosts = -1; - options->print_motd = -1; - options->print_lastlog = -1; -- options->x11_forwarding = -1; -+ options->x11_forwarding = 1; - options->x11_display_offset = -1; - options->x11_use_localhost = -1; - options->xauth_location = NULL; -@@ -127,12 +131,39 @@ - options->num_permitted_opens = -1; - options->adm_forced_command = NULL; - options->chroot_directory = NULL; -+ options->none_enabled = -1; -+ options->tcp_rcv_buf_poll = -1; -+ options->hpn_disabled = -1; -+ options->hpn_buffer_size = -1; - options->zero_knowledge_password_authentication = -1; -+#ifdef WITH_LDAP_PUBKEY -+ /* XXX dirty */ -+ options->lpk.ld = NULL; -+ options->lpk.on = -1; -+ options->lpk.servers = NULL; -+ options->lpk.u_basedn = NULL; -+ options->lpk.g_basedn = NULL; -+ options->lpk.binddn = NULL; -+ options->lpk.bindpw = NULL; -+ options->lpk.sgroup = NULL; -+ options->lpk.filter = NULL; -+ options->lpk.fgroup = NULL; -+ options->lpk.l_conf = NULL; -+ options->lpk.tls = -1; -+ options->lpk.b_timeout.tv_sec = -1; -+ options->lpk.s_timeout.tv_sec = -1; -+ options->lpk.flags = FLAG_EMPTY; -+#endif - } - - void - fill_default_server_options(ServerOptions *options) - { -+ /* needed for hpn socket tests */ -+ int sock; -+ int socksize; -+ int socksizelen = sizeof(int); -+ - /* Portable-specific options */ - if (options->use_pam == -1) - options->use_pam = 1; -@@ -265,6 +296,32 @@ - options->permit_tun = SSH_TUNMODE_NO; - if (options->zero_knowledge_password_authentication == -1) - options->zero_knowledge_password_authentication = 0; -+#ifdef WITH_LDAP_PUBKEY -+ if (options->lpk.on == -1) -+ options->lpk.on = _DEFAULT_LPK_ON; -+ if (options->lpk.servers == NULL) -+ options->lpk.servers = _DEFAULT_LPK_SERVERS; -+ if (options->lpk.u_basedn == NULL) -+ options->lpk.u_basedn = _DEFAULT_LPK_UDN; -+ if (options->lpk.g_basedn == NULL) -+ options->lpk.g_basedn = _DEFAULT_LPK_GDN; -+ if (options->lpk.binddn == NULL) -+ options->lpk.binddn = _DEFAULT_LPK_BINDDN; -+ if (options->lpk.bindpw == NULL) -+ options->lpk.bindpw = _DEFAULT_LPK_BINDPW; -+ if (options->lpk.sgroup == NULL) -+ options->lpk.sgroup = _DEFAULT_LPK_SGROUP; -+ if (options->lpk.filter == NULL) -+ options->lpk.filter = _DEFAULT_LPK_FILTER; -+ if (options->lpk.tls == -1) -+ options->lpk.tls = _DEFAULT_LPK_TLS; -+ if (options->lpk.b_timeout.tv_sec == -1) -+ options->lpk.b_timeout.tv_sec = _DEFAULT_LPK_BTIMEOUT; -+ if (options->lpk.s_timeout.tv_sec == -1) -+ options->lpk.s_timeout.tv_sec = _DEFAULT_LPK_STIMEOUT; -+ if (options->lpk.l_conf == NULL) -+ options->lpk.l_conf = _DEFAULT_LPK_LDP; -+#endif - - if (options->hpn_disabled == -1) - options->hpn_disabled = 0; -@@ -345,8 +402,15 @@ - sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, - sMatch, sPermitOpen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, -+ sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, - sZeroKnowledgePasswordAuthentication, - sDeprecated, sUnsupported -+#ifdef WITH_LDAP_PUBKEY -+ ,sLdapPublickey, sLdapServers, sLdapUserDN -+ ,sLdapGroupDN, sBindDN, sBindPw, sMyGroup -+ ,sLdapFilter, sForceTLS, sBindTimeout -+ ,sSearchTimeout, sLdapConf -+#endif - } ServerOpCodes; - - #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ -@@ -457,6 +521,20 @@ - { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, - { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, - { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, -+#ifdef WITH_LDAP_PUBKEY -+ { _DEFAULT_LPK_TOKEN, sLdapPublickey, SSHCFG_GLOBAL }, -+ { _DEFAULT_SRV_TOKEN, sLdapServers, SSHCFG_GLOBAL }, -+ { _DEFAULT_USR_TOKEN, sLdapUserDN, SSHCFG_GLOBAL }, -+ { _DEFAULT_GRP_TOKEN, sLdapGroupDN, SSHCFG_GLOBAL }, -+ { _DEFAULT_BDN_TOKEN, sBindDN, SSHCFG_GLOBAL }, -+ { _DEFAULT_BPW_TOKEN, sBindPw, SSHCFG_GLOBAL }, -+ { _DEFAULT_MYG_TOKEN, sMyGroup, SSHCFG_GLOBAL }, -+ { _DEFAULT_FIL_TOKEN, sLdapFilter, SSHCFG_GLOBAL }, -+ { _DEFAULT_TLS_TOKEN, sForceTLS, SSHCFG_GLOBAL }, -+ { _DEFAULT_BTI_TOKEN, sBindTimeout, SSHCFG_GLOBAL }, -+ { _DEFAULT_STI_TOKEN, sSearchTimeout, SSHCFG_GLOBAL }, -+ { _DEFAULT_LDP_TOKEN, sLdapConf, SSHCFG_GLOBAL }, -+#endif - { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, - { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, - { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL }, -@@ -1368,6 +1446,107 @@ - while (arg) - arg = strdelim(&cp); - break; -+#ifdef WITH_LDAP_PUBKEY -+ case sLdapPublickey: -+ intptr = &options->lpk.on; -+ goto parse_flag; -+ case sLdapServers: -+ /* arg = strdelim(&cp); */ -+ p = line; -+ while(*p++); -+ arg = p; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing ldap server",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ if ((options->lpk.servers = ldap_parse_servers(arg)) == NULL) -+ fatal("%s line %d: error in ldap servers", filename, linenum); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sLdapUserDN: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing ldap server",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.u_basedn = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sLdapGroupDN: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing ldap server",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.g_basedn = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sBindDN: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing binddn",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.binddn = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sBindPw: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing bindpw",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.bindpw = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sMyGroup: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing groupname",filename, linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.sgroup = xstrdup(arg); -+ if (options->lpk.sgroup) -+ options->lpk.fgroup = ldap_parse_groups(options->lpk.sgroup); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sLdapFilter: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing filter",filename, linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.filter = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sForceTLS: -+ intptr = &options->lpk.tls; -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing yes/no argument.", -+ filename, linenum); -+ value = 0; /* silence compiler */ -+ if (strcmp(arg, "yes") == 0) -+ value = 1; -+ else if (strcmp(arg, "no") == 0) -+ value = 0; -+ else if (strcmp(arg, "try") == 0) -+ value = -1; -+ else -+ fatal("%s line %d: Bad yes/no argument: %s", -+ filename, linenum, arg); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ case sBindTimeout: -+ intptr = (int *) &options->lpk.b_timeout.tv_sec; -+ goto parse_int; -+ case sSearchTimeout: -+ intptr = (int *) &options->lpk.s_timeout.tv_sec; -+ goto parse_int; -+ break; -+ case sLdapConf: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing LpkLdapConf", filename, linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.l_conf = xstrdup(arg); -+ memset(arg, 0, strlen(arg)); -+ break; -+#endif - - default: - fatal("%s line %d: Missing handler for opcode %s (%d)", diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/openssh-lpk-5.0p1-0.3.9-servconv.patch /usr/home/dindin/workspace/openssh-portable/files/openssh-lpk-5.0p1-0.3.9-servconv.patch --- /usr/ports/security/openssh-portable/files/openssh-lpk-5.0p1-0.3.9-servconv.patch 2009-05-15 15:00:27.000000000 +0400 +++ /usr/home/dindin/workspace/openssh-portable/files/openssh-lpk-5.0p1-0.3.9-servconv.patch 1970-01-01 03:00:00.000000000 +0300 @@ -1,222 +0,0 @@ ---- servconf.c.orig 2009-05-02 19:24:09.000000000 +0400 -+++ servconf.c 2009-05-02 19:29:37.000000000 +0400 -@@ -42,6 +42,10 @@ - #include "channels.h" - #include "groupaccess.h" - -+#ifdef WITH_LDAP_PUBKEY -+#include "ldapauth.h" -+#endif -+ - static void add_listen_addr(ServerOptions *, char *, int); - static void add_one_listen_addr(ServerOptions *, char *, int); - -@@ -74,7 +78,7 @@ - options->ignore_user_known_hosts = -1; - options->print_motd = -1; - options->print_lastlog = -1; -- options->x11_forwarding = -1; -+ options->x11_forwarding = 1; - options->x11_display_offset = -1; - options->x11_use_localhost = -1; - options->xauth_location = NULL; -@@ -128,6 +132,24 @@ - options->adm_forced_command = NULL; - options->chroot_directory = NULL; - options->zero_knowledge_password_authentication = -1; -+#ifdef WITH_LDAP_PUBKEY -+ /* XXX dirty */ -+ options->lpk.ld = NULL; -+ options->lpk.on = -1; -+ options->lpk.servers = NULL; -+ options->lpk.u_basedn = NULL; -+ options->lpk.g_basedn = NULL; -+ options->lpk.binddn = NULL; -+ options->lpk.bindpw = NULL; -+ options->lpk.sgroup = NULL; -+ options->lpk.filter = NULL; -+ options->lpk.fgroup = NULL; -+ options->lpk.l_conf = NULL; -+ options->lpk.tls = -1; -+ options->lpk.b_timeout.tv_sec = -1; -+ options->lpk.s_timeout.tv_sec = -1; -+ options->lpk.flags = FLAG_EMPTY; -+#endif - } - - void -@@ -265,6 +287,32 @@ - options->permit_tun = SSH_TUNMODE_NO; - if (options->zero_knowledge_password_authentication == -1) - options->zero_knowledge_password_authentication = 0; -+#ifdef WITH_LDAP_PUBKEY -+ if (options->lpk.on == -1) -+ options->lpk.on = _DEFAULT_LPK_ON; -+ if (options->lpk.servers == NULL) -+ options->lpk.servers = _DEFAULT_LPK_SERVERS; -+ if (options->lpk.u_basedn == NULL) -+ options->lpk.u_basedn = _DEFAULT_LPK_UDN; -+ if (options->lpk.g_basedn == NULL) -+ options->lpk.g_basedn = _DEFAULT_LPK_GDN; -+ if (options->lpk.binddn == NULL) -+ options->lpk.binddn = _DEFAULT_LPK_BINDDN; -+ if (options->lpk.bindpw == NULL) -+ options->lpk.bindpw = _DEFAULT_LPK_BINDPW; -+ if (options->lpk.sgroup == NULL) -+ options->lpk.sgroup = _DEFAULT_LPK_SGROUP; -+ if (options->lpk.filter == NULL) -+ options->lpk.filter = _DEFAULT_LPK_FILTER; -+ if (options->lpk.tls == -1) -+ options->lpk.tls = _DEFAULT_LPK_TLS; -+ if (options->lpk.b_timeout.tv_sec == -1) -+ options->lpk.b_timeout.tv_sec = _DEFAULT_LPK_BTIMEOUT; -+ if (options->lpk.s_timeout.tv_sec == -1) -+ options->lpk.s_timeout.tv_sec = _DEFAULT_LPK_STIMEOUT; -+ if (options->lpk.l_conf == NULL) -+ options->lpk.l_conf = _DEFAULT_LPK_LDP; -+#endif - - /* Turn privilege separation on by default */ - if (use_privsep == -1) -@@ -311,6 +359,12 @@ - sUsePrivilegeSeparation, sAllowAgentForwarding, - sZeroKnowledgePasswordAuthentication, - sDeprecated, sUnsupported -+#ifdef WITH_LDAP_PUBKEY -+ ,sLdapPublickey, sLdapServers, sLdapUserDN -+ ,sLdapGroupDN, sBindDN, sBindPw, sMyGroup -+ ,sLdapFilter, sForceTLS, sBindTimeout -+ ,sSearchTimeout, sLdapConf -+#endif - } ServerOpCodes; - - #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ -@@ -421,6 +475,20 @@ - { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, - { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL }, - { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL }, -+#ifdef WITH_LDAP_PUBKEY -+ { _DEFAULT_LPK_TOKEN, sLdapPublickey, SSHCFG_GLOBAL }, -+ { _DEFAULT_SRV_TOKEN, sLdapServers, SSHCFG_GLOBAL }, -+ { _DEFAULT_USR_TOKEN, sLdapUserDN, SSHCFG_GLOBAL }, -+ { _DEFAULT_GRP_TOKEN, sLdapGroupDN, SSHCFG_GLOBAL }, -+ { _DEFAULT_BDN_TOKEN, sBindDN, SSHCFG_GLOBAL }, -+ { _DEFAULT_BPW_TOKEN, sBindPw, SSHCFG_GLOBAL }, -+ { _DEFAULT_MYG_TOKEN, sMyGroup, SSHCFG_GLOBAL }, -+ { _DEFAULT_FIL_TOKEN, sLdapFilter, SSHCFG_GLOBAL }, -+ { _DEFAULT_TLS_TOKEN, sForceTLS, SSHCFG_GLOBAL }, -+ { _DEFAULT_BTI_TOKEN, sBindTimeout, SSHCFG_GLOBAL }, -+ { _DEFAULT_STI_TOKEN, sSearchTimeout, SSHCFG_GLOBAL }, -+ { _DEFAULT_LDP_TOKEN, sLdapConf, SSHCFG_GLOBAL }, -+#endif - { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL }, - { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, - { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL }, -@@ -1311,6 +1379,107 @@ - while (arg) - arg = strdelim(&cp); - break; -+#ifdef WITH_LDAP_PUBKEY -+ case sLdapPublickey: -+ intptr = &options->lpk.on; -+ goto parse_flag; -+ case sLdapServers: -+ /* arg = strdelim(&cp); */ -+ p = line; -+ while(*p++); -+ arg = p; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing ldap server",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ if ((options->lpk.servers = ldap_parse_servers(arg)) == NULL) -+ fatal("%s line %d: error in ldap servers", filename, linenum); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sLdapUserDN: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing ldap server",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.u_basedn = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sLdapGroupDN: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing ldap server",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.g_basedn = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sBindDN: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing binddn",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.binddn = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sBindPw: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing bindpw",filename,linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.bindpw = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sMyGroup: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing groupname",filename, linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.sgroup = xstrdup(arg); -+ if (options->lpk.sgroup) -+ options->lpk.fgroup = ldap_parse_groups(options->lpk.sgroup); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sLdapFilter: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing filter",filename, linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.filter = xstrdup(arg); -+ memset(arg,0,strlen(arg)); -+ break; -+ case sForceTLS: -+ intptr = &options->lpk.tls; -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing yes/no argument.", -+ filename, linenum); -+ value = 0; /* silence compiler */ -+ if (strcmp(arg, "yes") == 0) -+ value = 1; -+ else if (strcmp(arg, "no") == 0) -+ value = 0; -+ else if (strcmp(arg, "try") == 0) -+ value = -1; -+ else -+ fatal("%s line %d: Bad yes/no argument: %s", -+ filename, linenum, arg); -+ if (*intptr == -1) -+ *intptr = value; -+ break; -+ case sBindTimeout: -+ intptr = (int *) &options->lpk.b_timeout.tv_sec; -+ goto parse_int; -+ case sSearchTimeout: -+ intptr = (int *) &options->lpk.s_timeout.tv_sec; -+ goto parse_int; -+ break; -+ case sLdapConf: -+ arg = cp; -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing LpkLdapConf", filename, linenum); -+ arg[strlen(arg)] = '\0'; -+ options->lpk.l_conf = xstrdup(arg); -+ memset(arg, 0, strlen(arg)); -+ break; -+#endif - - default: - fatal("%s line %d: Missing handler for opcode %s (%d)", diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/openssh-lpk-5.0p1-0.3.9.patch /usr/home/dindin/workspace/openssh-portable/files/openssh-lpk-5.0p1-0.3.9.patch --- /usr/ports/security/openssh-portable/files/openssh-lpk-5.0p1-0.3.9.patch 2009-05-15 15:00:27.000000000 +0400 +++ /usr/home/dindin/workspace/openssh-portable/files/openssh-lpk-5.0p1-0.3.9.patch 1970-01-01 03:00:00.000000000 +0300 @@ -1,1653 +0,0 @@ -# -# Based on: http://dev.inversepath.com/openssh-lpk/openssh-lpk-4.6p1-0.3.9.patch -# ---- Makefile.in.orig 2008-03-12 22:41:31.000000000 -0300 -+++ Makefile.in 2008-04-17 21:25:41.000000000 -0300 -@@ -86,7 +86,7 @@ - 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 \ -- audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o -+ audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o ldapauth.o - - MANPAGES = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out - MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5 ---- README.lpk.orig 2008-04-17 21:24:57.000000000 -0300 -+++ README.lpk 2008-04-17 21:24:57.000000000 -0300 -@@ -0,0 +1,267 @@ -+OpenSSH LDAP PUBLIC KEY PATCH -+Copyright (c) 2003 Eric AUGE (eau@phear.org) -+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. -+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. -+ -+purposes of this patch: -+ -+This patch would help to have authentication centralization policy -+using ssh public key authentication. -+This patch could be an alternative to other "secure" authentication system -+working in a similar way (Kerberos, SecurID, etc...), except the fact -+that it's based on OpenSSH and its public key abilities. -+ -+>> FYI: << -+'uid': means unix accounts existing on the current server -+'lpkServerGroup:' mean server group configured on the current server ('lpkServerGroup' in sshd_config) -+ -+example schema: -+ -+ -+ server1 (uid: eau,rival,toto) (lpkServerGroup: unix) -+ ___________ / -+ / \ --- - server3 (uid: eau, titi) (lpkServerGroup: unix) -+ | LDAP Server | \ -+ | eau ,rival | server2 (uid: rival, eau) (lpkServerGroup: unix) -+ | titi ,toto | -+ | userx,.... | server5 (uid: eau) (lpkServerGroup: mail) -+ \___________/ \ / -+ ----- - server4 (uid: eau, rival) (no group configured) -+ \ -+ etc... -+ -+- WHAT WE NEED : -+ -+ * configured LDAP server somewhere on the network (i.e. OpenLDAP) -+ * patched sshd (with this patch ;) -+ * LDAP user(/group) entry (look at users.ldif (& groups.ldif)): -+ User entry: -+ - attached to the 'ldapPublicKey' objectclass -+ - attached to the 'posixAccount' objectclass -+ - with a filled 'sshPublicKey' attribute -+ Example: -+ dn: uid=eau,ou=users,dc=cuckoos,dc=net -+ objectclass: top -+ objectclass: person -+ objectclass: organizationalPerson -+ objectclass: posixAccount -+ objectclass: ldapPublicKey -+ description: Eric AUGE Account -+ userPassword: blah -+ cn: Eric AUGE -+ sn: Eric AUGE -+ uid: eau -+ uidNumber: 1034 -+ gidNumber: 1 -+ homeDirectory: /export/home/eau -+ sshPublicKey: ssh-dss AAAAB3... -+ sshPublicKey: ssh-dss AAAAM5... -+ -+ Group entry: -+ - attached to the 'posixGroup' objectclass -+ - with a 'cn' groupname attribute -+ - with multiple 'memberUid' attributes filled with usernames allowed in this group -+ Example: -+ # few members -+ dn: cn=unix,ou=groups,dc=cuckoos,dc=net -+ objectclass: top -+ objectclass: posixGroup -+ description: Unix based servers group -+ cn: unix -+ gidNumber: 1002 -+ memberUid: eau -+ memberUid: user1 -+ memberUid: user2 -+ -+ -+- HOW IT WORKS : -+ -+ * without patch -+ If a user wants to authenticate to log in a server the sshd, will first look for authentication method allowed (RSAauth,kerberos,etc..) -+ and if RSAauth and tickets based auth fails, it will fallback to standard password authentication (if enabled). -+ -+ * with the patch -+ If a user want to authenticate to log in a server, the sshd will first look for auth method including LDAP pubkey, if the ldappubkey options is enabled. -+ It will do an ldapsearch to get the public key directly from the LDAP instead of reading it from the server filesystem. -+ (usually in $HOME/.ssh/authorized_keys) -+ -+ If groups are enabled, it will also check if the user that wants to login is in the group of the server he is trying to log into. -+ If it fails, it falls back on RSA auth files ($HOME/.ssh/authorized_keys), etc.. and finally to standard password authentication (if enabled). -+ -+ 7 tokens are added to sshd_config : -+ # here is the new patched ldap related tokens -+ # entries in your LDAP must be posixAccount & strongAuthenticationUser & posixGroup -+ UseLPK yes # look the pub key into LDAP -+ LpkServers ldap://10.31.32.5/ ldap://10.31.32.4 ldap://10.31.32.3 # which LDAP server for users ? (URL format) -+ LpkUserDN ou=users,dc=foobar,dc=net # which base DN for users ? -+ LpkGroupDN ou=groups,dc=foobar,dc=net # which base DN for groups ? -+ LpkBindDN cn=manager,dc=foobar,dc=net # which bind DN ? -+ LpkBindPw asecret # bind DN credidentials -+ LpkServerGroup agroupname # the group the server is part of -+ -+ Right now i'm using anonymous binding to get public keys, because getting public keys of someone doesn't impersonate him¸ but there is some -+ flaws you have to take care of. -+ -+- HOW TO INSERT A USER/KEY INTO AN LDAP ENTRY -+ -+ * my way (there is plenty :) -+ - create ldif file (i.e. users.ldif) -+ - cat ~/.ssh/id_dsa.pub OR cat ~/.ssh/id_rsa.pub OR cat ~/.ssh/identity.pub -+ - my way in 4 steps : -+ Example: -+ -+ # you add this to the user entry in the LDIF file : -+ [...] -+ objectclass: posixAccount -+ objectclass: ldapPublicKey -+ [...] -+ sshPubliKey: ssh-dss AAAABDh12DDUR2... -+ [...] -+ -+ # insert your entry and you're done :) -+ ldapadd -D balblabla -w bleh < file.ldif -+ -+ all standard options can be present in the 'sshPublicKey' attribute. -+ -+- WHY : -+ -+ Simply because, i was looking for a way to centralize all sysadmins authentication, easily, without completely using LDAP -+ as authentication method (like pam_ldap etc..). -+ -+ After looking into Kerberos, SecurID, and other centralized secure authentications systems, the use of RSA and LDAP to get -+ public key for authentication allows us to control who has access to which server (the user needs an account and to be in 'strongAuthenticationUser' -+ objectclass within LDAP and part of the group the SSH server is in). -+ -+ Passwords update are no longer a nightmare for a server farm (key pair passphrase is stored on each user's box and private key is locally encrypted using his passphrase -+ so each user can change it as much as he wants). -+ -+ Blocking a user account can be done directly from the LDAP (if sshd is using RSAAuth + ldap only). -+ -+- RULES : -+ Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' which are defined in core.schema. -+ and the additionnal lpk.schema. -+ -+ This patch could allow a smooth transition between standard auth (/etc/passwd) and complete LDAP based authentication -+ (pamldap, nss_ldap, etc..). -+ -+ This can be an alternative to other (old?/expensive?) authentication methods (Kerberos/SecurID/..). -+ -+ Referring to schema at the beginning of this file if user 'eau' is only in group 'unix' -+ 'eau' would ONLY access 'server1', 'server2', 'server3' AND 'server4' BUT NOT 'server5'. -+ If you then modify the LDAP 'mail' group entry to add 'memberUid: eau' THEN user 'eau' would be able -+ to log in 'server5' (i hope you got the idea, my english is bad :). -+ -+ Each server's sshd is patched and configured to ask the public key and the group infos in the LDAP -+ server. -+ When you want to allow a new user to have access to the server parc, you just add him an account on -+ your servers, you add his public key into his entry on the LDAP server, it's done. -+ -+ Because sshds are looking public keys into the LDAP directly instead of a file ($HOME/.ssh/authorized_keys). -+ -+ When the user needs to change his passphrase he can do it directly from his workstation by changing -+ his own key set lock passphrase, and all servers are automatically aware. -+ -+ With a CAREFUL LDAP server configuration you could allow a user to add/delete/modify his own entry himself -+ so he can add/modify/delete himself his public key when needed. -+ -+­ FLAWS : -+ LDAP must be well configured, getting the public key of some user is not a problem, but if anonymous LDAP -+ allow write to users dn, somebody could replace someuser's public key by its own and impersonate some -+ of your users in all your server farm be VERY CAREFUL. -+ -+ MITM attack when sshd is requesting the public key, could lead to a compromise of your servers allowing login -+ as the impersonnated user. -+ -+ If LDAP server is down then, fallback on passwd auth. -+ -+ the ldap code part has not been well audited yet. -+ -+- LDAP USER ENTRY EXAMPLES (LDIF Format, look in users.ldif) -+ --- CUT HERE --- -+ dn: uid=jdoe,ou=users,dc=foobar,dc=net -+ objectclass: top -+ objectclass: person -+ objectclass: organizationalPerson -+ objectclass: posixAccount -+ objectclass: ldapPublicKey -+ description: My account -+ cn: John Doe -+ sn: John Doe -+ uid: jdoe -+ uidNumber: 100 -+ gidNumber: 100 -+ homeDirectory: /home/jdoe -+ sshPublicKey: ssh-dss AAAAB3NzaC1kc3MAAAEBAOvL8pREUg9wSy/8+hQJ54YF3AXkB0OZrXB.... -+ [...] -+ --- CUT HERE --- -+ -+- LDAP GROUP ENTRY EXAMPLES (LDIF Format, look in groups.ldif) -+ --- CUT HERE --- -+ dn: cn=unix,ou=groups,dc=cuckoos,dc=net -+ objectclass: top -+ objectclass: posixGroup -+ description: Unix based servers group -+ cn: unix -+ gidNumber: 1002 -+ memberUid: jdoe -+ memberUid: user1 -+ memberUid: user2 -+ [...] -+ --- CUT HERE --- -+ -+>> FYI: << -+Multiple 'sshPublicKey' in a user entry are allowed, as well as multiple 'memberUid' attributes in a group entry -+ -+- COMPILING: -+ 1. Apply the patch -+ 2. ./configure --with-your-options --with-ldap=/prefix/to/ldap_libs_and_includes -+ 3. make -+ 4. it's done. -+ -+- BLA : -+ I hope this could help, and i hope to be clear enough,, or give ideas. questions/comments/improvements are welcome. -+ -+- TODO : -+ Redesign differently. -+ -+- DOCS/LINK : -+ http://pacsec.jp/core05/psj05-barisani-en.pdf -+ http://fritz.potsdam.edu/projects/openssh-lpk/ -+ http://fritz.potsdam.edu/projects/sshgate/ -+ http://dev.inversepath.com/trac/openssh-lpk -+ http://lam.sf.net/ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm ) -+ -+- CONTRIBUTORS/IDEAS/GREETS : -+ - Falk Siemonsmeier. -+ - Jacob Rief. -+ - Michael Durchgraf. -+ - frederic peters. -+ - Finlay dobbie. -+ - Stefan Fisher. -+ - Robin H. Johnson. -+ - Adrian Bridgett. -+ -+- CONTACT : -+ - Eric AUGE -+ - Andrea Barisani ---- auth-rsa.c.orig 2006-11-07 10:14:42.000000000 -0200 -+++ auth-rsa.c 2008-04-17 21:24:57.000000000 -0300 -@@ -175,10 +175,96 @@ - u_long linenum = 0; - struct stat st; - Key *key; -+#ifdef WITH_LDAP_PUBKEY -+ ldap_key_t * k; -+ unsigned int i = 0; -+#endif - - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); - -+#ifdef WITH_LDAP_PUBKEY -+ /* here is the job */ -+ key = key_new(KEY_RSA1); -+ -+ if (options.lpk.on) { -+ debug("[LDAP] trying LDAP first uid=%s", pw->pw_name); -+ if ( ldap_ismember(&options.lpk, pw->pw_name) > 0) { -+ if ( (k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) { -+ for (i = 0 ; i < k->num ; i++) { -+ char *cp, *options = NULL; -+ -+ for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++) -+ ; -+ if (!*cp || *cp == '\n' || *cp == '#') -+ continue; -+ -+ /* -+ * Check if there are options for this key, and if so, -+ * save their starting address and skip the option part -+ * for now. If there are no options, set the starting -+ * address to NULL. -+ */ -+ if (*cp < '0' || *cp > '9') { -+ int quoted = 0; -+ options = cp; -+ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { -+ if (*cp == '\\' && cp[1] == '"') -+ cp++; /* Skip both */ -+ else if (*cp == '"') -+ quoted = !quoted; -+ } -+ } else -+ options = NULL; -+ -+ /* Parse the key from the line. */ -+ if (hostfile_read_key(&cp, &bits, key) == 0) { -+ debug("[LDAP] line %d: non ssh1 key syntax", i); -+ continue; -+ } -+ /* cp now points to the comment part. */ -+ -+ /* Check if the we have found the desired key (identified by its modulus). */ -+ if (BN_cmp(key->rsa->n, client_n) != 0) -+ continue; -+ -+ /* check the real bits */ -+ if (bits != (unsigned int)BN_num_bits(key->rsa->n)) -+ logit("[LDAP] Warning: ldap, line %lu: keysize mismatch: " -+ "actual %d vs. announced %d.", (unsigned long)i, BN_num_bits(key->rsa->n), bits); -+ -+ /* We have found the desired key. */ -+ /* -+ * If our options do not allow this key to be used, -+ * do not send challenge. -+ */ -+ if (!auth_parse_options(pw, options, "[LDAP]", (unsigned long) i)) -+ continue; -+ -+ /* break out, this key is allowed */ -+ allowed = 1; -+ -+ /* add the return stuff etc... */ -+ /* Restore the privileged uid. */ -+ restore_uid(); -+ -+ /* return key if allowed */ -+ if (allowed && rkey != NULL) -+ *rkey = key; -+ else -+ key_free(key); -+ -+ ldap_keys_free(k); -+ return (allowed); -+ } -+ } else { -+ logit("[LDAP] no keys found for '%s'!", pw->pw_name); -+ } -+ } else { -+ logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup); -+ } -+ } -+#endif - /* The authorized keys. */ - file = authorized_keys_file(pw); - debug("trying public RSA key file %s", file); ---- auth2-pubkey.c.orig 2006-08-04 23:39:39.000000000 -0300 -+++ auth2-pubkey.c 2008-04-17 21:24:57.000000000 -0300 -@@ -53,6 +53,10 @@ - #include "monitor_wrap.h" - #include "misc.h" - -+#ifdef WITH_LDAP_PUBKEY -+#include "ldapauth.h" -+#endif -+ - /* import */ - extern ServerOptions options; - extern u_char *session_id2; -@@ -186,10 +190,79 @@ - struct stat st; - Key *found; - char *fp; -+#ifdef WITH_LDAP_PUBKEY -+ ldap_key_t * k; -+ unsigned int i = 0; -+#endif - - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); - -+#ifdef WITH_LDAP_PUBKEY -+ found_key = 0; -+ /* allocate a new key type */ -+ found = key_new(key->type); -+ -+ /* first check if the options is enabled, then try.. */ -+ if (options.lpk.on) { -+ debug("[LDAP] trying LDAP first uid=%s",pw->pw_name); -+ if (ldap_ismember(&options.lpk, pw->pw_name) > 0) { -+ if ((k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) { -+ /* Skip leading whitespace, empty and comment lines. */ -+ for (i = 0 ; i < k->num ; i++) { -+ /* dont forget if multiple keys to reset options */ -+ char *cp, *options = NULL; -+ -+ for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++) -+ ; -+ if (!*cp || *cp == '\n' || *cp == '#') -+ continue; -+ -+ if (key_read(found, &cp) != 1) { -+ /* no key? check if there are options for this key */ -+ int quoted = 0; -+ debug2("[LDAP] user_key_allowed: check options: '%s'", cp); -+ options = cp; -+ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { -+ if (*cp == '\\' && cp[1] == '"') -+ cp++; /* Skip both */ -+ else if (*cp == '"') -+ quoted = !quoted; -+ } -+ /* Skip remaining whitespace. */ -+ for (; *cp == ' ' || *cp == '\t'; cp++) -+ ; -+ if (key_read(found, &cp) != 1) { -+ debug2("[LDAP] user_key_allowed: advance: '%s'", cp); -+ /* still no key? advance to next line*/ -+ continue; -+ } -+ } -+ -+ if (key_equal(found, key) && -+ auth_parse_options(pw, options, file, linenum) == 1) { -+ found_key = 1; -+ debug("[LDAP] matching key found"); -+ fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); -+ verbose("[LDAP] Found matching %s key: %s", key_type(found), fp); -+ -+ /* restoring memory */ -+ ldap_keys_free(k); -+ xfree(fp); -+ restore_uid(); -+ key_free(found); -+ return found_key; -+ break; -+ } -+ }/* end of LDAP for() */ -+ } else { -+ logit("[LDAP] no keys found for '%s'!", pw->pw_name); -+ } -+ } else { -+ logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup); -+ } -+ } -+#endif - debug("trying public key file %s", file); - - /* Fail quietly if file does not exist */ ---- config.h.in.orig 2008-04-03 07:01:49.000000000 -0300 -+++ config.h.in 2008-04-17 21:24:57.000000000 -0300 -@@ -539,6 +539,9 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_IF_TUN_H - -+/* Define if you want LDAP support */ -+#undef WITH_LDAP_PUBKEY -+ - /* Define if your libraries define login() */ - #undef HAVE_LOGIN - ---- configure.ac.orig 2008-03-26 22:33:07.000000000 -0300 -+++ configure.ac 2008-04-17 21:24:57.000000000 -0300 -@@ -1285,6 +1285,37 @@ - esac ] - ) - -+# Check whether user wants LDAP support -+LDAP_MSG="no" -+AC_ARG_WITH(ldap, -+ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)], -+ [ -+ if test "x$withval" != "xno" ; then -+ -+ if test "x$withval" != "xyes" ; then -+ CPPFLAGS="$CPPFLAGS -I${withval}/include" -+ LDFLAGS="$LDFLAGS -L${withval}/lib" -+ fi -+ -+ AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support]) -+ LIBS="-lldap $LIBS" -+ LDAP_MSG="yes" -+ -+ AC_MSG_CHECKING([for LDAP support]) -+ AC_TRY_COMPILE( -+ [#include -+ #include ], -+ [(void)ldap_init(0, 0);], -+ [AC_MSG_RESULT(yes)], -+ [ -+ AC_MSG_RESULT(no) -+ AC_MSG_ERROR([** Incomplete or missing ldap libraries **]) -+ ] -+ ) -+ fi -+ ] -+) -+ - dnl Checks for library functions. Please keep in alphabetical order - AC_CHECK_FUNCS( \ - arc4random \ -@@ -4089,6 +4120,7 @@ - echo " Smartcard support: $SCARD_MSG" - echo " S/KEY support: $SKEY_MSG" - echo " TCP Wrappers support: $TCPW_MSG" -+echo " LDAP support: $LDAP_MSG" - echo " MD5 password support: $MD5_MSG" - echo " libedit support: $LIBEDIT_MSG" - echo " Solaris process contract support: $SPC_MSG" ---- configure.orig 2008-04-03 07:01:50.000000000 -0300 -+++ configure 2008-04-17 21:24:57.000000000 -0300 -@@ -1339,6 +1339,7 @@ - --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH) - --with-libedit[=PATH] Enable libedit support for sftp - --with-audit=module Enable EXPERIMENTAL audit support (modules=debug,bsm) -+ --with-ldap[=PATH] Enable LDAP pubkey support (optionally in PATH) - --with-ssl-dir=PATH Specify path to OpenSSL installation - --without-openssl-header-check Disable OpenSSL version consistency check - --with-ssl-engine Enable OpenSSL (hardware) ENGINE support -@@ -12514,6 +12515,85 @@ - fi - - -+# Check whether user wants LDAP support -+LDAP_MSG="no" -+ -+# Check whether --with-ldap was given. -+if test "${with_ldap+set}" = set; then -+ withval=$with_ldap; -+ if test "x$withval" != "xno" ; then -+ -+ if test "x$withval" != "xyes" ; then -+ CPPFLAGS="$CPPFLAGS -I${withval}/include" -+ LDFLAGS="$LDFLAGS -L${withval}/lib" -+ fi -+ -+ -+cat >>confdefs.h <<\_ACEOF -+#define WITH_LDAP_PUBKEY 1 -+_ACEOF -+ -+ LIBS="-lldap $LIBS" -+ LDAP_MSG="yes" -+ -+ { echo "$as_me:$LINENO: checking for LDAP support" >&5 -+echo $ECHO_N "checking for LDAP support... $ECHO_C" >&6; } -+ cat >conftest.$ac_ext <<_ACEOF -+/* confdefs.h. */ -+_ACEOF -+cat confdefs.h >>conftest.$ac_ext -+cat >>conftest.$ac_ext <<_ACEOF -+/* end confdefs.h. */ -+#include -+ #include -+int -+main () -+{ -+(void)ldap_init(0, 0); -+ ; -+ return 0; -+} -+_ACEOF -+rm -f conftest.$ac_objext -+if { (ac_try="$ac_compile" -+case "(($ac_try" in -+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; -+ *) ac_try_echo=$ac_try;; -+esac -+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 -+ (eval "$ac_compile") 2>conftest.er1 -+ ac_status=$? -+ grep -v '^ *+' conftest.er1 >conftest.err -+ rm -f conftest.er1 -+ cat conftest.err >&5 -+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 -+ (exit $ac_status); } && { -+ test -z "$ac_c_werror_flag" || -+ test ! -s conftest.err -+ } && test -s conftest.$ac_objext; then -+ { echo "$as_me:$LINENO: result: yes" >&5 -+echo "${ECHO_T}yes" >&6; } -+else -+ echo "$as_me: failed program was:" >&5 -+sed 's/^/| /' conftest.$ac_ext >&5 -+ -+ -+ { echo "$as_me:$LINENO: result: no" >&5 -+echo "${ECHO_T}no" >&6; } -+ { { echo "$as_me:$LINENO: error: ** Incomplete or missing ldap libraries **" >&5 -+echo "$as_me: error: ** Incomplete or missing ldap libraries **" >&2;} -+ { (exit 1); exit 1; }; } -+ -+ -+fi -+ -+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -+ fi -+ -+ -+fi -+ -+ - - - -@@ -29860,6 +29940,7 @@ - echo " Smartcard support: $SCARD_MSG" - echo " S/KEY support: $SKEY_MSG" - echo " TCP Wrappers support: $TCPW_MSG" -+echo " LDAP support: $LDAP_MSG" - echo " MD5 password support: $MD5_MSG" - echo " libedit support: $LIBEDIT_MSG" - echo " Solaris process contract support: $SPC_MSG" ---- ldapauth.c.orig 2008-04-17 21:24:57.000000000 -0300 -+++ ldapauth.c 2008-04-17 21:24:57.000000000 -0300 -@@ -0,0 +1,575 @@ -+/* -+ * $Id: openssh-lpk-5.0p1-0.3.9.patch,v 1.2 2009/05/15 11:00:27 pav Exp $ -+ */ -+ -+/* -+ * -+ * Copyright (c) 2005, Eric AUGE -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -+ * -+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -+ * 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. -+ * Neither the name of the phear.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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" -+ -+#ifdef WITH_LDAP_PUBKEY -+ -+#include -+#include -+#include -+#include -+ -+#include "ldapauth.h" -+#include "log.h" -+ -+static char *attrs[] = { -+ PUBKEYATTR, -+ NULL -+}; -+ -+/* filter building infos */ -+#define FILTER_GROUP_PREFIX "(&(objectclass=posixGroup)" -+#define FILTER_OR_PREFIX "(|" -+#define FILTER_OR_SUFFIX ")" -+#define FILTER_CN_PREFIX "(cn=" -+#define FILTER_CN_SUFFIX ")" -+#define FILTER_UID_FORMAT "(memberUid=%s)" -+#define FILTER_GROUP_SUFFIX ")" -+#define FILTER_GROUP_SIZE(group) (size_t) (strlen(group)+(ldap_count_group(group)*5)+52) -+ -+/* just filter building stuff */ -+#define REQUEST_GROUP_SIZE(filter, uid) (size_t) (strlen(filter)+strlen(uid)+1) -+#define REQUEST_GROUP(buffer, prefilter, pwname) \ -+ buffer = (char *) calloc(REQUEST_GROUP_SIZE(prefilter, pwname), sizeof(char)); \ -+ if (!buffer) { \ -+ perror("calloc()"); \ -+ return FAILURE; \ -+ } \ -+ snprintf(buffer, REQUEST_GROUP_SIZE(prefilter,pwname), prefilter, pwname) -+/* -+XXX OLD group building macros -+#define REQUEST_GROUP_SIZE(grp, uid) (size_t) (strlen(grp)+strlen(uid)+46) -+#define REQUEST_GROUP(buffer,pwname,grp) \ -+ buffer = (char *) calloc(REQUEST_GROUP_SIZE(grp, pwname), sizeof(char)); \ -+ if (!buffer) { \ -+ perror("calloc()"); \ -+ return FAILURE; \ -+ } \ -+ snprintf(buffer,REQUEST_GROUP_SIZE(grp,pwname),"(&(objectclass=posixGroup)(cn=%s)(memberUid=%s))",grp,pwname) -+ */ -+ -+/* -+XXX stock upstream version without extra filter support -+#define REQUEST_USER_SIZE(uid) (size_t) (strlen(uid)+64) -+#define REQUEST_USER(buffer, pwname) \ -+ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname), sizeof(char)); \ -+ if (!buffer) { \ -+ perror("calloc()"); \ -+ return NULL; \ -+ } \ -+ snprintf(buffer,REQUEST_USER_SIZE(pwname),"(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s))",pwname) -+ */ -+ -+#define REQUEST_USER_SIZE(uid, filter) (size_t) (strlen(uid)+64+(filter != NULL ? strlen(filter) : 0)) -+#define REQUEST_USER(buffer, pwname, customfilter) \ -+ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname, customfilter), sizeof(char)); \ -+ if (!buffer) { \ -+ perror("calloc()"); \ -+ return NULL; \ -+ } \ -+ snprintf(buffer, REQUEST_USER_SIZE(pwname, customfilter), \ -+ "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)", \ -+ pwname, (customfilter != NULL ? customfilter : "")) -+ -+/* some portable and working tokenizer, lame though */ -+static int tokenize(char ** o, size_t size, char * input) { -+ unsigned int i = 0, num; -+ const char * charset = " \t"; -+ char * ptr = input; -+ -+ /* leading white spaces are ignored */ -+ num = strspn(ptr, charset); -+ ptr += num; -+ -+ while ((num = strcspn(ptr, charset))) { -+ if (i < size-1) { -+ o[i++] = ptr; -+ ptr += num; -+ if (*ptr) -+ *ptr++ = '\0'; -+ } -+ } -+ o[i] = NULL; -+ return SUCCESS; -+} -+ -+void ldap_close(ldap_opt_t * ldap) { -+ -+ if (!ldap) -+ return; -+ -+ if ( ldap_unbind_ext(ldap->ld, NULL, NULL) < 0) -+ ldap_perror(ldap->ld, "ldap_unbind()"); -+ -+ ldap->ld = NULL; -+ FLAG_SET_DISCONNECTED(ldap->flags); -+ -+ return; -+} -+ -+/* init && bind */ -+int ldap_connect(ldap_opt_t * ldap) { -+ int version = LDAP_VERSION3; -+ -+ if (!ldap->servers) -+ return FAILURE; -+ -+ /* Connection Init and setup */ -+ ldap->ld = ldap_init(ldap->servers, LDAP_PORT); -+ if (!ldap->ld) { -+ ldap_perror(ldap->ld, "ldap_init()"); -+ return FAILURE; -+ } -+ -+ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) { -+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)"); -+ return FAILURE; -+ } -+ -+ /* Timeouts setup */ -+ if (ldap_set_option(ldap->ld, LDAP_OPT_NETWORK_TIMEOUT, &ldap->b_timeout) != LDAP_SUCCESS) { -+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT)"); -+ } -+ if (ldap_set_option(ldap->ld, LDAP_OPT_TIMEOUT, &ldap->s_timeout) != LDAP_SUCCESS) { -+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_TIMEOUT)"); -+ } -+ -+ /* TLS support */ -+ if ( (ldap->tls == -1) || (ldap->tls == 1) ) { -+ if (ldap_start_tls_s(ldap->ld, NULL, NULL ) != LDAP_SUCCESS) { -+ /* failed then reinit the initial connect */ -+ ldap_perror(ldap->ld, "ldap_connect: (TLS) ldap_start_tls()"); -+ if (ldap->tls == 1) -+ return FAILURE; -+ -+ ldap->ld = ldap_init(ldap->servers, LDAP_PORT); -+ if (!ldap->ld) { -+ ldap_perror(ldap->ld, "ldap_init()"); -+ return FAILURE; -+ } -+ -+ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) { -+ ldap_perror(ldap->ld, "ldap_set_option()"); -+ return FAILURE; -+ } -+ } -+ } -+ -+ -+ if ( ldap_simple_bind_s(ldap->ld, ldap->binddn, ldap->bindpw) != LDAP_SUCCESS) { -+ ldap_perror(ldap->ld, "ldap_simple_bind_s()"); -+ return FAILURE; -+ } -+ -+ /* says it is connected */ -+ FLAG_SET_CONNECTED(ldap->flags); -+ -+ return SUCCESS; -+} -+ -+/* must free allocated ressource */ -+static char * ldap_build_host(char *host, int port) { -+ unsigned int size = strlen(host)+11; -+ char * h = (char *) calloc (size, sizeof(char)); -+ int rc; -+ if (!h) -+ return NULL; -+ -+ rc = snprintf(h, size, "%s:%d ", host, port); -+ if (rc == -1) -+ return NULL; -+ return h; -+} -+ -+static int ldap_count_group(const char * input) { -+ const char * charset = " \t"; -+ const char * ptr = input; -+ unsigned int count = 0; -+ unsigned int num; -+ -+ num = strspn(ptr, charset); -+ ptr += num; -+ -+ while ((num = strcspn(ptr, charset))) { -+ count++; -+ ptr += num; -+ ptr++; -+ } -+ -+ return count; -+} -+ -+/* format filter */ -+char * ldap_parse_groups(const char * groups) { -+ unsigned int buffer_size = FILTER_GROUP_SIZE(groups); -+ char * buffer = (char *) calloc(buffer_size, sizeof(char)); -+ char * g = NULL; -+ char * garray[32]; -+ unsigned int i = 0; -+ -+ if ((!groups)||(!buffer)) -+ return NULL; -+ -+ g = strdup(groups); -+ if (!g) { -+ free(buffer); -+ return NULL; -+ } -+ -+ /* first separate into n tokens */ -+ if ( tokenize(garray, sizeof(garray)/sizeof(*garray), g) < 0) { -+ free(g); -+ free(buffer); -+ return NULL; -+ } -+ -+ /* build the final filter format */ -+ strlcat(buffer, FILTER_GROUP_PREFIX, buffer_size); -+ strlcat(buffer, FILTER_OR_PREFIX, buffer_size); -+ i = 0; -+ while (garray[i]) { -+ strlcat(buffer, FILTER_CN_PREFIX, buffer_size); -+ strlcat(buffer, garray[i], buffer_size); -+ strlcat(buffer, FILTER_CN_SUFFIX, buffer_size); -+ i++; -+ } -+ strlcat(buffer, FILTER_OR_SUFFIX, buffer_size); -+ strlcat(buffer, FILTER_UID_FORMAT, buffer_size); -+ strlcat(buffer, FILTER_GROUP_SUFFIX, buffer_size); -+ -+ free(g); -+ return buffer; -+} -+ -+/* a bit dirty but leak free */ -+char * ldap_parse_servers(const char * servers) { -+ char * s = NULL; -+ char * tmp = NULL, *urls[32]; -+ unsigned int num = 0 , i = 0 , asize = 0; -+ LDAPURLDesc *urld[32]; -+ -+ if (!servers) -+ return NULL; -+ -+ /* local copy of the arg */ -+ s = strdup(servers); -+ if (!s) -+ return NULL; -+ -+ /* first separate into URL tokens */ -+ if ( tokenize(urls, sizeof(urls)/sizeof(*urls), s) < 0) -+ return NULL; -+ -+ i = 0; -+ while (urls[i]) { -+ if (! ldap_is_ldap_url(urls[i]) || -+ (ldap_url_parse(urls[i], &urld[i]) != 0)) { -+ return NULL; -+ } -+ i++; -+ } -+ -+ /* now free(s) */ -+ free (s); -+ -+ /* how much memory do we need */ -+ num = i; -+ for (i = 0 ; i < num ; i++) -+ asize += strlen(urld[i]->lud_host)+11; -+ -+ /* alloc */ -+ s = (char *) calloc( asize+1 , sizeof(char)); -+ if (!s) { -+ for (i = 0 ; i < num ; i++) -+ ldap_free_urldesc(urld[i]); -+ return NULL; -+ } -+ -+ /* then build the final host string */ -+ for (i = 0 ; i < num ; i++) { -+ /* built host part */ -+ tmp = ldap_build_host(urld[i]->lud_host, urld[i]->lud_port); -+ strncat(s, tmp, strlen(tmp)); -+ ldap_free_urldesc(urld[i]); -+ free(tmp); -+ } -+ -+ return s; -+} -+ -+void ldap_options_print(ldap_opt_t * ldap) { -+ debug("ldap options:"); -+ debug("servers: %s", ldap->servers); -+ if (ldap->u_basedn) -+ debug("user basedn: %s", ldap->u_basedn); -+ if (ldap->g_basedn) -+ debug("group basedn: %s", ldap->g_basedn); -+ if (ldap->binddn) -+ debug("binddn: %s", ldap->binddn); -+ if (ldap->bindpw) -+ debug("bindpw: %s", ldap->bindpw); -+ if (ldap->sgroup) -+ debug("group: %s", ldap->sgroup); -+ if (ldap->filter) -+ debug("filter: %s", ldap->filter); -+} -+ -+void ldap_options_free(ldap_opt_t * l) { -+ if (!l) -+ return; -+ if (l->servers) -+ free(l->servers); -+ if (l->u_basedn) -+ free(l->u_basedn); -+ if (l->g_basedn) -+ free(l->g_basedn); -+ if (l->binddn) -+ free(l->binddn); -+ if (l->bindpw) -+ free(l->bindpw); -+ if (l->sgroup) -+ free(l->sgroup); -+ if (l->fgroup) -+ free(l->fgroup); -+ if (l->filter) -+ free(l->filter); -+ if (l->l_conf) -+ free(l->l_conf); -+ free(l); -+} -+ -+/* free keys */ -+void ldap_keys_free(ldap_key_t * k) { -+ ldap_value_free_len(k->keys); -+ free(k); -+ return; -+} -+ -+ldap_key_t * ldap_getuserkey(ldap_opt_t *l, const char * user) { -+ ldap_key_t * k = (ldap_key_t *) calloc (1, sizeof(ldap_key_t)); -+ LDAPMessage *res, *e; -+ char * filter; -+ int i; -+ -+ if ((!k) || (!l)) -+ return NULL; -+ -+ /* Am i still connected ? RETRY n times */ -+ /* XXX TODO: setup some conf value for retrying */ -+ if (!(l->flags & FLAG_CONNECTED)) -+ for (i = 0 ; i < 2 ; i++) -+ if (ldap_connect(l) == 0) -+ break; -+ -+ /* quick check for attempts to be evil */ -+ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || -+ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) -+ return NULL; -+ -+ /* build filter for LDAP request */ -+ REQUEST_USER(filter, user, l->filter); -+ -+ if ( ldap_search_st( l->ld, -+ l->u_basedn, -+ LDAP_SCOPE_SUBTREE, -+ filter, -+ attrs, 0, &l->s_timeout, &res ) != LDAP_SUCCESS) { -+ -+ ldap_perror(l->ld, "ldap_search_st()"); -+ -+ free(filter); -+ free(k); -+ -+ /* XXX error on search, timeout etc.. close ask for reconnect */ -+ ldap_close(l); -+ -+ return NULL; -+ } -+ -+ /* free */ -+ free(filter); -+ -+ /* check if any results */ -+ i = ldap_count_entries(l->ld,res); -+ if (i <= 0) { -+ ldap_msgfree(res); -+ free(k); -+ return NULL; -+ } -+ -+ if (i > 1) -+ debug("[LDAP] duplicate entries, using the FIRST entry returned"); -+ -+ e = ldap_first_entry(l->ld, res); -+ k->keys = ldap_get_values_len(l->ld, e, PUBKEYATTR); -+ k->num = ldap_count_values_len(k->keys); -+ -+ ldap_msgfree(res); -+ return k; -+} -+ -+ -+/* -1 if trouble -+ 0 if user is NOT member of current server group -+ 1 if user IS MEMBER of current server group -+ */ -+int ldap_ismember(ldap_opt_t * l, const char * user) { -+ LDAPMessage *res; -+ char * filter; -+ int i; -+ -+ if ((!l->sgroup) || !(l->g_basedn)) -+ return 1; -+ -+ /* Am i still connected ? RETRY n times */ -+ /* XXX TODO: setup some conf value for retrying */ -+ if (!(l->flags & FLAG_CONNECTED)) -+ for (i = 0 ; i < 2 ; i++) -+ if (ldap_connect(l) == 0) -+ break; -+ -+ /* quick check for attempts to be evil */ -+ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || -+ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) -+ return FAILURE; -+ -+ /* build filter for LDAP request */ -+ REQUEST_GROUP(filter, l->fgroup, user); -+ -+ if (ldap_search_st( l->ld, -+ l->g_basedn, -+ LDAP_SCOPE_SUBTREE, -+ filter, -+ NULL, 0, &l->s_timeout, &res) != LDAP_SUCCESS) { -+ -+ ldap_perror(l->ld, "ldap_search_st()"); -+ -+ free(filter); -+ -+ /* XXX error on search, timeout etc.. close ask for reconnect */ -+ ldap_close(l); -+ -+ return FAILURE; -+ } -+ -+ free(filter); -+ -+ /* check if any results */ -+ if (ldap_count_entries(l->ld, res) > 0) { -+ ldap_msgfree(res); -+ return 1; -+ } -+ -+ ldap_msgfree(res); -+ return 0; -+} -+ -+/* -+ * ldap.conf simple parser -+ * XXX TODO: sanity checks -+ * must either -+ * - free the previous ldap_opt_before replacing entries -+ * - free each necessary previously parsed elements -+ * ret: -+ * -1 on FAILURE, 0 on SUCCESS -+ */ -+int ldap_parse_lconf(ldap_opt_t * l) { -+ FILE * lcd; /* ldap.conf descriptor */ -+ char buf[BUFSIZ]; -+ char * s = NULL, * k = NULL, * v = NULL; -+ int li, len; -+ -+ lcd = fopen (l->l_conf, "r"); -+ if (lcd == NULL) { -+ /* debug("Cannot open %s", l->l_conf); */ -+ perror("ldap_parse_lconf()"); -+ return FAILURE; -+ } -+ -+ while (fgets (buf, sizeof (buf), lcd) != NULL) { -+ -+ if (*buf == '\n' || *buf == '#') -+ continue; -+ -+ k = buf; -+ v = k; -+ while (*v != '\0' && *v != ' ' && *v != '\t') -+ v++; -+ -+ if (*v == '\0') -+ continue; -+ -+ *(v++) = '\0'; -+ -+ while (*v == ' ' || *v == '\t') -+ v++; -+ -+ li = strlen (v) - 1; -+ while (v[li] == ' ' || v[li] == '\t' || v[li] == '\n') -+ --li; -+ v[li + 1] = '\0'; -+ -+ if (!strcasecmp (k, "uri")) { -+ if ((l->servers = ldap_parse_servers(v)) == NULL) { -+ fatal("error in ldap servers"); -+ return FAILURE; -+ } -+ -+ } -+ else if (!strcasecmp (k, "base")) { -+ s = strchr (v, '?'); -+ if (s != NULL) { -+ len = s - v; -+ l->u_basedn = malloc (len + 1); -+ strncpy (l->u_basedn, v, len); -+ l->u_basedn[len] = '\0'; -+ } else { -+ l->u_basedn = strdup (v); -+ } -+ } -+ else if (!strcasecmp (k, "binddn")) { -+ l->binddn = strdup (v); -+ } -+ else if (!strcasecmp (k, "bindpw")) { -+ l->bindpw = strdup (v); -+ } -+ else if (!strcasecmp (k, "timelimit")) { -+ l->s_timeout.tv_sec = atoi (v); -+ } -+ else if (!strcasecmp (k, "bind_timelimit")) { -+ l->b_timeout.tv_sec = atoi (v); -+ } -+ else if (!strcasecmp (k, "ssl")) { -+ if (!strcasecmp (v, "start_tls")) -+ l->tls = 1; -+ } -+ } -+ -+ fclose (lcd); -+ return SUCCESS; -+} -+ -+#endif /* WITH_LDAP_PUBKEY */ ---- ldapauth.h.orig 2008-04-17 21:24:57.000000000 -0300 -+++ ldapauth.h 2008-04-17 21:24:57.000000000 -0300 -@@ -0,0 +1,124 @@ -+/* -+ * $Id: openssh-lpk-5.0p1-0.3.9.patch,v 1.2 2009/05/15 11:00:27 pav Exp $ -+ */ -+ -+/* -+ * -+ * Copyright (c) 2005, Eric AUGE -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -+ * -+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -+ * 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. -+ * Neither the name of the phear.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 LDAPAUTH_H -+#define LDAPAUTH_H -+ -+#define LDAP_DEPRECATED 1 -+ -+#include -+#include -+#include -+#include -+ -+/* tokens in use for config */ -+#define _DEFAULT_LPK_TOKEN "UseLPK" -+#define _DEFAULT_SRV_TOKEN "LpkServers" -+#define _DEFAULT_USR_TOKEN "LpkUserDN" -+#define _DEFAULT_GRP_TOKEN "LpkGroupDN" -+#define _DEFAULT_BDN_TOKEN "LpkBindDN" -+#define _DEFAULT_BPW_TOKEN "LpkBindPw" -+#define _DEFAULT_MYG_TOKEN "LpkServerGroup" -+#define _DEFAULT_FIL_TOKEN "LpkFilter" -+#define _DEFAULT_TLS_TOKEN "LpkForceTLS" -+#define _DEFAULT_BTI_TOKEN "LpkBindTimelimit" -+#define _DEFAULT_STI_TOKEN "LpkSearchTimelimit" -+#define _DEFAULT_LDP_TOKEN "LpkLdapConf" -+ -+/* default options */ -+#define _DEFAULT_LPK_ON 0 -+#define _DEFAULT_LPK_SERVERS NULL -+#define _DEFAULT_LPK_UDN NULL -+#define _DEFAULT_LPK_GDN NULL -+#define _DEFAULT_LPK_BINDDN NULL -+#define _DEFAULT_LPK_BINDPW NULL -+#define _DEFAULT_LPK_SGROUP NULL -+#define _DEFAULT_LPK_FILTER NULL -+#define _DEFAULT_LPK_TLS -1 -+#define _DEFAULT_LPK_BTIMEOUT 10 -+#define _DEFAULT_LPK_STIMEOUT 10 -+#define _DEFAULT_LPK_LDP NULL -+ -+/* flags */ -+#define FLAG_EMPTY 0x00000000 -+#define FLAG_CONNECTED 0x00000001 -+ -+/* flag macros */ -+#define FLAG_SET_EMPTY(x) x&=(FLAG_EMPTY) -+#define FLAG_SET_CONNECTED(x) x|=(FLAG_CONNECTED) -+#define FLAG_SET_DISCONNECTED(x) x&=~(FLAG_CONNECTED) -+ -+/* defines */ -+#define FAILURE -1 -+#define SUCCESS 0 -+#define PUBKEYATTR "sshPublicKey" -+ -+/* -+ * -+ * defined files path -+ * (should be relocated to pathnames.h, -+ * if one day it's included within the tree) -+ * -+ */ -+#define _PATH_LDAP_CONFIG_FILE "/etc/ldap.conf" -+ -+/* structures */ -+typedef struct ldap_options { -+ int on; /* Use it or NOT */ -+ LDAP * ld; /* LDAP file desc */ -+ char * servers; /* parsed servers for ldaplib failover handling */ -+ char * u_basedn; /* user basedn */ -+ char * g_basedn; /* group basedn */ -+ char * binddn; /* binddn */ -+ char * bindpw; /* bind password */ -+ char * sgroup; /* server group */ -+ char * fgroup; /* group filter */ -+ char * filter; /* additional filter */ -+ char * l_conf; /* use ldap.conf */ -+ int tls; /* TLS only */ -+ struct timeval b_timeout; /* bind timeout */ -+ struct timeval s_timeout; /* search timeout */ -+ unsigned int flags; /* misc flags (reconnection, future use?) */ -+} ldap_opt_t; -+ -+typedef struct ldap_keys { -+ struct berval ** keys; /* the public keys retrieved */ -+ unsigned int num; /* number of keys */ -+} ldap_key_t; -+ -+ -+/* function headers */ -+void ldap_close(ldap_opt_t *); -+int ldap_connect(ldap_opt_t *); -+char * ldap_parse_groups(const char *); -+char * ldap_parse_servers(const char *); -+void ldap_options_print(ldap_opt_t *); -+void ldap_options_free(ldap_opt_t *); -+void ldap_keys_free(ldap_key_t *); -+int ldap_parse_lconf(ldap_opt_t *); -+ldap_key_t * ldap_getuserkey(ldap_opt_t *, const char *); -+int ldap_ismember(ldap_opt_t *, const char *); -+ -+#endif ---- lpk-user-example.txt.orig 2008-04-17 21:24:57.000000000 -0300 -+++ lpk-user-example.txt 2008-04-17 21:24:57.000000000 -0300 -@@ -0,0 +1,117 @@ -+ -+Post to ML -> User Made Quick Install Doc. -+Contribution from John Lane -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ -+OpenSSH LDAP keystore Patch -+=========================== -+ -+NOTE: these notes are a transcript of a specific installation -+ they work for me, your specifics may be different! -+ from John Lane March 17th 2005 john@lane.uk.net -+ -+This is a patch to OpenSSH 4.0p1 to allow it to obtain users' public keys -+from their LDAP record as an alternative to ~/.ssh/authorized_keys. -+ -+(Assuming here that necessary build stuff is in $BUILD) -+ -+cd $BUILD/openssh-4.0p1 -+patch -Np1 -i $BUILD/openssh-lpk-4.0p1-0.3.patch -+mkdir -p /var/empty && -+./configure --prefix=/usr --sysconfdir=/etc/ssh \ -+ --libexecdir=/usr/sbin --with-md5-passwords --with-pam \ -+ --with-libs="-lldap" --with-cppflags="-DWITH_LDAP_PUBKEY" -+Now do. -+make && -+make install -+ -+Add the following config to /etc/ssh/ssh_config -+UseLPK yes -+LpkServers ldap://myhost.mydomain.com -+LpkUserDN ou=People,dc=mydomain,dc=com -+ -+We need to tell sshd about the SSL keys during boot, as root's -+environment does not exist at that time. Edit /etc/rc.d/init.d/sshd. -+Change the startup code from this: -+ echo "Starting SSH Server..." -+ loadproc /usr/sbin/sshd -+ ;; -+to this: -+ echo "Starting SSH Server..." -+ LDAPRC="/root/.ldaprc" loadproc /usr/sbin/sshd -+ ;; -+ -+Re-start the sshd daemon: -+/etc/rc.d/init.d/sshd restart -+ -+Install the additional LDAP schema -+cp $BUILD/openssh-lpk-0.2.schema /etc/openldap/schema/openssh.schema -+ -+Now add the openSSH LDAP schema to /etc/openldap/slapd.conf: -+Add the following to the end of the existing block of schema includes -+include /etc/openldap/schema/openssh.schema -+ -+Re-start the LDAP server: -+/etc/rc.d/init.d/slapd restart -+ -+To add one or more public keys to a user, eg "testuser" : -+ldapsearch -x -W -Z -LLL -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D -+"uid=testuser,ou=People,dc=mydomain,dc=com" > /tmp/testuser -+ -+append the following to this /tmp/testuser file -+objectclass: ldapPublicKey -+sshPublicKey: ssh-rsa -+AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KS -+qIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z8XwSsuAoR1t86t+5dlI -+7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key -+ -+Then do a modify: -+ldapmodify -x -D "uid=testuser,ou=People,dc=mydomain,dc=com" -W -f -+/tmp/testuser -Z -+Enter LDAP Password: -+modifying entry "uid=testuser,ou=People,dc=mydomain,dc=com" -+And check the modify is ok: -+ldapsearch -x -W -Z -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D -+"uid=testuser,ou=People,dc=mydomain,dc=com" -+Enter LDAP Password: -+# extended LDIF -+# -+# LDAPv3 -+# base with scope sub -+# filter: (objectclass=*) -+# requesting: ALL -+# -+ -+# testuser, People, mydomain.com -+dn: uid=testuser,ou=People,dc=mydomain,dc=com -+uid: testuser -+cn: testuser -+objectClass: account -+objectClass: posixAccount -+objectClass: top -+objectClass: shadowAccount -+objectClass: ldapPublicKey -+shadowLastChange: 12757 -+shadowMax: 99999 -+shadowWarning: 7 -+loginShell: /bin/bash -+uidNumber: 9999 -+gidNumber: 501 -+homeDirectory: /home/testuser -+userPassword:: e1NTSEF9UDgwV1hnM1VjUDRJK0k1YnFiL1d4ZUJObXlZZ3Z3UTU= -+sshPublicKey: ssh-rsa -+AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KSqIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z -+8XwSsuAoR1t86t+5dlI7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key -+ -+# search result -+search: 3 -+result: 0 Success -+ -+# numResponses: 2 -+# numEntries: 1 -+ -+Now start a ssh session to user "testuser" from usual ssh client (e.g. -+puTTY). Login should succeed. -+ -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ---- openssh-lpk_openldap.schema.orig 2008-04-17 21:24:57.000000000 -0300 -+++ openssh-lpk_openldap.schema 2008-04-17 21:24:57.000000000 -0300 -@@ -0,0 +1,19 @@ -+# -+# LDAP Public Key Patch schema for use with openssh-ldappubkey -+# Author: Eric AUGE -+# -+# Based on the proposal of : Mark Ruijter -+# -+ -+ -+# octetString SYNTAX -+attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' -+ DESC 'MANDATORY: OpenSSH Public key' -+ EQUALITY octetStringMatch -+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) -+ -+# printableString SYNTAX yes|no -+objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY -+ DESC 'MANDATORY: OpenSSH LPK objectclass' -+ MUST ( sshPublicKey $ uid ) -+ ) ---- openssh-lpk_sun.schema.orig 2008-04-17 21:24:57.000000000 -0300 -+++ openssh-lpk_sun.schema 2008-04-17 21:24:57.000000000 -0300 -@@ -0,0 +1,21 @@ -+# -+# LDAP Public Key Patch schema for use with openssh-ldappubkey -+# Author: Eric AUGE -+# -+# Schema for Sun Directory Server. -+# Based on the original schema, modified by Stefan Fischer. -+# -+ -+dn: cn=schema -+ -+# octetString SYNTAX -+attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' -+ DESC 'MANDATORY: OpenSSH Public key' -+ EQUALITY octetStringMatch -+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) -+ -+# printableString SYNTAX yes|no -+objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY -+ DESC 'MANDATORY: OpenSSH LPK objectclass' -+ MUST ( sshPublicKey $ uid ) -+ ) ---- sshd.c.orig 2008-03-11 08:58:25.000000000 -0300 -+++ sshd.c 2008-04-17 21:24:57.000000000 -0300 -@@ -126,6 +126,10 @@ - int deny_severity; - #endif /* LIBWRAP */ - -+#ifdef WITH_LDAP_PUBKEY -+#include "ldapauth.h" -+#endif -+ - #ifndef O_NOCTTY - #define O_NOCTTY 0 - #endif -@@ -1454,6 +1458,16 @@ - exit(1); - } - -+#ifdef WITH_LDAP_PUBKEY -+ /* ldap_options_print(&options.lpk); */ -+ /* XXX initialize/check ldap connection and set *LD */ -+ if (options.lpk.on) { -+ if (options.lpk.l_conf && (ldap_parse_lconf(&options.lpk) < 0) ) -+ error("[LDAP] could not parse %s", options.lpk.l_conf); -+ if (ldap_connect(&options.lpk) < 0) -+ error("[LDAP] could not initialize ldap connection"); -+ } -+#endif - debug("sshd version %.100s", SSH_RELEASE); - - /* Store privilege separation user for later use if required. */ ---- sshd_config.5.orig 2008-03-26 21:02:02.000000000 -0300 -+++ sshd_config.5 2008-04-17 21:24:57.000000000 -0300 -@@ -964,6 +964,62 @@ - program. - The default is - .Pa /usr/X11R6/bin/xauth . -+.It Cm UseLPK -+Specifies whether LDAP public key retrieval must be used or not. It allow -+an easy centralisation of public keys within an LDAP directory. The argument must be -+.Dq yes -+or -+.Dq no . -+.It Cm LpkLdapConf -+Specifies whether LDAP Public keys should parse the specified ldap.conf file -+instead of sshd_config Tokens. The argument must be a valid path to an ldap.conf -+file like -+.Pa /etc/ldap.conf -+.It Cm LpkServers -+Specifies LDAP one or more [:space:] separated server's url the following form may be used: -+.Pp -+LpkServers ldaps://127.0.0.1 ldap://127.0.0.2 ldap://127.0.0.3 -+.It Cm LpkUserDN -+Specifies the LDAP user DN. -+.Pp -+LpkUserDN ou=users,dc=phear,dc=org -+.It Cm LpkGroupDN -+Specifies the LDAP groups DN. -+.Pp -+LpkGroupDN ou=groups,dc=phear,dc=org -+.It Cm LpkBindDN -+Specifies the LDAP bind DN to use if necessary. -+.Pp -+LpkBindDN cn=Manager,dc=phear,dc=org -+.It Cm LpkBindPw -+Specifies the LDAP bind credential. -+.Pp -+LpkBindPw secret -+.It Cm LpkServerGroup -+Specifies one or more [:space:] separated group the server is part of. -+.Pp -+LpkServerGroup unix mail prod -+.It Cm LpkFilter -+Specifies an additional LDAP filter to use for finding SSH keys -+.Pp -+LpkFilter (hostAccess=master.phear.org) -+.It Cm LpkForceTLS -+Specifies if the LDAP server connection must be tried, forced or not used. The argument must be -+.Dq yes -+or -+.Dq no -+or -+.Dq try . -+.It Cm LpkSearchTimelimit -+Sepcifies the search time limit before the search is considered over. value is -+in seconds. -+.Pp -+LpkSearchTimelimit 3 -+.It Cm LpkBindTimelimit -+Sepcifies the bind time limit before the connection is considered dead. value is -+in seconds. -+.Pp -+LpkBindTimelimit 3 - .El - .Sh TIME FORMATS - .Xr sshd 8 ---- sshd_config.orig 2008-02-10 09:40:12.000000000 -0200 -+++ sshd_config 2008-04-17 21:28:29.000000000 -0300 -@@ -107,6 +107,21 @@ - # no default banner path - #Banner none - -+# here are the new patched ldap related tokens -+# entries in your LDAP must have posixAccount & ldapPublicKey objectclass -+#UseLPK yes -+#LpkLdapConf /etc/ldap.conf -+#LpkServers ldap://10.1.7.1/ ldap://10.1.7.2/ -+#LpkUserDN ou=users,dc=phear,dc=org -+#LpkGroupDN ou=groups,dc=phear,dc=org -+#LpkBindDN cn=Manager,dc=phear,dc=org -+#LpkBindPw secret -+#LpkServerGroup mail -+#LpkFilter (hostAccess=master.phear.org) -+#LpkForceTLS no -+#LpkSearchTimelimit 3 -+#LpkBindTimelimit 3 -+ - # override default of no subsystems - Subsystem sftp /usr/libexec/sftp-server - ---- servconf.h.orig 2008-03-07 04:31:24.000000000 -0300 -+++ servconf.h 2008-04-17 21:24:57.000000000 -0300 -@@ -16,6 +16,10 @@ - #ifndef SERVCONF_H - #define SERVCONF_H - -+#ifdef WITH_LDAP_PUBKEY -+#include "ldapauth.h" -+#endif -+ - #define MAX_PORTS 256 /* Max # ports. */ - - #define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ -@@ -142,6 +146,9 @@ - int use_pam; /* Enable auth via PAM */ - - int permit_tun; -+#ifdef WITH_LDAP_PUBKEY -+ ldap_opt_t lpk; -+#endif - - int num_permitted_opens; - diff -ruN --exclude=CVS /usr/ports/security/openssh-portable/files/openssh-lpk-5.0p1-64bit.patch /usr/home/dindin/workspace/openssh-portable/files/openssh-lpk-5.0p1-64bit.patch --- /usr/ports/security/openssh-portable/files/openssh-lpk-5.0p1-64bit.patch 2009-03-24 20:33:41.000000000 +0300 +++ /usr/home/dindin/workspace/openssh-portable/files/openssh-lpk-5.0p1-64bit.patch 1970-01-01 03:00:00.000000000 +0300 @@ -1,44 +0,0 @@ -diff -Nuar --exclude '*.rej' servconf.c.orig servconf.c ---- servconf.c.orig 2008-08-23 15:02:47.000000000 -0700 -+++ servconf.c 2008-08-23 15:04:21.000000000 -0700 -@@ -701,6 +701,7 @@ - int cmdline = 0, *intptr, value, n; - SyslogFacility *log_facility_ptr; - LogLevel *log_level_ptr; -+ unsigned long lvalue, *longptr; - ServerOpCodes opcode; - u_short port; - u_int i, flags = 0; -@@ -715,6 +716,7 @@ - if (!arg || !*arg || *arg == '#') - return 0; - intptr = NULL; -+ longptr = NULL; - charptr = NULL; - opcode = parse_token(arg, filename, linenum, &flags); - -@@ -1449,11 +1451,20 @@ - *intptr = value; - break; - case sBindTimeout: -- intptr = (int *) &options->lpk.b_timeout.tv_sec; -- goto parse_int; -+ longptr = (unsigned long *) &options->lpk.b_timeout.tv_sec; -+parse_ulong: -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing integer value.", -+ filename, linenum); -+ lvalue = atol(arg); -+ if (*activep && *longptr == -1) -+ *longptr = lvalue; -+ break; -+ - case sSearchTimeout: -- intptr = (int *) &options->lpk.s_timeout.tv_sec; -- goto parse_int; -+ longptr = (unsigned long *) &options->lpk.s_timeout.tv_sec; -+ goto parse_ulong; - break; - case sLdapConf: - arg = cp; --- openssh-portable-5.2.p1_2,1.patch ends here --- >Release-Note: >Audit-Trail: >Unformatted: