SecTranslocateUtilities.cpp [plain text]
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <dlfcn.h>
#define __APPLE_API_PRIVATE
#include <quarantine.h>
#undef __APPLE_API_PRIVATE
#include <security_utilities/logging.h>
#include <security_utilities/unix++.h>
#include <security_utilities/cfutilities.h>
#include "SecTranslocateUtilities.hpp"
#define APP_TRANSLOCATION_DIR "/AppTranslocation/"
namespace Security {
using namespace Security::UnixPlusPlus;
namespace SecTranslocate {
using namespace std;
void ExtendedAutoFileDesc::init()
{
char absPath[MAXPATHLEN];
if(isOpen())
{
UnixError::check(fstatfs(fd(), &fsInfo));
fcntl(F_GETPATH, absPath);
realPath = absPath;
quarantined = false;
qtn_flags = 0;
quarantineFetched = false; }
}
bool ExtendedAutoFileDesc::isFileSystemType(const string &fsType) const
{
notOpen();
return fsType == fsInfo.f_fstypename;
}
bool ExtendedAutoFileDesc::pathIsAbsolute() const
{
notOpen();
return originalPath == realPath;
}
bool ExtendedAutoFileDesc::isMountPoint() const
{
notOpen(); return realPath == fsInfo.f_mntonname;
}
bool ExtendedAutoFileDesc::isInPrefixDir(const string &prefixDir) const
{
notOpen();
return strncmp(realPath.c_str(), prefixDir.c_str(), prefixDir.length()) == 0;
}
string ExtendedAutoFileDesc::getFsType() const
{
notOpen();
return fsInfo.f_fstypename;
}
string ExtendedAutoFileDesc::getMountPoint() const
{
notOpen();
return fsInfo.f_mntonname;
}
string ExtendedAutoFileDesc::getMountFromPath() const
{
notOpen();
return fsInfo.f_mntfromname;
}
const string& ExtendedAutoFileDesc::getRealPath() const
{
notOpen();
return realPath;
}
fsid_t const ExtendedAutoFileDesc::getFsid() const
{
notOpen();
return fsInfo.f_fsid;
}
void ExtendedAutoFileDesc::fetchQuarantine()
{
if(!quarantineFetched)
{
notOpen();
qtn_file_t qf = qtn_file_alloc();
if(qf)
{
if(0 == qtn_file_init_with_fd(qf, fd()))
{
quarantined = true;
qtn_flags = qtn_file_get_flags(qf);
}
qtn_file_free(qf);
quarantineFetched = true;
}
else
{
Syslog::error("SecTranslocate: failed to allocate memory for quarantine struct");
UnixError::throwMe();
}
}
}
bool ExtendedAutoFileDesc::isQuarantined()
{
notOpen();
fetchQuarantine();
return quarantined;
}
bool ExtendedAutoFileDesc::isUserApproved()
{
notOpen();
fetchQuarantine();
return ((qtn_flags & QTN_FLAG_USER_APPROVED) == QTN_FLAG_USER_APPROVED);
}
bool ExtendedAutoFileDesc::shouldTranslocate()
{
notOpen();
fetchQuarantine();
return ((qtn_flags & (QTN_FLAG_TRANSLOCATE | QTN_FLAG_DO_NOT_TRANSLOCATE)) == QTN_FLAG_TRANSLOCATE);
}
vector<string> splitPath(const string &path)
{
vector<string> out;
size_t start = 0;
size_t end = 0;
size_t len = 0;
if(path.empty() || path.front() != '/')
{
Syslog::error("SecTranslocate::splitPath: asked to split a non-absolute or empty path: %s",path.c_str());
UnixError::throwMe(EINVAL);
}
while(end != string::npos)
{
end = path.find('/', start);
len = (end == string::npos) ? end : (end - start);
string temp = path.substr(start,len);
if(!temp.empty())
{
out.push_back(temp);
}
start = end + 1;
}
return out;
}
string joinPath(vector<string>& path)
{
string out = "";
for(auto &i : path)
{
out += "/"+i;
}
return out;
}
string joinPathUpTo(vector<string> &path, size_t index)
{
if (path.size() == 0 || index > path.size()-1)
{
Syslog::error("SecTranslocate::joinPathUpTo invalid index %lu (size %lu)",index, path.size()-1);
UnixError::throwMe(EINVAL);
}
string out = "";
for (size_t i = 0; i <= index; i++)
{
out += "/" + path[i];
}
return out;
}
string getRealPath(const string &path)
{
char absPath[MAXPATHLEN];
AutoFileDesc fd(path);
fd.fcntl(F_GETPATH, absPath);
return absPath;
}
string makeUUID()
{
CFRef<CFUUIDRef> newUUID = CFUUIDCreate(NULL);
if (!newUUID)
{
UnixError::throwMe(ENOMEM);
}
CFRef<CFStringRef> str = CFUUIDCreateString(NULL, newUUID.get());
if (!str)
{
UnixError::throwMe(ENOMEM);
}
return cfString(str);
}
void* checkedDlopen(const char* path, int mode)
{
void* handle = dlopen(path, mode);
if(handle == NULL)
{
Syslog::critical("SecTranslocate: failed to load library %s: %s", path, dlerror());
UnixError::throwMe();
}
return handle;
}
void* checkedDlsym(void* handle, const char* symbol)
{
void* result = dlsym(handle, symbol);
if(result == NULL)
{
Syslog::critical("SecTranslocate: failed to load symbol %s: %s", symbol, dlerror());
UnixError::throwMe();
}
return result;
}
string translocationDirForUser()
{
char userTempPath[MAXPATHLEN];
if(confstr(_CS_DARWIN_USER_TEMP_DIR, userTempPath, sizeof(userTempPath)) == 0)
{
Syslog::error("SecTranslocate: Failed to get temp dir for user %d (error:%d)",
getuid(),
errno);
UnixError::throwMe();
}
return getRealPath(userTempPath)+APP_TRANSLOCATION_DIR;
}
int getFDForDirectory(const string &directoryPath, bool *owned)
{
FileDesc fd(directoryPath, O_RDONLY, FileDesc::modeMissingOk);
if(!fd)
{
UnixError::check(mkdir(directoryPath.c_str(),0755));
fd.open(directoryPath);
if(owned)
{
*owned = true;
}
}
else if (owned)
{
*owned = false;
}
return fd;
}
}
}