Merge pull request #3 from apamment/ssh

Merge SSH
This commit is contained in:
Andrew Pamment 2016-08-07 17:38:07 +10:00 committed by GitHub
commit 75564de4ea
11 changed files with 585 additions and 113 deletions

View File

@ -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) $(CC) -c -o $@ $< $(CFLAGS)
magicka: $(OBJ) 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 .PHONY: clean

View File

@ -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) $(CC) -c -o $@ $< $(CFLAGS)
magicka: $(OBJ) 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 .PHONY: clean

View File

@ -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) $(CC) -c -o $@ $< $(CFLAGS)
magicka: $(OBJ) 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 .PHONY: clean

100
bbs.c
View File

@ -15,17 +15,27 @@
#include "lua/lualib.h" #include "lua/lualib.h"
#include "lua/lauxlib.h" #include "lua/lauxlib.h"
int mynode; int mynode = 0;
struct bbs_config conf; struct bbs_config conf;
struct user_record *gUser; struct user_record *gUser;
int gSocket; int gSocket;
int sshBBS;
int usertimeout; int usertimeout;
int timeoutpaused; int timeoutpaused;
char *ipaddress; char *ipaddress;
void sigterm_handler2(int s)
{
if (mynode != 0) {
disconnect("Terminated.");
}
dolog("Terminated...");
exit(0);
}
void dolog(char *fmt, ...) { void dolog(char *fmt, ...) {
char buffer[512]; char buffer[512];
struct tm time_now; struct tm time_now;
@ -145,12 +155,20 @@ void s_printf(char *fmt, ...) {
} }
void s_putchar(char c) { void s_putchar(char c) {
if (sshBBS) {
putchar(c);
} else {
write(gSocket, &c, 1); write(gSocket, &c, 1);
} }
}
void s_putstring(char *c) { void s_putstring(char *c) {
if (sshBBS) {
printf("%s", c);
} else {
write(gSocket, c, strlen(c)); write(gSocket, c, strlen(c));
} }
}
void s_displayansi_p(char *file) { void s_displayansi_p(char *file) {
FILE *fptr; FILE *fptr;
@ -195,12 +213,17 @@ char s_getchar() {
do { do {
if (sshBBS) {
c = getchar();
} else {
len = read(gSocket, &c, 1); len = read(gSocket, &c, 1);
if (len == 0) { if (len == 0) {
disconnect("Socket Closed"); disconnect("Socket Closed");
} }
}
if (!sshBBS) {
while (c == 255) { while (c == 255) {
len = read(gSocket, &c, 1); len = read(gSocket, &c, 1);
if (len == 0) { if (len == 0) {
@ -218,16 +241,17 @@ char s_getchar() {
disconnect("Socket Closed"); disconnect("Socket Closed");
} }
} }
}
/* if (c == '\r') {
if (c == '\r') {
if (len == 0) { if (len == 0) {
disconnect("Socket Closed"); disconnect("Socket Closed");
} }
} }*/
} while (c == '\n'); } while (c == '\n');
usertimeout = 10; usertimeout = 10;
return (char)c; return (char)c;
} }
@ -299,7 +323,9 @@ void disconnect(char *calledby) {
dolog("Node %d disconnected (%s)", mynode, calledby); dolog("Node %d disconnected (%s)", mynode, calledby);
sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, mynode); sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, mynode);
remove(buffer); remove(buffer);
if (!sshBBS) {
close(gSocket); close(gSocket);
}
exit(0); exit(0);
} }
@ -456,7 +482,7 @@ void automessage_display() {
s_getc(); s_getc();
} }
void runbbs(int socket, char *ip) { void runbbs_real(int socket, char *ip, int ssh) {
char buffer[256]; char buffer[256];
char password[17]; char password[17];
@ -471,21 +497,33 @@ void runbbs(int socket, char *ip) {
time_t now; time_t now;
struct itimerval itime; struct itimerval itime;
struct sigaction sa; struct sigaction sa;
struct sigaction st;
lua_State *L; lua_State *L;
int do_internal_login = 0; int do_internal_login = 0;
ipaddress = ip; ipaddress = ip;
if (!ssh) {
write(socket, iac_echo, 3); write(socket, iac_echo, 3);
write(socket, iac_sga, 3); write(socket, iac_sga, 3);
gUser = NULL; 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; gSocket = socket;
s_printf("Magicka BBS v%d.%d (%s), Loading...\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_STR); s_printf("Magicka BBS v%d.%d (%s), Loading...\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_STR);
// find out which node we are // find out which node we are
mynode = 0;
for (i=1;i<=conf.nodes;i++) { for (i=1;i<=conf.nodes;i++) {
sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i); sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i);
if (stat(buffer, &s) != 0) { if (stat(buffer, &s) != 0) {
@ -506,7 +544,9 @@ void runbbs(int socket, char *ip) {
if (mynode == 0) { if (mynode == 0) {
s_printf("Sorry, all nodes are in use. Please try later\r\n"); s_printf("Sorry, all nodes are in use. Please try later\r\n");
if (!ssh) {
close(socket); close(socket);
}
exit(1); exit(1);
} }
@ -527,6 +567,7 @@ void runbbs(int socket, char *ip) {
s_displayansi("issue"); s_displayansi("issue");
if (!ssh) {
s_printf("\e[0mEnter your Login Name or NEW to create an account\r\n"); s_printf("\e[0mEnter your Login Name or NEW to create an account\r\n");
s_printf("Login:> "); s_printf("Login:> ");
@ -543,6 +584,8 @@ void runbbs(int socket, char *ip) {
disconnect("Incorrect Login"); disconnect("Incorrect Login");
} }
gUser = user;
for (i=1;i<=conf.nodes;i++) { for (i=1;i<=conf.nodes;i++) {
sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i); sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i);
if (stat(buffer, &s) == 0) { 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); sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, mynode);
nodefile = fopen(buffer, "w"); nodefile = fopen(buffer, "w");
if (!nodefile) { if (!nodefile) {
@ -588,7 +660,7 @@ void runbbs(int socket, char *ip) {
user->laston = now; user->laston = now;
save_user(user); save_user(user);
} }
gUser = user;
user->timeson++; user->timeson++;
@ -649,3 +721,13 @@ void runbbs(int socket, char *ip) {
dolog("%s is logging out, on node %d", user->loginname, mynode); dolog("%s is logging out, on node %d", user->loginname, mynode);
disconnect("Log out"); 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
View File

@ -90,6 +90,12 @@ struct bbs_config {
char *echomail_sem; char *echomail_sem;
char *netmail_sem; char *netmail_sem;
char *default_tagline; char *default_tagline;
int telnet_port;
int ssh_server;
int ssh_port;
char *ssh_dsa_key;
char *ssh_rsa_key;
char *irc_server; char *irc_server;
int irc_port; int irc_port;
@ -139,6 +145,7 @@ struct user_record {
extern void automessage_write(struct user_record *user); extern void automessage_write(struct user_record *user);
extern void automessage_display(); extern void automessage_display();
extern void dolog(char *fmt, ...); extern void dolog(char *fmt, ...);
extern void runbbs_ssh(char *ipaddress);
extern void runbbs(int sock, char *ipaddress); extern void runbbs(int sock, char *ipaddress);
extern struct fido_addr *parse_fido_addr(const char *str); extern struct fido_addr *parse_fido_addr(const char *str);
extern void s_putchar(char c); extern void s_putchar(char c);

View File

@ -12,6 +12,7 @@
extern struct bbs_config conf; extern struct bbs_config conf;
extern int mynode; extern int mynode;
extern int gSocket; extern int gSocket;
extern int sshBBS;
static char **screenbuffer; static char **screenbuffer;
static int chat_socket; static int chat_socket;
@ -110,6 +111,14 @@ void chat_system(struct user_record *user) {
char *message; char *message;
char *sep; char *sep;
char *target; char *target;
int chat_in;
if (sshBBS) {
chat_in = STDIN_FILENO;
} else {
chat_in = gSocket;
}
memset(inputbuffer, 0, 80); memset(inputbuffer, 0, 80);
if (conf.irc_server == NULL) { if (conf.irc_server == NULL) {
s_putstring("\r\nSorry, Chat is not supported on this system.\r\n"); 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) { while (1) {
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(gSocket, &fds); FD_SET(chat_in, &fds);
FD_SET(chat_socket, &fds); FD_SET(chat_socket, &fds);
if (chat_socket > gSocket) { if (chat_socket > chat_in) {
t = chat_socket + 1; t = chat_socket + 1;
} else { } else {
t = gSocket + 1; t = chat_in + 1;
} }
ret = select(t, &fds, NULL, NULL, NULL); ret = select(t, &fds, NULL, NULL, NULL);
if (ret > 0) { if (ret > 0) {
if (FD_ISSET(gSocket, &fds)) { if (FD_ISSET(chat_in, &fds)) {
len = read(gSocket, &c, 1); len = read(chat_in, &c, 1);
if (len == 0) { if (len == 0) {
raw("QUIT\r\n"); raw("QUIT\r\n");
disconnect("Socket closed"); disconnect("Socket closed");

View File

@ -1,4 +1,5 @@
[main] [main]
Telnet Port = 2023
BBS Name = Magicka BBS BBS Name = Magicka BBS
Sysop Name = sysop Sysop Name = sysop
nodes = 4 nodes = 4
@ -11,6 +12,10 @@ External Editor cmd = /home/andrew/MagickaBBS/doors/oedit.sh
External Editor stdio = false External Editor stdio = false
Automessage Write Level = 10 Automessage Write Level = 10
Fork = false 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] [paths]
PID File = /home/andrew/MagickaBBS/magicka.pid PID File = /home/andrew/MagickaBBS/magicka.pid

28
doors.c
View File

@ -23,6 +23,7 @@
extern struct bbs_config conf; extern struct bbs_config conf;
extern int mynode; extern int mynode;
extern int gSocket; extern int gSocket;
extern int sshBBS;
int running_door_pid = 0; int running_door_pid = 0;
int running_door = 0; int running_door = 0;
@ -140,6 +141,8 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
int t; int t;
struct winsize ws; struct winsize ws;
struct sigaction sa; struct sigaction sa;
int door_in;
int door_out;
timeoutpaused = 1; timeoutpaused = 1;
@ -148,11 +151,18 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
} }
if (stdio) { if (stdio) {
if (sshBBS) {
door_in = STDIN_FILENO;
door_out = STDOUT_FILENO;
} else {
door_in = gSocket;
door_out = gSocket;
}
arguments[0] = strdup(cmd); arguments[0] = strdup(cmd);
sprintf(buffer, "%d", mynode); sprintf(buffer, "%d", mynode);
arguments[1] = strdup(buffer); arguments[1] = strdup(buffer);
sprintf(buffer, "%d", gSocket); sprintf(buffer, "%d", door_out);
arguments[2] = strdup(buffer); arguments[2] = strdup(buffer);
arguments[3] = NULL; arguments[3] = NULL;
@ -192,16 +202,16 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
while(running_door != 0) { while(running_door != 0) {
FD_ZERO(&fdset); FD_ZERO(&fdset);
FD_SET(master, &fdset); FD_SET(master, &fdset);
FD_SET(gSocket, &fdset); FD_SET(door_in, &fdset);
if (master > gSocket) { if (master > door_in) {
t = master + 1; t = master + 1;
} else { } else {
t = gSocket + 1; t = door_in + 1;
} }
ret = select(t, &fdset, NULL, NULL, NULL); ret = select(t, &fdset, NULL, NULL, NULL);
if (ret > 0) { if (ret > 0) {
if (FD_ISSET(gSocket, &fdset)) { if (FD_ISSET(door_in, &fdset)) {
len = read(gSocket, &c, 1); len = read(door_in, &c, 1);
if (len == 0) { if (len == 0) {
close(master); close(master);
disconnect("Socket Closed"); disconnect("Socket Closed");
@ -217,7 +227,7 @@ void rundoor(struct user_record *user, char *cmd, int stdio) {
close(master); close(master);
break; 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[1]);
free(arguments[2]); free(arguments[2]);
} else { } else {
if (!sshBBS) {
sprintf(buffer, "%s %d %d", cmd, mynode, gSocket); sprintf(buffer, "%s %d %d", cmd, mynode, gSocket);
system(buffer); system(buffer);
} else {
s_printf("Non-STDIO door support on SSH is currently broken...\r\n");
}
} }
timeoutpaused = 0; timeoutpaused = 0;
} }

63
files.c
View File

@ -7,6 +7,7 @@
#include <libgen.h> #include <libgen.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <termios.h>
#include "Xmodem/zmodem.h" #include "Xmodem/zmodem.h"
#include "bbs.h" #include "bbs.h"
#include "lua/lua.h" #include "lua/lua.h"
@ -14,6 +15,7 @@
#include "lua/lauxlib.h" #include "lua/lauxlib.h"
extern struct bbs_config conf; extern struct bbs_config conf;
extern int gSocket; extern int gSocket;
extern int sshBBS;
struct file_entry { struct file_entry {
char *filename; char *filename;
@ -25,11 +27,32 @@ struct file_entry {
char **tagged_files; char **tagged_files;
int tagged_count = 0; 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 ZXmitStr(u_char *str, int len, ZModem *info) {
int i; int i;
for (i=0;i<len;i++) { for (i=0;i<len;i++) {
if (str[i] == 255) { if (str[i] == 255 && !sshBBS) {
if (write(info->ofd, &str[i], 1) == 0) { if (write(info->ofd, &str[i], 1) == 0) {
return ZmErrSys; return ZmErrSys;
} }
@ -131,7 +154,7 @@ int doIO(ZModem *zm) {
pos = 0; pos = 0;
for (j=0;j<len;j++) { for (j=0;j<len;j++) {
if (buffer[j] == 255) { if (buffer[j] == 255 && !sshBBS) {
if (buffer[j+1] == 255) { if (buffer[j+1] == 255) {
buffer2[pos] = 255; buffer2[pos] = 255;
pos++; pos++;
@ -168,9 +191,13 @@ void upload_zmodem(struct user_record *user) {
zm.windowsize = 0; zm.windowsize = 0;
zm.bufsize = 0; zm.bufsize = 0;
if (!sshBBS) {
zm.ifd = gSocket; zm.ifd = gSocket;
zm.ofd = gSocket; zm.ofd = gSocket;
} else {
zm.ifd = STDIN_FILENO;
zm.ofd = STDOUT_FILENO;
}
zm.zrinitflags = 0; zm.zrinitflags = 0;
zm.zsinitflags = 0; zm.zsinitflags = 0;
@ -199,8 +226,17 @@ void upload(struct user_record *user) {
int rc; int rc;
struct stat s; struct stat s;
char *err_msg = NULL; char *err_msg = NULL;
struct termios oldit;
struct termios oldot;
if (sshBBS) {
ttySetRaw(STDIN_FILENO, &oldit);
ttySetRaw(STDOUT_FILENO, &oldot);
}
upload_zmodem(user); upload_zmodem(user);
if (sshBBS) {
tcsetattr(STDIN_FILENO, TCSANOW, &oldit);
tcsetattr(STDOUT_FILENO, TCSANOW, &oldot);
}
s_printf("\r\nPlease enter a description:\r\n"); s_printf("\r\nPlease enter a description:\r\n");
buffer[0] = '\0'; buffer[0] = '\0';
@ -268,9 +304,13 @@ void download_zmodem(struct user_record *user, char *filename) {
zm.windowsize = 0; zm.windowsize = 0;
zm.bufsize = 0; zm.bufsize = 0;
if (!sshBBS) {
zm.ifd = gSocket; zm.ifd = gSocket;
zm.ofd = gSocket; zm.ofd = gSocket;
} else {
zm.ifd = STDIN_FILENO;
zm.ofd = STDOUT_FILENO;
}
zm.zrinitflags = 0; zm.zrinitflags = 0;
zm.zsinitflags = 0; zm.zsinitflags = 0;
@ -328,8 +368,14 @@ void download(struct user_record *user) {
sqlite3 *db; sqlite3 *db;
sqlite3_stmt *res; sqlite3_stmt *res;
int rc; 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++) { for (i=0;i<tagged_count;i++) {
download_zmodem(user, tagged_files[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); 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); sqlite3_close(db);
} }
if (sshBBS) {
tcsetattr(STDIN_FILENO, TCSANOW, &oldit);
tcsetattr(STDOUT_FILENO, TCSANOW, &oldot);
}
for (i=0;i<tagged_count;i++) { for (i=0;i<tagged_count;i++) {
free(tagged_files[i]); free(tagged_files[i]);
} }

View File

@ -7,7 +7,6 @@ extern int mynode;
extern struct bbs_config conf; extern struct bbs_config conf;
extern struct user_record *gUser; extern struct user_record *gUser;
extern int gSocket;
int l_bbsWString(lua_State *L) { int l_bbsWString(lua_State *L) {
char *str = (char *)lua_tostring(L, -1); char *str = (char *)lua_tostring(L, -1);

321
main.c
View File

@ -10,14 +10,33 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <libssh/callbacks.h>
#include <string.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 "bbs.h"
#include "inih/ini.h" #include "inih/ini.h"
extern struct bbs_config conf; extern struct bbs_config conf;
extern struct user_record *gUser;
int ssh_pid = -1;
int bbs_pid = 0;
void sigterm_handler(int s) void sigterm_handler(int s)
{ {
if (ssh_pid != -1) {
kill(ssh_pid, SIGTERM);
}
remove(conf.pid_file); remove(conf.pid_file);
exit(0); exit(0);
} }
@ -228,6 +247,20 @@ static int handler(void* user, const char* section, const char* name,
if (strcasecmp(section, "main") == 0) { if (strcasecmp(section, "main") == 0) {
if (strcasecmp(name, "bbs name") == 0) { if (strcasecmp(name, "bbs name") == 0) {
conf->bbs_name = strdup(value); 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) { } else if (strcasecmp(name, "sysop name") == 0) {
conf->sysop_name = strdup(value); conf->sysop_name = strdup(value);
} else if (strcasecmp(name, "nodes") == 0) { } else if (strcasecmp(name, "nodes") == 0) {
@ -318,6 +351,268 @@ static int handler(void* user, const char* section, const char* name,
return 1; 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) { void server(int port) {
struct sigaction sa; struct sigaction sa;
struct sigaction st; struct sigaction st;
@ -342,6 +637,19 @@ void server(int port) {
exit(1); 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); socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) { if (socket_desc == -1) {
remove(conf.pid_file); remove(conf.pid_file);
@ -390,15 +698,13 @@ void server(int port) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int port;
int i; int i;
int main_pid; int main_pid;
FILE *fptr; FILE *fptr;
struct stat s; struct stat s;
if (argc < 3) { if (argc < 2) {
fprintf(stderr, "Usage ./magicka config/bbs.ini port\n"); fprintf(stderr, "Usage ./magicka config/bbs.ini\n");
exit(1); exit(1);
} }
@ -414,6 +720,7 @@ int main(int argc, char **argv) {
conf.automsgwritelvl = 10; conf.automsgwritelvl = 10;
conf.echomail_sem = NULL; conf.echomail_sem = NULL;
conf.netmail_sem = NULL; conf.netmail_sem = NULL;
conf.telnet_port = 0;
// Load BBS data // Load BBS data
if (ini_parse(argv[1], handler, &conf) <0) { if (ini_parse(argv[1], handler, &conf) <0) {
@ -440,8 +747,6 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
port = atoi(argv[2]);
if (conf.fork) { if (conf.fork) {
if (stat(conf.pid_file, &s) == 0) { if (stat(conf.pid_file, &s) == 0) {
fprintf(stderr, "Magicka already running or stale pid file at: %s\n", conf.pid_file); 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); fclose(fptr);
} }
} else { } else {
server(port); server(conf.telnet_port);
} }
} else { } else {
server(port); server(conf.telnet_port);
} }
} }