More error message improvements; work around a suspect Solaris compiler bug

This commit is contained in:
hpa 2002-11-09 02:22:59 +00:00
parent 8036d9e857
commit 0f52cd8fa4
2 changed files with 45 additions and 27 deletions

View file

@ -458,7 +458,7 @@ main(int argc, char **argv)
exit(EX_OSERR);
}
nfd = open("/dev/null", O_RDWR);
if ( nfd >= 0 ) {
if ( nfd >= 3 ) {
#ifdef HAVE_DUP2
dup2(nfd, 0);
dup2(nfd, 1);
@ -469,7 +469,7 @@ main(int argc, char **argv)
close(2); dup(nfd);
#endif
close(nfd);
} else {
} else if ( nfd < 0 ) {
close(0); close(1); close(2);
}
#ifdef HAVE_SETSID
@ -684,14 +684,14 @@ main(int argc, char **argv)
}
char *rewrite_access(char *, int, const char **);
int validate_access(char *, int, struct formats *);
int validate_access(char *, int, struct formats *, const char **);
void tftp_sendfile(struct formats *, struct tftphdr *, int);
void tftp_recvfile(struct formats *, struct tftphdr *, int);
struct formats {
const char *f_mode;
char *(*f_rewrite)(char *, int, const char **);
int (*f_validate)(char *, int, struct formats *);
int (*f_validate)(char *, int, struct formats *, const char **);
void (*f_send)(struct formats *, struct tftphdr *, int);
void (*f_recv)(struct formats *, struct tftphdr *, int);
int f_convert;
@ -707,25 +707,27 @@ struct formats {
int
tftp(struct tftphdr *tp, int size)
{
char *cp;
char *cp, *end;
int argn, ecode;
struct formats *pf = NULL;
char *origfilename;
char *filename, *mode = NULL;
const char *maperrmsg;
const char *errmsgptr;
char *val = NULL, *opt = NULL;
char *ap = ackbuf + 2;
((struct tftphdr *)ackbuf)->th_opcode = ntohs(OACK);
origfilename = cp = (char *) &(tp->th_stuff);
argn = 0;
while ( cp < buf + size && *cp ) {
end = (char *)tp + size;
while ( cp < end && *cp ) {
do {
cp++;
} while (cp < buf + size && *cp);
} while (cp < end && *cp);
if ( *cp ) {
nak(EBADOP, "Request not null-terminated");
@ -747,8 +749,8 @@ tftp(struct tftphdr *tp, int size)
exit(0);
}
if ( !(filename =
(*pf->f_rewrite)(origfilename, tp->th_opcode, &maperrmsg)) ) {
nak(EACCESS, maperrmsg); /* File denied by mapping rule */
(*pf->f_rewrite)(origfilename, tp->th_opcode, &errmsgptr)) ) {
nak(EACCESS, errmsgptr); /* File denied by mapping rule */
exit(0);
}
if ( verbosity >= 1 ) {
@ -761,9 +763,9 @@ tftp(struct tftphdr *tp, int size)
tp->th_opcode == WRQ ? "WRQ" : "RRQ",
inet_ntoa(from.sin_addr), origfilename, filename);
}
ecode = (*pf->f_validate)(filename, tp->th_opcode, pf);
ecode = (*pf->f_validate)(filename, tp->th_opcode, pf, &errmsgptr);
if (ecode) {
nak(ecode, NULL);
nak(ecode, errmsgptr);
exit(0);
}
opt = ++cp;
@ -1034,7 +1036,8 @@ FILE *file;
* given as we have no login directory.
*/
int
validate_access(char *filename, int mode, struct formats *pf)
validate_access(char *filename, int mode,
struct formats *pf, const char **errmsg)
{
struct stat stbuf;
int i, len;
@ -1044,10 +1047,14 @@ validate_access(char *filename, int mode, struct formats *pf)
char stdio_mode[3];
tsize_ok = 0;
*errmsg = NULL;
if (!secure) {
if (*filename != '/')
if (*filename != '/') {
*errmsg = "Only absolute filenames allowed";
return (EACCESS);
}
/*
* prevent tricksters from getting around the directory
* restrictions
@ -1055,15 +1062,19 @@ validate_access(char *filename, int mode, struct formats *pf)
len = strlen(filename);
for ( i = 1 ; i < len-3 ; i++ ) {
cp = filename + i;
if ( *cp == '.' && memcmp(cp-1, "/../", 4) == 0)
if ( *cp == '.' && memcmp(cp-1, "/../", 4) == 0 ) {
*errmsg = "Reverse path not allowed";
return(EACCESS);
}
}
for (dirp = dirs; *dirp; dirp++)
if (strncmp(filename, *dirp, strlen(*dirp)) == 0)
break;
if (*dirp==0 && dirp!=dirs)
if (*dirp==0 && dirp!=dirs) {
*errmsg = "Forbidden directory";
return (EACCESS);
}
}
/*
@ -1088,7 +1099,7 @@ validate_access(char *filename, int mode, struct formats *pf)
case EEXIST:
return EEXISTS;
default:
return EACCESS;
return errno+100;
}
}
@ -1096,20 +1107,26 @@ validate_access(char *filename, int mode, struct formats *pf)
exit(EX_OSERR); /* This shouldn't happen */
if (mode == RRQ) {
if ( !unixperms && (stbuf.st_mode & (S_IREAD >> 6)) == 0 )
if ( !unixperms && (stbuf.st_mode & (S_IREAD >> 6)) == 0 ) {
*errmsg = "File must have global read permissions";
return (EACCESS);
}
tsize = stbuf.st_size;
/* We don't know the tsize if conversion is needed */
tsize_ok = !pf->f_convert;
} else {
if ( !unixperms ) {
if ( (stbuf.st_mode & (S_IWRITE >> 6)) == 0 )
if ( (stbuf.st_mode & (S_IWRITE >> 6)) == 0 ) {
*errmsg = "File must have global write permissions";
return (EACCESS);
}
/* We didn't get to truncate the file at open() time */
#ifdef HAVE_FTRUNCATE
if ( ftruncate(fd, (off_t)0) )
if ( ftruncate(fd, (off_t)0) ) {
*errmsg = "Cannot reset file size";
return(EACCESS);
}
#endif
}
tsize = 0;
@ -1138,8 +1155,6 @@ tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
static u_short block = 1; /* Static to avoid longjmp funnies */
int size, n;
ap = (struct tftphdr *)ackbuf;
if (oap) {
timeout = rexmtval;
(void)sigsetjmp(timeoutbuf,1);
@ -1154,6 +1169,7 @@ tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
syslog(LOG_WARNING, "tftpd: read: %m\n");
goto abort;
}
ap = (struct tftphdr *)ackbuf;
ap->th_opcode = ntohs((u_short)ap->th_opcode);
ap->th_block = ntohs((u_short)ap->th_block);
@ -1194,6 +1210,7 @@ tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
syslog(LOG_WARNING, "tftpd: read(ack): %m");
goto abort;
}
ap = (struct tftphdr *)ackbuf;
ap->th_opcode = ntohs((u_short)ap->th_opcode);
ap->th_block = ntohs((u_short)ap->th_block);