summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrrelyea <rrelyea@fba4d07e-fe0f-4d7f-8147-e0026e666dc0>2010-09-08 20:55:31 +0000
committerrrelyea <rrelyea@fba4d07e-fe0f-4d7f-8147-e0026e666dc0>2010-09-08 20:55:31 +0000
commit12ab0e4a366c0c6083dac7c4213c9329c118f03d (patch)
treeba388ce60778b21be69dbe683553599335897f0b
parentc6876ff8464a46a87ccc27d8084b8621ab2c23cd (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.cpp83
-rw-r--r--src/coolkey/slot.cpp8
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,