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