Skip to content

Commit

Permalink
Adding mod_sftp to the contrib modules.
Browse files Browse the repository at this point in the history
  • Loading branch information
castaglia committed Feb 13, 2009
1 parent 78e2223 commit a312d87
Show file tree
Hide file tree
Showing 58 changed files with 31,565 additions and 0 deletions.
10 changes: 10 additions & 0 deletions contrib/mod_sftp/.cvsignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
configure
Makefile
config.log
config.status
autom4te.cache
mod_sftp.h
.libs
*.la
*.o
*~
58 changes: 58 additions & 0 deletions contrib/mod_sftp/Makefile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
top_builddir=../..
top_srcdir=../../
srcdir=@srcdir@

include $(top_srcdir)/Make.rules

.SUFFIXES: .la .lo

SHARED_CFLAGS=-DPR_SHARED_MODULE
SHARED_LDFLAGS=-avoid-version -export-dynamic -module
VPATH=@srcdir@

MODULE_NAME=mod_sftp
MODULE_OBJS=mod_sftp.o msg.o packet.o cipher.o mac.o compress.o kex.o keys.o \
crypto.o utf8.o session.o service.o kbdint.o auth-hostbased.o auth-kbdint.o \
auth-password.o auth-publickey.o auth.o disconnect.o rfc4716.o keystore.o \
channel.o blacklist.o interop.o tap.o fxp.o scp.o
SHARED_MODULE_OBJS=mod_sftp.lo msg.lo packet.lo cipher.lo mac.lo \
compress.lo kex.lo keys.lo crypto.lo utf8.lo session.lo service.lo kbdint.lo \
auth-hostbased.lo auth-kbdint.lo auth-password.lo auth-publickey.lo auth.lo \
disconnect.lo rfc4716.lo keystore.lo channel.lo blacklist.lo interop.lo \
tap.lo fxp.lo scp.lo

# Necessary redefinitions
INCLUDES=-I. -I../.. -I../../include @INCLUDES@
CPPFLAGS= -DHAVE_CONFIG_H $(DEFAULT_PATHS) $(PLATFORM) $(INCLUDES)
LDFLAGS=-L../../lib @LIBDIRS@

.c.o:
$(CC) $(CPPFLAGS) $(CFLAGS) -c $<

.c.lo:
$(LIBTOOL) --mode=compile --tag=CC $(CC) $(CPPFLAGS) $(CFLAGS) $(SHARED_CFLAGS) -c $<

shared: $(SHARED_MODULE_OBJS)
$(LIBTOOL) --mode=link --tag=CC $(CC) -o $(MODULE_NAME).la $(SHARED_MODULE_OBJS) -rpath $(LIBEXECDIR) $(LDFLAGS) $(SHARED_LDFLAGS) $(SHARED_MODULE_LIBS) `cat $(MODULE_NAME).c | grep '$$Libraries:' | sed -e 's/^.*\$$Libraries: \(.*\)\\$$/\1/'`

static: $(MODULE_OBJS)
$(AR) rc $(MODULE_NAME).a $(MODULE_NAME).o $(MODULE_OBJS)
$(RANLIB) $(MODULE_NAME).a

install: install-misc
if [ -f $(MODULE_NAME).la ] ; then \
$(LIBTOOL) --mode=install --tag=CC $(INSTALL_BIN) $(MODULE_NAME).la $(DESTDIR)$(LIBEXECDIR) ; \
fi

install-misc:
$(INSTALL) -o $(INSTALL_USER) -g $(INSTALL_GROUP) -m 0644 dhparams.pem $(DESTDIR)$(sysconfdir)/dhparams.pem
$(INSTALL) -o $(INSTALL_USER) -g $(INSTALL_GROUP) -m 0644 blacklist.dat $(DESTDIR)$(sysconfdir)/blacklist.dat

clean:
$(RM) $(MODULE_NAME).a *.o *.la *.lo
$(LIBTOOL) --mode=clean $(RM) "$(MODULE_NAME).o"
$(LIBTOOL) --mode=clean $(RM) `echo "$(MODULE_NAME).la" | sed 's/\.la$\/.lo/g'`

dist: clean
$(RM) Makefile mod_sftp.h config.status config.cache config.log
-$(RM) -r .libs/ CVS/ RCS/
175 changes: 175 additions & 0 deletions contrib/mod_sftp/auth-hostbased.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* ProFTPD - mod_sftp 'hostbased' user authentication
* Copyright (c) 2008-2009 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, 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.h"
#include "ssh2.h"
#include "packet.h"
#include "msg.h"
#include "auth.h"
#include "session.h"
#include "keys.h"
#include "keystore.h"
#include "interop.h"
#include "blacklist.h"
#include "utf8.h"

static const char *trace_channel = "ssh2";

int sftp_auth_hostbased(struct ssh2_packet *pkt, const char *user,
const char *service, char **buf, uint32_t *buflen,
int *send_userauth_fail) {
struct passwd *pw;
char *hostkey_algo, *host_fqdn, *host_user, *host_user_utf8;
char *hostkey_data, *signature_data;
char *buf2, *ptr2;
const unsigned char *id;
uint32_t buflen2, bufsz2, hostkey_datalen, id_len, signature_len;
int pubkey_type;

hostkey_algo = sftp_msg_read_string(pkt->pool, buf, buflen);

hostkey_datalen = sftp_msg_read_int(pkt->pool, buf, buflen);
hostkey_data = sftp_msg_read_data(pkt->pool, buf, buflen, hostkey_datalen);

host_fqdn = sftp_msg_read_string(pkt->pool, buf, buflen);

host_user_utf8 = sftp_msg_read_string(pkt->pool, buf, buflen);
host_user = sftp_utf8_decode_str(pkt->pool, host_user_utf8);

signature_len = sftp_msg_read_int(pkt->pool, buf, buflen);
signature_data = sftp_msg_read_data(pkt->pool, buf, buflen, signature_len);

pr_trace_msg(trace_channel, 9,
"client sent '%s' host key, FQDN %s, and remote user '%s'",
hostkey_algo, host_fqdn, host_user);

if (strcmp(hostkey_algo, "ssh-rsa") == 0) {
pubkey_type = EVP_PKEY_RSA;

} else if (strcmp(hostkey_algo, "ssh-dss") == 0) {
pubkey_type = EVP_PKEY_DSA;

/* XXX Need to support X509v3 certs here */

} else {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"unsupported host key algorithm '%s' requested, rejecting request",
hostkey_algo);

*send_userauth_fail = TRUE;
errno = EINVAL;
return 0;
}

if (sftp_keys_verify_pubkey_type(pkt->pool, hostkey_data, hostkey_datalen,
pubkey_type) != TRUE) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"unable to verify that given host key matches given '%s' algorithm",
hostkey_algo);

*send_userauth_fail = TRUE;
errno = EINVAL;
return 0;
}

(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"public key fingerprint: %s",
sftp_keys_get_fingerprint(pkt->pool, hostkey_data, hostkey_datalen,
SFTP_KEYS_FP_DIGEST_MD5));

pw = pr_auth_getpwnam(pkt->pool, user);
if (pw == NULL) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"no account for user '%s' found", user);

pr_log_auth(PR_LOG_NOTICE,
"USER %s: no such user found from %s [%s] to %s:%d", user,
session.c->remote_name, pr_netaddr_get_ipstr(session.c->remote_addr),
pr_netaddr_get_ipstr(session.c->local_addr), session.c->local_port);

*send_userauth_fail = TRUE;
errno = ENOENT;
return 0;
}

/* XXX Should we check the given FQDN here against the client's actual
* DNS name and/or IP address? Or leave that up to the keystore's
* verify_host_key() function?
*/

if (sftp_blacklist_reject_key(pkt->pool, hostkey_data, hostkey_datalen)) {
*send_userauth_fail = TRUE;
errno = EPERM;
return 0;
}

/* The client signed the request as well; we need to authenticate the
* host with the given key now. If that succeeds, we use the signature to
* verify the request. And if that succeeds, then we're done authenticating.
*/

if (sftp_keystore_verify_host_key(pkt->pool, user, host_fqdn, host_user,
hostkey_data, hostkey_datalen) < 0) {
*send_userauth_fail = TRUE;
errno = EPERM;
return 0;
}

/* Make sure the signature matches as well. */

id_len = sftp_session_get_id(&id);

/* XXX Is this buffer large enough? Too large? */
bufsz2 = buflen2 = 2048;
ptr2 = buf2 = sftp_msg_getbuf(pkt->pool, bufsz2);

sftp_msg_write_data(&buf2, &buflen2, (char *) id, id_len, TRUE);
sftp_msg_write_byte(&buf2, &buflen2, SFTP_SSH2_MSG_USER_AUTH_REQUEST);
sftp_msg_write_string(&buf2, &buflen2, user);

if (sftp_interop_supports_feature(SFTP_SSH2_FEAT_SERVICE_IN_HOST_SIG)) {
sftp_msg_write_string(&buf2, &buflen2, service);

} else {
sftp_msg_write_string(&buf2, &buflen2, "ssh-userauth");
}

sftp_msg_write_string(&buf2, &buflen2, "hostbased");
sftp_msg_write_string(&buf2, &buflen2, hostkey_algo);
sftp_msg_write_data(&buf2, &buflen2, hostkey_data, hostkey_datalen, TRUE);
sftp_msg_write_string(&buf2, &buflen2, host_fqdn);
sftp_msg_write_string(&buf2, &buflen2, host_user_utf8);

if (sftp_keys_verify_signed_data(pkt->pool, hostkey_algo, hostkey_data,
hostkey_datalen, signature_data, signature_len, (unsigned char *) ptr2,
(bufsz2 - buflen2)) < 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"failed to verify '%s' signature on hostbased auth request for "
"user '%s', host %s", hostkey_algo, user, host_fqdn);
*send_userauth_fail = TRUE;
return 0;
}

return 1;
}
133 changes: 133 additions & 0 deletions contrib/mod_sftp/auth-kbdint.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* ProFTPD - mod_sftp 'keyboard-interactive' user authentication
* Copyright (c) 2008 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, 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.h"
#include "ssh2.h"
#include "packet.h"
#include "auth.h"
#include "msg.h"
#include "cipher.h"
#include "mac.h"
#include "utf8.h"
#include "kbdint.h"

static const char *trace_channel = "ssh2";

int sftp_auth_kbdint(struct ssh2_packet *pkt, const char *user,
const char *service, char **buf, uint32_t *buflen,
int *send_userauth_fail) {
const char *cipher_algo, *mac_algo;
struct passwd *pw;
char *submethods;
sftp_kbdint_driver_t *driver;
int res = -1;

if (sftp_kbdint_have_drivers() == 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"no 'keyboard-interactive' drivers currently registered, unable to "
"authenticate user '%s' via 'keyboard-interactive' method", user);

*send_userauth_fail = TRUE;
errno = EPERM;
return 0;
}

pw = pr_auth_getpwnam(pkt->pool, user);
if (pw == NULL) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"no account for user '%s' found", user);

pr_log_auth(PR_LOG_NOTICE,
"USER %s: no such user found from %s [%s] to %s:%d", user,
session.c->remote_name, pr_netaddr_get_ipstr(session.c->remote_addr),
pr_netaddr_get_ipstr(session.c->local_addr), session.c->local_port);

*send_userauth_fail = TRUE;
errno = ENOENT;
return 0;
}

cipher_algo = sftp_cipher_get_read_algo();
mac_algo = sftp_mac_get_read_algo();

/* XXX Is this too strict? For PAM authentication, no -- but for S/Key or
* one-time password authencation, maybe yes.
*/
if (strcmp(cipher_algo, "none") == 0 ||
strcmp(mac_algo, "none") == 0) {
(void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
"cipher algorithm '%s' or MAC algorithm '%s' unacceptable for "
"keyboard-interactive authentication, denying authentication request",
cipher_algo, mac_algo);

*send_userauth_fail = TRUE;
errno = EPERM;
return 0;
}

/* Read off the deprecated language string. */
sftp_msg_read_string(pkt->pool, buf, buflen);

submethods = sftp_msg_read_string(pkt->pool, buf, buflen);

if (strlen(submethods) > 0) {
pr_trace_msg(trace_channel, 8, "client suggested 'keyboard-interactive' "
"methods: %s", submethods);
}

/* XXX get our own get_shared_name() function (see kex.c), to see if
* any of the "hints" sent by the client match any of the registered
* kbdint drivers.
*/

driver = sftp_kbdint_first_driver();
while (driver) {
pr_signals_handle();

pr_trace_msg(trace_channel, 3, "trying kbdint driver '%s' for user '%s'",
driver->driver_name, user);

res = driver->open(driver, user);
if (res < 0) {
driver = sftp_kbdint_next_driver();
continue;
}

res = driver->authenticate(driver, user);
driver->close(driver);

if (res == 0)
break;

driver = sftp_kbdint_next_driver();
}

if (res < 0) {
*send_userauth_fail = TRUE;
errno = EPERM;
return 0;
}

return 1;
}
Loading

0 comments on commit a312d87

Please sign in to comment.