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

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