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