2

I need to write a program, part of which involves checking if the userid of the person executing the program exists in the ACL file of a file which the program uses. That is, this program writes into the file and only users whose ID and privileges are entered in the ACL are allowed to do so. How can the program check this? I know that I need to use the getresid function to get the RUID of the executing process, but how do I check this value against all the values stored in the ACL? Please help me!

CodingInCircles
  • 2,565
  • 11
  • 59
  • 84

2 Answers2

2

Traditionally, linux programs don't do interpretive access control very much. There are two cases.

Case 1, the simple case. A file has an acl (or just modes). Some user runs a program under his user/group set, and the kernel either allows or denies based on the modes/acl. All done.

Case 2, the hard case. A program runs as root, but wishes to operate on behalf of some other user. So, it calls setuid/setgid to 'become' that user, then performs the operation (like opening a file), and then calls to restore itself to root-itude afterwards.

However, based on your comments to chown's answer, I think that you are just in case 1. The user foo runs the program, so the kernel does all the work for you.

bmargulies
  • 97,814
  • 39
  • 186
  • 310
  • The program has the SUID bit set, which means that the user has ownership of the file and the EUID will be of the owner. When someone else wants to execute his binary, the RUID of that user has to be matched with the ID in the ACL. I think this would then be case 2? – CodingInCircles Sep 24 '11 at 22:49
  • yes, that's it. You need to call setXXX to 'become' the 'on-behalf-of' user before calling 'open' or whatever. – bmargulies Sep 24 '11 at 22:54
1

If I misunderstood the question I apologize, but hopefully you will find this helpful:

Exceprt from some acl documentation:

The following functions retrieve and manipulate ACL entries:

acl_copy_entry()
acl_create_entry()
acl_delete_entry()
acl_first_entry()
acl_get_entry()

The following functions retrieve and manipulate fields in an ACL entry:

acl_add_perm() 
acl_clear_perm()
alc_delete_perm() 
acl_get_permset() 
acl_get_qualifier() 
acl_get_tag_type() 
acl_set_permset() 
acl_set_qualifier() 
acl_set_tag_type()

...

ACL Entries

An ACL entry consists of the following fields:

Tag type (defined in the acl.h header file):

ACL_USER_OBJ - The owning user entry.

ACL_GROUP_OBJ - The owning group entry.

ACL_USER - An entry for other users.

ACL_GROUP - An entry for other groups.

ACL_OTHER_OBJ - The entry for all users and groups that are not included in another entry.

Tag qualifier - The qualifier value for a ACL_USER entry is a user ID.

The qualifier value for a ACL_GROUP entry is a group ID. The qualifier value for any of the *_OBJ entries is NULL.

From acl_update.c:

/* 
Find the the ACL entry in 'acl' corresponding to the tag type and
   qualifier in 'tag' and 'id'. Return the matching entry, or NULL
   if no entry was found. */

static acl_entry_t
findEntry(acl_t acl, acl_tag_t tag, id_t qaul)
{
    acl_entry_t entry;
    acl_tag_t entryTag;
    uid_t *uidp;
    gid_t *gidp;
    int ent, s;

    for (ent = ACL_FIRST_ENTRY; ; ent = ACL_NEXT_ENTRY) {
        s = acl_get_entry(acl, ent, &entry);
        if (s == -1)
            errExit("acl_get_entry");

        if (s == 0)
            return NULL;

        if (acl_get_tag_type(entry, &entryTag) == -1)
            errExit("acl_get_tag_type");

        if (tag == entryTag) {
            if (tag == ACL_USER) {
                uidp = acl_get_qualifier(entry);
                if (uidp == NULL)
                    errExit("acl_get_qualifier");

                if (qaul == *uidp) {
                    if (acl_free(uidp) == -1)
                        errExit("acl_free");
                    return entry;
                } else {
                    if (acl_free(uidp) == -1)
                        errExit("acl_free");
                }

            } else if (tag == ACL_GROUP) {
                gidp = acl_get_qualifier(entry);
                if (gidp == NULL)
                    errExit("acl_get_qualifier");

                if (qaul == *gidp) {
                    if (acl_free(gidp) == -1)
                        errExit("acl_free");
                    return entry;
                } else {
                    if (acl_free(gidp) == -1)
                        errExit("acl_free");
                }

            } else {
                return entry;
            }
        }
    }
}

I dont think u need to check the ACL of a specific file, but if I am wrong, here is some info to do so:

$ getfacl myFile 
# file: myFile
# owner: jon
# group: people
user::rwx
user:foo:rwx
group::rwx
mask::rwx
other::--- 

then to get a uid from the name (untested but should be close):

$ grep /etc/passwd `getfacl myFile | grep owner | split -d":" -f2` | egrep -o "[0-9]+"

Some more resources:

acl/facl examples and reference man acl

POSIX Access Control Lists

statacl

chown
  • 51,908
  • 16
  • 134
  • 170
  • Excellent answer and very close to what I'm looking for. I've already looked up the man page, but wasn't very sure about how to acutally use it in a program. In the sample ACL file, you've written: `user:foo:rwx`. What I need to do is this: If the user foo executes my program, my program needs to check if his name exists in the ACL. Something like: `getresid(&rID);...if(rID exists in ACL file) do thing1, thing2 etc.` That's all I need to do. How to do this? Thanks again for your patience and help! :) And sorry about this :( – CodingInCircles Sep 24 '11 at 22:28
  • Check out [acl_update.c method `findEntry()`](http://man7.org/tlpi/code/online/dist/acl/acl_update.c.html#findEntry). Also pasted it above. Happy to help Akshay :) – chown Sep 24 '11 at 22:33
  • You're a lifesaver! Thanks a lot! :) I'm new to Linux and so it's especially tough for me to even express what I am to look for. Can I ask you more questions, if and when I have them? :) – CodingInCircles Sep 24 '11 at 22:45