From 7e7fb423e6edb7a15e5959b9888543c14bed76fc Mon Sep 17 00:00:00 2001 From: "Jan F. Chadima" Date: Wed, 28 Apr 2010 11:07:03 +0000 Subject: [PATCH] - Added LDAP support --- openssh-5.5p1-ldap.patch | 2547 ++++++++++++++++++++++++++++++++++++++ openssh.spec | 27 +- 2 files changed, 2573 insertions(+), 1 deletion(-) create mode 100644 openssh-5.5p1-ldap.patch diff --git a/openssh-5.5p1-ldap.patch b/openssh-5.5p1-ldap.patch new file mode 100644 index 0000000..591ff23 --- /dev/null +++ b/openssh-5.5p1-ldap.patch @@ -0,0 +1,2547 @@ +diff -up openssh-5.5p1/config.h.in.ldap openssh-5.5p1/config.h.in +--- openssh-5.5p1/config.h.in.ldap 2010-04-16 02:17:09.000000000 +0200 ++++ openssh-5.5p1/config.h.in 2010-04-28 11:34:13.000000000 +0200 +@@ -1,5 +1,8 @@ + /* config.h.in. Generated from configure.ac by autoheader. */ + ++/* Define if building universal (internal helper macro) */ ++#undef AC_APPLE_UNIVERSAL_BUILD ++ + /* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address + */ + #undef AIX_GETNAMEINFO_HACK +@@ -536,6 +539,57 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_LASTLOG_H + ++/* Define to 1 if you have the header file. */ ++#undef HAVE_LBER_H ++ ++/* Define to 1 if you have the `ldapssl_init' function. */ ++#undef HAVE_LDAPSSL_INIT ++ ++/* Define to 1 if you have the `ldap_controls_free' function. */ ++#undef HAVE_LDAP_CONTROLS_FREE ++ ++/* Define to 1 if you have the `ldap_get_lderrno' function. */ ++#undef HAVE_LDAP_GET_LDERRNO ++ ++/* Define to 1 if you have the `ldap_get_option' function. */ ++#undef HAVE_LDAP_GET_OPTION ++ ++/* Define to 1 if you have the header file. */ ++#undef HAVE_LDAP_H ++ ++/* Define to 1 if you have the `ldap_init' function. */ ++#undef HAVE_LDAP_INIT ++ ++/* Define to 1 if you have the `ldap_initialize' function. */ ++#undef HAVE_LDAP_INITIALIZE ++ ++/* Define to 1 if you have the `ldap_memfree' function. */ ++#undef HAVE_LDAP_MEMFREE ++ ++/* Define to 1 if you have the `ldap_parse_result' function. */ ++#undef HAVE_LDAP_PARSE_RESULT ++ ++/* Define to 1 if you have the `ldap_pvt_tls_set_option' function. */ ++#undef HAVE_LDAP_PVT_TLS_SET_OPTION ++ ++/* Define to 1 if you have the `ldap_set_lderrno' function. */ ++#undef HAVE_LDAP_SET_LDERRNO ++ ++/* Define to 1 if you have the `ldap_set_option' function. */ ++#undef HAVE_LDAP_SET_OPTION ++ ++/* Define to 1 if you have the `ldap_set_rebind_proc' function. */ ++#undef HAVE_LDAP_SET_REBIND_PROC ++ ++/* Define to 1 if you have the header file. */ ++#undef HAVE_LDAP_SSL_H ++ ++/* Define to 1 if you have the `ldap_start_tls_s' function. */ ++#undef HAVE_LDAP_START_TLS_S ++ ++/* Define to 1 if you have the header file. */ ++#undef HAVE_LIBAUDIT_H ++ + /* Define to 1 if you have the `bsm' library (-lbsm). */ + #undef HAVE_LIBBSM + +@@ -575,6 +629,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_LIMITS_H + ++/* Define if you want Linux audit support. */ ++#undef HAVE_LINUX_AUDIT ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_LINUX_IF_TUN_H + +@@ -771,6 +828,9 @@ + /* Define to 1 if you have the `setgroups' function. */ + #undef HAVE_SETGROUPS + ++/* Define to 1 if you have the `setkeycreatecon' function. */ ++#undef HAVE_SETKEYCREATECON ++ + /* Define to 1 if you have the `setlogin' function. */ + #undef HAVE_SETLOGIN + +@@ -921,13 +981,13 @@ + /* define if you have struct sockaddr_in6 data type */ + #undef HAVE_STRUCT_SOCKADDR_IN6 + +-/* Define to 1 if `sin6_scope_id' is member of `struct sockaddr_in6'. */ ++/* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */ + #undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID + + /* define if you have struct sockaddr_storage data type */ + #undef HAVE_STRUCT_SOCKADDR_STORAGE + +-/* Define to 1 if `st_blksize' is member of `struct stat'. */ ++/* Define to 1 if `st_blksize' is a member of `struct stat'. */ + #undef HAVE_STRUCT_STAT_ST_BLKSIZE + + /* Define to 1 if the system has the type `struct timespec'. */ +@@ -1191,6 +1251,9 @@ + /* Define if pututxline updates lastlog too */ + #undef LASTLOG_WRITE_PUTUTXLINE + ++/* number arguments of ldap_set_rebind_proc */ ++#undef LDAP_SET_REBIND_PROC_ARGS ++ + /* Define if you want TCP Wrappers support */ + #undef LIBWRAP + +@@ -1274,6 +1337,9 @@ + /* Define to the one symbol short name of this package. */ + #undef PACKAGE_TARNAME + ++/* Define to the home page for this package. */ ++#undef PACKAGE_URL ++ + /* Define to the version of this package. */ + #undef PACKAGE_VERSION + +@@ -1360,6 +1426,10 @@ + /* Prepend the address family to IP tunnel traffic */ + #undef SSH_TUN_PREPEND_AF + ++/* Define to your vendor patch level, if it has been modified from the ++ upstream source release. */ ++#undef SSH_VENDOR_PATCHLEVEL ++ + /* Define to 1 if you have the ANSI C header files. */ + #undef STDC_HEADERS + +@@ -1384,6 +1454,9 @@ + /* Use btmp to log bad logins */ + #undef USE_BTMP + ++/* platform uses an in-memory credentials cache */ ++#undef USE_CCAPI ++ + /* Use libedit for sftp */ + #undef USE_LIBEDIT + +@@ -1396,6 +1469,9 @@ + /* Use PIPES instead of a socketpair() */ + #undef USE_PIPES + ++/* platform has the Security Authorization Session API */ ++#undef USE_SECURITY_SESSION_API ++ + /* Define if you have Solaris process contracts */ + #undef USE_SOLARIS_PROCESS_CONTRACTS + +@@ -1418,12 +1494,26 @@ + /* Define if you want IRIX project management */ + #undef WITH_IRIX_PROJECT + ++/* Enable LDAP pubkey support */ ++#undef WITH_LDAP_PUBKEY ++ ++/* Enable pubkey agent support */ ++#undef WITH_PUBKEY_AGENT ++ + /* Define if you want SELinux support. */ + #undef WITH_SELINUX + +-/* Define to 1 if your processor stores words with the most significant byte +- first (like Motorola and SPARC, unlike Intel and VAX). */ +-#undef WORDS_BIGENDIAN ++/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most ++ significant byte first (like Motorola and SPARC, unlike Intel). */ ++#if defined AC_APPLE_UNIVERSAL_BUILD ++# if defined __BIG_ENDIAN__ ++# define WORDS_BIGENDIAN 1 ++# endif ++#else ++# ifndef WORDS_BIGENDIAN ++# undef WORDS_BIGENDIAN ++# endif ++#endif + + /* Define if xauth is found in your path */ + #undef XAUTH_PATH +diff -up openssh-5.5p1/configure.ac.ldap openssh-5.5p1/configure.ac +--- openssh-5.5p1/configure.ac.ldap 2010-04-28 11:34:09.000000000 +0200 ++++ openssh-5.5p1/configure.ac 2010-04-28 11:34:13.000000000 +0200 +@@ -1382,6 +1382,106 @@ AC_ARG_WITH(pka, + ] + ) + ++# Check whether user wants LDAP support ++LDAP_MSG="no" ++INSTALL_SSH_LDAP_HELPER="" ++AC_ARG_WITH(ldap, ++ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)], ++ [ ++ if test "x$withval" != "xno" ; then ++ ++ INSTALL_SSH_LDAP_HELPER="yes" ++ CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED" ++ ++ 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]) ++ LDAP_MSG="yes" ++ ++ AC_CHECK_HEADERS(lber.h) ++ AC_CHECK_HEADERS(ldap.h, , AC_MSG_ERROR(could not locate )) ++ AC_CHECK_HEADERS(ldap_ssl.h) ++ ++ AC_ARG_WITH(ldap-lib, ++ [ --with-ldap-lib=type select ldap library [auto|netscape5|netscape4|netscape3|umich|openldap]]) ++ ++ if test -z "$with_ldap_lib"; then ++ with_ldap_lib=auto ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = umich -o $with_ldap_lib = openldap \); then ++ AC_CHECK_LIB(lber, main, LIBS="-llber $LIBS" found_ldap_lib=yes) ++ AC_CHECK_LIB(ldap, main, LIBS="-lldap $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape5 \); then ++ AC_CHECK_LIB(ldap50, main, LIBS="-lldap50 -lssldap50 -lssl3 -lnss3 -lnspr4 -lprldap50 -lplc4 -lplds4 $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape4 \); then ++ AC_CHECK_LIB(ldapssl41, main, LIBS="-lldapssl41 -lplc3 -lplds3 -lnspr3 $LIBS" found_ldap_lib=yes) ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldapssl40, main, LIBS="-lldapssl40 $LIBS" found_ldap_lib=yes) ++ fi ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldap41, main, LIBS="-lldap41 $LIBS" found_ldap_lib=yes) ++ fi ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldap40, main, LIBS="-lldap40 $LIBS" found_ldap_lib=yes) ++ fi ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape3 \); then ++ AC_CHECK_LIB(ldapssl30, main, LIBS="-lldapssl30 $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib"; then ++ AC_MSG_ERROR(could not locate a valid LDAP library) ++ fi ++ ++ AC_MSG_CHECKING([for working 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 **]) ++ ]) ++ AC_CHECK_FUNCS( \ ++ ldap_init \ ++ ldap_get_lderrno \ ++ ldap_set_lderrno \ ++ ldap_parse_result \ ++ ldap_memfree \ ++ ldap_controls_free \ ++ ldap_set_option \ ++ ldap_get_option \ ++ ldapssl_init \ ++ ldap_start_tls_s \ ++ ldap_pvt_tls_set_option \ ++ ldap_initialize \ ++ ) ++ AC_CHECK_FUNCS(ldap_set_rebind_proc, ++ AC_MSG_CHECKING([number arguments of ldap_set_rebind_proc]) ++ AC_TRY_COMPILE( ++ [#include ++ #include ], ++ [ldap_set_rebind_proc(0, 0, 0);], ++ [ac_cv_ldap_set_rebind_proc=3], ++ [ac_cv_ldap_set_rebind_proc=2]) ++ AC_MSG_RESULT($ac_cv_ldap_set_rebind_proc) ++ AC_DEFINE(LDAP_SET_REBIND_PROC_ARGS, $ac_cv_ldap_set_rebind_proc, [number arguments of ldap_set_rebind_proc]) ++ ) ++ fi ++ ] ++) ++AC_SUBST(INSTALL_SSH_LDAP_HELPER) ++ + dnl Checks for library functions. Please keep in alphabetical order + AC_CHECK_FUNCS( \ + arc4random \ +@@ -4239,6 +4339,7 @@ echo " Smartcard support + echo " S/KEY support: $SKEY_MSG" + echo " TCP Wrappers support: $TCPW_MSG" + echo " PKA support: $PKA_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 -up openssh-5.5p1/ldapbody.c.ldap openssh-5.5p1/ldapbody.c +--- openssh-5.5p1/ldapbody.c.ldap 2010-04-28 11:34:13.000000000 +0200 ++++ openssh-5.5p1/ldapbody.c 2010-04-28 11:34:13.000000000 +0200 +@@ -0,0 +1,494 @@ ++/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "ldapincludes.h" ++#include "log.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include "ldapmisc.h" ++#include "ldapbody.h" ++#include ++#include ++ ++#define LDAPSEARCH_FORMAT "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)" ++#define PUBKEYATTR "sshPublicKey" ++#define LDAP_LOGFILE "%s/ldap.%d" ++ ++static FILE *logfile = NULL; ++static LDAP *ld; ++ ++static char *attrs[] = { ++ PUBKEYATTR, ++ NULL ++}; ++ ++void ++ldap_checkconfig (void) ++{ ++#ifdef HAVE_LDAP_INITIALIZE ++ if (options.host == NULL && options.uri == NULL) ++#else ++ if (options.host == NULL) ++#endif ++ fatal ("missing \"host\" in config file"); ++} ++ ++#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) ++static int ++_rebind_proc (LDAP * ld, LDAP_CONST char *url, int request, ber_int_t msgid) ++{ ++ struct timeval timeout; ++ int rc; ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ LDAPMessage *result; ++#endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */ ++ ++ debug2 ("Doing LDAP rebind to %s", options.binddn); ++ if (options.ssl == SSL_START_TLS) { ++ if ((rc = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) { ++ error ("ldap_starttls_s: %s", ldap_err2string (rc)); ++ return LDAP_OPERATIONS_ERROR; ++ } ++ } ++ ++#if !defined(HAVE_LDAP_PARSE_RESULT) || !defined(HAVE_LDAP_CONTROLS_FREE) ++ return ldap_simple_bind_s (ld, options.binddn, options.bindpw); ++#else ++ if (ldap_simple_bind(ld, options.binddn, options.bindpw) < 0) ++ fatal ("ldap_simple_bind %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); ++ ++ timeout.tv_sec = options.bind_timelimit; ++ timeout.tv_usec = 0; ++ result = NULL; ++ if ((rc = ldap_result (ld, msgid, FALSE, &timeout, &result)) < 1) { ++ error ("ldap_result %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); ++ ldap_msgfree (result); ++ return LDAP_OPERATIONS_ERROR; ++ } ++ debug3 ("LDAP rebind to %s succesfull", options.binddn); ++ return rc; ++#endif ++} ++#else ++ ++static int ++_rebind_proc (LDAP * ld, char **whop, char **credp, int *methodp, int freeit) ++{ ++ if (freeit) ++ return LDAP_SUCCESS; ++ ++ *whop = strdup (options.binddn); ++ *credp = strdup (options.bindpw); ++ *methodp = LDAP_AUTH_SIMPLE; ++ debug2 ("Doing LDAP rebind for %s", *whop); ++ return LDAP_SUCCESS; ++} ++#endif ++ ++void ++ldap_do_connect(void) ++{ ++ int rc, msgid, ld_errno = 0; ++ struct timeval timeout; ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ int parserc; ++ LDAPMessage *result; ++ LDAPControl **controls; ++ int reconnect = 0; ++#endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */ ++ ++ debug ("LDAP do connect"); ++ ++retry: ++ if (reconnect) { ++ debug3 ("Reconnecting with ld_errno %d", ld_errno); ++ if (options.bind_policy == 0 || ++ (ld_errno != LDAP_SERVER_DOWN && ld_errno != LDAP_TIMEOUT) || ++ reconnect > 5) ++ fatal ("Cannot connect to LDAP server"); ++ ++ if (reconnect > 1) ++ sleep (reconnect - 1); ++ ++ if (ld != NULL) { ++ ldap_unbind (ld); ++ ld = NULL; ++ } ++ logit("reconnecting to LDAP server..."); ++ } ++ ++ if (ld == NULL) { ++ int rc; ++ struct timeval tv; ++ ++#ifdef HAVE_LDAP_SET_OPTION ++ if (options.debug > 0) { ++#ifdef LBER_OPT_LOG_PRINT_FILE ++ if (options.logdir) { ++ char *logfilename; ++ int logfilenamelen; ++ ++ logfilenamelen = strlen (LDAP_LOGFILE) + strlen ("000000") + strlen (options.logdir); ++ logfilename = xmalloc (logfilenamelen); ++ snprintf (logfilename, logfilenamelen, LDAP_LOGFILE, options.logdir, (int) getpid ()); ++ logfilename[logfilenamelen - 1] = 0; ++ if ((logfile = fopen (logfilename, "a")) == NULL) ++ fatal ("cannot append to %s: %s", logfilename, strerror (errno)); ++ debug3 ("LDAP debug into %s", logfilename); ++ xfree (logfilename); ++ ber_set_option (NULL, LBER_OPT_LOG_PRINT_FILE, logfile); ++ } ++#endif ++ if (options.debug) { ++#ifdef LBER_OPT_DEBUG_LEVEL ++ ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &options.debug); ++#endif /* LBER_OPT_DEBUG_LEVEL */ ++#ifdef LDAP_OPT_DEBUG_LEVEL ++ ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &options.debug); ++#endif /* LDAP_OPT_DEBUG_LEVEL */ ++ debug3 ("Set LDAP debug to %d", options.debug); ++ } ++ } ++#endif /* HAVE_LDAP_SET_OPTION */ ++ ++ ld = NULL; ++#ifdef HAVE_LDAPSSL_INIT ++ if (options.host != NULL) { ++ if (options.ssl_on == SSL_LDAPS) { ++ if ((rc = ldapssl_client_init (options.sslpath, NULL)) != LDAP_SUCCESS) ++ fatal ("ldapssl_client_init %s", ldap_err2string (rc)); ++ debug3 ("LDAPssl client init"); ++ } ++ ++ if (options.ssl_on != SSL_OFF) { ++ if ((ld = ldapssl_init (options.host, options.port, TRUE)) == NULL) ++ fatal ("ldapssl_init failed"); ++ debug3 ("LDAPssl init"); ++ } ++ } ++#endif /* HAVE_LDAPSSL_INIT */ ++ ++ /* continue with opening */ ++ if (ld == NULL) { ++#if defined (HAVE_LDAP_START_TLS_S) || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) ++ /* Some global TLS-specific options need to be set before we create our ++ * session context, so we set them here. */ ++ ++#ifdef LDAP_OPT_X_TLS_RANDOM_FILE ++ /* rand file */ ++ if (options.tls_randfile != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE, ++ options.tls_randfile)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_RANDOM_FILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS random file %s", options.tls_randfile); ++ } ++#endif /* LDAP_OPT_X_TLS_RANDOM_FILE */ ++ ++ /* ca cert file */ ++ if (options.tls_cacertfile != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, ++ options.tls_cacertfile)) != LDAP_SUCCESS) ++ error ("ldap_set_option(LDAP_OPT_X_TLS_CACERTFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS CA cert file %s ", options.tls_cacertfile); ++ } ++ ++ /* ca cert directory */ ++ if (options.tls_cacertdir != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, ++ options.tls_cacertdir)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS CA cert dir %s ", options.tls_cacertdir); ++ } ++ ++ /* require cert? */ ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, ++ &options.tls_checkpeer)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS check peer to %d ", options.tls_checkpeer); ++ ++ /* set cipher suite, certificate and private key: */ ++ if (options.tls_ciphers != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, ++ options.tls_ciphers)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CIPHER_SUITE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS ciphers to %s ", options.tls_ciphers); ++ } ++ ++ /* cert file */ ++ if (options.tls_cert != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE, ++ options.tls_cert)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CERTFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS cert file %s ", options.tls_cert); ++ } ++ ++ /* key file */ ++ if (options.tls_key != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE, ++ options.tls_key)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_KEYFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS key file %s ", options.tls_key); ++ } ++#endif ++#ifdef HAVE_LDAP_INITIALIZE ++ if (options.uri != NULL) { ++ if ((rc = ldap_initialize (&ld, options.uri)) != LDAP_SUCCESS) ++ fatal ("ldap_initialize %s", ldap_err2string (rc)); ++ debug3 ("LDAP initialize %s", options.uri); ++ } ++ } ++#endif /* HAVE_LDAP_INTITIALIZE */ ++ ++ /* continue with opening */ ++ if ((ld == NULL) && (options.host != NULL)) { ++#ifdef HAVE_LDAP_INIT ++ if ((ld = ldap_init (options.host, options.port)) == NULL) ++ fatal ("ldap_init failed"); ++ debug3 ("LDAP init %s:%d", options.host, options.port); ++#else ++ if ((ld = ldap_open (options.host, options.port)) == NULL) ++ fatal ("ldap_open failed"); ++ debug3 ("LDAP open %s:%d", options.host, options.port); ++#endif /* HAVE_LDAP_INIT */ ++ } ++ ++ if (ld == NULL) ++ fatal ("no way to open ldap"); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS) ++ if (options.ssl == SSL_LDAPS) { ++ if ((rc = ldap_set_option (ld, LDAP_OPT_X_TLS, &options.tls_checkpeer)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS) %s", ldap_err2string (rc)); ++ debug3 ("LDAP set LDAP_OPT_X_TLS_%d", options.tls_checkpeer); ++ } ++#endif /* LDAP_OPT_X_TLS */ ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_PROTOCOL_VERSION) ++ (void) ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, ++ &options.ldap_version); ++#else ++ ld->ld_version = options.ldap_version; ++#endif ++ debug3 ("LDAP set version to %d", options.ldap_version); ++ ++#if LDAP_SET_REBIND_PROC_ARGS == 3 ++ ldap_set_rebind_proc (ld, _rebind_proc, NULL); ++#elif LDAP_SET_REBIND_PROC_ARGS == 2 ++ ldap_set_rebind_proc (ld, _rebind_proc); ++#else ++#warning unknown LDAP_SET_REBIND_PROC_ARGS ++#endif ++ debug3 ("LDAP set rebind proc"); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_DEREF) ++ (void) ldap_set_option (ld, LDAP_OPT_DEREF, &options.deref); ++#else ++ ld->ld_deref = options.deref; ++#endif ++ debug3 ("LDAP set deref to %d", options.deref); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_TIMELIMIT) ++ (void) ldap_set_option (ld, LDAP_OPT_TIMELIMIT, ++ &options.timelimit); ++#else ++ ld->ld_timelimit = options.timelimit; ++#endif ++ debug3 ("LDAP set timelimit to %d", options.timelimit); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_X_OPT_CONNECT_TIMEOUT) ++ /* ++ * This is a new option in the Netscape SDK which sets ++ * the TCP connect timeout. For want of a better value, ++ * we use the bind_timelimit to control this. ++ */ ++ timeout = options.bind_timelimit * 1000; ++ (void) ldap_set_option (ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout); ++ debug3 ("LDAP set opt connect timeout to %d", timeout); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_NETWORK_TIMEOUT) ++ tv.tv_sec = options.bind_timelimit; ++ tv.tv_usec = 0; ++ (void) ldap_set_option (ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); ++ debug3 ("LDAP set opt network timeout to %ld.0", tv.tv_sec); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_REFERRALS) ++ (void) ldap_set_option (ld, LDAP_OPT_REFERRALS, ++ options.referrals ? LDAP_OPT_ON : LDAP_OPT_OFF); ++ debug3 ("LDAP set referrals to %d", options.referrals); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_RESTART) ++ (void) ldap_set_option (ld, LDAP_OPT_RESTART, ++ options.restart ? LDAP_OPT_ON : LDAP_OPT_OFF); ++ debug3 ("LDAP set restart to %d", options.restart); ++#endif ++ ++#ifdef HAVE_LDAP_START_TLS_S ++ if (options.ssl == SSL_START_TLS) { ++ int version; ++ ++ if (ldap_get_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version) ++ == LDAP_SUCCESS) { ++ if (version < LDAP_VERSION3) { ++ version = LDAP_VERSION3; ++ (void) ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, ++ &version); ++ debug3 ("LDAP set version to %d", version); ++ } ++ } ++ ++ if ((rc = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) ++ fatal ("ldap_starttls_s: %s", ldap_err2string (rc)); ++ debug3 ("LDAP start TLS"); ++ } ++#endif /* HAVE_LDAP_START_TLS_S */ ++ } ++ ++ if ((msgid = ldap_simple_bind (ld, options.binddn, ++ options.bindpw)) == -1) { ++ ld_errno = ldap_get_lderrno (ld, 0, 0); ++ ++ error ("ldap_simple_bind %s", ldap_err2string (ld_errno)); ++ reconnect++; ++ goto retry; ++ } ++ debug3 ("LDAP simple bind (%s)", options.binddn); ++ ++ timeout.tv_sec = options.bind_timelimit; ++ timeout.tv_usec = 0; ++ if ((rc = ldap_result (ld, msgid, FALSE, &timeout, &result)) < 1) { ++ ld_errno = ldap_get_lderrno (ld, 0, 0); ++ ++ error ("ldap_result %s", ldap_err2string (ld_errno)); ++ reconnect++; ++ goto retry; ++ } ++ debug3 ("LDAP result in time"); ++ ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ controls = NULL; ++ if ((parserc = ldap_parse_result (ld, result, &rc, 0, 0, 0, &controls, TRUE)) != LDAP_SUCCESS) ++ fatal ("ldap_parse_result %s", ldap_err2string (parserc)); ++ debug3 ("LDAP parse result OK"); ++ ++ if (controls != NULL) { ++ ldap_controls_free (controls); ++ } ++#else ++ rc = ldap_result2error (session->ld, result, TRUE); ++#endif ++ if (rc != LDAP_SUCCESS) ++ fatal ("error trying to bind as user \"%s\" (%s)", ++ options.binddn, ldap_err2string (rc)); ++ ++ debug2 ("LDAP do connect OK"); ++} ++ ++void ++process_user (const char *user, FILE *output) ++{ ++ LDAPMessage *res, *e; ++ char *buffer; ++ int bufflen, rc, i; ++ struct timeval timeout; ++ ++ debug ("LDAP process user"); ++ ++ /* quick check for attempts to be evil */ ++ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || ++ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) { ++ logit ("illegal user name %s not processed", user); ++ return; ++ } ++ ++ /* build filter for LDAP request */ ++ bufflen = strlen (LDAPSEARCH_FORMAT) + strlen (user); ++ if (options.ssh_filter != NULL) ++ bufflen += strlen (options.ssh_filter); ++ buffer = xmalloc (bufflen); ++ snprintf(buffer, bufflen, LDAPSEARCH_FORMAT, user, (options.ssh_filter != NULL) ? options.ssh_filter : NULL); ++ buffer[bufflen - 1] = 0; ++ ++ debug3 ("LDAP search scope = %d %s", options.scope, buffer); ++ ++ timeout.tv_sec = options.timelimit; ++ timeout.tv_usec = 0; ++ if ((rc = ldap_search_st(ld, options.base, options.scope, buffer, attrs, 0, &timeout, &res)) != LDAP_SUCCESS) { ++ error ("ldap_search_st(): %s", ldap_err2string (rc)); ++ xfree (buffer); ++ return; ++ } ++ ++ /* free */ ++ xfree (buffer); ++ ++ for (e = ldap_first_entry(ld, res); e != NULL; e = ldap_next_entry(ld, e)) { ++ int num; ++ struct berval **keys; ++ ++ keys = ldap_get_values_len(ld, e, PUBKEYATTR); ++ num = ldap_count_values_len(keys); ++ for (i = 0 ; i < num ; i++) { ++ char *cp; //, *options = NULL; ++ ++ for (cp = keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++); ++ if (!*cp || *cp == '\n' || *cp == '#') ++ continue; ++ ++ /* We have found the desired key. */ ++ fprintf (output, "%s\n", keys[i]->bv_val); ++ } ++ ++ ldap_value_free_len(keys); ++ } ++ ++ ldap_msgfree(res); ++ debug2 ("LDAP process user finished"); ++} ++ ++void ++ldap_do_close(void) ++{ ++ int rc; ++ ++ debug ("LDAP do close"); ++ if ((rc = ldap_unbind_ext(ld, NULL, NULL)) != LDAP_SUCCESS) ++ fatal ("ldap_unbind_ext: %s", ++ ldap_err2string (rc)); ++ ++ ld = NULL; ++ debug2 ("LDAP do close OK"); ++ return; ++} ++ +diff -up openssh-5.5p1/ldapbody.h.ldap openssh-5.5p1/ldapbody.h +--- openssh-5.5p1/ldapbody.h.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/ldapbody.h 2010-04-28 11:34:14.000000000 +0200 +@@ -0,0 +1,37 @@ ++/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAPBODY_H ++#define LDAPBODY_H ++ ++#include ++ ++void ldap_checkconfig(void); ++void ldap_do_connect(void); ++void process_user(const char *, FILE *); ++void ldap_do_close(void); ++ ++#endif /* LDAPBODY_H */ ++ +diff -up openssh-5.5p1/ldapconf.c.ldap openssh-5.5p1/ldapconf.c +--- openssh-5.5p1/ldapconf.c.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/ldapconf.c 2010-04-28 11:34:14.000000000 +0200 +@@ -0,0 +1,665 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "ldapincludes.h" ++#include "ldap-helper.h" ++#include "log.h" ++#include "misc.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include ++#include ++ ++/* Keyword tokens. */ ++ ++typedef enum { ++ lBadOption, ++ lHost, lURI, lBase, lBindDN, lBindPW, lRootBindDN, ++ lScope, lDeref, lPort, lTimeLimit, lBind_TimeLimit, ++ lLdap_Version, lBind_Policy, lSSLPath, lSSL, lReferrals, ++ lRestart, lTLS_CheckPeer, lTLS_Certificate, lTLS_CaCertFile, ++ lTLS_CaCertDir, lTLS_Ciphers, lTLS_Cert, lTLS_Key, ++ lTLS_RandFile, lLogdir, lDebug, lSSH_Filter, ++ lDeprecated, lUnsupported ++} OpCodes; ++ ++/* Textual representations of the tokens. */ ++ ++static struct { ++ const char *name; ++ OpCodes opcode; ++} keywords[] = { ++ { "Host", lHost }, ++ { "URI", lURI }, ++ { "Base", lBase }, ++ { "BindDN", lBindDN }, ++ { "BindPW", lBindPW }, ++ { "RootBindDN", lRootBindDN }, ++ { "Scope", lScope }, ++ { "Deref", lDeref }, ++ { "Port", lPort }, ++ { "Timelimit", lTimeLimit }, ++ { "Bind_Timelimit", lBind_TimeLimit }, ++ { "Ldap_Version", lLdap_Version }, ++ { "Bind_Policy", lBind_Policy }, ++ { "SSLPath", lSSLPath }, ++ { "SSL", lSSL }, ++ { "Referrals", lReferrals }, ++ { "Restart", lRestart }, ++ { "TLS_CheckPeer", lTLS_CheckPeer }, ++ { "TLS_Certificate", lTLS_Certificate }, ++ { "TLS_CaCertFile", lTLS_CaCertFile }, ++ { "TLS_CaCertDir", lTLS_CaCertDir }, ++ { "TLS_Ciphers", lTLS_Ciphers }, ++ { "TLS_Cert", lTLS_Cert }, ++ { "TLS_Key", lTLS_Key }, ++ { "TLS_RandFile", lTLS_RandFile }, ++ { "Logdir", lLogdir }, ++ { "Debug", lDebug }, ++ { "SSH_Filter", lSSH_Filter }, ++ { NULL, lBadOption } ++}; ++ ++/* Configuration ptions. */ ++ ++Options options; ++ ++/* ++ * 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; ++ ++ if (config_warning_config_file) ++ logit("%s: line %d: Bad configuration option: %s", ++ filename, linenum, cp); ++ return lBadOption; ++} ++ ++/* ++ * 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" ++ ++static int ++process_config_line(char *line, const char *filename, int linenum) ++{ ++ char *s, **charptr, **xstringptr, *endofnumber, *keyword, *arg; ++ char *rootbinddn = NULL; ++ int opcode, *intptr, value; ++ size_t len; ++ ++ /* 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 lBadOption: ++ /* don't panic, but count bad options */ ++ return -1; ++ /* NOTREACHED */ ++ ++ case lHost: ++ xstringptr = &options.host; ++parse_xstring: ++ if (!s || *s == '\0') ++ fatal("%s line %d: missing dn",filename,linenum); ++ if (*xstringptr == NULL) ++ *xstringptr = xstrdup(s); ++ return 0; ++ ++ case lURI: ++ xstringptr = &options.uri; ++ goto parse_xstring; ++ ++ case lBase: ++ xstringptr = &options.base; ++ goto parse_xstring; ++ ++ case lBindDN: ++ xstringptr = &options.binddn; ++ goto parse_xstring; ++ ++ case lBindPW: ++ charptr = &options.bindpw; ++parse_string: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (*charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ ++ case lRootBindDN: ++ xstringptr = &rootbinddn; ++ goto parse_xstring; ++ ++ case lScope: ++ intptr = &options.scope; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing sub/one/base argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (!strcasecmp (arg, "sub")) ++ value = LDAP_SCOPE_SUBTREE; ++ else if (!strcasecmp (arg, "one")) ++ value = LDAP_SCOPE_ONELEVEL; ++ else if (!strcasecmp (arg, "base")) ++ value = LDAP_SCOPE_BASE; ++ else ++ fatal("%.200s line %d: Bad sub/one/base argument.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lDeref: ++ intptr = &options.scope; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing never/searching/finding/always argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (!strcasecmp (arg, "never")) ++ value = LDAP_DEREF_NEVER; ++ else if (!strcasecmp (arg, "searching")) ++ value = LDAP_DEREF_SEARCHING; ++ else if (!strcasecmp (arg, "finding")) ++ value = LDAP_DEREF_FINDING; ++ else if (!strcasecmp (arg, "always")) ++ value = LDAP_DEREF_ALWAYS; ++ else ++ fatal("%.200s line %d: Bad never/searching/finding/always argument.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lPort: ++ 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 (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lTimeLimit: ++ intptr = &options.timelimit; ++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 (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lBind_TimeLimit: ++ intptr = &options.bind_timelimit; ++ goto parse_time; ++ ++ case lLdap_Version: ++ intptr = &options.ldap_version; ++ goto parse_int; ++ ++ case lBind_Policy: ++ intptr = &options.bind_policy; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing soft/hard argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "hard") == 0) ++ value = 1; ++ else if (strcasecmp(arg, "soft") == 0) ++ value = 0; ++ else ++ fatal("%.200s line %d: Bad soft/hard argument.", filename, linenum); ++ if (*intptr == -1) ++ break; ++ ++ case lSSLPath: ++ charptr = &options.sslpath; ++ goto parse_string; ++ ++ case lSSL: ++ intptr = &options.ssl; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no/start_tls argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0 || strcasecmp(arg, "on") == 0) ++ value = SSL_LDAPS; ++ else if (strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0 || strcasecmp(arg, "off") == 0) ++ value = SSL_OFF; ++ else if (!strcasecmp (arg, "start_tls")) ++ value = SSL_START_TLS; ++ else ++ fatal("%.200s line %d: Bad yes/no/start_tls argument.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lReferrals: ++ intptr = &options.referrals; ++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 (strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0 || strcasecmp(arg, "on") == 0) ++ value = 1; ++ else if (strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0 || strcasecmp(arg, "off") == 0) ++ value = 0; ++ else ++ fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lRestart: ++ intptr = &options.restart; ++ goto parse_flag; ++ ++ case lTLS_CheckPeer: ++ intptr = &options.tls_checkpeer; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing never/hard/demand/alow/try argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "never") == 0) ++ value = LDAP_OPT_X_TLS_NEVER; ++ else if (strcasecmp(arg, "hard") == 0) ++ value = LDAP_OPT_X_TLS_HARD; ++ else if (strcasecmp(arg, "demand") == 0) ++ value = LDAP_OPT_X_TLS_DEMAND; ++ else if (strcasecmp(arg, "allow") == 0) ++ value = LDAP_OPT_X_TLS_ALLOW; ++ else if (strcasecmp(arg, "try") == 0) ++ value = LDAP_OPT_X_TLS_TRY; ++ else ++ fatal("%.200s line %d: Bad never/hard/demand/alow/try argument.", filename, linenum); ++ if (*intptr == -1) ++ break; ++ ++ case lTLS_CaCertFile: ++ charptr = &options.tls_cacertfile; ++ goto parse_string; ++ ++ case lTLS_CaCertDir: ++ charptr = &options.tls_cacertdir; ++ goto parse_string; ++ ++ case lTLS_Ciphers: ++ xstringptr = &options.tls_ciphers; ++ goto parse_xstring; ++ ++ case lTLS_Cert: ++ charptr = &options.tls_cert; ++ goto parse_string; ++ ++ case lTLS_Key: ++ charptr = &options.tls_key; ++ goto parse_string; ++ ++ case lTLS_RandFile: ++ charptr = &options.tls_randfile; ++ goto parse_string; ++ ++ case lLogdir: ++ charptr = &options.logdir; ++ goto parse_string; ++ ++ case lDebug: ++ intptr = &options.debug; ++ goto parse_int; ++ ++ case lSSH_Filter: ++ xstringptr = &options.ssh_filter; ++ goto parse_xstring; ++ ++ case lDeprecated: ++ debug("%s line %d: Deprecated option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ case lUnsupported: ++ 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. ++ */ ++ ++void ++read_config_file(const char *filename) ++{ ++ FILE *f; ++ char line[1024]; ++ int active, linenum; ++ int bad_options = 0; ++ struct stat sb; ++ ++ if ((f = fopen(filename, "r")) == NULL) ++ fatal("fopen %s: %s", filename, strerror(errno)); ++ ++ 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(line, filename, linenum) != 0) ++ bad_options++; ++ } ++ fclose(f); ++ if ((bad_options > 0) && config_exclusive_config_file) ++ fatal("%s: terminating, %d bad configuration options", ++ filename, bad_options); ++} ++ ++/* ++ * 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(void) ++{ ++ memset(&options, 'X', sizeof(options)); ++ options.host = NULL; ++ options.uri = NULL; ++ options.base = NULL; ++ options.binddn = NULL; ++ options.bindpw = NULL; ++ options.scope = -1; ++ options.deref = -1; ++ options.port = -1; ++ options.timelimit = -1; ++ options.bind_timelimit = -1; ++ options.ldap_version = -1; ++ options.bind_policy = -1; ++ options.sslpath = NULL; ++ options.ssl = -1; ++ options.referrals = -1; ++ options.restart = -1; ++ options.tls_checkpeer = -1; ++ options.tls_cacertfile = NULL; ++ options.tls_cacertdir = NULL; ++ options.tls_ciphers = NULL; ++ options.tls_cert = NULL; ++ options.tls_key = NULL; ++ options.tls_randfile = NULL; ++ options.logdir = NULL; ++ options.debug = -1; ++ options.ssh_filter = NULL; ++} ++ ++/* ++ * 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(void) ++{ ++ if (options.uri != NULL) { ++ LDAPURLDesc *ludp; ++ ++ if (ldap_url_parse(options.uri, &ludp) == LDAP_SUCCESS) { ++ if (options.ssl == -1) { ++ if (strcmp (ludp->lud_scheme, "ldap") || strcmp (ludp->lud_scheme, "ldapi")) ++ options.ssl = 0; ++ else if (strcmp (ludp->lud_scheme, "ldaps")) ++ options.ssl = 2; ++ } ++ if (options.host == NULL) ++ options.host = xstrdup (ludp->lud_host); ++ if (options.port == -1) ++ options.port = ludp->lud_port; ++ ++ ldap_free_urldesc (ludp); ++ } ++ } ++ if (options.ssl == -1) ++ options.ssl = SSL_START_TLS; ++ if (options.port == -1) ++ options.port = (options.ssl == 0) ? 389 : 636; ++ if (options.uri == NULL) { ++ int len; ++#define MAXURILEN 4096 ++ ++ options.uri = xmalloc (MAXURILEN); ++ len = snprintf (options.uri, MAXURILEN, "ldap%s://%s:%d", ++ (options.ssl == 0) ? "" : "s", options.host, options.port); ++ options.uri[MAXURILEN - 1] = 0; ++ options.uri = xrealloc (options.uri, len + 1, 1); ++ } ++ if (options.binddn == NULL) ++ options.binddn = ""; ++ if (options.bindpw == NULL) ++ options.bindpw = ""; ++ if (options.scope == -1) ++ options.scope = LDAP_SCOPE_SUBTREE; ++ if (options.deref == -1) ++ options.deref = LDAP_DEREF_NEVER; ++ if (options.timelimit == -1) ++ options.timelimit = 10; ++ if (options.bind_timelimit == -1) ++ options.bind_timelimit = 10; ++ if (options.ldap_version == -1) ++ options.ldap_version = 3; ++ if (options.bind_policy == -1) ++ options.bind_policy = 1; ++ if (options.referrals == -1) ++ options.referrals = 1; ++ if (options.restart == -1) ++ options.restart = 1; ++ if (options.tls_checkpeer == -1) ++ options.tls_checkpeer = LDAP_OPT_X_TLS_HARD; ++ if (options.debug == -1) ++ options.debug = 0; ++ if (options.ssh_filter == NULL) ++ options.ssh_filter = ""; ++} ++ ++static const char * ++lookup_opcode_name(OpCodes code) ++{ ++ u_int i; ++ ++ for (i = 0; keywords[i].name != NULL; i++) ++ if (keywords[i].opcode == code) ++ return(keywords[i].name); ++ return "UNKNOWN"; ++} ++ ++static void ++dump_cfg_string(OpCodes code, const char *val) ++{ ++ if (val == NULL) ++ debug3("%s ", lookup_opcode_name(code)); ++ else ++ debug3("%s %s", lookup_opcode_name(code), val); ++} ++ ++static void ++dump_cfg_int(OpCodes code, int val) ++{ ++ if (val == -1) ++ debug3("%s ", lookup_opcode_name(code)); ++ else ++ debug3("%s %d", lookup_opcode_name(code), val); ++} ++ ++struct names { ++ int value; ++ char *name; ++}; ++ ++static void ++dump_cfg_namedint(OpCodes code, int val, struct names *names) ++{ ++ u_int i; ++ ++ if (val == -1) ++ debug3("%s ", lookup_opcode_name(code)); ++ else { ++ for (i = 0; names[i].value != -1; i++) ++ if (names[i].value == val) { ++ debug3("%s %s", lookup_opcode_name(code), names[i].name); ++ return; ++ } ++ debug3("%s unknown: %d", lookup_opcode_name(code), val); ++ } ++} ++ ++static struct names _yesnotls[] = { ++ { 0, "No" }, ++ { 1, "Yes" }, ++ { 2, "Start_TLS" }, ++ { -1, NULL }}; ++ ++static struct names _scope[] = { ++ { LDAP_SCOPE_BASE, "Base" }, ++ { LDAP_SCOPE_ONELEVEL, "One" }, ++ { LDAP_SCOPE_SUBTREE, "Sub"}, ++ { -1, NULL }}; ++ ++static struct names _deref[] = { ++ { LDAP_DEREF_NEVER, "Never" }, ++ { LDAP_DEREF_SEARCHING, "Searching" }, ++ { LDAP_DEREF_FINDING, "Finding" }, ++ { LDAP_DEREF_ALWAYS, "Always" }, ++ { -1, NULL }}; ++ ++static struct names _yesno[] = { ++ { 0, "No" }, ++ { 1, "Yes" }, ++ { -1, NULL }}; ++ ++static struct names _bindpolicy[] = { ++ { 0, "Soft" }, ++ { 1, "Hard" }, ++ { -1, NULL }}; ++ ++static struct names _checkpeer[] = { ++ { LDAP_OPT_X_TLS_NEVER, "Never" }, ++ { LDAP_OPT_X_TLS_HARD, "Hard" }, ++ { LDAP_OPT_X_TLS_DEMAND, "Demand" }, ++ { LDAP_OPT_X_TLS_ALLOW, "Allow" }, ++ { LDAP_OPT_X_TLS_TRY, "TRY" }, ++ { -1, NULL }}; ++ ++void ++dump_config(void) ++{ ++ dump_cfg_string(lURI, options.uri); ++ dump_cfg_string(lHost, options.host); ++ dump_cfg_int(lPort, options.port); ++ dump_cfg_namedint(lSSL, options.ssl, _yesnotls); ++ dump_cfg_int(lLdap_Version, options.ldap_version); ++ dump_cfg_int(lTimeLimit, options.timelimit); ++ dump_cfg_int(lBind_TimeLimit, options.bind_timelimit); ++ dump_cfg_string(lBase, options.base); ++ dump_cfg_string(lBindDN, options.binddn); ++ dump_cfg_string(lBindPW, options.bindpw); ++ dump_cfg_namedint(lScope, options.scope, _scope); ++ dump_cfg_namedint(lDeref, options.deref, _deref); ++ dump_cfg_namedint(lReferrals, options.referrals, _yesno); ++ dump_cfg_namedint(lRestart, options.restart, _yesno); ++ dump_cfg_namedint(lBind_Policy, options.bind_policy, _bindpolicy); ++ dump_cfg_string(lSSLPath, options.sslpath); ++ dump_cfg_namedint(lTLS_CheckPeer, options.tls_checkpeer, _checkpeer); ++ dump_cfg_string(lTLS_CaCertFile, options.tls_cacertfile); ++ dump_cfg_string(lTLS_CaCertDir, options.tls_cacertdir); ++ dump_cfg_string(lTLS_Ciphers, options.tls_ciphers); ++ dump_cfg_string(lTLS_Cert, options.tls_cert); ++ dump_cfg_string(lTLS_Key, options.tls_key); ++ dump_cfg_string(lTLS_RandFile, options.tls_randfile); ++ dump_cfg_string(lLogdir, options.logdir); ++ dump_cfg_int(lDebug, options.debug); ++ dump_cfg_string(lSSH_Filter, options.ssh_filter); ++} ++ +diff -up openssh-5.5p1/ldapconf.h.ldap openssh-5.5p1/ldapconf.h +--- openssh-5.5p1/ldapconf.h.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/ldapconf.h 2010-04-28 11:34:14.000000000 +0200 +@@ -0,0 +1,71 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAPCONF_H ++#define LDAPCONF_H ++ ++#define SSL_OFF 0 ++#define SSL_LDAPS 1 ++#define SSL_START_TLS 2 ++ ++/* Data structure for representing option data. */ ++ ++typedef struct { ++ char *host; ++ char *uri; ++ char *base; ++ char *binddn; ++ char *bindpw; ++ int scope; ++ int deref; ++ int port; ++ int timelimit; ++ int bind_timelimit; ++ int ldap_version; ++ int bind_policy; ++ char *sslpath; ++ int ssl; ++ int referrals; ++ int restart; ++ int tls_checkpeer; ++ char *tls_cacertfile; ++ char *tls_cacertdir; ++ char *tls_ciphers; ++ char *tls_cert; ++ char *tls_key; ++ char *tls_randfile; ++ char *logdir; ++ int debug; ++ char *ssh_filter; ++} Options; ++ ++extern Options options; ++ ++void read_config_file(const char *); ++void initialize_options(void); ++void fill_default_options(void); ++void dump_config(void); ++ ++#endif /* LDAPCONF_H */ +diff -up openssh-5.5p1/ldap-helper.c.ldap openssh-5.5p1/ldap-helper.c +--- openssh-5.5p1/ldap-helper.c.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/ldap-helper.c 2010-04-28 11:34:14.000000000 +0200 +@@ -0,0 +1,154 @@ ++/* $OpenBSD: ssh-pka-ldap.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "ldapincludes.h" ++#include "log.h" ++#include "misc.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include "ldapbody.h" ++#include ++#include ++ ++static int config_debug = 0; ++int config_exclusive_config_file = 0; ++static char *config_file_name = "/etc/ldap.conf"; ++static char *config_single_user = NULL; ++static int config_verbose = SYSLOG_LEVEL_VERBOSE; ++int config_warning_config_file = 0; ++extern char *__progname; ++ ++static void ++usage(void) ++{ ++ fprintf(stderr, "usage: %s [options]\n", ++ __progname); ++ fprintf(stderr, "Options:\n"); ++ fprintf(stderr, " -d Output the log messages to stderr.\n"); ++ fprintf(stderr, " -e Check the config file for unknown commands.\n"); ++ fprintf(stderr, " -f file Use alternate config file (default is /etc/ldap.conf).\n"); ++ fprintf(stderr, " -s user Do not demonize, send the user's key to stdout.\n"); ++ fprintf(stderr, " -v Increase verbosity of the debug output (implies -d).\n"); ++ fprintf(stderr, " -w Warn on unknown commands int the config file.\n"); ++ exit(1); ++} ++ ++/* ++ * Main program for the ssh pka ldap agent. ++ */ ++ ++int ++main(int ac, char **av) ++{ ++ int opt; ++ FILE *outfile = NULL; ++ ++ __progname = ssh_get_progname(av[0]); ++ ++ log_init(__progname, SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); ++ ++ /* ++ * Initialize option structure to indicate that no values have been ++ * set. ++ */ ++ initialize_options(); ++ ++ /* Parse command-line arguments. */ ++ while ((opt = getopt(ac, av, "def:s:vw")) != -1) { ++ switch (opt) { ++ case 'd': ++ config_debug = 1; ++ break; ++ ++ case 'e': ++ config_exclusive_config_file = 1; ++ config_warning_config_file = 1; ++ break; ++ ++ case 'f': ++ config_file_name = optarg; ++ break; ++ ++ case 's': ++ config_single_user = optarg; ++ outfile = fdopen (dup (fileno (stdout)), "w"); ++ break; ++ ++ case 'v': ++ config_debug = 1; ++ if (config_verbose < SYSLOG_LEVEL_DEBUG3) ++ config_verbose++; ++ break; ++ ++ case 'w': ++ config_warning_config_file = 1; ++ break; ++ ++ case '?': ++ default: ++ usage(); ++ break; ++ } ++ } ++ ++ /* Initialize loging */ ++ log_init(__progname, config_verbose, SYSLOG_FACILITY_AUTH, config_debug); ++ ++ if (ac != optind) ++ fatal ("illegal extra parameter %s", av[1]); ++ ++ /* Ensure that fds 0 and 2 are open or directed to /dev/null */ ++ if (config_debug == 0) ++ sanitise_stdfd(); ++ ++ /* Read config file */ ++ read_config_file(config_file_name); ++ fill_default_options(); ++ if (config_verbose == SYSLOG_LEVEL_DEBUG3) { ++ debug3 ("=== Configuration ==="); ++ dump_config(); ++ debug3 ("=== *** ==="); ++ } ++ ++ ldap_checkconfig(); ++ ldap_do_connect(); ++ ++ if (config_single_user) { ++ process_user (config_single_user, outfile); ++ } else { ++ fatal ("Not yet implemented"); ++/* TODO ++ * open unix socket a run the loop on it ++ */ ++ } ++ ++ ldap_do_close(); ++ return 0; ++} ++ ++/* Ugly hack */ ++void *buffer_get_string(Buffer *b, u_int *l) {} ++void buffer_put_string(Buffer *b, const void *f, u_int l) {} ++ +diff -up openssh-5.5p1/ldap-helper.h.ldap openssh-5.5p1/ldap-helper.h +--- openssh-5.5p1/ldap-helper.h.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/ldap-helper.h 2010-04-28 11:34:14.000000000 +0200 +@@ -0,0 +1,32 @@ ++/* $OpenBSD: ldap-helper.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAP_HELPER_H ++#define LDAP_HELPER_H ++ ++extern int config_exclusive_config_file; ++extern int config_warning_config_file; ++ ++#endif /* LDAP_HELPER_H */ +diff -up openssh-5.5p1/ldapincludes.h.ldap openssh-5.5p1/ldapincludes.h +--- openssh-5.5p1/ldapincludes.h.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/ldapincludes.h 2010-04-28 11:34:14.000000000 +0200 +@@ -0,0 +1,41 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAPINCLUDES_H ++#define LDAPINCLUDES_H ++ ++#include "includes.h" ++ ++#ifdef HAVE_LBER_H ++#include ++#endif ++#ifdef HAVE_LDAP_H ++#include ++#endif ++#ifdef HAVE_LDAP_SSL_H ++#include ++#endif ++ ++#endif /* LDAPINCLUDES_H */ +diff -up openssh-5.5p1/ldapmisc.c.ldap openssh-5.5p1/ldapmisc.c +--- openssh-5.5p1/ldapmisc.c.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/ldapmisc.c 2010-04-28 11:34:14.000000000 +0200 +@@ -0,0 +1,79 @@ ++ ++#include "ldapincludes.h" ++#include "ldapmisc.h" ++ ++#ifndef HAVE_LDAP_GET_LDERRNO ++int ++ldap_get_lderrno (LDAP * ld, char **m, char **s) ++{ ++#ifdef HAVE_LDAP_GET_OPTION ++ int rc; ++#endif ++ int lderrno; ++ ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, &lderrno)) != LDAP_SUCCESS) ++ return rc; ++#else ++ lderrno = ld->ld_errno; ++#endif ++ ++ if (s != NULL) { ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_STRING) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_ERROR_STRING, s)) != LDAP_SUCCESS) ++ return rc; ++#else ++ *s = ld->ld_error; ++#endif ++ } ++ ++ if (m != NULL) { ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_MATCHED_DN) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_MATCHED_DN, m)) != LDAP_SUCCESS) ++ return rc; ++#else ++ *m = ld->ld_matched; ++#endif ++ } ++ ++ return lderrno; ++} ++#endif ++ ++#ifndef HAVE_LDAP_SET_LDERRNO ++int ++ldap_set_lderrno (LDAP * ld, int lderrno, const char *m, const char *s) ++{ ++#ifdef HAVE_LDAP_SET_OPTION ++ int rc; ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_ERROR_NUMBER, &lderrno)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_errno = lderrno; ++#endif ++ ++ if (s != NULL) { ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_ERROR_STRING) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_ERROR_STRING, s)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_error = s; ++#endif ++ } ++ ++ if (m != NULL) { ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_MATCHED_DN) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_MATCHED_DN, m)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_matched = m; ++#endif ++ } ++ ++ return LDAP_SUCCESS; ++} ++#endif ++ +diff -up openssh-5.5p1/ldapmisc.h.ldap openssh-5.5p1/ldapmisc.h +--- openssh-5.5p1/ldapmisc.h.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/ldapmisc.h 2010-04-28 11:34:14.000000000 +0200 +@@ -0,0 +1,35 @@ ++/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAPMISC_H ++#define LDAPMISC_H ++ ++#include "ldapincludes.h" ++ ++int ldap_get_lderrno (LDAP *, char **, char **); ++int ldap_set_lderrno (LDAP *, int, const char *, const char *); ++ ++#endif /* LDAPMISC_H */ ++ +diff -up openssh-5.5p1/lpk-user-example.txt.ldap openssh-5.5p1/lpk-user-example.txt +--- openssh-5.5p1/lpk-user-example.txt.ldap 2010-04-28 11:34:14.000000000 +0200 ++++ openssh-5.5p1/lpk-user-example.txt 2010-04-28 11:34:14.000000000 +0200 +@@ -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 -up openssh-5.5p1/Makefile.in.ldap openssh-5.5p1/Makefile.in +--- openssh-5.5p1/Makefile.in.ldap 2010-04-28 11:34:10.000000000 +0200 ++++ openssh-5.5p1/Makefile.in 2010-04-28 11:34:15.000000000 +0200 +@@ -26,6 +26,7 @@ ASKPASS_PROGRAM=$(libexecdir)/ssh-askpas + SFTP_SERVER=$(libexecdir)/sftp-server + SSH_KEYSIGN=$(libexecdir)/ssh-keysign + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper ++SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper + RAND_HELPER=$(libexecdir)/ssh-rand-helper + PRIVSEP_PATH=@PRIVSEP_PATH@ + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ +@@ -61,8 +62,9 @@ EXEEXT=@EXEEXT@ + + INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ + INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ ++INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ + +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT) ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) + + LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ + canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ +@@ -93,8 +95,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw + audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \ + roaming_common.o roaming_serv.o kexgsss.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 ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out +-MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 ++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 ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ++MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 + MANTYPE = @MANTYPE@ + + CONFIGFILES=sshd_config.out ssh_config.out moduli.out +@@ -165,6 +167,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o + $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) + ++ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o ++ $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) ++ + sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o + $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +@@ -266,6 +271,9 @@ install-files: + fi + $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) ++ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ ++ $(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \ ++ fi + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) + $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 +@@ -285,6 +293,9 @@ install-files: + $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 + $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 + $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 ++ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ ++ $(INSTALL) -m 644 ssh-ldap-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 ; \ ++ fi + -rm -f $(DESTDIR)$(bindir)/slogin + ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 +@@ -384,6 +395,7 @@ uninstall: + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 ++ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 + + tests interop-tests: $(TARGETS) +diff -up openssh-5.5p1/openssh-lpk-openldap.schema.ldap openssh-5.5p1/openssh-lpk-openldap.schema +--- openssh-5.5p1/openssh-lpk-openldap.schema.ldap 2010-04-28 11:34:15.000000000 +0200 ++++ openssh-5.5p1/openssh-lpk-openldap.schema 2010-04-28 11:34:15.000000000 +0200 +@@ -0,0 +1,21 @@ ++# ++# LDAP Public Key Patch schema for use with openssh-ldappubkey ++# useful with PKA-LDAP also ++# ++# 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 -up openssh-5.5p1/openssh-lpk-sun.schema.ldap openssh-5.5p1/openssh-lpk-sun.schema +--- openssh-5.5p1/openssh-lpk-sun.schema.ldap 2010-04-28 11:34:15.000000000 +0200 ++++ openssh-5.5p1/openssh-lpk-sun.schema 2010-04-28 11:34:15.000000000 +0200 +@@ -0,0 +1,23 @@ ++# ++# LDAP Public Key Patch schema for use with openssh-ldappubkey ++# useful with PKA-LDAP also ++# ++# 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 -up openssh-5.5p1/README.lpk.ldap openssh-5.5p1/README.lpk +--- openssh-5.5p1/README.lpk.ldap 2010-04-28 11:34:15.000000000 +0200 ++++ openssh-5.5p1/README.lpk 2010-04-28 12:33:34.000000000 +0200 +@@ -0,0 +1,268 @@ ++OpenSSH LDAP PUBLIC KEY PATCH ++Copyright (c) 2003 Eric AUGE (eau@phear.org) ++All rights reserved. ++ ++Rewriten by Jan F. Chadima (jchadima@redhat.com) ++Copyright (c) 2010 Red Hat, Inc. ++The new PKA-LDAP patch is rewritten from the scratch. ++LDAP schema and part of the documentation is based on original ++LPK project (http://code.google.com/p/openssh-lpk), ++copyright (c) 2003 Eric AUGE ++The new openssh configuration is different from the original LPK one. ++ ++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 ++'ServerGroup:' mean server group configured on the current server by the SSH_Filter option in the ldap.conf. ++ ++example schema: ++ ++ ++ server1 (uid: eau,rival,toto) (ServerGroup: unix) ++ ___________ / ++ / \ --- - server3 (uid: eau, titi) (ServerGroup: unix) ++ | LDAP Server | \ ++ | eau ,rival | server2 (uid: rival, eau) (ServerGroup: unix) ++ | titi ,toto | ++ | userx,.... | server5 (uid: eau) (ServerGroup: 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) ++ ++ 2 tokens are added to sshd_config : ++ # here is the new patched ldap related tokens ++ PubkeyAgent /usr/libexec/openssh/ssh-ldap-helper -s %u ++ PubkeyAgentRunAs nobody ++ ++ The LDAP configuratin is read from common /etc/ldap.conf configuration file. ++There is also one optional parameter in the LDAP configuration file, SSH_Filter, which is a LDAP filter limiting keys to be searched. ++ ++- 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, no 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 : ++ - Eric AUGE ++ - Andrea Barisani ++ - Falk Siemonsmeier. ++ - Jacob Rief. ++ - Michael Durchgraf. ++ - frederic peters. ++ - Finlay dobbie. ++ - Stefan Fisher. ++ - Robin H. Johnson. ++ - Adrian Bridgett. ++ ++- CONTACT : ++ Jan F. Chadima ++ +diff -up openssh-5.5p1/ssh-ldap-helper.8.ldap openssh-5.5p1/ssh-ldap-helper.8 +--- openssh-5.5p1/ssh-ldap-helper.8.ldap 2010-04-28 11:34:15.000000000 +0200 ++++ openssh-5.5p1/ssh-ldap-helper.8 2010-04-28 11:34:15.000000000 +0200 +@@ -0,0 +1,78 @@ ++.\" $OpenBSD: ssh-ldap-helper.8,v 1.1 2010/02/10 23:20:38 markus Exp $ ++.\" ++.\" Copyright (c) 2010 Jan F. Chadima. All rights reserved. ++.\" ++.\" Permission to use, copy, modify, and distribute this software for any ++.\" purpose with or without fee is hereby granted, provided that the above ++.\" copyright notice and this permission notice appear in all copies. ++.\" ++.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++.\" ++.Dd $Mdocdate: April 29 2010 $ ++.Dt SSH-LDAP-HELPER 8 ++.Os ++.Sh NAME ++.Nm ssh-ldap-helper ++.Nd sshd helper program for ldap support ++.Sh SYNOPSIS ++.Nm ssh-ldap-helper ++.Op Fl devw ++.Op Fl f Ar file ++.Op Fl s Ar user ++.Sh DESCRIPTION ++.Nm ++is used by ++.Xr sshd 1 ++to access keys provided by a LDAP. ++.Nm ++is disabled by default and can only be enabled in the ++sshd configuration file ++.Pa /etc/ssh/sshd_config ++by setting ++.Cm PubkeyAgent ++to ++.Dq /usr/libexec/ssh-ldap-helper -s %u . ++.Pp ++.Nm ++is not intended to be invoked by the user, but from ++.Xr sshd 8 . ++.Pp ++The options are as follows: ++.Bl -tag -width Ds ++.It Fl d ++Set the debug mode, ++.Nm ++prints all logs to stderr instead of syslog. ++.It Fl e ++Implies \-w ++.Nm ++halt when an unknown item is found in the ldap.conf file. ++.It Fl f ++Default /etc/ldap.conf. ++.Nm ++uses this file as a ldap configuration file. ++.It Fl s ++.Nm ++print out the keys of the user on stdout and exits. ++.It Fl v ++Implies \-d ++increases verbosity. ++.It Fl w ++.Nm ++writes warnings about unknown items in the ldap.conf file. ++ ++.Sh SEE ALSO ++.Xr sshd 8 , ++.Xr sshd_config 5 , ++.Sh HISTORY ++.Nm ++first appeared in ++OpenSSH 5.5 + PKA-LDAP . ++.Sh AUTHORS ++.An Jan F. Chadima Aq jchadima@redhat.com diff --git a/openssh.spec b/openssh.spec index d0ac4df..86283d5 100644 --- a/openssh.spec +++ b/openssh.spec @@ -27,6 +27,9 @@ # Do we want libedit support %define libedit 1 +# Do we want LDAP support +%define ldap 1 + # Do we want NSS tokens support #NSS support is broken from 5.4p1 %define nss 0 @@ -67,7 +70,7 @@ %endif # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%define openssh_rel 3 +%define openssh_rel 4 %define openssh_ver 5.5p1 %define pam_ssh_agent_rel 26 %define pam_ssh_agent_ver 0.9.2 @@ -113,6 +116,7 @@ Patch73: openssh-5.4p1-gsskex.patch Patch74: openssh-5.3p1-randclean.patch Patch76: openssh-5.4p1-staterr.patch Patch77: openssh-5.5p1-stderr.diff +Patch78: openssh-5.5p1-ldap.patch License: BSD Group: Applications/Internet @@ -135,6 +139,9 @@ BuildRequires: gnome-libs-devel %if %{scard} BuildRequires: sharutils %endif +%if %{ldap} +BuildRequires: openldap-devel +%endif BuildRequires: autoconf, automake, perl, zlib-devel BuildRequires: audit-libs-devel BuildRequires: util-linux, groff @@ -267,6 +274,9 @@ popd %patch74 -p1 -b .randclean %patch76 -p1 -b .staterr %patch77 -p1 -b .stderr +%if %{ldap} +%patch78 -p1 -b .ldap +%endif autoreconf pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} @@ -323,6 +333,9 @@ fi %if %{scard} --with-smartcard \ %endif +%if %{ldap} + --with-ldap \ +%endif %if %{rescue} --without-pam \ %else @@ -502,14 +515,23 @@ fi %if ! %{rescue} %files server %defattr(-,root,root) +%if %{ldap} +%doc README.lpk lpk-user-example.txt openssh-lpk-openldap.schema openssh-lpk-sun.schema +%endif %dir %attr(0711,root,root) %{_var}/empty/sshd %attr(0755,root,root) %{_sbindir}/sshd %attr(0644,root,root) %{_sbindir}/.sshd.hmac %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server +%if %{ldap} +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-ldap-helper +%endif %attr(0644,root,root) %{_mandir}/man5/sshd_config.5* %attr(0644,root,root) %{_mandir}/man5/moduli.5* %attr(0644,root,root) %{_mandir}/man8/sshd.8* %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* +%if %{ldap} +%attr(0644,root,root) %{_mandir}/man8/ssh-ldap-helper.8* +%endif %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config %attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0755,root,root) /etc/rc.d/init.d/sshd @@ -532,6 +554,9 @@ fi %endif %changelog +* Wed Apr 29 2010 Jan F. Chadima - 5.5p1-4 + 0.9.2-26 +- Added LDAP support + * Mon Apr 26 2010 Jan F. Chadima - 5.5p1-3 + 0.9.2-26 - Ignore .bashrc output to stderr in the subsystems