Skip to content

Commit 71b7c29

Browse files
committed
add unit tests for Apache Require claim authz functions
Signed-off-by: Hans Zandbelt <hans.zandbelt@zmartzone.eu>
1 parent af8c65d commit 71b7c29

File tree

7 files changed

+310
-4
lines changed

7 files changed

+310
-4
lines changed

.cproject

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
</extensions>
1919
</storageModule>
2020
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
21-
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.linuxtools.cdt.autotools.core.buildArtefactType.autotools" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.linuxtools.cdt.autotools.core.buildArtefactType.autotools,org.eclipse.cdt.build.core.buildType=org.eclipse.linuxtools.cdt.autotools.core.buildType.default" cleanCommand="rm -rf" description="" errorParsers="org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="org.eclipse.linuxtools.cdt.autotools.core.configuration.build.1562680719" name="Build (GNU)" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.connection=unix:///var/run/docker.sock,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=" parent="org.eclipse.linuxtools.cdt.autotools.core.configuration.build">
21+
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.linuxtools.cdt.autotools.core.buildArtefactType.autotools" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.linuxtools.cdt.autotools.core.buildArtefactType.autotools,org.eclipse.cdt.build.core.buildType=org.eclipse.linuxtools.cdt.autotools.core.buildType.default" cleanCommand="rm -rf" description="" errorParsers="org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="org.eclipse.linuxtools.cdt.autotools.core.configuration.build.1562680719" name="Build (GNU)" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.connection=unix:///var/run/docker.sock" parent="org.eclipse.linuxtools.cdt.autotools.core.configuration.build">
2222
<folderInfo id="org.eclipse.linuxtools.cdt.autotools.core.configuration.build.1562680719." name="/" resourcePath="">
2323
<toolChain id="org.eclipse.linuxtools.cdt.autotools.core.toolChain.617277945" name="GNU Autotools Toolchain" superClass="org.eclipse.linuxtools.cdt.autotools.core.toolChain">
2424
<targetPlatform id="org.eclipse.linuxtools.cdt.autotools.core.toolchain.targetPlatform.359991688" isAbstract="false" name="GNU Autotools Target Platform" superClass="org.eclipse.linuxtools.cdt.autotools.core.toolchain.targetPlatform"/>

Makefile.am

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ check_liboauth2_LDADD = liboauth2.la
157157
if HAVE_APACHE
158158
check_liboauth2_CPPFLAGS += $(liboauth2_apache_la_CPPFLAGS)
159159
check_liboauth2_CFLAGS += $(liboauth2_apache_la_CFLAGS)
160-
check_liboauth2_LDADD += liboauth2_apache.la
160+
check_liboauth2_LDADD += liboauth2_apache.la ${liboauth2_apache_la_LIBADD}
161161
endif
162162
if HAVE_NGINX
163163
check_liboauth2_CPPFLAGS += $(liboauth2_nginx_la_CPPFLAGS)
@@ -181,6 +181,10 @@ check_liboauth2_SOURCES = \
181181
test/check_oauth2.c \
182182
test/check_openidc.c \
183183
test/server_stubs.c
184+
if HAVE_APACHE
185+
check_liboauth2_SOURCES += \
186+
test/check_apache.c
187+
endif
184188

185189
endif
186190

src/server/apache.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,15 +876,17 @@ bool oauth2_apache_authz_match_claim(oauth2_apache_request_ctx_t *ctx,
876876
return true;
877877

878878
/* a tilde denotes a string PCRE match */
879-
// } else if (!(*attr_c) && (*spec_c)
879+
// } else if (!(*attr_c) &&
880+
//(*spec_c)
880881
//== '~') {
881882
//
882883
// /* skip the tilde */
883884
// spec_c++;
884885
//
885886
// if
886887
//(oauth2_authz_match_expression(r, spec_c, val) ==
887-
//TRUE) return true;
888+
// TRUE) return
889+
// true;
888890
/* dot means child nodes must be evaluated */
889891
} else if (!(*attr_c) && (*spec_c) == '.') {
890892

test/check_apache.c

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/***************************************************************************
2+
*
3+
* Copyright (C) 2018-2019 - ZmartZone Holding BV - www.zmartzone.eu
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as
7+
* published by the Free Software Foundation, either version 3 of the
8+
* License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
* @Author: Hans Zandbelt - hans.zandbelt@zmartzone.eu
19+
*
20+
**************************************************************************/
21+
22+
#include "check_liboauth2.h"
23+
#include "oauth2/apache.h"
24+
#include <check.h>
25+
26+
static apr_pool_t *pool = NULL;
27+
static request_rec *request = NULL;
28+
static oauth2_log_t *log = 0;
29+
30+
static request_rec *setup_request(apr_pool_t *pool)
31+
{
32+
// const unsigned int kIdx = 0;
33+
// const unsigned int kEls = kIdx + 1;
34+
request_rec *request =
35+
(request_rec *)apr_pcalloc(pool, sizeof(request_rec));
36+
37+
request->pool = pool;
38+
39+
request->headers_in = apr_table_make(request->pool, 0);
40+
request->headers_out = apr_table_make(request->pool, 0);
41+
request->err_headers_out = apr_table_make(request->pool, 0);
42+
43+
apr_table_set(request->headers_in, "Host", "www.example.com");
44+
apr_table_set(request->headers_in, "OIDC_foo", "some-value");
45+
apr_table_set(request->headers_in, "Cookie",
46+
"foo=bar; "
47+
"oauth2_openidc_session"
48+
"=0123456789abcdef; baz=zot");
49+
50+
request->server = apr_pcalloc(request->pool, sizeof(struct server_rec));
51+
request->server->process =
52+
apr_pcalloc(request->pool, sizeof(struct process_rec));
53+
request->server->process->pool = request->pool;
54+
request->connection =
55+
apr_pcalloc(request->pool, sizeof(struct conn_rec));
56+
request->connection->bucket_alloc =
57+
apr_bucket_alloc_create(request->pool);
58+
request->connection->local_addr =
59+
apr_pcalloc(request->pool, sizeof(apr_sockaddr_t));
60+
61+
apr_pool_userdata_set("https", "scheme", NULL, request->pool);
62+
request->server->server_hostname = "www.example.com";
63+
request->connection->local_addr->port = 443;
64+
request->unparsed_uri = "/bla?foo=bar&param1=value1";
65+
request->args = "foo=bar&param1=value1";
66+
apr_uri_parse(request->pool,
67+
"https://www.example.com/bla?foo=bar&param1=value1",
68+
&request->parsed_uri);
69+
/*
70+
auth_openidc_module.module_index = kIdx;
71+
oidc_cfg *cfg = oidc_create_server_config(request->pool,
72+
request->server); cfg->provider.issuer = "https://idp.example.com";
73+
cfg->provider.authorization_endpoint_url =
74+
"https://idp.example.com/authorize";
75+
cfg->provider.scope = "openid";
76+
cfg->provider.client_id = "client_id";
77+
cfg->provider.token_binding_policy =
78+
OIDC_TOKEN_BINDING_POLICY_OPTIONAL; cfg->redirect_uri =
79+
"https://www.example.com/protected/";
80+
81+
oidc_dir_cfg *d_cfg = oidc_create_dir_config(request->pool,
82+
NULL);
83+
*/
84+
/*
85+
request->server->module_config = apr_pcalloc(request->pool,
86+
sizeof(ap_conf_vector_t *) * kEls);
87+
request->per_dir_config = apr_pcalloc(request->pool,
88+
sizeof(ap_conf_vector_t *) * kEls);
89+
*/
90+
/*
91+
ap_set_module_config(request->server->module_config,
92+
&auth_openidc_module, cfg);
93+
ap_set_module_config(request->per_dir_config,
94+
&auth_openidc_module, d_cfg);
95+
96+
cfg->crypto_passphrase = "12345678901234567890123456789012";
97+
cfg->cache = &oidc_cache_shm;
98+
cfg->cache_cfg = NULL;
99+
cfg->cache_shm_size_max = 500;
100+
cfg->cache_shm_entry_size_max = 16384 + 255 + 17;
101+
cfg->cache_encrypt = 1;
102+
if (cfg->cache->post_config(request->server) != OK) {
103+
printf("cfg->cache->post_config failed!\n");
104+
exit(-1);
105+
}
106+
*/
107+
return request;
108+
}
109+
110+
static void check_apache_log_request(oauth2_log_sink_t *sink,
111+
const char *filename, unsigned long line,
112+
const char *function,
113+
oauth2_log_level_t level, const char *msg)
114+
{
115+
oauth2_log(log, filename, line, function, level, "%s", msg);
116+
}
117+
118+
static void setup(void)
119+
{
120+
log = oauth2_init(OAUTH2_LOG_TRACE1, 0);
121+
122+
apr_initialize();
123+
apr_pool_create(&pool, NULL);
124+
request = setup_request(pool);
125+
}
126+
127+
static void teardown(void)
128+
{
129+
apr_pool_destroy(pool);
130+
apr_terminate();
131+
132+
oauth2_shutdown(log);
133+
}
134+
135+
START_TEST(test_apache_request_state)
136+
{
137+
json_error_t err;
138+
const char *s_claims = "{ \"sub\": \"joe\" }";
139+
json_t *in_claims = NULL, *out_claims = NULL;
140+
const char *key = "C";
141+
char *value = NULL;
142+
oauth2_apache_request_ctx_t *ctx = NULL;
143+
144+
ctx = oauth2_apache_request_context(request, check_apache_log_request,
145+
"check_apache");
146+
in_claims = json_loads(s_claims, 0, &err);
147+
148+
oauth2_apache_request_state_set_json(ctx, key, in_claims);
149+
150+
oauth2_apache_request_state_get_json(ctx, key, &out_claims);
151+
ck_assert_ptr_ne(out_claims, NULL);
152+
153+
oauth2_json_string_get(log, out_claims, "sub", &value, NULL);
154+
ck_assert_ptr_ne(value, NULL);
155+
ck_assert_str_eq(value, "joe");
156+
157+
json_decref(in_claims);
158+
json_decref(out_claims);
159+
}
160+
END_TEST
161+
162+
START_TEST(test_apache_authz_match_claim)
163+
{
164+
json_error_t err;
165+
oauth2_apache_request_ctx_t *ctx = NULL;
166+
const char *s_claims = "{ \"sub\": \"joe\" }";
167+
json_t *claims = NULL;
168+
bool rc = false;
169+
170+
ctx = oauth2_apache_request_context(request, check_apache_log_request,
171+
"check_apache");
172+
claims = json_loads(s_claims, 0, &err);
173+
174+
rc = oauth2_apache_authz_match_claim(ctx, "sub:joe", claims);
175+
ck_assert_int_eq(rc, true);
176+
177+
rc = oauth2_apache_authz_match_claim(ctx, "sub:hans", claims);
178+
ck_assert_int_eq(rc, false);
179+
180+
json_decref(claims);
181+
}
182+
END_TEST
183+
184+
START_TEST(test_apache_authorize)
185+
{
186+
json_error_t err;
187+
oauth2_apache_request_ctx_t *ctx = NULL;
188+
const char *s_claims = "{ \"sub\": \"joe\" }";
189+
json_t *claims = NULL;
190+
authz_status rc = AUTHZ_DENIED;
191+
192+
ctx = oauth2_apache_request_context(request, check_apache_log_request,
193+
"check_apache");
194+
claims = json_loads(s_claims, 0, &err);
195+
196+
rc = oauth2_apache_authorize(ctx, claims, "sub:hans",
197+
oauth2_apache_authz_match_claim);
198+
ck_assert_int_eq(rc, AUTHZ_DENIED_NO_USER);
199+
200+
request->user = "joe";
201+
rc = oauth2_apache_authorize(ctx, claims, "sub:hans",
202+
oauth2_apache_authz_match_claim);
203+
ck_assert_int_eq(rc, AUTHZ_DENIED);
204+
205+
rc = oauth2_apache_authorize(ctx, claims, "sub:joe",
206+
oauth2_apache_authz_match_claim);
207+
ck_assert_int_eq(rc, AUTHZ_GRANTED);
208+
209+
json_decref(claims);
210+
}
211+
END_TEST
212+
213+
Suite *oauth2_check_apache_suite()
214+
{
215+
Suite *s = suite_create("apache");
216+
TCase *c = tcase_create("core");
217+
218+
tcase_add_checked_fixture(c, setup, teardown);
219+
220+
tcase_add_test(c, test_apache_request_state);
221+
tcase_add_test(c, test_apache_authz_match_claim);
222+
tcase_add_test(c, test_apache_authorize);
223+
224+
suite_add_tcase(s, c);
225+
226+
return s;
227+
}

test/check_liboauth2.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ int main(void)
292292
srunner_add_suite(sr, oauth2_check_proto_suite());
293293
srunner_add_suite(sr, oauth2_check_oauth2_suite());
294294
srunner_add_suite(sr, oauth2_check_openidc_suite());
295+
srunner_add_suite(sr, oauth2_check_apache_suite());
295296

296297
// srunner_run_all(sr, CK_ENV);
297298
srunner_run_all(sr, CK_VERBOSE);

test/check_liboauth2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Suite *oauth2_check_http_suite();
4040
Suite *oauth2_check_proto_suite();
4141
Suite *oauth2_check_oauth2_suite();
4242
Suite *oauth2_check_openidc_suite();
43+
Suite *oauth2_check_apache_suite();
4344

4445
char *oauth2_check_http_serve(const char *request);
4546
char *oauth2_check_jose_serve(const char *request);

test/server_stubs.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,77 @@
11
#ifdef HAVE_APACHE
2+
#include <apr_lib.h>
23
#include <oauth2/apache.h>
34

5+
static char *substring_conf(apr_pool_t *p, const char *start, int len,
6+
char quote)
7+
{
8+
char *result = apr_palloc(p, len + 1);
9+
char *resp = result;
10+
int i;
11+
12+
for (i = 0; i < len; ++i) {
13+
if (start[i] == '\\' &&
14+
(start[i + 1] == '\\' || (quote && start[i + 1] == quote)))
15+
*resp++ = start[++i];
16+
else
17+
*resp++ = start[i];
18+
}
19+
20+
*resp++ = '\0';
21+
#if RESOLVE_ENV_PER_TOKEN
22+
return (char *)ap_resolve_env(p, result);
23+
#else
24+
return result;
25+
#endif
26+
}
27+
28+
AP_DECLARE(char *) ap_getword_conf(apr_pool_t *p, const char **line)
29+
{
30+
const char *str = *line, *strend;
31+
char *res;
32+
char quote;
33+
34+
while (apr_isspace(*str))
35+
++str;
36+
37+
if (!*str) {
38+
*line = str;
39+
return "";
40+
}
41+
42+
if ((quote = *str) == '"' || quote == '\'') {
43+
strend = str + 1;
44+
while (*strend && *strend != quote) {
45+
if (*strend == '\\' && strend[1] &&
46+
(strend[1] == quote || strend[1] == '\\')) {
47+
strend += 2;
48+
} else {
49+
++strend;
50+
}
51+
}
52+
res = substring_conf(p, str + 1, strend - str - 1, quote);
53+
54+
if (*strend == quote)
55+
++strend;
56+
} else {
57+
strend = str;
58+
while (*strend && !apr_isspace(*strend))
59+
++strend;
60+
61+
res = substring_conf(p, str, strend - str, 0);
62+
}
63+
64+
while (apr_isspace(*strend))
65+
++strend;
66+
*line = strend;
67+
return res;
68+
}
69+
70+
AP_DECLARE(char *) ap_getword_conf_nc(apr_pool_t *p, char **line)
71+
{
72+
return ap_getword_conf(p, (const char **)line);
73+
}
74+
475
AP_DECLARE(int) ap_should_client_block(request_rec *r)
576
{
677
return 0;

0 commit comments

Comments
 (0)