| /* |
| |
| kHTTPd -- the next generation |
| |
| Permissions/Security functions |
| |
| */ |
| |
| /**************************************************************** |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2, or (at your option) |
| * any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| * |
| ****************************************************************/ |
| |
| |
| #include <linux/kernel.h> |
| |
| #include <linux/errno.h> |
| #include <linux/slab.h> |
| #include <linux/net.h> |
| #include <linux/sched.h> |
| #include <linux/skbuff.h> |
| #include <linux/smp_lock.h> |
| #include <linux/un.h> |
| #include <linux/unistd.h> |
| |
| #include <net/ip.h> |
| #include <net/sock.h> |
| #include <net/tcp.h> |
| |
| #include <asm/atomic.h> |
| #include <asm/semaphore.h> |
| #include <asm/processor.h> |
| #include <asm/uaccess.h> |
| |
| #include <linux/file.h> |
| |
| #include "sysctl.h" |
| #include "security.h" |
| #include "prototypes.h" |
| |
| /* |
| |
| The basic security function answers "Userspace" when any one of the following |
| conditions is met: |
| |
| 1) The filename contains a "?" (this is before % decoding, all others are |
| after % decoding) |
| 2) The filename doesn't start with a "/" |
| 3) The file does not exist |
| 4) The file does not have enough permissions |
| (sysctl-configurable, default = worldreadble) |
| 5) The file has any of the "forbidden" permissions |
| (sysctl-configurable, default = execute, directory and sticky) |
| 6) The filename contains a string as defined in the "Dynamic" list. |
| |
| */ |
| |
| |
| /* Prototypes */ |
| |
| static void DecodeHexChars(char *URL); |
| static struct DynamicString *DynamicList=NULL; |
| |
| |
| |
| /* |
| |
| The function "OpenFileForSecurity" returns either the "struct file" pointer |
| of the file, or NULL. NULL means "let userspace handle it". |
| |
| */ |
| struct file *OpenFileForSecurity(char *Filename) |
| { |
| struct file *filp = NULL; |
| struct DynamicString *List; |
| umode_t permission; |
| |
| EnterFunction("OpenFileForSecurity"); |
| if (Filename==NULL) |
| goto out_error; |
| |
| if (strlen(Filename)>=256 ) |
| goto out_error; /* Sanity check */ |
| |
| /* Rule no. 1 -- No "?" characters */ |
| #ifndef BENCHMARK |
| if (strchr(Filename,'?')!=NULL) |
| goto out_error; |
| |
| /* Intermediate step: decode all %hex sequences */ |
| |
| DecodeHexChars(Filename); |
| |
| /* Rule no. 2 -- Must start with a "/" */ |
| |
| if (Filename[0]!='/') |
| goto out_error; |
| |
| #endif |
| /* Rule no. 3 -- Does the file exist ? */ |
| |
| filp = filp_open(Filename, O_RDONLY, 0); |
| |
| if (IS_ERR(filp)) |
| goto out_error; |
| |
| #ifndef BENCHMARK |
| permission = filp->f_dentry->d_inode->i_mode; |
| |
| /* Rule no. 4 : must have enough permissions */ |
| |
| if ((permission & sysctl_khttpd_permreq)==0) |
| goto out_error_put; |
| |
| /* Rule no. 5 : cannot have "forbidden" permission */ |
| |
| if ((permission & sysctl_khttpd_permforbid)!=0) |
| goto out_error_put; |
| |
| /* Rule no. 6 : No string in DynamicList can be a |
| substring of the filename */ |
| |
| List = DynamicList; |
| while (List!=NULL) |
| { |
| if (strstr(Filename,List->value)!=NULL) |
| goto out_error_put; |
| |
| List = List->Next; |
| } |
| |
| #endif |
| LeaveFunction("OpenFileForSecurity - success"); |
| out: |
| return filp; |
| |
| out_error_put: |
| fput(filp); |
| out_error: |
| filp=NULL; |
| LeaveFunction("OpenFileForSecurity - fail"); |
| goto out; |
| } |
| |
| /* |
| |
| DecodeHexChars does the actual %HEX decoding, in place. |
| In place is possible because strings only get shorter by this. |
| |
| */ |
| static void DecodeHexChars(char *URL) |
| { |
| char *Source,*Dest; |
| int val,val2; |
| |
| EnterFunction("DecodeHexChars"); |
| |
| Source = strchr(URL,'%'); |
| |
| if (Source==NULL) |
| return; |
| |
| Dest = Source; |
| |
| while (*Source!=0) |
| { |
| if (*Source=='%') |
| { |
| Source++; |
| val = *Source; |
| |
| if (val>'Z') val-=0x20; |
| val = val - '0'; |
| if (val<0) val=0; |
| if (val>9) val-=7; |
| if (val>15) val=15; |
| |
| Source++; |
| |
| val2 = *Source; |
| |
| if (val2>'Z') val2-=0x20; |
| val2 = val2 - '0'; |
| if (val2<0) val2=0; |
| if (val2>9) val2-=7; |
| if (val2>15) val2=15; |
| |
| *Dest=val*16+val2; |
| } else *Dest = *Source; |
| Dest++; |
| Source++; |
| } |
| *Dest=0; |
| |
| LeaveFunction("DecodeHexChars"); |
| } |
| |
| |
| void AddDynamicString(const char *String) |
| { |
| struct DynamicString *Temp; |
| |
| EnterFunction("AddDynamicString"); |
| |
| Temp = (struct DynamicString*)kmalloc(sizeof(struct DynamicString),(int)GFP_KERNEL); |
| |
| if (Temp==NULL) |
| return; |
| |
| memset(Temp->value,0,sizeof(Temp->value)); |
| strncpy(Temp->value,String,sizeof(Temp->value)-1); |
| |
| Temp->Next = DynamicList; |
| DynamicList = Temp; |
| |
| LeaveFunction("AddDynamicString"); |
| } |
| |
| void GetSecureString(char *String) |
| { |
| struct DynamicString *Temp; |
| int max; |
| |
| EnterFunction("GetSecureString"); |
| |
| *String = 0; |
| |
| memset(String,0,255); |
| |
| strncpy(String,"Dynamic strings are : -",255); |
| Temp = DynamicList; |
| while (Temp!=NULL) |
| { |
| max=253 - strlen(String) - strlen(Temp->value); |
| strncat(String,Temp->value,max); |
| max=253 - strlen(String) - 3; |
| strncat(String,"- -",max); |
| Temp = Temp->Next; |
| } |
| |
| LeaveFunction("GetSecureString"); |
| } |