dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
dnl
dnl Process this file with autoconf to produce a configure script.
AC_INIT(./mod_sftp_ldap.c)
AC_CANONICAL_SYSTEM
ostype=`echo $build_os | sed 's/\..*$//g' | sed 's/-.*//g' | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
AC_PROG_CC
AC_PROG_CPP
AC_AIX
AC_ISC_POSIX
AC_MINIX
AC_PROG_MAKE_SET
dnl Need to support/handle the --enable-devel option, to see if coverage
dnl is being used
AC_ARG_ENABLE(devel,
[AC_HELP_STRING(
[--enable-devel],
[enable developer-only code (default=no)])
],
[
if test x"$enableval" != xno ; then
if test `echo $enableval | grep -c coverage` = "1" ; then
UTILS_LIBS="--coverage $UTILS_LIBS"
fi
fi
])
dnl Need to support/handle the --with-includes and --with-libraries options
AC_ARG_WITH(includes,
[AC_HELP_STRING(
[--with-includes=LIST],
[add additional include paths to proftpd. LIST is a colon-separated list of include paths to add e.g. --with-includes=/some/mysql/include:/my/include])
],
[ ac_addl_includes=`echo "$withval" | sed -e 's/:/ /g'` ;
for ainclude in $ac_addl_includes; do
if test x"$ac_build_addl_includes" = x ; then
ac_build_addl_includes="-I$ainclude"
else
ac_build_addl_includes="-I$ainclude $ac_build_addl_includes"
fi
done
CPPFLAGS="$CPPFLAGS $ac_build_addl_includes"
])
AC_ARG_WITH(libraries,
[AC_HELP_STRING(
[--with-libraries=LIST],
[add additional library paths to proftpd. LIST is a colon-separated list of include paths to add e.g. --with-libraries=/some/mysql/libdir:/my/libs])
],
[ ac_addl_libdirs=`echo "$withval" | sed -e 's/:/ /g'` ;
for alibdir in $ac_addl_libdirs; do
if test x"$ac_build_addl_libdirs" = x ; then
ac_build_addl_libdirs="-L$alibdir"
else
ac_build_addl_libdirs="-L$alibdir $ac_build_addl_libdirs"
fi
done
LDFLAGS="$LDFLAGS $ac_build_addl_libdirs"
])
AC_HEADER_STDC
AC_CHECK_HEADERS(stdlib.h unistd.h)
INCLUDES="$ac_build_addl_includes"
LIBDIRS="$ac_build_addl_libdirs"
AC_SUBST(INCLUDES)
AC_SUBST(LDFLAGS)
AC_SUBST(LIBDIRS)
AC_CONFIG_HEADER(mod_sftp_ldap.h)
AC_OUTPUT(
t/Makefile
Makefile
)
proftpd-mod_sftp_ldap-0.2/install-sh 0000775 0000000 0000000 00000012721 14215645241 0017655 0 ustar 00root root 0000000 0000000 #! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0
proftpd-mod_sftp_ldap-0.2/keys.c 0000664 0000000 0000000 00000031475 14215645241 0016777 0 ustar 00root root 0000000 0000000 /*
* ProFTPD: mod_sftp_ldap keys
* Copyright (c) 2010-2016 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* As a special exemption, the respective copyright holders give permission
* to link this program with OpenSSL, and distribute the resulting
* executable, without including the source code for OpenSSL in the source
* distribution.
*/
#include "keys.h"
#define SFTP_LDAP_BUFSZ 1024
#define SFTP_LDAP_KEY_BEGIN_MARKER_LEN 31
#define SFTP_LDAP_KEY_END_MARKER_LEN 29
/* Given a blob of bytes retrieved from a single row, read that blob as if
* it were text, line by line.
*/
static char *get_line(pool *p, char **blob, size_t *bloblen) {
char linebuf[SFTP_LDAP_BUFSZ], *line = "", *data;
size_t datalen;
data = *blob;
datalen = *bloblen;
if (data == NULL ||
datalen == 0) {
errno = EOF;
return NULL;
}
while (data != NULL && datalen > 0) {
char *ptr;
size_t delimlen, linelen;
int have_line_continuation = FALSE;
pr_signals_handle();
if (datalen <= 2) {
line = pstrcat(p, line, data, NULL);
*blob = NULL;
*bloblen = 0;
return line;
}
/* Find the CRLF markers in the data. */
ptr = strstr(data, "\r\n");
if (ptr != NULL) {
delimlen = 1;
} else {
ptr = strstr(data, "\n");
if (ptr != NULL) {
delimlen = 0;
}
}
if (ptr == NULL) {
/* Just return the rest of the data. */
line = pstrcat(p, line, data, NULL);
*blob = NULL;
*bloblen = 0;
return line;
}
linelen = (ptr - data + 1);
if (linelen == 1) {
data += (delimlen + 1);
datalen -= (delimlen + 1);
continue;
}
/* Watch out for lines larger than our buffer. */
if (linelen > sizeof(linebuf)) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"line of key data (%lu bytes) exceeds buffer size, truncating; "
"this WILL cause authentication failures", (unsigned long) linelen);
linelen = sizeof(linebuf);
}
memcpy(linebuf, data, linelen);
linebuf[linelen-1] = '\0';
data += (linelen + delimlen);
datalen -= (linelen + delimlen);
/* Check for continued lines. */
if (linelen >= 2 &&
linebuf[linelen-2] == '\\') {
linebuf[linelen-2] = '\0';
have_line_continuation = TRUE;
}
line = pstrcat(p, line, linebuf, NULL);
linelen = strlen(line);
if (have_line_continuation) {
continue;
}
ptr = strchr(line, ':');
if (ptr != NULL) {
unsigned int header_taglen, header_valuelen;
/* We have a header. Make sure the header tag is not longer than
* the specified length of 64 bytes, and that the header value is
* not longer than 1024 bytes.
*/
header_taglen = ptr - line;
if (header_taglen > 64) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"header tag too long (%u) in retrieved LDAP data", header_taglen);
errno = EINVAL;
return NULL;
}
/* Header value starts at 2 after the ':' (one for the mandatory
* space character.
*/
header_valuelen = linelen - (header_taglen + 2);
if (header_valuelen > 1024) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"header value too long (%u) in retrieved LDAP data", header_valuelen);
errno = EINVAL;
return NULL;
}
}
*blob = data;
*bloblen = datalen;
return line;
}
return NULL;
}
int sftp_ldap_keys_parse_raw(pool *p, char **blob, size_t *bloblen,
unsigned char **key_data, uint32_t *key_datalen) {
char chunk[SFTP_LDAP_BUFSZ], *data = NULL;
BIO *bio = NULL, *b64 = NULL, *bmem = NULL;
int chunklen, res;
long datalen = 0;
char *ptr;
if (p == NULL ||
blob == NULL ||
bloblen == NULL ||
key_data == NULL ||
key_datalen == NULL) {
errno = EINVAL;
return -1;
}
/* First we need to check for any leading/trailing SSH-isms in the key, i.e.
* an "ssh-rsa", "ssh-dss", or "ecdsa-sha2-nistp*" prefix. Fortunately
* the prefix, and the trailing suffix, are separated from the key material
* with spaces.
*/
ptr = strchr(*blob, ' ');
if (ptr != NULL) {
size_t prefix_len;
/* Advance the blob pointer past the prefix. */
prefix_len = (ptr + 1) - *blob;
(*bloblen) -= prefix_len;
(*blob) += prefix_len;
}
ptr = strrchr(*blob, ' ');
if (ptr != NULL) {
size_t suffix_len;
/* "Trim" off the suffix by truncating the bloblen appropriately. */
suffix_len = strlen(ptr);
(*bloblen) -= suffix_len;
}
bio = BIO_new(BIO_s_mem());
if (BIO_write(bio, (void *) *blob, *bloblen) < 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error buffering base64 data: %s", sftp_crypto_get_errors());
}
/* Add a base64 filter BIO, and read the data out, thus base64-decoding
* the key. Write the decoded data into another memory BIO.
*/
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bio = BIO_push(b64, bio);
bmem = BIO_new(BIO_s_mem());
memset(chunk, '\0', sizeof(chunk));
chunklen = BIO_read(bio, (void *) chunk, sizeof(chunk));
if (chunklen < 0 &&
!BIO_should_retry(bio)) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"unable to base64-decode data from LDAP directory: %s",
sftp_crypto_get_errors());
BIO_free_all(bio);
BIO_free_all(bmem);
errno = EPERM;
return -1;
}
while (chunklen > 0) {
pr_signals_handle();
if (BIO_write(bmem, (void *) chunk, chunklen) < 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error writing to memory BIO: %s", sftp_crypto_get_errors());
BIO_free_all(bio);
BIO_free_all(bmem);
errno = EPERM;
return -1;
}
memset(chunk, '\0', sizeof(chunk));
chunklen = BIO_read(bio, (void *) chunk, sizeof(chunk));
}
datalen = BIO_get_mem_data(bmem, &data);
if (data != NULL &&
datalen > 0) {
*key_datalen = datalen;
*key_data = palloc(p, datalen + 1);
(*key_data)[datalen] = '\0';
memcpy(*key_data, data, datalen);
res = 0;
} else {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error base64-decoding key data from LDAP directory");
errno = ENOENT;
res = -1;
}
BIO_free_all(bio);
bio = NULL;
BIO_free_all(bmem);
return res;
}
/* Note: When iterating backwards, be sure to ignore/skip over any potential
* end marker.
*/
static void find_key_start(char **line, size_t *linelen) {
register unsigned int i;
/* Do NOT examine the end marker. */
if (*linelen >= SFTP_LDAP_KEY_END_MARKER_LEN) {
size_t datalen;
datalen = *linelen - SFTP_LDAP_KEY_END_MARKER_LEN;
if (strncmp(*line + datalen, SFTP_SSH2_PUBKEY_END_MARKER, SFTP_LDAP_KEY_END_MARKER_LEN) == 0) {
i = datalen;
} else {
i = *linelen;
}
} else {
i = *linelen;
}
while (i-- > 0) {
char ch;
pr_signals_handle();
ch = (*line)[i];
if (('a' <= ch && ch <= 'z') ||
('A' <= ch && ch <= 'Z') ||
('0' <= ch && ch <= '9') ||
ch == '+' ||
ch == '/' ||
ch == '=') {
continue;
}
/* The start of the line, then, is the next character AFTER this one. */
*line = &((*line)[i+1]);
*linelen = *linelen - i - 1;
break;
}
}
int sftp_ldap_keys_parse_rfc4716(pool *p, char **blob, size_t *bloblen,
unsigned char **key_data, uint32_t *key_datalen) {
char *line;
BIO *bio = NULL;
int had_key_data = FALSE, res = -1;
if (p == NULL ||
blob == NULL ||
bloblen == NULL ||
key_data == NULL ||
key_datalen == NULL) {
errno = EINVAL;
return -1;
}
line = get_line(p, blob, bloblen);
while (line == NULL &&
errno == EINVAL) {
pr_signals_handle();
line = get_line(p, blob, bloblen);
}
if (line == NULL) {
return -1;
}
while (line != NULL) {
size_t linelen;
pr_signals_handle();
linelen = strlen(line);
if (bio == NULL &&
strncmp(line, SFTP_SSH2_PUBKEY_BEGIN_MARKER, SFTP_LDAP_KEY_BEGIN_MARKER_LEN) == 0) {
bio = BIO_new(BIO_s_mem());
linelen -= SFTP_LDAP_KEY_BEGIN_MARKER_LEN;
line += SFTP_LDAP_KEY_BEGIN_MARKER_LEN;
had_key_data = TRUE;
}
if (bio != NULL &&
linelen >= SFTP_LDAP_KEY_END_MARKER_LEN &&
strncmp(line, SFTP_SSH2_PUBKEY_END_MARKER, SFTP_LDAP_KEY_END_MARKER_LEN) == 0) {
char chunk[SFTP_LDAP_BUFSZ], *data = NULL;
BIO *b64 = NULL, *bmem = NULL;
int chunklen;
long datalen = 0;
/* Add a base64 filter BIO, and read the data out, thus base64-decoding
* the key. Write the decoded data into another memory BIO.
*/
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bio = BIO_push(b64, bio);
bmem = BIO_new(BIO_s_mem());
memset(chunk, '\0', sizeof(chunk));
chunklen = BIO_read(bio, (void *) chunk, sizeof(chunk));
if (chunklen < 0 &&
!BIO_should_retry(bio)) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"unable to base64-decode RFC4716 key data from database: %s",
sftp_crypto_get_errors());
BIO_free_all(bio);
BIO_free_all(bmem);
errno = EPERM;
return -1;
}
while (chunklen > 0) {
pr_signals_handle();
if (BIO_write(bmem, (void *) chunk, chunklen) < 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error writing to memory BIO: %s", sftp_crypto_get_errors());
BIO_free_all(bio);
BIO_free_all(bmem);
errno = EPERM;
return -1;
}
memset(chunk, '\0', sizeof(chunk));
chunklen = BIO_read(bio, (void *) chunk, sizeof(chunk));
}
datalen = BIO_get_mem_data(bmem, &data);
if (data != NULL &&
datalen > 0) {
*key_datalen = datalen;
*key_data = palloc(p, datalen + 1);
(*key_data)[datalen] = '\0';
memcpy(*key_data, data, datalen);
res = 0;
} else {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error base64-decoding RFC4716 key data from LDAP directory");
errno = ENOENT;
res = -1;
}
BIO_free_all(bio);
bio = NULL;
BIO_free_all(bmem);
break;
}
if (bio != NULL &&
linelen > 0) {
size_t chunklen;
/* Watch out for any headers in the key data; we cannot handle those
* here. However, if we simply bail, it makes things difficult for the
* admin wishing to use the keys, as user authentication will fail.
*
* Thus we try some heuristics to avoid/skip the headers. The key data
* in which we are interested is base64-encoded. We thus iterate from
* the end of the line, looking for any non-base64 characters. If found,
* we ignore them.
*/
find_key_start(&line, &linelen);
chunklen = linelen;
/* Do NOT consume the end marker. */
if (linelen >= SFTP_LDAP_KEY_END_MARKER_LEN) {
size_t datalen;
datalen = linelen - SFTP_LDAP_KEY_END_MARKER_LEN;
if (strncmp(line + datalen, SFTP_SSH2_PUBKEY_END_MARKER, SFTP_LDAP_KEY_END_MARKER_LEN) == 0) {
/* Truncate the data to be written to the bio to not include the
* end marker.
*/
chunklen -= SFTP_LDAP_KEY_END_MARKER_LEN;
}
}
if (chunklen > 0) {
if (BIO_write(bio, line, chunklen) < 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error buffering base64 data: %s", sftp_crypto_get_errors());
}
linelen -= chunklen;
line += chunklen;
}
} else {
/* Consider this line consumed. */
linelen = 0;
}
/* Get the next line, but only if we're done with this one. */
if (linelen == 0) {
line = get_line(p, blob, bloblen);
while (line == NULL &&
errno == EINVAL) {
pr_signals_handle();
line = get_line(p, blob, bloblen);
}
}
}
/* Provide a default errno value if necessary. */
if (had_key_data == FALSE &&
res < 0) {
errno = ENOENT;
}
return res;
}
proftpd-mod_sftp_ldap-0.2/keys.h 0000664 0000000 0000000 00000002610 14215645241 0016771 0 ustar 00root root 0000000 0000000 /*
* ProFTPD - mod_sftp_ldap keys
* Copyright (c) 2016 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*
* As a special exemption, TJ Saunders and other respective copyright holders
* give permission to link this program with OpenSSL, and distribute the
* resulting executable, without including the source code for OpenSSL in the
* source distribution.
*/
#include "mod_sftp_ldap.h"
#ifndef MOD_SFTP_LDAP_KEYS_H
#define MOD_SFTP_LDAP_KEYS_H
int sftp_ldap_keys_parse_raw(pool *p, char **blob, size_t *bloblen,
unsigned char **key_data, uint32_t *key_datalen);
int sftp_ldap_keys_parse_rfc4716(pool *p, char **blob, size_t *bloblen,
unsigned char **key_data, uint32_t *key_datalen);
#endif /* MOD_SFTP_LDAP_KEYS_H */
proftpd-mod_sftp_ldap-0.2/mod_sftp_ldap.c 0000664 0000000 0000000 00000017025 14215645241 0020632 0 ustar 00root root 0000000 0000000 /*
* ProFTPD: mod_sftp_ldap -- LDAP backend module for retrieving authorized keys
* Copyright (c) 2010-2016 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* As a special exemption, the respective copyright holders give permission
* to link this program with OpenSSL, and distribute the resulting
* executable, without including the source code for OpenSSL in the source
* distribution.
*
* -----DO NOT EDIT BELOW THIS LINE-----
* $Archive: mod_sftp_ldap.a $
*/
#include "mod_sftp_ldap.h"
#include "keys.h"
module sftp_ldap_module;
static const char *trace_channel = "ssh2";
static int ldapstore_verify_key_raw(pool *p, int nrow, char *ldap_data,
size_t ldap_datalen, unsigned char *key_data, uint32_t key_datalen) {
unsigned char *parsed_data = NULL;
uint32_t parsed_datalen = 0;
int res;
res = sftp_ldap_keys_parse_raw(p, &ldap_data, &ldap_datalen, &parsed_data,
&parsed_datalen);
if (res < 0) {
pr_trace_msg(trace_channel, 10,
"unable to parse data (row %u) as raw key", nrow+1);
return -1;
}
res = sftp_keys_compare_keys(p, key_data, key_datalen, parsed_data,
parsed_datalen);
if (res < 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error comparing client-sent host key with LDAP data (row %u): %s",
nrow+1, strerror(errno));
} else if (res == FALSE) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"client-sent host key does not match LDAP data (row %u)", nrow+1);
res = -1;
} else {
res = 0;
}
return res;
}
static int ldapstore_verify_key_rfc4716(pool *p, int nrow, char *ldap_data,
size_t ldap_datalen, unsigned char *key_data, uint32_t key_datalen) {
unsigned char *parsed_data = NULL;
uint32_t parsed_datalen = 0;
int res;
res = sftp_ldap_keys_parse_rfc4716(p, &ldap_data, &ldap_datalen, &parsed_data,
&parsed_datalen);
while (res == 0) {
pr_signals_handle();
res = sftp_keys_compare_keys(p, key_data, key_datalen, parsed_data,
parsed_datalen);
if (res < 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error comparing client-sent key with LDAP data (row %u): %s",
nrow+1, strerror(errno));
parsed_data = NULL;
parsed_datalen = 0;
res = sftp_ldap_keys_parse_rfc4716(p, &ldap_data, &ldap_datalen,
&parsed_data, &parsed_datalen);
continue;
} else if (res == FALSE) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"client-sent key does not match LDAP data (row %u)", nrow+1);
parsed_data = NULL;
parsed_datalen = 0;
res = sftp_ldap_keys_parse_rfc4716(p, &ldap_data, &ldap_datalen,
&parsed_data, &parsed_datalen);
continue;
}
return 0;
}
return -1;
}
static int ldapstore_verify_user_key(sftp_keystore_t *store, pool *p,
const char *user, unsigned char *key_data, uint32_t key_datalen) {
register unsigned int i;
pool *tmp_pool;
cmdtable *ldap_cmdtab;
cmd_rec *ldap_cmd;
modret_t *ldap_res;
array_header *ldap_keys;
char **values;
int res;
/* Find the cmdtable for the ldap_ssh_publickey_lookup command. */
ldap_cmdtab = pr_stash_get_symbol(PR_SYM_HOOK, "ldap_ssh_publickey_lookup",
NULL, NULL);
if (ldap_cmdtab == NULL) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"unable to find LDAP hook symbol 'ldap_ssh_publickey_lookup'");
errno = EPERM;
return -1;
}
tmp_pool = make_sub_pool(store->keystore_pool);
ldap_cmd = pr_cmd_alloc(tmp_pool, 1, user);
ldap_res = pr_module_call(ldap_cmdtab->m, ldap_cmdtab->handler, ldap_cmd);
if (ldap_res == NULL ||
MODRET_ISERROR(ldap_res)) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"error performing LDAP search");
destroy_pool(tmp_pool);
errno = EPERM;
return -1;
}
ldap_keys = (array_header *) ldap_res->data;
if (ldap_keys->nelts == 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"LDAP search returned zero results");
destroy_pool(tmp_pool);
errno = ENOENT;
return -1;
} else {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_LDAP_VERSION,
"LDAP search returned %d %s", ldap_keys->nelts,
ldap_keys->nelts != 1 ? "keys" : "key");
}
values = (char **) ldap_keys->elts;
for (i = 0; i < ldap_keys->nelts; i++) {
char *ldap_data;
size_t ldap_datalen;
pr_signals_handle();
ldap_data = values[i];
ldap_datalen = strlen(values[i]);
res = ldapstore_verify_key_rfc4716(p, i, ldap_data, ldap_datalen, key_data,
key_datalen);
if (res == 0) {
pr_trace_msg(trace_channel, 10, "found matching RFC4716 public key "
"(row %u) for user '%s'", i+1, user);
destroy_pool(tmp_pool);
return 0;
}
res = ldapstore_verify_key_raw(p, i, ldap_data, ldap_datalen, key_data,
key_datalen);
if (res == 0) {
pr_trace_msg(trace_channel, 10,
"found matching public key (row %u) for user '%s'", i+1, user);
destroy_pool(tmp_pool);
return 0;
}
}
destroy_pool(tmp_pool);
errno = ENOENT;
return -1;
}
static int ldapstore_close(sftp_keystore_t *store) {
/* Nothing to do here. */
return 0;
}
static sftp_keystore_t *ldapstore_open(pool *parent_pool,
int requested_key_type, const char *store_info, const char *user) {
sftp_keystore_t *store;
pool *ldapstore_pool;
if (requested_key_type != SFTP_SSH2_USER_KEY_STORE) {
errno = EPERM;
return NULL;
}
ldapstore_pool = make_sub_pool(parent_pool);
pr_pool_tag(ldapstore_pool, "SFTP LDAP-based Keystore Pool");
store = pcalloc(ldapstore_pool, sizeof(sftp_keystore_t));
store->keystore_pool = ldapstore_pool;
store->store_ktypes = SFTP_SSH2_USER_KEY_STORE;
store->verify_user_key = ldapstore_verify_user_key;
store->store_close = ldapstore_close;
return store;
}
/* Event handlers
*/
#if defined(PR_SHARED_MODULE)
static void sftpldap_mod_unload_ev(const void *event_data, void *user_data) {
if (strcmp("mod_sftp_ldap.c", (const char *) event_data) == 0) {
sftp_keystore_unregister_store("ldap", SFTP_SSH2_USER_KEY_STORE);
pr_event_unregister(&sftp_ldap_module, NULL, NULL);
}
}
#endif /* PR_SHARED_MODULE */
/* Initialization routines
*/
static int sftpldap_init(void) {
sftp_keystore_register_store("ldap", ldapstore_open,
SFTP_SSH2_USER_KEY_STORE);
#if defined(PR_SHARED_MODULE)
pr_event_register(&sftp_ldap_module, "core.module-unload",
sftpldap_mod_unload_ev, NULL);
#endif /* PR_SHARED_MODULE */
return 0;
}
module sftp_ldap_module = {
NULL, NULL,
/* Module API version 2.0 */
0x20,
/* Module name */
"sftp_ldap",
/* Module configuration handler table */
NULL,
/* Module command handler table */
NULL,
/* Module authentication handler table */
NULL,
/* Module initialization function */
sftpldap_init,
/* Module child initialization function */
NULL,
/* Module version */
MOD_SFTP_LDAP_VERSION
};
proftpd-mod_sftp_ldap-0.2/mod_sftp_ldap.h.in 0000664 0000000 0000000 00000002527 14215645241 0021245 0 ustar 00root root 0000000 0000000 /*
* ProFTPD - mod_sftp_ldap
* Copyright (c) 2016 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*
* As a special exemption, TJ Saunders and other respective copyright holders
* give permission to link this program with OpenSSL, and distribute the
* resulting executable, without including the source code for OpenSSL in the
* source distribution.
*/
#ifndef MOD_SFTP_LDAP_H
#define MOD_SFTP_LDAP_H
#include "conf.h"
#include "mod_sftp.h"
#define MOD_SFTP_LDAP_VERSION "mod_sftp_ldap/0.2"
/* Make sure the version of proftpd is as necessary. */
#if PROFTPD_VERSION_NUMBER < 0x0001030602
# error "ProFTPD 1.3.6rc2 or later required"
#endif
#endif /* MOD_SFTP_LDAP_H */
proftpd-mod_sftp_ldap-0.2/mod_sftp_ldap.html 0000664 0000000 0000000 00000010353 14215645241 0021351 0 ustar 00root root 0000000 0000000
ProFTPD module mod_sftp_ldap
ProFTPD module mod_sftp_ldap
The mod_sftp
module for ProFTPD can support different storage formats for
its user- and host-based authorized keys. By default, the mod_sftp
module supports storing authorized keys in flats. This
mod_sftp_ldap
module allows for authorized SSH keys to be stored
in LDAP directories.
This module is contained in the mod_sftp_ldap.c
file for
ProFTPD 1.3.x, and is not compiled by default. Installation
instructions are discussed here.
The most current version of mod_sftp_ldap
can be found at:
http://www.castaglia.org/proftpd/
This product includes software developed by the OpenSSL Project for use in the
OpenSSL Toolkit (http://www.openssl.org/).
This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).
Author
Please contact TJ Saunders <tj at castaglia.org> with any
questions, concerns, or suggestions regarding this module.
To install mod_sftp_ldap
, go to the third-party module area in
the proftpd source code and unpack the mod_sftp_ldap
source
tarball:
$ cd proftpd-dir/contrib/
$ tar zxvf /path/to/mod_sftp_ldap-version.tar.gz
after unpacking the latest proftpd-1.3.x source code. Then follow the
usual steps for using third-party modules in proftpd, making sure to include
the mod_sftp
and mod_ldap
modules, which
mod_sftp_ldap
requires. For including
mod_sftp_ldap
as a staticly linked module:
$ ./configure --with-modules=mod_ldap:mod_sftp:mod_sftp_ldap ...
$ make
$ make install
The mod_sftp_ldap
module works by using hooks in the
mod_ldap
module code to retrieve authorized user keys during
the LDAP queries. Thus the mod_sftp_ldap
module has no
configuration directives of its own.
To help demonstrate, see the example configuration below:
<IfModule mod_ldap.c>
# mod_ldap configuration here
</IfModule>
<IfModule mod_sftp.c>
SFTPEngine on
SFTPLog /path/to/sftp.log
# Host keys, for server host authentication
SFTPHostKey /etc/ssh_host_dsa_key
SFTPHostKey /etc/ssh_host_rsa_key
<IfModule mod_sftp_ldap.c>
# Instead of using a file-based key store, we tell mod_sftp to use
# the LDAP-based key store provided by mod_sftp_ldap
SFTPAuthorizedUserKeys ldap:
</IfModule>
</IfModule>
What should the schema be, for the directory entry which holds these authorized
keys? The mod_sftp_ldap
module assumes a posixAccount
user entry with an ldapPublicKey
objectclass and
sshPublicKey
attributes; multiple sshPublicKey
attributes are allowed.
Example LDIF:
dn: uid=foo,ou=users,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: posixAccount
objectClass: ldapPublicKey
description: John Doe Account
userPassword: {crypt}0LXhFAsrBWEEQ
cn: John Doe
sn: John Doe
uid: foo
uidNumber: 1234
gidNumber: 123
homeDirectory: /home/foo
sshPublicKey: ---- BEGIN SSH2 PUBLIC KEY ---- ...
sshPublicKey: ---- BEGIN SSH2 PUBLIC KEY ---- ...
Which leads to the next question: how can I transfer existing authorized
SSH keys from their current flat files into the LDAP entries? First, you need
to make sure that the key is in the RFC4716 format, using:
$ ssh-keygen -e -f /path/to/key.pub
Then simply add the output data to your LDAP entry's sshPublicKey
attribute.
© Copyright 2010-2020 TJ Saunders
All Rights Reserved
proftpd-mod_sftp_ldap-0.2/t/ 0000775 0000000 0000000 00000000000 14215645241 0016111 5 ustar 00root root 0000000 0000000 proftpd-mod_sftp_ldap-0.2/t/Makefile.in 0000664 0000000 0000000 00000003206 14215645241 0020157 0 ustar 00root root 0000000 0000000 CC=@CC@
@SET_MAKE@
top_builddir=../../..
top_srcdir=../../..
module_srcdir=..
srcdir=@srcdir@
VPATH=@srcdir@
include $(top_srcdir)/Make.rules
# Necessary redefinitions
INCLUDES=-I. -I.. -I$(module_srcdir)/include -I../../.. -I../../../include @INCLUDES@
TEST_CPPFLAGS=$(ADDL_CPPFLAGS) -DHAVE_CONFIG_H $(DEFAULT_PATHS) $(PLATFORM) $(INCLUDES)
TEST_LDFLAGS=-L$(top_srcdir)/lib @LIBDIRS@
EXEEXT=@EXEEXT@
TEST_API_DEPS=\
$(top_srcdir)/lib/prbase.a \
$(top_srcdir)/src/pool.o \
$(top_srcdir)/src/privs.o \
$(top_srcdir)/src/str.o \
$(top_srcdir)/src/sets.o \
$(top_srcdir)/src/table.o \
$(top_srcdir)/src/netacl.o \
$(top_srcdir)/src/class.o \
$(top_srcdir)/src/event.o \
$(top_srcdir)/src/timers.o \
$(top_srcdir)/src/stash.o \
$(top_srcdir)/src/modules.o \
$(top_srcdir)/src/cmd.o \
$(top_srcdir)/src/configdb.o \
$(top_srcdir)/src/parser.o \
$(top_srcdir)/src/regexp.o \
$(top_srcdir)/src/fsio.o \
$(top_srcdir)/src/netio.o \
$(top_srcdir)/src/inet.o \
$(top_srcdir)/src/netaddr.o \
$(top_srcdir)/src/response.o \
$(top_srcdir)/src/auth.o \
$(top_srcdir)/src/env.o \
$(top_srcdir)/src/trace.o \
$(top_srcdir)/src/support.o \
$(top_srcdir)/src/error.o \
$(module_srcdir)/keys.o
TEST_API_LIBS=-lcheck -lm
TEST_API_OBJS=\
api/keys.o \
api/stubs.o \
api/tests.o
dummy:
api/.c.o:
$(CC) $(CPPFLAGS) $(TEST_CPPFLAGS) $(CFLAGS) -c $<
api-tests$(EXEEXT): $(TEST_API_OBJS) $(TEST_API_DEPS)
$(LIBTOOL) --mode=link --tag=CC $(CC) $(LDFLAGS) $(TEST_LDFLAGS) -o $@ $(TEST_API_DEPS) $(TEST_API_OBJS) $(TEST_API_LIBS) $(LIBS)
./$@
clean:
$(LIBTOOL) --mode=clean $(RM) *.o api/*.o api-tests$(EXEEXT) api-tests.log
proftpd-mod_sftp_ldap-0.2/t/api/ 0000775 0000000 0000000 00000000000 14215645241 0016662 5 ustar 00root root 0000000 0000000 proftpd-mod_sftp_ldap-0.2/t/api/NOTES 0000664 0000000 0000000 00000000522 14215645241 0017474 0 ustar 00root root 0000000 0000000 We can create a fake HOOK, as provided by mod_ldap, for supplying the necessary
key data to mod_sftp_ldap. Next, then, how to exercise those functions
for parsing/extracting keys from that data?
And how to do these tests, when there is no top-level configure script? We
just need a Makefile (right)? Maybe provide a configure script?
proftpd-mod_sftp_ldap-0.2/t/api/keys.c 0000664 0000000 0000000 00000025740 14215645241 0020011 0 ustar 00root root 0000000 0000000 /*
* ProFTPD - mod_sftp_ldap testsuite
* Copyright (c) 2016 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*
* As a special exemption, TJ Saunders and other respective copyright holders
* give permission to link this program with OpenSSL, and distribute the
* resulting executable, without including the source code for OpenSSL in the
* source distribution.
*/
/* Key-parsing tests. */
#include "tests.h"
#include "keys.h"
static pool *p = NULL;
static const char *raw_key = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7jGx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00ydqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84uO6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMmef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPkByq2pv4VBo953gK7f1AQ== tj@Imp.local";
static const char *rfc4716_single_line_key =
"---- BEGIN SSH2 PUBLIC KEY ----"
"AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7j"
"Gx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00y"
"dqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84u"
"O6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMm"
"ef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPk"
"Byq2pv4VBo953gK7f1AQ=="
"---- END SSH2 PUBLIC KEY ----";
static const char *rfc4716_single_line_key_with_comment =
"---- BEGIN SSH2 PUBLIC KEY ----"
"Comment: \"2048-bit RSA, converted from OpenSSH by tj@Imp.local\""
"AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7j"
"Gx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00y"
"dqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84u"
"O6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMm"
"ef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPk"
"Byq2pv4VBo953gK7f1AQ=="
"---- END SSH2 PUBLIC KEY ----";
static const char *rfc4716_single_line_key_with_xtag =
"---- BEGIN SSH2 PUBLIC KEY ----"
"X-Tag: Foo Bar"
"AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7j"
"Gx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00y"
"dqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84u"
"O6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMm"
"ef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPk"
"Byq2pv4VBo953gK7f1AQ=="
"---- END SSH2 PUBLIC KEY ----";
static const char *rfc4716_multi_line_key =
"---- BEGIN SSH2 PUBLIC KEY ----\n"
"AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7j\n"
"Gx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00y\n"
"dqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84u\n"
"O6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMm\n"
"ef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPk\n"
"Byq2pv4VBo953gK7f1AQ==\n"
"---- END SSH2 PUBLIC KEY ----\n";
static const char *rfc4716_multi_line_key_with_comment =
"---- BEGIN SSH2 PUBLIC KEY ----\n"
"Comment: \"2048-bit RSA, converted from OpenSSH by tj@Imp.local\"\n"
"AAAAB3NzaC1yc2EAAAABIwAAAQEAzJ1CLwnVP9mUa8uyM+XBzxLxsRvGz4cS59aPTgdw7j\n"
"Gx1jCvC9ya400x7ej5Q4ubwlAAPblXzG5GYv2ROmYQ1DIjrhmR/61tDKUvAAZIgtvLZ00y\n"
"dqqpq5lG4ubVJ4gW6sxbPfq/X12kV1gxGsFLUJCgoYInZGyIONrnvmQjFIfIx+mQXaK84u\n"
"O6w0CT6KhRWgonajMrlO6P8O7qr80rFmOZsBNIMooyYrGTaMyxVsQK2SY+VKbXWFC+2HMm\n"
"ef62n+02ohAOBKtOsSOn8HE2wi7yMA0g8jRTd8kZcWBIkAhizPvl8pqG1F0DCmLn00rhPk\n"
"Byq2pv4VBo953gK7f1AQ==\n"
"---- END SSH2 PUBLIC KEY ----\n";
static void set_up(void) {
if (p == NULL) {
sftp_pool = p = make_sub_pool(NULL);
}
if (getenv("TEST_VERBOSE") != NULL) {
pr_trace_set_levels("ssh2", 1, 20);
}
}
static void tear_down(void) {
if (getenv("TEST_VERBOSE") != NULL) {
pr_trace_set_levels("ssh2", 0, 0);
}
if (p) {
destroy_pool(p);
sftp_pool = p = NULL;
}
}
START_TEST (keys_parse_raw_invalid_params_test) {
int res;
char *blob = NULL;
size_t bloblen = 0;
unsigned char *key_data = NULL;
res = sftp_ldap_keys_parse_raw(NULL, NULL, NULL, NULL, NULL);
fail_unless(res < 0, "Failed to handle null pool");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
res = sftp_ldap_keys_parse_raw(p, NULL, NULL, NULL, NULL);
fail_unless(res < 0, "Failed to handle null blob");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
res = sftp_ldap_keys_parse_raw(p, &blob, NULL, NULL, NULL);
fail_unless(res < 0, "Failed to handle null bloblen");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
res = sftp_ldap_keys_parse_raw(p, &blob, &bloblen, NULL, NULL);
fail_unless(res < 0, "Failed to handle null key data");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
res = sftp_ldap_keys_parse_raw(p, &blob, &bloblen, &key_data, NULL);
fail_unless(res < 0, "Failed to handle null key datalen");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
}
END_TEST
START_TEST (keys_parse_raw_single_line_test) {
int res;
char *blob;
size_t bloblen;
unsigned char *key_data = NULL;
uint32_t key_datalen = 0;
blob = "foo\n";
bloblen = strlen(blob);
res = sftp_ldap_keys_parse_raw(p, &blob, &bloblen, &key_data, &key_datalen);
fail_unless(res < 0, "Failed to handle invalid raw key");
fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
strerror(errno), errno);
blob = pstrdup(p, raw_key);
bloblen = strlen(raw_key);
key_data = NULL;
key_datalen = 0;
res = sftp_ldap_keys_parse_raw(p, &blob, &bloblen, &key_data, &key_datalen);
fail_unless(res == 0, "Failed to handle valid raw key: %s", strerror(errno));
}
END_TEST
START_TEST (keys_parse_rfc4716_invalid_params_test) {
int res;
char *blob = NULL;
size_t bloblen = 0;
unsigned char *key_data = NULL;
res = sftp_ldap_keys_parse_rfc4716(NULL, NULL, NULL, NULL, NULL);
fail_unless(res < 0, "Failed to handle null pool");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
res = sftp_ldap_keys_parse_rfc4716(p, NULL, NULL, NULL, NULL);
fail_unless(res < 0, "Failed to handle null blob");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
res = sftp_ldap_keys_parse_rfc4716(p, &blob, NULL, NULL, NULL);
fail_unless(res < 0, "Failed to handle null bloblen");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, NULL, NULL);
fail_unless(res < 0, "Failed to handle null key data");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, &key_data, NULL);
fail_unless(res < 0, "Failed to handle null key datalen");
fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
strerror(errno), errno);
}
END_TEST
START_TEST (keys_parse_rfc4716_single_line_test) {
int res;
char *blob;
size_t bloblen;
unsigned char *key_data = NULL;
uint32_t key_datalen = 0;
blob = "foo\n";
bloblen = strlen(blob);
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, &key_data,
&key_datalen);
fail_unless(res < 0, "Failed to handle invalid RFC 4716 key");
fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
strerror(errno), errno);
blob = pstrdup(p, rfc4716_single_line_key_with_comment);
bloblen = strlen(rfc4716_single_line_key_with_comment);
key_data = NULL;
key_datalen = 0;
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, &key_data,
&key_datalen);
fail_unless(res == 0,
"Failed to handle RFC 4716 key with Comment header: %s", strerror(errno));
blob = pstrdup(p, rfc4716_single_line_key_with_xtag);
bloblen = strlen(rfc4716_single_line_key_with_xtag);
key_data = NULL;
key_datalen = 0;
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, &key_data,
&key_datalen);
fail_unless(res == 0,
"Failed to handle RFC 4716 key with X-Tag header: %s", strerror(errno));
blob = pstrdup(p, rfc4716_single_line_key);
bloblen = strlen(rfc4716_single_line_key);
key_data = NULL;
key_datalen = 0;
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, &key_data,
&key_datalen);
fail_unless(res == 0, "Failed to handle valid RFC 4716 key: %s",
strerror(errno));
}
END_TEST
START_TEST (keys_parse_rfc4716_multi_line_test) {
int res;
char *blob;
size_t bloblen;
unsigned char *key_data = NULL;
uint32_t key_datalen = 0;
blob = "foo\n";
bloblen = strlen(blob);
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, &key_data,
&key_datalen);
fail_unless(res < 0, "Failed to handle invalid RFC 4716 key");
fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
strerror(errno), errno);
blob = pstrdup(p, rfc4716_multi_line_key_with_comment);
bloblen = strlen(rfc4716_multi_line_key_with_comment);
key_data = NULL;
key_datalen = 0;
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, &key_data,
&key_datalen);
fail_unless(res == 0,
"Failed to handle RFC 4716 key with Comment header: %s", strerror(errno));
blob = pstrdup(p, rfc4716_multi_line_key);
bloblen = strlen(rfc4716_multi_line_key);
key_data = NULL;
key_datalen = 0;
res = sftp_ldap_keys_parse_rfc4716(p, &blob, &bloblen, &key_data,
&key_datalen);
fail_unless(res == 0, "Failed to handle valid RFC 4716 key: %s",
strerror(errno));
}
END_TEST
Suite *tests_get_keys_suite(void) {
Suite *suite;
TCase *testcase;
suite = suite_create("keys");
testcase = tcase_create("base");
tcase_add_checked_fixture(testcase, set_up, tear_down);
tcase_add_test(testcase, keys_parse_raw_invalid_params_test);
tcase_add_test(testcase, keys_parse_raw_single_line_test);
tcase_add_test(testcase, keys_parse_rfc4716_invalid_params_test);
tcase_add_test(testcase, keys_parse_rfc4716_single_line_test);
tcase_add_test(testcase, keys_parse_rfc4716_multi_line_test);
suite_add_tcase(suite, testcase);
return suite;
}
proftpd-mod_sftp_ldap-0.2/t/api/stubs.c 0000664 0000000 0000000 00000011155 14215645241 0020171 0 ustar 00root root 0000000 0000000 /*
* ProFTPD - mod_sftp_ldap API testsuite
* Copyright (c) 2016-2020 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*
* As a special exemption, TJ Saunders and other respective copyright holders
* give permission to link this program with OpenSSL, and distribute the
* resulting executable, without including the source code for OpenSSL in the
* source distribution.
*/
#include "tests.h"
/* Stubs */
session_t session;
int ServerUseReverseDNS = FALSE;
server_rec *main_server = NULL;
pid_t mpid = 1;
unsigned char is_master = TRUE;
volatile unsigned int recvd_signal_flags = 0;
module *static_modules[] = { NULL };
module *loaded_modules = NULL;
xaset_t *server_list = NULL;
int sftp_logfd = -1;
pool *sftp_pool = NULL;
static cmd_rec *next_cmd = NULL;
int login_check_limits(xaset_t *set, int recurse, int and, int *found) {
return TRUE;
}
int xferlog_open(const char *path) {
return 0;
}
int pr_cmd_read(cmd_rec **cmd) {
if (next_cmd != NULL) {
*cmd = next_cmd;
next_cmd = NULL;
} else {
errno = ENOENT;
*cmd = NULL;
}
return 0;
}
int pr_config_get_server_xfer_bufsz(int direction) {
int bufsz = -1;
switch (direction) {
case PR_NETIO_IO_RD:
bufsz = PR_TUNABLE_DEFAULT_RCVBUFSZ;
break;
case PR_NETIO_IO_WR:
bufsz = PR_TUNABLE_DEFAULT_SNDBUFSZ;
break;
default:
errno = EINVAL;
return -1;
}
return bufsz;
}
void pr_log_auth(int priority, const char *fmt, ...) {
if (getenv("TEST_VERBOSE") != NULL) {
va_list msg;
fprintf(stderr, "AUTH: ");
va_start(msg, fmt);
vfprintf(stderr, fmt, msg);
va_end(msg);
fprintf(stderr, "\n");
}
}
void pr_log_debug(int level, const char *fmt, ...) {
if (getenv("TEST_VERBOSE") != NULL) {
va_list msg;
fprintf(stderr, "DEBUG%d: ", level);
va_start(msg, fmt);
vfprintf(stderr, fmt, msg);
va_end(msg);
fprintf(stderr, "\n");
}
}
int pr_log_event_generate(unsigned int log_type, int log_fd, int log_level,
const char *log_msg, size_t log_msglen) {
errno = ENOSYS;
return -1;
}
int pr_log_event_listening(unsigned int log_type) {
return FALSE;
}
int pr_log_openfile(const char *log_file, int *log_fd, mode_t log_mode) {
int res;
struct stat st;
if (log_file == NULL ||
log_fd == NULL) {
errno = EINVAL;
return -1;
}
res = stat(log_file, &st);
if (res < 0) {
if (errno != ENOENT) {
return -1;
}
} else {
if (S_ISDIR(st.st_mode)) {
errno = EISDIR;
return -1;
}
}
*log_fd = STDERR_FILENO;
return 0;
}
void pr_log_pri(int prio, const char *fmt, ...) {
if (getenv("TEST_VERBOSE") != NULL) {
va_list msg;
fprintf(stderr, "PRI%d: ", prio);
va_start(msg, fmt);
vfprintf(stderr, fmt, msg);
va_end(msg);
fprintf(stderr, "\n");
}
}
void pr_log_stacktrace(int fd, const char *name) {
}
int pr_log_writefile(int fd, const char *name, const char *fmt, ...) {
if (getenv("TEST_VERBOSE") != NULL) {
va_list msg;
fprintf(stderr, "%s: ", name);
va_start(msg, fmt);
vfprintf(stderr, fmt, msg);
va_end(msg);
fprintf(stderr, "\n");
}
return 0;
}
int pr_scoreboard_entry_update(pid_t pid, ...) {
return 0;
}
void pr_session_disconnect(module *m, int reason_code, const char *details) {
}
void pr_session_end(int flags) {
}
const char *pr_session_get_protocol(int flags) {
return "ftp";
}
int pr_session_set_protocol(const char *proto) {
return 0;
}
void pr_signals_handle(void) {
}
/* Module-specific stubs */
const char *sftp_crypto_get_errors(void) {
return "(to be implemented)";
}
int sftp_keys_compare_keys(pool *p,
unsigned char *remote_data, uint32_t remote_datalen,
unsigned char *local_data, uint32_t local_datalen) {
errno = ENOSYS;
return -1;
}
int sftp_keystore_register_store(const char *store_type,
sftp_keystore_t *(store_open)(pool *, int, const char *, const char *),
unsigned int store_ktypes) {
errno = ENOSYS;
return -1;
}
proftpd-mod_sftp_ldap-0.2/t/api/tests.c 0000664 0000000 0000000 00000006575 14215645241 0020205 0 ustar 00root root 0000000 0000000 /*
* ProFTPD - mod_sftp_ldap API testsuite
* Copyright (c) 2016 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*
* As a special exemption, TJ Saunders and other respective copyright holders
* give permission to link this program with OpenSSL, and distribute the
* resulting executable, without including the source code for OpenSSL in the
* source distribution.
*/
#include "tests.h"
struct testsuite_info {
const char *name;
Suite *(*get_suite)(void);
};
static struct testsuite_info suites[] = {
{ "keys", tests_get_keys_suite },
{ NULL, NULL }
};
static Suite *tests_get_suite(const char *suite) {
register unsigned int i;
for (i = 0; suites[i].name != NULL; i++) {
if (strcmp(suite, suites[i].name) == 0) {
return (*suites[i].get_suite)();
}
}
errno = ENOENT;
return NULL;
}
int main(int argc, char *argv[]) {
const char *log_file = "api-tests.log";
int nfailed = 0;
SRunner *runner = NULL;
char *requested = NULL;
runner = srunner_create(NULL);
/* XXX This log name should be set outside this code, e.g. via environment
* variable or command-line option.
*/
srunner_set_log(runner, log_file);
requested = getenv("SFTP_LDAP_TEST_SUITE");
if (requested) {
Suite *suite;
suite = tests_get_suite(requested);
if (suite) {
srunner_add_suite(runner, suite);
} else {
fprintf(stderr,
"No such test suite ('%s') requested via SFTP_LDAP_TEST_SUITE\n",
requested);
return EXIT_FAILURE;
}
} else {
register unsigned int i;
for (i = 0; suites[i].name; i++) {
Suite *suite;
suite = (suites[i].get_suite)();
if (suite) {
srunner_add_suite(runner, suite);
}
}
}
/* Configure the Trace API to write to stderr. */
pr_trace_use_stderr(TRUE);
requested = getenv("SFTP_LDAP_TEST_NOFORK");
if (requested) {
srunner_set_fork_status(runner, CK_NOFORK);
} else {
requested = getenv("CK_DEFAULT_TIMEOUT");
if (requested == NULL) {
setenv("CK_DEFAULT_TIMEOUT", "60", 1);
}
}
srunner_run_all(runner, CK_NORMAL);
nfailed = srunner_ntests_failed(runner);
if (runner)
srunner_free(runner);
if (nfailed != 0) {
fprintf(stderr, "-------------------------------------------------\n");
fprintf(stderr, " FAILED %d %s\n\n", nfailed,
nfailed != 1 ? "tests" : "test");
fprintf(stderr, " Please send email to:\n\n");
fprintf(stderr, " tj@castaglia.org\n\n");
fprintf(stderr, " containing the `%s' file (in the t/ directory)\n", log_file);
fprintf(stderr, " and the output from running `proftpd -V'\n");
fprintf(stderr, "-------------------------------------------------\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
proftpd-mod_sftp_ldap-0.2/t/api/tests.h 0000664 0000000 0000000 00000002727 14215645241 0020205 0 ustar 00root root 0000000 0000000 /*
* ProFTPD - mod_sftp_ldap API testsuite
* Copyright (c) 2016-2020 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*
* As a special exemption, TJ Saunders and other respective copyright holders
* give permission to link this program with OpenSSL, and distribute the
* resulting executable, without including the source code for OpenSSL in the
* source distribution.
*/
/* Testsuite management */
#ifndef MOD_SFTP_LDAP_TESTS_H
#define MOD_SFTP_LDAP_TESTS_H
#include "mod_sftp_ldap.h"
#ifdef HAVE_CHECK_H
# include
#else
# error "Missing Check installation; necessary for ProFTPD testsuite"
#endif
Suite *tests_get_keys_suite(void);
extern volatile unsigned int recvd_signal_flags;
extern pid_t mpid;
extern server_rec *main_server;
#endif /* MOD_SFTP_LDAP_TESTS_H */