Add Upload support

This commit is contained in:
Andrew Pamment 2017-03-21 22:18:51 +10:00
parent c3c682cad1
commit 5a932dd17c
3 changed files with 96 additions and 2 deletions

View File

@ -128,6 +128,10 @@ static int handler(void* user, const char* section, const char* name, const char
if (cfg->fileroot[strlen(cfg->fileroot) -1] == '/') { if (cfg->fileroot[strlen(cfg->fileroot) -1] == '/') {
cfg->fileroot[strlen(cfg->fileroot) -1] = '\0'; cfg->fileroot[strlen(cfg->fileroot) -1] = '\0';
} }
} else if (strcasecmp(name, "upload folder") == 0) {
cfg->upload_folder = strdup(value);
} else if (strcasecmp(name, "upload sec level") == 0) {
cfg->upload_seclevel = atoi(value);
} }
} }
return 1; return 1;
@ -221,6 +225,80 @@ int open_tcp_connection(struct ftpserver *cfg, struct ftpclient *client) {
return 1; return 1;
} }
void handle_STOR(struct ftpserver *cfg, struct ftpclient *client, char *path) {
char newpath[PATH_MAX];
struct stat s;
pid_t pid;
char buffer[1024];
int j;
int i;
FILE *fptr;
if (path[0] == '/') {
snprintf(newpath, PATH_MAX, "%s", path);
} else {
snprintf(newpath, PATH_MAX, "%s/%s", client->current_path, path);
}
for (i=strlen(newpath);i > 0; i--) {
if (newpath[i] == '/') {
newpath[i] = '\0';
break;
}
}
if (strcmp(&newpath[1], cfg->upload_folder) == 0) {
if (path[0] == '/') {
snprintf(newpath, PATH_MAX, "%s%s", cfg->fileroot, path);
} else {
snprintf(newpath, PATH_MAX, "%s%s/%s",cfg->fileroot, client->current_path, path);
}
if (client->seclevel >= cfg->upload_seclevel) {
if (stat(newpath, &s) != 0) {
pid = fork();
if (pid == 0) {
fptr = fopen(newpath, "wb");
if (fptr) {
if (open_tcp_connection(cfg, client)) {
send_msg(client, "150 Data connection accepted; transfer starting.\r\n");
while (1) {
j = recv(client->data_socket, buffer, 1024, 0);
if (j == 0) {
break;
}
if (j < 0) {
send_msg(client, "426 TCP connection was established but then broken\r\n");
fclose(fptr);
unlink(newpath);
close_tcp_connection(client);
exit(0);
}
fwrite(buffer, 1, j, fptr);
}
fclose(fptr);
close_tcp_connection(client);
send_msg(client, "226 Transfer OK.\r\n");
exit(0);
} else {
send_msg(client, "425 TCP connection cannot be established.\r\n");
fclose(fptr);
exit(0);
}
}
} else if (pid < 0) {
send_msg(client, "451 STOR Failed.\r\n");
}
} else {
send_msg(client, "553 File Exists.\n");
}
} else {
send_msg(client, "532 Access Denied.\n");
}
} else {
send_msg(client, "532 Access Denied.\n");
}
}
void handle_PASV(struct ftpserver *cfg, struct ftpclient *client) { void handle_PASV(struct ftpserver *cfg, struct ftpclient *client) {
char buffer[200]; char buffer[200];
char *ipcpy; char *ipcpy;
@ -436,7 +514,7 @@ void handle_PASS(struct ftpserver *cfg, struct ftpclient *client, char *password
sqlite3 *db; sqlite3 *db;
sqlite3_stmt *res; sqlite3_stmt *res;
int rc; int rc;
char *sql = "SELECT password, salt FROM users WHERE loginname = ?"; char *sql = "SELECT password, salt, sec_level FROM users WHERE loginname = ?";
char *pass_hash; char *pass_hash;
if (strlen(client->name) == 0) { if (strlen(client->name) == 0) {
@ -469,6 +547,7 @@ void handle_PASS(struct ftpserver *cfg, struct ftpclient *client, char *password
if (step == SQLITE_ROW) { if (step == SQLITE_ROW) {
pass_hash = hash_sha256(password, (char *)sqlite3_column_text(res, 1)); pass_hash = hash_sha256(password, (char *)sqlite3_column_text(res, 1));
if (strcmp(pass_hash, (char *)sqlite3_column_text(res, 0)) == 0) { if (strcmp(pass_hash, (char *)sqlite3_column_text(res, 0)) == 0) {
client->seclevel = sqlite3_column_int(res, 2);
send_msg(client, "230 User Logged in, Proceed.\r\n"); send_msg(client, "230 User Logged in, Proceed.\r\n");
strncpy(client->password, password, 32); strncpy(client->password, password, 32);
} else { } else {
@ -566,6 +645,9 @@ int handle_client(struct ftpserver *cfg, struct ftpclient *client, char *buf, in
} else } else
if (strcmp(cmd, "RETR") == 0) { if (strcmp(cmd, "RETR") == 0) {
handle_RETR(cfg, client, argument); handle_RETR(cfg, client, argument);
} else
if (strcmp(cmd, "STOR") == 0) {
handle_STOR(cfg, client, argument);
} else { } else {
send_msg(client, "500 Command not recognized.\r\n"); send_msg(client, "500 Command not recognized.\r\n");
} }
@ -654,6 +736,7 @@ void init(struct ftpserver *cfg) {
clients[client_count]->type = 1; clients[client_count]->type = 1;
clients[client_count]->status = 0; clients[client_count]->status = 0;
clients[client_count]->data_port = 0; clients[client_count]->data_port = 0;
clients[client_count]->seclevel = 0;
memset(clients[client_count]->name, 0, 16); memset(clients[client_count]->name, 0, 16);
memset(clients[client_count]->password, 0, 32); memset(clients[client_count]->password, 0, 32);

View File

@ -13,12 +13,15 @@ struct ftpclient {
char password[32]; char password[32];
int data_srv_socket; int data_srv_socket;
int status; int status;
int seclevel;
}; };
struct ftpserver { struct ftpserver {
int port; int port;
char *fileroot; char *fileroot;
char *userdb; char *userdb;
char *upload_folder;
int upload_seclevel;
}; };
#endif #endif

View File

@ -1,4 +1,12 @@
[Main] [Main]
; Port to listen on
Port = 2121 Port = 2121
; Path and Filename of Magicka Users DB
Users DB = /home/andrew/MagickaBBS/users.sq3 Users DB = /home/andrew/MagickaBBS/users.sq3
; Root of files to serve
File Root = /home/andrew/MagickaBBS/ftproot/ File Root = /home/andrew/MagickaBBS/ftproot/
; Upload Folder is relative to file root. Make sure it exists
; Or remove this line to disable uploads.
Upload Folder = incoming
; Minimum Security Level to Upload - 0 to allow anonymous uploads
Upload Sec Level = 10