Skip to content

Commit

Permalink
Bug#4285: Use AIX' loginfailed() and loginsuccess() functions, if ava…
Browse files Browse the repository at this point in the history
…ilable,

for recording login successes/failures.
  • Loading branch information
Castaglia committed Jan 31, 2017
1 parent 43a439c commit 3a56cb4
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 3 deletions.
9 changes: 9 additions & 0 deletions config.h.in
Expand Up @@ -402,9 +402,15 @@
/* Define if you have the llistxattr function. */
#undef HAVE_LLISTXATTR

/* Define if you have the loginfailed function. */
#undef HAVE_LOGINFAILED

/* Define if you have the loginrestrictions function. */
#undef HAVE_LOGINRESTRICTIONS

/* Define if you have the loginsuccess function. */
#undef HAVE_LOGINSUCCESS

/* Define if you have the lremovexattr function. */
#undef HAVE_LREMOVEXATTR

Expand Down Expand Up @@ -753,6 +759,9 @@
/* Define if you have the <sys/acl.h> header file. */
#undef HAVE_SYS_ACL_H

/* Define if you have the <sys/audit.h> header file. */
#undef HAVE_SYS_AUDIT_H

/* Define if you have the <sys/dir.h> header file. */
#undef HAVE_SYS_DIR_H

Expand Down
129 changes: 128 additions & 1 deletion configure
Expand Up @@ -21872,7 +21872,8 @@ fi



for ac_header in krb.h login.h prot.h usersec.h

for ac_header in krb.h login.h prot.h usersec.h sys/audit.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
Expand Down Expand Up @@ -22381,6 +22382,132 @@ fi
done


{ echo "$as_me:$LINENO: checking for AIX loginfailed" >&5
echo $ECHO_N "checking for AIX loginfailed... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */

#include <sys/types.h>
#ifdef HAVE_USERSEC_H
# include <usersec.h>
#endif

int
main ()
{

(void) loginfailed(NULL, NULL, NULL, 0);

;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then


cat >>confdefs.h <<\_ACEOF
#define HAVE_LOGINFAILED 1
_ACEOF

{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }

else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5


{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }


fi

rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

{ echo "$as_me:$LINENO: checking for AIX loginsuccess" >&5
echo $ECHO_N "checking for AIX loginsuccess... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */

#include <sys/types.h>
#ifdef HAVE_USERSEC_H
# include <usersec.h>
#endif

int
main ()
{

(void) loginsuccess(NULL, NULL, NULL, NULL);

;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then


cat >>confdefs.h <<\_ACEOF
#define HAVE_LOGINSUCCESS 1
_ACEOF

{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }

else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5


{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }


fi

rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


if test x"$install_user" = x; then
if test "x$target_os" = "xcygwin"; then
Expand Down
41 changes: 40 additions & 1 deletion configure.in
Expand Up @@ -1334,7 +1334,7 @@ if test "$pr_cv_var__pw_stayopen" = "yes"; then
AC_DEFINE(HAVE__PW_STAYOPEN, 1, [Define if you have __pw_stayopen variable.])
fi

AC_CHECK_HEADERS(krb.h login.h prot.h usersec.h)
AC_CHECK_HEADERS(krb.h login.h prot.h usersec.h sys/audit.h)

dnl HP-UX's hpsecurity.h can multiply define MAXINT and confuse configure
AC_CHECK_HEADERS(hpsecurity.h, [
Expand All @@ -1356,6 +1356,45 @@ AC_CHECK_HEADERS(hpsecurity.h, [
])
])

dnl AIX's "lastlog" support is done via specific functions, rather than a
dnl struct (Bug#4285).
AC_MSG_CHECKING(for AIX loginfailed)
AC_TRY_COMPILE([
#include <sys/types.h>
#ifdef HAVE_USERSEC_H
# include <usersec.h>
#endif
],
[
(void) loginfailed(NULL, NULL, NULL, 0);
],
[
AC_DEFINE(HAVE_LOGINFAILED, 1, [Define if you have AIX loginfailed function])
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
]
)

AC_MSG_CHECKING(for AIX loginsuccess)
AC_TRY_COMPILE([
#include <sys/types.h>
#ifdef HAVE_USERSEC_H
# include <usersec.h>
#endif
],
[
(void) loginsuccess(NULL, NULL, NULL, NULL);
],
[
AC_DEFINE(HAVE_LOGINSUCCESS, 1, [Define if you have AIX loginsuccess function]
)
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
]
)

dnl Checks for installation user/group

if test x"$install_user" = x; then
Expand Down
68 changes: 67 additions & 1 deletion modules/mod_auth.c
Expand Up @@ -2,7 +2,7 @@
* ProFTPD - FTP server daemon
* Copyright (c) 1997, 1998 Public Flood Software
* Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
* Copyright (c) 2001-2016 The ProFTPD Project team
* Copyright (c) 2001-2017 The ProFTPD Project team
*
* 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
Expand All @@ -29,6 +29,14 @@
#include "conf.h"
#include "privs.h"

#ifdef HAVE_USERSEC_H
# include <usersec.h>
#endif

#ifdef HAVE_SYS_AUDIT_H
# include <sys/audit.h>
#endif

extern pid_t mpid;

module auth_module;
Expand Down Expand Up @@ -336,7 +344,34 @@ static int do_auth(pool *p, xaset_t *conf, const char *u, char *pw) {
/* Command handlers
*/

static void login_failed(pool *p, const char *user) {
#ifdef HAVE_LOGINFAILED
char *host, *sess_ttyname;
int res, xerrno;

host = pr_netaddr_get_dnsstr(session.c->remote_addr);
sess_ttyname = pr_session_get_ttyname(p);

PRIVS_ROOT
res = loginfailed((char *) user, host, sess_ttyname, AUDIT_FAIL);
xerrno = errno;
PRIVS_RELINQUISH

if (res < 0) {
pr_trace_msg("auth", 3, "AIX loginfailed() error for user '%s', "
"host '%s', tty '%s', reason %d: %s", user, host, sess_ttyname,
AUDIT_FAIL, strerror(errno));
}
#endif /* HAVE_LOGINFAILED */
}

MODRET auth_err_pass(cmd_rec *cmd) {
const char *user;

user = pr_table_get(session.notes, "mod_auth.orig-user", NULL);
if (user != NULL) {
login_failed(cmd->tmp_pool, user);
}

/* Remove the stashed original USER name here in a LOG_CMD_ERR handler, so
* that other modules, who may want to lookup the original USER parameter on
Expand Down Expand Up @@ -371,6 +406,35 @@ MODRET auth_log_pass(cmd_rec *cmd) {
return PR_DECLINED(cmd);
}

static void login_succeeded(pool *p, const char *user) {
#ifdef HAVE_LOGINSUCCESS
char *host, *msg = NULL, *sess_ttyname;
int res, xerrno;

host = pr_netaddr_get_dnsstr(session.c->remote_addr);
sess_ttyname = pr_session_get_ttyname(p);

PRIVS_ROOT
res = loginsuccess((char *) user, host, sess_ttyname, &msg);
xerrno = errno;
PRIVS_RELINQUISH

if (res == 0) {
if (msg != NULL) {
pr_trace_msg("auth", 14, "AIX loginsuccess() report: %s", msg);
}

} else {
pr_trace_msg("auth", 3, "AIX loginsuccess() error for user '%s', "
"host '%s', tty '%s': %s", user, host, sess_ttyname, strerror(errno));
}

if (msg != NULL) {
free(msg);
}
#endif /* HAVE_LOGINSUCCESS */
}

MODRET auth_post_pass(cmd_rec *cmd) {
config_rec *c = NULL;
const char *grantmsg = NULL, *user;
Expand Down Expand Up @@ -596,6 +660,8 @@ MODRET auth_post_pass(cmd_rec *cmd) {
pr_response_add(auth_pass_resp_code, "%s", grantmsg);
}

login_succeeded(cmd->tmp_pool, user);

/* A RootRevoke value of 0 indicates 'false', 1 indicates 'true', and
* 2 indicates 'NonCompliantActiveTransfer'. We will drop root privs for any
* RootRevoke value greater than 0.
Expand Down

0 comments on commit 3a56cb4

Please sign in to comment.