Main Page | Class List | Directories | File List | Class Members | File Members

filedir.c

Go to the documentation of this file.
00001 /* cfengine for GNU
00002  
00003         Copyright (C) 1995
00004         Free Software Foundation, Inc.
00005  
00006    This file is part of GNU cfengine - written and maintained 
00007    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
00008    Dept. of Theoretical physics, University of Oslo
00009  
00010    This program is free software; you can redistribute it and/or modify it
00011    under the terms of the GNU General Public License as published by the
00012    Free Software Foundation; either version 2, or (at your option) any
00013    later version.
00014  
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019  
00020   You should have received a copy of the GNU General Public License
00021   along with this program; if not, write to the Free Software
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00023 
00024 */
00025  
00026 
00027 #include "cf.defs.h"
00028 #include "cf.extern.h"
00029 
00030 
00031 /*********************************************************************/
00032 
00033 int IsHomeDir(name)
00034 
00035       /* This assumes that the dir lies under mountpattern */
00036 
00037 char *name;
00038 
00039 { char *sp;
00040   struct Item *ip;
00041   int slashes;
00042 
00043 if (name == NULL || strlen(name) == 0)
00044    {
00045    return false;
00046    }
00047   
00048 if (VMOUNTLIST == NULL)
00049    {
00050    return (false);
00051    } 
00052 
00053 for (ip = VHOMEPATLIST; ip != NULL; ip=ip->next)
00054    {
00055    slashes = 0;
00056 
00057    for (sp = ip->name; *sp != '\0'; sp++)
00058       {
00059       if (*sp == '/')
00060          {
00061          slashes++;
00062          }
00063       }
00064    
00065    for (sp = name+strlen(name); (*(sp-1) != '/') && (sp >= name) && (slashes >= 0); sp--)
00066       {
00067       if (*sp == '/')
00068          {
00069          slashes--;
00070          }
00071       }
00072 
00073    /* Full comparison */
00074    
00075    if (WildMatch(ip->name,sp))
00076       {
00077       Debug("IsHomeDir(true)\n");
00078       return(true);
00079       }
00080    }
00081 
00082 Debug("IsHomeDir(false)\n");
00083 return(false);
00084 }
00085 
00086 
00087 /*********************************************************************/
00088 
00089 int EmptyDir(path)
00090 
00091 char *path;
00092 
00093 { DIR *dirh;
00094   struct dirent *dirp;
00095   int count = 0;
00096   
00097 Debug2("cfengine: EmptyDir(%s)\n",path);
00098 
00099 if ((dirh = opendir(path)) == NULL)
00100    {
00101    snprintf(OUTPUT,bufsize*2,"Can't open directory %s\n",path);
00102    CfLog(cfverbose,OUTPUT,"opendir");
00103    return true;
00104    }
00105 
00106 for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
00107    {
00108    if (!SensibleFile(dirp->d_name,path,NULL))
00109       {
00110       continue;
00111       }
00112 
00113    count++;
00114    }
00115 
00116 closedir(dirh);
00117 
00118 return (!count);
00119 }
00120 
00121 /*********************************************************************/
00122 
00123 int RecursiveCheck(name,plus,minus,action,uidlist,gidlist,recurse,rlevel,ptr,sb)
00124 
00125 char *name;
00126 mode_t plus,minus;
00127 struct UidList *uidlist;
00128 struct GidList *gidlist;
00129 enum fileactions action;
00130 int recurse;
00131 int rlevel;
00132 struct File *ptr;
00133 struct stat *sb;
00134 
00135 { DIR *dirh;
00136   int goback; 
00137   struct dirent *dirp;
00138   char pcwd[bufsize];
00139   struct stat statbuf;
00140   
00141 if (recurse == -1)
00142    {
00143    return false;
00144    }
00145 
00146 if (rlevel > recursion_limit)
00147    {
00148    snprintf(OUTPUT,bufsize*2,"WARNING: Very deep nesting of directories (>%d deep): %s (Aborting files)",rlevel,name);
00149    CfLog(cferror,OUTPUT,"");
00150    return false;
00151    }
00152  
00153 bzero(pcwd,bufsize); 
00154 
00155 Debug("RecursiveCheck(%s,+%o,-%o)\n",name,plus,minus);
00156 
00157 if (!DirPush(name,sb))
00158    {
00159    return false;
00160    }
00161  
00162 if ((dirh = opendir(".")) == NULL)
00163    {
00164    if (lstat(name,&statbuf) != -1)
00165       {
00166       CheckExistingFile(name,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
00167       }
00168    return true;
00169    }
00170 
00171 for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
00172    {
00173    if (!SensibleFile(dirp->d_name,name,NULL))
00174       {
00175       continue;
00176       }
00177 
00178    if (IgnoreFile(name,dirp->d_name,ptr->ignores))
00179       {
00180       continue;
00181       }
00182    
00183    strcpy(pcwd,name);                                   /* Assemble pathname */
00184    AddSlash(pcwd);
00185 
00186    if (BufferOverflow(pcwd,dirp->d_name))
00187       {
00188       closedir(dirh);
00189       return true;
00190       }
00191 
00192    strcat(pcwd,dirp->d_name);
00193 
00194    if (lstat(dirp->d_name,&statbuf) == -1)
00195       {
00196       snprintf(OUTPUT,bufsize*2,"RecursiveCheck was looking at %s when this happened:\n",pcwd);
00197       CfLog(cferror,OUTPUT,"lstat");
00198       continue;
00199       }
00200    
00201    if (TRAVLINKS)
00202       {
00203       if (lstat(dirp->d_name,&statbuf) == -1)
00204          {
00205          snprintf(OUTPUT,bufsize*2,"Can't stat %s\n",pcwd);
00206          CfLog(cferror,OUTPUT,"stat");
00207          continue;
00208          }
00209 
00210       if (S_ISLNK(statbuf.st_mode) && (statbuf.st_mode != getuid()))      
00211          {
00212          snprintf(OUTPUT,bufsize,"File %s is an untrusted link. cfagent will not follow it with a destructive operation (tidy)",pcwd);
00213          continue;
00214          }
00215 
00216       if (stat(dirp->d_name,&statbuf) == -1)
00217          {
00218          snprintf(OUTPUT,bufsize*2,"RecursiveCheck was working on %s when this happened:\n",pcwd);
00219          CfLog(cferror,OUTPUT,"stat");
00220          continue;
00221          }
00222       }
00223 
00224 
00225    if (S_ISLNK(statbuf.st_mode))            /* should we ignore links? */
00226       {
00227       CheckExistingFile(pcwd,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
00228       continue;
00229       }
00230 
00231    if (S_ISDIR(statbuf.st_mode))
00232       {
00233       if (IsMountedFileSystem(&statbuf,pcwd,rlevel))
00234          {
00235          continue;
00236          }
00237       else
00238          {
00239          if ((ptr->recurse > 1) || (ptr->recurse == INFINITERECURSE))
00240             {
00241             CheckExistingFile(pcwd,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
00242             goback = RecursiveCheck(pcwd,plus,minus,action,uidlist,gidlist,recurse-1,rlevel+1,ptr,&statbuf);
00243             DirPop(goback,name,sb);
00244             }
00245          else
00246             {
00247             CheckExistingFile(pcwd,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
00248             }
00249          }
00250       }
00251    else
00252       {
00253       CheckExistingFile(pcwd,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
00254       }
00255    }
00256 
00257 closedir(dirh);
00258 return true; 
00259 }
00260 
00261 
00262 /*********************************************************************/
00263 
00264 void CheckExistingFile(file,plus,minus,action,uidlist,gidlist,dstat,ptr,acl_aliases)
00265 
00266 char *file;
00267 mode_t plus,minus;
00268 struct UidList *uidlist;
00269 struct GidList *gidlist;
00270 enum fileactions action;
00271 struct stat *dstat;
00272 struct File *ptr;
00273 struct Item *acl_aliases;
00274  
00275 { mode_t newperm = dstat->st_mode, maskvalue;
00276   int amroot = true, fixmode = true, docompress=false;
00277   unsigned char digest[EVP_MAX_MD_SIZE+1];
00278 
00279 #if defined HAVE_CHFLAGS
00280   u_long newflags;
00281 #endif
00282 
00283 maskvalue = umask(0);                 /* This makes the DEFAULT modes absolute */
00284  
00285 if (action == compress)
00286    {
00287    docompress = true;
00288    if (ptr != NULL)
00289       {
00290       AddMultipleClasses(ptr->defines);
00291       }
00292    action = fixall;    /* Fix any permissions which are set */
00293    }
00294   
00295 Debug("%s: Checking fs-object %s\n",VPREFIX,file);
00296 
00297 #if defined HAVE_CHFLAGS
00298 if (ptr != NULL)
00299    {
00300    Debug("CheckExistingFile(+%o,-%o,+%o,-%o)\n",plus,minus,ptr->plus_flags,ptr->minus_flags);
00301    }
00302 else
00303    {
00304    Debug("CheckExistingFile(+%o,-%o)\n",plus,minus);
00305    }
00306 #else
00307 Debug("CheckExistingFile(+%o,-%o)\n",plus,minus);
00308 #endif
00309  
00310 if (ptr != NULL)
00311    {
00312    if (IgnoredOrExcluded(files,file,ptr->inclusions,ptr->exclusions))
00313       {
00314       Debug("Skipping excluded file %s\n",file);
00315       umask(maskvalue);
00316       return;
00317       }
00318 
00319    if (!FileObjectFilter(file,dstat,ptr->filters,files))
00320       {
00321       Debug("Skipping filtered file %s\n",file);
00322       umask(maskvalue);
00323       return;
00324       }
00325 
00326    if (action == alert)
00327       {
00328       snprintf(OUTPUT,bufsize*2,"Alert specified on file %s (m=%o,o=%d,g=%d)",file,(dstat->st_mode & 07777),dstat->st_uid,dstat->st_gid);
00329       CfLog(cferror,OUTPUT,"");
00330       return;
00331       }
00332    }
00333 
00334 if (!IsPrivileged())                            
00335    {
00336    amroot = false;
00337    }
00338 
00339  /* directories must have x set if r set, regardless  */
00340 
00341 
00342 newperm = (dstat->st_mode & 07777);
00343 newperm |= plus;
00344 newperm &= ~minus;
00345 
00346 if (S_ISREG(dstat->st_mode) && (action == fixdirs || action == warndirs)) 
00347    {
00348    Debug("Regular file, returning...\n");
00349    umask(maskvalue);
00350    return;
00351    }
00352 
00353 if (S_ISDIR(dstat->st_mode))  
00354    {
00355    if (action == fixplain || action == warnplain)
00356       {
00357       umask(maskvalue);
00358       return;
00359       }
00360 
00361    Debug("Directory...fixing x bits\n");
00362 
00363    if (newperm & S_IRUSR)
00364       {
00365       newperm  |= S_IXUSR;
00366       }
00367 
00368    if (newperm & S_IRGRP)
00369       {
00370       newperm |= S_IXGRP;
00371       }
00372 
00373    if (newperm & S_IROTH)
00374       {
00375       newperm |= S_IXOTH;
00376       }
00377    }
00378 
00379 if (dstat->st_uid == 0 && (dstat->st_mode & S_ISUID))
00380    {
00381    if (newperm & S_ISUID)
00382       {
00383       if (! IsItemIn(VSETUIDLIST,file))
00384          {
00385          if (amroot)
00386             {
00387             snprintf(OUTPUT,bufsize*2,"NEW SETUID root PROGRAM %s\n",file);
00388             CfLog(cfinform,OUTPUT,"");
00389             }
00390          PrependItem(&VSETUIDLIST,file,NULL);
00391          }
00392       }
00393    else
00394       {
00395       switch (action)
00396          {
00397          case fixall:
00398          case fixdirs:
00399          case fixplain:  snprintf(OUTPUT,bufsize*2,"Removing setuid (root) flag from %s...\n\n",file);
00400                          CfLog(cfinform,OUTPUT,"");
00401                          
00402                          if (ptr != NULL)
00403                             {
00404                             AddMultipleClasses(ptr->defines);
00405                             }
00406                          break;
00407          case warnall:
00408          case warndirs:
00409          case warnplain: if (amroot)
00410                             {
00411                             snprintf(OUTPUT,bufsize*2,"WARNING setuid (root) flag on %s...\n\n",file);
00412                             CfLog(cferror,OUTPUT,"");
00413                             }
00414                          break;
00415 
00416          }
00417       }
00418    }
00419 
00420 if (dstat->st_uid == 0 && (dstat->st_mode & S_ISGID))
00421    {
00422    if (newperm & S_ISGID)
00423       {
00424       if (! IsItemIn(VSETUIDLIST,file))
00425          {
00426          if (S_ISDIR(dstat->st_mode))
00427             {
00428             /* setgid directory */
00429             }
00430          else
00431             {
00432             if (amroot)
00433                {
00434                snprintf(OUTPUT,bufsize*2,"NEW SETGID root PROGRAM %s\n",file);
00435                CfLog(cferror,OUTPUT,"");
00436                }
00437             PrependItem(&VSETUIDLIST,file,NULL);
00438             }
00439          }
00440       }
00441    else
00442       {
00443       switch (action)
00444          {
00445          case fixall:
00446          case fixdirs:
00447          case fixplain: snprintf(OUTPUT,bufsize*2,"Removing setgid (root) flag from %s...\n\n",file);
00448                         CfLog(cfinform,OUTPUT,"");
00449                         if (ptr != NULL)
00450                            {
00451                            AddMultipleClasses(ptr->defines);
00452                            }
00453                         break;
00454          case warnall:
00455          case warndirs:
00456          case warnplain: snprintf(OUTPUT,bufsize*2,"WARNING setgid (root) flag on %s...\n\n",file);
00457                          CfLog(cferror,OUTPUT,"");
00458                          break;
00459 
00460          default:        break;
00461          }
00462       }
00463    }
00464 
00465 if (CheckOwner(file,action,uidlist,gidlist,dstat))
00466    {
00467    if (ptr != NULL)
00468       {
00469       AddMultipleClasses(ptr->defines);
00470       }
00471    }
00472 
00473 if ((ptr != NULL) && S_ISREG(dstat->st_mode) && (ptr->checksum != 'n'))
00474     {
00475     Debug("Checking checksum integrity of %s\n",file);
00476 
00477     bzero(digest,EVP_MAX_MD_SIZE+1);
00478     ChecksumFile(file,digest,ptr->checksum);
00479 
00480     if (!DONTDO)
00481        {
00482        if (ChecksumChanged(file,digest,cferror,false,ptr->checksum))
00483           {
00484           }
00485        }
00486     }
00487 
00488 if (S_ISLNK(dstat->st_mode))             /* No point in checking permission on a link */
00489    {
00490    if (ptr != NULL)
00491       {
00492       KillOldLink(file,ptr->defines);
00493       }
00494    else
00495       {
00496       KillOldLink(file,NULL);
00497       }
00498    umask(maskvalue);
00499    return;
00500    }
00501 
00502 if (stat(file,dstat) == -1)
00503    {
00504    snprintf(OUTPUT,bufsize*2,"Can't stat file %s while looking at permissions (was not copied?)\n",file);
00505    CfLog(cfverbose,OUTPUT,"stat");
00506    umask(maskvalue);
00507    return;
00508    }
00509 
00510 if (CheckACLs(file,action,acl_aliases))
00511    {
00512    if (ptr != NULL)
00513       {
00514       AddMultipleClasses(ptr->defines);
00515       }
00516    }
00517 
00518 #ifndef HAVE_CHFLAGS
00519 if (((newperm & 07777) == (dstat->st_mode & 07777)) && (action != touch))    /* file okay */
00520    {
00521    Debug("File okay, newperm = %o, stat = %o\n",(newperm & 07777),(dstat->st_mode & 07777));
00522    if (docompress)
00523       {
00524       CompressFile(file);
00525       }
00526 
00527    if (ptr != NULL)
00528       {
00529       AddMultipleClasses(ptr->elsedef);
00530       }
00531 
00532    umask(maskvalue);
00533    return;
00534    }
00535 #else
00536 if ((newperm & 07777) == (dstat->st_mode & 07777))    /* file okay */
00537    {
00538    Debug("File okay, newperm = %o, stat = %o\n",(newperm & 07777),(dstat->st_mode & 07777));
00539    fixmode = false;
00540    }
00541 #endif 
00542 
00543 if (fixmode)
00544    {
00545    Debug("Trying to fix mode...\n"); 
00546    
00547    switch (action)
00548       {
00549       case linkchildren:
00550           
00551       case warnplain:
00552           if (S_ISREG(dstat->st_mode))
00553              {
00554              snprintf(OUTPUT,bufsize*2,"%s has permission %o\n",file,dstat->st_mode & 07777);
00555              CfLog(cferror,OUTPUT,"");
00556              snprintf(OUTPUT,bufsize*2,"[should be %o]\n",newperm & 07777);
00557              CfLog(cferror,OUTPUT,"");
00558              }
00559           break;
00560       case warndirs:
00561           if (S_ISDIR(dstat->st_mode))
00562              {
00563              snprintf(OUTPUT,bufsize*2,"%s has permission %o\n",file,dstat->st_mode & 07777);
00564              CfLog(cferror,OUTPUT,"");
00565              snprintf(OUTPUT,bufsize*2,"[should be %o]\n",newperm & 07777);
00566              CfLog(cferror,OUTPUT,"");
00567              }
00568           break;
00569       case warnall:   
00570           snprintf(OUTPUT,bufsize*2,"%s has permission %o\n",file,dstat->st_mode & 07777);
00571           CfLog(cferror,OUTPUT,"");
00572           snprintf(OUTPUT,bufsize*2,"[should be %o]\n",newperm & 07777);
00573           CfLog(cferror,OUTPUT,"");
00574           break;
00575           
00576       case fixplain:
00577           if (S_ISREG(dstat->st_mode))
00578              {
00579              if (! DONTDO)
00580                 {
00581                 if (chmod (file,newperm & 07777) == -1)
00582                    {
00583                    snprintf(OUTPUT,bufsize*2,"chmod failed on %s\n",file);
00584                    CfLog(cferror,OUTPUT,"chmod");
00585                    break;
00586                    }
00587                 }
00588              
00589              snprintf(OUTPUT,bufsize*2,"%s had permission %o, changed it to %o\n",
00590                      file,dstat->st_mode & 07777,newperm & 07777);
00591              CfLog(cfinform,OUTPUT,"");
00592              
00593              if (ptr != NULL)
00594                 {
00595                 AddMultipleClasses(ptr->defines);
00596                 }
00597              }
00598           break;
00599           
00600       case fixdirs:
00601           if (S_ISDIR(dstat->st_mode))
00602              {
00603              if (! DONTDO)
00604                 {
00605                 if (chmod (file,newperm & 07777) == -1)
00606                    {
00607                    snprintf(OUTPUT,bufsize*2,"chmod failed on %s\n",file);
00608                    CfLog(cferror,OUTPUT,"chmod");
00609                    break;
00610                    }
00611                 }
00612              
00613              snprintf(OUTPUT,bufsize*2,"%s had permission %o, changed it to %o\n",
00614                      file,dstat->st_mode & 07777,newperm & 07777);
00615              CfLog(cfinform,OUTPUT,"");
00616              
00617              if (ptr != NULL)
00618                 {
00619                 AddMultipleClasses(ptr->defines);
00620                 }
00621              }
00622           break;
00623           
00624       case fixall:
00625           if (! DONTDO)
00626              {
00627              if (chmod (file,newperm & 07777) == -1)
00628                 {
00629                 snprintf(OUTPUT,bufsize*2,"chmod failed on %s\n",file);
00630                 CfLog(cferror,OUTPUT,"chmod");
00631                 break;
00632                 }
00633              }
00634           
00635           snprintf(OUTPUT,bufsize*2,"%s had permission %o, changed it to %o\n",
00636                   file,dstat->st_mode & 07777,newperm & 07777);
00637           CfLog(cfinform,OUTPUT,"");
00638           
00639           if (ptr != NULL)
00640              {
00641              AddMultipleClasses(ptr->defines);
00642              }
00643           break;
00644           
00645       case touch:
00646           if (! DONTDO)
00647              {
00648              if (chmod (file,newperm & 07777) == -1)
00649                 {
00650                 snprintf(OUTPUT,bufsize*2,"chmod failed on %s\n",file);
00651                 CfLog(cferror,OUTPUT,"chmod");
00652                 break;
00653                 }
00654              utime (file,NULL);
00655              }
00656           if (ptr != NULL)
00657              {
00658              AddMultipleClasses(ptr->defines);
00659              }
00660           break;
00661           
00662       default:     FatalError("cfengine: internal error CheckExistingFile(): illegal file action\n");
00663       }
00664    }
00665 
00666  
00667 #if defined HAVE_CHFLAGS  /* BSD special flags */
00668 
00669 if (ptr != NULL)
00670    {
00671    newflags = (dstat->st_flags & CHFLAGS_MASK) ;
00672    newflags |= ptr->plus_flags;
00673    newflags &= ~(ptr->minus_flags);
00674    
00675    if ((newflags & CHFLAGS_MASK) == (dstat->st_flags & CHFLAGS_MASK))    /* file okay */
00676       {
00677       Debug("File okay, flags = %o, current = %o\n",(newflags & CHFLAGS_MASK),(dstat->st_flags & CHFLAGS_MASK));
00678       }
00679    else
00680       {
00681       Debug("Fixing %s, newflags = %o, flags = %o\n",file,(newflags & CHFLAGS_MASK),(dstat->st_flags & CHFLAGS_MASK));
00682       
00683       switch (action)
00684          {
00685          case linkchildren:
00686              
00687          case warnplain:
00688              if (S_ISREG(dstat->st_mode))
00689                 {
00690                 snprintf(OUTPUT,bufsize*2,"%s has flags %o\n",file,dstat->st_flags & CHFLAGS_MASK);
00691                 CfLog(cferror,OUTPUT,"");
00692                 snprintf(OUTPUT,bufsize*2,"[should be %o]\n",newflags & CHFLAGS_MASK);
00693                 CfLog(cferror,OUTPUT,"");
00694                 }
00695              break;
00696          case warndirs:
00697              if (S_ISDIR(dstat->st_mode))
00698                 {
00699                 snprintf(OUTPUT,bufsize*2,"%s has flags %o\n",file,dstat->st_mode & CHFLAGS_MASK);
00700                 CfLog(cferror,OUTPUT,"");
00701                 snprintf(OUTPUT,bufsize*2,"[should be %o]\n",newflags & CHFLAGS_MASK);
00702                 CfLog(cferror,OUTPUT,"");
00703                 }
00704              break;
00705          case warnall:
00706              snprintf(OUTPUT,bufsize*2,"%s has flags %o\n",file,dstat->st_mode & CHFLAGS_MASK);
00707              CfLog(cferror,OUTPUT,"");
00708              snprintf(OUTPUT,bufsize*2,"[should be %o]\n",newflags & CHFLAGS_MASK);
00709              CfLog(cferror,OUTPUT,"");
00710              break;
00711              
00712          case fixplain:
00713              
00714              if (S_ISREG(dstat->st_mode))
00715                 {
00716                 if (! DONTDO)
00717                    {
00718                    if (chflags (file,newflags & CHFLAGS_MASK) == -1)
00719                       {
00720                       snprintf(OUTPUT,bufsize*2,"chflags failed on %s\n",file);
00721                       CfLog(cferror,OUTPUT,"chflags");
00722                       break;
00723                       }
00724                    }
00725                 
00726                 snprintf(OUTPUT,bufsize*2,"%s had flags %o, changed it to %o\n",
00727                         file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK);
00728                 CfLog(cfinform,OUTPUT,"");
00729                 
00730                 if (ptr != NULL)
00731                    {
00732                    AddMultipleClasses(ptr->defines);
00733                    }
00734                 }
00735              break;
00736              
00737          case fixdirs:
00738              if (S_ISDIR(dstat->st_mode))
00739                 {
00740                 if (! DONTDO)
00741                    {
00742                    if (chflags (file,newflags & CHFLAGS_MASK) == -1)
00743                       {
00744                       snprintf(OUTPUT,bufsize*2,"chflags failed on %s\n",file);
00745                       CfLog(cferror,OUTPUT,"chflags");
00746                       break;
00747                       }
00748                    }
00749                 
00750                 snprintf(OUTPUT,bufsize*2,"%s had flags %o, changed it to %o\n",
00751                         file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK);
00752                 CfLog(cfinform,OUTPUT,"");
00753                 
00754                 if (ptr != NULL)
00755                    {
00756                    AddMultipleClasses(ptr->defines);
00757                    }
00758                 }
00759              break;
00760              
00761       case fixall:
00762           if (! DONTDO)
00763              {
00764              if (chflags (file,newflags & CHFLAGS_MASK) == -1)
00765                 {
00766                 snprintf(OUTPUT,bufsize*2,"chflags failed on %s\n",file);
00767                 CfLog(cferror,OUTPUT,"chflags");
00768                 break;
00769                 }
00770              }
00771           
00772           snprintf(OUTPUT,bufsize*2,"%s had flags %o, changed it to %o\n",
00773                   file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK);
00774           CfLog(cfinform,OUTPUT,"");
00775           
00776           if (ptr != NULL)
00777              {
00778              AddMultipleClasses(ptr->defines);
00779              }
00780           break;
00781           
00782       case touch:
00783           if (! DONTDO)
00784              {
00785              if (chflags (file,newflags & CHFLAGS_MASK) == -1)
00786                 {
00787                 snprintf(OUTPUT,bufsize*2,"chflags failed on %s\n",file);
00788                 CfLog(cferror,OUTPUT,"chflags");
00789                 break;
00790                 }
00791              utime (file,NULL);
00792              }
00793           if (ptr != NULL)
00794              {
00795              AddMultipleClasses(ptr->defines);
00796              }
00797           break;
00798           
00799          default:     FatalError("cfengine: internal error CheckExistingFile(): illegal file action\n");
00800          }
00801       }
00802    }
00803 #endif
00804 
00805 if (docompress)
00806    {
00807    CompressFile(file);
00808    if (ptr != NULL)
00809       {
00810       AddMultipleClasses(ptr->defines);
00811       }
00812    }
00813 
00814 umask(maskvalue);  
00815 Debug("CheckExistingFile(Done)\n"); 
00816 }
00817 
00818 /*********************************************************************/
00819 
00820 void CheckCopiedFile(file,plus,minus,action,uidlist,gidlist,dstat,sstat,ptr,acl_aliases)
00821 
00822 char *file;
00823 mode_t plus,minus;
00824 struct UidList *uidlist;
00825 struct GidList *gidlist;
00826 enum fileactions action;
00827 struct stat *dstat;
00828 struct stat *sstat;
00829 struct File *ptr;
00830 struct Item *acl_aliases;
00831 
00832 { mode_t newplus,newminus;
00833 
00834  /* plus/minus must be relative to source file, not to
00835     perms of newly created file! */
00836 
00837 Debug("CheckCopiedFile(%s)\n",file); 
00838 
00839 if ((plus == 0) && (minus == 0))
00840     {
00841     newplus = sstat->st_mode & 07777 | plus;
00842     newminus = ~(sstat->st_mode & 07777 & ~minus) & 07777;
00843     CheckExistingFile(file,newplus,newminus,fixall,uidlist,gidlist,dstat,NULL,acl_aliases);
00844     }
00845  else
00846     {
00847     CheckExistingFile(file,plus,minus,fixall,uidlist,gidlist,dstat,NULL,acl_aliases);
00848     }
00849 }
00850 
00851 /*********************************************************************/
00852 
00853 int CheckOwner(file,action,uidlist,gidlist,statbuf)
00854 
00855 char *file;
00856 enum fileactions action;
00857 struct UidList *uidlist;
00858 struct GidList *gidlist;
00859 struct stat *statbuf;
00860 
00861 { struct passwd *pw;
00862   struct group *gp;
00863   struct UidList *ulp, *unknownulp;
00864   struct GidList *glp, *unknownglp;
00865   short uidmatch = false, gidmatch = false;
00866   uid_t uid = sameowner; 
00867   gid_t gid = samegroup;
00868 
00869 Debug("CheckOwner: %d\n",statbuf->st_uid);
00870   
00871 for (ulp = uidlist; ulp != NULL; ulp=ulp->next)
00872    {
00873    Debug(" uid %d\n",ulp->uid);
00874    
00875    if (ulp->uid == unknown_owner) /* means not found while parsing */
00876       {
00877       unknownulp = MakeUidList (ulp->uidname);  /* Will only match one */
00878       if (unknownulp != NULL && statbuf->st_uid == unknownulp->uid)
00879          {
00880          uid = unknownulp->uid;
00881          uidmatch = true;
00882          break;
00883          }
00884       }
00885    
00886    if (ulp->uid == sameowner || statbuf->st_uid == ulp->uid)   /* "same" matches anything */
00887       {
00888       uid = ulp->uid;
00889       uidmatch = true;
00890       break;
00891       }
00892    }
00893 
00894 for (glp = gidlist; glp != NULL; glp=glp->next)
00895    {
00896    if (glp->gid == unknown_group) /* means not found while parsing */
00897       {
00898       unknownglp = MakeGidList (glp->gidname);  /* Will only match one */
00899       if (unknownglp != NULL && statbuf->st_gid == unknownglp->gid)
00900          {
00901          gid = unknownglp->gid;
00902          gidmatch = true;
00903          break;
00904          }
00905       }
00906    if (glp->gid == samegroup || statbuf->st_gid == glp->gid)  /* "same" matches anything */
00907       {
00908       gid = glp->gid;
00909       gidmatch = true;
00910       break;
00911       }
00912    }
00913 
00914 
00915 if (uidmatch && gidmatch)
00916    {
00917    return false;
00918    }
00919 else
00920    {
00921    if (! uidmatch)
00922       {
00923       for (ulp = uidlist; ulp != NULL; ulp=ulp->next)
00924          {
00925          if (uidlist->uid != unknown_owner)
00926             {
00927             uid = uidlist->uid;    /* default is first (not unknown) item in list */
00928             break;
00929             }
00930          }
00931       }
00932    
00933    if (! gidmatch)
00934       {
00935       for (glp = gidlist; glp != NULL; glp=glp->next)
00936          {
00937          if (gidlist->gid != unknown_group)
00938             {
00939             gid = gidlist->gid;    /* default is first (not unknown) item in list */
00940             break;
00941             }
00942          }
00943       }
00944 
00945    if (S_ISLNK(statbuf->st_mode) && (action == fixdirs || action == fixplain))
00946       {
00947       Debug2("File %s incorrect type (link), skipping...\n",file);
00948       return false;
00949       }
00950 
00951    if ((S_ISREG(statbuf->st_mode) && action == fixdirs) || (S_ISDIR(statbuf->st_mode) && action == fixplain))
00952       {
00953       Debug2("File %s incorrect type, skipping...\n",file);
00954       return false;
00955       }
00956 
00957    switch (action)
00958       {
00959       case fixplain:
00960       case fixdirs:
00961       case fixall: 
00962       case touch:
00963                   if (VERBOSE || DEBUG || D2)
00964                      {
00965                      if (uid == sameowner && gid == samegroup)
00966                         {
00967                         printf("%s:   touching %s\n",VPREFIX,file);
00968                         }
00969                      else
00970                         {
00971                         if (uid != sameowner)
00972                            {
00973                            Debug("(Change owner to uid %d if possible)\n",uid);
00974                            }
00975 
00976                         if (gid != samegroup)
00977                            {
00978                            Debug("Change group to gid %d if possible)\n",gid);
00979                            }
00980                         }
00981                      }
00982 
00983                   if (! DONTDO && S_ISLNK(statbuf->st_mode))
00984                      {
00985 #ifdef HAVE_LCHOWN
00986                      Debug("Using LCHOWN function\n");
00987                      if (lchown(file,uid,gid) == -1)
00988                         {
00989                         snprintf(OUTPUT,bufsize*2,"Cannot set ownership on link %s!\n",file);
00990                         CfLog(cflogonly,OUTPUT,"lchown");
00991                         }
00992                      else
00993                         {
00994                         return true;
00995                         }
00996 #endif
00997                      }
00998                   else if (! DONTDO)
00999                      {
01000                      if (chown(file,uid,gid) == -1)
01001                         {
01002                         snprintf(OUTPUT,bufsize*2,"Cannot set ownership on file %s!\n",file);
01003                         CfLog(cflogonly,OUTPUT,"chown");
01004                         }
01005                      else
01006                         {
01007                         return true;
01008                         }
01009                      }
01010                   break;
01011 
01012       case linkchildren:
01013       case warnall: 
01014       case warndirs:
01015       case warnplain:
01016                   if ((pw = getpwuid(statbuf->st_uid)) == NULL)
01017                      {
01018                      snprintf(OUTPUT,bufsize*2,"File %s is not owned by anybody in the passwd database\n",file);
01019                      CfLog(cferror,OUTPUT,"");
01020                      snprintf(OUTPUT,bufsize*2,"(uid = %d,gid = %d)\n",statbuf->st_uid,statbuf->st_gid);
01021                      CfLog(cferror,OUTPUT,"");
01022                      break;
01023                      }
01024 
01025                   if ((gp = getgrgid(statbuf->st_gid)) == NULL)
01026                      {
01027                      snprintf(OUTPUT,bufsize*2,"File %s is not owned by any group in group database\n",file);
01028                      CfLog(cferror,OUTPUT,"");
01029                      break;
01030                      }
01031 
01032                   snprintf(OUTPUT,bufsize*2,"File %s is owned by [%s], group [%s]\n",file,pw->pw_name,gp->gr_name);
01033                   CfLog(cferror,OUTPUT,"");
01034                   break;
01035       }
01036    }
01037 
01038 return false; 
01039 }
01040 
01041 
01042 /*********************************************************************/
01043 
01044 int CheckHomeSubDir(testpath,tidypath,recurse)
01045 
01046 char *testpath, *tidypath;
01047 int recurse;
01048 
01049 { char *subdirstart, *sp1, *sp2;
01050   char buffer[bufsize];
01051   int homelen;
01052 
01053 if (strncmp(tidypath,"home/",5) == 0)
01054    {
01055    strcpy(buffer,testpath);
01056 
01057    for (ChopLastNode(buffer); strlen(buffer) != 0; ChopLastNode(buffer))
01058      {
01059      if (IsHomeDir(buffer))
01060         {
01061         break;
01062         }
01063      }
01064 
01065    homelen = strlen(buffer);
01066 
01067    if (homelen == 0)   /* No homedir */
01068       {
01069       return false;
01070       }
01071 
01072    Debug2("CheckHomeSubDir(%s,%s)\n",testpath,tidypath);
01073 
01074    subdirstart = tidypath + 4;                                   /* Ptr to start of subdir */
01075 
01076    strcpy(buffer,testpath);
01077 
01078    ChopLastNode(buffer);                                         /* Filename only */
01079 
01080    for (sp1 = buffer + homelen +1; *sp1 != '/' && *sp1 != '\0'; sp1++) /* skip user name dir */
01081       {
01082       }
01083 
01084    sp2 = subdirstart;
01085 
01086    if (strncmp(sp1,sp2,strlen(sp2)) != 0)
01087       {
01088       return false;
01089       } 
01090 
01091    Debug2("CheckHomeSubDir(true)\n");
01092    return(true);
01093    }
01094 
01095 return true;
01096 }
01097 
01098 /**************************************************************/
01099 
01100 int FileIsNewer(file1,file2)
01101 
01102 /* True if file2 is newer than file 1 */
01103 
01104 char *file1, *file2;
01105 
01106 { struct stat statbuf1, statbuf2;
01107 
01108 if (stat(file2,&statbuf2) == -1)
01109    {
01110    CfLog(cferror,"","stat");
01111    return false;
01112    }
01113 
01114 if (stat(file1,&statbuf1) == -1)
01115    {
01116    CfLog(cferror,"","stat");
01117    return true;
01118    }
01119 
01120 if (statbuf1.st_mtime < statbuf2.st_mtime)
01121    {
01122    return true;
01123    }
01124 else
01125    {
01126    return false;
01127    }
01128 }
01129 
01130 
01131 /*********************************************************************/
01132 /* Used by files and tidy modules                                    */
01133 /*********************************************************************/
01134 
01135 int IgnoreFile (pathto,name,ignores)
01136 
01137 char *pathto, *name;
01138 struct Item *ignores;
01139 
01140 { struct Item *ip;
01141 
01142 Debug("IgnoreFile(%s)\n",name);
01143  
01144 if (name == NULL || strlen(name) == 0)
01145    {
01146    return false;
01147    }
01148  
01149 strcpy(VBUFF,pathto);
01150 AddSlash(VBUFF);
01151 strcat(VBUFF,name);
01152 
01153 if (ignores != NULL)
01154    {
01155    if (IsWildItemIn(ignores,VBUFF))
01156       {
01157       Debug("cfengine: Ignoring private abs path [%s][%s]\n",pathto,name);
01158       return true;
01159       }
01160 
01161    if (IsWildItemIn(ignores,name))
01162       {
01163       Debug("cfengine: Ignoring private pattern [%s][%s]\n",pathto,name);
01164       return true;
01165       }
01166    }
01167 
01168 for (ip = VIGNORE; ip != NULL; ip=ip->next)
01169    {
01170    if (IsExcluded(ip->classes))
01171       {
01172       continue;
01173       }
01174 
01175    if (*(ip->name) == '/')
01176       {
01177       if (strcmp(VBUFF,ip->name) == 0)
01178          {
01179          Debug("cfengine: Ignoring global abs path [%s][%s]\n",pathto,name);
01180          return true;
01181          }
01182       }
01183    else
01184       {
01185       if (WildMatch(ip->name,name))
01186          {
01187          Debug("cfengine: Ignoring global pattern [%s][%s]\n",pathto,name);
01188          return true;
01189          }
01190       }
01191    }
01192 
01193 return false;
01194 }
01195 
01196 /*********************************************************************/
01197 
01198 void CompressFile(file)
01199 
01200 char *file;
01201 
01202 { char comm[bufsize];
01203   FILE *pp;
01204  
01205 if (strlen(COMPRESSCOMMAND) == 0)
01206    {
01207    CfLog(cferror,"CompressCommand variable is not defined","");
01208    return;
01209    }
01210  
01211 snprintf(comm,bufsize,"%s %s",COMPRESSCOMMAND,file); 
01212 
01213 snprintf(OUTPUT,bufsize*2,"Compressing file %s",file); 
01214 CfLog(cfinform,OUTPUT,"");
01215  
01216 if ((pp=cfpopen(comm,"r")) == NULL)
01217    {
01218    snprintf(OUTPUT,bufsize*2,"Compression command failed on %s",file);
01219    CfLog(cfverbose,OUTPUT,"");
01220    }
01221 
01222 while (!feof(pp))
01223    {
01224    ReadLine(VBUFF,bufsize,pp);
01225    CfLog(cfinform,VBUFF,"");
01226    }
01227 
01228 cfpclose(pp); 
01229 }
01230 

© sourcejam.com 2005-2008