commit
75564de4ea
@ -10,7 +10,7 @@ OBJ = inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
magicka: $(OBJ)
|
||||
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -lssl -lcrypto
|
||||
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -lssl -lcrypto -lssh
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
@ -10,7 +10,7 @@ OBJ = inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
magicka: $(OBJ)
|
||||
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -ldl -lssl -lcrypto
|
||||
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/local/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -ldl -lssl -lcrypto -lssh
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
@ -10,7 +10,7 @@ OBJ = inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o doors.o bbs_list.o
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
magicka: $(OBJ)
|
||||
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/pkg/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -lssl -lcrypto
|
||||
$(CC) -o magicka -o $@ $^ $(CFLAGS) -L/usr/pkg/lib -lsqlite3 $(JAMLIB) $(ZMODEM) $(LUA) -lutil -lm -lssl -lcrypto -lssh
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
100
bbs.c
100
bbs.c
@ -15,17 +15,27 @@
|
||||
#include "lua/lualib.h"
|
||||
#include "lua/lauxlib.h"
|
||||
|
||||
int mynode;
|
||||
int mynode = 0;
|
||||
struct bbs_config conf;
|
||||
|
||||
struct user_record *gUser;
|
||||
int gSocket;
|
||||
|
||||
int sshBBS;
|
||||
int usertimeout;
|
||||
int timeoutpaused;
|
||||
|
||||
char *ipaddress;
|
||||
|
||||
void sigterm_handler2(int s)
|
||||
{
|
||||
if (mynode != 0) {
|
||||
disconnect("Terminated.");
|
||||
}
|
||||
dolog("Terminated...");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void dolog(char *fmt, ...) {
|
||||
char buffer[512];
|
||||
struct tm time_now;
|
||||
@ -145,12 +155,20 @@ void s_printf(char *fmt, ...) {
|
||||
}
|
||||
|
||||
void s_putchar(char c) {
|
||||
if (sshBBS) {
|
||||
putchar(c);
|
||||
} else {
|
||||
write(gSocket, &c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void s_putstring(char *c) {
|
||||
if (sshBBS) {
|
||||
printf("%s", c);
|
||||
} else {
|
||||
write(gSocket, c, strlen(c));
|
||||
}
|
||||
}
|
||||
|
||||
void s_displayansi_p(char *file) {
|
||||
FILE *fptr;
|
||||
@ -195,12 +213,17 @@ char s_getchar() {
|
||||
|
||||
do {
|
||||
|
||||
if (sshBBS) {
|
||||
c = getchar();
|
||||
} else {
|
||||
len = read(gSocket, &c, 1);
|
||||
|
||||
if (len == 0) {
|
||||
disconnect("Socket Closed");
|
||||
}
|
||||
}
|
||||
|
||||
if (!sshBBS) {
|
||||
while (c == 255) {
|
||||
len = read(gSocket, &c, 1);
|
||||
if (len == 0) {
|
||||
@ -218,16 +241,17 @@ char s_getchar() {
|
||||
disconnect("Socket Closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (c == '\r') {
|
||||
/* if (c == '\r') {
|
||||
if (len == 0) {
|
||||
disconnect("Socket Closed");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
} while (c == '\n');
|
||||
usertimeout = 10;
|
||||
|
||||
return (char)c;
|
||||
}
|
||||
|
||||
@ -299,7 +323,9 @@ void disconnect(char *calledby) {
|
||||
dolog("Node %d disconnected (%s)", mynode, calledby);
|
||||
sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, mynode);
|
||||
remove(buffer);
|
||||
if (!sshBBS) {
|
||||
close(gSocket);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -456,7 +482,7 @@ void automessage_display() {
|
||||
s_getc();
|
||||
}
|
||||
|
||||
void runbbs(int socket, char *ip) {
|
||||
void runbbs_real(int socket, char *ip, int ssh) {
|
||||
char buffer[256];
|
||||
char password[17];
|
||||
|
||||
@ -471,21 +497,33 @@ void runbbs(int socket, char *ip) {
|
||||
time_t now;
|
||||
struct itimerval itime;
|
||||
struct sigaction sa;
|
||||
struct sigaction st;
|
||||
lua_State *L;
|
||||
int do_internal_login = 0;
|
||||
|
||||
ipaddress = ip;
|
||||
|
||||
if (!ssh) {
|
||||
write(socket, iac_echo, 3);
|
||||
write(socket, iac_sga, 3);
|
||||
|
||||
gUser = NULL;
|
||||
sshBBS = 0;
|
||||
} else {
|
||||
sshBBS = 1;
|
||||
}
|
||||
|
||||
st.sa_handler = sigterm_handler2;
|
||||
sigemptyset(&st.sa_mask);
|
||||
if (sigaction(SIGTERM, &st, NULL) == -1) {
|
||||
dolog("Failed to setup sigterm handler.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gSocket = socket;
|
||||
|
||||
s_printf("Magicka BBS v%d.%d (%s), Loading...\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_STR);
|
||||
|
||||
// find out which node we are
|
||||
mynode = 0;
|
||||
for (i=1;i<=conf.nodes;i++) {
|
||||
sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i);
|
||||
if (stat(buffer, &s) != 0) {
|
||||
@ -506,7 +544,9 @@ void runbbs(int socket, char *ip) {
|
||||
|
||||
if (mynode == 0) {
|
||||
s_printf("Sorry, all nodes are in use. Please try later\r\n");
|
||||
if (!ssh) {
|
||||
close(socket);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -527,6 +567,7 @@ void runbbs(int socket, char *ip) {
|
||||
|
||||
s_displayansi("issue");
|
||||
|
||||
if (!ssh) {
|
||||
s_printf("\e[0mEnter your Login Name or NEW to create an account\r\n");
|
||||
s_printf("Login:> ");
|
||||
|
||||
@ -543,6 +584,8 @@ void runbbs(int socket, char *ip) {
|
||||
disconnect("Incorrect Login");
|
||||
}
|
||||
|
||||
gUser = user;
|
||||
|
||||
for (i=1;i<=conf.nodes;i++) {
|
||||
sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i);
|
||||
if (stat(buffer, &s) == 0) {
|
||||
@ -562,7 +605,36 @@ void runbbs(int socket, char *ip) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (gUser != NULL) {
|
||||
user = gUser;
|
||||
s_printf("\e[0mWelcome back %s. Press enter to log in...\r\n", gUser->loginname);
|
||||
s_getc();
|
||||
for (i=1;i<=conf.nodes;i++) {
|
||||
sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i);
|
||||
if (stat(buffer, &s) == 0) {
|
||||
nodefile = fopen(buffer, "r");
|
||||
if (!nodefile) {
|
||||
dolog("Error opening nodefile!");
|
||||
disconnect("Error opening nodefile!");
|
||||
}
|
||||
fgets(buffer, 256, nodefile);
|
||||
|
||||
if (strcasecmp(user->loginname, buffer) == 0) {
|
||||
fclose(nodefile);
|
||||
s_printf("\r\nYou are already logged in.\r\n");
|
||||
disconnect("Already Logged in");
|
||||
}
|
||||
fclose(nodefile);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_printf("\e[0mWelcome to %s! Press enter to create an account...\r\n", conf.bbs_name);
|
||||
s_getc();
|
||||
gUser = new_user();
|
||||
user = gUser;
|
||||
}
|
||||
}
|
||||
sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, mynode);
|
||||
nodefile = fopen(buffer, "w");
|
||||
if (!nodefile) {
|
||||
@ -588,7 +660,7 @@ void runbbs(int socket, char *ip) {
|
||||
user->laston = now;
|
||||
save_user(user);
|
||||
}
|
||||
gUser = user;
|
||||
|
||||
user->timeson++;
|
||||
|
||||
|
||||
@ -649,3 +721,13 @@ void runbbs(int socket, char *ip) {
|
||||
dolog("%s is logging out, on node %d", user->loginname, mynode);
|
||||
disconnect("Log out");
|
||||
}
|
||||
|
||||
void runbbs(int socket, char *ip) {
|
||||
runbbs_real(socket, ip, 0);
|
||||
}
|
||||
|
||||
void runbbs_ssh(char *ip) {
|
||||
setbuf(stdin, NULL);
|
||||
setbuf(stdout, NULL);
|
||||
runbbs_real(-1, ip, 1);
|
||||
}
|
||||
|
7
bbs.h
7
bbs.h
@ -90,6 +90,12 @@ struct bbs_config {
|
||||
char *echomail_sem;
|
||||
char *netmail_sem;
|
||||
char *default_tagline;
|
||||
int telnet_port;
|
||||
|
||||
int ssh_server;
|
||||
int ssh_port;
|
||||
char *ssh_dsa_key;
|
||||
char *ssh_rsa_key;
|
||||
|
||||
char *irc_server;
|
||||
int irc_port;
|
||||
@ -139,6 +145,7 @@ struct user_record {
|
||||
extern void automessage_write(struct user_record *user);
|
||||
extern void automessage_display();
|
||||
extern void dolog(char *fmt, ...);
|
||||
extern void runbbs_ssh(char *ipaddress);
|
||||
extern void runbbs(int sock, char *ipaddress);
|
||||
extern struct fido_addr *parse_fido_addr(const char *str);
|
||||
extern void s_putchar(char c);
|
||||
|
@ -12,6 +12,7 @@
|
||||
extern struct bbs_config conf;
|
||||
extern int mynode;
|
||||
extern int gSocket;
|
||||
extern int sshBBS;
|
||||
|
||||
static char **screenbuffer;
|
||||
static int chat_socket;
|
||||
@ -110,6 +111,14 @@ void chat_system(struct user_record *user) {
|
||||
char *message;
|
||||
char *sep;
|
||||
char *target;
|
||||
int chat_in;
|
||||
|
||||
if (sshBBS) {
|
||||
chat_in = STDIN_FILENO;
|
||||
} else {
|
||||
chat_in = gSocket;
|
||||
}
|
||||
|
||||
memset(inputbuffer, 0, 80);
|
||||
if (conf.irc_server == NULL) {
|
||||
s_putstring("\r\nSorry, Chat is not supported on this system.\r\n");
|
||||
@ -151,20 +160,20 @@ void chat_system(struct user_record *user) {
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(gSocket, &fds);
|
||||
FD_SET(chat_in, &fds);
|
||||
FD_SET(chat_socket, &fds);
|
||||
|
||||
if (chat_socket > gSocket) {
|
||||
if (chat_socket > chat_in) {
|
||||
t = chat_socket + 1;
|
||||
} else {
|
||||
t = gSocket + 1;
|
||||
t = chat_in + 1;
|
||||
}
|
||||
|
||||
ret = select(t, &fds, NULL, NULL, NULL);
|
||||
|
||||
if (ret > 0) {
|
||||
if (FD_ISSET(gSocket, &fds)) {
|
||||
len = read(gSocket, &c, 1);
|
||||
if (FD_ISSET(chat_in, &fds)) {
|
||||
len = read(chat_in, &c, 1);
|
||||
if (len == 0) {
|
||||
raw("QUIT\r\n");
|
||||
disconnect("Socket closed");
|
||||
|
@ -1,4 +1,5 @@
|
||||
[main]
|
||||
Telnet Port = 2023
|
||||
BBS Name = Magicka BBS
|
||||
Sysop Name = sysop
|
||||
nodes = 4
|
||||
@ -11,6 +12,10 @@ External Editor cmd = /home/andrew/MagickaBBS/doors/oedit.sh
|
||||
External Editor stdio = false
|
||||
Automessage Write Level = 10
|
||||
Fork = false
|
||||
Enable SSH = false
|
||||
SSH Port = 2024
|
||||
SSH DSA Key = /home/andrew/MagickaBBS/keys/ssh_host_dsa_key
|
||||
SSH RSA Key = /home/andrew/MagickaBBS/keys/ssh_rsa_key
|
||||
|
||||
[paths]
|
||||
PID File = /home/andrew/MagickaBBS/magicka.pid
|
||||
|
28
doors.c
28
doors.c
@ -23,6 +23,7 @@
|
||||
extern struct bbs_config conf;
|
||||
extern int mynode;
|
||||
extern int gSocket;
|
||||
extern int sshBBS;
|
||||
|
||||
int running_door_pid = 0;
|
||||
int running_door = 0;
|
||||
@ -140,6 +141,8 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
|
||||
int t;
|
||||
struct winsize ws;
|
||||
struct sigaction sa;
|
||||
int door_in;
|
||||
int door_out;
|
||||
|
||||
timeoutpaused = 1;
|
||||
|
||||
@ -148,11 +151,18 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
|
||||
}
|
||||
|
||||
if (stdio) {
|
||||
if (sshBBS) {
|
||||
door_in = STDIN_FILENO;
|
||||
door_out = STDOUT_FILENO;
|
||||
} else {
|
||||
door_in = gSocket;
|
||||
door_out = gSocket;
|
||||
}
|
||||
|
||||
arguments[0] = strdup(cmd);
|
||||
sprintf(buffer, "%d", mynode);
|
||||
arguments[1] = strdup(buffer);
|
||||
sprintf(buffer, "%d", gSocket);
|
||||
sprintf(buffer, "%d", door_out);
|
||||
arguments[2] = strdup(buffer);
|
||||
arguments[3] = NULL;
|
||||
|
||||
@ -192,16 +202,16 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
|
||||
while(running_door != 0) {
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(master, &fdset);
|
||||
FD_SET(gSocket, &fdset);
|
||||
if (master > gSocket) {
|
||||
FD_SET(door_in, &fdset);
|
||||
if (master > door_in) {
|
||||
t = master + 1;
|
||||
} else {
|
||||
t = gSocket + 1;
|
||||
t = door_in + 1;
|
||||
}
|
||||
ret = select(t, &fdset, NULL, NULL, NULL);
|
||||
if (ret > 0) {
|
||||
if (FD_ISSET(gSocket, &fdset)) {
|
||||
len = read(gSocket, &c, 1);
|
||||
if (FD_ISSET(door_in, &fdset)) {
|
||||
len = read(door_in, &c, 1);
|
||||
if (len == 0) {
|
||||
close(master);
|
||||
disconnect("Socket Closed");
|
||||
@ -217,7 +227,7 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
|
||||
close(master);
|
||||
break;
|
||||
}
|
||||
write(gSocket, &c, 1);
|
||||
write(door_out, &c, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -227,8 +237,12 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
|
||||
free(arguments[1]);
|
||||
free(arguments[2]);
|
||||
} else {
|
||||
if (!sshBBS) {
|
||||
sprintf(buffer, "%s %d %d", cmd, mynode, gSocket);
|
||||
system(buffer);
|
||||
} else {
|
||||
s_printf("Non-STDIO door support on SSH is currently broken...\r\n");
|
||||
}
|
||||
}
|
||||
timeoutpaused = 0;
|
||||
}
|
||||
|
63
files.c
63
files.c
@ -7,6 +7,7 @@
|
||||
#include <libgen.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
#include "Xmodem/zmodem.h"
|
||||
#include "bbs.h"
|
||||
#include "lua/lua.h"
|
||||
@ -14,6 +15,7 @@
|
||||
#include "lua/lauxlib.h"
|
||||
extern struct bbs_config conf;
|
||||
extern int gSocket;
|
||||
extern int sshBBS;
|
||||
|
||||
struct file_entry {
|
||||
char *filename;
|
||||
@ -25,11 +27,32 @@ struct file_entry {
|
||||
char **tagged_files;
|
||||
int tagged_count = 0;
|
||||
|
||||
int ttySetRaw(int fd, struct termios *prevTermios) {
|
||||
struct termios t;
|
||||
|
||||
if (tcgetattr(fd, &t) == -1)
|
||||
return -1;
|
||||
|
||||
if (prevTermios != NULL)
|
||||
*prevTermios = t;
|
||||
|
||||
t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO);
|
||||
t.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR | INPCK | ISTRIP | IXON | PARMRK);
|
||||
t.c_oflag &= ~OPOST;
|
||||
t.c_cc[VMIN] = 1;
|
||||
t.c_cc[VTIME] = 0;
|
||||
|
||||
if (tcsetattr(fd, TCSAFLUSH, &t) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ZXmitStr(u_char *str, int len, ZModem *info) {
|
||||
int i;
|
||||
|
||||
for (i=0;i<len;i++) {
|
||||
if (str[i] == 255) {
|
||||
if (str[i] == 255 && !sshBBS) {
|
||||
if (write(info->ofd, &str[i], 1) == 0) {
|
||||
return ZmErrSys;
|
||||
}
|
||||
@ -131,7 +154,7 @@ int doIO(ZModem *zm) {
|
||||
|
||||
pos = 0;
|
||||
for (j=0;j<len;j++) {
|
||||
if (buffer[j] == 255) {
|
||||
if (buffer[j] == 255 && !sshBBS) {
|
||||
if (buffer[j+1] == 255) {
|
||||
buffer2[pos] = 255;
|
||||
pos++;
|
||||
@ -168,9 +191,13 @@ void upload_zmodem(struct user_record *user) {
|
||||
zm.windowsize = 0;
|
||||
zm.bufsize = 0;
|
||||
|
||||
if (!sshBBS) {
|
||||
zm.ifd = gSocket;
|
||||
zm.ofd = gSocket;
|
||||
|
||||
} else {
|
||||
zm.ifd = STDIN_FILENO;
|
||||
zm.ofd = STDOUT_FILENO;
|
||||
}
|
||||
zm.zrinitflags = 0;
|
||||
zm.zsinitflags = 0;
|
||||
|
||||
@ -199,8 +226,17 @@ void upload(struct user_record *user) {
|
||||
int rc;
|
||||
struct stat s;
|
||||
char *err_msg = NULL;
|
||||
|
||||
struct termios oldit;
|
||||
struct termios oldot;
|
||||
if (sshBBS) {
|
||||
ttySetRaw(STDIN_FILENO, &oldit);
|
||||
ttySetRaw(STDOUT_FILENO, &oldot);
|
||||
}
|
||||
upload_zmodem(user);
|
||||
if (sshBBS) {
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldit);
|
||||
tcsetattr(STDOUT_FILENO, TCSANOW, &oldot);
|
||||
}
|
||||
|
||||
s_printf("\r\nPlease enter a description:\r\n");
|
||||
buffer[0] = '\0';
|
||||
@ -268,9 +304,13 @@ void download_zmodem(struct user_record *user, char *filename) {
|
||||
zm.windowsize = 0;
|
||||
zm.bufsize = 0;
|
||||
|
||||
if (!sshBBS) {
|
||||
zm.ifd = gSocket;
|
||||
zm.ofd = gSocket;
|
||||
|
||||
} else {
|
||||
zm.ifd = STDIN_FILENO;
|
||||
zm.ofd = STDOUT_FILENO;
|
||||
}
|
||||
zm.zrinitflags = 0;
|
||||
zm.zsinitflags = 0;
|
||||
|
||||
@ -328,8 +368,14 @@ void download(struct user_record *user) {
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *res;
|
||||
int rc;
|
||||
|
||||
struct termios oldit;
|
||||
struct termios oldot;
|
||||
if (sshBBS) {
|
||||
ttySetRaw(STDIN_FILENO, &oldit);
|
||||
ttySetRaw(STDOUT_FILENO, &oldot);
|
||||
}
|
||||
for (i=0;i<tagged_count;i++) {
|
||||
|
||||
download_zmodem(user, tagged_files[i]);
|
||||
|
||||
sprintf(buffer, "%s/%s.sq3", conf.bbs_path, conf.file_directories[user->cur_file_dir]->file_subs[user->cur_file_sub]->database);
|
||||
@ -377,6 +423,11 @@ void download(struct user_record *user) {
|
||||
sqlite3_close(db);
|
||||
}
|
||||
|
||||
if (sshBBS) {
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldit);
|
||||
tcsetattr(STDOUT_FILENO, TCSANOW, &oldot);
|
||||
}
|
||||
|
||||
for (i=0;i<tagged_count;i++) {
|
||||
free(tagged_files[i]);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ extern int mynode;
|
||||
extern struct bbs_config conf;
|
||||
|
||||
extern struct user_record *gUser;
|
||||
extern int gSocket;
|
||||
|
||||
int l_bbsWString(lua_State *L) {
|
||||
char *str = (char *)lua_tostring(L, -1);
|
||||
|
321
main.c
321
main.c
@ -10,14 +10,33 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/callbacks.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
#if defined(linux)
|
||||
# include <pty.h>
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
# include <util.h>
|
||||
#else
|
||||
# include <libutil.h>
|
||||
#endif
|
||||
#include <termios.h>
|
||||
#include "bbs.h"
|
||||
#include "inih/ini.h"
|
||||
|
||||
extern struct bbs_config conf;
|
||||
extern struct user_record *gUser;
|
||||
|
||||
int ssh_pid = -1;
|
||||
int bbs_pid = 0;
|
||||
|
||||
void sigterm_handler(int s)
|
||||
{
|
||||
if (ssh_pid != -1) {
|
||||
kill(ssh_pid, SIGTERM);
|
||||
}
|
||||
remove(conf.pid_file);
|
||||
exit(0);
|
||||
}
|
||||
@ -228,6 +247,20 @@ static int handler(void* user, const char* section, const char* name,
|
||||
if (strcasecmp(section, "main") == 0) {
|
||||
if (strcasecmp(name, "bbs name") == 0) {
|
||||
conf->bbs_name = strdup(value);
|
||||
} else if (strcasecmp(name, "telnet port") == 0) {
|
||||
conf->telnet_port = atoi(value);
|
||||
} else if (strcasecmp(name, "enable ssh") == 0) {
|
||||
if (strcasecmp(value, "true") == 0) {
|
||||
conf->ssh_server = 1;
|
||||
} else {
|
||||
conf->ssh_server = 0;
|
||||
}
|
||||
} else if (strcasecmp(name, "ssh port") == 0) {
|
||||
conf->ssh_port = atoi(value);
|
||||
} else if (strcasecmp(name, "ssh dsa key") == 0) {
|
||||
conf->ssh_dsa_key = strdup(value);
|
||||
} else if (strcasecmp(name, "ssh rsa key") == 0) {
|
||||
conf->ssh_rsa_key = strdup(value);
|
||||
} else if (strcasecmp(name, "sysop name") == 0) {
|
||||
conf->sysop_name = strdup(value);
|
||||
} else if (strcasecmp(name, "nodes") == 0) {
|
||||
@ -318,6 +351,268 @@ static int handler(void* user, const char* section, const char* name,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssh_authenticate(ssh_session p_ssh_session) {
|
||||
ssh_message message;
|
||||
char *username;
|
||||
char *password;
|
||||
|
||||
do {
|
||||
message = ssh_message_get(p_ssh_session);
|
||||
switch(ssh_message_type(message)) {
|
||||
case SSH_REQUEST_AUTH:
|
||||
switch(ssh_message_subtype(message)) {
|
||||
case SSH_AUTH_METHOD_PASSWORD:
|
||||
username = ssh_message_auth_user(message);
|
||||
password = ssh_message_auth_password(message);
|
||||
|
||||
if (strcasecmp(username, "new") == 0 && strcasecmp(password, "new") == 0) {
|
||||
ssh_message_auth_reply_success(message, 0);
|
||||
ssh_message_free(message);
|
||||
gUser = NULL;
|
||||
return 1;
|
||||
}
|
||||
gUser = check_user_pass(username, password);
|
||||
if (gUser != NULL) {
|
||||
ssh_message_auth_reply_success(message, 0);
|
||||
ssh_message_free(message);
|
||||
return 1;
|
||||
}
|
||||
ssh_message_free(message);
|
||||
return 0;
|
||||
case SSH_AUTH_METHOD_NONE:
|
||||
default:
|
||||
ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE);
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE);
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while(1);
|
||||
}
|
||||
|
||||
char *ssh_getip(ssh_session session) {
|
||||
struct sockaddr_storage tmp;
|
||||
struct sockaddr_in *sock;
|
||||
unsigned int len = 100;
|
||||
char ip[100] = "\0";
|
||||
|
||||
getpeername(ssh_get_fd(session), (struct sockaddr*)&tmp, &len);
|
||||
sock = (struct sockaddr_in *)&tmp;
|
||||
inet_ntop(AF_INET, &sock->sin_addr, ip, len);
|
||||
|
||||
return strdup(ip);
|
||||
}
|
||||
|
||||
static int ssh_copy_fd_to_chan(socket_t fd, int revents, void *userdata) {
|
||||
ssh_channel chan = (ssh_channel)userdata;
|
||||
char buf[2048];
|
||||
int sz = 0;
|
||||
|
||||
if(!chan) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if(revents & POLLIN) {
|
||||
sz = read(fd, buf, 2048);
|
||||
if(sz > 0) {
|
||||
ssh_channel_write(chan, buf, sz);
|
||||
}
|
||||
}
|
||||
if(revents & POLLHUP) {
|
||||
ssh_channel_close(chan);
|
||||
sz = -1;
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
static int ssh_copy_chan_to_fd(ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *data,
|
||||
uint32_t len,
|
||||
int is_stderr,
|
||||
void *userdata) {
|
||||
int fd = *(int*)userdata;
|
||||
int sz;
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)is_stderr;
|
||||
|
||||
sz = write(fd, data, len);
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void ssh_chan_close(ssh_session session, ssh_channel channel, void *userdata) {
|
||||
int fd = *(int*)userdata;
|
||||
(void)session;
|
||||
(void)channel;
|
||||
kill(bbs_pid, SIGTERM);
|
||||
sleep(10);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
struct ssh_channel_callbacks_struct ssh_cb = {
|
||||
.channel_data_function = ssh_copy_chan_to_fd,
|
||||
.channel_eof_function = ssh_chan_close,
|
||||
.channel_close_function = ssh_chan_close,
|
||||
.userdata = NULL
|
||||
};
|
||||
|
||||
void serverssh(int port) {
|
||||
ssh_session p_ssh_session;
|
||||
ssh_bind p_ssh_bind;
|
||||
int err;
|
||||
int pid;
|
||||
int shell = 0;
|
||||
int fd;
|
||||
ssh_channel chan = 0;
|
||||
char *ip;
|
||||
ssh_event event;
|
||||
short events;
|
||||
ssh_message message;
|
||||
struct termios tios;
|
||||
|
||||
|
||||
err = ssh_init();
|
||||
if (err == -1) {
|
||||
fprintf(stderr, "Error starting SSH server.\n");
|
||||
exit(-1);
|
||||
}
|
||||
p_ssh_session = ssh_new();
|
||||
if (p_ssh_session == NULL) {
|
||||
fprintf(stderr, "Error starting SSH server.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
p_ssh_bind = ssh_bind_new();
|
||||
if (p_ssh_bind == NULL) {
|
||||
fprintf(stderr, "Error starting SSH server.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ssh_bind_options_set(p_ssh_bind, SSH_BIND_OPTIONS_BINDPORT, &port);
|
||||
ssh_bind_options_set(p_ssh_bind, SSH_BIND_OPTIONS_DSAKEY, conf.ssh_dsa_key);
|
||||
ssh_bind_options_set(p_ssh_bind, SSH_BIND_OPTIONS_RSAKEY, conf.ssh_rsa_key);
|
||||
|
||||
ssh_bind_listen(p_ssh_bind);
|
||||
|
||||
while (1) {
|
||||
if (ssh_bind_accept(p_ssh_bind, p_ssh_session) == SSH_OK) {
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
if (ssh_handle_key_exchange(p_ssh_session)) {
|
||||
exit(-1);
|
||||
}
|
||||
if (ssh_authenticate(p_ssh_session) == 1) {
|
||||
do {
|
||||
message = ssh_message_get(p_ssh_session);
|
||||
if (message) {
|
||||
|
||||
if (ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN && ssh_message_subtype(message) == SSH_CHANNEL_SESSION) {
|
||||
chan = ssh_message_channel_request_open_reply_accept(message);
|
||||
ssh_message_free(message);
|
||||
break;
|
||||
} else {
|
||||
ssh_message_reply_default(message);
|
||||
ssh_message_free(message);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(!chan);
|
||||
if (!chan) {
|
||||
fprintf(stderr, "Failed to get channel\n");
|
||||
ssh_finalize();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
do {
|
||||
message = ssh_message_get(p_ssh_session);
|
||||
if (message) {
|
||||
if (ssh_message_type(message) == SSH_REQUEST_CHANNEL) {
|
||||
if (ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) {
|
||||
shell = 1;
|
||||
ssh_message_channel_request_reply_success(message);
|
||||
ssh_message_free(message);
|
||||
break;
|
||||
} else if (ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_PTY) {
|
||||
ssh_message_channel_request_reply_success(message);
|
||||
ssh_message_free(message);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (!shell);
|
||||
|
||||
if (!shell) {
|
||||
fprintf(stderr, "Failed to get shell\n");
|
||||
ssh_finalize();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ip = ssh_getip(p_ssh_session);
|
||||
|
||||
|
||||
|
||||
bbs_pid = forkpty(&fd, NULL, NULL, NULL);
|
||||
if (bbs_pid == 0) {
|
||||
tcgetattr(STDIN_FILENO, &tios);
|
||||
tios.c_lflag &= ~(ICANON | ECHO | ECHONL);
|
||||
tios.c_iflag &= INLCR;
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios);
|
||||
runbbs_ssh(ip);
|
||||
exit(0);
|
||||
}
|
||||
free(ip);
|
||||
ssh_cb.userdata = &fd;
|
||||
ssh_callbacks_init(&ssh_cb);
|
||||
ssh_set_channel_callbacks(chan, &ssh_cb);
|
||||
|
||||
events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
|
||||
|
||||
event = ssh_event_new();
|
||||
if(event == NULL) {
|
||||
ssh_finalize();
|
||||
exit(0);
|
||||
}
|
||||
if(ssh_event_add_fd(event, fd, events, ssh_copy_fd_to_chan, chan) != SSH_OK) {
|
||||
ssh_finalize();
|
||||
exit(0);
|
||||
}
|
||||
if(ssh_event_add_session(event, p_ssh_session) != SSH_OK) {
|
||||
ssh_finalize();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
do {
|
||||
ssh_event_dopoll(event, 1000);
|
||||
} while(!ssh_channel_is_closed(chan));
|
||||
|
||||
ssh_event_remove_fd(event, fd);
|
||||
|
||||
ssh_event_remove_session(event, p_ssh_session);
|
||||
|
||||
ssh_event_free(event);
|
||||
}
|
||||
ssh_disconnect(p_ssh_session);
|
||||
ssh_finalize();
|
||||
|
||||
exit(0);
|
||||
} else if (pid > 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void server(int port) {
|
||||
struct sigaction sa;
|
||||
struct sigaction st;
|
||||
@ -342,6 +637,19 @@ void server(int port) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (conf.ssh_server) {
|
||||
// fork ssh server
|
||||
ssh_pid = fork();
|
||||
|
||||
if (ssh_pid > 0) {
|
||||
serverssh(conf.ssh_port);
|
||||
exit(0);
|
||||
}
|
||||
if (ssh_pid != 0) {
|
||||
fprintf(stderr, "Error forking ssh server.");
|
||||
}
|
||||
}
|
||||
|
||||
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (socket_desc == -1) {
|
||||
remove(conf.pid_file);
|
||||
@ -390,15 +698,13 @@ void server(int port) {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int port;
|
||||
|
||||
int i;
|
||||
int main_pid;
|
||||
FILE *fptr;
|
||||
struct stat s;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Usage ./magicka config/bbs.ini port\n");
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage ./magicka config/bbs.ini\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -414,6 +720,7 @@ int main(int argc, char **argv) {
|
||||
conf.automsgwritelvl = 10;
|
||||
conf.echomail_sem = NULL;
|
||||
conf.netmail_sem = NULL;
|
||||
conf.telnet_port = 0;
|
||||
|
||||
// Load BBS data
|
||||
if (ini_parse(argv[1], handler, &conf) <0) {
|
||||
@ -440,8 +747,6 @@ int main(int argc, char **argv) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
port = atoi(argv[2]);
|
||||
|
||||
if (conf.fork) {
|
||||
if (stat(conf.pid_file, &s) == 0) {
|
||||
fprintf(stderr, "Magicka already running or stale pid file at: %s\n", conf.pid_file);
|
||||
@ -463,9 +768,9 @@ int main(int argc, char **argv) {
|
||||
fclose(fptr);
|
||||
}
|
||||
} else {
|
||||
server(port);
|
||||
server(conf.telnet_port);
|
||||
}
|
||||
} else {
|
||||
server(port);
|
||||
server(conf.telnet_port);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user