Started work on an ftp server(not nearly finished)
This commit is contained in:
parent
18fee3a050
commit
c304f02496
6
users.c
6
users.c
@ -230,9 +230,9 @@ struct user_record *check_user_pass(char *loginname, char *password) {
|
|||||||
struct user_record *user;
|
struct user_record *user;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
sqlite3_stmt *res;
|
sqlite3_stmt *res;
|
||||||
int rc;
|
int rc;
|
||||||
char *sql = "SELECT Id, loginname, password, salt, firstname,"
|
char *sql = "SELECT Id, loginname, password, salt, firstname,"
|
||||||
"lastname, email, location, sec_level, last_on, time_left, cur_mail_conf, cur_mail_area, cur_file_dir, cur_file_sub, times_on, bwavepktno, archiver, protocol FROM users WHERE loginname LIKE ?";
|
"lastname, email, location, sec_level, last_on, time_left, cur_mail_conf, cur_mail_area, cur_file_dir, cur_file_sub, times_on, bwavepktno, archiver, protocol FROM users WHERE loginname LIKE ?";
|
||||||
char *pass_hash;
|
char *pass_hash;
|
||||||
|
|
||||||
|
358
utils/magiftpd/magiftpd.c
Normal file
358
utils/magiftpd/magiftpd.c
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include "magiftpd.h"
|
||||||
|
#include "../../inih/ini.h"
|
||||||
|
|
||||||
|
static struct ftpclient **clients;
|
||||||
|
static int client_count = 0;
|
||||||
|
|
||||||
|
static int handler(void* user, const char* section, const char* name, const char* value) {}
|
||||||
|
struct ftpserver *cfg = (struct ftpserver *)user;
|
||||||
|
|
||||||
|
if (strcasecmp(section, "main") == 0) {
|
||||||
|
if (strcasecmp(name, "port") == 0) {
|
||||||
|
cfg->port = atoi(value);
|
||||||
|
} else if (strcasecmp(name, "users db") == 0) {
|
||||||
|
cfg->userdb = strdup(value);
|
||||||
|
} else if (strcasecmp(name, "file root") == 0) {
|
||||||
|
cfg->fileroot = strdup(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *hash_sha256(char *pass, char *salt) {
|
||||||
|
char *buffer = (char *)malloc(strlen(pass) + strlen(salt) + 1);
|
||||||
|
char *shash = (char *)malloc(66);
|
||||||
|
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||||
|
|
||||||
|
if (!buffer) {
|
||||||
|
fprintf(stderr, "Out of memory!\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(buffer, "%s%s", pass, salt);
|
||||||
|
|
||||||
|
|
||||||
|
SHA256_CTX sha256;
|
||||||
|
SHA256_Init(&sha256);
|
||||||
|
SHA256_Update(&sha256, buffer, strlen(buffer));
|
||||||
|
SHA256_Final(hash, &sha256);
|
||||||
|
int i = 0;
|
||||||
|
for(i = 0; i < SHA256_DIGEST_LENGTH; i++) {
|
||||||
|
sprintf(shash + (i * 2), "%02x", hash[i]);
|
||||||
|
}
|
||||||
|
shash[64] = 0;
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
return shash;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_msg(struct ftpclient *client, char *msg) {
|
||||||
|
int len = strlen(msg);
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
while (l > 0) {
|
||||||
|
n = send(client->fd, msg + n, l, 0);
|
||||||
|
l -= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_TYPE(struct ftpserver *cfg, struct ftpclient *client) {
|
||||||
|
send_msg(client, "200 Type set to I.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_PWD(struct ftpserver *cfg, struct ftpclient *client) {
|
||||||
|
char *buffer = (char *)malloc(strlen(client->current_path) + 9);
|
||||||
|
if (!buffer) {
|
||||||
|
fprintf(stderr, "Out of memory\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(buffer, "257 \"%s\"\r\n", client->current_path);
|
||||||
|
send_msg(client, buffer);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_SYST(struct ftpserver *cfg, struct ftpclient *client) {
|
||||||
|
send_msg(client, "215 UNIX Type: L8\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_PASS(struct ftpserver *cfg, struct ftpclient *client, char *password) {
|
||||||
|
sqlite3 *db;
|
||||||
|
sqlite3_stmt *res;
|
||||||
|
int rc;
|
||||||
|
char *sql = "SELECT password, salt FROM users WHERE loginname = ?";
|
||||||
|
char *pass_hash;
|
||||||
|
|
||||||
|
if (strlen(client->name) == 0) {
|
||||||
|
send_msg(client, "503 Need username first\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(client->name, "anonymous")) {
|
||||||
|
strncpy(client->password, password, 32);
|
||||||
|
client->password[31] = '\0';
|
||||||
|
} else {
|
||||||
|
rc = sqlite3_open(cfg->userdb, &db);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);
|
||||||
|
|
||||||
|
if (rc == SQLITE_OK) {
|
||||||
|
sqlite3_bind_text(res, 1, client->name, -1, 0);
|
||||||
|
} else {
|
||||||
|
fprintf(sterr, "Failed to execute statement: %s", sqlite3_errmsg(db));
|
||||||
|
sqlite3_close(db);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int step = sqlite3_step(res);
|
||||||
|
|
||||||
|
if (step == SQLITE_ROW) {
|
||||||
|
pass_hash = hash_sha256(password, sqlite3_column_text(res, 1));
|
||||||
|
if (strcmp(pass_hash, sqlite3_column_text(res, 0)) == 0) {
|
||||||
|
send_msg(client, "230 User Logged in, Proceed.\r\n");
|
||||||
|
strncpy(client->password, password, 32);
|
||||||
|
} else {
|
||||||
|
send_msg(client, "530 Username or Password unacceptable.\r\n");
|
||||||
|
}
|
||||||
|
free(pass_hash);
|
||||||
|
sqlite3_finalize(res);
|
||||||
|
sqlite3_close(db);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
send_msg(client, "530 Username or Password unacceptable.\r\n");
|
||||||
|
sqlite3_finalize(res);
|
||||||
|
sqlite3_close(db);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_USER(struct ftpserver *cfg, struct ftpclient *client, char *username) {
|
||||||
|
strncpy(client->name, username, 16)
|
||||||
|
client->name[15] = '\0';
|
||||||
|
if (strcmp(client->name, "anonymous") == 0) {
|
||||||
|
send_msg(client, "331 Guest login ok, send your complete e-mail address as password.\r\n");
|
||||||
|
} else {
|
||||||
|
send_msg(client, "331 User name ok, need password.\r\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle_client(struct ftpserver *cfg, struct ftpclient *client, char *buf, int nbytes) {
|
||||||
|
|
||||||
|
char cmd[1024];
|
||||||
|
char argument[1024];
|
||||||
|
int i;
|
||||||
|
int cmd_len = 0;
|
||||||
|
int argument_len = 0;
|
||||||
|
int stage = 0;
|
||||||
|
|
||||||
|
for (i=0;i<nbytes;i++) {
|
||||||
|
if (stage == 0 && buf[i] != ' ') {
|
||||||
|
cmd[cmd_len++] = buf[i];
|
||||||
|
cmd[cmd_len] = '\0';
|
||||||
|
} else if (stage == 0 && buf[i] == ' ') {
|
||||||
|
stage = 1;
|
||||||
|
} else if (stage == 1) {
|
||||||
|
argument[argument_len++] = buf[i];
|
||||||
|
argument[argument_len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cmd, "USER") == 0) {
|
||||||
|
if (argument_len > 0) {
|
||||||
|
handle_USER(cfg, client, argument);
|
||||||
|
} else {
|
||||||
|
send_msg(client, "530 Missing username.\r\n")
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (strcmp(cmd, "PASS") == 0) {
|
||||||
|
if (argument_len > 0) {
|
||||||
|
handle_PASS(cfg, client, argument);
|
||||||
|
} else {
|
||||||
|
send_msg(client, "530 Username or Password not accepted.\r\n")
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (strcmp(cmd, "SYST") == 0) {
|
||||||
|
handle_SYST(cfg, client);
|
||||||
|
} else
|
||||||
|
if (strcmp(cmd, "PWD" == 0) {
|
||||||
|
handle_PWD(cfg, client);
|
||||||
|
} else
|
||||||
|
if (strcmp(cmd, "TYPE") == 0) {
|
||||||
|
handle_TYPE(cfg, client);
|
||||||
|
} else
|
||||||
|
if (strcmp(cmd, "CWD") == 0) {
|
||||||
|
if (argument_len > 0) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(struct ftpserver *cfg) {
|
||||||
|
int server_socket;
|
||||||
|
struct sockaddr_in server, client;
|
||||||
|
fd_set master, read_fds;
|
||||||
|
int fdmax = 0;
|
||||||
|
int c;
|
||||||
|
int i,j,k;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
server_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (server_socket == -1) {
|
||||||
|
fprintf(stderr, "Couldn't create socket..\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
server.sin_family = AF_INET;
|
||||||
|
server.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
server.sin_port = htons(cfg->port);
|
||||||
|
|
||||||
|
if (bind(server_socket, (struct sockaddr *)&server, sizeof(server)) < 0) {
|
||||||
|
perror("Bind Failed, Error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(server_socket, 3);
|
||||||
|
|
||||||
|
|
||||||
|
FD_ZERO(&master);
|
||||||
|
FD_SET(server_socket, &master);
|
||||||
|
fd_max = server_socket;
|
||||||
|
|
||||||
|
c = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
read_fds = master;
|
||||||
|
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
|
||||||
|
perror("select");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i <= fdmax; i++) {
|
||||||
|
if (FD_ISSET(i, &read_fds)) {
|
||||||
|
if (i == server_socket) {
|
||||||
|
new_fd = accept(server_socket, (struct sockaddr *)&client, (socklen_t *)&c);
|
||||||
|
if (new_fd == -1) {
|
||||||
|
perror("accept");
|
||||||
|
} else {
|
||||||
|
if (client_count == 0) {
|
||||||
|
clients = (struct ftpclient **)malloc(sizeof(struct ftpclient *));
|
||||||
|
} else {
|
||||||
|
clients = (struct ftpclient **)realloc(clients, sizeof(struct ftpclient *) * (client_count + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clients) {
|
||||||
|
fprintf(stderr, "Out of memory!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
clients[client_count] = (struct ftpclient *)malloc(sizeof(struct ftpclient));
|
||||||
|
|
||||||
|
if (!clients[client_count]) {
|
||||||
|
fprintf(stderr, "Out of memory!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
clients[client_count]->fd = new_fd;
|
||||||
|
strcpy(clients[client_count]->current_path, "/");
|
||||||
|
clients[client_count]->data_socket = -1;
|
||||||
|
clients[client_count]->data_srv_socket = -1;
|
||||||
|
clients[client_count]->type = 1;
|
||||||
|
clients[client_count]->status = 0;
|
||||||
|
clients[client_count]->data_port = 0;
|
||||||
|
memset(clients[client_count]->name, 0, 16);
|
||||||
|
memset(clients[client_count]->password, 0, 32);
|
||||||
|
|
||||||
|
client_count++;
|
||||||
|
|
||||||
|
FD_SET(new_fd, &master);
|
||||||
|
if (new_fd > fdmax) {
|
||||||
|
fdmax = new_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
send_msg(clients[client_count - 1], "220 magiftpd Ready\r\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
|
||||||
|
for (k=0;k<client_count;k++) {
|
||||||
|
if (clients[k]->fd == i) {
|
||||||
|
free(clients[k]);
|
||||||
|
|
||||||
|
for (j=k;j<client_count-1;j++) {
|
||||||
|
clients[j] = clients[j+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
client_count--;
|
||||||
|
|
||||||
|
if (client_count == 0) {
|
||||||
|
free(clients);
|
||||||
|
} else {
|
||||||
|
clients = realloc(clients, sizeof(struct ftpclient) * (client_count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(i); // bye!
|
||||||
|
FD_CLR(i, &master); // remove from master set
|
||||||
|
} else {
|
||||||
|
for (j=0;j<client_count;j++) {
|
||||||
|
if (clients[j]->fd == i) {
|
||||||
|
if (handle_client(cfg, clients[j], buf, nbytes) != 0) {
|
||||||
|
close(clients[j]->fd);
|
||||||
|
FD_CLR(i, &master); // remove from master set
|
||||||
|
free(clients[j]);
|
||||||
|
|
||||||
|
for (k=j;k<client_count-1;k++) {
|
||||||
|
clients[k] = clients[k+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
client_count--;
|
||||||
|
|
||||||
|
if (client_count == 0) {
|
||||||
|
free(clients);
|
||||||
|
} else {
|
||||||
|
clients = realloc(clients, sizeof(struct ftpclient) * (client_count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
struct ftpserver ftpsrv;
|
||||||
|
ftpsrv.port = 2121;
|
||||||
|
ftpsrv.userdb = NULL;
|
||||||
|
ftpsrv.fileroot = NULL;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "Usage: %s [config.ini]\n", argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ini_parse(argv[1], handler, &ftpsrv) <0) {
|
||||||
|
fprintf(stderr, "Unable to load configuration ini (%s)!\n", argv[1]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftpsrv.userdb == NULL || ftpsrv.fileroot == NULL) {
|
||||||
|
fprintf(stderr, "Missing configuration values.\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
init(&ftpsrv);
|
||||||
|
}
|
24
utils/magiftpd/magiftpd.h
Normal file
24
utils/magiftpd/magiftpd.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef __MAGIFTPD_H
|
||||||
|
#define __MAGIFTPD_H
|
||||||
|
|
||||||
|
struct ftpclient {
|
||||||
|
int fd;
|
||||||
|
int data_socket;
|
||||||
|
char current_path[PATH_MAX];
|
||||||
|
char data_ip[20];
|
||||||
|
int data_port;
|
||||||
|
int type;
|
||||||
|
// char ip[20];
|
||||||
|
char name[16];
|
||||||
|
char password[32];
|
||||||
|
int data_srv_socket;
|
||||||
|
int status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ftpserver {
|
||||||
|
int port;
|
||||||
|
char *fileroot;
|
||||||
|
char *userdb;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
4
utils/magiftpd/magiftpd.ini
Normal file
4
utils/magiftpd/magiftpd.ini
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[Main]
|
||||||
|
Port = 2121
|
||||||
|
Users DB = /home/andrew/MagickaBBS/users.sq3
|
||||||
|
File Root = /home/andrew/MagickaBBS/ftproot/
|
Reference in New Issue
Block a user