00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "cf.defs.h"
00028 #include "cf.extern.h"
00029
00030
00031
00032
00033 int IsHomeDir(name)
00034
00035
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
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);
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))
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);
00284
00285 if (action == compress)
00286 {
00287 docompress = true;
00288 if (ptr != NULL)
00289 {
00290 AddMultipleClasses(ptr->defines);
00291 }
00292 action = fixall;
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
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
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))
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))
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))
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
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))
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
00835
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)
00876 {
00877 unknownulp = MakeUidList (ulp->uidname);
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)
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)
00897 {
00898 unknownglp = MakeGidList (glp->gidname);
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)
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;
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;
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)
01068 {
01069 return false;
01070 }
01071
01072 Debug2("CheckHomeSubDir(%s,%s)\n",testpath,tidypath);
01073
01074 subdirstart = tidypath + 4;
01075
01076 strcpy(buffer,testpath);
01077
01078 ChopLastNode(buffer);
01079
01080 for (sp1 = buffer + homelen +1; *sp1 != '/' && *sp1 != '\0'; sp1++)
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
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
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