File: /usr/src/linux/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;
87 struct DynamicString *List;
88 umode_t permission;
89
90
91
92 EnterFunction("OpenFileForSecurity");
93 if (Filename==NULL)
94 return NULL;
95
96 if (strlen(Filename)>=256 ) return NULL; /* Sanity check */
97
98 /* Rule no. 1 -- No "?" characters */
99 #ifndef BENCHMARK
100 if (strchr(Filename,'?')!=NULL)
101 return NULL;
102
103 /* Intermediate step: decode all %hex sequences */
104
105 DecodeHexChars(Filename);
106
107 /* Rule no. 2 -- Must start with a "/" */
108
109
110 if (Filename[0]!='/')
111 return NULL;
112
113 #endif
114 /* Rule no. 3 -- Does the file exist ? */
115
116 filp = filp_open(Filename, O_RDONLY, 0);
117
118 if (IS_ERR(filp))
119 return NULL;
120
121 #ifndef BENCHMARK
122 permission = filp->f_dentry->d_inode->i_mode;
123
124 /* Rule no. 4 : must have enough permissions */
125
126
127 if ((permission & sysctl_khttpd_permreq)==0)
128 {
129 if (filp!=NULL)
130 fput(filp);
131 filp=NULL;
132 return NULL;
133 }
134
135 /* Rule no. 5 : cannot have "forbidden" permission */
136
137
138 if ((permission & sysctl_khttpd_permforbid)!=0)
139 {
140 if (filp!=NULL)
141 fput(filp);
142 filp=NULL;
143 return NULL;
144 }
145
146 /* Rule no. 6 : No string in DynamicList can be a
147 substring of the filename */
148
149
150 List = DynamicList;
151
152 while (List!=NULL)
153 {
154 if (strstr(Filename,List->value)!=NULL)
155 {
156 if (filp!=NULL)
157 fput(filp);
158 filp=NULL;
159 return NULL;
160 }
161 List = List->Next;
162 }
163
164 #endif
165 LeaveFunction("OpenFileForSecurity - success");
166
167 return filp;
168 }
169
170 /*
171
172 DecodeHexChars does the actual %HEX decoding, in place.
173 In place is possible because strings only get shorter by this.
174
175 */
176 static void DecodeHexChars(char *URL)
177 {
178 char *Source,*Dest;
179 int val,val2;
180
181 EnterFunction("DecodeHexChars");
182
183 Source = strchr(URL,'%');
184
185 if (Source==NULL)
186 return;
187
188 Dest = Source;
189
190 while (*Source!=0)
191 {
192 if (*Source=='%')
193 {
194 Source++;
195 val = *Source;
196
197 if (val>'Z') val-=0x20;
198 val = val - '0';
199 if (val<0) val=0;
200 if (val>9) val-=7;
201 if (val>15) val=15;
202
203 Source++;
204
205 val2 = *Source;
206
207 if (val2>'Z') val2-=0x20;
208 val2 = val2 - '0';
209 if (val2<0) val2=0;
210 if (val2>9) val2-=7;
211 if (val2>15) val2=15;
212
213 *Dest=val*16+val2;
214 } else *Dest = *Source;
215 Dest++;
216 Source++;
217 }
218 *Dest=0;
219
220 LeaveFunction("DecodeHexChars");
221 }
222
223
224 void AddDynamicString(const char *String)
225 {
226 struct DynamicString *Temp;
227
228 EnterFunction("AddDynamicString");
229
230 Temp = (struct DynamicString*)kmalloc(sizeof(struct DynamicString),(int)GFP_KERNEL);
231
232 if (Temp==NULL)
233 return;
234
235 memset(Temp->value,0,sizeof(Temp->value));
236 strncpy(Temp->value,String,sizeof(Temp->value)-1);
237
238 Temp->Next = DynamicList;
239 DynamicList = Temp;
240
241 LeaveFunction("AddDynamicString");
242 }
243
244 void GetSecureString(char *String)
245 {
246 struct DynamicString *Temp;
247 int max;
248
249 EnterFunction("GetSecureString");
250
251 *String = 0;
252
253 memset(String,0,255);
254
255 strncpy(String,"Dynamic strings are : -",255);
256 Temp = DynamicList;
257 while (Temp!=NULL)
258 {
259 max=253 - strlen(String) - strlen(Temp->value);
260 strncat(String,Temp->value,max);
261 max=253 - strlen(String) - 3;
262 strncat(String,"- -",max);
263 Temp = Temp->Next;
264 }
265
266 LeaveFunction("GetSecureString");
267 }
268