[Cfengine-3] / trunk / src / files_operators.c Repository:
ViewVC logotype

Annotation of /trunk/src/files_operators.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 38 - (view) (download) (as text)

1 : mark 38 /*
2 :     Copyright (C) 2008 - Mark Burgess
3 :    
4 :     This file is part of Cfengine 3 - written and maintained by Mark Burgess.
5 :    
6 :     This program is free software; you can redistribute it and/or modify it
7 :     under the terms of the GNU General Public License as published by the
8 :     Free Software Foundation; either version 3, or (at your option) any
9 :     later version.
10 :     This program is distributed in the hope that it will be useful,
11 :     but WITHOUT ANY WARRANTY; without even the implied warranty of
12 :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 :     GNU General Public License for more details.
14 :    
15 :     You should have received a copy of the GNU General Public License
16 :     along with this program; if not, write to the Free Software
17 :     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 :    
19 :     */
20 :    
21 :     /*****************************************************************************/
22 :     /* */
23 :     /* File: files_operators.c */
24 :     /* */
25 :     /*****************************************************************************/
26 :    
27 :     #include "cf3.defs.h"
28 :     #include "cf3.extern.h"
29 :    
30 :     extern int CFA_MAXTHREADS;
31 :     extern struct cfagent_connection *COMS;
32 :    
33 :     /*****************************************************************************/
34 :    
35 :     int VerifyFileLeaf(char *path,struct stat *sb,struct FileAttr attr,struct Promise *pp)
36 :    
37 :     {
38 :     /* Here we can assume that we are in the parent directory of the leaf */
39 :    
40 :     if (!SelectLeaf(path,sb,attr,pp))
41 :     {
42 :     Debug("Skipping non-selected file %s\n",path);
43 :     return false;
44 :     }
45 :    
46 :     Verbose(" -> Handling file existence constraints on %s\n",path);
47 :    
48 :     /* We still need to augment the scope of context "this" for commands */
49 :    
50 :     NewScalar("this","promiser",path,cf_str); // Parameters may only be scalars
51 :    
52 :     // AugmentScope("this",bp->args,params);
53 :    
54 :    
55 :     if (attr.transformer != NULL)
56 :     {
57 :     if (!TransformFile(path,attr,pp))
58 :     {
59 :     /* NOP? */
60 :     }
61 :     }
62 :     else
63 :     {
64 :     if (attr.haverename)
65 :     {
66 :     VerifyName(path,sb,attr,pp);
67 :     }
68 :    
69 :     if (attr.havedelete)
70 :     {
71 :     VerifyDelete(path,sb,attr,pp);
72 :     }
73 :    
74 :     if (attr.touch)
75 :     {
76 :     TouchFile(path,sb,attr,pp); // intrinsically non-convergent op
77 :     }
78 :     }
79 :    
80 :     if (attr.haveperms)
81 :     {
82 :     VerifyFileAttributes(path,sb,attr,pp);
83 :     }
84 :    
85 :     DeleteScalar("this","promiser");
86 :     return true;
87 :     }
88 :    
89 :     /*****************************************************************************/
90 :    
91 :     int CreateFile(char *file,struct Promise *pp,struct FileAttr attr)
92 :    
93 :     { int fd;
94 :    
95 :     /* If name ends in /. then this is a directory */
96 :    
97 :     // attr.move_obstructions for MakeParentDirectory
98 :    
99 :     if (strcmp("/.",file+strlen(file)-2) == 0)
100 :     {
101 :     if (!DONTDO)
102 :     {
103 :     if (!MakeParentDirectory(file,attr.move_obstructions))
104 :     {
105 :     return false;
106 :     }
107 :     }
108 :     }
109 :     else
110 :     {
111 :     if (!DONTDO)
112 :     {
113 :     MakeParentDirectory(file,attr.move_obstructions);
114 :    
115 :     if ((fd = creat(file,attr.perms.plus)) == -1)
116 :     {
117 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Error creating file %s, mode = %o\n",file,attr.perms.plus);
118 :     CfLog(cfinform,OUTPUT,"creat");
119 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
120 :     return false;
121 :     }
122 :     else
123 :     {
124 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Creating file %s, mode = %o\n",file,attr.perms.plus);
125 :     CfLog(cfinform,OUTPUT,"");
126 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
127 :     close(fd);
128 :     }
129 :     }
130 :     }
131 :    
132 :     return true;
133 :     }
134 :    
135 :     /*****************************************************************************/
136 :    
137 :     int ScheduleCopyOperation(char *destination,struct FileAttr attr,struct Promise *pp)
138 :    
139 :     { struct cfagent_connection *conn;
140 :    
141 :     Verbose(" -> Copy file %s from %s check\n",destination,pp->promiser);
142 :    
143 :     if (attr.copy.servers == NULL || strcmp(attr.copy.servers->item,"localhost") == 0)
144 :     {
145 :     conn = NULL;
146 :     pp->this_server = strdup("localhost");
147 :     }
148 :     else
149 :     {
150 :     conn = NewServerConnection(attr,pp);
151 :    
152 :     if (conn == NULL)
153 :     {
154 :     snprintf(OUTPUT,CF_BUFSIZE,"No suitable server responded to hail\n");
155 :     CfLog(cfinform,OUTPUT,"");
156 :     PromiseRef(cfinform,pp);
157 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
158 :     return false;
159 :     }
160 :     }
161 :    
162 :     pp->conn = conn; /* for ease of access */
163 :     pp->cache = NULL;
164 :    
165 :     CopyFileSources(destination,attr,pp);
166 :     return true;
167 :     }
168 :    
169 :     /*****************************************************************************/
170 :    
171 :     int ScheduleLinkOperation(char *destination,struct FileAttr attr,struct Promise *pp)
172 :    
173 :     {
174 :     Verbose(" -> Handling linking\n");
175 :     return true;
176 :     }
177 :    
178 :     /*****************************************************************************/
179 :    
180 :     int ScheduleEditOperation(char *destination,struct FileAttr attr,struct Promise *pp)
181 :    
182 :     {
183 :     Verbose(" -> Handling file edits (not yet implemented)\n");
184 :     return true;
185 :     }
186 :    
187 :     /*****************************************************************************/
188 :     /* Level */
189 :     /*****************************************************************************/
190 :    
191 :     void VerifyFileAttributes(char *file,struct stat *dstat,struct FileAttr attr,struct Promise *pp)
192 :    
193 :     { mode_t newperm = dstat->st_mode, maskvalue;
194 :    
195 :     #if defined HAVE_CHFLAGS
196 :     u_long newflags;
197 :     #endif
198 :    
199 :     Debug("VerifyFileAttributes(%s)\n",file);
200 :    
201 :     maskvalue = umask(0); /* This makes the DEFAULT modes absolute */
202 :    
203 :     newperm = (dstat->st_mode & 07777);
204 :     newperm |= attr.perms.plus;
205 :     newperm &= ~(attr.perms.minus);
206 :    
207 :     /* directories must have x set if r set, regardless */
208 :    
209 :     if (S_ISDIR(dstat->st_mode))
210 :     {
211 :     if (attr.perms.rxdirs != 'n')
212 :     {
213 :     Debug("Directory...fixing x bits\n");
214 :    
215 :     if (newperm & S_IRUSR)
216 :     {
217 :     newperm |= S_IXUSR;
218 :     }
219 :    
220 :     if (newperm & S_IRGRP)
221 :     {
222 :     newperm |= S_IXGRP;
223 :     }
224 :    
225 :     if (newperm & S_IROTH)
226 :     {
227 :     newperm |= S_IXOTH;
228 :     }
229 :     }
230 :     else
231 :     {
232 :     Verbose("NB: rxdirs is set to false - x for r bits not checked\n");
233 :     }
234 :     }
235 :    
236 :     VerifySetUidGid(file,dstat,newperm,pp,attr);
237 :    
238 :     #ifdef DARWIN
239 :     if (CheckFinderType(file,action,cf_findertype,dstat))
240 :     {
241 :     /* nop */
242 :     }
243 :     #endif
244 :    
245 :     if (VerifyOwner(file,pp,attr,dstat))
246 :     {
247 :     /* nop */
248 :     }
249 :    
250 :     if (attr.havechange && S_ISREG(dstat->st_mode))
251 :     {
252 :     VerifyFileIntegrity(file,pp,attr);
253 :     }
254 :    
255 :     if (S_ISLNK(dstat->st_mode)) /* No point in checking permission on a link */
256 :     {
257 :     KillGhostLink(file,attr,pp);
258 :     umask(maskvalue);
259 :     return;
260 :     }
261 :    
262 :     /*
263 :     if (CheckACLs(file,action,ptr->acl_aliases))
264 :     {
265 :     if (ptr != NULL)
266 :     {
267 :     AddMultipleClasses(ptr->defines);
268 :     }
269 :     }
270 :     */
271 :    
272 :     if ((newperm & 07777) == (dstat->st_mode & 07777)) /* file okay */
273 :     {
274 :     Debug("File okay, newperm = %o, stat = %o\n",(newperm & 07777),(dstat->st_mode & 07777));
275 :     snprintf(OUTPUT,CF_BUFSIZE*2," -> File permissions on %s as promised\n",file);
276 :     CfLog(cfverbose,OUTPUT,"");
277 :     ClassAuditLog(pp,attr,OUTPUT,CF_NOP);
278 :     }
279 :     else
280 :     {
281 :     Debug("Trying to fix mode...newperm = %o, stat = %o\n",(newperm & 07777),(dstat->st_mode & 07777));
282 :    
283 :     switch (attr.transaction.action)
284 :     {
285 :     case cfa_warn:
286 :    
287 :     snprintf(OUTPUT,CF_BUFSIZE*2,"%s has permission %o\n",file,dstat->st_mode & 07777);
288 :     CfLog(cferror,OUTPUT,"");
289 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
290 :     snprintf(OUTPUT,CF_BUFSIZE*2,"[should be %o]\n",newperm & 07777);
291 :     CfLog(cferror,OUTPUT,"");
292 :     break;
293 :    
294 :     case cfa_fix:
295 :    
296 :     if (!DONTDO)
297 :     {
298 :     if (chmod(file,newperm & 07777) == -1)
299 :     {
300 :     snprintf(OUTPUT,CF_BUFSIZE*2,"chmod failed on %s\n",file);
301 :     CfLog(cferror,OUTPUT,"chmod");
302 :     break;
303 :     }
304 :     }
305 :    
306 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Object %s had permission %o, changed it to %o\n",
307 :     file,dstat->st_mode & 07777,newperm & 07777);
308 :     CfLog(cfinform,OUTPUT,"");
309 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
310 :     break;
311 :    
312 :     default:
313 :     FatalError("cfengine: internal error VerifyFileAttributes(): illegal file action\n");
314 :     }
315 :     }
316 :    
317 :     #if defined HAVE_CHFLAGS /* BSD special flags */
318 :     newflags = (dstat->st_flags & CHFLAGS_MASK) ;
319 :     newflags |= ptr->plus_flags;
320 :     newflags &= ~(ptr->minus_flags);
321 :    
322 :     if ((newflags & CHFLAGS_MASK) == (dstat->st_flags & CHFLAGS_MASK)) /* file okay */
323 :     {
324 :     Debug("BSD File okay, flags = %o, current = %o\n",(newflags & CHFLAGS_MASK),(dstat->st_flags & CHFLAGS_MASK));
325 :     }
326 :     else
327 :     {
328 :     Debug("BSD Fixing %s, newflags = %o, flags = %o\n",file,(newflags & CHFLAGS_MASK),(dstat->st_flags & CHFLAGS_MASK));
329 :    
330 :     switch (attr.transaction.action)
331 :     {
332 :     case cfa_warn:
333 :    
334 :     snprintf(OUTPUT,CF_BUFSIZE*2,"%s has flags %o\n",file,dstat->st_mode & CHFLAGS_MASK);
335 :     CfLog(cferror,OUTPUT,"");
336 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
337 :     snprintf(OUTPUT,CF_BUFSIZE*2,"[should be %o]\n",newflags & CHFLAGS_MASK);
338 :     CfLog(cferror,OUTPUT,"");
339 :     break;
340 :    
341 :     case cfa_fix:
342 :    
343 :     if (! DONTDO)
344 :     {
345 :     if (chflags (file,newflags & CHFLAGS_MASK) == -1)
346 :     {
347 :     snprintf(OUTPUT,CF_BUFSIZE*2,"chflags failed on %s\n",file);
348 :     CfLog(cferror,OUTPUT,"chflags");
349 :     ClassAuditLog(pp,attr,OUTPUT,CF_DENIED);
350 :     break;
351 :     }
352 :     else
353 :     {
354 :     snprintf(OUTPUT,CF_BUFSIZE*2,"%s had flags %o, changed it to %o\n",
355 :     file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK);
356 :     CfLog(cfinform,OUTPUT,"");
357 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
358 :     }
359 :     }
360 :    
361 :     break;
362 :    
363 :     default:
364 :     FatalError("cfengine: internal error VerifyFileAttributes() illegal file action\n");
365 :     }
366 :     }
367 :     #endif
368 :    
369 :     if (attr.touch)
370 :     {
371 :     if (utime(file,NULL) == -1)
372 :     {
373 :     snprintf(OUTPUT,CF_BUFSIZE,"Touching file %s",file);
374 :     CfLog(cfinform,OUTPUT,"utime");
375 :     ClassAuditLog(pp,attr,OUTPUT,CF_DENIED);
376 :     }
377 :     else
378 :     {
379 :     snprintf(OUTPUT,CF_BUFSIZE,"Touching file %s",file);
380 :     CfLog(cfinform,OUTPUT,"");
381 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
382 :     }
383 :     }
384 :    
385 :     umask(maskvalue);
386 :     Debug("CheckExistingFile(Done)\n");
387 :     }
388 :    
389 :     /*********************************************************************/
390 :    
391 :     void VerifyCopiedFileAttributes(char *file,struct stat *dstat,struct stat *sstat,struct FileAttr attr,struct Promise *pp)
392 :    
393 :     { mode_t newplus,newminus;
394 :     uid_t save_uid;
395 :     gid_t save_gid;
396 :    
397 :     // How do we get the default attr?
398 :    
399 :     Debug("VerifyCopiedFile(%s,+%o,-%o)\n",file,attr.perms.plus,attr.perms.minus);
400 :    
401 :     save_uid = (attr.perms.owners)->uid;
402 :     save_gid = (attr.perms.groups)->gid;
403 :    
404 :     if ((attr.perms.owners)->uid == CF_SAME_OWNER) /* Preserve uid and gid */
405 :     {
406 :     (attr.perms.owners)->uid = sstat->st_uid;
407 :     }
408 :    
409 :     if ((attr.perms.groups)->gid == CF_SAME_GROUP)
410 :     {
411 :     (attr.perms.groups)->gid = sstat->st_gid;
412 :     }
413 :    
414 :     // Will this preserve if no mode set?
415 :    
416 :     newplus = (sstat->st_mode & 07777) | attr.perms.plus;
417 :     newminus = ~(newplus & ~(attr.perms.minus)) & 07777;
418 :    
419 :     attr.perms.plus = newplus;
420 :     attr.perms.minus = newminus;
421 :    
422 :     VerifyFileAttributes(file,dstat,attr,pp);
423 :    
424 :     (attr.perms.owners)->uid = save_uid;
425 :     (attr.perms.groups)->gid = save_gid;
426 :     }
427 :    
428 :     /*****************************************************************************/
429 :     /* Level */
430 :     /*****************************************************************************/
431 :    
432 :     void VerifySetUidGid(char *file,struct stat *dstat,mode_t newperm,struct Promise *pp,struct FileAttr attr)
433 :    
434 :     { int amroot = true;
435 :    
436 :     if (!IsPrivileged())
437 :     {
438 :     amroot = false;
439 :     }
440 :    
441 :     if (dstat->st_uid == 0 && (dstat->st_mode & S_ISUID))
442 :     {
443 :     if (newperm & S_ISUID)
444 :     {
445 :     if (!IsItemIn(VSETUIDLIST,file))
446 :     {
447 :     if (amroot)
448 :     {
449 :     snprintf(OUTPUT,CF_BUFSIZE*2,"NEW SETUID root PROGRAM %s\n",file);
450 :     CfLog(cfinform,OUTPUT,"");
451 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
452 :     }
453 :    
454 :     PrependItem(&VSETUIDLIST,file,NULL);
455 :     }
456 :     }
457 :     else
458 :     {
459 :     switch (attr.transaction.action)
460 :     {
461 :     case cfa_fix:
462 :    
463 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Removing setuid (root) flag from %s...\n\n",file);
464 :     CfLog(cfinform,OUTPUT,"");
465 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
466 :     break;
467 :    
468 :     case cfa_warn:
469 :    
470 :     if (amroot)
471 :     {
472 :     snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING setuid (root) flag on %s...\n\n",file);
473 :     CfLog(cferror,OUTPUT,"");
474 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
475 :     }
476 :     break;
477 :     }
478 :     }
479 :     }
480 :    
481 :     if (dstat->st_uid == 0 && (dstat->st_mode & S_ISGID))
482 :     {
483 :     if (newperm & S_ISGID)
484 :     {
485 :     if (!IsItemIn(VSETUIDLIST,file))
486 :     {
487 :     if (S_ISDIR(dstat->st_mode))
488 :     {
489 :     /* setgid directory */
490 :     }
491 :     else
492 :     {
493 :     if (amroot)
494 :     {
495 :     snprintf(OUTPUT,CF_BUFSIZE*2,"NEW SETGID root PROGRAM %s\n",file);
496 :     CfLog(cferror,OUTPUT,"");
497 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
498 :     }
499 :    
500 :     PrependItem(&VSETUIDLIST,file,NULL);
501 :     }
502 :     }
503 :     }
504 :     else
505 :     {
506 :     switch (attr.transaction.action)
507 :     {
508 :     case cfa_fix:
509 :    
510 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Removing setgid (root) flag from %s...\n\n",file);
511 :     CfLog(cfinform,OUTPUT,"");
512 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
513 :     break;
514 :    
515 :     case cfa_warn:
516 :    
517 :     snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING setgid (root) flag on %s...\n\n",file);
518 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
519 :     CfLog(cferror,OUTPUT,"");
520 :     break;
521 :    
522 :     default:
523 :     break;
524 :     }
525 :     }
526 :     }
527 :     }
528 :    
529 :     /*****************************************************************************/
530 :    
531 :     int MoveObstruction(char *from,struct FileAttr attr,struct Promise *pp)
532 :    
533 :     { struct stat sb;
534 :     char stamp[CF_BUFSIZE],saved[CF_BUFSIZE];
535 :     time_t now_stamp = time((time_t *)NULL);
536 :    
537 :     if (lstat(from,&sb) == 0)
538 :     {
539 :     if (!attr.move_obstructions)
540 :     {
541 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Object %s exists and is obstructing our promise\n",from);
542 :     CfLog(cfverbose,OUTPUT,"");
543 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
544 :     return false;
545 :     }
546 :    
547 :     if (S_ISREG(sb.st_mode))
548 :     {
549 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Moving plain file %s to %s%s\n",from,from,CF_SAVED);
550 :     CfLog(cfsilent,OUTPUT,"");
551 :    
552 :     if (DONTDO)
553 :     {
554 :     return false;
555 :     }
556 :    
557 :     saved[0] = '\0';
558 :     strcpy(saved,from);
559 :    
560 :     sprintf(stamp, "_%d_%s",CFSTARTTIME,CanonifyName(ctime(&now_stamp)));
561 :     strcat(saved,stamp);
562 :     strcat(saved,CF_SAVED);
563 :    
564 :     if (rename(from,saved) == -1)
565 :     {
566 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't rename %s to %s\n",from,saved);
567 :     CfLog(cferror,OUTPUT,"rename");
568 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
569 :     return false;
570 :     }
571 :    
572 :     if (ArchiveToRepository(saved,attr,pp))
573 :     {
574 :     unlink(saved);
575 :     }
576 :    
577 :     return true;
578 :     }
579 :    
580 :     if (S_ISDIR(sb.st_mode) && attr.link.when_no_file == cfa_force)
581 :     {
582 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Moving directory %s to %s%s.dir\n",from,from,CF_SAVED);
583 :     CfLog(cfsilent,OUTPUT,"");
584 :    
585 :     if (DONTDO)
586 :     {
587 :     return false;
588 :     }
589 :    
590 :     saved[0] = '\0';
591 :     strcpy(saved,from);
592 :    
593 :     sprintf(stamp, "_%d_%s", CFSTARTTIME, CanonifyName(ctime(&now_stamp)));
594 :     strcat(saved,stamp);
595 :     strcat(saved,CF_SAVED);
596 :     strcat(saved,".dir");
597 :    
598 :     if (stat(saved,&sb) != -1)
599 :     {
600 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't save directory %s, since %s exists already\n",from,saved);
601 :     CfLog(cferror,OUTPUT,"");
602 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
603 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to force link to existing directory %s\n",from);
604 :     CfLog(cferror,OUTPUT,"");
605 :     return false;
606 :     }
607 :    
608 :     if (rename(from,saved) == -1)
609 :     {
610 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't rename %s to %s\n",from,saved);
611 :     CfLog(cferror,OUTPUT,"rename");
612 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
613 :     return false;
614 :     }
615 :     }
616 :     }
617 :    
618 :     return true;
619 :     }
620 :    
621 :     /*********************************************************************/
622 :     /* Level */
623 :     /*********************************************************************/
624 :    
625 :     void VerifyName(char *path,struct stat *sb,struct FileAttr attr,struct Promise *pp)
626 :    
627 :     { mode_t newperm;
628 :     struct stat dsb;
629 :    
630 :     if (lstat(path,&dsb) == -1)
631 :     {
632 :     snprintf(OUTPUT,CF_BUFSIZE,"File object named %s is not there (promise kept)",path);
633 :     CfLog(cfinform,OUTPUT,"");
634 :     ClassAuditLog(pp,attr,OUTPUT,CF_NOP);
635 :     return;
636 :     }
637 :     else
638 :     {
639 :     snprintf(OUTPUT,CF_BUFSIZE,"Warning - file object %s exists, contrary to promise\n",path);
640 :     CfLog(cfinform,OUTPUT,"");
641 :     }
642 :    
643 :     if (S_ISLNK(dsb.st_mode))
644 :     {
645 :     if (attr.rename.disable)
646 :     {
647 :     if (!DONTDO)
648 :     {
649 :     if (unlink(path) == -1)
650 :     {
651 :     snprintf(OUTPUT,CF_BUFSIZE*2," !! Unable to unlink %s\n",path);
652 :     CfLog(cferror,OUTPUT,"unlink");
653 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
654 :     }
655 :     else
656 :     {
657 :     snprintf(OUTPUT,CF_BUFSIZE," -> Disabling symbolic link %s -> %s by deleting it\n",path,VBUFF);
658 :     CfLog(cfinform,OUTPUT,"");
659 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
660 :     }
661 :     }
662 :     else
663 :     {
664 :     snprintf(OUTPUT,CF_BUFSIZE," * Need to disable link %s -> %s to keep promise\n",path,VBUFF);
665 :     CfLog(cfinform,OUTPUT,"");
666 :     }
667 :    
668 :     return;
669 :     }
670 :     }
671 :    
672 :     /* Normal disable - has priority */
673 :    
674 :     if (attr.rename.disable)
675 :     {
676 :     char newname[CF_BUFSIZE];
677 :    
678 :     if (attr.rename.newname && strlen(attr.rename.newname) > 0)
679 :     {
680 :     if (IsAbsPath(attr.rename.newname))
681 :     {
682 :     strncpy(path,attr.rename.newname,CF_BUFSIZE-1);
683 :     }
684 :     else
685 :     {
686 :     strcpy(newname,path);
687 :     ChopLastNode(newname);
688 :     if (!JoinPath(newname,attr.rename.newname))
689 :     {
690 :     ReleaseCurrentLock();
691 :     return;
692 :     }
693 :     }
694 :     }
695 :     else
696 :     {
697 :     strcpy(newname,path);
698 :    
699 :     if (attr.rename.disable_suffix)
700 :     {
701 :     if (!JoinSuffix(newname,attr.rename.disable_suffix))
702 :     {
703 :     return;
704 :     }
705 :     }
706 :     else
707 :     {
708 :     if (!JoinSuffix(newname,".cfdisabled"))
709 :     {
710 :     return;
711 :     }
712 :     }
713 :     }
714 :    
715 :     if ((attr.rename.plus != CF_SAMEMODE) && (attr.rename.minus != CF_SAMEMODE))
716 :     {
717 :     newperm = (sb->st_mode & 07777);
718 :     newperm |= attr.perms.plus;
719 :     newperm &= ~(attr.perms.minus);
720 :     }
721 :     else
722 :     {
723 :     newperm = (mode_t)0600;
724 :     }
725 :    
726 :     if (DONTDO)
727 :     {
728 :     snprintf(OUTPUT,CF_BUFSIZE*2," -> File %s should be renamed to %s to keep promise\n",path,newname);
729 :     CfLog(cfinform,OUTPUT,"");
730 :     return;
731 :     }
732 :     else
733 :     {
734 :     chmod(path,newperm);
735 :    
736 :     snprintf(OUTPUT,CF_BUFSIZE*2," -> Disabling/renaming file %s to %s with mode %o\n",path,newname,newperm);
737 :     CfLog(cfinform,OUTPUT,"");
738 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
739 :    
740 :     if (!IsItemIn(VREPOSLIST,newname))
741 :     {
742 :     if (rename(path,newname) == -1)
743 :     {
744 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Error occurred while renaming %s\n",path);
745 :     CfLog(cferror,OUTPUT,"rename");
746 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
747 :     return;
748 :     }
749 :    
750 :     if (ArchiveToRepository(newname,attr,pp))
751 :     {
752 :     unlink(newname);
753 :     }
754 :     }
755 :     else
756 :     {
757 :     snprintf(OUTPUT,CF_BUFSIZE," !! Disable required twice? Would overwrite saved copy - changing permissions only",path);
758 :     CfLog(cferror,OUTPUT,"");
759 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
760 :     }
761 :     }
762 :    
763 :     return;
764 :     }
765 :    
766 :     if (attr.rename.rotate == 0)
767 :     {
768 :     if (! DONTDO)
769 :     {
770 :     TruncateFile(path);
771 :     snprintf(OUTPUT,CF_BUFSIZE*2," -> Truncating (emptying) %s\n",path);
772 :     CfLog(cfinform,OUTPUT,"");
773 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
774 :     }
775 :     else
776 :     {
777 :     snprintf(OUTPUT,CF_BUFSIZE," * File %s needs emptying",path);
778 :     CfLog(cferror,OUTPUT,"");
779 :     }
780 :     return;
781 :     }
782 :    
783 :    
784 :     if (attr.rename.rotate > 0)
785 :     {
786 :     if (!DONTDO)
787 :     {
788 :     RotateFiles(path,attr.rename.rotate);
789 :     snprintf(OUTPUT,CF_BUFSIZE*2," -> Rotating files %s in %d fifo\n",path,attr.rename.rotate);
790 :     CfLog(cfinform,OUTPUT,"");
791 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
792 :     }
793 :     else
794 :     {
795 :     snprintf(OUTPUT,CF_BUFSIZE," * File %s needs rotating",path);
796 :     CfLog(cferror,OUTPUT,"");
797 :     }
798 :    
799 :     return;
800 :     }
801 :     }
802 :    
803 :     /*********************************************************************/
804 :    
805 :     void VerifyDelete(char *path,struct stat *sb,struct FileAttr attr,struct Promise *pp)
806 :    
807 :     { char *lastnode = ReadLastNode(path);
808 :    
809 :     Verbose(" -> Verifying file deletions for %s\n",path);
810 :    
811 :     if (DONTDO)
812 :     {
813 :     snprintf(OUTPUT,CF_BUFSIZE,"Promise requires deletion of file object %s\n",path);
814 :     CfLog(cfinform,OUTPUT,"");
815 :     }
816 :     else
817 :     {
818 :     if (!S_ISDIR(sb->st_mode))
819 :     {
820 :     if (unlink(lastnode) == -1)
821 :     {
822 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't unlink %s tidying\n",path);
823 :     CfLog(cfverbose,OUTPUT,"unlink");
824 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
825 :     }
826 :     else
827 :     {
828 :     snprintf(OUTPUT,CF_BUFSIZE," -> Deleted file %s\n",path);
829 :     CfLog(cfinform,OUTPUT,"");
830 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
831 :     }
832 :     }
833 :     else
834 :     {
835 :     if (!attr.delete.rmdirs)
836 :     {
837 :     snprintf(OUTPUT,CF_BUFSIZE,"Keeping directory %s\n",path);
838 :     CfLog(cfinform,OUTPUT,"unlink");
839 :     return;
840 :     }
841 :    
842 :     if (rmdir(lastnode) == -1)
843 :     {
844 :     snprintf(OUTPUT,CF_BUFSIZE,"Delete directory %s failed\n",path);
845 :     CfLog(cfinform,OUTPUT,"unlink");
846 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
847 :     }
848 :     else
849 :     {
850 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Deleted directory %s\n",path);
851 :     CfLog(cfinform,OUTPUT,"");
852 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
853 :     }
854 :     }
855 :     }
856 :     }
857 :    
858 :     /*********************************************************************/
859 :    
860 :     void TouchFile(char *path,struct stat *sb,struct FileAttr attr,struct Promise *pp)
861 :     {
862 :     }
863 :    
864 :     /*********************************************************************/
865 :    
866 :     void VerifyFileIntegrity(char *file,struct Promise *pp,struct FileAttr attr)
867 :    
868 :     { unsigned char digest1[EVP_MAX_MD_SIZE+1];
869 :     unsigned char digest2[EVP_MAX_MD_SIZE+1];
870 :    
871 :     Debug("Checking checksum/hash integrity of %s\n",file);
872 :    
873 :     memset(digest1,0,EVP_MAX_MD_SIZE+1);
874 :     memset(digest2,0,EVP_MAX_MD_SIZE+1);
875 :    
876 :     if (attr.change.hash == cf_besthash)
877 :     {
878 :     if (!DONTDO)
879 :     {
880 :     HashFile(file,digest1,cf_md5);
881 :     HashFile(file,digest2,cf_sha1);
882 :     FileHashChanged(file,digest1,cferror,cf_md5,attr,pp);
883 :     FileHashChanged(file,digest2,cferror,cf_sha1,attr,pp);
884 :     }
885 :     }
886 :     else
887 :     {
888 :     HashFile(file,digest1,attr.change.hash);
889 :    
890 :     if (!DONTDO)
891 :     {
892 :     if (FileHashChanged(file,digest1,cferror,attr.change.hash,attr,pp))
893 :     {
894 :     }
895 :     }
896 :     }
897 :     }
898 :    
899 :     /*********************************************************************/
900 :    
901 :     int VerifyOwner(char *file,struct Promise *pp,struct FileAttr attr,struct stat *sb)
902 :    
903 :     { struct passwd *pw;
904 :     struct group *gp;
905 :     struct UidList *ulp, *unknownulp;
906 :     struct GidList *glp, *unknownglp;
907 :     short uidmatch = false, gidmatch = false;
908 :     uid_t uid = CF_SAME_OWNER;
909 :     gid_t gid = CF_SAME_GROUP;
910 :    
911 :     Debug("VerifyOwner: %d\n",sb->st_uid);
912 :    
913 :     for (ulp = attr.perms.owners; ulp != NULL; ulp=ulp->next)
914 :     {
915 :     if (ulp->uid == CF_UNKNOWN_OWNER)
916 :     {
917 :     unknownulp = MakeUidList(ulp->uidname); /* Will only match one */
918 :    
919 :     if (unknownulp != NULL && sb->st_uid == unknownulp->uid)
920 :     {
921 :     uid = unknownulp->uid;
922 :     uidmatch = true;
923 :     break;
924 :     }
925 :     }
926 :    
927 :     if (ulp->uid == CF_SAME_OWNER || sb->st_uid == ulp->uid) /* "same" matches anything */
928 :     {
929 :     uid = ulp->uid;
930 :     uidmatch = true;
931 :     break;
932 :     }
933 :     }
934 :    
935 :     for (glp = attr.perms.groups; glp != NULL; glp=glp->next)
936 :     {
937 :     if (glp->gid == CF_UNKNOWN_GROUP) /* means not found while parsing */
938 :     {
939 :     unknownglp = MakeGidList(glp->gidname); /* Will only match one */
940 :    
941 :     if (unknownglp != NULL && sb->st_gid == unknownglp->gid)
942 :     {
943 :     gid = unknownglp->gid;
944 :     gidmatch = true;
945 :     break;
946 :     }
947 :     }
948 :    
949 :     if (glp->gid == CF_SAME_GROUP || sb->st_gid == glp->gid) /* "same" matches anything */
950 :     {
951 :     gid = glp->gid;
952 :     gidmatch = true;
953 :     break;
954 :     }
955 :     }
956 :    
957 :     if (uidmatch && gidmatch)
958 :     {
959 :     return false;
960 :     }
961 :     else
962 :     {
963 :     if (! uidmatch)
964 :     {
965 :     for (ulp = attr.perms.owners; ulp != NULL; ulp=ulp->next)
966 :     {
967 :     if (attr.perms.owners->uid != CF_UNKNOWN_OWNER)
968 :     {
969 :     uid = attr.perms.owners->uid; /* default is first (not unknown) item in list */
970 :     break;
971 :     }
972 :     }
973 :     }
974 :    
975 :     if (! gidmatch)
976 :     {
977 :     for (glp = attr.perms.groups; glp != NULL; glp=glp->next)
978 :     {
979 :     if (attr.perms.groups->gid != CF_UNKNOWN_GROUP)
980 :     {
981 :     gid = attr.perms.groups->gid; /* default is first (not unknown) item in list */
982 :     break;
983 :     }
984 :     }
985 :     }
986 :    
987 :     switch (attr.transaction.action)
988 :     {
989 :     case cfa_fix:
990 :    
991 :     if (uid == CF_SAME_OWNER && gid == CF_SAME_GROUP)
992 :     {
993 :     Verbose("%s: touching %s\n",VPREFIX,file);
994 :     }
995 :     else
996 :     {
997 :     if (uid != CF_SAME_OWNER)
998 :     {
999 :     Debug("(Change owner to uid %d if possible)\n",uid);
1000 :     }
1001 :    
1002 :     if (gid != CF_SAME_GROUP)
1003 :     {
1004 :     Debug("Change group to gid %d if possible)\n",gid);
1005 :     }
1006 :     }
1007 :    
1008 :     if (!DONTDO && S_ISLNK(sb->st_mode))
1009 :     {
1010 :     #ifdef HAVE_LCHOWN
1011 :     Debug("Using LCHOWN function\n");
1012 :     if (lchown(file,uid,gid) == -1)
1013 :     {
1014 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot set ownership on link %s!\n",file);
1015 :     CfLog(cflogonly,OUTPUT,"lchown");
1016 :     }
1017 :     else
1018 :     {
1019 :     return true;
1020 :     }
1021 :     #endif
1022 :     }
1023 :     else if (!DONTDO)
1024 :     {
1025 :     if (!uidmatch)
1026 :     {
1027 :     snprintf(OUTPUT,CF_BUFSIZE,"Owner of %s was %d, setting to %d",file,sb->st_uid,uid);
1028 :     CfLog(cfinform,OUTPUT,"");
1029 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
1030 :     }
1031 :    
1032 :     if (!gidmatch)
1033 :     {
1034 :     snprintf(OUTPUT,CF_BUFSIZE,"Group of %s was %d, setting to %d",file,sb->st_gid,gid);
1035 :     CfLog(cfinform,OUTPUT,"");
1036 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
1037 :     }
1038 :    
1039 :     if (!S_ISLNK(sb->st_mode))
1040 :     {
1041 :     if (chown(file,uid,gid) == -1)
1042 :     {
1043 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot set ownership on file %s!\n",file);
1044 :     CfLog(cflogonly,OUTPUT,"chown");
1045 :     ClassAuditLog(pp,attr,OUTPUT,CF_DENIED);
1046 :     }
1047 :     else
1048 :     {
1049 :     return true;
1050 :     }
1051 :     }
1052 :     }
1053 :     break;
1054 :    
1055 :     case cfa_warn:
1056 :    
1057 :     if ((pw = getpwuid(sb->st_uid)) == NULL)
1058 :     {
1059 :     snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is not owned by anybody in the passwd database\n",file);
1060 :     CfLog(cferror,OUTPUT,"");
1061 :     snprintf(OUTPUT,CF_BUFSIZE*2,"(uid = %d,gid = %d)\n",sb->st_uid,sb->st_gid);
1062 :     CfLog(cferror,OUTPUT,"");
1063 :     break;
1064 :     }
1065 :    
1066 :     if ((gp = getgrgid(sb->st_gid)) == NULL)
1067 :     {
1068 :     snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is not owned by any group in group database\n",file);
1069 :     CfLog(cferror,OUTPUT,"");
1070 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
1071 :     break;
1072 :     }
1073 :    
1074 :     snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is owned by [%s], group [%s]\n",file,pw->pw_name,gp->gr_name);
1075 :     CfLog(cferror,OUTPUT,"");
1076 :     ClassAuditLog(pp,attr,OUTPUT,CF_WARN);
1077 :     break;
1078 :     }
1079 :     }
1080 :    
1081 :     return false;
1082 :     }
1083 :    
1084 :    
1085 :     /*********************************************************************/
1086 :     /* Level */
1087 :     /*********************************************************************/
1088 :    
1089 :     int TransformFile(char *file,struct FileAttr attr,struct Promise *pp)
1090 :    
1091 :     { char comm[CF_EXPANDSIZE];
1092 :     FILE *pop;
1093 :    
1094 :     if (attr.transformer == NULL)
1095 :     {
1096 :     return false;
1097 :     }
1098 :    
1099 :     ExpandScalar(attr.transformer,comm);
1100 :    
1101 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Transforming: %s ",comm);
1102 :     CfLog(cfinform,OUTPUT,"");
1103 :    
1104 :     if ((pop = cfpopen(comm,"r")) == NULL)
1105 :     {
1106 :     snprintf(OUTPUT,CF_BUFSIZE,"Transformer %s %s failed",attr.transformer,file);
1107 :     CfLog(cfinform,OUTPUT,"");
1108 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
1109 :     return false;
1110 :     }
1111 :    
1112 :     while (!feof(pop))
1113 :     {
1114 :     ReadLine(VBUFF,CF_BUFSIZE,pop);
1115 :     CfLog(cfinform,VBUFF,"");
1116 :     }
1117 :    
1118 :     cfpclose(pop);
1119 :    
1120 :     snprintf(OUTPUT,CF_BUFSIZE,"Transformer %s => %s seemed ok",file,comm);
1121 :     CfLog(cfinform,OUTPUT,"");
1122 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
1123 :     return true;
1124 :     }
1125 :    
1126 :     /*******************************************************************/
1127 :    
1128 :     int MakeParentDirectory(char *parentandchild,int force)
1129 :    
1130 :     {
1131 :     /* For now, just transform to cf2 code */
1132 :    
1133 :     if (force)
1134 :     {
1135 :     return MakeDirectoriesFor(parentandchild,'y');
1136 :     }
1137 :     else
1138 :     {
1139 :     return MakeDirectoriesFor(parentandchild,'n');
1140 :     }
1141 :     }

Administrator
ViewVC Help
Powered by ViewVC 1.0.3