From 05ba7bb2f06466ff606819692c175d59478a32c3 Mon Sep 17 00:00:00 2001 From: Seraphim Mellos Date: Sat, 14 Jun 2008 14:52:45 +0300 Subject: Added log messages and restructured base dir organization --- LICENSE | 23 ++++ include/pam_mod_misc.h | 33 ------ include/pam_mod_misc.h~ | 56 --------- include/security/pam_mod_misc.h | 36 ++++++ src/pam_unix/pam_unix.c | 47 ++++++-- src/pam_unix/pam_unix.c~ | 249 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 345 insertions(+), 99 deletions(-) create mode 100644 LICENSE delete mode 100755 include/pam_mod_misc.h delete mode 100755 include/pam_mod_misc.h~ create mode 100755 include/security/pam_mod_misc.h create mode 100644 src/pam_unix/pam_unix.c~ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5306b00 --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2008 Seraphim Mellos + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + diff --git a/include/pam_mod_misc.h b/include/pam_mod_misc.h deleted file mode 100755 index b1609fc..0000000 --- a/include/pam_mod_misc.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PAM_MOD_MISC_H -#define PAM_MOD_MISC_H - -/* - * All of this file has been taken from freebsd-lib and has been slightly - * modified to avoid any problems when used on Linux machines. It provides - * an easier logging interface and some additional options for OpenPAM. - */ - -#ifndef __linux__ -# include -#endif - - -/* - * Common option names - */ -#define PAM_OPT_NULLOK "nullok" -#define PAM_OPT_AUTH_AS_SELF "auth_as_self" -#define PAM_OPT_ECHO_PASS "echo_pass" -#define PAM_OPT_DEBUG "debug" - - -#define PAM_LOG(...) \ - openpam_log(PAM_LOG_DEBUG, __VA_ARGS__) - -#define PAM_RETURN(arg) \ - return (arg) - -#define PAM_VERBOSE_ERROR(...) \ - _pam_verbose_error(pamh, flags, __FILE__, __FUNCTION__, __VA_ARGS__) - -#endif diff --git a/include/pam_mod_misc.h~ b/include/pam_mod_misc.h~ deleted file mode 100755 index 7576989..0000000 --- a/include/pam_mod_misc.h~ +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * Copyright 1998 Juniper Networks, Inc. - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD: src/lib/libpam/libpam/security/pam_mod_misc.h,v 1.12 2003/05/31 16:56:35 des Exp $ - */ - -#ifndef PAM_MOD_MISC_H -#define PAM_MOD_MISC_H - -#include - -/* - * Common option names - */ -#define PAM_OPT_NULLOK "nullok" -#define PAM_OPT_AUTH_AS_SELF "auth_as_self" -#define PAM_OPT_ECHO_PASS "echo_pass" -#define PAM_OPT_DEBUG "debug" - -__BEGIN_DECLS -void _pam_verbose_error(pam_handle_t *, int, const char *, - const char *, const char *, ...); -__END_DECLS - -#define PAM_LOG(...) \ - openpam_log(PAM_LOG_DEBUG, __VA_ARGS__) - -#define PAM_RETURN(arg) \ - return (arg) - -#define PAM_VERBOSE_ERROR(...) \ - _pam_verbose_error(pamh, flags, __FILE__, __FUNCTION__, __VA_ARGS__) - -#endif diff --git a/include/security/pam_mod_misc.h b/include/security/pam_mod_misc.h new file mode 100755 index 0000000..829dece --- /dev/null +++ b/include/security/pam_mod_misc.h @@ -0,0 +1,36 @@ +#ifndef PAM_MOD_MISC_H +#define PAM_MOD_MISC_H + +/* + * All of this file has been taken from freebsd-lib and has been slightly + * modified to avoid any problems when used on Linux machines. It provides + * an easier logging interface and some additional options for OpenPAM. + */ + +#ifndef __linux__ +# include +#endif + + +/* + * Common option names + */ +#define PAM_OPT_NULLOK "nullok" +#define PAM_OPT_AUTH_AS_SELF "auth_as_self" +#define PAM_OPT_ECHO_PASS "echo_pass" +#define PAM_OPT_DEBUG "debug" + + +#define PAM_LOG(...) \ + openpam_log(PAM_LOG_DEBUG, __VA_ARGS__) + +#define PAM_ERROR(...) \ + openpam_log(PAM_LOG_ERROR, __VA_ARGS__) + +#define PAM_RETURN(arg) \ + return (arg) + +#define PAM_VERBOSE_ERROR(...) \ + _pam_verbose_error(pamh, flags, __FILE__, __FUNCTION__, __VA_ARGS__) + +#endif diff --git a/src/pam_unix/pam_unix.c b/src/pam_unix/pam_unix.c index c246fd7..c65ec10 100644 --- a/src/pam_unix/pam_unix.c +++ b/src/pam_unix/pam_unix.c @@ -1,4 +1,3 @@ - /* #include */ #include #include @@ -23,6 +22,9 @@ #include #include +/* + * User authentication + */ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, @@ -38,27 +40,30 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, /* identify user */ if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) { - puts("POULOS1"); - PAM_LOG("Authenticating as self"); + PAM_LOG("Authenticating as self."); pwd = getspnam(getlogin()); } else { if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) { - puts("POULOS2"); - PAM_LOG("Authenticating with uname failed"); + PAM_ERROR("Authenticating with uname %s failed.", user); return (pam_err); } pwd = getspnam(user); } - puts("POULOS3"); + + PAM_LOG("Authenticating user: %s", user); + /* get password */ if (pwd != NULL) { + PAM_LOG("Doing real authentication"); pass = pwd->sp_pwdp; if (pass[0] == '\0') { if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) && - openpam_get_option(pamh, PAM_OPT_NULLOK)) + openpam_get_option(pamh, PAM_OPT_NULLOK)){ + PAM_ERROR("Authentication failed. Empty passwd not allowed"); return (PAM_SUCCESS); + } pass = "*"; } @@ -66,6 +71,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, lc = login_getpwclass(pwd); #endif } else { + PAM_LOG("Doing dummy authentication"); pass = "*"; #ifndef __linux__ lc = login_getpwclass(NULL); @@ -79,6 +85,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, #else pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, (const char **) &pass, NULL); #endif + PAM_LOG("Got password for user %s", user); if (pam_err == PAM_CONV_ERR) return (pam_err); @@ -88,11 +95,14 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, /* check shadow */ crypt_pass = crypt(pass, pwd->sp_pwdp); - if ( strcmp(crypt_pass, pwd->sp_pwdp) != 0 ) + if ( strcmp(crypt_pass, pwd->sp_pwdp) != 0 ) { + PAM_ERROR("Wrong password. Authentication failed."); pam_err = PAM_AUTH_ERR; - else + } else { + PAM_LOG("Authentication completed succesfully"); pam_err = PAM_SUCCESS; - + } + return (pam_err); } @@ -110,6 +120,10 @@ pam_sm_setcred(pam_handle_t *pamh , int flags , } +/* + * Account Management + */ + PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags , int argc , const char *argv[] ) { @@ -224,6 +238,19 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags , return (pam_err); +} + +/* + * Password Management + */ + +PAM_EXTERN int +pam_sm_chautok(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + + + } diff --git a/src/pam_unix/pam_unix.c~ b/src/pam_unix/pam_unix.c~ new file mode 100644 index 0000000..c5215b9 --- /dev/null +++ b/src/pam_unix/pam_unix.c~ @@ -0,0 +1,249 @@ +/* #include */ +#include +#include +#include +#include + + +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#define PAM_PASSWORD + +#ifndef __linux__ +#include +#endif + + +#include +#include +#include + +/* + * User authentication + */ + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc , const char **argv ) { + +#ifndef __linux__ + login_cap_t *lc; +#endif + struct spwd *pwd; + const char *pass, *crypt_pass, *user; + int pam_err; + + /* identify user */ + + if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) { + puts("POULOS1"); + PAM_LOG("Authenticating as self"); + pwd = getspnam(getlogin()); + } else { + if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) { + puts("POULOS2"); + PAM_LOG("Authenticating with uname failed"); + return (pam_err); + } + + pwd = getspnam(user); + } + puts("POULOS3"); + /* get password */ + + if (pwd != NULL) { + pass = pwd->sp_pwdp; + if (pass[0] == '\0') { + if (!(flags & PAM_DISALLOW_NULL_AUTHTOK) && + openpam_get_option(pamh, PAM_OPT_NULLOK)) + return (PAM_SUCCESS); + + pass = "*"; + } +#ifndef __linux__ + lc = login_getpwclass(pwd); +#endif + } else { + pass = "*"; +#ifndef __linux__ + lc = login_getpwclass(NULL); +#endif + } + +#ifndef __linux__ + prompt = login_getcapstr(lc, "passwd_prompt", NULL, NULL); + pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, prompt); + login_close(lc); +#else + pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, (const char **) &pass, NULL); +#endif + + if (pam_err == PAM_CONV_ERR) + return (pam_err); + if (pam_err != PAM_SUCCESS) + return (PAM_AUTH_ERR); + + /* check shadow */ + + crypt_pass = crypt(pass, pwd->sp_pwdp); + if ( strcmp(crypt_pass, pwd->sp_pwdp) != 0 ) + pam_err = PAM_AUTH_ERR; + else + pam_err = PAM_SUCCESS; + + return (pam_err); +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh , int flags , + int argc , const char *argv[] ) { + + /* + * This functions takes care of renewing/initializing + * user credentials as well as gid/uids. Someday, it + * will be completed. For now, it's not very urgent. + */ + + return (PAM_SUCCESS); +} + + +/* + * Account Management + */ + +PAM_EXTERN int +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags , + int argc , const char *argv[] ) { + + + +#ifndef __linux__ + login_cap_t *lc; +#endif + + struct spwd *pwd; + int pam_err; + const char *user; + time_t curtime; + +#ifndef __linux__ + const void *rhost, *tty; + char rhostip[MAXHOSTNAMELEN] = ""; +#endif + + /* Sanity checks for uname,pwd,tty,host etc */ + + pam_err = pam_get_user(pamh, &user, NULL); + + if (pam_err != PAM_SUCCESS) + return (pam_err); + + if (user == NULL || (pwd = getspnam(user)) == NULL) + return (PAM_SERVICE_ERR); +#ifndef __linux__ + + /* + * tty/host info are provided by login classes + * and cannot be used out of the box under Linux + * for sanity checking (BSD only). May need to + * be ported/rewritten to work on Linux as well. + * Time will tell... + */ + pam_err = pam_get_item(pamh, PAM_RHOST, &rhost); + + if (pam_err != PAM_SUCCESS) + return (pam_err); + + pam_err = pam_get_item(pamh, PAM_TTY, &tty); + + if (pam_err != PAM_SUCCESS) + return (pam_err); +#endif + if (*pwd->sp_pwdp == '\0' && + (flags & PAM_DISALLOW_NULL_AUTHTOK) != 0) + return (PAM_NEW_AUTHTOK_REQD); + +#ifndef __linux__ + lc = login_getpwclass(pwd); + + if (lc == NULL) { + return (PAM_SERVICE_ERR); + + } +#endif + /* Check if pw_lstchg or pw_expire is set */ + + if (pwd->sp_lstchg || pwd->sp_expire) + curtime = time(NULL) / (60 * 60 * 24); + if (pwd->sp_expire) { + if ( (curtime > pwd->sp_expire ) && ( pwd->sp_expire != -1 ) ) { +#ifndef __linux__ + login_close(lc); +#endif + return (PAM_ACCT_EXPIRED); + } else if ( ( pwd->sp_expire - curtime < pwd->sp_warn) ) { +// pam_error(pamh, "Warning: your account expires on %s", +// ctime(&pwd->pw_expire)); + } + } + + if (pwd->sp_lstchg == 0 ) { + return (PAM_NEW_AUTHTOK_REQD); + } + + /* check all other possibilities (mostly stolen from pam_tcb) */ + + if ((curtime > (pwd->sp_lstchg + pwd->sp_max + pwd->sp_inact)) && + (pwd->sp_max != -1) && (pwd->sp_inact != -1) && + (pwd->sp_lstchg != 0)) + return (PAM_ACCT_EXPIRED); + + if (((pwd->sp_lstchg + pwd->sp_max) < curtime) && + (pwd->sp_max != -1)) + return (PAM_ACCT_EXPIRED); + + if ((curtime - pwd->sp_lstchg > pwd->sp_max) + && (curtime - pwd->sp_lstchg > pwd->sp_inact) + && (curtime - pwd->sp_lstchg > pwd->sp_max + pwd->sp_inact) + && (pwd->sp_max != -1) && (pwd->sp_inact != -1)) + return (PAM_ACCT_EXPIRED); + + pam_err = (PAM_SUCCESS); + +#ifndef __linux__ + + /* validate tty/host/time */ + + if (!auth_hostok(lc, rhost, rhostip) || + !auth_ttyok(lc, tty) || + !auth_timeok(lc, time(NULL))) + pam_err = PAM_AUTH_ERR; + + + login_close(lc); +#endif + + return (pam_err); + +} + +/* + * Password Management + */ + +PAM_EXTERN int +pam_sm_chautok(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + + + +} + + +PAM_MODULE_ENTRY("pam_unix") -- cgit v1.2.3-65-gdbad