Use getopt(), restrict upload access

This commit is contained in:
Thomas Kolb 2013-08-19 19:59:54 +02:00
parent 6dfd30e508
commit 1c103e0952
2 changed files with 76 additions and 26 deletions

View file

@ -25,6 +25,7 @@
" <body>" " <body>"
#define FOOTER \ #define FOOTER \
" <p><small>Generated by fileshare " VERSION ".</small></p>" \
" </body>" \ " </body>" \
"</html>" "</html>"
@ -84,6 +85,7 @@
" <li>You are trying to access a file that the server isn't allowed to read</li>" \ " <li>You are trying to access a file that the server isn't allowed to read</li>" \
" <li>The target filesystem entry is not a regular file or directory</li>" \ " <li>The target filesystem entry is not a regular file or directory</li>" \
" <li>The URL contains \"/..\", which is blocked for security reasons</li>" \ " <li>The URL contains \"/..\", which is blocked for security reasons</li>" \
" <li>You are trying to upload a file, and uploads are not enabled for this server</li>" \
" </ul>" \ " </ul>" \
FOOTER FOOTER

View file

@ -11,6 +11,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h>
#include <errno.h> #include <errno.h>
@ -55,7 +56,7 @@ magic_t magicCookie;
#endif #endif
int running = 1; int running = 1;
int uploadEnabled = 1; int uploadEnabled = 0;
void request_completed(void *cls, void request_completed(void *cls,
struct MHD_Connection * connection, struct MHD_Connection * connection,
@ -398,8 +399,15 @@ static int connection_handler(void * cls,
connstate->postProcessor = NULL; connstate->postProcessor = NULL;
connstate->requestType = GET; connstate->requestType = GET;
} else if(0 == strcmp(method, "POST")) { } else if(0 == strcmp(method, "POST")) {
if(!uploadEnabled) {
LOG(LVL_WARN,
"Uploads are disabled, so POST requests are denied.",
connstate->localFileName);
return MHD_queue_response(connection, MHD_HTTP_FORBIDDEN, error403Response);
} else {
connstate->postProcessor = MHD_create_post_processor(connection, 1024*1024, post_processor, connstate); connstate->postProcessor = MHD_create_post_processor(connection, 1024*1024, post_processor, connstate);
connstate->requestType = POST; connstate->requestType = POST;
}
} else { } else {
LOG(LVL_WARN, "Unexpected method: %s.", method); LOG(LVL_WARN, "Unexpected method: %s.", method);
return MHD_NO; return MHD_NO;
@ -442,7 +450,7 @@ static int connection_handler(void * cls,
if(S_ISREG(connstate->targetStat.st_mode)) { if(S_ISREG(connstate->targetStat.st_mode)) {
return serv_regular_file(connection, connstate); return serv_regular_file(connection, connstate);
} else if(S_ISDIR(connstate->targetStat.st_mode)) { } else if(S_ISDIR(connstate->targetStat.st_mode)) {
if(connstate->uploadRequest) { if(uploadEnabled && connstate->uploadRequest) {
return MHD_queue_response(connection, MHD_HTTP_OK, uploadFormResponse); return MHD_queue_response(connection, MHD_HTTP_OK, uploadFormResponse);
} else { } else {
return serv_directory(connection, connstate); return serv_directory(connection, connstate);
@ -541,6 +549,53 @@ void print_urls(int port) {
freeifaddrs(ifaddr); freeifaddrs(ifaddr);
} }
int parse_cmdline(int argc, char **argv, int *port, int *enableUpload, char **shareRoot) {
int c;
*enableUpload = 0;
*port = DEFAULT_PORT;
while ((c = getopt (argc, argv, "up:")) != -1) {
switch (c) {
case 'u':
*enableUpload = 1;
break;
case 'p':
// a port was given on the command line, try to parse it
if(sscanf(optarg, "%i", port) != 1) {
LOG(LVL_FATAL, "%s is not a valid port number!", optarg);
return 1;
}
if(*port < 1 || *port > 65535) {
LOG(LVL_FATAL, "Port %i is out of range [1-65535]!", *port);
return 1;
}
break;
case '?':
if (optopt == 'p') {
LOG(LVL_ERR, "Option -%c requires an argument.\n", optopt);
} else if (isprint (optopt)) {
LOG(LVL_ERR, "Unknown option `-%c'.\n", optopt);
} else {
LOG(LVL_ERR, "Unknown option character `\\x%x'.\n", optopt);
}
return 1;
default:
return 1;
}
}
if(optind < argc) {
// found non-option argument -> use as shared dir
*shareRoot = argv[optind];
return 0;
}
return 1;
}
int main(int argc, char ** argv) { int main(int argc, char ** argv) {
struct MHD_Daemon *d, *d6; struct MHD_Daemon *d, *d6;
struct stat sBuf; struct stat sBuf;
@ -556,14 +611,24 @@ int main(int argc, char ** argv) {
logger_set_verbosity(LVL_INFO); logger_set_verbosity(LVL_INFO);
#endif #endif
if (argc < 2) { // parse command line arguments
LOG(LVL_ERR, "Too few arguments!"); if(parse_cmdline(argc, argv, &port, &uploadEnabled, &shareRoot)) {
LOG(LVL_INFO, "Usage: %s <dir> [<port>]", argv[0]); LOG(LVL_ERR, "Failed to parse command line!");
LOG(LVL_INFO, "Usage: %s [arguments] <dir>", argv[0]);
LOG(LVL_INFO, "");
LOG(LVL_INFO, "Arguments:");
LOG(LVL_INFO, "");
LOG(LVL_INFO, "\t-u Enable Uploads");
LOG(LVL_INFO, "\t-p port Change the listening port.");
LOG(LVL_INFO, "");
return 1; return 1;
} }
if(uploadEnabled) {
LOG(LVL_WARN, "Uploads are enabled. Users can create new files anywhere in %s !", shareRoot);
}
// check if shareRoot is an existing directory // check if shareRoot is an existing directory
shareRoot = argv[1];
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));
return EXIT_FAILURE; return EXIT_FAILURE;
@ -578,24 +643,7 @@ int main(int argc, char ** argv) {
remove_trailing_slash(shareRoot); remove_trailing_slash(shareRoot);
LOG(LVL_INFO, "Shared directory is: %s", shareRoot); LOG(LVL_INFO, "Shared directory is: %s", shareRoot);
if(argc >= 3) {
// a port was given on the command line, try to parse it
if(sscanf(argv[2], "%i", &port) != 1) {
LOG(LVL_FATAL, "%s is not a valid port number!", argv[2]);
return EXIT_FAILURE;
}
if(port < 1 || port > 65535) {
LOG(LVL_FATAL, "Port %i is out of range [1-65535]!", port);
return EXIT_FAILURE;
}
LOG(LVL_INFO, "Using port: %i", port); LOG(LVL_INFO, "Using port: %i", port);
} else {
LOG(LVL_INFO, "Using default port: %i", DEFAULT_PORT);
port = DEFAULT_PORT;
}
#ifdef HAVE_MAGIC #ifdef HAVE_MAGIC
// initialize libmagic // initialize libmagic