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 */
OpenFileForSecurity(char * Filename)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 */
DecodeHexChars(char * URL)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
AddDynamicString(const char * String)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
GetSecureString(char * String)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 }
255