diff --git a/Makefile.freebsd b/Makefile.freebsd index 2e7cb11..a46a2e5 100644 --- a/Makefile.freebsd +++ b/Makefile.freebsd @@ -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 diff --git a/Makefile.linux b/Makefile.linux index ef09a42..c602ab8 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -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 diff --git a/Makefile.minix b/Makefile.minix index f8459dc..fce46fc 100644 --- a/Makefile.minix +++ b/Makefile.minix @@ -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 diff --git a/bbs.c b/bbs.c index 2d2f616..69b9c86 100644 --- a/bbs.c +++ b/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; - +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,11 +155,19 @@ void s_printf(char *fmt, ...) { } void s_putchar(char c) { - write(gSocket, &c, 1); + if (sshBBS) { + putchar(c); + } else { + write(gSocket, &c, 1); + } } void s_putstring(char *c) { - write(gSocket, c, strlen(c)); + if (sshBBS) { + printf("%s", c); + } else { + write(gSocket, c, strlen(c)); + } } void s_displayansi_p(char *file) { @@ -194,40 +212,46 @@ char s_getchar() { int len; do { - - len = read(gSocket, &c, 1); - - if (len == 0) { - disconnect("Socket Closed"); - } - while (c == 255) { + if (sshBBS) { + c = getchar(); + } else { len = read(gSocket, &c, 1); - if (len == 0) { + + if (len == 0) { disconnect("Socket Closed"); - } else if (c == 255) { - usertimeout = 10; - return c; - } - len = read(gSocket, &c, 1); - if (len == 0) { - disconnect("Socket Closed"); - } - len = read(gSocket, &c, 1); + } + } + + if (!sshBBS) { + while (c == 255) { + len = read(gSocket, &c, 1); + if (len == 0) { + disconnect("Socket Closed"); + } else if (c == 255) { + usertimeout = 10; + return c; + } + len = read(gSocket, &c, 1); + if (len == 0) { + disconnect("Socket Closed"); + } + len = read(gSocket, &c, 1); + if (len == 0) { + disconnect("Socket Closed"); + } + } + } + + + /* if (c == '\r') { if (len == 0) { disconnect("Socket Closed"); } - } - - + }*/ + } while (c == '\n'); + usertimeout = 10; - if (c == '\r') { - if (len == 0) { - disconnect("Socket Closed"); - } - } - } while (c == '\n'); - usertimeout = 10; return (char)c; } @@ -298,8 +322,10 @@ void disconnect(char *calledby) { } dolog("Node %d disconnected (%s)", mynode, calledby); sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, mynode); - remove(buffer); - close(gSocket); + 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]; @@ -470,23 +496,35 @@ void runbbs(int socket, char *ip) { struct tm oldtime; time_t now; struct itimerval itime; - struct sigaction sa; + struct sigaction sa; + struct sigaction st; lua_State *L; int do_internal_login = 0; ipaddress = ip; - write(socket, iac_echo, 3); - write(socket, iac_sga, 3); - - gUser = NULL; + 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++) { + for (i=1;i<=conf.nodes;i++) { sprintf(buffer, "%s/nodeinuse.%d", conf.bbs_path, i); if (stat(buffer, &s) != 0) { mynode = i; @@ -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"); - close(socket); + if (!ssh) { + close(socket); + } exit(1); } @@ -527,42 +567,74 @@ void runbbs(int socket, char *ip) { s_displayansi("issue"); - s_printf("\e[0mEnter your Login Name or NEW to create an account\r\n"); - s_printf("Login:> "); + if (!ssh) { + s_printf("\e[0mEnter your Login Name or NEW to create an account\r\n"); + s_printf("Login:> "); - s_readstring(buffer, 25); + s_readstring(buffer, 25); - if (strcasecmp(buffer, "new") == 0) { - user = new_user(); - } else { - s_printf("\r\nPassword:> "); - s_readpass(password, 16); - user = check_user_pass(buffer, password); - if (user == NULL) { - s_printf("\r\nIncorrect Login.\r\n"); - disconnect("Incorrect Login"); - } + if (strcasecmp(buffer, "new") == 0) { + user = new_user(); + } else { + s_printf("\r\nPassword:> "); + s_readpass(password, 16); + user = check_user_pass(buffer, password); + if (user == NULL) { + s_printf("\r\nIncorrect Login.\r\n"); + disconnect("Incorrect Login"); + } - 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); + gUser = user; - if (strcasecmp(user->loginname, buffer) == 0) { - fclose(nodefile); - s_printf("\r\nYou are already logged in.\r\n"); - disconnect("Already Logged in"); + 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); } - fclose(nodefile); - } - } - } + } + } + } 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); +} diff --git a/bbs.h b/bbs.h index 9a057bc..9e94bce 100644 --- a/bbs.h +++ b/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); diff --git a/chat_system.c b/chat_system.c index e103a8c..f9c1dce 100644 --- a/chat_system.c +++ b/chat_system.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,8 +111,16 @@ void chat_system(struct user_record *user) { char *message; char *sep; char *target; - memset(inputbuffer, 0, 80); - if (conf.irc_server == NULL) { + 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"); return; } @@ -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"); diff --git a/config_default/bbs.ini b/config_default/bbs.ini index 17fc636..603e08c 100644 --- a/config_default/bbs.ini +++ b/config_default/bbs.ini @@ -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 diff --git a/doors.c b/doors.c index 19dba9b..39ef459 100644 --- a/doors.c +++ b/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 { - sprintf(buffer, "%s %d %d", cmd, mynode, gSocket); - system(buffer); + 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; } diff --git a/files.c b/files.c index 19ff2b8..45cb369 100644 --- a/files.c +++ b/files.c @@ -7,6 +7,7 @@ #include #include #include +#include #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;iofd, &str[i], 1) == 0) { return ZmErrSys; } @@ -131,7 +154,7 @@ int doIO(ZModem *zm) { pos = 0; for (j=0;jcur_file_dir]->file_subs[user->cur_file_sub]->database); @@ -376,6 +422,11 @@ void download(struct user_record *user) { sqlite3_finalize(res); sqlite3_close(db); } + + if (sshBBS) { + tcsetattr(STDIN_FILENO, TCSANOW, &oldit); + tcsetattr(STDOUT_FILENO, TCSANOW, &oldot); + } for (i=0;i #include #include +#include +#include +#include #include +#include +#if defined(linux) +# include +#elif defined(__OpenBSD__) || defined(__NetBSD__) +# include +#else +# include +#endif +#include #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); } }