Subtext: a multi-user BBS server for Macintosh Written by joshua stein - http://jcs.org/subtext Subtext is free software; see the LICENSE file for copyright/licensing. Introduction ================================================================== Subtext is a multi-user BBS server that is developed and runs on Macintosh System 6 and above. It supports dialin access through a serial modem and Telnet access through MacTCP. Features ================================================================== - Multithreaded, multi-user BBS server that runs on System 6+ - Telnet support through MacTCP - Direct serial modem support (no Communications Toolbox) - Multiple threaded message boards - FTN (FidoNet) EchoMail and NetMail support with Binkp hub synching - Multi-user interactive chat - Private messaging/mail - File uploading and downloading with ZMODEM support - Integrated ANSI-capable local console - Local log window with smart screen blanking - Remote syslog (RFC3164) support - Secure user password storage with SHA256 - View/menu templates with variable expansion - Configurable main menu key shortcuts - Telnet brute-force IP banning by sending messages to a firewall host - Offline IP geolocation database support for connecting telnet IPs Setup ================================================================== Most of the administration is done through the BBS itself, by logging in as a sysop and accessing the sysop menu. BBS settings, file areas, message boards, and user accounts can all be modified through this menu. Editing view tepmlates is done by editing plaintext files in the "views" directory created where the BBS database lives. When first run, Subtext will ask to open an existing BBS database. Clicking Cancel will prompt to save a new database. On subsequent runs, Subtext will automatically try to open the last database that it successfully opened unless the Command key is held down at startup. When creating a new database, Subtext will create a default sysop user with the username "sysop" and password "p4ssw0rd". It will also fill in some defaults such as an example BBS name and hostname. On launch, Subtext will open its logger window and initialize its connection methods, which are only the console by default. Clicking the BBS menu and then Open Console will open a sysop session. Pressing ! will access the Sysop menu, and then S will enter the BBS Settings menu. To enable dialin access, change the Modem Port setting to 1 for the modem port or 2 for the printer port depending on where the modem is connected. An appropriate Modem Init String can also be configured, though it should *not* be configured for Auto-Answer. The number of rings after which an "ATA" is issued can be configured in the settings menu. To enable Telnet access, set the Telnet Port to anything other than 0, such as the standard telnet port of 23. Enabling Telnet requires MacTCP to be installed and configured. View Templates ================================================================== In the "views" directory automatically created where the BBS database lives are a number of text files that are used throughout the BBS: - issue.txt: Pre-login welcome screen ("issue" file) - menu.txt: Main menu - menu_options.txt: Menu commands, see Main Menu Configuration below - no_free_nodes.txt: "No Free Nodes" message shown through telnet - page_sysop.txt: Text shown before paging the sysop - short_menu.txt: Short menu shown after user has seen the main menu - signoff.txt: Session signoff - signup.txt: Account signup text After editing view text files, they must be reloaded through the BBS's console menu option, or through the sysop menu when logged in. Views support expansion of variables, which are put inside {{ and }} characters, such as "You are connected to {{node}}." Supported variables: - {{B}} Enable bold attribute if the user's terminal supports ANSI (otherwise it prints nothing). - {{/B}} Resets ANSI attributes (including bold) if the user's terminal supports ANSI. - {{#}} Stops varible expansion for the rest of the template. Useful when printing untrusted data (mostly used internally). - {{center_XX}} Print spaces of length equal to the user's terminal width minus XX, divided by two. For example, if the user's terminal is 80 characters wide and the variable {{center_50}} is used before a 50-character-wide menu line, 15 space characters will be printed. This is useful for centering a menu on wide terminals but preventing empty space on narrower terminals. - {{logged_in_time}} The amount of time the user has been logged in (still usable in signoff template), such as "7m20s". - {{new_mail}} If the user has any new, unread mail messages, the count such as "(4 New)". Otherwise it is blank. - {{node}} The current node, such as "ttyt0". - {{phone_number}} The system's configured phone number, such as "(312) 555-1212". - {{time}} The current system time in 24-hour format, such as "23:59". - {{timezone}} The system's configured "Timezone (Abbrev)". - {{username}} The currently logged-in user's username, or "guest". - {{"string"}} Print the literal string "string". This is useful in conditionals. Variable results can also be truncated or padded to a particular length, which can be helpful when creating menus with columns. This is done with the pipe character and the length, such as: {{ username|10 }} Conditionals are also supported with ternary operators "?" and ":" to print something if the condition is true (or non-null), otherwise print something else. The following conditionals are supported: - user True if the current user is logged in as a non-guest. - sysop True if the current user is a sysop. For example, the following would print one string in menu if the user is a sysop, otherwise it prints something else. {{ sysop ? "Answer sysop page" : "Page the sysop" }} Or when printing mail for the user: {{ user ? new_mail : "Guests cannot access mail." }} Main Menu Configuration ================================================================== In addition to creating a custom menu layout, it may be desirable to change the mapping of keys to functions. This can be done by editing the menu_options.txt file and then reloading it through the BBS. The mapping is one action per line, with the Action, Menu Key, All Keys list, and Label, separated by a colon. Blank lines and those starting with # are ignored. When there is no custom Main Menu view defined, a list of options will be programmatically generated by showing all menu options with a Menu Key defined with the Menu Key and Label. Options with no Menu Key defined are still accessible by any key in the All Keys field, but are not shown. The default mapping is: # Action:Menu Key:All Keys:Label BOARD_LIST_FTN_AREAS:A:Aa:List FTN Areas BOARD_SHOW_FIRST:B:Bb:Message Board BOARD_SHOW_1::1:Message Board 1 BOARD_SHOW_2::2:Message Board 2 BOARD_SHOW_3::3:Message Board 3 BOARD_SHOW_4::4:Message Board 4 BOARD_SHOW_5::5:Message Board 5 BOARD_SHOW_6::6:Message Board 6 BOARD_SHOW_7::7:Message Board 7 BOARD_SHOW_8::8:Message Board 8 BOARD_SHOW_9::9:Message Board 9 BOARD_SHOW_10::10:Message Board 10 CHAT:C:Cc:Multi-User Chat FILES_MENU:F:Ff:File Areas GOODBYE:G:GgXx:Goodbye RECENT_LOGINS:L:Ll:Recent Logins MAIL_COMPOSE:N:Nn:Compose New Mail MAIL_MENU:M:Mm:Private Mail {{ user ? new_mail : "" }} MOTD:O:Oo:Message Of The Day PAGE_SEND_OR_ANSWER:P:Pp:{{ sysop ? "Answer Page" : "Page Sysop" }} SETTINGS_OR_SIGNUP:S:Ss:{{ user ? "Settings" : "Signup For Account" }} WHOS_ONLINE:W:Ww:Who's Online SHOW_MENU:?:?:List Menu Options SYSOP_MENU::!:Sysop Menu FTN (FidoNet) Support ================================================================== Subtext supports FTN EchoMail (distributed message boards) and NetMail (relayed mail to a user at another node) by way of a Binkp hub. Directly-delivered "CrashMail" is not supported. Subtext has a built-in scanner/tosser with limited support for PKZIP archives of FTN packets. To get started, configure the FTN Hub Binkp hostname, port, and password settings. The network name, hub node address (e.g., "21:3/100"), local node address, and packet passwords must also be set. This is enough to enable NetMail, so users can send mail to a user@XX:X/XXX and have it delivered through the hub. Likewise, any incoming NetMail for valid usernames are delivered, or bounced to the Sysop. To enable EchoMail areas, create local boards in the Sysop menu and set the "FTN Area Name" field to match each desired area name exactly. Note that once a board has its FTN area name set, it cannot be removed later due to FTN boards using a different database structure than local, threaded boards. Once Binkp polling is enabled, Subtext will attempt to login to the Binkp hub at the configured interval and retrieve any packets sent from the hub, saving them to the "binkp:inbox" directory. After fetching any outstanding files, packets in the "binkp:outbox" directory are sent to the hub. Packets (or PKZIP archives of packets) in the inbox are tossed and NetMail is delivered. Any EchoMail packets for areas that match the FTN Area Name set in a local board are imported. Packets that cannot be tossed properly are moved to the "binkp:bad" directory. If the "FTN Hub Binkp Delete After Processing" option is enabled, packets are moved to the "binkp:processed" directory upon completion, which can be useful during testing. Otherwise, processed packets are deleted. To minimize latency, the Binkp poller will not start while there are any users logged in. This means that NetMail messages sent locally will not be sent out right away unless a Sysop manually triggers Binkp polling from the Sysop menu. This comes into play when communicating back and forth with an FTN AreaFix bot to configure which area messages should be delivered through the Binkp hub. Trusted Host ================================================================== While Subtext can handle direct TCP connections for Telnet, it will likely be behind a firewall/trusted host. To limit brute-force login attempts, Subtext has a hard-coded list of banned account names that most bots will try in rapid succession, such as "root", "admin", etc. When a Telnet client tries one of these usernames, Subtext can send a UDP packet to the trusted host containing the IP to be banned (in dotted-quad plaintext format, such as "192.168.1.1"). The trusted host IP and port can be configured in the Sysop menu. If either value is empty/zero, this functionality is disabled. Since there is no authentication with this mechanism, ensure the trusted host is only listening for UDP packets on the interface facing the Subtext server! Also during Telnet negotiation, if the IP of the connecting client matches the trusted host's IP, Subtext will honor the "REMOTE_ADDR" value present in the NEWENV variable list and use it as the client's connecting IP address in logs. This is useful if the trusted host is acting as a web proxy and can pass the IP of the web client through to Subtext over Telnet. When transferring files to and from a host connecting through the trusted host, Subtext will use its custom NoModem protocol instead of ZMODEM. This makes it easier to implement file transfers through a web or other custom frontend. IP Geolocation ================================================================== When configured with the path of an appropriate IP geolocation database, Subtext will use it to lookup connecting IPs. If a location is found, it will be logged to the logger and stored in the session log, which will also make it visible from the "who's online" and "recent logins' screens, so users can see where other users are connecting from. The format of this database is specified in the ipdb.c file. Free pre-built databases generated from public IP geolocation data can be downloaded from the Subtext website. These databases can be quite large (>40MB) and may be updated frequently, so they are not distributed with Subtext. Screen Blanking ================================================================== When running on compact Macs, it is recommended to enable Subtext's screen blanking option to prevent the log window from burning into the CRT. When the system is idle for a configured amount of time, it will blank the entire screen for a configured amount of time, immediately unblanking as soon as a new connection comes in, or when a key is pressed or a mouse button is clicked. This is better than using a dedicated screen saver which will not unblank after a period of time, and may be wasting CPU time drawing flying toasters while Subtext needs to process user activity. Run on Startup (System 6) ================================================================== To run Subtext when your Mac starts up, select the Subtext application in Finder, then open the Special -> Set Startup... menu. Under "Upon startup, automatically open:" select Subtext.