]> git.ipfire.org Git - thirdparty/HylaFAX.git/commitdiff
This changes how PAM authentication is done.
authorAidan Van Dyk <aidan@ifax.com>
Thu, 25 Jan 2007 15:50:15 +0000 (15:50 +0000)
committerAidan Van Dyk <aidan@ifax.com>
Thu, 25 Jan 2007 15:50:15 +0000 (15:50 +0000)
1) Straightens out hosts/pam checks in checkUser/checkPasswd
2) Moves all PAM related functions to PAM.c++ from both User.c++ and Login.c++
3) Changes PAM to not try and re-use existing sessions.  This has
   been reported to cause problems, using separate sessions seems to fix this.

CHANGES
hfaxd/HylaFAXServer.c++
hfaxd/HylaFAXServer.h
hfaxd/Login.c++
hfaxd/Makefile.in
hfaxd/SNPPServer.c++
hfaxd/User.c++

diff --git a/CHANGES b/CHANGES
index 47afd891f7a9868b2b798416f7c740068519db88..f7cb6d82dabd403b334a25ccc89b7c8f4551e344 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,7 @@
 
 Chandlog since HylaFAX 4.3.1
 
+* PAM reworked to use complete sessions independantly (25 Jan 2007)
 * Added debian/ directory with rules to create a simple Debian package (21 Jan 2007)
 * Simplify/Unify mime encoder selection and use (9 Jan 2007)
 * Add the Include: option for Config file options (8 Jan 2007)
index 7072fb0bd4b77553cf3ddb3de06c149bcd284d8f..aa514b41dbd6350df8466e28fc49bcc47b4b8676 100644 (file)
@@ -61,11 +61,6 @@ HylaFAXServer::HylaFAXServer()
     adminAttempts = 0;         // NB: not reset by REIN command
     idcache = NULL;
 
-#ifdef HAVE_PAM
-       pamh = NULL;
-       pam_chrooted = false;
-#endif
-
     data = -1;                 // current data connection (socket)
     pdata = -1;                        // passive mode data connect (socket)
     faxqFd = -1;
index 395a9e6694e31c93ed7d6ad249f9f50bdbda01ff..a3f0df503959fd2c3adbe048b45d57704c19a59d 100644 (file)
 
 #include "config.h"
 
-#ifdef HAVE_PAM
-extern "C" {
-#include <security/pam_appl.h>
-#include <grp.h>
-}
-#endif // HAVE_PAM
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <dirent.h>
@@ -216,11 +209,6 @@ protected:
     /*
      * User authentication and login-related state.
      */
-#ifdef HAVE_PAM
-       pam_handle_t *pamh;             // handle to current pam session
-       bool    pam_chrooted;   // if already chrooted, PAM gets disabled
-#endif
-
     fxStr      passwd;                 // encrypted user password
     fxStr      adminwd;                // encrypted passwd for admin privileges
     u_int      uid;                    // client's ID
@@ -229,7 +217,7 @@ protected:
     u_int      adminAttempts;          // number of failed admin attempts
     u_int      maxAdminAttempts;       // admin failures before server exits
     fxStr      the_user;               // name of user
-       fxStr   admingroup;                     // name of local user group that is allowed
+    fxStr      admingroup;                     // name of local user group that is allowed
                                                                // to administer the fax server
     IDCache*   idcache;                // fax UID -> name mapping table
     /*
@@ -349,12 +337,18 @@ protected:
     void setFileOwner(const char* filename);
 
     void loginRefused(const char* why);
-       bool pamCheck(const char* user=NULL, const char* pass=NULL);
-       bool pamIsAdmin(const char* user=NULL);
-       void pamEnd(int pamret);
+
     bool checkUser(const char*);
-    bool checkuser(FILE*, const char *name);
-    bool checkuser(const char *name);
+    bool checkPasswd(const char*);
+
+    bool checkuserHosts(FILE*, const char *name);
+    bool checkuserPAM(const char *name);
+
+    bool checkpasswdHosts(const char* passwd);
+    bool checkpasswdPAM(const char* passwd);
+
+    bool isAdminGroup(const char* user=NULL);
+
     void login(int code);
     void end_login(void);
     virtual void dologout(int status);
index 5352c51e5c4c11098121dcf3b760a36c6805d78d..5cd2b33dff5ac7ffd24cae213b4343ac5cde0853 100644 (file)
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <fcntl.h>
+#include <grp.h>
 #include <pwd.h>
 #if HAS_CRYPT_H
 #include <crypt.h>
@@ -96,133 +97,23 @@ HylaFAXServer::userCmd(const char* name)
        loginRefused("user denied");
 }
 
-#ifdef HAVE_PAM
-int
-pamconv(int num_msg, STRUCT_PAM_MESSAGE **msg, struct pam_response **resp, void *appdata)
-{
-       char *password =(char*) appdata;
-       struct pam_response* replies;
-
-       if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
-           return PAM_CONV_ERR;
-
-       if (password == NULL)
-           /*
-            * Solaris doesn't have PAM_CONV_AGAIN defined.
-            */
-           #ifdef PAM_CONV_AGAIN
-               return PAM_CONV_AGAIN;
-           #else
-               return PAM_CONV_ERR;
-           #endif
-
-       replies=(struct pam_response*)calloc(num_msg, sizeof(struct pam_response));
-
-       replies[0].resp = strdup(password);
-       replies[0].resp_retcode = 0;
-       *resp = replies;
-
-       return PAM_SUCCESS;
-}
-#endif //HAVE_PAM
-
 bool
-HylaFAXServer::pamIsAdmin(const char* user)
+HylaFAXServer::isAdminGroup(const char* user)
 {
        bool retval = false;
-#ifdef HAVE_PAM
-       int i;
-       static struct group* grinfo = getgrnam(admingroup);
-       const char *curruser = (user == NULL ? the_user.c_str() : user);
-       if (grinfo != NULL) {
-               for (i=0; grinfo->gr_mem[i] != NULL; i++) {
-                       if (strcmp(curruser, grinfo->gr_mem[i]) == 0) retval = true;
-               }
+       if (admingroup.length() > 0) {
+           int i;
+           static struct group* grinfo = getgrnam(admingroup);
+           const char *curruser = (user == NULL ? the_user.c_str() : user);
+           if (grinfo != NULL) {
+                   for (i=0; grinfo->gr_mem[i] != NULL; i++) {
+                           if (strcmp(curruser, grinfo->gr_mem[i]) == 0) retval = true;
+                   }
+           }
        }
-#endif //HAVE_PAM
        return(retval);
 }
 
-bool
-HylaFAXServer::pamCheck(const char* user, const char* pass)
-{
-       bool retval = false;
-#ifdef HAVE_PAM
-       if (pamh == NULL)
-           return false;
-
-       if (user == NULL) user = the_user;
-       if (pass == NULL) pass = passwd.c_str();
-
-       struct pam_conv conv = {
-               pamconv,
-               (void*)pass
-       };
-       
-
-       int pamret;
-
-       /*
-        * Solaris has proprietary pam_[sg]et_item() extension.
-        * Sun defines PAM_MSG_VERSION therefore is possible to use
-        * it in order to recognize the extensions of Solaris
-        */
-       #ifdef PAM_MSG_VERSION
-           pamret = pam_set_item(pamh, PAM_CONV, (const void *)&conv);
-       #else
-           pamret = pam_set_item(pamh, PAM_CONV, &conv);
-       #endif
-
-       if (pamret == PAM_SUCCESS)
-           pamret = pam_authenticate(pamh, 0);
-
-       if (pamret == PAM_SUCCESS)
-           pamret = pam_acct_mgmt(pamh, 0);
-
-       if (pamret == PAM_SUCCESS)
-               retval = true;
-
-       pamEnd(pamret);
-#endif
-       return retval;
-}
-
-void HylaFAXServer::pamEnd(int pamret)
-{
-#ifdef HAVE_PAM
-    if (pamret == PAM_SUCCESS)
-    {
-       if (pamIsAdmin())
-           state |= S_PRIVILEGED;
-
-       char *newname=NULL;
-
-       /*
-        * Solaris has proprietary pam_[sg]et_item() extension.
-        * Sun defines PAM_MSG_VERSION therefore is possible to use
-        * it in order to recognize the extensions of Solaris
-        */
-       #ifdef PAM_MSG_VERSION
-           pamret = pam_get_item(pamh, PAM_USER, (void **)&newname);
-       #else
-           pamret = pam_get_item(pamh, PAM_USER, (const void **)&newname);
-       #endif
-
-       if (pamret == PAM_SUCCESS && newname != NULL)
-           the_user = strdup(newname);
-
-       struct passwd* uinfo=getpwnam((const char *)the_user);
-       if (uinfo != NULL) {
-           uid = uinfo->pw_uid;
-       }       
-
-    }
-    pamret = pam_end(pamh, pamret);
-    pamh = NULL;
-
-#endif //HAVE_PAM
-}
-
 void
 HylaFAXServer::passCmd(const char* pass)
 {
@@ -246,7 +137,8 @@ HylaFAXServer::passCmd(const char* pass)
        pass++;
     } else
        state |= S_LREPLIES;
-    if (pass[0] == '\0' || !(strcmp(crypt(pass, passwd), passwd) == 0 || pamCheck(the_user, pass))) {
+
+    if (! checkPasswd(pass)) {
        if (++loginAttempts >= maxLoginAttempts) {
            reply(530, "Login incorrect (closing connection).");
            logNotice("Repeated login failures for user %s from %s [%s]"
@@ -296,10 +188,6 @@ HylaFAXServer::login(int code)
        return;
     }
 
-#ifdef HAVE_PAM
-    pam_chrooted = true;
-#endif
-
     (void) isShutdown(false);  // display any shutdown messages
     reply(code, "User %s logged in.", (const char*) the_user);
     if (TRACE(LOGIN))
@@ -314,7 +202,7 @@ HylaFAXServer::login(int code)
 
     initDefaultJob();          // setup connection-related state
     dirSetup();                        // initialize directory handling
-       if (pamIsAdmin()) state |= S_PRIVILEGED;
+       if (isAdminGroup()) state |= S_PRIVILEGED;
 }
 
 void
@@ -322,7 +210,7 @@ HylaFAXServer::adminCmd(const char* pass)
 {
     fxAssert(IS(LOGGEDIN), "ADMIN command permitted when not logged in");
     // NB: null adminwd is permitted
-    if ((strcmp(crypt(pass, adminwd), adminwd) != 0) && !pamIsAdmin()) {
+    if ((strcmp(crypt(pass, adminwd), adminwd) != 0) && !isAdminGroup()) {
        if (++adminAttempts >= maxAdminAttempts) {
            reply(530, "Password incorrect (closing connection).");
            logNotice("Repeated admin failures from %s [%s]"
index ea4cfc3b8b7e799ff13622c608799eb3916084b9..3a0db7eccbd147d4445c5c770ebc4fb6d3222e5f 100644 (file)
@@ -56,6 +56,7 @@ C++FILES=Admin.c++ \
        Status.c++ \
        Trigger.c++ \
        User.c++ \
+       PAM.c++ \
        \
        SuperServer.c++ \
        InetFaxServer.c++ \
index fed65faadac6bf0525633d71fcf0fcfac4819004..bcfbc48b8140f7aa0beefd00cb967f066e4c7cd2 100644 (file)
@@ -997,8 +997,7 @@ SNPPServer::loginCmd(const char* loginID, const char* pass)
     passwd = "*";                      // just in case...
 
     if (checkUser(loginID)) {
-       if (passwd != "") {
-           if (pass[0] == '\0' || !(streq(crypt(pass, passwd), passwd) || pamCheck(the_user, pass))) {
+       if (! checkPasswd(passwd)) {
                if (++loginAttempts >= maxLoginAttempts) {
                    reply(421, "Login incorrect (closing connection).");
                    logNotice("Repeated SNPP login failures for user %s from %s [%s]"
@@ -1016,7 +1015,6 @@ SNPPServer::loginCmd(const char* loginID, const char* pass)
                );
                return;
            }
-       }
        login(250);
     } else {
        if (++loginAttempts >= maxLoginAttempts) {
index f160e4aa92da49f8241882dd1b360f200d036468..8dc955295ac63714f459ca091586cd79f256df7c 100644 (file)
 #endif
 #endif /* CHAR_BIT */
 
+
 /*
  * User Access Control Support.
  */
 gid_t  HylaFAXServer::faxuid = 0;              // reserved fax uid
 #define        FAXUID_RESV     HylaFAXServer::faxuid   // reserved fax uid
 
-#ifdef HAVE_PAM
-extern int
-pamconv(int num_msg, STRUCT_PAM_MESSAGE **msg, struct pam_response **resp, void *appdata);
-#endif
-
 bool
 HylaFAXServer::checkUser(const char* name)
 {
     bool check = false;
     FILE* db = fopen(fixPathname(userAccessFile), "r");
     if (db != NULL) {
-       check = checkuser(db, name) || checkuser(name);
+       check = checkuserHosts(db, name);
        fclose(db);
     } else
        logError("Unable to open the user access file %s: %s",
            (const char*) userAccessFile, strerror(errno));
+
+    if (! check)
+       check = checkuserPAM(name);
+
     /*
      * This causes the user to be prompted for a password
      * and then denied access.  We do this to guard against
@@ -73,6 +73,22 @@ HylaFAXServer::checkUser(const char* name)
     return (true);
 }
 
+bool
+HylaFAXServer::checkPasswd (const char* pass)
+{
+    if (pass[0] == '\0')
+       return false;
+
+    if (checkpasswdHosts(pass))
+        return true;
+
+    if (checkpasswdPAM(pass))
+        return true;
+
+    return false;
+}
+
+
 static bool
 nextRecord(FILE* db, char line[], u_int size)
 {
@@ -92,48 +108,13 @@ nextRecord(FILE* db, char line[], u_int size)
     return (false);
 }
 
-bool
-HylaFAXServer::checkuser(const char* name)
-{
-       bool retval=false;
-
-#ifdef HAVE_PAM
-       if (pam_chrooted) {
-           logNotice("PAM authentication for %s can't be used for a re-issuance of USER command because of chroot jail\n", name);
-           return false;
-       }
-
-       int pamret;
-       struct pam_conv conv = {pamconv, NULL};         
-
-       pamret = pam_start(FAX_SERVICE, name, &conv, &pamh);
-
-       if (pamret == PAM_SUCCESS)
-               pamret = pam_authenticate(pamh, 0);
-
-       if (pamret == PAM_SUCCESS)
-               pamret = pam_acct_mgmt(pamh, 0);
-
-       if (pamret == PAM_SUCCESS) {
-               passwd = "";
-               pamEnd(pamret);
-       } else {
-           passwd = "*";
-           adminwd = "*";
-       }
-       retval = true;
-
-#endif //HAVE_PAM
-       return(retval);
-}
-
 /*
  * Check the user name and host name/address against
  * the list of users and hosts that are permitted to
  * user the server and setup password handling.
  */
 bool
-HylaFAXServer::checkuser(FILE* db, const char* name)
+HylaFAXServer::checkuserHosts(FILE* db, const char* name)
 {
     struct stat sb;
     if (Sys::fstat(fileno(db), sb) < 0)
@@ -216,6 +197,15 @@ HylaFAXServer::checkuser(FILE* db, const char* name)
     return (false);
 }
 
+bool
+HylaFAXServer::checkpasswdHosts (const char* pass)
+{
+    if (strcmp(crypt(pass,passwd),passwd) == 0)
+        return true;
+
+    return false;
+}
+
 fxDECLARE_PtrKeyDictionary(IDCache, u_int, fxStr)
 fxIMPLEMENT_PtrKeyObjValueDictionary(IDCache, u_int, fxStr)