[cpp-sp] branch main updated: Initial impl of encrypting session files.
Codeberg
noreply at shibboleth.net
Tue Sep 22 18:45:40 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository cpp-sp.
View the commit online:
https://codeberg.org/Shibboleth/cpp-sp/commit/06c5cab9a3a0c76f0a9f1731296de26bea812fff
The following commit(s) were added to refs/heads/main by this push:
new 06c5cab9 Initial impl of encrypting session files.
06c5cab9 is described below
commit 06c5cab9a3a0c76f0a9f1731296de26bea812fff
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Tue Sep 22 14:45:21 2026 -0400
Initial impl of encrypting session files.
---
shibsp/session/impl/AbstractSessionCache.cpp | 4 +-
shibsp/session/impl/FilesystemSessionCache.cpp | 131 +++++++++++++++++----
shibsp/session/impl/StorageServiceSessionCache.cpp | 1 -
3 files changed, 106 insertions(+), 30 deletions(-)
diff --git a/shibsp/session/impl/AbstractSessionCache.cpp b/shibsp/session/impl/AbstractSessionCache.cpp
index fbbb358a..f7cbb46b 100644
--- a/shibsp/session/impl/AbstractSessionCache.cpp
+++ b/shibsp/session/impl/AbstractSessionCache.cpp
@@ -644,8 +644,6 @@ bool AbstractSessionCache::update(SPRequest& request, unique_lock<Session>& sess
{
// On input we hold an exclusive lock on the relevant session.
- DDF newData;
-
try {
// Validate and reformat attribute data.
const AttributeConfiguration& attrConfig = request.getAgent().getAttributeConfiguration(
@@ -662,7 +660,7 @@ bool AbstractSessionCache::update(SPRequest& request, unique_lock<Session>& sess
// The update requires that we copy the existing DDF from the original session and then
// replace members with "like" names.
- newData = dynamic_cast<BasicSession*>(session.mutex())->cloneData();
+ DDF newData = dynamic_cast<BasicSession*>(session.mutex())->cloneData();
DDFJanitor janitor(newData);
DDF child = data.first();
while (!child.isnull()) {
diff --git a/shibsp/session/impl/FilesystemSessionCache.cpp b/shibsp/session/impl/FilesystemSessionCache.cpp
index dd36081d..774b18fd 100644
--- a/shibsp/session/impl/FilesystemSessionCache.cpp
+++ b/shibsp/session/impl/FilesystemSessionCache.cpp
@@ -20,8 +20,10 @@
#include "internal.h"
#include "exceptions.h"
+#include "Agent.h"
#include "AgentConfig.h"
#include "SPRequest.h"
+#include "remoting/RemotingService.h"
#include "session/AbstractSessionCache.h"
#include "logging/Category.h"
#include "util/Date.h"
@@ -79,8 +81,11 @@ namespace {
static void* file_cleanup_fn(void*);
static void file_cleanup_callback(const char* pathname, const char* filename, struct stat& stat_buf, void* data);
+ void store_session(SPRequest* request, const char* path, DDF& sessionData);
+
Category& m_spilog;
string m_dir;
+ bool m_encrypt;
time_t m_cleanupInterval;
unsigned int m_fileTimeout;
condition_variable m_file_cleanup_wait;
@@ -88,11 +93,13 @@ namespace {
};
static const char CACHE_DIRECTORY_PROP_NAME[] = "cacheDirectory";
+ static const char ENCRYPT_FILES_PROP_NAME[] = "encryptFiles";
static const char FILE_CLEANUP_TRACKING_FILE_PROP_NAME[] = "fileCleanupTrackingFile";
static const char FILE_CLEANUP_INTERVAL_PROP_NAME[] = "fileCleanupInterval";
static const char FILE_TIMEOUT_PROP_NAME[] = "fileTimeout";
static const char CACHE_DIRECTORY_PROP_DEFAULT[] = "sessions";
+ static bool ENCRYPT_FILES_PROP_DEFAULT = false;
static const char FILE_CLEANUP_TRACKING_FILE_PROP_DEFAULT[] = "shibsp_cache_cleanup";
static unsigned int FILE_CLEANUP_INTERVAL_PROP_DEFAULT = 1800;
static unsigned int FILE_TIMEOUT_PROP_DEFAULT = 3600 * 8;
@@ -149,6 +156,8 @@ FilesystemSessionCache::FilesystemSessionCache(const ptree& pt)
throw ConfigurationException("Configured session cache directory was inaccessible to agent process.");
}
+ m_encrypt = getBool(ENCRYPT_FILES_PROP_NAME, ENCRYPT_FILES_PROP_DEFAULT);
+
m_cleanupInterval = getUnsignedInt(FILE_CLEANUP_INTERVAL_PROP_NAME, FILE_CLEANUP_INTERVAL_PROP_DEFAULT);
if (m_cleanupInterval) {
m_fileTimeout = getUnsignedInt(FILE_TIMEOUT_PROP_NAME, FILE_TIMEOUT_PROP_DEFAULT);
@@ -217,24 +226,24 @@ string FilesystemSessionCache::cache_create(SPRequest* request, const char* cand
#else
close(f);
#endif
- ofstream os(path);
- if (!os) {
- log(ERROR_MARK, "error writing new session to file (%s), errno=%d", path.c_str(), errno);
- throw IOException("Error writing new session to file.");
- }
-
- os << sessionData;
- if (os) {
+ try {
+ store_session(request, path.c_str(), sessionData);
log(DEBUG_MARK, "stored new session (%s)", key.c_str());
return key;
}
+ catch (const exception& e) {
+ log(ERROR_MARK, "exception while storing new session data to file (%s): %s", path.c_str(), e.what());
+ std::remove(path.c_str());
+ throw;
+ }
}
+
// If we get here, we're attempting a retry until we exhaust.
int e = errno;
if (e != EEXIST) {
- log(ERROR_MARK, "error opening new session file (%s), errno=%d", path.c_str(), e);
+ log(ERROR_MARK, "error creating new session file (%s), errno=%d", path.c_str(), e);
} else {
- log(DEBUG_MARK, "error opening new session file (%s), errno=%d", path.c_str(), e);
+ log(DEBUG_MARK, "error creating new session file (%s), errno=%d", path.c_str(), e);
}
key = AgentConfig::getConfig().generateRandom(16);
@@ -284,7 +293,7 @@ DDF FilesystemSessionCache::cache_read(
effective_version++;
}
- // If we get here, we have the effective variables are set correctly.
+ // If we get here, the effective variables are set correctly.
ifstream is(effective_path);
if (!is) {
@@ -311,8 +320,32 @@ DDF FilesystemSessionCache::cache_read(
}
}
- is >> obj;
- is.close();
+ if (m_encrypt) {
+ string buf;
+ is >> buf;
+ is.close();
+
+ log(DEBUG_MARK, "decrypting session data");
+ const RemotingService* remoting = AgentConfig::getConfig().getAgent().getRemotingService();
+ DDF in = remoting->build("sealer", nullptr, request ? request->getRequestID() : nullptr);
+ DDFJanitor injanitor(in);
+
+ in.addmember("op").string("D");
+ in.addmember("value").string(buf);
+
+ DDF out = remoting->send(in); // let this throw to caller
+ DDFJanitor outjanitor(out);
+ const char* decrypted = out["value"].string();
+ if (!decrypted) {
+ throw OperationException("No decrypted session data returned from sealer operation.");
+ }
+ istringstream source(decrypted);
+ source >> obj;
+ }
+ else {
+ is >> obj;
+ is.close();
+ }
if (!isSessionDataValid(obj)) {
log(ERROR_MARK, "deserialized session from file (%s) was invalid", effective_path.c_str());
@@ -414,7 +447,7 @@ bool FilesystemSessionCache::cache_update(SPRequest* request, const char* key, u
version++;
string path = m_dir + key;
computeVersionedFilename(path, version);
-
+
// We attempt an exclusive open to "reserve" the new version's file name.
#ifdef WIN32
int f = _open(path.c_str(), _O_CREAT | _O_EXCL, _S_IREAD | _S_IWRITE);
@@ -445,22 +478,21 @@ bool FilesystemSessionCache::cache_update(SPRequest* request, const char* key, u
close(f);
#endif
- ofstream os(path);
- if (!os) {
- log(ERROR_MARK, "error writing new version of session to file (%s), errno=%d", path.c_str(), errno);
- throw IOException("Error attempting to open file for writing of updated session.");
- }
-
// Ensure the new version is set accurately.
sessionData.addmember("ver").integer(version);
- os << sessionData;
- if (os) {
- log(DEBUG_MARK, "stored new version of session to file (%s)", path.c_str());
+
+ try {
+ store_session(request, path.c_str(), sessionData);
+ log(DEBUG_MARK, "stored updated session (%s) with version (%u)", key, version);
return true;
}
-
- log(ERROR_MARK, "error writing new version of session to file (%s), errno=%d", path.c_str(), errno);
- throw IOException("Error attempting to write to file holding updated session version.");
+ catch (const exception& e) {
+ log(ERROR_MARK, "exception while storing updated session to file (%s): %s", path.c_str(), e.what());
+ // Restore old version.
+ sessionData.addmember("ver").integer(--version);
+ std::remove(path.c_str());
+ throw;
+ }
}
bool FilesystemSessionCache::cache_touch(SPRequest* request, const char* key, unsigned int version, unsigned int timeout)
@@ -535,6 +567,53 @@ void FilesystemSessionCache::cache_remove(SPRequest* request, const char* key)
}
}
+void FilesystemSessionCache::store_session(SPRequest* request, const char* path, DDF& sessionData)
+{
+ if (m_encrypt) {
+ log(DEBUG_MARK, "encrypting session data");
+ const RemotingService* remoting = AgentConfig::getConfig().getAgent().getRemotingService();
+ DDF in = remoting->build("sealer", nullptr, request ? request->getRequestID() : nullptr);
+ DDFJanitor injanitor(in);
+
+ in.addmember("op").string("E");
+ ostringstream sink;
+ sink << sessionData;
+ in.addmember("value").string(sink.str().c_str());
+
+ DDF out = remoting->send(in); // let this throw to caller
+ DDFJanitor outjanitor(out);
+ const char* encrypted = out["value"].string();
+ if (!encrypted) {
+ throw OperationException("No encrypted session data returned from sealer operation.");
+ }
+
+ ofstream os(path);
+ if (!os) {
+ log(ERROR_MARK, "error writing new session to file (%s), errno=%d", path, errno);
+ throw IOException("Error opening new session file for writing.");
+ }
+ os << encrypted;
+ if (!os) {
+ log(ERROR_MARK, "error writing new session to file (%s), errno=%d", path, errno);
+ throw IOException("Error writing new session to file.");
+ }
+ os.close();
+ }
+ else {
+ ofstream os(path);
+ if (!os) {
+ log(ERROR_MARK, "error writing new session to file (%s), errno=%d", path, errno);
+ throw IOException("Error opening new session file for writing.");
+ }
+ os << sessionData;
+ if (!os) {
+ log(ERROR_MARK, "error writing new session to file (%s), errno=%d", path, errno);
+ throw IOException("Error writing new session to file.");
+ }
+ os.close();
+ }
+}
+
void* FilesystemSessionCache::file_cleanup_fn(void* p)
{
FilesystemSessionCache* pcache = reinterpret_cast<FilesystemSessionCache*>(p);
diff --git a/shibsp/session/impl/StorageServiceSessionCache.cpp b/shibsp/session/impl/StorageServiceSessionCache.cpp
index 9093f7fd..ed85c98e 100644
--- a/shibsp/session/impl/StorageServiceSessionCache.cpp
+++ b/shibsp/session/impl/StorageServiceSessionCache.cpp
@@ -108,7 +108,6 @@ string StorageServiceSessionCache::cache_create(SPRequest* request, const char*,
DDFJanitor outJanitor(out);
const char* key = out["key"].string();
if (!key || !*key) {
- log(ERROR_MARK, "no session key returned from create operation");
throw OperationException("No session key returned from create operation.");
}
return string(key);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list