Added optional HTTP Authentication

This commit is contained in:
Thomas Kolb 2015-11-23 21:23:57 +01:00
parent 77a2ee3d8e
commit 900ee14e32
2 changed files with 76 additions and 5 deletions

View file

@ -89,4 +89,13 @@
" </ul>" \ " </ul>" \
FOOTER FOOTER
#define ERROR_401 \
HEADER1 \
" <title>Error 401 - Unauthorized</title>" \
HEADER2 \
" <h1>Error 401 - Unauthorized</h1>" \
" <p>You are not authorized to see the requested content.<p>" \
" <p>Enter the correct username and password!<p>" \
FOOTER
#endif // TEMPLATES_H #endif // TEMPLATES_H

View file

@ -45,6 +45,8 @@
#define DEFAULT_PORT 8888 #define DEFAULT_PORT 8888
char *shareRoot; char *shareRoot;
char *password;
struct MHD_Response *error401Response;
struct MHD_Response *error403Response; struct MHD_Response *error403Response;
struct MHD_Response *error404Response; struct MHD_Response *error404Response;
struct MHD_Response *error500Response; struct MHD_Response *error500Response;
@ -419,6 +421,36 @@ int key_value_iterator(void *cls,
} }
} }
// returns 1 on successful authentication and 0 when auth. failed
static int check_authorization(struct MHD_Connection *connection) {
char *auth_pass;
char *auth_user;
int fail;
if(password == NULL) {
return 1;
}
auth_pass = NULL;
auth_user = MHD_basic_auth_get_username_password(connection, &auth_pass);
fail = (auth_user == NULL) || (0 != strcmp(auth_user, "fileshare")) || (0 != strcmp(auth_pass, password));
if (auth_user != NULL) {
free(auth_user);
}
if (auth_pass != NULL) {
free(auth_pass);
}
if(fail) {
return 0;
} else {
return 1;
}
}
static int connection_handler(void * cls, static int connection_handler(void * cls,
struct MHD_Connection *connection, struct MHD_Connection *connection,
@ -493,6 +525,16 @@ static int connection_handler(void * cls,
return MHD_queue_response(connection, MHD_HTTP_FORBIDDEN, error403Response); return MHD_queue_response(connection, MHD_HTTP_FORBIDDEN, error403Response);
} }
// check the authentication, if enabled
if(!check_authorization(connection)) {
LOG(LVL_WARN,
"Unauthorized request from %s for %s .",
connstate->clientIP, connstate->localFileName);
return MHD_queue_basic_auth_fail_response(
connection, "Fileshare " VERSION, error401Response);
}
// check properties of the target file/dir // check properties of the target file/dir
if(stat(connstate->localFileName, &(connstate->targetStat)) == -1) { if(stat(connstate->localFileName, &(connstate->targetStat)) == -1) {
LOG(LVL_ERR, "Cannot stat %s: %s", LOG(LVL_ERR, "Cannot stat %s: %s",
@ -609,13 +651,14 @@ void print_urls(int port) {
freeifaddrs(ifaddr); freeifaddrs(ifaddr);
} }
int parse_cmdline(int argc, char **argv, int *port, int *enableUpload, char **shareRoot) { int parse_cmdline(int argc, char **argv, int *port, int *enableUpload, char **shareRoot, char **password) {
int c; int c;
*enableUpload = 0; *enableUpload = 0;
*port = DEFAULT_PORT; *port = DEFAULT_PORT;
*password = NULL;
while ((c = getopt (argc, argv, "up:")) != -1) { while ((c = getopt (argc, argv, "up:P:")) != -1) {
switch (c) { switch (c) {
case 'u': case 'u':
*enableUpload = 1; *enableUpload = 1;
@ -632,6 +675,10 @@ int parse_cmdline(int argc, char **argv, int *port, int *enableUpload, char **sh
return 1; return 1;
} }
break; break;
case 'P':
// a password was given on the command line.
*password = optarg;
break;
case '?': case '?':
if (optopt == 'p') { if (optopt == 'p') {
LOG(LVL_ERR, "Option -%c requires an argument.\n", optopt); LOG(LVL_ERR, "Option -%c requires an argument.\n", optopt);
@ -674,7 +721,7 @@ int main(int argc, char ** argv) {
#endif #endif
// parse command line arguments // parse command line arguments
if(parse_cmdline(argc, argv, &port, &uploadEnabled, &shareRoot)) { if(parse_cmdline(argc, argv, &port, &uploadEnabled, &shareRoot, &password)) {
LOG(LVL_ERR, "Failed to parse command line!"); LOG(LVL_ERR, "Failed to parse command line!");
LOG(LVL_INFO, "Usage: %s [arguments] <dir>", argv[0]); LOG(LVL_INFO, "Usage: %s [arguments] <dir>", argv[0]);
LOG(LVL_INFO, ""); LOG(LVL_INFO, "");
@ -682,6 +729,7 @@ int main(int argc, char ** argv) {
LOG(LVL_INFO, ""); LOG(LVL_INFO, "");
LOG(LVL_INFO, "\t-u Enable Uploads"); LOG(LVL_INFO, "\t-u Enable Uploads");
LOG(LVL_INFO, "\t-p port Change the listening port."); LOG(LVL_INFO, "\t-p port Change the listening port.");
LOG(LVL_INFO, "\t-P password Optional password for HTTP authentication.");
LOG(LVL_INFO, ""); LOG(LVL_INFO, "");
return 1; return 1;
} }
@ -690,6 +738,12 @@ int main(int argc, char ** argv) {
LOG(LVL_WARN, "Uploads are enabled. Users can create new files anywhere in %s !", shareRoot); LOG(LVL_WARN, "Uploads are enabled. Users can create new files anywhere in %s !", shareRoot);
} }
if(password != NULL) {
LOG(LVL_INFO, "HTTP Authentication enabled. Clients must log in as user 'fileshare', password '%s'.", password);
} else {
LOG(LVL_WARN, "HTTP Authentication disabled, everybody can download the shared files!");
}
// check if shareRoot is an existing directory // check if shareRoot is an existing directory
if(stat(shareRoot, &sBuf) == -1) { if(stat(shareRoot, &sBuf) == -1) {
LOG(LVL_FATAL, "Cannot stat %s: %s", shareRoot, strerror(errno)); LOG(LVL_FATAL, "Cannot stat %s: %s", shareRoot, strerror(errno));
@ -728,6 +782,12 @@ int main(int argc, char ** argv) {
init_signal_handlers(); init_signal_handlers();
// create the static response for error pages // create the static response for error pages
error401Response = MHD_create_response_from_data(
strlen(ERROR_401),
(void*) ERROR_401,
MHD_NO,
MHD_NO);
error403Response = MHD_create_response_from_data( error403Response = MHD_create_response_from_data(
strlen(ERROR_403), strlen(ERROR_403),
(void*) ERROR_403, (void*) ERROR_403,
@ -746,6 +806,7 @@ int main(int argc, char ** argv) {
MHD_NO, MHD_NO,
MHD_NO); MHD_NO);
MHD_add_response_header(error401Response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html");
MHD_add_response_header(error403Response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); MHD_add_response_header(error403Response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html");
MHD_add_response_header(error404Response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); MHD_add_response_header(error404Response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html");
MHD_add_response_header(error500Response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); MHD_add_response_header(error500Response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html");
@ -810,6 +871,7 @@ int main(int argc, char ** argv) {
MHD_stop_daemon(d6); MHD_stop_daemon(d6);
MHD_destroy_response(error401Response);
MHD_destroy_response(error403Response); MHD_destroy_response(error403Response);
MHD_destroy_response(error404Response); MHD_destroy_response(error404Response);
MHD_destroy_response(error500Response); MHD_destroy_response(error500Response);