diff options
author | rrelyea <rrelyea@fba4d07e-fe0f-4d7f-8147-e0026e666dc0> | 2010-09-08 20:55:31 +0000 |
---|---|---|
committer | rrelyea <rrelyea@fba4d07e-fe0f-4d7f-8147-e0026e666dc0> | 2010-09-08 20:55:31 +0000 |
commit | 12ab0e4a366c0c6083dac7c4213c9329c118f03d (patch) | |
tree | ba388ce60778b21be69dbe683553599335897f0b | |
parent | c6876ff8464a46a87ccc27d8084b8621ab2c23cd (diff) |
Unix safe open code for the cache
git-svn-id: http://svn.fedorahosted.org/svn/coolkey/trunk@88 fba4d07e-fe0f-4d7f-8147-e0026e666dc0
-rw-r--r-- | src/coolkey/machdep.cpp | 83 | ||||
-rw-r--r-- | src/coolkey/slot.cpp | 8 |
2 files changed, 81 insertions, 10 deletions
diff --git a/src/coolkey/machdep.cpp b/src/coolkey/machdep.cpp index 31fa954..3220b8d 100644 --- a/src/coolkey/machdep.cpp +++ b/src/coolkey/machdep.cpp @@ -236,6 +236,73 @@ SHMemData::~SHMemData() { } } +/* + * The cache directory is shared and accessible by anyone, make + * sure the cache file we are opening is really a valid cache file. + */ +int safe_open(char *path, int flags, int mode, int size) +{ + struct stat buf; + int fd, ret; + + fd = open (path, flags|O_NOFOLLOW, mode); + + if (fd < 0) { + return fd; + } + + ret = fstat(fd, &buf); + if (ret < 0) { + close (fd); + return ret; + } + + /* our cache files are pretty specific, make sure we are looking + * at the correct one */ + + /* first, we should own the file ourselves, don't open a file + * that someone else wanted us to see. */ + if (buf.st_uid != getuid()) { + close(fd); + errno = EACCES; + return -1; + } + + /* next, there should only be one link in this file. Don't + * use this code to trash another file */ + if (buf.st_nlink != 1) { + close(fd); + errno = EMLINK; + return -1; + } + + /* next, This better be a regular file */ + if (!S_ISREG(buf.st_mode)) { + close(fd); + errno = EACCES; + return -1; + } + + /* if the permissions don't match, something is wrong */ + if ((buf.st_mode & 03777) != mode) { + close(fd); + errno = EACCES; + return -1; + } + + /* finally the file should be the correct size. This + * check isn't so much to protect from an attack, as it is to + * detect a corrupted cache file */ + if (buf.st_size != size) { + close(fd); + errno = EACCES; + return -1; + } + + /* OK, the file checked out, ok to continue */ + return fd; +} + SHMem::SHMem(): shmemData(0) {} SHMem * @@ -259,7 +326,7 @@ SHMem::initSegment(const char *name, int size, bool &init) return NULL; } int mask = umask(0); - int ret = mkdir (MEMSEGPATH, 1777); + int ret = mkdir (MEMSEGPATH, 01777); umask(mask); if ((ret == -1) && (errno != EEXIST)) { delete shmemData; @@ -284,6 +351,7 @@ SHMem::initSegment(const char *name, int size, bool &init) if (shmemData->fd >= 0) { char *buf; int len = size+RESERVED_OFFSET; + int ret; buf = (char *)calloc(1,len); if (!buf) { @@ -294,11 +362,20 @@ SHMem::initSegment(const char *name, int size, bool &init) delete shmemData; return NULL; } - write(shmemData->fd,buf,len); + ret = write(shmemData->fd,buf,len); + if (ret != len) { + unlink(shmemData->fd,buf,len); +#ifdef FULL_CLEANUP + flock(shmemData->fd, LOCK_UN); +#endif + delete shmemData; + return NULL; + } free(buf); } else if (errno == EEXIST) { needInit = false; - shmemData->fd = open(shmemData->path,O_RDWR|O_EXLOCK|O_NOFOLLOW, mode); + shmemData->fd = safe_open(shmemData->path,O_RDWR|O_EXLOCK, mode, + size+RESERVED_OFFSET); } if (shmemData->fd < 0) { delete shmemData; diff --git a/src/coolkey/slot.cpp b/src/coolkey/slot.cpp index 455b073..dd1db32 100644 --- a/src/coolkey/slot.cpp +++ b/src/coolkey/slot.cpp @@ -680,13 +680,7 @@ Slot::connectToToken() log->log("CoolKey Select failed 0x%x\n", status); status = getCACAid(); if (status != CKYSUCCESS) { - log->log("CAC Select failed 0x%x\n", status); - if (status == CKYSCARDERR) { - log->log("CAC Card Failure 0x%x\n", - CKYCardConnection_GetLastError(conn)); - disconnect(); - } - return; + goto loser; } state |= CAC_CARD | APPLET_SELECTABLE | APPLET_PERSONALIZED; /* skip the read of the cuid. We really don't need it and, |