예제 #1
0
파일: private.c 프로젝트: dellelce/wuftpd
void priv_gpass(char *gpass)
{
    char *xgpass = NULL;
    struct acgrp *grp;
    uid_t uid;
    gid_t gid;

    if (group_given == 0) {
	reply(503, "Give group name with SITE GROUP first.");
	return;
    }
    /* OK, now they're getting a chance to specify a password.  Make them
     * give the group name again if they fail... */
    group_given = 0;

    grp = priv_getent(groupname);
    if (passbuf && gpass && *gpass != '\0' && grp && *grp->gpass != '\0')
#if defined(SecureWare) || defined(HPUX_10_TRUSTED)
	xgpass = bigcrypt(gpass, grp->gpass);
#else
	xgpass = crypt(gpass, grp->gpass);
#endif

    if (!(((gpass != NULL)
	   && (*gpass != '\0')
	   && (grp != NULL)
	   && (*grp->gpass != '\0')
	   && (strcmp(xgpass, grp->gpass) == 0))
	  || (((gpass == NULL)
	       || (*gpass == '\0'))
	      && (grp != NULL)
	      && (*grp->gpass == '\0'))
	)) {
	reply(530, "Group access request incorrect.");
	grp = NULL;
	if (++group_attempts >= lgi_failure_threshold) {
	    syslog(LOG_NOTICE,
		   "repeated group access failures from %s, group %s",
		   remoteident, groupname);
	    exit(0);
	}
	sleep(group_attempts);	/* slow down password crackers */
	return;
    }

    uid = geteuid();
    gid = grp->gr_gid;

    delay_signaling();		/* we can't allow any signals while euid==0: kinch */
    seteuid(0);
    setegid(gid);
    seteuid(uid);
    enable_signaling();		/* we can allow signals once again: kinch */

    reply(200, "Group access enabled.");
    group_attempts = 0;
}
char *realpath(char const   *pathname , char *result , char *chroot_path ) 
{ char curpath[256] ;
  char workpath[256] ;
  char namebuf[256] ;
  int where ;
  int last ;
  uid_t userid ;
  char *tmp ;
  char *tmp_0 ;
  int tmp_1 ;
  char *__retres ;
  
  {if (result == (void *)0) {__retres = (char *)((void *)0);
     goto return_label;}
  
  if (pathname == (void *)0) {*result = (char)0;
    __retres = (char *)((void *)0);
    goto return_label;}
  
  strcpy(curpath, pathname);
  if ((int const   )*(pathname + 0) != '/')
  {tmp_0 = getcwd(workpath, 256);
  if (! tmp_0) {userid = geteuid();
    delay_signaling();
    seteuid((short)0);
    tmp = getcwd(workpath, 256);
    if (! tmp) {strcpy(result, ".");
      seteuid(userid);
      enable_signaling();
      __retres = (char *)((void *)0);
      goto return_label;}
    
    seteuid(userid);
    enable_signaling();}
  }
  else {workpath[0] = (char)0;}
  
  where = 0;
  while ((int )curpath[where] != 0) {tmp_1 = strcmp(curpath + where, ".");
    if (! tmp_1) {where ++;
      continue;}
    
    /* STAC: BAD */
    strcpy(namebuf, workpath);
    last = 0;
    while ((int )namebuf[last] != 0) {goto __Cont;
      __Cont: /* CIL Label */ ;
      last ++;}
    
    if (last == 0) {r_strcat(namebuf, "/");}
    else {{last --;
           }
    if ((int )namebuf[last] != '/') {r_strcat(namebuf, "/");}
    }
    
    /* STAC: BAD */
    r_strcat(namebuf, curpath + where);}
  
  __retres = result;
  return_label: /* CIL Label */ 
  return (__retres);}

}
예제 #3
0
/*
 * char *fb_realpath(const char *path, char resolved_path[MAXPATHLEN]);
 *
 * Find the real name of path, by removing all ".", ".." and symlink
 * components.  Returns (resolved) on success, or (NULL) on failure,
 * in which case the path which caused trouble is left in (resolved).
 */
char *fb_realpath(const char *path, char *resolved)
{
    struct stat sb;
    int fd, rootd, serrno;
    char *p, *q, wbuf[MAXPATHLEN];
    /*int symlinks = 0;*/
    int resultcode;

#ifdef HAS_NO_FCHDIR
/* AIX Has no fchdir() so we hope the getcwd() call doesn't overrun the buffer! */
    char cwd[MAXPATHLEN + 1];
    char *pcwd;
#endif

    /* Save the starting point. */
    errno = 0;
#ifdef HAS_NO_FCHDIR
#ifdef HAVE_GETCWD
    pcwd = getcwd(cwd, sizeof(cwd));
#else
    pcwd = getwd(cwd);
#endif
#else
    fd = open(".", O_RDONLY);
#endif
    if (EACCES == errno) {
	uid_t userid = geteuid();
	delay_signaling();	/* we can't allow any signals while euid==0: kinch */
	seteuid(0);
#ifdef HAS_NO_FCHDIR
#ifdef HAVE_GETCWD
	pcwd = getcwd(cwd, sizeof(cwd));
#else
	pcwd = getwd(cwd);
#endif
#else
	fd = open(".", O_RDONLY);
#endif
	seteuid(userid);
	enable_signaling();	/* we can allow signals once again: kinch */
    }
#ifdef HAS_NO_FCHDIR
    if (pcwd == NULL)
#else
    if (fd < 0)
#endif
    {
	(void) strcpy(resolved, ".");
	return (NULL);
    }

    /*
     * Find the dirname and basename from the path to be resolved.
     * Change directory to the dirname component.
     * lstat the basename part.
     *     if it is a symlink, read in the value and loop.
     *     if it is a directory, then change to that directory.
     * get the current directory name and append the basename.
     */
    
    (void) strncpy(resolved, path, MAXPATHLEN - 1);
    resolved[MAXPATHLEN - 1] = '\0';

    printf("Before loop resolved = %s\n",resolved); 
 
  loop:
    q = strrchr(resolved, '/');     /* given /home/misha/docs.txt, q now pts to the last slash */
    if (q != NULL) {
      p = q + 1;                   /* p points to docs.txt */

      if (q == resolved)
	q = "/";
      else {
	do {
	  --q;
	} while (q > resolved && *q == '/');
	q[1] = '\0';               /* chop of the last slash */ 
	q = resolved;              /* q = /home/misha */
      }
      
      printf("now resolved = %s\n", resolved);
      errno = 0;
      resultcode = chdir(q);           /* cd to /home/misha */
      
      printf("result of chdir(%s) = %d\n", q, resultcode); 

      if (EACCES == errno) {
	uid_t userid = geteuid();
	delay_signaling();	/* we can't allow any signals while euid==0: kinch */
	seteuid(0);
	errno = 0;
	resultcode = chdir(q);
	seteuid(userid);
	enable_signaling();	/* we can allow signals once again: kinch */
      }
      if (resultcode < 0)
	{
	  printf("Going to err1..\n");
	  goto err1;
	}
    }
    else
      p = resolved;
    
    printf("Dealing with p = %s\n", p);

    /* Deal with the last component. */
    if (*p != '\0') {
      errno = 0;
      resultcode = lstat(p, &sb);

      printf("lstat(%s, &sb) = %d\n",p, resultcode);
 
      if (EACCES == errno) {   /* if permission denied */
	uid_t userid = geteuid();
	delay_signaling();	/* we can't allow any signals while euid==0: kinch */
	seteuid(0);      /* need to become root */
	errno = 0;
	resultcode = lstat(p, &sb);  /* try lstat again, only now as root */
	seteuid(userid);   /* lower privileges!!  */
	enable_signaling();	/* we can allow signals once again: kinch */
      }
      
      if (resultcode == 0) {
#ifdef HAVE_LSTAT
	if (S_ISLNK(sb.st_mode)) {              /* check if docs is a link */ 
	  printf("%s is a link\n", p);

	  if (++symlinks > MAXSYMLINKS) {       /* too many sym links */
	    printf("exceeded MAXSYMLINKS!!\n");
	    errno = ELOOP;                    /* too many levels of sym links */
	    goto err1;
	  }
	  errno = 0;
	  {
	    size_t len = strlen(p);
	    char *tmp = calloc(len + 1, sizeof(char));
	    if (tmp == 0) {
	      serrno = errno;
	      goto err1;
	    }
	    strcpy(tmp, p);
	    p = tmp;

	    printf("p = tmp = %s\n", tmp);
	  }
	  n = readlink(p, resolved, MAXPATHLEN);
	  printf("finished reading link\n");

	  if (EACCES == errno) {                /* i.e if read permission was denied */
 	    printf("access error reading link\n");
	    uid_t userid = geteuid();
	    delay_signaling();	                /* we can't allow any signals while euid==0: kinch */
	    seteuid(0);                         /*need to become root */ 
	    errno = 0;         
	    n = readlink(p, resolved, MAXPATHLEN);
	    seteuid(userid);
	    enable_signaling();		/* we can allow signals once again: kinch */
	  }
	  if (n < 0) {
	    printf("readlink returned %d\n", n);
	    free(p);
	    goto err1;
	    }
	  free(p);
	  resolved[n] = '\0';
	  goto loop;
	}
#endif /* HAVE_LSTAT */
	if (S_ISDIR(sb.st_mode)) {   /* is docs.txt a directory inside /home/misha? */
	  errno = 0;

	  resultcode = chdir(p);        

	  printf("changed dir to %s\n", p);
	  printf("resultcode = %d\n", resultcode);
	  if (EACCES == errno) { 	    
	    uid_t userid = geteuid();
	    printf("had an access error while chdir'ing to %s\n", p);
	    delay_signaling();	/* we can't allow any signals while euid==0: kinch */
	    seteuid(0);
	    errno = 0;
	    resultcode = chdir(p);  /*mz: cd to dir as root, because we lacked permissions */
	    seteuid(userid);
	    enable_signaling();		/* we can allow signals once again: kinch */
	  }
	  if (resultcode < 0)
	    {
	      printf("resultcode = %d in S_ISDIR\n", resultcode);
	      goto err1;
	    }
	  p="";
	}
      }
    }
    
    /*
     * Save the last component name and get the full pathname of
     * the current directory.
     */
    (void) strcpy(wbuf, p);  /* wbuf now contains docs.txt */
    printf("wbuf = %s\n", wbuf);
    errno = 0;
#ifdef HAVE_GETCWD
    resultcode = getcwd(resolved, MAXPATHLEN) == NULL ? 0 : 1; /* cur dir should be /home/misha */
    printf("getcwd yields resolved = %s\n", resolved);        /* and should be shorter than MAXPATHLEN */
#else
    resultcode = getwd(resolved) == NULL ? 0 : 1;       
    printf("getwd yields resolved = %s\n", resolved); 
    if (resolved[MAXPATHLEN - 1] != '\0') {       /* not good.. current working dir longer than MAXPATHLEN */
      printf("resolved cwd is longer than MAXPATHLEN!\n");
      resultcode = 0;
      errno = ERANGE;
    }
#endif
    if (EACCES == errno) {
      uid_t userid = geteuid();
      delay_signaling();	/* we can't allow any signals while euid==0: kinch */
      seteuid(0);
      errno = 0;
#ifdef HAVE_GETCWD
      resultcode = getcwd(resolved, MAXPATHLEN) == NULL ? 0 : 1;
      printf("getcwd gives resultcode = %d\n", resultcode); 
#else
      resultcode = getwd(resolved) == NULL ? 0 : 1;
      if (resolved[MAXPATHLEN - 1] != '\0') {
	resultcode = 0;
	printf("Buffer overflow was attempted!\n");
	errno = ERANGE;
      }
#endif
      seteuid(userid);
      enable_signaling();	/* we can allow signals once again: kinch */
    }
    if (resultcode == 0){
      printf("resultcode was 0, going to err1\n");
      goto err1;
    }
    /*
     * Join the two strings together, ensuring that the right thing
     * happens if the last component is empty, or the dirname is root.
     */
    if (resolved[0] == '/' && resolved[1] == '\0')
      {
	printf("rootd = 1\n");
	rootd = 1;                                             /* we're inside root */
      }
    else{
      printf("rootd = 0\n"); 
      rootd = 0;                                             /* we're not in root */
    }
    printf("strlen(resolved) + strlen(wbuf) + rootd + 1 = %d\n", strlen(resolved) + strlen(wbuf) + rootd + 1);
    
    if (*wbuf) {                             
      if (strlen(resolved) + strlen(wbuf) + rootd + 1 >= MAXPATHLEN) {     /* we changed > to >= */
	errno = ENAMETOOLONG;                    
        printf("resolved path too long!\n");
	goto err1;                              
      }
      if (rootd == 0)
	(void) strcat(resolved, "/");    
      /* OK */                            
      (void) strcat(resolved, wbuf);     /* this should be fine*/
      printf("after strcat, resolved = %s, strlen(resolved) = %d\n", resolved, strlen(resolved));
  }                                    
    
    /* Go back to where we came from. */
    errno = 0;
#ifdef HAS_NO_FCHDIR
    resultcode = chdir(cwd);
#else
    resultcode = fchdir(fd);
#endif
    if (EACCES == errno) {
      uid_t userid = geteuid();
      delay_signaling();	/* we can't allow any signals while euid==0: kinch */
      seteuid(0);
      errno = 0;
#ifdef HAS_NO_FCHDIR
      resultcode = chdir(cwd);
#else
      resultcode = fchdir(fd);
#endif
      seteuid(userid);
      enable_signaling();	/* we can allow signals once again: kinch */
    }
    if (resultcode < 0) {
      serrno = errno;
      goto err2;
    }
    
#ifndef HAS_NO_FCHDIR
    /* It's okay if the close fails, what's an fd more or less? */
    (void) close(fd);
#endif
    return (resolved);
    
 err1:serrno = errno;
#ifdef HAS_NO_FCHDIR
    (void) chdir(cwd);
#else
    (void) fchdir(fd);
    printf("fchdir(fd) completed\n");
#endif
    if (EACCES == errno) {
      uid_t userid = geteuid();
      delay_signaling();	/* we can't allow any signals while euid==0: kinch */
      seteuid(0);
#ifdef HAS_NO_FCHDIR
      (void) chdir(cwd);
#else
      (void) fchdir(fd);
#endif
      seteuid(userid);
      enable_signaling();	/* we can allow signals once again: kinch */
    }
#ifdef HAS_NO_FCHDIR
 err2:errno = serrno;
#else
 err2:(void) close(fd);
    errno = serrno;
#endif
    return (NULL);
}
예제 #4
0
char *
realpath(const char *pathname, char *result, char* chroot_path)
{
  char curpath[MAXPATHLEN],
    workpath[MAXPATHLEN],
    linkpath[MAXPATHLEN],
    namebuf[MAXPATHLEN];
  int len;
  int where;
  int ptr;
  int last;

  if (result == NULL)
    return(NULL);

  if(pathname == NULL){
    *result = EOS; 
    return(NULL);
  }

  strcpy(curpath, pathname);

  if (pathname[0] != '/') {
    uid_t userid;
		
    if (!getcwd(workpath,MAXPATHLEN)) {
      userid = geteuid();
      delay_signaling();
      seteuid(0);
      if (!getcwd(workpath,MAXPATHLEN)) {
        strcpy(result, ".");
        seteuid(userid);
        enable_signaling();
        return (NULL);
      }
      seteuid(userid);
      enable_signaling();
    }
  } else
    workpath[0] = EOS;

  where = 0;
  while (curpath[where] != EOS) {
    if (!strcmp(curpath + where, ".")) {
      where++;
      continue;
    }

    strcpy(namebuf, workpath);
    for (last = 0; namebuf[last] != EOS; last++)
      continue;
    
    /* Chop out the out-of-bounds writes.... */
  }

  /* Stand-in for checking stat fields. */
  if (nondet_int() == 1) {
    len = readlink(namebuf, linkpath, MAXPATHLEN);
    if (len <= 0)
      return NULL;
  
    linkpath[len] = EOS;

    if (linkpath[0] == '/')
      workpath[0] = EOS;
    if (curpath[where] != EOS) {
      /* BAD */
      r_strcat(linkpath, "/");
      /* BAD */
      r_strcat(linkpath, curpath + where);
    }
    /* BAD */
    r_strcpy(curpath, linkpath);
  }

  return result;
}
예제 #5
0
char *fb_realpath(const char *path, char *resolved)
{
  struct stat sb;
  
  int userid1, userid2, userid3, userid4, userid5, userid6, userid7, userid8; // uid_t
  int fd, n, rootd, serrno;
  int len; // size_t len
  char *tmp;
  char *p, *q, wbuf[MAXPATHLEN];
  int symlinks = 0;
  int resultcode;
  int err1_goto, err2_goto, loop_goto;
#ifdef HAS_NO_FCHDIR
  /* AIX Has no fchdir() so we hope the getcwd() call doesn't overrun the buffer! */
  char cwd[MAXPATHLEN + 1];
  char *pcwd;
#endif
  int errno_copy;
  /* Save the starting point. */
  errno_copy = 0;
  err1_goto = err2_goto = loop_goto = 0;
#ifdef HAS_NO_FCHDIR
#ifdef HAVE_GETCWD
  pcwd = getcwd(cwd, sizeof(cwd));
#else
  pcwd = getwd(cwd);
#endif
#else
  fd = open(".", O_RDONLY);
#endif
  if (EACCES == errno_copy) {
    userid1 = geteuid();
    delay_signaling();	/* we can't allow any signals while euid==0: kinch */
    seteuid(0);
#ifdef HAS_NO_FCHDIR
#ifdef HAVE_GETCWD
    pcwd = getcwd(cwd, sizeof(cwd));
#else
    pcwd = getwd(cwd);
#endif
#else
    fd = open(".", O_RDONLY);
#endif
    seteuid(userid1);
    enable_signaling();	/* we can allow signals once again: kinch */
  }
#ifdef HAS_NO_FCHDIR
  if (pcwd == NULL)
#else
    if (fd < 0)
#endif
      {
	(void) strcpy(resolved, ".");
	return (NULL);
      }

  /*
   * Find the dirname and basename from the path to be resolved.
   * Change directory to the dirname component.
   * lstat the basename part.
   *     if it is a symlink, read in the value and loop.
   *     if it is a directory, then change to that directory.
   * get the current directory name and append the basename.
   */
  (void) strncpy(resolved, path, MAXPATHLEN - 1);
  resolved[MAXPATHLEN - 1] = '\0';
  loop_goto = 1;
 loop:
  while(loop_goto==1) {
    err1_goto = err2_goto = loop_goto = 0;
    q = strrchr(resolved, '/'); // q = NULL
    
    if (q != NULL) {
      p = q + 1;
      if (q == resolved)
	q = "/";
      else {
	do { // add do
	  --q;
	} while (q > resolved && *q == '/');
	q[1] = '\0';
	q = resolved;
      }
    
      errno_copy = 0;
      resultcode = chdir(q);
      if (EACCES == errno_copy) {
	userid2 = geteuid();
	delay_signaling();	/* we can't allow any signals while euid==0: kinch */
	seteuid(0);
	errno_copy = 0;
	resultcode = chdir(q);
	seteuid(userid2);
	enable_signaling();	/* we can allow signals once again: kinch */
      }
      if (resultcode < 0)
	err1_goto = 1;/* goto err1; */
    }
    else
      p = resolved;
    if(err1_goto!=1) {
      /* Deal with the last component. */
      if (*p != '\0') {
	errno_copy = 0;
	resultcode = lstat(p, &sb);
	if (EACCES == errno_copy) {
	  userid3 = geteuid();
	  delay_signaling();	/* we can't allow any signals while euid==0: kinch */
	  seteuid(0);
	  errno_copy = 0;
	  resultcode = lstat(p, &sb);
	  seteuid(userid3);
	  enable_signaling();	/* we can allow signals once again: kinch */
	}
	if (resultcode == 0) {
#ifdef HAVE_LSTAT
	  if (S_ISLNK(sb.st_mode)) {
	    if (++symlinks > MAXSYMLINKS) {
	      errno_copy = ELOOP;
	      err1_goto = 1;/*goto err1;*/
	    } else {
	      errno_copy = 0;
	      {
		len = strlen(p);
		tmp = malloc(len + 1, sizeof(char)); //calloc
		if (tmp == 0) {
		  serrno = errno_copy;
		  err1_goto = 1;/*goto err1;*/
		} else {
		  strcpy(tmp, p);
		  p = tmp;
		}
	      }
	      if(err1_goto!=1) {
		n = readlink(p, resolved, MAXPATHLEN);
		if (EACCES == errno_copy) {
		  userid4 = geteuid();
		  delay_signaling();	/* we can't allow any signals while euid==0: kinch */
		  seteuid(0);
		  errno_copy = 0;
		  n = readlink(p, resolved, MAXPATHLEN);
		  seteuid(userid4);
		  enable_signaling();		/* we can allow signals once again: kinch */
		}
		if (n < 0) {
		  free(p);
		  err1_goto = 1;/*goto err1;*/
		} else {
		  free(p);
		  resolved[n] = '\0';
		  loop_goto = 1;/*goto loop;*/
		}
	      }
	    }
	  }
	  if(loop_goto!=1) {
	    if(err1_goto!=1) {
#endif /* HAVE_LSTAT */
	      if (S_ISDIR(sb.st_mode)) {
		errno_copy = 0;
		resultcode = chdir(p);
		if (EACCES == errno_copy) {
		  userid5 = geteuid();
		  delay_signaling();	/* we can't allow any signals while euid==0: kinch */
		  seteuid(0);
		  errno_copy = 0;
		  resultcode = chdir(p);
		  seteuid(userid5);
		  enable_signaling();		/* we can allow signals once again: kinch */
		}
		if (resultcode < 0)
		  err1_goto = 1;/*goto err1;*/
		else
		  p = "";
	      }
	    }
	  }
	}
      }
      if(loop_goto!=1) {
	if(err1_goto!=1) {
	  /*
	   * Save the last component name and get the full pathname of
	   * the current directory.
	   */
	  (void) strcpy(wbuf, p);
	  errno_copy = 0;
#ifdef HAVE_GETCWD
	  resultcode = getcwd(resolved, MAXPATHLEN) == NULL ? 0 : 1;
#else // resultcode = 1; resolved is updated with working directory
	  resultcode = getwd(resolved) == NULL ? 0 : 1;
	  if (resolved[MAXPATHLEN - 1] != '\0') {
	    resultcode = 0;
	    errno_copy = ERANGE;
	  }
#endif
	  if (EACCES == errno_copy) {
	    userid6 = geteuid();
	    delay_signaling();	/* we can't allow any signals while euid==0: kinch */
	    seteuid(0);
	    errno_copy = 0;
#ifdef HAVE_GETCWD
	    resultcode = getcwd(resolved, MAXPATHLEN) == NULL ? 0 : 1;
#else
	    resultcode = getwd(resolved) == NULL ? 0 : 1;
	    if (resolved[MAXPATHLEN - 1] != '\0') {
	      resultcode = 0;
	      errno_copy = ERANGE;
	    }
#endif
	    seteuid(userid6);
	    enable_signaling();	/* we can allow signals once again: kinch */
	  }
	  if (resultcode == 0)
	    err1_goto = 1;/*goto err1;*/
	  else {
	    /*
	     * Join the two strings together, ensuring that the right thing
	     * happens if the last component is empty, or the dirname is root.
	     */
	    if (resolved[0] == '/' && resolved[1] == '\0')
	      rootd = 1;
	    else
	      rootd = 0;
	  
	    if (*wbuf) {
	      if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
		errno_copy = ENAMETOOLONG;
		err1_goto = 1; /*goto err1;*/
	      } else {
		if (rootd == 0)
		  (void) strcat(resolved, "/");
		(void) strcat(resolved, wbuf);
	      
	      }
	    }
	    if(err1_goto!=1) {
	      /* Go back to where we came from. */
	      errno_copy = 0;
#ifdef HAS_NO_FCHDIR
	      resultcode = chdir(cwd);
#else
	      resultcode = fchdir(fd);
#endif
	      if (EACCES == errno_copy) {
		userid7 = geteuid();
		delay_signaling();	/* we can't allow any signals while euid==0: kinch */
		seteuid(0);
		errno_copy = 0;
#ifdef HAS_NO_FCHDIR
		resultcode = chdir(cwd);
#else
		resultcode = fchdir(fd);
#endif
		seteuid(userid7);
		enable_signaling();	/* we can allow signals once again: kinch */
	      }
	      if (resultcode < 0) {
		serrno = errno_copy;
		err2_goto = 1;/*goto err2;*/
	      } else {
	      
#ifndef HAS_NO_FCHDIR
		/* It's okay if the close fails, what's an fd more or less? */
		(void) close(fd);
#endif
		return (resolved);
	      }
	    }
	  }
	}
      }
    }
  }
 err1:
  if(err2_goto!=1) {
    serrno = errno_copy;
#ifdef HAS_NO_FCHDIR
    (void) chdir(cwd);
#else
    (void) fchdir(fd);
#endif
    if (EACCES == errno_copy) {
      userid8 = geteuid();
      delay_signaling();	/* we can't allow any signals while euid==0: kinch */
      seteuid(0);
#ifdef HAS_NO_FCHDIR
      (void) chdir(cwd);
#else
      (void) fchdir(fd);
#endif
      seteuid(userid8);
      enable_signaling();	/* we can allow signals once again: kinch */
    }
  }
#ifdef HAS_NO_FCHDIR
 err2:errno_copy = serrno;
#else
 err2:(void) close(fd);
  errno_copy = serrno;
#endif
  return (NULL);
}
예제 #6
0
char *my_realpath(const char *pathname, char *result, char* chroot_path){
  struct stat sbuf; 
  char canary[] = "GOOD";
  char curpath[MAXPATHLEN], 
    workpath[MAXPATHLEN],
    linkpath[MAXPATHLEN],
    namebuf[MAXPATHLEN],
    *where,
    *ptr,
    *last;
  int len;
  uid_t userid;
  int resultcode;
  
  /* check arguments! */
  
  if (result == NULL)                    /* result must not be null! */
    return(NULL);
  
  if(pathname == NULL){            /* if pathname is null, there is nothing to do */
    *result = '\0'; 
    return(NULL);
  }
  
  printf("MY_REALPATH: pathname passed in = %s\n", pathname);
  
  printf("strcpy(curpath, pathname):Copying %d bytes into an array of size %d\n", 
	 strlen(pathname), sizeof(curpath));
  /* BAD */
  strcpy(curpath, pathname);                /* could overflow curpath.. pathname is tainted */
  printf ("canary=[%s]\n", canary);
  
  if (*pathname != '/') {
    uid_t userid;
    
#ifdef HAVE_GETCWD
    if (!getcwd(workpath,MAXPATHLEN)) {     /* put current working dir into workpath (at most MAXPATHLEN bytes) */
#else
      if (!getwd(workpath)) {              /* put current working dir into workpath (at most PATH_MAX bytes)...deprecated */
#endif	
	userid = geteuid();
	delay_signaling(); /* we can't allow any signals while euid==0: kinch */
	seteuid(0);
#ifdef HAVE_GETCWD
	if (!getcwd(workpath,MAXPATHLEN)) {
#else
	  if (!getwd(workpath)) {    /* this is ok.. workpath can be at most MAXPATHLEN */
#endif
	    strcpy(result, ".");     
	    seteuid(userid);
	    enable_signaling();      /* we can allow signals once again: kinch */
	    return (NULL);
	  }
	  seteuid(userid);
	  enable_signaling();        /* we can allow signals once again: kinch */
	}
      } else
        *workpath = '\0';
      
      /* curpath is the path we're still resolving      */
      /* linkpath is the path a symbolic link points to */
      /* workpath is the path we've resolved            */
      
      /*loop:*/  /* Don't use GOTOs!!! Even the almighty PolySpace can't handle them*/
      
      where = curpath;   /* where = pathname */
      while (*where != '\0') {
	if (!strcmp(where, ".")) {   
	  where++;
	  continue;
	}
        /* deal with "./" */
	if (!strncmp(where, "./", 2)) {
	  where += 2;
	  continue;
        }
	/* deal with "../" */
	if (!strncmp(where, "../", 3)) {
	  where += 3;
	  ptr = last = workpath;    /* workpath is cwd */
	  while (*ptr != '\0') {
	    if (*ptr == '/')
	      last = ptr;           /* finds the last slash in cwd */
	    ptr++;
	  }
	  *last = '\0';
	  continue;
	}
        ptr = strchr(where, '/');
        if (ptr == (char *)NULL)
	  ptr = where + strlen(where) - 1;
        else
	  *ptr = '\0';
	
        strcpy(namebuf, workpath);          /* this is a safe call */
        for (last = namebuf; *last; last++)
	  continue;
        if ((last == namebuf) || (*--last != '/')) {	   
	  /* BAD */	  
	  strcat(namebuf, "/");                     /* append slash to cwd.. dangerous.. could be an off-by-one overflow */
	  printf ("canary=[%s]\n", canary);
	}
	/* BAD */
	strcat(namebuf, where);
	printf ("canary=[%s]\n", canary);
	  
	where = ++ptr;
	
	userid = geteuid();
	delay_signaling(); /* we can't allow any signals while euid==0: kinch */
	seteuid(0);
	resultcode = lstat(namebuf, &sbuf);
	seteuid(userid);
	enable_signaling(); /* we can allow signals once again: kinch */
	  
	if (resultcode == -1) {
	  if (chroot_path == NULL){
	    /* BAD */
	    strcpy(result, namebuf);
	    printf ("canary=[%s]\n", canary);
	  }
	  else {
	    /*BAD*/
	    strcpy(result, chroot_path);
	    printf ("canary=[%s]\n", canary);
	    if (namebuf[0]!='/')
	      {
		/*BAD*/
		strcat(result, namebuf);
		printf ("canary=[%s]\n", canary);
	      }
	    else if (namebuf[1] != '\0') {
	      for (ptr=result; *ptr!= '\0'; ptr++);
	      if (ptr==result || *--ptr != '/') {
		/* BAD */
		strcat(result, namebuf);
		printf ("canary=[%s]\n", canary);
	      }
	      else {
		/*BAD*/
		strcat(result, &namebuf[1]);
		printf ("canary=[%s]\n", canary);
	      }
	    }
	  }
	  return (NULL);
	}
	/* was IFLNK */
#ifdef HAVE_SYMLINK
	if ((sbuf.st_mode & S_IFMT) == S_IFLNK) {
	  userid = geteuid();
	  delay_signaling(); /* we can't allow any signals while euid==0: kinch */
	  seteuid(0);
	  len = readlink(namebuf, linkpath, MAXPATHLEN);   /* safe */
	  seteuid(userid);
	  enable_signaling(); /* we can allow signals once again: kinch */
	  if (len == 0) {
	    if (chroot_path == NULL) {
	      /* BAD */
	      strcpy(result, namebuf);
	      printf ("canary=[%s]\n", canary);
	    }
	    else {
              /*BAD*/
	      strcpy(result, chroot_path);  
	      printf ("canary=[%s]\n", canary);
	      if (namebuf[0]!='/') {
		/* BAD */
		strcat(result, namebuf);
		printf ("canary=[%s]\n", canary);
	      }
	      else if (namebuf[1]!='\0') {
		for (ptr=result; *ptr!= '\0'; ptr++);
		if (ptr==result || *--ptr != '/') {
		  /* BAD */
		  strcat(result, namebuf);
		  printf ("canary=[%s]\n", canary);
		}
		else {
		  /* BAD */
		  strcat(result, &namebuf[1]);
		  printf ("canary=[%s]\n", canary);
		}
	      }
	    }
	    return (NULL);
	  }
	  *(linkpath + len) = '\0';   /* readlink doesn't null-terminate
				       * result */
	  if (*linkpath == '/')
	    *workpath = '\0';
	  if (*where) {
	    /* BAD */
	    strcat(linkpath, "/");
	    printf ("canary=[%s]\n", canary);
	    /* BAD */
	    strcat(linkpath, where);
	    printf ("canary=[%s]\n", canary);
	  }
	  
	  /*BAD*/
	  strcpy(curpath, linkpath);
	  printf ("canary=[%s]\n", canary);
	  

	  /*goto loop;*/
	  /* Replace goto loop with the following two lines */
	  where = curpath;
	  continue;
	}
#endif
	if ((sbuf.st_mode & S_IFDIR) == S_IFDIR) {
	  /* BAD */
	  strcpy(workpath, namebuf);
	  printf ("canary=[%s]\n", canary);
	  continue;
	}
	if (*where) {
	  if (chroot_path == NULL) {
	    /* BAD */
	    strcpy(result, namebuf);
	    printf ("canary=[%s]\n", canary);
	  }
	  else {
	    strcpy(result, chroot_path);
	    if (namebuf[0]!='/') {
	      /* BAD */
	      strcat(result, namebuf);
	      printf ("canary=[%s]\n", canary);
	    }
	    else if (namebuf[1]!='\0') {
	      for (ptr=result; *ptr!= '\0'; ptr++);
	      if (ptr==result || *--ptr != '/') {
		/* BAD */
		strcat(result, namebuf);
		printf ("canary=[%s]\n", canary);
	      }
 	      else {
		/* BAD */
		strcat(result, &namebuf[1]);
		printf ("canary=[%s]\n", canary);
	      }
	    }
	  }
	  return (NULL);      /* path/notadir/morepath */
	} else {
	  /* BAD */
	  strcpy(workpath, namebuf);
	  printf ("canary=[%s]\n", canary);
	}
      }
      if (chroot_path == NULL) {
	/* BAD */
	strcpy(result, workpath);
	printf ("canary=[%s]\n", canary);
      }
      else {
	/*BAD*/
	strcpy(result, chroot_path);
	printf ("canary=[%s]\n", canary);
	if (workpath[0]!='/') {
	  /* BAD */
	  strcat(result, workpath);
	  printf ("canary=[%s]\n", canary);
	}
	else if (workpath[1] != '\0') {
	  for (ptr=result; *ptr!= '\0'; ptr++);
	  if (ptr==result || *--ptr != '/') {
	    /* BAD */
	    strcat(result, workpath);
	    printf ("canary=[%s]\n", canary);
	  }
	  else {
	    /* BAD */
	    strcat(result, &workpath[1]);
	    printf ("canary=[%s]\n", canary);
	  }
	}
      }
      return (result);
    }