7ae50c2fd34f4dd94a4523588931c3c3a6a8196d
[tpg/acess2.git] / KernelLand / Kernel / vfs / acls.c
1 /* 
2  * Acess Micro VFS
3  */
4 #include <acess.h>
5 #include "vfs.h"
6 #include "vfs_int.h"
7
8 // === PROTOTYPES ===
9 Uint    VFS_int_CheckACLs(tVFS_ACL *ACLs, int Num, int bDeny, Uint Perms, tUID UID, tGID GID);
10
11 // === GLOBALS ===
12 tVFS_ACL        gVFS_ACL_EveryoneRWX = { {1,-1}, {0,VFS_PERM_ALL} };
13 tVFS_ACL        gVFS_ACL_EveryoneRW = { {1,-1}, {0,VFS_PERM_ALL^VFS_PERM_EXEC} };
14 tVFS_ACL        gVFS_ACL_EveryoneRX = { {1,-1}, {0,VFS_PERM_READ|VFS_PERM_EXEC} };
15 tVFS_ACL        gVFS_ACL_EveryoneRO = { {1,-1}, {0,VFS_PERM_READ} };
16
17 // === CODE ===
18 Uint VFS_int_CheckACLs(tVFS_ACL *ACLs, int Num, int bDeny, Uint Perms, tUID UID, tGID GID)
19 {
20          int    i;
21         for(i = 0; i < Num; i ++ )
22         {
23                 if(ACLs[i].Perm.Inv)
24                         continue;       // Ignore ALLOWs
25                 // Check if the entry applies to this case
26                 if(ACLs[i].Ent.ID != 0x7FFFFFFF)
27                 {
28                         if(!ACLs[i].Ent.Group) {
29                                 if(ACLs[i].Ent.ID != UID)       continue;
30                         }
31                         else {
32                                 if(ACLs[i].Ent.ID != GID)       continue;
33                         }
34                 }
35                 
36                 //Log("Deny %x", Node->ACLs[i].Perms);
37                 
38                 if(bDeny && (ACLs[i].Perm.Perms & Perms) != 0 )
39                 {
40                         return ACLs[i].Perm.Perms & Perms;
41                 }
42                 if(!bDeny && (ACLs[i].Perm.Perms & Perms) == Perms)
43                 {
44                         return 0;       //(~ACLs[i].Perm.Perms) & Perms;
45                 }
46         }
47         return bDeny ? 0 : Perms;
48 }
49
50 /**
51  * \fn int VFS_CheckACL(tVFS_Node *Node, Uint Permissions)
52  * \brief Checks the permissions on a file
53  */
54 int VFS_CheckACL(tVFS_Node *Node, Uint Permissions)
55 {
56         Uint    rv;
57          int    uid = Threads_GetUID();
58          int    gid = Threads_GetGID();
59         
60         // Root can do anything
61         if(uid == 0)    return 1;
62         
63         // Root only file?, fast return
64         if( Node->NumACLs == 0 ) {
65                 Log("VFS_CheckACL - %p inaccesable, NumACLs = 0, uid=%i", Node, uid);
66                 return 0;
67         }
68         
69         // Check Deny Permissions
70         rv = VFS_int_CheckACLs(Node->ACLs, Node->NumACLs, 1, Permissions, uid, gid);
71         if( !rv )
72                 Log("VFS_CheckACL - %p inaccesable, %x denied", Node, rv);
73                 return 0;
74         rv = VFS_int_CheckACLs(Node->ACLs, Node->NumACLs, 0, Permissions, uid, gid);
75         if( !rv ) {
76                 Log("VFS_CheckACL - %p inaccesable, %x not allowed", Node, rv);
77                 return 0;
78         }
79
80         return 1;
81 }
82 /**
83  * \fn int VFS_GetACL(int FD, tVFS_ACL *Dest)
84  */
85 int VFS_GetACL(int FD, tVFS_ACL *Dest)
86 {
87          int    i;
88         tVFS_Handle     *h = VFS_GetHandle(FD);
89         
90         // Error check
91         if(!h) {
92                 return -1;
93         }
94         
95         // Root can do anything
96         if(Dest->Ent.Group == 0 && Dest->Ent.ID == 0) {
97                 Dest->Perm.Inv = 0;
98                 Dest->Perm.Perms = -1;
99                 return 1;
100         }
101         
102         // Root only file?, fast return
103         if( h->Node->NumACLs == 0 ) {
104                 Dest->Perm.Inv = 0;
105                 Dest->Perm.Perms = 0;
106                 return 0;
107         }
108         
109         // Check Deny Permissions
110         for(i=0;i<h->Node->NumACLs;i++)
111         {
112                 if(h->Node->ACLs[i].Ent.Group != Dest->Ent.Group)       continue;
113                 if(h->Node->ACLs[i].Ent.ID != Dest->Ent.ID)     continue;
114                 
115                 Dest->Perm.Inv = h->Node->ACLs[i].Perm.Inv;
116                 Dest->Perm.Perms = h->Node->ACLs[i].Perm.Perms;
117                 return 1;
118         }
119         
120         
121         Dest->Perm.Inv = 0;
122         Dest->Perm.Perms = 0;
123         return 0;
124 }
125
126 /**
127  * \fn tVFS_ACL *VFS_UnixToAcessACL(Uint Mode, Uint Owner, Uint Group)
128  * \brief Converts UNIX permissions to three Acess ACL entries
129  */
130 tVFS_ACL *VFS_UnixToAcessACL(Uint Mode, Uint Owner, Uint Group)
131 {
132         tVFS_ACL        *ret = malloc(sizeof(tVFS_ACL)*3);
133         
134         // Error Check
135         if(!ret)        return NULL;
136         
137         // Owner
138         ret[0].Ent.Group = 0; ret[0].Ent.ID = Owner;
139         ret[0].Perm.Inv = 0;  ret[0].Perm.Perms = 0;
140         if(Mode & 0400) ret[0].Perm.Perms |= VFS_PERM_READ;
141         if(Mode & 0200) ret[0].Perm.Perms |= VFS_PERM_WRITE;
142         if(Mode & 0100) ret[0].Perm.Perms |= VFS_PERM_EXEC;
143         
144         // Group
145         ret[1].Ent.Group = 1; ret[1].Ent.ID = Group;
146         ret[1].Perm.Inv = 0;  ret[1].Perm.Perms = 0;
147         if(Mode & 0040) ret[1].Perm.Perms |= VFS_PERM_READ;
148         if(Mode & 0020) ret[1].Perm.Perms |= VFS_PERM_WRITE;
149         if(Mode & 0010) ret[1].Perm.Perms |= VFS_PERM_EXEC;
150         
151         // Global
152         ret[2].Ent.Group = 1; ret[2].Ent.ID = -1;
153         ret[2].Perm.Inv = 0;  ret[2].Perm.Perms = 0;
154         if(Mode & 0004) ret[2].Perm.Perms |= VFS_PERM_READ;
155         if(Mode & 0002) ret[2].Perm.Perms |= VFS_PERM_WRITE;
156         if(Mode & 0001) ret[2].Perm.Perms |= VFS_PERM_EXEC;
157         
158         // Return buffer
159         return ret;
160 }
161
162 // === EXPORTS ===
163 // --- Variables ---
164 EXPORTV(gVFS_ACL_EveryoneRWX);
165 EXPORTV(gVFS_ACL_EveryoneRW);
166 EXPORTV(gVFS_ACL_EveryoneRX);
167 // --- Functions ---
168 EXPORT(VFS_UnixToAcessACL);

UCC git Repository :: git.ucc.asn.au