diff --git a/src/sbbs3/GNUmakefile b/src/sbbs3/GNUmakefile index f97a2a5eeb535a072c34511f4703ffa18fc8b8f9..c1e097f004e4ca08bb3242c2a850053c081ae1df 100644 --- a/src/sbbs3/GNUmakefile +++ b/src/sbbs3/GNUmakefile @@ -35,6 +35,11 @@ ifeq ($(os),qnx) LDFLAGS += -lsocket endif +ifdef USE_CRYPTLIB + CFLAGS += -DUSE_CRYPTLIB + SBBS_LIBS += -lcl +endif + ifdef PREFIX CFLAGS += -DPREFIX=$(PREFIX) endif @@ -122,12 +127,12 @@ LDFLAGS += $(UIFC-MT_LDFLAGS) $(XPDEV-MT_LDFLAGS) $(SMBLIB_LDFLAGS) $(CIOLIB-MT_ # Monolithic Synchronet executable Build Rule $(SBBSMONO): $(MONO_OBJS) $(OBJS) @echo Linking $@ - $(QUIET)$(CXX) -o $@ $(LDFLAGS) $(MT_LDFLAGS) $(MONO_OBJS) $(OBJS) $(SMBLIB_LIBS) $(XPDEV-MT_LIBS) + $(QUIET)$(CXX) -o $@ $(LDFLAGS) $(MT_LDFLAGS) $(MONO_OBJS) $(OBJS) $(SBBS_LIBS) $(SMBLIB_LIBS) $(XPDEV-MT_LIBS) # Synchronet BBS library Link Rule $(SBBS): $(OBJS) $(LIBS) @echo Linking $@ - $(QUIET)$(MKSHPPLIB) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(SHLIBOPTS) + $(QUIET)$(MKSHPPLIB) $(LDFLAGS) -o $@ $(OBJS) $(SBBS_LIBS) $(LIBS) $(SHLIBOPTS) # FTP Server Link Rule $(FTPSRVR): $(MTOBJODIR)/ftpsrvr.o diff --git a/src/sbbs3/answer.cpp b/src/sbbs3/answer.cpp index 89b2b0c7c7df44f43617e4b27e8bbb98fed6ec39..1416f9404f6cda8f1c2417a8c08b22952c2a2ae0 100644 --- a/src/sbbs3/answer.cpp +++ b/src/sbbs3/answer.cpp @@ -178,6 +178,71 @@ bool sbbs_t::answer() /* Retrieve terminal type from telnet client --RS */ request_telnet_opt(TELNET_DO,TELNET_TERM_TYPE); } +#ifdef USE_CRYPTLIB + if(sys_status&SS_SSH) { + cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_USERNAME, rlogin_name, &i); + rlogin_name[i]=0; + cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_PASSWORD, rlogin_pass, &i); + rlogin_pass[i]=0; + lprintf(LOG_DEBUG,"Node %d SSH: '%.*s' / '%.*s'" + ,cfg.node_num + ,LEN_ALIAS*2,rlogin_name + ,LEN_ALIAS*2,rlogin_pass); + useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, rlogin_name, 0); + if(useron.number) { + getuserdat(&cfg,&useron); + useron.misc&=~(ANSI|COLOR|RIP|WIP); + SAFECOPY(tmp + ,rlogin_pass); + for(i=0;i<3;i++) { + if(stricmp(tmp,useron.pass)) { + rioctl(IOFI); /* flush input buffer */ + bputs(text[InvalidLogon]); + if(cfg.sys_misc&SM_ECHO_PW) + sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'" + ,0,useron.alias,tmp); + else + sprintf(str,"(%04u) %-25s FAILED Password attempt" + ,0,useron.alias); + logline("+!",str); + bputs(text[PasswordPrompt]); + console|=CON_R_ECHOX; + getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB); + console&=~(CON_R_ECHOX|CON_L_ECHOX); + } + else { + if(REALSYSOP) { + rioctl(IOFI); /* flush input buffer */ + if(!chksyspass()) + bputs(text[InvalidLogon]); + else { + i=0; + break; + } + } + else + break; + } + } + if(i) { + if(stricmp(tmp,useron.pass)) { + bputs(text[InvalidLogon]); + if(cfg.sys_misc&SM_ECHO_PW) + sprintf(str,"(%04u) %-25s FAILED Password attempt: '%s'" + ,0,useron.alias,tmp); + else + sprintf(str,"(%04u) %-25s FAILED Password attempt" + ,0,useron.alias); + logline("+!",str); + } + useron.number=0; + hangup(); + } + } + else + lprintf(LOG_DEBUG,"Node %d RLogin: Unknown user: %s",cfg.node_num,rlogin_name); + } +#endif /* Detect terminal type */ mswait(200); diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp index 4f91223817815cbf83b2210844821e88e7fefff6..a59ddbeaf1324b32a02025646d46581ab9ef63b1 100644 --- a/src/sbbs3/main.cpp +++ b/src/sbbs3/main.cpp @@ -82,6 +82,9 @@ SOCKET uspy_socket[MAX_NODES]; /* UNIX domain spy sockets */ SOCKET node_socket[MAX_NODES]; static SOCKET telnet_socket=INVALID_SOCKET; static SOCKET rlogin_socket=INVALID_SOCKET; +#ifdef USE_CRYPTLIB +static SOCKET ssh_socket=INVALID_SOCKET; +#endif static sbbs_t* sbbs=NULL; static scfg_t scfg; static char * text[TOTAL_TEXT]; @@ -1341,6 +1344,15 @@ void input_thread(void *arg) if(rd > (int)sizeof(inbuf)) rd=sizeof(inbuf); +#ifdef USE_CRYPTLIB + if(sbbs->ssh_mode && sock==sbbs->client_socket) { + if(!cryptStatusOK(cryptPopData(sbbs->ssh_session, (char*)inbuf, rd, &i))) + rd=-1; + else + rd=i; + } + else +#endif rd = recv(sock, (char*)inbuf, rd, 0); if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0) @@ -1566,6 +1578,15 @@ void output_thread(void* arg) continue; } +#if USE_CRYPTLIB + if(sbbs->ssh_mode) { + if(!cryptStatusOK(cryptPushData(sbbs->ssh_session, (char*)buf+bufbot, buftop-bufbot, &i))) + i=-1; + else + cryptFlushData(sbbs->ssh_session); + } + else +#endif i=sendsocket(sbbs->client_socket, (char*)buf+bufbot, buftop-bufbot); if(i==SOCKET_ERROR) { if(ERROR_VALUE == ENOTSOCK) @@ -2340,6 +2361,10 @@ sbbs_t::sbbs_t(ushort node_num, DWORD addr, char* name, SOCKET sd, /* Init some important variables */ +#ifdef USE_CRYPTLIB + ssh_mode=false; +#endif + rio_abortable=false; console = 0; @@ -3711,6 +3736,12 @@ static void cleanup(int code) close_socket(rlogin_socket); rlogin_socket=INVALID_SOCKET; } +#ifdef USE_CRYPTLIB + if(ssh_socket!=INVALID_SOCKET) { + close_socket(ssh_socket); + ssh_socket=INVALID_SOCKET; + } +#endif #ifdef _WINSOCKAPI_ @@ -3783,6 +3814,9 @@ void DLLCALL bbs_thread(void* arg) struct sockaddr_un uspy_addr; socklen_t uspy_addr_len; #endif +#ifdef USE_CRYPTLIB + CRYPT_CONTEXT ssh_context; +#endif if(startup==NULL) { sbbs_beep(100,500); @@ -3806,6 +3840,9 @@ void DLLCALL bbs_thread(void* arg) /* Setup intelligent defaults */ if(startup->telnet_port==0) startup->telnet_port=IPPORT_TELNET; if(startup->rlogin_port==0) startup->rlogin_port=513; +#ifdef USE_CRYPTLIB + if(startup->ssh_port==0) startup->ssh_port=22; +#endif if(startup->outbuf_drain_timeout==0) startup->outbuf_drain_timeout=10; if(startup->sem_chk_freq==0) startup->sem_chk_freq=2; if(startup->temp_dir[0]) backslash(startup->temp_dir); @@ -4058,6 +4095,93 @@ void DLLCALL bbs_thread(void* arg) lprintf(LOG_INFO,"RLogin server listening on port %d",startup->rlogin_port); } +#ifdef USE_CRYPTLIB + if(startup->options&BBS_OPT_ALLOW_SSH) { + bool loaded_key=false; + + CRYPT_KEYSET ssh_keyset; + + cryptInit(); + cryptAddRandom(NULL,CRYPT_RANDOM_SLOWPOLL); + /* Get the private key... first try loading it from a file... */ + sprintf(str,"%s%s",scfg.ctrl_dir,"cryptlib.key"); + if(cryptStatusOK(cryptKeysetOpen(&ssh_keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, str, CRYPT_KEYOPT_NONE))) { + if(cryptStatusOK(cryptGetPrivateKey(ssh_keyset, &ssh_context, CRYPT_KEYID_NAME, "ssh_server", scfg.sys_pass))) + loaded_key=true; + cryptKeysetClose(ssh_keyset); + /* Failed to load the key... delete the keyfile and create a new one */ + if(!loaded_key) + remove(str); + } + + if(!loaded_key) { + /* Couldn't do that... create a new context and use the key from there... */ + + if(!cryptStatusOK(i=cryptCreateContext(&ssh_context, CRYPT_UNUSED, CRYPT_ALGO_RSA))) { + lprintf(LOG_ERR,"Cryptlib error %d creating context",i); + goto NO_SSH; + } + if(!cryptStatusOK(i=cryptSetAttributeString(ssh_context, CRYPT_CTXINFO_LABEL, "ssh_server", 10))) { + lprintf(LOG_ERR,"Cryptlib error %d setting key label",i); + goto NO_SSH; + } + if(!cryptStatusOK(i=cryptGenerateKey(ssh_context))) { + lprintf(LOG_ERR,"Cryptlib error %d generating key",i); + goto NO_SSH; + } + + /* Ok, now try saving this one... use the syspass to enctrpy it. */ + if(cryptStatusOK(cryptKeysetOpen(&ssh_keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, str, CRYPT_KEYOPT_CREATE))) { + cryptAddPrivateKey(ssh_keyset, ssh_context, scfg.sys_pass); + cryptKeysetClose(ssh_keyset); + } + } + + /* open a socket and wait for a client */ + + ssh_socket = open_socket(SOCK_STREAM, "ssh"); + + if(ssh_socket == INVALID_SOCKET) { + lprintf(LOG_ERR,"!ERROR %d creating SSH socket", ERROR_VALUE); + cleanup(1); + return; + } + + lprintf(LOG_INFO,"SSH socket %d opened",ssh_socket); + + /*****************************/ + /* Listen for incoming calls */ + /*****************************/ + memset(&server_addr, 0, sizeof(server_addr)); + + server_addr.sin_addr.s_addr = htonl(startup->ssh_interface); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(startup->ssh_port); + + if(startup->seteuid!=NULL) + startup->seteuid(FALSE); + result = retry_bind(ssh_socket,(struct sockaddr *)&server_addr,sizeof(server_addr) + ,startup->bind_retry_count,startup->bind_retry_delay,"SSH Server",lprintf); + if(startup->seteuid!=NULL) + startup->seteuid(TRUE); + if(result != 0) { + lprintf(LOG_NOTICE,"%s",BIND_FAILURE_HELP); + cleanup(1); + return; + } + + result = listen(ssh_socket, 1); + + if(result != 0) { + lprintf(LOG_ERR,"!ERROR %d (%d) listening on SSH socket", result, ERROR_VALUE); + cleanup(1); + return; + } + lprintf(LOG_INFO,"SSH server listening on port %d",startup->ssh_port); + } +NO_SSH: +#endif + sbbs = new sbbs_t(0, server_addr.sin_addr.s_addr ,"BBS System", telnet_socket, &scfg, text, NULL); sbbs->online = 0; @@ -4249,6 +4373,14 @@ void DLLCALL bbs_thread(void* arg) if(rlogin_socket+1>high_socket_set) high_socket_set=rlogin_socket+1; } +#ifdef USE_CRYPTLIB + if(startup->options&BBS_OPT_ALLOW_SSH + && ssh_socket!=INVALID_SOCKET) { + FD_SET(ssh_socket,&socket_set); + if(ssh_socket+1>high_socket_set) + high_socket_set=ssh_socket+1; + } +#endif #ifdef __unix__ for(i=first_node;i<=last_node;i++) { if(uspy_listen_socket[i-1]!=INVALID_SOCKET) { @@ -4286,6 +4418,9 @@ void DLLCALL bbs_thread(void* arg) client_addr_len = sizeof(client_addr); bool rlogin = false; +#ifdef USE_CRYPTLIB + bool ssh = false; +#endif is_client=FALSE; if(telnet_socket!=INVALID_SOCKET @@ -4299,6 +4434,46 @@ void DLLCALL bbs_thread(void* arg) ,&client_addr_len); rlogin = true; is_client=TRUE; +#ifdef USE_CRYPTLIB + } else if(ssh_socket!=INVALID_SOCKET + && FD_ISSET(ssh_socket,&socket_set)) { + client_socket = accept_socket(ssh_socket, (struct sockaddr *)&client_addr + ,&client_addr_len); + if(!cryptStatusOK(i=cryptCreateSession(&sbbs->ssh_session, CRYPT_UNUSED, CRYPT_SESSION_SSH_SERVER))) { + lprintf(LOG_ERR,"Cryptlib error %d creating session",i); + close_socket(client_socket); + continue; + } + if(!cryptStatusOK(i=cryptSetAttribute(sbbs->ssh_session, CRYPT_SESSINFO_PRIVATEKEY, ssh_context))) { + lprintf(LOG_ERR,"Cryptlib error %d setting private key",i); + cryptDestroySession(sbbs->ssh_session); + close_socket(client_socket); + continue; + } + /* Accept any credentials */ + if(!cryptStatusOK(i=cryptSetAttribute(sbbs->ssh_session, CRYPT_SESSINFO_AUTHRESPONSE, 1))) { + lprintf(LOG_ERR,"Cryptlib error %d setting AUTHRESPONSE",i); + cryptDestroySession(sbbs->ssh_session); + close_socket(client_socket); + continue; + } + if(!cryptStatusOK(i=cryptSetAttribute(sbbs->ssh_session, CRYPT_SESSINFO_NETWORKSOCKET, client_socket))) { + lprintf(LOG_ERR,"Cryptlib error %d setting socket",i); + cryptDestroySession(sbbs->ssh_session); + close_socket(client_socket); + continue; + } + if(!cryptStatusOK(i=cryptSetAttribute(sbbs->ssh_session, CRYPT_SESSINFO_ACTIVE, 1))) { + lprintf(LOG_ERR,"Cryptlib error %d setting session active",i); + cryptDestroySession(sbbs->ssh_session); + close_socket(client_socket); + continue; + } + cryptPopData(sbbs->ssh_session, str, sizeof(str), &i); + ssh = true; + is_client=TRUE; + sbbs->ssh_mode=true; +#endif } else { #ifdef __unix__ for(i=first_node;i<=last_node;i++) { @@ -4364,13 +4539,24 @@ void DLLCALL bbs_thread(void* arg) strcpy(host_ip,inet_ntoa(client_addr.sin_addr)); if(trashcan(&scfg,host_ip,"ip-silent")) { +#ifdef USE_CRYPTLIB + if(ssh) { + cryptDestroySession(sbbs->ssh_session); + sbbs->ssh_mode=false; + } +#endif close_socket(client_socket); continue; } lprintf(LOG_INFO,"%04d %s connection accepted from: %s port %u" ,client_socket - ,rlogin ? "RLogin" : "Telnet", host_ip, ntohs(client_addr.sin_port)); +#ifdef USE_CRYPTLIB + ,rlogin ? "RLogin" : (ssh ? "SSH" : "Telnet") +#else + ,rlogin ? "RLogin" : "Telnet" +#endif + , host_ip, ntohs(client_addr.sin_port)); #ifdef _WIN32 if(startup->answer_sound[0] && !(startup->options&BBS_OPT_MUTE)) @@ -4381,6 +4567,12 @@ void DLLCALL bbs_thread(void* arg) sbbs->online=ON_REMOTE; if(sbbs->trashcan(host_ip,"ip")) { +#ifdef USE_CRYPTLIB + if(ssh) { + cryptDestroySession(sbbs->ssh_session); + sbbs->ssh_mode=false; + } +#endif close_socket(client_socket); lprintf(LOG_NOTICE,"%04d !CLIENT BLOCKED in ip.can" ,client_socket); @@ -4419,6 +4611,12 @@ void DLLCALL bbs_thread(void* arg) } if(sbbs->trashcan(host_name,"host")) { +#ifdef USE_CRYPTLIB + if(ssh) { + cryptDestroySession(sbbs->ssh_session); + sbbs->ssh_mode=false; + } +#endif close_socket(client_socket); lprintf(LOG_NOTICE,"%04d !CLIENT BLOCKED in host.can",client_socket); sprintf(logstr, "Blocked Hostname: %s",host_name); @@ -4445,7 +4643,11 @@ void DLLCALL bbs_thread(void* arg) SAFECOPY(client.addr,host_ip); SAFECOPY(client.host,host_name); client.port=ntohs(client_addr.sin_port); +#ifdef USE_CRYPTLIB + client.protocol=rlogin ? "RLogin":(ssh ? "SSH" : "Telnet"); +#else client.protocol=rlogin ? "RLogin":"Telnet"; +#endif client.user="<unknown>"; client_on(client_socket,&client,FALSE /* update */); @@ -4473,6 +4675,12 @@ void DLLCALL bbs_thread(void* arg) } mswait(3000); client_off(client_socket); +#ifdef USE_CRYPTLIB + if(ssh) { + cryptDestroySession(sbbs->ssh_session); + sbbs->ssh_mode=false; + } +#endif close_socket(client_socket); continue; } @@ -4480,9 +4688,16 @@ void DLLCALL bbs_thread(void* arg) node_socket[i-1]=client_socket; sbbs_t* new_node = new sbbs_t(i, client_addr.sin_addr.s_addr, host_name - ,client_socket, &scfg, text, &client); + ,client_socket + ,&scfg, text, &client); new_node->client=client; +#ifdef USE_CRYPTLIB + if(ssh) { + new_node->ssh_session=sbbs->ssh_session; + new_node->ssh_mode=true; + } +#endif /* copy the IDENT response, if any */ if(identity!=NULL) @@ -4503,6 +4718,12 @@ void DLLCALL bbs_thread(void* arg) delete new_node; node_socket[i-1]=INVALID_SOCKET; client_off(client_socket); +#ifdef USE_CRYPTLIB + if(ssh) { + cryptDestroySession(sbbs->ssh_session); + sbbs->ssh_mode=false; + } +#endif close_socket(client_socket); continue; } @@ -4512,6 +4733,14 @@ void DLLCALL bbs_thread(void* arg) new_node->sys_status|=SS_RLOGIN; new_node->telnet_mode|=TELNET_MODE_OFF; // RLogin does not use Telnet commands } +#ifdef USE_CRYPTLIB + if(ssh) { + new_node->connection="SSH"; + new_node->sys_status|=SS_SSH; + new_node->telnet_mode|=TELNET_MODE_OFF; // SSH does not use Telnet commands + new_node->ssh_session=sbbs->ssh_session; + } +#endif node_threads_running++; new_node->input_thread=(HANDLE)_beginthread(input_thread,0, new_node); diff --git a/src/sbbs3/newuser.cpp b/src/sbbs3/newuser.cpp index 06e99dd72f1408a95375222d4d096b635c201d9d..20d5dd70834eb83504e629d163be947a7a158bdd 100644 --- a/src/sbbs3/newuser.cpp +++ b/src/sbbs3/newuser.cpp @@ -186,7 +186,11 @@ BOOL sbbs_t::newuser() else useron.misc&=~NO_EXASCII; +#ifdef USE_CRYPTLIB + if((sys_status&SS_RLOGIN || sys_status&SS_SSH) && rlogin_name[0]) +#else if(sys_status&SS_RLOGIN && rlogin_name[0]) +#endif strcpy(useron.alias,rlogin_name); else { while(online) { diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index 79be76860f7f711dc1df70ecdf6f82fd5a64ddc2..a56afac354ec0b763f143a9abb451351defbdf29 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -109,6 +109,10 @@ extern int thread_suid_broken; /* NPTL is no longer broken */ #endif +#ifdef USE_CRYPTLIB +#include <cryptlib.h> +#endif + /***********************/ /* Synchronet-specific */ /***********************/ @@ -169,6 +173,10 @@ public: char client_name[128]; char client_ident[128]; DWORD local_addr; +#ifdef USE_CRYPTLIB + CRYPT_SESSION ssh_session; + bool ssh_mode; +#endif scfg_t cfg; diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c index 037a58683d1b33743ecdfc50c91ef331e1c8aaea..7c862b7e65a1197fbd33f71677f4a9d750628d53 100644 --- a/src/sbbs3/sbbs_ini.c +++ b/src/sbbs3/sbbs_ini.c @@ -296,6 +296,13 @@ void sbbs_read_ini( bbs->rlogin_port =iniGetShortInt(list,section,"RLoginPort",513); +#ifdef USE_CRYPTLIB + bbs->ssh_interface + =iniGetIpAddress(list,section,"SSHInterface",global->interface_addr); + bbs->ssh_port + =iniGetShortInt(list,section,"SSHPort",22); +#endif + bbs->first_node =iniGetShortInt(list,section,"FirstNode",1); bbs->last_node @@ -729,9 +736,18 @@ BOOL sbbs_write_ini( iniRemoveValue(lp,section,"RLoginInterface"); else if(!iniSetIpAddress(lp,section,"RLoginInterface",bbs->rlogin_interface,&style)) break; - if(!iniSetShortInt(lp,section,"RLoginPort",bbs->rlogin_port,&style)) break; + +#ifdef USE_CRYPTLIB + if(bbs->ssh_interface==global->interface_addr) + iniRemoveValue(lp,section,"SSHInterface"); + else if(!iniSetIpAddress(lp,section,"SSHInterface",bbs->ssh_interface,&style)) + break; + if(!iniSetShortInt(lp,section,"SSHPort",bbs->ssh_port,&style)) + break; +#endif + if(!iniSetShortInt(lp,section,"FirstNode",bbs->first_node,&style)) break; if(!iniSetShortInt(lp,section,"LastNode",bbs->last_node,&style)) diff --git a/src/sbbs3/sbbscon.c b/src/sbbs3/sbbscon.c index 5d2cb9c0468425291e303aa588e3853911ea607e..4c00094b768cbd4f0db29b722ade4039545f3b57 100644 --- a/src/sbbs3/sbbscon.c +++ b/src/sbbs3/sbbscon.c @@ -1640,7 +1640,12 @@ int main(int argc, char** argv) if(!thread_suid_broken) { if(bbs_startup.telnet_port < IPPORT_RESERVED || (bbs_startup.options & BBS_OPT_ALLOW_RLOGIN - && bbs_startup.rlogin_port < IPPORT_RESERVED)) + && bbs_startup.rlogin_port < IPPORT_RESERVED) +#ifdef USE_CRYPTLIB + || (bbs_startup.options & BBS_OPT_ALLOW_SSH + && bbs_startup.ssh_port < IPPORT_RESERVED) +#endif + ) bbs_startup.options|=BBS_OPT_NO_RECYCLE; if(ftp_startup.port < IPPORT_RESERVED) ftp_startup.options|=FTP_OPT_NO_RECYCLE; diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h index 8344dd25dd7f9fc6af367cda5e785781ad765f1b..d02dc89ce832393b6dc9182f503a4906811cdb87 100644 --- a/src/sbbs3/startup.h +++ b/src/sbbs3/startup.h @@ -75,12 +75,18 @@ typedef struct { WORD last_node; WORD telnet_port; WORD rlogin_port; +#ifdef USE_CRYPTLIB + WORD ssh_port; +#endif WORD outbuf_highwater_mark; /* output block size control */ WORD outbuf_drain_timeout; WORD sem_chk_freq; /* semaphore file checking frequency (in seconds) */ DWORD telnet_interface; DWORD options; /* See BBS_OPT definitions */ DWORD rlogin_interface; +#ifdef USE_CRYPTLIB + DWORD ssh_interface; +#endif RingBuf** node_spybuf; /* Spy output buffer (each node) */ RingBuf** node_inbuf; /* User input buffer (each node) */ sem_t** node_spysem; /* Spy output semaphore (each node) */ @@ -154,6 +160,9 @@ static struct init_field { #define BBS_OPT_NO_EVENTS (1<<9) /* Don't run event thread */ #define BBS_OPT_NO_SPY_SOCKETS (1<<10) /* Don't create spy sockets */ #define BBS_OPT_NO_HOST_LOOKUP (1<<11) +#ifdef USE_CRYPTLIB +#define BBS_OPT_ALLOW_SSH (1<<26) /* Allow logins via BSD SSH */ +#endif #define BBS_OPT_NO_RECYCLE (1<<27) /* Disable recycling of server */ #define BBS_OPT_GET_IDENT (1<<28) /* Get Identity (RFC 1413) */ #define BBS_OPT_NO_JAVASCRIPT (1<<29) /* JavaScript disabled */ @@ -161,8 +170,13 @@ static struct init_field { #define BBS_OPT_MUTE (1<<31) /* Mute sounds */ /* bbs_startup_t.options bits that require re-init/recycle when changed */ +#ifdef USE_CRYPTLIB +#define BBS_INIT_OPTS (BBS_OPT_ALLOW_RLOGIN|BBS_OPT_ALLOW_SSH|BBS_OPT_NO_EVENTS|BBS_OPT_NO_SPY_SOCKETS \ + |BBS_OPT_NO_JAVASCRIPT|BBS_OPT_LOCAL_TIMEZONE) +#else #define BBS_INIT_OPTS (BBS_OPT_ALLOW_RLOGIN|BBS_OPT_NO_EVENTS|BBS_OPT_NO_SPY_SOCKETS \ |BBS_OPT_NO_JAVASCRIPT|BBS_OPT_LOCAL_TIMEZONE) +#endif #if defined(STARTUP_INI_BITDESC_TABLES) static ini_bitdesc_t bbs_options[] = { @@ -178,6 +192,9 @@ static ini_bitdesc_t bbs_options[] = { { BBS_OPT_NO_EVENTS ,"NO_EVENTS" }, { BBS_OPT_NO_HOST_LOOKUP ,"NO_HOST_LOOKUP" }, { BBS_OPT_NO_SPY_SOCKETS ,"NO_SPY_SOCKETS" }, +#ifdef USE_CRYPTLIB + { BBS_OPT_ALLOW_SSH ,"ALLOW_SSH" }, +#endif { BBS_OPT_NO_RECYCLE ,"NO_RECYCLE" }, { BBS_OPT_GET_IDENT ,"GET_IDENT" }, { BBS_OPT_NO_JAVASCRIPT ,"NO_JAVASCRIPT" },