chore: add CMake test infrastructure and placeholder unit test files for future coverage
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
#include "../../test_framework.h"
|
||||
#include "../http_endpoints.h"
|
||||
|
||||
TEST_SUITE(auth_401_challenge)
|
||||
|
||||
TEST(no_auth_header_returns_401) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/protected.txt", "secret", 6);
|
||||
|
||||
endpoint_test_execute(ctx, "GET", "/protected.txt", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(401_includes_www_authenticate_header) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/protected.txt", "secret", 6);
|
||||
|
||||
endpoint_test_execute(ctx, "GET", "/protected.txt", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
ASSERT_TRUE(endpoint_response_has_header(ctx, "WWW-Authenticate", NULL));
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(401_challenge_includes_realm) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/file.txt", "x", 1);
|
||||
|
||||
endpoint_test_execute(ctx, "GET", "/file.txt", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
const char *www_auth = endpoint_response_get_header(ctx, "WWW-Authenticate");
|
||||
ASSERT_NOT_NULL(www_auth);
|
||||
ASSERT_TRUE(strstr(www_auth, "realm=") != NULL);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(401_for_put_without_auth) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
endpoint_test_execute(ctx, "PUT", "/newfile.txt", "content", 7);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(401_for_delete_without_auth) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/file.txt", "x", 1);
|
||||
|
||||
endpoint_test_execute(ctx, "DELETE", "/file.txt", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(401_for_mkcol_without_auth) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
endpoint_test_execute(ctx, "MKCOL", "/newfolder", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(401_for_proppatch_without_auth) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/file.txt", "x", 1);
|
||||
|
||||
const char *body =
|
||||
"<?xml version=\"1.0\"?>"
|
||||
"<propertyupdate xmlns=\"DAV:\">"
|
||||
"<set><prop><displayname>x</displayname></prop></set>"
|
||||
"</propertyupdate>";
|
||||
|
||||
endpoint_test_execute(ctx, "PROPPATCH", "/file.txt", body, strlen(body));
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(malformed_auth_header_returns_401) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/file.txt", "x", 1);
|
||||
|
||||
http_request_init(&ctx->request);
|
||||
strncpy(ctx->request.method, "GET", sizeof(ctx->request.method) - 1);
|
||||
strncpy(ctx->request.uri, "/file.txt", sizeof(ctx->request.uri) - 1);
|
||||
http_request_add_header(&ctx->request, "Authorization", "InvalidScheme xyz123");
|
||||
|
||||
http_response_init(&ctx->response);
|
||||
webdav_handle_request(ctx->fixture->storage, ctx->fixture->locks,
|
||||
ctx->fixture->props, &ctx->request, &ctx->response);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(empty_auth_header_returns_401) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/file.txt", "x", 1);
|
||||
|
||||
http_request_init(&ctx->request);
|
||||
strncpy(ctx->request.method, "GET", sizeof(ctx->request.method) - 1);
|
||||
strncpy(ctx->request.uri, "/file.txt", sizeof(ctx->request.uri) - 1);
|
||||
http_request_add_header(&ctx->request, "Authorization", "");
|
||||
|
||||
http_response_init(&ctx->response);
|
||||
webdav_handle_request(ctx->fixture->storage, ctx->fixture->locks,
|
||||
ctx->fixture->props, &ctx->request, &ctx->response);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(options_allowed_without_auth) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
endpoint_test_execute(ctx, "OPTIONS", "/", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_200_OK, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
#include "../../test_framework.h"
|
||||
#include "../http_endpoints.h"
|
||||
|
||||
TEST_SUITE(auth_basic_flow)
|
||||
|
||||
TEST(basic_auth_valid_credentials) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "testuser", "testpass",
|
||||
"test@example.com", 0);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/protected.txt", "secret", 6);
|
||||
|
||||
endpoint_test_execute_with_auth(ctx, "GET", "/protected.txt",
|
||||
"testuser", "testpass", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_200_OK, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(basic_auth_invalid_password) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "testuser", "correctpass",
|
||||
"test@example.com", 0);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/protected.txt", "secret", 6);
|
||||
|
||||
endpoint_test_execute_with_auth(ctx, "GET", "/protected.txt",
|
||||
"testuser", "wrongpass", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(basic_auth_unknown_user) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/protected.txt", "secret", 6);
|
||||
|
||||
endpoint_test_execute_with_auth(ctx, "GET", "/protected.txt",
|
||||
"unknown", "anypass", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(basic_auth_disabled_user) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "disabled", "password",
|
||||
"disabled@example.com", 0);
|
||||
user_manager_enable(ctx->fixture->user_mgr, "disabled", 0);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/protected.txt", "secret", 6);
|
||||
|
||||
endpoint_test_execute_with_auth(ctx, "GET", "/protected.txt",
|
||||
"disabled", "password", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(basic_auth_put_file) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "writer", "writepass",
|
||||
"writer@example.com", 0);
|
||||
|
||||
const char *content = "new file content";
|
||||
endpoint_test_execute_with_auth(ctx, "PUT", "/newfile.txt",
|
||||
"writer", "writepass",
|
||||
content, strlen(content));
|
||||
|
||||
ASSERT_EQUAL(HTTP_201_CREATED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(basic_auth_mkcol) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "creator", "createpass",
|
||||
"creator@example.com", 0);
|
||||
|
||||
endpoint_test_execute_with_auth(ctx, "MKCOL", "/newfolder",
|
||||
"creator", "createpass", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_201_CREATED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(basic_auth_delete) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "deleter", "deletepass",
|
||||
"deleter@example.com", 0);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/todelete.txt", "x", 1);
|
||||
|
||||
endpoint_test_execute_with_auth(ctx, "DELETE", "/todelete.txt",
|
||||
"deleter", "deletepass", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_204_NO_CONTENT, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(basic_auth_special_chars_in_password) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "special", "p@ss:w0rd!#$",
|
||||
"special@example.com", 0);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/file.txt", "x", 1);
|
||||
|
||||
endpoint_test_execute_with_auth(ctx, "GET", "/file.txt",
|
||||
"special", "p@ss:w0rd!#$", NULL, 0);
|
||||
|
||||
ASSERT_EQUAL(HTTP_200_OK, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
#include "../../test_framework.h"
|
||||
#include "../http_endpoints.h"
|
||||
#include "../../src/auth/auth.h"
|
||||
|
||||
TEST_SUITE(auth_digest_flow)
|
||||
|
||||
static void compute_digest_response(const char *username, const char *password,
|
||||
const char *realm, const char *nonce,
|
||||
const char *method, const char *uri,
|
||||
const char *nc, const char *cnonce,
|
||||
const char *qop, char *out_response) {
|
||||
char ha1[65], ha2[65];
|
||||
|
||||
char a1[512];
|
||||
snprintf(a1, sizeof(a1), "%s:%s:%s", username, realm, password);
|
||||
auth_md5_hex(a1, strlen(a1), ha1);
|
||||
|
||||
char a2[512];
|
||||
snprintf(a2, sizeof(a2), "%s:%s", method, uri);
|
||||
auth_md5_hex(a2, strlen(a2), ha2);
|
||||
|
||||
char response_str[1024];
|
||||
snprintf(response_str, sizeof(response_str), "%s:%s:%s:%s:%s:%s",
|
||||
ha1, nonce, nc, cnonce, qop, ha2);
|
||||
auth_md5_hex(response_str, strlen(response_str), out_response);
|
||||
}
|
||||
|
||||
TEST(digest_auth_valid_credentials) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "digestuser", "digestpass",
|
||||
"digest@example.com", 0);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/secure.txt", "secret data", 11);
|
||||
|
||||
const char *realm = "WebDAV";
|
||||
const char *nonce = "abc123nonce";
|
||||
const char *uri = "/secure.txt";
|
||||
const char *nc = "00000001";
|
||||
const char *cnonce = "xyz789cnonce";
|
||||
const char *qop = "auth";
|
||||
|
||||
char response[65];
|
||||
compute_digest_response("digestuser", "digestpass", realm, nonce,
|
||||
"GET", uri, nc, cnonce, qop, response);
|
||||
|
||||
char auth_header[1024];
|
||||
snprintf(auth_header, sizeof(auth_header),
|
||||
"Digest username=\"digestuser\", realm=\"%s\", nonce=\"%s\", "
|
||||
"uri=\"%s\", nc=%s, cnonce=\"%s\", qop=%s, response=\"%s\"",
|
||||
realm, nonce, uri, nc, cnonce, qop, response);
|
||||
|
||||
http_request_init(&ctx->request);
|
||||
strncpy(ctx->request.method, "GET", sizeof(ctx->request.method) - 1);
|
||||
strncpy(ctx->request.uri, uri, sizeof(ctx->request.uri) - 1);
|
||||
http_request_add_header(&ctx->request, "Authorization", auth_header);
|
||||
|
||||
http_response_init(&ctx->response);
|
||||
webdav_handle_request(ctx->fixture->storage, ctx->fixture->locks,
|
||||
ctx->fixture->props, &ctx->request, &ctx->response);
|
||||
|
||||
ASSERT_EQUAL(HTTP_200_OK, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(digest_auth_invalid_response) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "testuser", "testpass",
|
||||
"test@example.com", 0);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/file.txt", "data", 4);
|
||||
|
||||
char auth_header[1024];
|
||||
snprintf(auth_header, sizeof(auth_header),
|
||||
"Digest username=\"testuser\", realm=\"WebDAV\", nonce=\"abc123\", "
|
||||
"uri=\"/file.txt\", nc=00000001, cnonce=\"xyz789\", qop=auth, "
|
||||
"response=\"invalidresponse\"");
|
||||
|
||||
http_request_init(&ctx->request);
|
||||
strncpy(ctx->request.method, "GET", sizeof(ctx->request.method) - 1);
|
||||
strncpy(ctx->request.uri, "/file.txt", sizeof(ctx->request.uri) - 1);
|
||||
http_request_add_header(&ctx->request, "Authorization", auth_header);
|
||||
|
||||
http_response_init(&ctx->response);
|
||||
webdav_handle_request(ctx->fixture->storage, ctx->fixture->locks,
|
||||
ctx->fixture->props, &ctx->request, &ctx->response);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(digest_auth_unknown_user) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
storage_write_file(ctx->fixture->storage, "/file.txt", "data", 4);
|
||||
|
||||
char response[65];
|
||||
compute_digest_response("unknown", "anypass", "WebDAV", "nonce123",
|
||||
"GET", "/file.txt", "00000001", "cnonce", "auth", response);
|
||||
|
||||
char auth_header[1024];
|
||||
snprintf(auth_header, sizeof(auth_header),
|
||||
"Digest username=\"unknown\", realm=\"WebDAV\", nonce=\"nonce123\", "
|
||||
"uri=\"/file.txt\", nc=00000001, cnonce=\"cnonce\", qop=auth, "
|
||||
"response=\"%s\"", response);
|
||||
|
||||
http_request_init(&ctx->request);
|
||||
strncpy(ctx->request.method, "GET", sizeof(ctx->request.method) - 1);
|
||||
strncpy(ctx->request.uri, "/file.txt", sizeof(ctx->request.uri) - 1);
|
||||
http_request_add_header(&ctx->request, "Authorization", auth_header);
|
||||
|
||||
http_response_init(&ctx->response);
|
||||
webdav_handle_request(ctx->fixture->storage, ctx->fixture->locks,
|
||||
ctx->fixture->props, &ctx->request, &ctx->response);
|
||||
|
||||
ASSERT_EQUAL(HTTP_401_UNAUTHORIZED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
TEST(digest_auth_put_operation) {
|
||||
endpoint_test_ctx_t *ctx = endpoint_test_create();
|
||||
ASSERT_NOT_NULL(ctx);
|
||||
|
||||
user_manager_add(ctx->fixture->user_mgr, "writer", "writepass",
|
||||
"writer@example.com", 0);
|
||||
|
||||
const char *realm = "WebDAV";
|
||||
const char *nonce = "putnonce";
|
||||
const char *uri = "/newfile.txt";
|
||||
const char *nc = "00000001";
|
||||
const char *cnonce = "putcnonce";
|
||||
const char *qop = "auth";
|
||||
|
||||
char response[65];
|
||||
compute_digest_response("writer", "writepass", realm, nonce,
|
||||
"PUT", uri, nc, cnonce, qop, response);
|
||||
|
||||
char auth_header[1024];
|
||||
snprintf(auth_header, sizeof(auth_header),
|
||||
"Digest username=\"writer\", realm=\"%s\", nonce=\"%s\", "
|
||||
"uri=\"%s\", nc=%s, cnonce=\"%s\", qop=%s, response=\"%s\"",
|
||||
realm, nonce, uri, nc, cnonce, qop, response);
|
||||
|
||||
const char *content = "file content";
|
||||
http_request_init(&ctx->request);
|
||||
strncpy(ctx->request.method, "PUT", sizeof(ctx->request.method) - 1);
|
||||
strncpy(ctx->request.uri, uri, sizeof(ctx->request.uri) - 1);
|
||||
http_request_add_header(&ctx->request, "Authorization", auth_header);
|
||||
ctx->request.body = strdup(content);
|
||||
ctx->request.body_len = strlen(content);
|
||||
ctx->request.content_length = strlen(content);
|
||||
|
||||
http_response_init(&ctx->response);
|
||||
webdav_handle_request(ctx->fixture->storage, ctx->fixture->locks,
|
||||
ctx->fixture->props, &ctx->request, &ctx->response);
|
||||
|
||||
ASSERT_EQUAL(HTTP_201_CREATED, ctx->response.status);
|
||||
|
||||
endpoint_test_destroy(ctx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user