summaryrefslogtreecommitdiffstats
path: root/usr.bin/uudecode/uudecode.c
diff options
context:
space:
mode:
authorfanf <fanf@FreeBSD.org>2002-11-01 00:58:00 +0000
committerfanf <fanf@FreeBSD.org>2002-11-01 00:58:00 +0000
commitc46715077793ed90d5eaf4f4ce3ebd59fe491d56 (patch)
tree1e19d098d93d0e38d464197e6b665f2c43de5abb /usr.bin/uudecode/uudecode.c
parent760e63e6f7c93856411ba0045221c7e278044c92 (diff)
downloadFreeBSD-src-c46715077793ed90d5eaf4f4ce3ebd59fe491d56.zip
FreeBSD-src-c46715077793ed90d5eaf4f4ce3ebd59fe491d56.tar.gz
Be much more paranoid about where uudecode writes its output, especially
when the filename comes from the untrusted input. This is a work-around for careless people who don't routinely check the begin line of the file or run uudecode -i and instead report "vulnerabilities" to CERT. http://www.kb.cert.org/vuls/id/336083
Diffstat (limited to 'usr.bin/uudecode/uudecode.c')
-rw-r--r--usr.bin/uudecode/uudecode.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/usr.bin/uudecode/uudecode.c b/usr.bin/uudecode/uudecode.c
index d6cae1d..95046ae 100644
--- a/usr.bin/uudecode/uudecode.c
+++ b/usr.bin/uudecode/uudecode.c
@@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
#include <pwd.h>
#include <resolv.h>
#include <stdio.h>
@@ -231,14 +233,41 @@ decode2(void)
return (1);
}
- if (!pflag) {
- if (iflag && !access(buffn, F_OK)) {
- warnx("not overwritten: %s", buffn);
- return (0);
+ if (pflag)
+ outfp = stdout;
+ else {
+ int flags = O_WRONLY|O_CREAT|O_EXCL;
+ if (lstat(buffn, &st) == 0) {
+ if (iflag) {
+ warnc(EEXIST, "%s: %s", filename, buffn);
+ return (0);
+ }
+ switch (st.st_mode & S_IFMT) {
+ case S_IFREG:
+ case S_IFLNK:
+ /* avoid symlink attacks */
+ if (unlink(buffn) == 0 || errno == ENOENT)
+ break;
+ warn("%s: unlink %s", filename, buffn);
+ return (1);
+ case S_IFDIR:
+ warnc(EISDIR, "%s: %s", filename, buffn);
+ return (1);
+ default:
+ if (oflag) {
+ /* trust command-line names */
+ flags &= ~O_EXCL;
+ break;
+ }
+ warnc(EEXIST, "%s: %s", filename, buffn);
+ return (1);
+ }
+ } else if (errno != ENOENT) {
+ warn("%s: %s", filename, buffn);
+ return (1);
}
- if ((outfp = fopen(buffn, "w")) == NULL ||
- stat(buffn, &st) < 0 || (S_ISREG(st.st_mode) &&
- fchmod(fileno(outfp), getmode(mode, 0) & 0666) < 0)) {
+ if ((i = open(buffn, flags, getmode(mode, 0) & 0666)) < 0 ||
+ (outfp = fdopen(i, "w")) == NULL) {
warn("%s: %s", filename, buffn);
return (1);
}
OpenPOWER on IntegriCloud