/[pdpsoft]/trunk/grid-mw-security/cgul/fileutil/fileutil.c
ViewVC logotype

Diff of /trunk/grid-mw-security/cgul/fileutil/fileutil.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1509 by msalle, Wed Feb 10 23:32:47 2010 UTC revision 1510 by msalle, Sun Feb 14 12:31:32 2010 UTC
# Line 59  int priv_drop(int unpriv_uid,int unpriv_ Line 59  int priv_drop(int unpriv_uid,int unpriv_
59      /* Anything to be done? */      /* Anything to be done? */
60      rc=( target_uid==0 || target_uid==euid ? 0 : seteuid(target_uid) );      rc=( target_uid==0 || target_uid==euid ? 0 : seteuid(target_uid) );
61      /* Error: try to restore */      /* Error: try to restore */
62      if (rc!=0) setegid(egid); /* ignore rc of THIS process, it's damage control */      if (rc!=0) setegid(egid); /* ignore rc of THIS process: damage control */
63    
64      return 0;      return 0;
65  }  }
# Line 94  int raise_priv(uid_t euid, gid_t egid) { Line 94  int raise_priv(uid_t euid, gid_t egid) {
94   *  LCK_READ    - set shared read lock   *  LCK_READ    - set shared read lock
95   *  LCK_WRITE   - set exclusive write lock   *  LCK_WRITE   - set exclusive write lock
96   *  LCK_UNLOCK  - unset lock   *  LCK_UNLOCK  - unset lock
97   * Locks are exclusive for writing and shared for reading: multiple processes can   * Locks are exclusive for writing and shared for reading: multiple processes
98   * read simultaneously, but writing is exclusive, both for reading and writing.   * can read simultaneously, but writing is exclusive, both for reading and
99     * writing.
100   * Returns -1 on error, 0 on success.   * Returns -1 on error, 0 on success.
101   */   */
102  int cgul_filelock(int fd, int lock_type, int action) {  int cgul_filelock(int fd, int lock_type, int action) {
# Line 148  int cgul_filelock(int fd, int lock_type, Line 149  int cgul_filelock(int fd, int lock_type,
149   * -3: permissions error   * -3: permissions error
150   * -4: memory error   * -4: memory error
151   * -5: too many retries needed during reading   * -5: too many retries needed during reading
152     * -6: locking failed
153   */   */
154  int cgul_read_proxy(const char *path, int lock_type, char **proxy)  {  int cgul_read_proxy(const char *path, int lock_type, char **proxy)  {
155      const int tries=10; /* max number of retries for reading a changing file */      const int tries=10; /* max number of retries for reading a changing file */
# Line 155  int cgul_read_proxy(const char *path, in Line 157  int cgul_read_proxy(const char *path, in
157      struct stat st1,st2,*sptr1,*sptr2,*sptr3;      struct stat st1,st2,*sptr1,*sptr2,*sptr3;
158      uid_t uid=getuid(),euid=geteuid();      uid_t uid=getuid(),euid=geteuid();
159      gid_t gid=getgid(),egid=getegid();      gid_t gid=getgid(),egid=getegid();
160      char *buf,*buf_new;/* *proxy will be updated when we know everything is ok */      char *buf,*buf_new; /* *proxy will be updated when everything is ok */
161      ssize_t size;      ssize_t size;
162    
163      /* Drop privilege to real uid and real gid, only when we can and are      /* Drop privilege to real uid and real gid, only when we can and are
# Line 168  int cgul_read_proxy(const char *path, in Line 170  int cgul_read_proxy(const char *path, in
170      }      }
171      /* Lock file */      /* Lock file */
172      if (cgul_filelock(fd,lock_type,LCK_READ))    {      if (cgul_filelock(fd,lock_type,LCK_READ))    {
173          close(fd); raise_priv(euid,egid); return -1;          close(fd); raise_priv(euid,egid); return -6;
174      }      }
175      /* Stat the file before reading:      /* Stat the file before reading:
176       * Need ownership and mode for allowed values, size for malloc */       * Need ownership and mode for allowed values, size for malloc */
177      if (fstat(fd,&st1)) {      if (fstat(fd,&st1)) {
178          close(fd); raise_priv(euid,egid); return -1;          close(fd); raise_priv(euid,egid); return -1;
179      }      }
180      /* Check we own it (only uid) and is unreadable/unwriteable for anyone else      /* Check we own it (only uid) and it is unreadable/unwriteable for anyone
181       * */       * else */
182      if ( st1.st_uid!=uid ||      if ( st1.st_uid!=uid ||
183           st1.st_mode & S_IRGRP || st1.st_mode & S_IWGRP ||           st1.st_mode & S_IRGRP || st1.st_mode & S_IWGRP ||
184           st1.st_mode & S_IROTH || st1.st_mode & S_IWOTH )   {           st1.st_mode & S_IROTH || st1.st_mode & S_IWOTH )   {
# Line 254  int cgul_read_proxy(const char *path, in Line 256  int cgul_read_proxy(const char *path, in
256   *                group={root,trust_gid}   *                group={root,trust_gid}
257   * Return values:   * Return values:
258   *  0: succes   *  0: succes
259   *  -1: I/O error   *  -1: I/O error, including when file changed during reading in any way other
260     *      than access time.
261   *  -2: privilege-drop error   *  -2: privilege-drop error
262   *  -3: permission error (untrusted path)   *  -3: permission error (untrusted path)
263   *  -4: memory error   *  -4: memory error
# Line 266  int cgul_read_config(const char *path, c Line 269  int cgul_read_config(const char *path, c
269      uid_t euid=geteuid(),uid=getuid(),target_uid;      uid_t euid=geteuid(),uid=getuid(),target_uid;
270      gid_t egid=getegid(),gid=getgid(),target_gid;      gid_t egid=getegid(),gid=getgid(),target_gid;
271      struct safe_id_range_list ulist,glist;      struct safe_id_range_list ulist,glist;
272      struct stat st;      struct stat st_before,st_after;
273      char *buf;      char *buf;
274    
275      /* Expected level of trust depends on mode: user switching or not */      /* Expected level of trust depends on mode: user switching or not */
# Line 283  int cgul_read_config(const char *path, c Line 286  int cgul_read_config(const char *path, c
286          /* Nothing to switch, trust_uid/trust_gid will be used to check the file          /* Nothing to switch, trust_uid/trust_gid will be used to check the file
287           * permissions only. */           * permissions only. */
288          target_uid=0; /* target_uid is also added to the safe id list */          target_uid=0; /* target_uid is also added to the safe id list */
289          target_gid=0; /* just in case target_gid would be added to the safe id list */          target_gid=0; /* just in case target_gid would be added to the safe id
290                             list */
291          switching=0;          switching=0;
292      }      }
293    
# Line 297  int cgul_read_config(const char *path, c Line 301  int cgul_read_config(const char *path, c
301           safe_add_id_to_list(&glist,trust_gid) )    {           safe_add_id_to_list(&glist,trust_gid) )    {
302          raise_priv(euid,egid); return -4;          raise_priv(euid,egid); return -4;
303      }      }
304        /* Do an lstat so that we can compare modes etc. before/after */
305        if (lstat(path,&st_before)) {
306            raise_priv(euid,egid); return -2;
307        }
308    
309      /* Check trust */      /* Check trust */
310      trust=safe_is_path_trusted_r(path,&ulist,&glist);      trust=safe_is_path_trusted_r(path,&ulist,&glist);
311      /* free the range lists */      /* free the range lists */
# Line 326  int cgul_read_config(const char *path, c Line 335  int cgul_read_config(const char *path, c
335              raise_priv(euid,egid); return -5;              raise_priv(euid,egid); return -5;
336      }      }
337      /* Open file and stat the file (latter for size) */      /* Open file and stat the file (latter for size) */
338      if ((fd=open(path,O_RDONLY))==-1 || fstat(fd,&st))  {      if ((fd=open(path,O_RDONLY))==-1)   {
339          raise_priv(euid,egid); return -1;          raise_priv(euid,egid); return -1;
340      }      }
341      /* Get expected space, don't forget trailing '\0' */      /* Get expected space, don't forget trailing '\0' */
342      if ( (buf=(char *)malloc((size_t)(st.st_size+sizeof(char))))==NULL)   {      if ( (buf=(char *)malloc((size_t)(st_before.st_size+sizeof(char))))==NULL)
343        {
344          close(fd); raise_priv(euid,egid); return -4;          close(fd); raise_priv(euid,egid); return -4;
345      }      }
346      /* Read the file, check we get right size */      /* Read the file, check we get right size */
347      if (read(fd,buf,st.st_size)!=(ssize_t)st.st_size)      if ( read(fd,buf,st_before.st_size)!=(ssize_t)st_before.st_size ||
348          /* read error, but don't return yet, we want to free the memory           fstat(fd,&st_after) ||                     /* Do stat fd           */
349           * centrally */           st_before.st_dev   !=st_after.st_dev ||    /* device               */
350             st_before.st_ino   !=st_after.st_ino ||    /* inode                */
351             st_before.st_size  !=st_after.st_size ||   /* size                 */
352             st_before.st_mode  !=st_after.st_mode ||   /* mode                 */
353             st_before.st_uid   !=st_after.st_uid ||    /* uid                  */  
354             st_before.st_gid   !=st_after.st_gid ||    /* gid                  */
355             st_before.st_mtime !=st_after.st_mtime ||  /* modification time    */
356             st_before.st_ctime !=st_after.st_ctime )   /* creation time        */
357            /* something changed or went wrong: classify all as I/O error, because
358             * we were reading a trusted or confidential file.
359             * Don't return yet, we want to free the memory centrally */
360          rc=-1;          rc=-1;
361      else    {      else    {
362          /* add trailing '\0' */          /* add trailing '\0' */
363          buf[st.st_size]='\0';          buf[st_after.st_size]='\0';
364          rc=0;          rc=0;
365      }      }
366      /* Close file */      /* Close file */
# Line 366  int cgul_read_config(const char *path, c Line 386  int cgul_read_config(const char *path, c
386   * -2: privilege-drop error   * -2: privilege-drop error
387   * -3: permissions error, including file directly in / or not absolute   * -3: permissions error, including file directly in / or not absolute
388   * -4: memory error   * -4: memory error
389     * -6: locking failed
390   */   */
391  int cgul_write_proxy(const char *path, int lock_type, const char *proxy,  int cgul_write_proxy(const char *path, int lock_type, const char *proxy,
392                       int write_uid, int write_gid) {                       int write_uid, int write_gid) {
# Line 381  int cgul_write_proxy(const char *path, i Line 402  int cgul_write_proxy(const char *path, i
402      if (write_uid>=0)      if (write_uid>=0)
403          target_uid=write_uid;          target_uid=write_uid;
404      else      else
405          target_uid=(uid==0 ? euid : uid); /* when real==root -> stay effective */          target_uid=(uid==0 ? euid : uid); /* when real==root: stay effective */
406      /* Set write gid */      /* Set write gid */
407      if (write_gid>=0)      if (write_gid>=0)
408          target_gid=write_gid;          target_gid=write_gid;
409      else      else
410          target_gid=(gid==0 ? egid : gid); /* when real==root -> stay effective */          target_gid=(gid==0 ? egid : gid); /* when real==root: stay effective */
411    
412      /* Drop privilege when (e)uid == 0 */      /* Drop privilege when (e)uid == 0 */
413      if ( (euid==0 || uid==0) && priv_drop(target_uid,target_gid))      if ( (euid==0 || uid==0) && priv_drop(target_uid,target_gid))
# Line 412  int cgul_write_proxy(const char *path, i Line 433  int cgul_write_proxy(const char *path, i
433      }      }
434      /* Lock the file */      /* Lock the file */
435      if ( cgul_filelock(fd,lock_type,LCK_WRITE) ) {      if ( cgul_filelock(fd,lock_type,LCK_WRITE) ) {
436          close(fd); raise_priv(euid,egid); return -1;          close(fd); raise_priv(euid,egid); return -6;
437      }      }
438      /* Do a chmod and chown, in case it already existed. If this fails, the file      /* Do a chmod and chown, in case it already existed. If this fails, the file
439       * has the wrong permissions.       * has the wrong permissions.
# Line 425  int cgul_write_proxy(const char *path, i Line 446  int cgul_write_proxy(const char *path, i
446           write(fd,proxy,expsize)!=(ssize_t)expsize )    {           write(fd,proxy,expsize)!=(ssize_t)expsize )    {
447          close(fd); raise_priv(euid,egid); return -1; /* write error */          close(fd); raise_priv(euid,egid); return -1; /* write error */
448      }      }
449      /* unlock */      /* unlock: ignore the exit code */
450      cgul_filelock(fd,lock_type,LCK_UNLOCK);      cgul_filelock(fd,lock_type,LCK_UNLOCK);
451      /* close the file, don't ignore exit values: might have write error */      /* close the file, don't ignore exit values: might have write error */
452      if (close(fd))      if (close(fd))
# Line 456  int cgul_write_proxy(const char *path, i Line 477  int cgul_write_proxy(const char *path, i
477   *  -5: invalid template: it MUST end with 6 X's   *  -5: invalid template: it MUST end with 6 X's
478   */   */
479  int cgul_write_uniq_proxy(char *path_template, const char *proxy,  int cgul_write_uniq_proxy(char *path_template, const char *proxy,
480                            int write_uid, int write_gid) {                            int write_uid, int write_gid) {
481      const mode_t filemode=S_IRUSR | S_IWUSR;      const mode_t filemode=S_IRUSR | S_IWUSR;
482      const mode_t dirmode=S_IRUSR | S_IWUSR | S_IXUSR;      const mode_t dirmode=S_IRUSR | S_IWUSR | S_IXUSR;
483      int fd,rc;      int fd,rc;
# Line 474  int cgul_write_uniq_proxy(char *path_tem Line 495  int cgul_write_uniq_proxy(char *path_tem
495      if (write_uid>=0)      if (write_uid>=0)
496          target_uid=write_uid;          target_uid=write_uid;
497      else      else
498          target_uid=(uid==0 ? euid : uid); /* when real==root -> stay effective */          target_uid=(uid==0 ? euid : uid); /* when real==root: stay effective */
499      /* Set write gid */      /* Set write gid */
500      if (write_gid>=0)      if (write_gid>=0)
501          target_gid=write_gid;          target_gid=write_gid;
502      else      else
503          target_gid=(gid==0 ? egid : gid); /* when real==root -> stay effective */          target_gid=(gid==0 ? egid : gid); /* when real==root: stay effective */
504    
505      /* Drop privilege when (e)uid == 0 */      /* Drop privilege when (e)uid == 0 */
506      if ( (euid==0 || uid==0) && priv_drop(target_uid,target_gid))      if ( (euid==0 || uid==0) && priv_drop(target_uid,target_gid))

Legend:
Removed from v.1509  
changed lines
  Added in v.1510

grid.support@nikhef.nl
ViewVC Help
Powered by ViewVC 1.1.28