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);} }
/* * 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); }
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; }
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); }
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); }