[cpp-sp] branch main updated: Add CSPRNG impl, dummy sessio store.

Scott Cantor cantor.2 at osu.edu
Tue Jun 3 14:18:44 UTC 2025


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository cpp-sp.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=f0ffb3d2f074761475e5c0d0c574d146a2f2a3a8

The following commit(s) were added to refs/heads/main by this push:
     new f0ffb3d2 Add CSPRNG impl, dummy sessio store.
f0ffb3d2 is described below

commit f0ffb3d2f074761475e5c0d0c574d146a2f2a3a8
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Jun 3 10:18:40 2025 -0400

    Add CSPRNG impl, dummy sessio store.
---
 Projects/vc22/shibsp.vcxproj                 |   6 +-
 doc/CSPRNG.LICENSE                           |  23 ++++
 doc/Makefile.am                              |   1 +
 shibsp/Makefile.am                           |   4 +
 shibsp/csprng/csprng.h                       |  50 +++++++
 shibsp/csprng/csprng.hpp                     | 195 +++++++++++++++++++++++++++
 shibsp/csprng/impl/csprng.cpp                | 137 +++++++++++++++++++
 shibsp/csprng/is_iterable.hpp                |  46 +++++++
 shibsp/session/impl/AbstractSessionCache.cpp |   1 +
 shibsp/session/impl/MemorySessionCache.cpp   |  14 +-
 10 files changed, 471 insertions(+), 6 deletions(-)

diff --git a/Projects/vc22/shibsp.vcxproj b/Projects/vc22/shibsp.vcxproj
index 2bcab0c8..04ee38b3 100644
--- a/Projects/vc22/shibsp.vcxproj
+++ b/Projects/vc22/shibsp.vcxproj
@@ -32,10 +32,13 @@
     <ClInclude Include="..\..\shibsp\AccessControl.h" />
     <ClInclude Include="..\..\shibsp\Agent.h" />
     <ClInclude Include="..\..\shibsp\AgentConfig.h" />
-    <ClInclude Include="..\..\shibsp\attribute\AttributeConfiguration.h" />
     <ClInclude Include="..\..\shibsp\base.h" />
     <ClInclude Include="..\..\shibsp\config_pub_win32.h" />
     <ClInclude Include="..\..\shibsp\exceptions.h" />
+    <ClInclude Include="..\..\shibsp\attribute\AttributeConfiguration.h" />
+    <ClInclude Include="..\..\shibsp\csprng\csprng.h" />
+    <ClInclude Include="..\..\shibsp\csprng\csprng.hpp" />
+    <ClInclude Include="..\..\shibsp\csprng\is_iterable.hpp" />
     <ClInclude Include="..\..\shibsp\handler\AbstractHandler.h" />
     <ClInclude Include="..\..\shibsp\handler\AssertionConsumerService.h" />
     <ClInclude Include="..\..\shibsp\handler\Handler.h" />
@@ -84,6 +87,7 @@
     <ClCompile Include="..\..\shibsp\AbstractSPRequest.cpp" />
     <ClCompile Include="..\..\shibsp\Agent.cpp" />
     <ClCompile Include="..\..\shibsp\attribute\impl\DefaultAttributeConfiguration.cpp" />
+    <ClCompile Include="..\..\shibsp\csprng\impl\csprng.cpp" />
     <ClCompile Include="..\..\shibsp\exceptions.cpp" />
     <ClCompile Include="..\..\shibsp\handler\impl\AbstractHandler.cpp">
       <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4296;%(DisableSpecificWarnings)</DisableSpecificWarnings>
diff --git a/doc/CSPRNG.LICENSE b/doc/CSPRNG.LICENSE
new file mode 100644
index 00000000..1dad8e93
--- /dev/null
+++ b/doc/CSPRNG.LICENSE
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/doc/Makefile.am b/doc/Makefile.am
index e13fca4c..567b602c 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -13,6 +13,7 @@ docfiles = \
 	NOTICE.txt \
 	README.txt \
 	RELEASE.txt \
+	CSPRNG.LICENSE \
 	FASTCGI.LICENSE
 
 pkgdoc_DATA = $(docfiles)
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index 15fb425d..5608a9c4 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -87,6 +87,9 @@ utilinclude_HEADERS = \
 
 noinst_HEADERS = \
 	internal.h \
+	csprng/csprng.h \
+	csprng/csprng.hpp \
+	csprng/is_iterable.hpp \
 	logging/impl/AbstractLoggingService.h \
 	logging/impl/LoggingServiceSPI.h \
 	logging/impl/StringUtil.h \
@@ -101,6 +104,7 @@ libshibsp_la_SOURCES = \
 	exceptions.cpp \
 	version.cpp \
 	attribute/impl/DefaultAttributeConfiguration.cpp \
+	csprng/impl/csprng.cpp \
 	handler/impl/AbstractHandler.cpp \
 	handler/impl/AdminLogoutInitiator.cpp \
 	handler/impl/AttributeCheckerHandler.cpp \
diff --git a/shibsp/csprng/csprng.h b/shibsp/csprng/csprng.h
new file mode 100644
index 00000000..b49f338d
--- /dev/null
+++ b/shibsp/csprng/csprng.h
@@ -0,0 +1,50 @@
+/*
+// Interface to the OS Cryptographically-Secure Pseudo-Random Number Generator
+
+// Copyright 2017 Michael Thomas Greer
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file ../../LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt )
+*/
+
+#pragma once
+#ifndef DUTHOMHAS_CSPRNG_H
+#define DUTHOMHAS_CSPRNG_H
+
+/* ------------------------------------------------------------------------------------------------
+ * CSPRNG
+ */
+typedef void* CSPRNG;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CSPRNG csprng_create();
+/* Returns a new CSPRNG object, 0 on error.
+ */
+
+int csprng_get( CSPRNG, void* dest, unsigned long long size );
+/* Fills $dest with $size bytes worth of random data.
+ * Returns 1 on succes, 0 on failure.
+ */
+
+long csprng_get_int( CSPRNG );
+/* Return a random value
+ * There is no way to know if it failed.
+ * (If it did fail, the result will be 0, which is fairly unlikely
+ *  to occur multiple times in sequence.
+ *  It is also unlikely to fail at all if csprng_create() succeeded.)
+ */
+
+CSPRNG csprng_destroy( CSPRNG );
+/* Destroy an existing CSPRNG object. Returns 0.
+ * Use it as:
+ *   v = csprng_destroy( v );
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/shibsp/csprng/csprng.hpp b/shibsp/csprng/csprng.hpp
new file mode 100644
index 00000000..9e3dc1eb
--- /dev/null
+++ b/shibsp/csprng/csprng.hpp
@@ -0,0 +1,195 @@
+// Interface to the OS Cryptographically-Secure Pseudo-Random Number Generator
+
+// Copyright 2017 Michael Thomas Greer
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file ../../LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt )
+
+#ifndef DUTHOMHAS_CSPRNG_HPP
+#define DUTHOMHAS_CSPRNG_HPP
+
+#include <shibsp/base.h>
+#include <shibsp/csprng/csprng.h>
+#include <shibsp/csprng/is_iterable.hpp>
+
+#include <initializer_list>
+#include <iterator>
+#include <limits>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+
+//-------------------------------------------------------------------------------------------------
+namespace duthomhas
+{
+  struct csprng
+  {
+    // Standard C++ Library PRNG boilerplate  . . . . . . . . . . . . . . . . . . . . . .
+    typedef unsigned long result_type;
+
+    static constexpr result_type min() { return std::numeric_limits <result_type> ::min(); }
+    static constexpr result_type max() { return std::numeric_limits <result_type> ::max(); }
+
+    template <typename Sseq>
+    void seed( Sseq& ) { }
+    void seed( result_type ) { }
+    void discard( unsigned long long ) { }
+
+  public:
+    // Standard C++ std::seed_seq boilerplate . . . . . . . . . . . . . . . . . . . . . .
+    template <typename Iterator>
+    csprng( Iterator begin, Iterator end ):
+      internal( csprng_create() ),
+      sseq( internal, std::distance( begin, end ) )
+      { }
+
+    template <typename T>
+    csprng( std::initializer_list <T> xs ):
+      internal( csprng_create() ),
+      sseq( internal, xs.size() )
+      { }
+
+    struct sseq_type
+    {
+      // ( This is separated out like this otherwise objects that take a SeedSeq
+      //   object may get confused by the conversion operators in the main class. )
+
+      template <typename Iterator>
+      void generate( Iterator begin, Iterator end )
+      {
+        while (begin != end)
+          *begin++ = csprng_get_int( internal );
+      }
+
+      std::size_t size() const { return seed_seq_size; }
+
+      template <typename Iterator>
+      void param( Iterator dest ) const
+      {
+        for (auto n = seed_seq_size; n--; )
+          *dest++ = csprng_get_int( internal );
+      }
+
+      CSPRNG& internal;
+      std::size_t seed_seq_size;
+
+      sseq_type( CSPRNG& internal, std::size_t seed_seq_size ):
+        internal( internal ),
+        seed_seq_size( seed_seq_size )
+        { }
+    };
+
+  public:
+    // Runtime errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+    struct exception: public std::runtime_error
+    {
+      exception( const char*        message ): std::runtime_error( message ) { }
+      exception( const std::string& message ): std::runtime_error( message ) { }
+    };
+
+    // Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+    csprng(): internal( csprng_create() ), sseq( internal, 0 )
+    {
+      if (!internal)
+        throw exception( "duthomhas::CSPRNG: Failed to initialize the OS CSPRNG" );
+    }
+
+    csprng( const csprng& that ):
+      internal( csprng_create() ),
+      sseq( internal, that.sseq.seed_seq_size )
+    {
+      if (!internal)
+        throw exception( "duthomhas::CSPRNG: Failed to initialize the OS CSPRNG" );
+    }
+
+    // Destructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+   ~csprng()
+    {
+      internal = csprng_destroy( internal );
+    }
+
+    // Typed buffer fill  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+    //   int* xs = rng( new int[ 5 ], 5 );
+    template <typename T>
+    T* operator () ( T* buffer, std::size_t n )
+    {
+      if (!csprng_get( internal, (void*)buffer, n * sizeof(T) ))
+        throw exception( "duthomhas::CSPRNG: Failed to read the OS CSPRNG" );
+      return buffer;
+    }
+
+    // Untyped buffer fill  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+    //   void* p = get_some_unknown_with_known_size_in_bytes();
+    //   rng( p, size_in_bytes );
+//    template <typename T>
+    void* operator () ( void* buffer, std::size_t n )
+    {
+      return operator () <unsigned char> ( (unsigned char*)buffer, n );
+    }
+
+    // Typed assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+    //   int x = rng();
+    template <typename T>
+    operator T ()
+    {
+      T result;
+      return operator () ( result );
+    }
+
+    // Untyped function --> unsigned long . . . . . . . . . . . . . . . . . . . . . . . .
+    //   rng()
+    result_type operator () ()
+    {
+      result_type result;
+      return *operator () ( &result, 1 );
+    }
+
+    // Fundamental / assignable from fundamental types function . . . . . . . . . . . . .
+    //   rng( int() )
+    //
+    //   int x;
+    //   rng( x )
+    template <typename T>
+    typename std::enable_if <std::is_fundamental <typename std::remove_reference <T> ::type> ::value, T&> ::type
+    operator () ( T&& value )
+    {
+      operator () ( &value, 1 );
+      return value;
+    }
+
+    // Iterable types function  . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+    //   auto s = rng( std::string( 20, 0 ) );
+    //   auto v = rng( std::vector <int> ( 20 ) );
+    template <typename Iterable>
+    typename std::enable_if <is_iterable <Iterable> ::value, Iterable&> ::type
+    operator () ( Iterable&& value )
+    {
+      for (auto& v : value)
+        operator () ( v );
+      return value;
+    }
+
+    // Array types function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+    //   int xs[ 20 ];
+    //   rng( xs )
+    template <typename T, std::size_t N>
+    T* operator () ( T* (&array)[ N ] )
+    {
+      for (auto& v : array)
+        operator () ( v );
+      return &(array[0]);
+    }
+
+  private:
+    // Internal state is hidden from user . . . . . . . . . . . . . . . . . . . . . . . .
+    CSPRNG internal;
+    
+  public:
+    // This thing is public, though . . . . . . . . . . . . . . . . . . . . . . . . . . .
+    sseq_type sseq;
+
+  };
+
+}
+
+#endif
diff --git a/shibsp/csprng/impl/csprng.cpp b/shibsp/csprng/impl/csprng.cpp
new file mode 100644
index 00000000..e06dd099
--- /dev/null
+++ b/shibsp/csprng/impl/csprng.cpp
@@ -0,0 +1,137 @@
+/*
+// Source for the OS Cryptographically-Secure Pseudo-Random Number Generator
+
+// Copyright 2017 Michael Thomas Greer
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file ../LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt )
+*/
+
+#include "csprng/csprng.h"
+
+/* ///////////////////////////////////////////////////////////////////////////////////////////// */
+#ifdef _WIN32
+/* ///////////////////////////////////////////////////////////////////////////////////////////// */
+
+  #include <windows.h>
+  #include <wincrypt.h>
+
+  #ifdef _MSC_VER
+  #pragma comment(lib, "advapi32.lib")
+  #endif
+  
+  #ifdef __cplusplus
+  extern "C" {
+  #endif
+
+  /* ------------------------------------------------------------------------------------------- */
+  typedef union
+  {
+    CSPRNG     object;
+    HCRYPTPROV hCryptProv;
+  }
+  CSPRNG_TYPE;
+
+  /* ------------------------------------------------------------------------------------------- */
+  CSPRNG csprng_create()
+  {
+    CSPRNG_TYPE csprng;
+    if (!CryptAcquireContextA( &csprng.hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT ))
+      csprng.hCryptProv = 0;
+    return csprng.object;
+  }
+
+  /* ------------------------------------------------------------------------------------------- */
+  int csprng_get( CSPRNG object, void* dest, unsigned long long size )
+  {
+    // Alas, we have to be pedantic here. csprng_get().size is a 64-bit entity.
+    // However, CryptGenRandom().size is only a 32-bit DWORD. So we have to make sure failure 
+    // isn't from providing less random data than requested, even if absurd.
+    unsigned long long n;
+    
+    CSPRNG_TYPE csprng;
+    csprng.object = object;
+    if (!csprng.hCryptProv) return 0;
+    
+    n = size >> 30;
+    while (n--)
+      if (!CryptGenRandom( csprng.hCryptProv, 1UL << 30, (BYTE*)dest )) return 0;
+      
+    return !!CryptGenRandom( csprng.hCryptProv, size & ((1ULL << 30) - 1), (BYTE*)dest );
+  }
+
+  /* ------------------------------------------------------------------------------------------- */
+  long csprng_get_int( CSPRNG object )
+  {
+    long result;
+    return csprng_get( object, &result, sizeof(result) ) ? result : 0;
+  }
+
+  /* ------------------------------------------------------------------------------------------- */
+  CSPRNG csprng_destroy( CSPRNG object )
+  {
+    CSPRNG_TYPE csprng;
+    csprng.object = object;
+    if (csprng.hCryptProv) CryptReleaseContext( csprng.hCryptProv, 0 );
+    return 0;
+  }
+
+  #ifdef __cplusplus
+  }
+  #endif
+
+/* ///////////////////////////////////////////////////////////////////////////////////////////// */
+#else  /* Using /dev/urandom                                                                     */
+/* ///////////////////////////////////////////////////////////////////////////////////////////// */
+
+  #include <stdio.h>
+
+  #ifdef __cplusplus
+  extern "C" {
+  #endif
+
+  /* ------------------------------------------------------------------------------------------- */
+  typedef union
+  {
+    CSPRNG object;
+    FILE*  urandom;
+  }
+  CSPRNG_TYPE;
+
+  /* ------------------------------------------------------------------------------------------- */
+  CSPRNG csprng_create()
+  {
+    CSPRNG_TYPE csprng;
+    csprng.urandom = fopen( "/dev/urandom", "rb" );
+    return csprng.object;
+  }
+
+  /* ------------------------------------------------------------------------------------------- */
+  int csprng_get( CSPRNG object, void* dest, unsigned long long size )
+  {
+    CSPRNG_TYPE csprng;
+    csprng.object = object;
+    return (csprng.urandom) && (fread( (char*)dest, 1, size, csprng.urandom ) == size);
+  }
+
+  /* ------------------------------------------------------------------------------------------- */
+  long csprng_get_int( CSPRNG object )
+  {
+    long result;
+    return csprng_get( object, &result, sizeof(result) ) ? result : 0;
+  }
+
+  /* ------------------------------------------------------------------------------------------- */
+  CSPRNG csprng_destroy( CSPRNG object )
+  {
+    CSPRNG_TYPE csprng;
+    csprng.object = object;
+    if (csprng.urandom) fclose( csprng.urandom );
+    return 0;
+  }
+  
+  #ifdef __cplusplus
+  }
+  #endif
+
+#endif
diff --git a/shibsp/csprng/is_iterable.hpp b/shibsp/csprng/is_iterable.hpp
new file mode 100644
index 00000000..cb991909
--- /dev/null
+++ b/shibsp/csprng/is_iterable.hpp
@@ -0,0 +1,46 @@
+// is_iterable.hpp
+
+// Copyright 2017 Michael Thomas Greer
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file ../../LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt )
+
+#ifndef DUTHOMHAS_IS_ITERABLE_HPP
+#define DUTHOMHAS_IS_ITERABLE_HPP
+
+namespace duthomhas
+{
+
+  // The basis for this code was found at
+  // https://stackoverflow.com/a/29634934/2706707
+  using std::begin;
+  using std::end;
+
+  template <typename T>
+  class is_iterable
+  {
+    template <typename U>
+    static constexpr auto is_iterable_impl( int ) 
+      -> decltype(
+           begin( std::declval <U&> () ) != end( std::declval <U&> () ),   // begin/end and operator !=
+           void(),                                                         // Handle evil operator ,
+           ++std::declval <decltype( begin( std::declval <U&> () ) )&> (), // operator ++
+           void( *begin( std::declval <U&> () ) ),                         // operator*
+           std::true_type {}
+         )
+    { return std::true_type {}; }
+  
+    template <typename U>
+    static constexpr std::false_type is_iterable_impl(...)
+    { return std::false_type {}; }
+  
+    typedef decltype( is_iterable_impl <T> ( 0 ) ) type;
+    
+  public:
+    //static constexpr bool value = type::value;
+    enum : bool { value = type::value };
+  };
+
+}
+
+#endif
diff --git a/shibsp/session/impl/AbstractSessionCache.cpp b/shibsp/session/impl/AbstractSessionCache.cpp
index 6b41c3aa..e9f686e7 100644
--- a/shibsp/session/impl/AbstractSessionCache.cpp
+++ b/shibsp/session/impl/AbstractSessionCache.cpp
@@ -171,6 +171,7 @@ string AbstractSessionCache::create(SPRequest& request, DDF& session)
         return string();
     }
 
+    session.name(key.c_str());
     unique_ptr<BasicSession> sessionObject(new BasicSession(*this, session));
 
     const char* issuer = nullptr;
diff --git a/shibsp/session/impl/MemorySessionCache.cpp b/shibsp/session/impl/MemorySessionCache.cpp
index 2d33605f..1352bc6e 100644
--- a/shibsp/session/impl/MemorySessionCache.cpp
+++ b/shibsp/session/impl/MemorySessionCache.cpp
@@ -17,13 +17,14 @@
  *
  * SessionCache implementation using non-shared memory.
  * 
- * <p>This is a more or less degenerate implementation of the SessionCacheSPI interface
- * for testing and perhaps very constrained use cases in which only a single agent process
- * can exist.</p>
+ * <p>This is a degenerate implementation for testing and perhaps very constrained use cases
+ * in which only a single agent process can exist. It essentially no-ops all the operations
+ * such that the base class in-process cache is the only store.</p>
  */
 
 #include "internal.h"
 #include "exceptions.h"
+#include "csprng/csprng.hpp"
 #include "session/AbstractSessionCache.h"
 #include "logging/Category.h"
 
@@ -49,6 +50,9 @@ namespace {
             ) const;
         bool cache_touch(const char* key, unsigned int timeout=0) const;
         void cache_remove(const char* key);
+    
+    private:
+        duthomhas::csprng m_rng;
     };
 };
 
@@ -68,7 +72,7 @@ MemorySessionCache::~MemorySessionCache()
 
 string MemorySessionCache::cache_create(DDF& sessionData)
 {
-    return string();
+    return m_rng(string(16,0));
 }
 
 DDF MemorySessionCache::cache_read(
@@ -84,7 +88,7 @@ DDF MemorySessionCache::cache_read(
 
 bool MemorySessionCache::cache_touch(const char* key, unsigned int timeout) const
 {
-    return false;
+    return true;
 }
 
 void MemorySessionCache::cache_remove(const char* key)

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list