mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-03-11 06:53:54 +00:00
Get HTTP Basic authentication working
Second 'rhizomehttp' test now passes
This commit is contained in:
parent
21fe12859f
commit
2ac1bc3240
@ -352,13 +352,11 @@ static const char * _reserve(struct http_request *r, struct substring str)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static const char * _reserve_str(struct http_request *r, const char *str)
|
static const char * _reserve_str(struct http_request *r, const char *str)
|
||||||
{
|
{
|
||||||
struct substring sub = { .start = str, .end = str + strlen(str) };
|
struct substring sub = { .start = str, .end = str + strlen(str) };
|
||||||
return _reserve(r, sub);
|
return _reserve(r, sub);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int _end_of_content(struct http_request *r)
|
static inline int _end_of_content(struct http_request *r)
|
||||||
{
|
{
|
||||||
@ -744,8 +742,12 @@ static int _parse_authorization(struct http_request *r, struct http_client_autho
|
|||||||
if (_skip_literal(r, "Basic") && _skip_space(r)) {
|
if (_skip_literal(r, "Basic") && _skip_space(r)) {
|
||||||
size_t bufsz = 5 + header_bytes * 3 / 4; // enough for base64 decoding
|
size_t bufsz = 5 + header_bytes * 3 / 4; // enough for base64 decoding
|
||||||
char buf[bufsz];
|
char buf[bufsz];
|
||||||
if (_parse_authorization_credentials_basic(r, &auth->credentials.basic, buf, bufsz) == -1) {
|
if (_parse_authorization_credentials_basic(r, &auth->credentials.basic, buf, bufsz)) {
|
||||||
auth->scheme = BASIC;
|
auth->scheme = BASIC;
|
||||||
|
if ( (auth->credentials.basic.user = _reserve_str(r, auth->credentials.basic.user)) == NULL
|
||||||
|
|| (auth->credentials.basic.password = _reserve_str(r, auth->credentials.basic.password)) == NULL
|
||||||
|
)
|
||||||
|
return 0; // error
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (r->debug_flag && *r->debug_flag)
|
if (r->debug_flag && *r->debug_flag)
|
||||||
@ -1047,6 +1049,7 @@ static int http_request_parse_header(struct http_request *r)
|
|||||||
assert(r->request_header.authorization.scheme != NOAUTH);
|
assert(r->request_header.authorization.scheme != NOAUTH);
|
||||||
r->cursor = nextline;
|
r->cursor = nextline;
|
||||||
_commit(r);
|
_commit(r);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
goto malformed;
|
goto malformed;
|
||||||
}
|
}
|
||||||
@ -1820,8 +1823,10 @@ static const char *httpResultString(int response_code)
|
|||||||
static int _render_response(struct http_request *r)
|
static int _render_response(struct http_request *r)
|
||||||
{
|
{
|
||||||
struct http_response hr = r->response;
|
struct http_response hr = r->response;
|
||||||
assert(hr.result_code >= 200);
|
assert(hr.result_code >= 100);
|
||||||
assert(hr.result_code < 600);
|
assert(hr.result_code < 600);
|
||||||
|
if (hr.result_code == 401)
|
||||||
|
assert(hr.header.www_authenticate.scheme != NOAUTH);
|
||||||
const char *result_string = httpResultString(hr.result_code);
|
const char *result_string = httpResultString(hr.result_code);
|
||||||
strbuf sb = strbuf_local(r->response_buffer, r->response_buffer_size);
|
strbuf sb = strbuf_local(r->response_buffer, r->response_buffer_size);
|
||||||
if (hr.content == NULL && hr.content_generator == NULL) {
|
if (hr.content == NULL && hr.content_generator == NULL) {
|
||||||
@ -1876,6 +1881,7 @@ static int _render_response(struct http_request *r)
|
|||||||
case BASIC: scheme = "Basic"; break;
|
case BASIC: scheme = "Basic"; break;
|
||||||
}
|
}
|
||||||
if (scheme) {
|
if (scheme) {
|
||||||
|
assert(hr.result_code == 401);
|
||||||
strbuf_sprintf(sb, "WWW-Authenticate: %s realm=", scheme);
|
strbuf_sprintf(sb, "WWW-Authenticate: %s realm=", scheme);
|
||||||
strbuf_append_quoted_string(sb, hr.header.www_authenticate.realm);
|
strbuf_append_quoted_string(sb, hr.header.www_authenticate.realm);
|
||||||
strbuf_puts(sb, "\r\n");
|
strbuf_puts(sb, "\r\n");
|
||||||
@ -1933,7 +1939,6 @@ static size_t http_request_drain(struct http_request *r)
|
|||||||
static void http_request_start_response(struct http_request *r)
|
static void http_request_start_response(struct http_request *r)
|
||||||
{
|
{
|
||||||
assert(r->phase == RECEIVE);
|
assert(r->phase == RECEIVE);
|
||||||
assert(r->response.result_code != 0);
|
|
||||||
if (r->response.content || r->response.content_generator) {
|
if (r->response.content || r->response.content_generator) {
|
||||||
assert(r->response.header.content_type != NULL);
|
assert(r->response.header.content_type != NULL);
|
||||||
assert(r->response.header.content_type[0]);
|
assert(r->response.header.content_type[0]);
|
||||||
@ -1951,6 +1956,13 @@ static void http_request_start_response(struct http_request *r)
|
|||||||
http_request_drain(r);
|
http_request_drain(r);
|
||||||
if (r->phase != RECEIVE)
|
if (r->phase != RECEIVE)
|
||||||
return;
|
return;
|
||||||
|
// Ensure conformance to HTTP standards.
|
||||||
|
if (r->response.result_code == 401 && r->response.header.www_authenticate.scheme == NOAUTH) {
|
||||||
|
WHY("HTTP 401 response missing WWW-Authenticate header, sending 500 Server Error instead");
|
||||||
|
r->response.result_code = 500;
|
||||||
|
r->response.content = NULL;
|
||||||
|
r->response.content_generator = NULL;
|
||||||
|
}
|
||||||
// If the response cannot be rendered, then render a 500 Server Error instead. If that fails,
|
// If the response cannot be rendered, then render a 500 Server Error instead. If that fails,
|
||||||
// then just close the connection.
|
// then just close the connection.
|
||||||
http_request_render_response(r);
|
http_request_render_response(r);
|
||||||
@ -1958,6 +1970,7 @@ static void http_request_start_response(struct http_request *r)
|
|||||||
WARN("Cannot render HTTP response, sending 500 Server Error instead");
|
WARN("Cannot render HTTP response, sending 500 Server Error instead");
|
||||||
r->response.result_code = 500;
|
r->response.result_code = 500;
|
||||||
r->response.content = NULL;
|
r->response.content = NULL;
|
||||||
|
r->response.content_generator = NULL;
|
||||||
http_request_render_response(r);
|
http_request_render_response(r);
|
||||||
if (r->response_buffer == NULL) {
|
if (r->response_buffer == NULL) {
|
||||||
WHY("Cannot render HTTP 500 Server Error response, closing connection");
|
WHY("Cannot render HTTP 500 Server Error response, closing connection");
|
||||||
@ -1983,8 +1996,6 @@ static void http_request_start_response(struct http_request *r)
|
|||||||
void http_request_response_static(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes)
|
void http_request_response_static(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes)
|
||||||
{
|
{
|
||||||
assert(r->phase == RECEIVE);
|
assert(r->phase == RECEIVE);
|
||||||
assert(result >= 100);
|
|
||||||
assert(result < 300);
|
|
||||||
assert(mime_type != NULL);
|
assert(mime_type != NULL);
|
||||||
assert(mime_type[0]);
|
assert(mime_type[0]);
|
||||||
r->response.result_code = result;
|
r->response.result_code = result;
|
||||||
@ -1999,8 +2010,6 @@ void http_request_response_static(struct http_request *r, int result, const char
|
|||||||
void http_request_response_generated(struct http_request *r, int result, const char *mime_type, HTTP_CONTENT_GENERATOR generator)
|
void http_request_response_generated(struct http_request *r, int result, const char *mime_type, HTTP_CONTENT_GENERATOR generator)
|
||||||
{
|
{
|
||||||
assert(r->phase == RECEIVE);
|
assert(r->phase == RECEIVE);
|
||||||
assert(result >= 100);
|
|
||||||
assert(result < 300);
|
|
||||||
assert(mime_type != NULL);
|
assert(mime_type != NULL);
|
||||||
assert(mime_type[0]);
|
assert(mime_type[0]);
|
||||||
r->response.result_code = result;
|
r->response.result_code = result;
|
||||||
@ -2021,8 +2030,6 @@ void http_request_response_generated(struct http_request *r, int result, const c
|
|||||||
void http_request_simple_response(struct http_request *r, uint16_t result, const char *body)
|
void http_request_simple_response(struct http_request *r, uint16_t result, const char *body)
|
||||||
{
|
{
|
||||||
assert(r->phase == RECEIVE);
|
assert(r->phase == RECEIVE);
|
||||||
assert(result >= 200);
|
|
||||||
assert(result < 600);
|
|
||||||
strbuf h = NULL;
|
strbuf h = NULL;
|
||||||
if (body) {
|
if (body) {
|
||||||
size_t html_len = strlen(body) + 40;
|
size_t html_len = strlen(body) + 40;
|
||||||
|
@ -25,6 +25,7 @@ source "${0%/*}/../testdefs_rhizome.sh"
|
|||||||
shopt -s extglob
|
shopt -s extglob
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
CR='
'
|
||||||
setup_curl 7
|
setup_curl 7
|
||||||
setup_jq 1.2
|
setup_jq 1.2
|
||||||
setup_servald
|
setup_servald
|
||||||
@ -68,7 +69,6 @@ test_AuthBasicMissing() {
|
|||||||
--dump-header http.headers \
|
--dump-header http.headers \
|
||||||
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
||||||
assertStdoutIs '401'
|
assertStdoutIs '401'
|
||||||
CR='
'
|
|
||||||
assertGrep http.headers "^WWW-Authenticate: Basic realm=\"Serval Rhizome\"$CR$"
|
assertGrep http.headers "^WWW-Authenticate: Basic realm=\"Serval Rhizome\"$CR$"
|
||||||
}
|
}
|
||||||
teardown_AuthBasicMissing() {
|
teardown_AuthBasicMissing() {
|
||||||
@ -78,18 +78,25 @@ teardown_AuthBasicMissing() {
|
|||||||
|
|
||||||
doc_AuthBasicWrong="Basic Authentication credentials must be correct"
|
doc_AuthBasicWrong="Basic Authentication credentials must be correct"
|
||||||
test_AuthBasicWrong() {
|
test_AuthBasicWrong() {
|
||||||
execute --exit-status=67 curl \
|
executeOk curl \
|
||||||
--silent --fail --show-error \
|
--silent --show-error --write-out '%{http_code}' \
|
||||||
--output http.output \
|
--output http.output \
|
||||||
--dump-header http.headers \
|
--dump-header http.headers \
|
||||||
--basic --user fred:nurks \
|
--basic --user fred:nurks \
|
||||||
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
||||||
|
assertStdoutIs '401'
|
||||||
|
assertGrep http.headers "^WWW-Authenticate: Basic realm=\"Serval Rhizome\"$CR$"
|
||||||
executeOk curl \
|
executeOk curl \
|
||||||
--silent --fail --show-error \
|
--silent --fail --show-error --write-out '%{http_code}' \
|
||||||
--output http.output \
|
--output http.output \
|
||||||
--dump-header http.headers \
|
--dump-header http.headers \
|
||||||
--basic --user ron:weasley \
|
--basic --user ron:weasley \
|
||||||
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
||||||
|
assertStdoutIs '200'
|
||||||
|
}
|
||||||
|
teardown_AuthBasicWrong() {
|
||||||
|
tfw_cat http.headers http.output
|
||||||
|
teardown
|
||||||
}
|
}
|
||||||
|
|
||||||
doc_RhizomeList="Fetch full Rhizome bundle list in JSON format"
|
doc_RhizomeList="Fetch full Rhizome bundle list in JSON format"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user