Commit 10bee717 authored by ale's avatar ale

various fixes to mod_sso

parent 6d738803
......@@ -5,10 +5,12 @@ SUBDIRS = . test
noinst_LTLIBRARIES = libmod_sso.la
noinst_DATA = mod_sso.la
libmod_sso_la_SOURCES = mod_sso.cc mod_sso.h sso_utils.cc
SSO_LIBS = $(top_builddir)/src/sso/libsso.la
libmod_sso_la_SOURCES = mod_sso.c mod_sso.h sso_utils.c
libmod_sso_la_CPPFLAGS = $(APACHE_CFLAGS) $(AM_CPPFLAGS)
#libmod_sso_la_LDFLAGS = -module
#libmod_sso_la_LIBADD = $(SSO_LIBS) $(NACL_LIBS)
libmod_sso_la_LDFLAGS = -module
libmod_sso_la_LIBADD = $(SSO_LIBS)
install-exec-local:
$(INSTALL) -D -o 0 -g 0 -m 644 $(builddir)/.libs/mod_sso.so \
......@@ -18,6 +20,6 @@ install-exec-local:
mod_sso.la: libmod_sso.la
$(APXS) -c -o $@ $< $(AM_LDFLAGS) $(APACHE_CFLAGS) \
$(SSO_LIBS) $(NACL_LIBS) -lstdc++
$(SSO_LIBS)
......@@ -22,11 +22,9 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string>
#include <vector>
#include <map>
#include <sso/sso.h>
#include "ap_config.h"
#include "apr_strings.h"
/* overwrite package vars set by apache */
#undef PACKAGE_BUGREPORT
......@@ -38,26 +36,26 @@
struct request_rec;
using std::string;
using std::map;
using std::vector;
namespace modsso {
struct modsso_params {
char *t;
char *d;
};
typedef map<string, string> params_t;
typedef struct modsso_params *modsso_params_t;
// sso_utils.cc
void debug(const string& s);
string url_decode(const string& str);
string url_encode(const string& str);
params_t parse_query_string(const string& str);
void make_cookie_value(string& cookie_value, const string& name,
const string& session_id, const string& path,
int cookie_lifespan);
void set_cookie(request_rec *r, const string& cookie_name,
const string& value, const string& path);
void del_cookie(request_rec *r, const string& cookie_name);
vector<string> explode(string s, string e);
} // namespace
void debug(const char *s);
char *modsso_url_decode(apr_pool_t *p, const char *str);
char *modsso_url_encode(apr_pool_t *p, const char *str);
//char *modsso_url_encode(const char *str);
int modsso_parse_query_string(apr_pool_t *p,
const char *str,
modsso_params_t params);
void modsso_set_cookie(request_rec *r, const char *cookie_name,
const char *value, const char *path);
void modsso_del_cookie(request_rec *r, const char *cookie_name);
......@@ -22,8 +22,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
/* $Id$ */
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
......@@ -33,27 +31,25 @@
#include "http_main.h"
#include "ap_config.h"
#include "mod_sso.h"
#include <ctype.h>
namespace modsso {
using std::string;
void debug(const string& s) {
void debug(const char *s) {
#ifdef DEBUG
fprintf(stderr, "%s\n", s.c_str());
fprintf(stderr, "%s\n", s);
#endif
}
// ugly implementation of url decoding
string url_decode(const string& str) {
string out;
// Ugly implementation of url decoding. Returns a newly allocated
// string (using malloc).
char *modsso_url_decode(apr_pool_t *p, const char *i) {
char *o, *output = (char *)apr_palloc(p, 1 + strlen(i));
char state = 'N';
char buf[3], obuf[2];
for (string::const_iterator i = str.begin(); i != str.end(); i++) {
for (o = output; *i; i++) {
switch(state) {
case 'N':
if (*i == '%') state = 1;
else out += *i;
else *o++ = *i;
break;
case 1:
{
......@@ -62,8 +58,8 @@ string url_decode(const string& str) {
if ((c >= 'a' && c <= 'f') || (c >= '0' && c <= '9')) {
state = 2;
} else {
out += "%";
out += *i;
*o++ = '%';
*o++ = *i;
state = 'N';
}
break;
......@@ -77,11 +73,11 @@ string url_decode(const string& str) {
obuf[0] = strtol(buf, 0, 16);
obuf[1] = 0;
if (obuf[0])
out += obuf;
*o++ = obuf[0];
} else {
out += "%";
out += buf[0];
out += *i;
*o++ = '%';
*o++ = buf[0];
*o++ = *i;
}
state = 'N';
break;
......@@ -89,92 +85,116 @@ string url_decode(const string& str) {
}
}
if (state != 'N') {
out += buf[0];
*o++ = buf[0];
if (state > 1)
out += buf[1];
*o++ = buf[1];
}
return out;
*o = '\0';
return output;
}
// ugly implementation of url encoding
string url_encode(const string& str) {
char *modsso_url_encode(apr_pool_t *p, const char *s) {
static const char *hex = "0123456789ABCDEF";
string out;
for (string::const_iterator i = str.begin(); i != str.end(); i++) {
unsigned char c = *i;
char *out = (char *)apr_palloc(p, strlen(s) * 3 + 1), *optr;
for (optr = out; *s; s++) {
unsigned char c = *s;
if (!isalnum(c) && (c != '.') && (c != '-') && (c != '_')) {
out += "%";
out += hex[(c & 0xf0) >> 4];
out += hex[c & 0x0f];
*optr++ = '%';
*optr++ = hex[(c & 0xf0) >> 4];
*optr++ = hex[c & 0x0f];
} else {
out += c;
*optr++ = c;
}
}
*optr = '\0';
return out;
}
params_t parse_query_string(const string& str) {
params_t p;
if(str.size() == 0) return p;
vector<string> pairs = explode(str, "&");
for (unsigned int i=0; i < pairs.size(); i++) {
string::size_type loc = pairs[i].find( "=", 0 );
// if loc found and loc isn't last char in string
if (loc != string::npos && loc != str.size()-1) {
string key = url_decode(pairs[i].substr(0, loc));
string value = url_decode(pairs[i].substr(loc+1));
p[key] = value;
int modsso_parse_query_string(apr_pool_t *p, const char *str, modsso_params_t params) {
char *tmp = apr_pstrdup(p, str), *strptr = NULL;
params->d = NULL;
params->t = NULL;
if (str == NULL) {
return 0;
}
while (1) {
char *token, *value, *sep;
token = strtok_r(tmp, "&", &strptr);
if (token == NULL) {
break;
}
tmp = NULL;
token = modsso_url_decode(p, token);
sep = strchr(token, '=');
if (sep == NULL) {
continue;
}
*sep++ = '\0';
value = sep;
if (!strcmp(token, "d")) {
params->d = value;
} else if (!strcmp(token, "t")) {
params->t = value;
}
}
return p;
if (!params->d || !params->d[0]
|| !params->t || !params->t[0]) {
return -1;
}
return 0;
}
void make_cookie_value(string& cookie_value, const string& name,
const string& session_id, const string& path,
int cookie_lifespan) {
static char *make_cookie_value(request_rec *r,
const char *name,
const char *session_id,
const char *path,
int cookie_lifespan)
{
size_t sz = 1024;
char *cookie_value = (char *)apr_palloc(r->pool, sz);
if (cookie_lifespan == 0) {
cookie_value = name + "=" + session_id + "; path=" + path + "; secure;";
snprintf(cookie_value, sz,
"%s=%s; path=%s; secure; httpOnly;",
name, session_id, path);
} else {
char expires[200];
time_t t;
t = time(NULL) + cookie_lifespan;
struct tm *tmp;
t = time(NULL) + cookie_lifespan;
tmp = gmtime(&t);
char expires[200];
strftime(expires, sizeof(expires), "%a, %d-%b-%Y %H:%M:%S GMT", tmp);
cookie_value = name + "=" + session_id + "; expires=" + string(expires) + "; Path=" + path + "; secure; httpOnly;";
snprintf(cookie_value, sz,
"%s=%s; expires=%s; path=%s; secure; httpOnly;",
name, session_id, expires, path);
}
return cookie_value;
}
void set_cookie(request_rec *r, const std::string& cookie_name,
const std::string& value, const std::string& path)
void modsso_set_cookie(request_rec *r, const char *cookie_name,
const char *value, const char *path)
{
std::string cookie_value;
make_cookie_value(cookie_value, cookie_name, value, path, 0);
char *cookie_value;
cookie_value = make_cookie_value(r, cookie_name, value, path, 0);
apr_table_setn(r->err_headers_out, "Set-Cookie",
apr_pstrdup(r->pool, cookie_value.c_str()));
apr_pstrdup(r->pool, cookie_value));
}
void del_cookie(request_rec *r, const std::string& cookie_name) {
std::string cookie_value;
cookie_value = cookie_name + "=; expires=Mar, 01-01-1971 00:00:00 GMT";
void modsso_del_cookie(request_rec *r, const char *cookie_name)
{
char cookie_value[512];
sprintf(cookie_value, "%s=; expires=Mar, 01-01-1971 00:00:00 GMT",
cookie_name);
apr_table_setn(r->err_headers_out, "Set-Cookie",
apr_pstrdup(r->pool, cookie_value.c_str()));
apr_pstrdup(r->pool, cookie_value));
}
vector<string> explode(string s, string e) {
vector<string> ret;
int iPos = s.find(e, 0);
int iPit = e.length();
while (iPos>-1) {
if (iPos!=0)
ret.push_back(s.substr(0,iPos));
s.erase(0,iPos+iPit);
iPos = s.find(e, 0);
}
if (s!="")
ret.push_back(s);
return ret;
}
} // namespace modsso
......@@ -6,9 +6,9 @@ check_PROGRAMS = \
EXTRA_DIST = httpd_integration_test.py
TESTS = $(check_PROGRAMS)
AM_CPPFLAGS += $(GTEST_CPPFLAGS)
AM_CPPFLAGS += $(APACHE_CFLAGS) $(GTEST_CPPFLAGS)
AM_LDFLAGS += $(GTEST_LDFLAGS)
LDADD += $(builddir)/../libmod_sso.la $(GTEST_LIBS) $(APR_LIBS) -laprutil-1
LDADD = $(builddir)/../libmod_sso.la $(GTEST_LIBS) $(APR_LIBS) -laprutil-1
sso_utils_unittest_SOURCES = sso_utils_unittest.cc
......
......@@ -17,6 +17,8 @@ for exe in (APACHE_BIN, APXS_BIN):
if not os.path.exists(exe):
raise Exception('%s not found, this test cannot run' % exe)
devnull = open(os.devnull)
def _start_httpd(public_key):
with open('public.key', 'w') as fd:
......@@ -24,21 +26,36 @@ def _start_httpd(public_key):
env = dict(os.environ)
env['TESTROOT'] = os.getcwd()
env['MODULEDIR'] = subprocess.check_output(
[APXS_BIN, '-q', 'LIBEXECDIR']).strip()
[APXS_BIN, '-q', 'LIBEXECDIR'], stderr=devnull).strip()
cmd = [APACHE_BIN, "-f", os.path.join(os.getcwd(), "test-httpd.conf"), "-X"]
if os.getenv('STRACE'):
cmd = ['strace', '-s', '256', '-f'] + cmd
httpd = subprocess.Popen(cmd, env=env)
print 'httpd pid:', httpd.pid
time.sleep(1)
if httpd.poll():
raise Exception('httpd failed to start!')
return httpd
def _stop_httpd(httpd):
os.kill(httpd.pid, 15)
httpd.terminate()
time.sleep(1)
try:
os.kill(httpd.pid, 9)
httpd.kill()
except OSError:
pass
status = httpd.wait()
if os.WIFEXITED(status):
print 'httpd exited with status %d' % os.WEXITSTATUS(status)
elif os.WIFSIGNALED(status):
print 'httpd exited due to signal %d' % os.WTERMSIG(status)
else:
print 'httpd exited for unknown reason (returncode=%d)' % status
try:
os.remove("test-httpd.pid")
except OSError:
......@@ -112,9 +129,7 @@ class HttpdIntegrationTest(unittest.TestCase):
for i in xrange(n):
cookie = 'SSO_test=%s' % self._ticket()
status, body, location = _query("/index.html", cookie=cookie)
if status != 200:
errors += 1
self.assertEquals(0, errors)
self.assertEquals(200, status)
def testRedirectionUrls(self):
......@@ -238,7 +253,6 @@ class HttpdIntegrationTest(unittest.TestCase):
conn.close()
if __name__ == "__main__":
unittest.main()
......@@ -2,7 +2,10 @@
#include <stdlib.h>
#include <gtest/gtest.h>
#include <string>
extern "C" {
#include "../mod_sso.h"
}
using std::string;
......@@ -12,50 +15,53 @@ class SSOUtilsTest : public testing::Test {
protected:
virtual void SetUp() {
apr_pool_create(&pool_, NULL);
}
apr_pool_t *pool_;
};
TEST_F(SSOUtilsTest, UrlDecode) {
string sample("%76%61%6Cue"), reference("value");
string result = modsso::url_decode(sample);
string result = modsso_url_decode(pool_, sample.c_str());
EXPECT_EQ(reference, result);
string bad_input("%%%%%%%%%");
result = modsso::url_decode(bad_input);
result = modsso_url_decode(pool_, bad_input.c_str());
EXPECT_EQ(bad_input, result);
bad_input = "%az%AZ%Z%Z";
result = modsso::url_decode(bad_input);
result = modsso_url_decode(pool_, bad_input.c_str());
EXPECT_EQ(bad_input, result);
}
TEST_F(SSOUtilsTest, UrlEncode) {
string sample("http://example.com"),
reference("http%3A%2F%2Fexample.com");
string result = modsso::url_encode(sample);
string result = modsso_url_encode(pool_, sample.c_str());
EXPECT_EQ(reference, result);
}
TEST_F(SSOUtilsTest, ParseQueryString) {
modsso::params_t parms;
parms = modsso::parse_query_string("key1=val1&key%32=%76%61%6C2");
ASSERT_EQ("val1", parms["key1"]);
ASSERT_EQ("val2", parms["key2"]) << "URL-decoding failed";
parms = modsso::parse_query_string("key3=");
ASSERT_EQ(string(), parms["key3"]);
modsso_params parms;
ASSERT_EQ(0, modsso_parse_query_string(pool_, "t=val1&d=%76%61%6C2", &parms));
EXPECT_EQ("val1", string(parms.t));
EXPECT_EQ("val2", string(parms.d)) << "URL-decoding failed";
ASSERT_EQ(-1, modsso_parse_query_string(pool_, "key3=", &parms));
}
TEST_F(SSOUtilsTest, MakeCookieValue) {
string cookie;
modsso::make_cookie_value(cookie, "COOKIE", "value", "/", 0);
ASSERT_EQ("COOKIE=value; path=/; secure;", cookie);
}
//TEST_F(SSOUtilsTest, MakeCookieValue) {
// string cookie;
// modsso::make_cookie_value(cookie, "COOKIE", "value", "/", 0);
// ASSERT_EQ("COOKIE=value; path=/; secure;", cookie);
//}
} // namespace
int main(int argc, char **argv) {
//apr_app_initialize(&argc, &argv, NULL);
apr_initialize();
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment