Compare commits

...

6 Commits
yops ... master

Author SHA1 Message Date
  Artyom Beilis de995bae7a
Merge pull request #65 from mark-whiting/master 4 years ago
  Mark Whiting 04aa46b2b0 Added config options to set the HttpOnly and SameSite directives on the session cookie. 4 years ago
  Mark Whiting 571fc96ac6 Added support for the HttpOnly and SameSite directives to cookies. 4 years ago
  Artyom Beilis 270634e69f
Merge pull request #44 from mgavin/cppcms_tmpl_cc_python2_fix 5 years ago
  Artyom Beilis 3e3cf43201 Attempt to fix #43 failure to read from /dev/urandom 5 years ago
  mgavin ddc23a101b cppcms_tmpl_cc: 5 years ago
9 changed files with 189 additions and 13 deletions
Split View
  1. +6
    -3
      bin/cppcms_tmpl_cc
  2. +6
    -0
      cppcms/capi/session.h
  3. +29
    -1
      cppcms/http_cookie.h
  4. +20
    -0
      private/cached_settings.h
  5. +14
    -0
      src/capi/session.cpp
  6. +63
    -6
      src/http_cookie.cpp
  7. +8
    -1
      src/session_interface.cpp
  8. +12
    -2
      src/urandom.cpp
  9. +31
    -0
      tests/cookie_test.cpp

+ 6
- 3
bin/cppcms_tmpl_cc View File

@@ -11,7 +11,10 @@
import os
import re
import sys
import StringIO
try:
from StringIO import StringIO
except ModuleNotFoundError: # StringIO moved to io in python 3
from io import StringIO

str_match=r'"([^"\\]|\\[^"]|\\")*"'
single_var_param_match=r'(?:-?\d+|"(?:[^"\\]|\\[^"]|\\")*")'
@@ -1244,8 +1247,8 @@ view_created=False
scope_filter='cppcms::filters::escape'

view_name = ''
declarations = StringIO.StringIO();
definitions = StringIO.StringIO();
declarations = StringIO();
definitions = StringIO();
inline_cpp_to = output_declaration
inline_templates = "default"
output_template = output_definition


+ 6
- 0
cppcms/capi/session.h View File

@@ -155,6 +155,12 @@ CPPCMS_API long long cppcms_capi_cookie_expires(cppcms_capi_cookie const *cookie

CPPCMS_API int cppcms_capi_cookie_is_secure(cppcms_capi_cookie const *cookie);

CPPCMS_API int cppcms_capi_cookie_is_httponly(cppcms_capi_cookie const *cookie);

CPPCMS_API int cppcms_capi_cookie_samesite_none_defined(cppcms_capi_cookie const *cookie);
CPPCMS_API int cppcms_capi_cookie_samesite_lax_defined(cppcms_capi_cookie const *cookie);
CPPCMS_API int cppcms_capi_cookie_samesite_strict_defined(cppcms_capi_cookie const *cookie);

///
/// @}
///


+ 29
- 1
cppcms/http_cookie.h View File

@@ -120,6 +120,30 @@ public:
void secure(bool v);

///
/// Check if the httponly propertie is set on the cookies
///
bool httponly() const;

///
/// Set httponly property on the cookies
///
void httponly(bool v);

///
/// Check if one of the samesite properties is set on the cookies
///
bool samesite_none() const;
bool samesite_lax() const;
bool samesite_strict() const;

///
/// Set one of the samesite properties on the cookies
///
void samesite_none(bool v);
void samesite_lax(bool v);
void samesite_strict(bool v);

///
/// Check if cookie is not assigned - empty
///
bool empty() const;
@@ -165,7 +189,11 @@ private:
uint32_t secure_ : 1;
uint32_t has_age_ : 1;
uint32_t has_expiration_: 1;
CPPCMS_UNUSED_MEMBER uint32_t reserved_ : 29;
uint32_t httponly_ : 1;
uint32_t samesite_none_: 1;
uint32_t samesite_lax_: 1;
uint32_t samesite_strict_: 1;
CPPCMS_UNUSED_MEMBER uint32_t reserved_ : 25;
};




+ 20
- 0
private/cached_settings.h View File

@@ -142,6 +142,10 @@ namespace impl {
bool use_age;
bool use_exp;
bool secure;
bool httponly;
bool use_samesite_none;
bool use_samesite_lax;
bool use_samesite_strict;
bool remove_unknown_cookies;
} cookies;
cached_session(json::value const &v)
@@ -173,6 +177,22 @@ namespace impl {
cookies.use_age = cookies.use_exp = true;
}
cookies.secure = v.get("session.cookies.secure",false);
cookies.httponly = v.get("session.cookies.httponly", false);

std::string samesite = v.get("session.cookies.samesite", "");
cookies.use_samesite_none = false;
cookies.use_samesite_lax = false;
cookies.use_samesite_strict = false;
if (samesite == "none") {
cookies.use_samesite_none = true;
} else if (samesite == "lax") {
cookies.use_samesite_lax = true;
} else if (samesite == "strict") {
cookies.use_samesite_strict = true;
} else if (!samesite.empty()) {
BOOSTER_WARNING("cppcms") << "Invalid session.cookies.samesite"
"if set should be one of 'none', 'lax', or 'strict'; defaults to unset";
}
}
} session;
struct cached_misc {


+ 14
- 0
src/capi/session.cpp View File

@@ -108,6 +108,10 @@ struct cppcms_capi_cookie {
std::string path;
std::string domain;
bool secure;
bool httponly;
bool has_samesite_none;
bool has_samesite_lax;
bool has_samesite_strict;
bool has_expires;
bool has_max_age;
time_t expires;
@@ -121,6 +125,10 @@ struct cppcms_capi_cookie {
path(c.path()),
domain(c.domain()),
secure(c.secure()),
httponly(c.httponly()),
has_samesite_none(c.samesite_none()),
has_samesite_lax(c.samesite_lax()),
has_samesite_strict(c.samesite_strict()),
has_expires(c.expires_defined()),
has_max_age(c.max_age_defined()),
expires(c.expires()),
@@ -764,4 +772,10 @@ long long cppcms_capi_cookie_expires(cppcms_capi_cookie const *cookie) { return

int cppcms_capi_cookie_is_secure(cppcms_capi_cookie const *cookie) { return cookie ? cookie->secure: -1; }

int cppcms_capi_cookie_is_httponly(cppcms_capi_cookie const *cookie) { return cookie ? cookie->httponly: -1; }

int cppcms_capi_cookie_samesite_none_defined(cppcms_capi_cookie const *cookie) { return cookie ? cookie->has_samesite_none: -1; }
int cppcms_capi_cookie_samesite_lax_defined(cppcms_capi_cookie const *cookie) { return cookie ? cookie->has_samesite_lax: -1; }
int cppcms_capi_cookie_samesite_strict_defined(cppcms_capi_cookie const *cookie) { return cookie ? cookie->has_samesite_strict: -1; }

} // extern "C"

+ 63
- 6
src/http_cookie.cpp View File

@@ -78,6 +78,46 @@ void cookie::browser_age()
bool cookie::secure() const { return secure_; }
void cookie::secure(bool secure) { secure_ = secure ? 1: 0; }

bool cookie::httponly() const { return httponly_; }
void cookie::httponly(bool httponly) { httponly_ = httponly ? 1 : 0; }

bool cookie::samesite_none() const { return samesite_none_; }
bool cookie::samesite_lax() const { return samesite_lax_; }
bool cookie::samesite_strict() const { return samesite_strict_; }

void cookie::samesite_none(bool v)
{
if (v) {
samesite_none_ = 1;
samesite_lax_ = 0;
samesite_strict_ = 0;
} else {
samesite_none_ = 0;
}
}

void cookie::samesite_lax(bool v)
{
if (v) {
samesite_none_ = 0;
samesite_lax_ = 1;
samesite_strict_ = 0;
} else {
samesite_lax_ = 0;
}
}

void cookie::samesite_strict(bool v)
{
if (v) {
samesite_none_ = 0;
samesite_lax_ = 0;
samesite_strict_ = 1;
} else {
samesite_strict_ = 0;
}
}

void cookie::write(std::ostream &out) const
{
if(name_.empty())
@@ -117,6 +157,15 @@ void cookie::write(std::ostream &out) const
out<<"; Path="<<path_;
if(secure_)
out<<"; Secure";
if(httponly_)
out<<"; HttpOnly";
// The samesite_*_ setters guarantee that only one of the following is set.
if(samesite_none_)
out<<"; SameSite=None";
if(samesite_lax_)
out<<"; SameSite=Lax";
if(samesite_strict_)
out<<"; SameSite=Strict";
out<<"; Version=1";
}

@@ -127,21 +176,21 @@ std::ostream &operator<<(std::ostream &out,cookie const &c)
}

cookie::cookie(std::string name,std::string value) :
name_(name), value_(value), secure_(0), has_age_(0), has_expiration_(0)
name_(name), value_(value), secure_(0), has_age_(0), has_expiration_(0), httponly_(0), samesite_none_(0), samesite_lax_(0), samesite_strict_(0)
{
}

cookie::cookie(std::string name,std::string value,unsigned age) :
name_(name), value_(value), max_age_(age), secure_(0), has_age_(1), has_expiration_(0)
name_(name), value_(value), max_age_(age), secure_(0), has_age_(1), has_expiration_(0), httponly_(0), samesite_none_(0), samesite_lax_(0), samesite_strict_(0)
{
}
cookie::cookie(std::string name,std::string value,unsigned age,std::string path,std::string domain,std::string comment) :
name_(name), value_(value), path_(path),domain_(domain),comment_(comment),max_age_(age), secure_(0), has_age_(1), has_expiration_(0)
name_(name), value_(value), path_(path),domain_(domain),comment_(comment),max_age_(age), secure_(0), has_age_(1), has_expiration_(0), httponly_(0), samesite_none_(0), samesite_lax_(0), samesite_strict_(0)
{
}

cookie::cookie(std::string name,std::string value,std::string path,std::string domain,std::string comment) :
name_(name), value_(value), path_(path),domain_(domain),comment_(comment), secure_(0), has_age_(0), has_expiration_(0)
name_(name), value_(value), path_(path),domain_(domain),comment_(comment), secure_(0), has_age_(0), has_expiration_(0), httponly_(0), samesite_none_(0), samesite_lax_(0), samesite_strict_(0)
{
}

@@ -155,7 +204,11 @@ cookie::cookie(cookie const &other) :
max_age_(other.max_age_),
secure_(other.secure_),
has_age_(other.has_age_),
has_expiration_(other.has_expiration_)
has_expiration_(other.has_expiration_),
httponly_(other.httponly_),
samesite_none_(other.samesite_none_),
samesite_lax_(other.samesite_lax_),
samesite_strict_(other.samesite_strict_)
{
}

@@ -171,10 +224,14 @@ cookie const &cookie::operator=(cookie const &other)
secure_=other.secure_;
has_age_=other.has_age_;
has_expiration_ = other.has_expiration_;
httponly_ = other.httponly_;
samesite_none_ = other.samesite_none_;
samesite_lax_ = other.samesite_lax_;
samesite_strict_ = other.samesite_strict_;
return *this;
}

cookie::cookie() : secure_(0), has_age_(0), has_expiration_(0) {}
cookie::cookie() : secure_(0), has_age_(0), has_expiration_(0), httponly_(0), samesite_none_(0), samesite_lax_(0), samesite_strict_(0) {}
cookie::~cookie() {}




+ 8
- 1
src/session_interface.cpp View File

@@ -481,6 +481,10 @@ void session_interface::set_session_cookie(int64_t age,std::string const &data,s
bool use_exp = cached_settings().session.cookies.use_exp;

bool secure = cached_settings().session.cookies.secure;
bool httponly = cached_settings().session.cookies.httponly;
bool use_samesite_none = cached_settings().session.cookies.use_samesite_none;
bool use_samesite_lax = cached_settings().session.cookies.use_samesite_lax;
bool use_samesite_strict = cached_settings().session.cookies.use_samesite_strict;

http::cookie the_cookie(cookie_name,util::urlencode(data),path,domain);

@@ -501,8 +505,11 @@ void session_interface::set_session_cookie(int64_t age,std::string const &data,s
}
}


the_cookie.secure(secure);
the_cookie.httponly(httponly);
the_cookie.samesite_none(use_samesite_none);
the_cookie.samesite_lax(use_samesite_lax);
the_cookie.samesite_strict(use_samesite_strict);
if(d->adapter)
d->adapter->set_cookie(the_cookie);


+ 12
- 2
src/urandom.cpp View File

@@ -80,6 +80,7 @@ namespace cppcms {
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

@@ -108,11 +109,20 @@ namespace cppcms {
int fd = open("/dev/urandom",O_RDONLY);
if(!fd)
throw cppcms_error("Failed to open /dev/urandom");
n = read(fd,ptr,len);
while(len > 0) {
n = read(fd,ptr,len);
if(n < 0 && errno == EINTR)
continue;
if(n <= 0)
break;
ptr = static_cast<char *>(ptr) + n;
len -= n;
}
close(fd);
}
if(n!=int(len))
if(len > 0) {
throw cppcms_error("Failed to read /dev/urandom");
}
}
}



+ 31
- 0
tests/cookie_test.cpp View File

@@ -44,6 +44,37 @@ void basic_test()
TEST(ss.str()=="Set-Cookie:a=b; Version=1");
}
{
c.httponly(true);
std::ostringstream ss;
ss << c;
TEST(ss.str()=="Set-Cookie:a=b; HttpOnly; Version=1");
}
{
c.samesite_none(true);
std::ostringstream ss;
ss << c;
TEST(ss.str()=="Set-Cookie:a=b; HttpOnly; SameSite=None; Version=1");
}
{
c.samesite_lax(true);
std::ostringstream ss;
ss << c;
TEST(ss.str()=="Set-Cookie:a=b; HttpOnly; SameSite=Lax; Version=1");
}
{
c.samesite_strict(true);
std::ostringstream ss;
ss << c;
TEST(ss.str()=="Set-Cookie:a=b; HttpOnly; SameSite=Strict; Version=1");
}
{
c.httponly(false);
c.samesite_strict(false);
std::ostringstream ss;
ss << c;
TEST(ss.str()=="Set-Cookie:a=b; Version=1");
}
{
c.max_age(10);
std::ostringstream ss;
ss << c;


Loading…
Cancel
Save