Use PAM uid, POSIX ACL's
"Lanclos, Jason" <[email protected]>
| Newsgroups | gmane.comp.telephony.fax.hylafax.devel |
|---|---|
| Message-ID | <C873311FC373AD40BCF51C51E3DAD4800131E2A8BF@Autolycus.ldaf.state.la.us> |
I have HylaFAX 6.0.3 installed and running on CentOS 5.3 with Samba/winbind setup to utilized user accounts in Active Directory. Winbind generates the users UID, and does group membership lookups. When enabling Job Protection in HylaFAX, and setting the group id on the files to the User's UID, winbind would start to fail its lookups. I presume this is because accounts provided by winbind do not have GID's that match the UID. In order to get around this, I enabled POSIX ACLs on the file system, and setup the following permissions: # file: var/spool/hylafax/recvq # owner: uucp # group: uucp user::rwx group::rwx mask::rwx other::r-x default:user::rwx default:user:uucp:rwx default:group::rwx default:mask::rwx default:other::--- Example of file in revcq # file: fax000060498.tif # owner: jlanclos # group: uucp user::rw- user:uucp:rwx group::rw- mask::rwx other::--- HylaFAX runs as the uucp user, so it still has access to all the files, while allowing the User to be the file owner. The included patch enables HylaFAX to work correctly with this setup, and allows permissions to be granted on a group level for the faxes. It also gets the UID from PAM if it is not found in the hosts.hfaxd file. It does require hfaxd to be linked with libacl.
hylafax.patch
(application/octet-stream, 12.5 KB)
diff -ru --new-file hylafax-6.0.3/hfaxd/FileCache.c++ hylafax-6.0.3-ldaf/hfaxd/FileCache.c++
--- hylafax-6.0.3/hfaxd/FileCache.c++ 1999-06-13 02:41:12.000000000 -0500
+++ hylafax-6.0.3-ldaf/hfaxd/FileCache.c++ 2009-10-23 13:38:11.000000000 -0500
@@ -30,6 +30,7 @@
FileCache* FileCache::cache[4096]; // cache of stat results
#define CACHESIZE (sizeof (cache) / sizeof (cache[0]))
+aclcache_t FileCache::aclcache;
// statistics
u_int FileCache::lookups = 0; // total # lookups
u_int FileCache::hits = 0; // # lookups that hit in the cache
@@ -97,7 +98,7 @@
probes++;
if (fi->name == pathname) {
fi->serial = master++;
- sb = fi->sb;
+ sb = fi->sb;
hits++;
return (true);
}
@@ -120,6 +121,7 @@
fi->name = pathname;
fi->serial = master++;
fi->sb = sb;
+ update_acl(pathname,sb);
}
return (true);
}
@@ -141,6 +143,7 @@
if (fi->name == pathname) {
hits++;
fi->sb.st_mode = (fi->sb.st_mode&~0777) | (mode&0777);
+ update_acl(pathname,fi->sb);
break;
}
h = (u_int)(h*h) % CACHESIZE;
@@ -180,6 +183,7 @@
hits++;
fi->sb.st_uid = uid;
fi->sb.st_gid = gid;
+ update_acl(pathname,fi->sb);
break;
}
h = (u_int)(h*h) % CACHESIZE;
@@ -207,6 +211,7 @@
hits++;
fi->serial = master++;
fi->sb = sb;
+ update_acl(pathname,sb);
return (true);
} else {
flushed++;
@@ -234,6 +239,7 @@
fi->name = pathname;
fi->serial = master++;
fi->sb = sb;
+ update_acl(pathname,sb);
}
return (true);
}
@@ -247,6 +253,7 @@
while (fi && --maxprobes) {
if (fi->name == pathname) {
flushed++;
+ flush_acl(fi->sb.st_ino);
cache[h] = NULL;
delete fi;
break;
@@ -255,3 +262,67 @@
fi = cache[h];
}
}
+
+
+
+
+acl_t
+FileCache::lookup_acl(const ino_t inode)
+{
+
+ acl_t acl = aclcache[inode];
+ if (!acl)
+ return (NULL);
+
+ return acl;
+}
+
+
+acl_t
+FileCache::lookup_acl(const char* pathname, struct stat& sb)
+{
+ int r;
+ acl_t acl = aclcache[sb.st_ino];
+ if (!acl) {
+ acl = acl_get_file(pathname,ACL_TYPE_ACCESS);
+ aclcache[sb.st_ino]=acl;
+ }
+ return acl;
+}
+
+bool
+FileCache::update_acl(const char* pathname, struct stat& sb)
+{
+
+ int r;
+ acl_t oldacl = aclcache[sb.st_ino];
+ acl_free(oldacl);
+// if (!acl) {
+ acl_t acl = acl_get_file(pathname,ACL_TYPE_ACCESS);
+ if (acl) {
+ aclcache[sb.st_ino]=acl;
+ return true;
+ }
+
+ //}
+ return false;
+}
+void
+FileCache::flush_acl(const ino_t inode)
+{
+ acl_t acl=lookup_acl(inode);
+ acl_free(acl);
+ aclcache.erase(inode);
+
+}
+void
+FileCache::reset_acl(void) {
+
+
+ aclcache_t::iterator it;
+
+ for (it=aclcache.begin() ; it != aclcache.end(); it++)
+ flush_acl((*it).first);
+
+}
+
diff -ru --new-file hylafax-6.0.3/hfaxd/FileCache.h hylafax-6.0.3-ldaf/hfaxd/FileCache.h
--- hylafax-6.0.3/hfaxd/FileCache.h 1999-06-13 02:41:12.000000000 -0500
+++ hylafax-6.0.3-ldaf/hfaxd/FileCache.h 2009-10-23 13:18:44.000000000 -0500
@@ -28,15 +28,22 @@
#include "Str.h"
#include <sys/stat.h>
-
+#include <stdlib.h>
+#include <iostream>
+#include <sys/acl.h>
+#include <acl/libacl.h>
+#include <map>
/*
* Cache to reduce the number of stat system calls.
*/
+
+typedef std::map<ino_t,acl_t> aclcache_t;
+
struct FileCache {
fxStr name;
struct stat sb;
u_int serial;
-
+ static aclcache_t aclcache;
static u_int master; // master serial # generator
static FileCache* cache[4096];
// statistics
@@ -60,5 +67,14 @@
static bool chmod(const char* pathname, mode_t mode);
static bool chown(const char* pathname, uid_t uid, gid_t gid);
static void reset(void);
+ static acl_t lookup_acl(const ino_t inode);
+ static acl_t lookup_acl(const char* pathname, struct stat& sb);
+ static bool update_acl(const char* pathname, struct stat& sb);
+ static void flush_acl(const ino_t inode);
+ static void reset_acl(void);
};
+
+
+
+
#endif /* _FileCache_ */
diff -ru --new-file hylafax-6.0.3/hfaxd/FileSystemACL.c++ hylafax-6.0.3-ldaf/hfaxd/FileSystemACL.c++
--- hylafax-6.0.3/hfaxd/FileSystemACL.c++ 1969-12-31 18:00:00.000000000 -0600
+++ hylafax-6.0.3-ldaf/hfaxd/FileSystemACL.c++ 2009-10-23 13:42:17.000000000 -0500
@@ -0,0 +1,80 @@
+#include "HylaFAXServer.h"
+#include "Sys.h"
+
+#include <sys/acl.h>
+#include <acl/libacl.h>
+#include <pwd.h>
+#include <grp.h>
+
+bool
+HylaFAXServer::checkFileRights_acl(int op,const struct stat& sb)
+{
+ if (!usefsacls)
+ return false;
+
+ bool grantaccess,checkthisacl,mask,founduseracl = false;
+ bool maskok = true;
+ acl_entry_t ent;
+ acl_t acl;
+ int r;
+ const char* username=userName(uid);
+ acl=FileCache::lookup_acl(sb.st_ino);
+
+ if (acl != NULL)
+ r = acl_get_entry(acl, ACL_FIRST_ENTRY,&ent);
+ if (r != 1)
+ return false;
+ while ( r > 0 && maskok) {
+ const id_t *id_p;
+ uid_t id;
+ checkthisacl = mask = false;
+ acl_tag_t e_type;
+ acl_get_tag_type(ent,&e_type);
+ id_p = (const id_t*) acl_get_qualifier(ent);
+ if (id_p) {
+ id = *id_p;
+ switch (e_type) {
+ case ACL_USER:
+ if (id == uid)
+ checkthisacl=founduseracl=true;
+ break;
+ case ACL_GROUP:
+ if (id_p && !founduseracl) {
+ struct group *grp;
+ grp = getgrgid(id);
+ for ( ; NULL != *(grp->gr_mem); (grp->gr_mem)++ ) {
+ if ( !strcmp(*(grp->gr_mem),username) )
+ checkthisacl=true;
+ }
+ }
+ break;
+ case ACL_MASK:
+ mask=checkthisacl=true;
+ break;
+ }
+ if (checkthisacl) {
+ acl_permset_t permset;
+ acl_get_permset(ent,&permset);
+ if (acl_get_perm(permset,op) && !mask)
+ grantaccess=true;
+ if (mask)
+ if (!acl_get_perm(permset,op))
+ grantaccess=maskok=false;
+ }
+ }
+ acl_free((void*)id_p);
+ acl_free(&ent);
+ r = acl_get_entry(acl,ACL_NEXT_ENTRY,&ent);
+ }
+ return grantaccess;
+}
+
+
+
+
+
+
+
+
+
+
diff -ru --new-file hylafax-6.0.3/hfaxd/FileSystemACL.h hylafax-6.0.3-ldaf/hfaxd/FileSystemACL.h
--- hylafax-6.0.3/hfaxd/FileSystemACL.h 1969-12-31 18:00:00.000000000 -0600
+++ hylafax-6.0.3-ldaf/hfaxd/FileSystemACL.h 2009-10-22 10:45:10.000000000 -0500
@@ -0,0 +1,12 @@
+#include <map>
+
+extern "C" {
+#include <sys/acl.h>
+#include <acl/libacl.h>
+#include <pwd.h>
+#include <grp.h>
+}
+
+
+
+
diff -ru --new-file hylafax-6.0.3/hfaxd/FileSystem.c++ hylafax-6.0.3-ldaf/hfaxd/FileSystem.c++
--- hylafax-6.0.3/hfaxd/FileSystem.c++ 2009-07-03 14:36:47.000000000 -0500
+++ hylafax-6.0.3-ldaf/hfaxd/FileSystem.c++ 2009-10-23 13:41:48.000000000 -0500
@@ -88,10 +88,19 @@
id = (u_int) atoi(user);
else if (!userID(user, id))
return;
- if (!FileCache::chown(pathname, sb.st_uid, (gid_t) id))
+ if (usefsacls) {
+ if (!FileCache::chown(pathname, sb.st_uid, (gid_t) faxuid))
perror_reply(550, pathname, errno);
- else
+ else
+ ack(250, cmdToken(T_CHOWN));
+ } else {
+ if (!FileCache::chown(pathname, sb.st_uid, (gid_t) id))
+ perror_reply(550, pathname, errno);
+ else
ack(250, cmdToken(T_CHOWN));
+
+ }
+
}
}
@@ -255,10 +264,18 @@
if (sb.st_mode & op) // public access
return (true);
- if ((sb.st_gid==uid) && ((sb.st_mode>>3)&op)) // owner access
- return (true);
- return false;
+ if (usefsacls) {
+ if ((sb.st_uid==uid) && ((sb.st_mode>>3)&op)) // owner access
+ return (true);
+ } else {
+ if ((sb.st_gid==uid) && ((sb.st_mode>>3)&op)) // owner access
+ return (true);
+ }
+
+ if(checkFileRights_acl(op,sb))
+ return (true);
+ return false;
}
/*
@@ -285,7 +302,11 @@
* successful file creation--for use below.
*/
sb.st_mode = S_IFREG|S_IRGRP|S_IWGRP;
- sb.st_gid = (gid_t) uid;
+ if (usefsacls)
+ sb.st_uid = (gid_t) uid;
+ else
+ sb.st_gid = (gid_t) uid;
+
sb.st_ino = 0; // NB: to be created
}
/*
@@ -331,10 +352,11 @@
perror_reply(550, path, EPERM); // cannot stor in dir.
return (NULL);
}
- if (!checkFileRights(op, sb)) {
- perror_reply(550, path, EPERM);
- return (NULL);
- }
+ if(!checkFileRights(op,sb))
+ if (!checkFileRights_acl(op,sb)) {
+ perror_reply(550, path, EPERM);
+ return (NULL);
+ }
}
} else { // privileged client
if (op != X_OK && S_ISDIR(sb.st_mode)) { // cannot r/w directory
@@ -394,7 +416,8 @@
if (!FileCache::lookup(file, sb)) {
fatal("setFileOwner called for non-existent file (check)");
}
- if (sb.st_gid != (gid_t) uid) {
+
+ if (sb.st_uid != (gid_t) uid) {
state |= S_SETGID; // not set, must force it
} else {
state &= ~S_SETGID; // set by OS, no work to do
@@ -410,9 +433,15 @@
if (!FileCache::lookup(file, sb)) {
fatal("setFileOwner called for non-existent file (set)");
}
- if (!FileCache::chown(file, sb.st_uid, (gid_t) uid)) {
+ if (usefsacls) {
+ if (!FileCache::chown(file, uid, (gid_t) faxuid)) {
logError("%s: chown: %s", file, strerror(errno));
- }
+ }
+ } else {
+ if (!FileCache::chown(file, sb.st_uid, (gid_t) uid)) {
+ logError("%s: chown: %s", file, strerror(errno));
+ }
+ }
}
}
@@ -654,7 +683,10 @@
buf.fput(fspec, (u_int) sb.st_size); // XXX
break;
case 'u':
- buf.fput(fspec, (u_int) sb.st_uid);
+ if (usefsacls)
+ buf.fput(fspec, (u_int) sb.st_uid);
+ else
+ buf.fput(fspec, (u_int) sb.st_gid);
break;
}
} else
diff -ru --new-file hylafax-6.0.3/hfaxd/HylaFAXServer.c++ hylafax-6.0.3-ldaf/hfaxd/HylaFAXServer.c++
--- hylafax-6.0.3/hfaxd/HylaFAXServer.c++ 2009-05-15 12:35:39.000000000 -0500
+++ hylafax-6.0.3-ldaf/hfaxd/HylaFAXServer.c++ 2009-10-23 13:26:36.000000000 -0500
@@ -653,6 +655,8 @@
{ "allowsorting", &HylaFAXServer::allowSorting, true },
{ "publicjobq", &HylaFAXServer::publicJobQ, false },
{ "publicrecvq", &HylaFAXServer::publicRecvQ, false },
+{ "usefsacls", &HylaFAXServer::usefsacls, false },
+{ "usepamuid", &HylaFAXServer::usePAMuid, false },
};
void
diff -ru --new-file hylafax-6.0.3/hfaxd/HylaFAXServer.h hylafax-6.0.3-ldaf/hfaxd/HylaFAXServer.h
--- hylafax-6.0.3/hfaxd/HylaFAXServer.h 2009-05-15 12:35:39.000000000 -0500
+++ hylafax-6.0.3-ldaf/hfaxd/HylaFAXServer.h 2009-10-23 13:59:05.000000000 -0500
@@ -236,6 +236,8 @@
bool publicJobQ; // Public/protection on recvq?
bool publicRecvQ; // Public/protection on recvq?
bool allowSorting; // Allow client to make us sort
+ bool usePAMuid; // Use PAM uid
+ bool usefsacls; // Use Extended ACLs
/*
* User authentication and login-related state.
*/
@@ -603,6 +603,9 @@
void getServerStatus(const char* fileName, fxStr& status);
void Mprintf(FILE*, const char*, const ModemConfig&);
void Mprintf(fxStackBuffer&, const char*, const ModemConfig&);
+
+ bool checkFileRights_acl(int op,const struct stat& sb);
+
public:
HylaFAXServer();
virtual ~HylaFAXServer();
diff -ru --new-file hylafax-6.0.3/hfaxd/RecvQueue.c++ hylafax-6.0.3-ldaf/hfaxd/RecvQueue.c++
--- hylafax-6.0.3/hfaxd/RecvQueue.c++ 2009-05-15 12:35:39.000000000 -0500
+++ hylafax-6.0.3-ldaf/hfaxd/RecvQueue.c++ 2009-10-23 12:55:16.000000000 -0500
@@ -464,7 +469,10 @@
buf.fput(fspec, (u_int) sb.st_size); // XXX
break;
case 'o':
- buf.fput(fspec, userName((u_int) sb.st_gid));
+ if (usefsacls)
+ buf.fput(fspec, userName((u_int) sb.st_uid));
+ else
+ buf.fput(fspec, userName((u_int) sb.st_gid));
break;
case 'p':
buf.fput(fspec, ri.npages);
diff -ru --new-file hylafax-6.0.3/hfaxd/User.c++ hylafax-6.0.3-ldaf/hfaxd/User.c++
--- hylafax-6.0.3/hfaxd/User.c++ 2009-05-15 12:35:39.000000000 -0500
+++ hylafax-6.0.3-ldaf/hfaxd/User.c++ 2009-10-14 17:08:30.000000000 -0500
@@ -62,9 +62,15 @@
logError("Unable to open the user access file %s: %s",
(const char*) userAccessFile, strerror(errno));
- if (! check)
+ if (! check) {
check = checkuserPAM(name);
+ if (usePAMuid) {
+ struct passwd *pwd = NULL;
+ pwd = getpwnam(name);
+ uid = pwd->pw_uid;
+ }
+ }
/*
* This causes the user to be prompted for a password
* and then denied access. We do this to guard against
@@ -265,6 +271,14 @@
if (idcache == NULL) // load cache from file
fillIDCache();
const fxStr* hit = idcache->find(id); // check cache
+ if (!hit && usePAMuid) {
+ struct passwd *pwd = NULL;
+ pwd = getpwuid(id);
+ if (pwd) {
+ (*idcache)[id]= fxStr(pwd->pw_name);
+ hit = idcache->find(id);
+ } // new entry
+ }
if (!hit) { // create entry w/ numeric value
(*idcache)[id] = fxStr((int) id, "%u");
hit = idcache->find(id); // new entry