/* Created: 03.19.05 11:34:57 by Attila Nagyidai $Id: C\040Console.c,v 1.1.2.1 2003/08/13 00:38:46 neum Exp $ This file is part of IBSH (Iron Bars Shell) , a restricted Unix shell Copyright (C) 2005 Attila Nagyidai 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 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Author: Attila Nagyidai Email: na@ent.hu Co-Author: Shy Email: shy@cpan.org Co-Author: Witzy Email: stazzz@altern.org URL: http://ibsh.sourceforge.net IRC: irc.freenode.net #ibsh RSS, Statistics, etc: http://sourceforge.net/projects/ibsh/ */ /* Header files */ #include "ibsh.h" extern Strng extensions[MAX_ITEMS]; /* witzy's fix of the DelBadFiles function, making it work and adding features. It drops rights of the files which don't end with an extension present into the extensions array, deletes symbolic links pointing out of the jail, and makes unexecutable the files that are executable. A message is printed each time such a file is found, explaining what was done. Don't forget that this function chdirs to the path given into parameter, so when DelBadFiles returns, your current working directory is this path. */ void DelBadFiles (const char *basedir) { DIR *dp; struct dirent *list; struct stat info, attr; char tmp[STRING_SIZE]; int i, allowed; strncpy(tmp, basedir, STRING_SIZE - 1); if ( lstat( tmp, &info ) == -1 ) { return; } if ( !S_ISDIR(info.st_mode) ) { return; } if ( (dp = opendir(tmp)) == NULL ) { closedir( dp ); return; } if ( chdir(tmp) == -1 ) { return; } while ( (list = readdir(dp)) != NULL ) { #ifdef DEBUG printf("direntry: %s\n", list->d_name); #endif if ( (lstat(list->d_name, &attr)) < 0 ) continue; // rename long path names #ifdef DEBUG printf("length: %d;\n", (strlen(basedir) + strlen(list->d_name) + 2) ); #endif if ( (strlen(basedir) + strlen(list->d_name) + 2) > 255 ) { snprintf(tmp, 255 - strlen(basedir) - 2, "%s", list->d_name); rename(list->d_name, tmp); #ifdef DEBUG printf("%s renamed to %s !\n", list->d_name, tmp); #endif if ( (antixploit(basedir, tmp)) == 1 ) { removeAllRights(list->d_name, &attr); } if (isExecutable(&attr)) { makeUnexecutable(tmp, &attr); } continue; } if ( S_ISDIR(attr.st_mode) ) { /* in the case of a directory */ if ( ((strcmp(list->d_name, ".")) != 0) && ((strcmp(list->d_name, "..")) != 0) ) { #ifdef DEBUG printf("recursive call for %s\n", list->d_name); #endif DelBadFiles(list->d_name); /* recursively look for bad files in this directory */ chdir (".."); } } else if ( S_ISLNK(attr.st_mode) ) { /* in the case of a symlink */ if ( symlinkGoesOuttaJail(list->d_name) ) { #ifdef DEBUG printf("symlinkoutofjail: %s\n", list->d_name); #endif if (unlink(list->d_name) == 0) { bzero (tmp, sizeof(tmp)); snprintf (tmp, sizeof(tmp)-1, "Illegal symbolic link %s was erased. Contact the sysadmin for policy.\n", list->d_name); logPrintBadfile (tmp); } } } else if (hasSomeRwxRights(&attr)) { /* other cases (in particular a file), only if there are some rights on it */ #ifdef DEBUG printf("%s has some rights\n", list->d_name); #endif /* check the runnability of the file */ if (isExecutable(&attr)) { #ifdef DEBUG printf("%s executable\n", list->d_name); #endif if (makeUnexecutable(list->d_name, &attr) == 0) { bzero (tmp, sizeof(tmp)); snprintf (tmp, sizeof(tmp)-1, "Executable file %s is not anymore. Contact the sysadmin for policy.\n", list->d_name); logPrintBadfile (tmp); } } if ( (antixploit(basedir, list->d_name)) == 1 ) { if (removeAllRights(list->d_name, &attr) == 0) { bzero (tmp, sizeof(tmp)); snprintf (tmp, sizeof(tmp)-1, "Illegal file %s got its rights dropped. Contact the sysadmin for policy.\n", list->d_name); logPrintBadfile (tmp); continue; } } /* check if the file has a permitted extension */ for (i = 0, allowed = 0; (strlen(extensions[i])) > 0 && !allowed; i++) { if ( (strstr(list->d_name, extensions[i])) != NULL ) { #ifdef DEBUG printf("filename: %s; extension: %s\n", list->d_name, extensions[i]); #endif allowed = 1; } } /* for */ if (!allowed) { /* if the file hasn't an allowed extension */ #ifdef DEBUG printf("not allowed extension for %s\n", list->d_name); #endif if (removeAllRights(list->d_name, &attr) == 0) { bzero (tmp, sizeof(tmp)); snprintf (tmp, sizeof(tmp)-1, "Illegal file %s got its rights dropped. Contact the sysadmin for policy.\n", list->d_name); logPrintBadfile (tmp); } } } /* else */ } /* while */ closedir( dp ); } /* takes a symlink location, resolves it and returns : 1 if the symlink points out of the jail 0 else, meaning the symlink is ok */ int symlinkGoesOuttaJail (const char * sl) { char fPnted[PATH_MAXb]; char rslvdPath[PATH_MAXb]; /* size of PATH_MAXb because of realpath() behavior */ int i; i = readlink (sl, fPnted, PATH_MAXb); if ( i > 0 && i < PATH_MAXb ) { fPnted[i] = '\0'; if (realpath (fPnted, rslvdPath) == rslvdPath) { if ( strncmp (loggedin.udir, rslvdPath, strlen(loggedin.udir)) == 0 ) return 0; else return 1; } } return 1; /* if this line is reached, there was a problem with the processing of the symlink, e.g. the path is too long, so we should consider that the symlink is bad, and may be deleted by the calling function */ } /* takes a stat structure, and returns 1 if at least one of the user/group/other execution bits or suid/guid are set 0 if no such bit is set at all */ int isExecutable (struct stat * s) { if ( ((s->st_mode & S_IXUSR) == S_IXUSR) | ((s->st_mode & S_IXGRP) == S_IXGRP) | ((s->st_mode & S_IXOTH) == S_IXOTH) | ((s->st_mode & S_ISUID) == S_ISUID) | ((s->st_mode & S_ISGID) == S_ISGID) ) return 1; return 0; } int hasSomeRwxRights (struct stat * s) { if ( ((s->st_mode & S_IRWXU) != 0) | ((s->st_mode & S_IRWXG) != 0) | ((s->st_mode & S_IRWXO) != 0) ) return 1; return 0; } int makeUnexecutable (const char * filename, struct stat * s) { return chmod (filename, s->st_mode & ~(S_IXUSR | S_IXGRP | S_IXOTH | S_ISUID | S_ISGID) ); } int removeAllRights (const char * filename, struct stat * s) { return chmod (filename, s->st_mode & ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID) ); } void logPrintBadfile (const char * msg) { OPENLOG; syslog(LOG_WARNING, "%s", msg); CLOSELOG; // printf ("ibsh: %s\n", msg); }