import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / net / khttpd / security.c
1 /*
2
3 kHTTPd -- the next generation
4
5 Permissions/Security functions
6
7 */
8
9 /****************************************************************
10  *      This program is free software; you can redistribute it and/or modify
11  *      it under the terms of the GNU General Public License as published by
12  *      the Free Software Foundation; either version 2, or (at your option)
13  *      any later version.
14  *
15  *      This program is distributed in the hope that it will be useful,
16  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *      GNU General Public License for more details.
19  *
20  *      You should have received a copy of the GNU General Public License
21  *      along with this program; if not, write to the Free Software
22  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  ****************************************************************/
25
26
27 #include <linux/kernel.h>
28
29 #include <linux/errno.h>
30 #include <linux/slab.h>
31 #include <linux/net.h>
32 #include <linux/sched.h>
33 #include <linux/skbuff.h>
34 #include <linux/smp_lock.h>
35 #include <linux/un.h>
36 #include <linux/unistd.h>
37
38 #include <net/ip.h>
39 #include <net/sock.h>
40 #include <net/tcp.h>
41
42 #include <asm/atomic.h>
43 #include <asm/semaphore.h>
44 #include <asm/processor.h>
45 #include <asm/uaccess.h>
46
47 #include <linux/file.h>
48
49 #include "sysctl.h"
50 #include "security.h"
51 #include "prototypes.h"
52
53 /*
54
55 The basic security function answers "Userspace" when any one of the following 
56 conditions is met:
57
58 1) The filename contains a "?" (this is before % decoding, all others are 
59                                 after % decoding)
60 2) The filename doesn't start with a "/"                                
61 3) The file does not exist
62 4) The file does not have enough permissions 
63    (sysctl-configurable, default = worldreadble)
64 5) The file has any of the "forbidden" permissions 
65    (sysctl-configurable, default = execute, directory and sticky)
66 6) The filename contains a string as defined in the "Dynamic" list.
67
68 */      
69
70
71 /* Prototypes */
72
73 static void DecodeHexChars(char *URL);
74 static struct DynamicString *DynamicList=NULL;
75
76         
77
78 /*
79
80 The function "OpenFileForSecurity" returns either the "struct file" pointer
81 of the file, or NULL. NULL means "let userspace handle it". 
82
83 */
84 struct file *OpenFileForSecurity(char *Filename)
85 {
86         struct file *filp = NULL;
87         struct DynamicString *List;
88         umode_t permission;
89         
90         EnterFunction("OpenFileForSecurity");
91         if (Filename==NULL)
92                 goto out_error;
93         
94         if (strlen(Filename)>=256 )
95                 goto out_error;  /* Sanity check */
96         
97         /* Rule no. 1  -- No "?" characters */
98 #ifndef BENCHMARK       
99         if (strchr(Filename,'?')!=NULL)
100                 goto out_error;
101
102         /* Intermediate step: decode all %hex sequences */
103         
104         DecodeHexChars(Filename);
105
106         /* Rule no. 2  -- Must start with a "/" */
107         
108         if (Filename[0]!='/')
109                 goto out_error;
110                 
111 #endif
112         /* Rule no. 3 -- Does the file exist ? */
113
114         filp = filp_open(Filename, O_RDONLY, 0);
115         
116         if (IS_ERR(filp))
117                 goto out_error;
118
119 #ifndef BENCHMARK               
120         permission = filp->f_dentry->d_inode->i_mode;
121         
122         /* Rule no. 4 : must have enough permissions */
123         
124         if ((permission & sysctl_khttpd_permreq)==0)
125                 goto out_error_put;     
126
127         /* Rule no. 5 : cannot have "forbidden" permission */
128         
129         if ((permission & sysctl_khttpd_permforbid)!=0)
130                 goto out_error_put;     
131                 
132         /* Rule no. 6 : No string in DynamicList can be a
133                         substring of the filename */
134         
135         List = DynamicList;
136         while (List!=NULL)
137         {
138                 if (strstr(Filename,List->value)!=NULL)
139                         goto out_error_put;     
140
141                 List = List->Next;
142         }
143         
144 #endif  
145         LeaveFunction("OpenFileForSecurity - success");
146 out:
147         return filp;
148
149 out_error_put:
150         fput(filp);
151 out_error:
152         filp=NULL;
153         LeaveFunction("OpenFileForSecurity - fail");
154         goto out;
155 }
156
157 /* 
158
159 DecodeHexChars does the actual %HEX decoding, in place. 
160 In place is possible because strings only get shorter by this.
161
162 */
163 static void DecodeHexChars(char *URL)
164 {
165         char *Source,*Dest;
166         int val,val2;
167         
168         EnterFunction("DecodeHexChars");
169         
170         Source = strchr(URL,'%');
171         
172         if (Source==NULL) 
173                 return;
174                 
175         Dest = Source;
176         
177         while (*Source!=0)
178         {
179                 if (*Source=='%')
180                 {
181                         Source++;
182                         val = *Source;
183                         
184                         if (val>'Z') val-=0x20;
185                         val = val - '0';
186                         if (val<0) val=0; 
187                         if (val>9) val-=7;
188                         if (val>15) val=15;
189                         
190                         Source++;
191
192                         val2 = *Source;
193                         
194                         if (val2>'Z') val2-=0x20;
195                         val2 = val2 - '0';
196                         if (val2<0) val2=0; 
197                         if (val2>9) val2-=7;
198                         if (val2>15) val2=15;
199
200                         *Dest=val*16+val2;
201                 } else *Dest = *Source;
202                 Dest++;
203                 Source++;
204         }
205         *Dest=0;        
206         
207         LeaveFunction("DecodeHexChars");
208 }
209
210
211 void AddDynamicString(const char *String)
212 {
213         struct DynamicString *Temp;
214         
215         EnterFunction("AddDynamicString");
216         
217         Temp = (struct DynamicString*)kmalloc(sizeof(struct DynamicString),(int)GFP_KERNEL);
218         
219         if (Temp==NULL) 
220                 return;
221                 
222         memset(Temp->value,0,sizeof(Temp->value));
223         strncpy(Temp->value,String,sizeof(Temp->value)-1);
224         
225         Temp->Next = DynamicList;
226         DynamicList = Temp;
227         
228         LeaveFunction("AddDynamicString");
229 }
230
231 void GetSecureString(char *String)
232 {
233         struct DynamicString *Temp;
234         int max;
235         
236         EnterFunction("GetSecureString");
237         
238         *String = 0;
239         
240         memset(String,0,255);
241         
242         strncpy(String,"Dynamic strings are : -",255);
243         Temp = DynamicList;
244         while (Temp!=NULL)
245         {
246                 max=253 - strlen(String) - strlen(Temp->value);
247                 strncat(String,Temp->value,max);
248                 max=253 - strlen(String) - 3;
249                 strncat(String,"- -",max);
250                 Temp = Temp->Next;
251         }       
252         
253         LeaveFunction("GetSecureString");
254 }