Giter Site home page Giter Site logo

interlinked1 / lbbs Goto Github PK

View Code? Open in Web Editor NEW
33.0 4.0 4.0 3.59 MB

Lightweight BBS For Linux - Bulletin Board System server software

License: GNU General Public License v2.0

Makefile 0.40% C 98.63% Shell 0.78% PHP 0.15% Sieve 0.04%
bbs bulletin-board bulletin-board-system rlogin ssh-server telnet-server ascii dialup finger-protocol irc-server

lbbs's Introduction

LBBS - The Lightweight Bulletin Board System

Contents

Welcome! Whether you're new to BBSing or a veteran sysop, LBBS was written to be a highly configurable, modular BBS for developers, sysops, and users alike.

LBBS is a BBS (bulletin board system) package and personal server written from the ground up to be extensible, modular, and, of course, lightweight. The codebase is relatively small (~80K SLOC), with relatively few dependencies. It is designed to be easy for sysops to administer, easy for users to use and navigate, and easy for developers to read, understand, maintain, and contribute to the source code.

While LBBS is first and foremost a BBS server, its different components can also be used individually: for example, you could use the mail modules as a private mail server, and not load the BBS-related functionality.

Features

Key features and capabilities include:

  • Fast and lightweight, written entirely in C
  • Terminal access via Telnet, RLogin, SSH, and UNIX domain socket support (note that Telnet and RLogin are plain text protocols and thus insecure)
  • ANSI art support
  • File transfers via FTP, SFTP, Gopher, HTTP/HTTPS, and ZMODEM
  • HTTP 1.1 web server, with WebSocket and forward-proxy support
  • User home directories
  • Container environment for executing programs
  • Password and public key authentication
  • Config-file driven configuration
  • Submenu "skip menu navigation" - select options in multiple nested menus at once
  • Automatic menu screen generation and resizing
  • Electronic mail (SMTP, POP3, IMAP4)
    • Aliases and subaddressing
    • Mailing lists
    • Mailbox quotas
    • Shared mailboxes and ACL controls
    • Multi-domain support
    • Relay support
    • Advanced queuing support
    • IMAP NOTIFY support
    • RFC 4468 BURL IMAP and server-side proxied append support, for more efficient (bandwidth saving) email submission
    • Remote mailboxes (IMAP proxy)
      • Built-in OAuth2 proxy, allowing the BBS to log in to remote IMAP servers using OAuth2, while your IMAP client uses your normal BBS credentials
    • SPF, DKIM, ARC, DMARC, and SpamAssassin support
    • Filtering
      • Sieve filtering scripts and ManageSieve service
      • MailScript filtering engine for flexible, custom, dynamic mail filtering rules (Sieve alternative)
    • Webmail client backend
  • Newsgroups (NNTP)
  • Native realtime chat
  • Internet Relay Chat client and server (including ChanServ), with native IRC, Slack, and Discord relays
  • Queue agent position system for Asterisk
  • Terminal autodetection (ANSI support, link speed)
  • Emulated slow baud rate support
  • TDD/TTY (telecommunications device for the deaf) support
  • Sysop capabilities
    • Node spying
    • Interrupt nodes
    • Kick nodes

Usage

Installation

To install LBBS, you will need to compile it from source. Fortunately, we've made this as easy as possible:

cd /usr/local/src
git clone https://github.com/InterLinked1/lbbs.git
cd lbbs
./scripts/install_prereq.sh
make modcheck
make modconfig
make
make install
make samples

(Running make modcheck is optional. It will tell you all the modules that are available and which will be disabled for the current build. Running make modconfig is what actually makes changes to the build environment, disabling any modules with unmet dependencies.)

If you are setting up a Linux server from scratch, you may also want to refer to scripts/server_setup.sh for a more complete script to set up your BBS server.

To start the BBS with the sysop console in the foreground, you can then run lbbs -c. To daemonize it, just run lbbs.

At the console, press ? or h for a list of available commands. You can also run lbbs -? or lbbs -h for a list of startup options.

Some configuration of the BBS will be needed before you can use it. Consult the sample configs in /etc/lbbs for an overview of settings you may need to configure. At a minimum, you will need to add a menu to the BBS (menus.conf).

LBBS is best run on a modern version of Debian Linux (Debian 11 or 12). It should also compile on most other commonly used Linux distros. A recent version of gcc is required (e.g. >= 11). The BBS core should compile and install on FreeBSD, but not all module dependencies may be available and some functionality may be degraded.

WARNING: Do not run the BBS as root! Create a non-root user and configure the BBS to run as that instead. See lbbs -? or /etc/lbbs/bbs.conf to configure the run user and run group.

Sysoping

Sysops can monitor and control the BBS using the sysop console provided by the mod_sysop module. For example, you can list information about configured BBS menus, spy on nodes, or restart the entire BBS. Most commands are available by typing / followed by a string, although some common commands are available by single-press hotkeys. Press ? in the console for a list of available options and commands.

If the BBS is started in the foreground, a sysop console is available on STDIN/STDOUT.

Additionally, regardless of how the BBS is started, the sysop console can be accessed remotely (so called since the access originates from outside the BBS process) by running the rsysop program. This program is part of the external utilities and is installed to /var/lib/lbbs/external/rsysop.

WARNING: Note that anyone that can access the rsysop program is able to perform sysop tasks on the BBS. Even if the BBS is not running as root, it should be running under an account that is secured to the sysop.

System Configuration

Configuration of LBBS and modules are done entirely through INI config files. Different parts of LBBS have their own config files, as does each module that uses one. Config files go in /etc/lbbs and sample configuration files exist in the configs subdirectory of the source tree. Each sample config file documents all available options. Refer to the sample configs for all relevant configuration.

A few especially important configuration files:

  • bbs.conf - key startup settings
  • mail.conf - Email configuration
  • menus.conf - BBS menus, menu items and options.
  • mod_auth_mysql.conf - MySQL/MariaDB auth provider module config
  • mod_mail.conf - General email server configuration
  • mod_smtp_filter_dkim.conf - DKIM signing
  • modules.conf - module loading settings (to disable a module, you do it here)
  • net_smtp.conf - SMTP server configuration
  • net_ssh.conf - SSH and SFTP server configuration
  • nodes.conf - Node-related configuration
  • tls.conf - SSL/TLS configuration
  • transfers.conf - File transfer configuration

Additionally, the MailScript rules engine uses a script file called .rules in the root maildir and the user's root maildir for manipulating messages. A sample MailScript rules file is in configs/.rules (though this is not a config file, but a sample rule script file).

User Configuration

User configuration goes in ~/.config, which is a subdirectory of each user's BBS home directory (unrelated to any system home directories).

Users can edit these files either via the BBS shell (if configured by the sysop) or via any enabled file transfer protocols (e.g. FTP, FTPS, SFTP).

  • .imapremote - IMAP client proxy configuration
  • .oauth.conf - OAuth authentication configuration (used for IMAP client proxy and SMTP submission)
  • .plan - UNIX .plan file, used by the Finger protocol
  • .project - UNIX .project file, used by the Finger protocol. Limited to 1 line.

Network Login Services

Network login or comm drivers are modules in the nets source directory, responsible for implementing a network login service. These are what allow users to actually connect to the BBS itself.

Generally speaking, the comm drivers implement some kind of standardized TCP-based protocol. There are builtin drivers for Telnet, RLogin, and SSH. Note that Telnet and RLogin are plain text protocols and thus insecure! Using SSH is recommended for any public connections.

LBBS also includes a UNIX domain socket module (net_unix). One use case for this is if you want to "proxy" connections to the BBS through the main, public-facing network login service. For example, say you run OpenSSH on port 22 (and you don't want to change the port), but you still want people to be able to connect to your BBS on port 22. You can create a public user account on your server that executes the BBS as a program, rather than providing a login shell. If you do this, you don't need any of the network drivers loaded or running besides net_unix (UNIX domain sockets provide the least overhead for these kinds of loopback connections). That said, the UNIX domain socket driver is quite primitive. Using one of the other drivers, particularly the SSH driver, will provide a far superior experience.

Do note, should you choose to proxy connections in the manner described above, there are several important security implications of doing this that you must understand, or you open your system up to vulnerabilities. See the comments at the top of the source file nets/net_unix.c

Unless you really know what you are doing, you are probably better off using LBBS's builtin network login services, rather than proxying the connection through your system's primary network login services. This will provide a more seamless user experience and mitigate potential security vulnerabilities described above.

Each comm driver handles window resizing in its own way.

  • net_ssh - full support for window size at login and resizing later
  • net_telnet - support for window size at login, but currently no support for resizing later (could be added as an enhancement)
  • net_rlogin - broken support for window size at login (doesn't work)
  • net_unix - no support for window size. UNIX domain sockets are similar to a raw TCP socket, there is no terminal protocol riding on top of the socket here. If you need (or want) window size support, use a different network comm driver.

None of the network comm drivers are mutually exclusive - you can enable as many or few as you want, and users can use whatever protocol they want to.

Generally speaking, for the reasons listed above, SSH is the recommended protocol. Apart from being the only protocol secure to use over the Internet, it also fully handles terminal resizing.

The BBS also comes with some network services that aren't intended for terminal usage, e.g. FTP, HTTP, IMAP, etc. See the nets directory for a full listing.

Using mod_auth_mysql

The BBS needs at least one authentication provider to be able to authenticate users. mod_auth_mysql is an included module that authenticates users against a MySQL/MariaDB database.

You'll need to create a user for the database, if you haven't already:

CREATE USER 'bbs'@'localhost' IDENTIFIED BY 'P@ssw0rdUShouldChAngE!';
GRANT ALL PRIVILEGES ON bbs.* TO 'bbs'@'localhost';
FLUSH PRIVILEGES;

Then, create a database called bbs and a table called users - the SQL to do so is in scripts/dbcreate.sql.

Don't forget to also add your DB connection info to mod_auth_mysql.conf!

FAQ

Can I try it out without installing anything?

Sure! The reference installation of LBBS is the PhreakNet BBS, reachable at bbs.phreaknet.org. Guest login is allowed.

How can I bind BBS services to privileged ports if it's not running as root?

If you are running your BBS as a non-root user (which you should!), you may encounter errors binding to particular ports. There are a few different methods you can use to bind to privileged ports (1 through 1023) when running the BBS as a non-root user.

The first is as simple as explicitly granting the BBS binary the right to do so, e.g.:

sudo setcap CAP_NET_BIND_SERVICE=+eip /usr/sbin/lbbs

This is the recommended approach if it works for you. If not, you can also explicitly allow all users to bind to any ports that are at least the specified port number:

sudo sysctl net.ipv4.ip_unprivileged_port_start=18

This example would allow any user to bind to ports 18 and above. The lowest standard port number currently used by the BBS is 18 (FTP).

Note that this method is not as secure as the first method, but is likely to work even if other methods fail.

Finally, note that many systems already have daemons running on the standard ports, e.g. sshd, telnetd, Apache web server, etc. If these are present, you will need to resolve the conflict, as only one program can bind to a port at any given time.

Can I run SSH and SFTP on the same port?

Yes (and, in fact, you must, if you wish to enable both). Originally, SSH and SFTP were provided by 2 independent modules. They are now combined, allowing for same-port usage, which users expect.

What terminal emulators are supported?

Most common terminal emulators should work fine. The emulator's terminal type is used, if sent, and some terminal autodetection is also performed.

Some emulators are particularly good. Of all the well-known ones, these three terminal emulators are particularly recommended for BBSing on Windows:

  • SyncTERM - Works well, looks nice. You must use the newer 1.2 version. The more commonly downloaded 1.1 version has major bugs.
  • qodem - Initial configuration slightly unintuitive, but otherwise works very well, with excellent support for non-standard display sizes.
  • PuTTY (and forks, like KiTTY) - Works well, no known issues. Not "retro" at all, but does the job fine.

Most other terminal emulators tested tend to have various setup, compatibility, or runtime issues. In particular:

  • NetRunner - Not recommended. Poorer support for ANSI escape sequences and Telnet options. Does not send a terminal type! Poor support for ncurses applications.

I see warnings about a terminal type not being in the terminfo database.

This typically happens for terminal emulators that report non-standard terminal types that are not installed by default on the system. This can be resolved by installing the appropriate terminfo file. See scripts/server_setup.sh for an example of adding syncterm support in this manner.

What is the difference between door_chat and door_irc?

door_chat is a fully self-contained, isolated chat module that can only be used from within the BBS. door_irc is an IRC client that can be used to connect to the local IRC server (provided by net_irc) or to another IRC server. In most cases, door_irc is likely what you want; however, door_chat can still be used on its own, if it meets your needs.

When using private namespace IRC channels, channel messages get sent to me as private messages.

It is likely that your IRC client does not properly support all the standardized channel prefixes (#, &, +, and !). Many clients only support the first two, if even that. Because of this limitation, you can override the prefix used for the per-user namespace prefix near the top of include/net_irc.h, by defining PRIVATE_NAMESPACE_PREFIX_CHAR appropriately. If your client only supports the # prefix properly, then unfortunately you cannot use this feature, unless you can fix your client.

The Discord relay seems to exit immediately after being started.

The bot you created likely doesn't have all the necessary permissions. Make sure "Privileged Gateway Intents" are enabled as appropriate.

I have multiple hostnames. Is SNI (Server Name Indication) supported?

Yes, LBBS supports SNI as both a client and a server. Refer to tls.conf for configuration details.

How can I serve webpages using the embedded web server?

There are 3 methods supported by the web server:

  • Embedded server applications - these are dynamic applications that run within the BBS itself
  • Static files - static files on disk that the web server sends to clients
  • CGI (Common Gateway Interface) - CGI can be used to dynamically send a webpage from an external program

Embedded dynamic scripting engines (e.g. a la Apache HTTP server's mod_php) are not currently supported.

How does the container enviornment (isoexec handler) work?

The isoexec handler creates the specified process in a separate namespace so that is isolated from the root namespace in which the BBS is running. Essentially, it creates a container, similar to how technologies like Docker work.

This enhances security by providing isolation between your system and whatever may be executed within the environment, such as a shell or other arbitrary program. For example, you can use this to provide users shell access on your BBS, but without actually granting them access to the main filesystem.

The container does require that you provide a root filesystem for it to use. An example of how to do this is in configs/menus.conf. Please also read the caveats, notes, and warnings about isoexec in the sample config file.

The isoroot program in the external directory also demonstrates how this functionality works in a standalone manner, if you want to test your container environment separately.

How do I set up TLS certificates?

You will need to get TLS certificates from a certificate authority to support protocols that use TLS for encryption.

We recommend using a free certificate authority, like Let's Encrypt.

The below steps show how you can get free 3-month TLS certificates from Let's Encrypt that will renew automatically as needed.

There are multiple ACME clients you can use; Certbot is another one. acme.sh is used here because it's lightweight; certbot installs quite a bunch of stuff (like snapd) that you probably don't otherwise need or want.

The guidance here uses a webroot in the BBS itself. There is an option to use a port, but this is misleading; if you run the ACME client in standalone mode, the BBS web server CANNOT be running at the same time. While this may be fine initially, it will be problematic for renewals. The webroot method ensures that certificates can be renewed without issue, as long as the BBS is running.

Finally, certificates will be stored in /etc/letsencrypt (just like Certbot), rather than inside your home directory (the default). You can obtain a certificate for multiple hostnames at the same time (see example in step 4):

  1. Enable HTTP (but not HTTPS (yet), which will fail without a TLS certificate configured) in net_http.conf.
  2. Start the BBS (or reload net_http if it's already running)
  3. curl https://get.acme.sh | sh
  4. ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt --always-force-new-domain-key --issue -w /home/bbs/www --cert-home /etc/letsencrypt -d example.com -d example.net -d example.org
  5. Run crontab -e and inspect the --home argument in the cron job that was added. It should be /etc/letsencrypt (or whatever path you chose for --cert-home). If not, update it.
  6. Update permissions: chown -R bbs /etc/letsencrypt/ && chgrp -R bbs /etc/letsencrypt/
  7. Now, update tls.conf with the path to the cert and key (cert key) that ACME spits out.
  8. Restart the BBS for TLS changes to take effect. In the future, you can also run /tlsreload to reload certificates without a full restart.

What format does the BBS use to store email?

The BBS mail servers use the maildir++ format. This is similar to what software like Dovecot and Courier use by default, although certain implementation details may differ.

Does the BBS provide a sendmail binary, for submitting local mail?

No, it does not. Consequently, you may see messages like this in your cron logs, for example:

(CRON) info (No MTA installed, discarding output)

This is because cron did not detect /usr/bin/sendmail, which is used by default to submit outgoing mail from outside of the local MTA.

Installing the actual sendmail is overkill and not recommended, since it also includes the Sendmail MTA, which will conflict with LBBS. However, you can install a lightweight client like ssmtp or msmtp (a more actively maintained variant) to do this. You just need to ensure you install an SMTP client consistent with the Sendmail interface, so that programs expecting sendmail will work properly.

If you install msmtp, be sure to configure it system-wide.

The below is a good default /etc/msmtprc for most systems:

account default
host 127.0.0.1
port 25
from [email protected]
tls off
logfile /var/log/msmtp.log

Make sure to substitute the default "from" address with something appropriate for your server.

Then, you can symlink msmtp to sendmail, and things should "just work": ln -s /usr/bin/msmtp /usr/sbin/sendmail.

Can I check email using the terminal instead of using IMAP/POP3?

Yes, evergreen is the officially recommended terminal mail client for LBBS. The door_evergreen module automatically wraps execution of the mail client as appropriate for usage within the BBS.

Does the BBS provide any kind of webmail access?

You can use wssmail, a fast and efficient webmail client designed with the BBS's mail server in mind (but may be used with any mail server). LBBS comes with the mod_webmail module, which is a backend module for wssmail.

Note that only the webmail backend is a BBS module. The corresponding webmail frontend is a required but separately maintained project. (In theory, the frontend could have multiple implementations as well.)

If you don't want to use mod_webmail, you can also use any other open source webmail package, e.g. SquirrelMail, RoundCube, etc. and that should work just fine. SquirrelMail is extremely simple (no JavaScript used or required); RoundCube comes with more features and extensibility. In particular, RoundCube comes with a built-in graphical ManageSieve editor, which can be useful for managing your Sieve scripts.

Do keep in mind that webmail offers significantly reduced functionality compared to a standard mail client (e.g. something in the Thunderbird family, like Interlink/MailNews).

How do I fully set up the webmail service?

You will need to set up both the frontend and the backend for the webmail.

The frontend refers to a frontend website that provides the user-facing HTML, CSS, and JavaScript.

The backend refers to a backend service which interfaces between the frontend and the IMAP/SMTP servers.

The backend is mod_webmail, though it runs on top of net_ws, which itself depends on the BBS's web server modules. The frontend is a separate project as the frontend is not coupled to the backend, other than through the requirement that the WebSocket interface be consistent with both.

No configuration is required of the backend. Only the frontend needs to be configured.

The frontend does not need to be run under the BBS's web server. For example, you can run the frontend under the Apache HTTP web server, just like any other virtualhost. You'll want to secure the site using TLS just like any other site if it's public facing.

Apart from the frontend site itself, you can also configure a WebSocket reverse proxy under Apache HTTP to accept WebSocket upgrades on your standard HTTPS port (e.g. 443) and hand those off to the BBS WebSocket server. That might look something like this:

RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*)           ws://localhost:8143/webmail [P,L]

This example assumes Apache is running on 443 (or whatever client facing port), and net_ws is listening on port 8143. Note that this connection is not encrypted, but this is a loopback connection so that does not matter.

Refer to the webmail package documentation for more information: https://github.com/InterLinked1/wssmail

Why is there a non-standard filtering engine (MailScript) included?

The MailScript filtering language was explicitly designed to be very simple to parse, unlike filtering languages with slightly more complicated syntax, such as Sieve. MailScript also allows for basic testing of filtering primitives independent of the filtering language used, which can be useful for testing. MailScript was added before Sieve support was added due to the easier implementation.

Currently, some capabilities, such as executing system commands or processing outgoing emails, that are only possible with MailScript, not with Sieve. Although there are Sieve extensions to do this, the Sieve implementation in the BBS does not yet support this (or rather, the underlying library does not). Eventually the goal is to have full feature parity.

Sieve rules can be edited by users directly using the ManageSieve protocol (net_sieve). In contrast, MailScript rules can only be modified by the sysop directly on the server. Additionally, MailScript allows for potentially dangerous operations out of the box, and should not normally be exposed to users.

It is recommended that Sieve be used for filtering if possible, since this is a standardized and well supported protocol. MailScript is a nonstandard syntax that was invented purely for this software, so it is not portable anywhere else. However, if the current Sieve implementation does not meet certain needs but MailScript does, feel free to use that as well. Both filtering engines can be used in conjunction with each other.

How do I enable spam filtering?

There is a builtin module for SpamAssassin integration. SpamAssassin installation and configuration is largely beyond the scope of this document, but here is a decent quickstart:

Installation

  • Install SpamAssassin: apt-get install -y spamassassin. You do not need spamass-milter since milters are not currently supported.
  • Create your preference file, e.g. /etc/spamassassin/config.cf:

    # Required score to be considered spam (5 is the default, and should generally be left alone)
    required_score      5
    
    # Heavily penalize HTML only emails
    score MIME_HTML_ONLY 2.10
    
    # Don't modify original message (apart from adding headers)
    report_safe 0
    
    # Bayes DB (specify a path and sa-learn will create the DB for you)
    bayes_path /var/lib/spamassassin/bayesdb/bayes
  • Go ahead and run sa-compile to compile your rule set into a more efficient form for runtime.

Training

SpamAssassin needs to be trained for optimal filtering results. It is best trained on real spam (and ham, or non-spam) messages. You can tell SpamAssassin about actual spam (sa-learn --spam /path/to/spam/folder) or ham (sa-learn --ham /path/to/ham/folder).

SpamAssassin can work reasonably well out of the box, but will get better with training. If you receive spam, don't delete them - put them in a special folder (e.g. Junk) and rerun sa-learn periodically.

You can also run on multiple folders - careful though, if users have a Sieve rule to move suspected spam to Junk, this could train on false positives if this is run before they react and correct that. Therefore, if your mail server is small, you may just want to do this manually periodically after receiving Spam:

sa-learn --spam /home/bbs/maildir/*/Junk/{cur,new}
sa-learn --ham /home/bbs/maildir/*/cur

Once you've trained the Bayes model, you can delete the spam messages if you wish. Rerunning the model on existing messages is fine too - the model will skip messages it's already seen, so there's no harm in not deleting them immediately, if you have the disk space.

Adding Spam Headers

SpamAssassin can be called by the SMTP server on incoming emails delivered from external recipients. This should be done automatically provided that mod_spamassassin is loaded and SpamAssassin is installed and configured properly. SpamAssassin will add some headers to each message, which can then be used in a Sieve script or MailScript rule to filter suspected spam into the Junk folder (but SpamAssassin on its own will not filter mail, just identify messages it thinks are spam).

SpamAssassin is best used before-queue, since this prevents backscatter by ensuring spam results are available for filtering rules to use (allowing recipients to outright reject highly suspected spam, for instance). mod_spamassassin invokes SpamAssassin during the SMTP delivery process to allow this.

When invoked directly (e.g. as /usr/bin/spamassassin), SpamAssassin will read the message from the BBS on STDIN and output the modified message on STDOUT. Because the BBS only needs SpamAssassin to prepend headers at the top, it will not use the entire returned body from SpamAssassin. Instead, it will prepend all of the SpamAssassin headers and ignore everything else, since that would just involve copying the remainder of the message back again for no reason. This contrasts with with more conventional facilities that mail transfer agents provide for modifying message bodies on delivery.

Filtering Spam

SpamAssassin will tag spam appropriately, but not do anything to it. That's where Sieve rules can help filter spam to the right place (or even reject it during the SMTP session). There are a few headers that SpamAssassin will add, e.g. X-Spam-Status. Users can customize what they want to do with spam and their threshold for spam filtering using a Sieve rule. The most common rule is to move suspected spam to the user's Junk folder.

Email sent from the BBS keeps going to people's spam!

Email deliverability is beyond the scope of this guide, but there are a few things you'll want to ensure:

  • SPF records are configured for any domains from which you send email
  • MX records are configured for any domains from which you send email
  • rDNS is configured for any IP addresses from which you send email (used for FCrDNS). If you use DigitalOcean, your Droplet name must be the rDNS hostname. The rDNS hostname must resolve to your IP but does not need to match your mail domain, nor encompass all of them.
  • DKIM is configured (see mod_smtp_filter_dkim.conf)

Additionally, there are many online tools that can do some deliverability checks for you, which may catch common configuration errors and mistakes:

How can I improve the efficiency of my email submissions?

You could use RFC 4468 BURL, but this is not supported by virtually any mail client (besides Trojita).

The recommended setting is to use MailScript rules to "filter" your outgoing emails. You can define a rule for each account to save a copy in your IMAP server's Sent folder. For your local BBS email account, you can use MOVETO .Sent; for remote IMAP servers, you can specify an IMAP URL like MOVETO imaps://[email protected]:[email protected]:993/Sent. The BBS's SMTP server will then save a copy of the message in the designated location before relaying or sending it.

This can be faster since normally your mail client uploads messages twice: once to your SMTP server to send it, and once to the IMAP server to save a copy of it (in the Sent folder). BURL IMAP was created to address this inefficiency, but unfortunately lacks widespread client support (although LBBS and several other IMAP servers do support it). Instead, the SMTP server can save the copy to the IMAP server (basically the inverse of BURL). (Gmail's SMTP server does something like this as well.) This doesn't require any special client support.

If you synchronize your Sent folder locally, you'll still end up downloading the message, but it'll use your download bandwidth instead of your uplink bandwidth, the latter of which is typically more limited.

If you do have the SMTP server save copies of your sent messages, make sure to disable "Save a copy of sent messages to..." in your mail client, to avoid saving a duplicate copy.

As noted above, currently Sieve and MailScript do not have feature parity, so you cannot use Sieve to do this; you must use MailScript rules.

Donations

LBBS is developed entirely by volunteers on their own time.

If LBBS is useful to you, please consider donating to fund further development and features. Thank you!

Licensing

If you intend to run an LBBS system or make modifications to LBBS, you must understand the license.

LBBS is licensed under the GNU General Public License version 2 (GPLv2). At a high level, GPLv2 is a copyleft license (sometimes referred to as a more restrictive license) that requires that any modifications to the source code be distributed to any users to whom the resulting program is made available. This contrasts with more permissive licenses such as the Apache License or MIT License that do not have such requirements. See the link for more details.

There are a few reasons I opted to license LBBS under the GPL, some out of choice, others less so:

  • The reality is that the days of commercial BBSes are long over. There is no money in running a BBS these days, nor is there any money in writing BBS software. LBBS is no exception. The majority of BBS users, sysops, and developers are all hobbyists doing this for fun, not to make a living. A copyleft license better suits the environment of BBSes today, encouraging contributors to share modifications and improvements with the community.
  • I considered licensing the LBBS core under the Affero General Public License (AGPL) and modules under the GPL, since BBS users are not entitled to the source code under the GPL unless the binaries are distributed to them. However, it was (and is) important to me that modules not be licensed under the AGPL, but something more permissive such as the GPL, so that sysops and developers could create their own custom modules and not be required to disclose the source code to their users, in order to provide more freedom for users and sysops. Rather than complicating things with split-licensing, licensing everything under the more permissive GPL is simpler.
  • Parts of the LBBS source code and binary have dependencies on components that are themselves licensed under the GPL. For example, the history functionality for the sysop command line, which depends on history(3), a component of the GNU readline library (licensed under the GPL). So, LBBS is required to be licensed with a copyleft license at least as strong as the GPL.

Note that these are merely the rationales for licensing this project under GPLv2, but the vast majority of users and sysops do not need to be concerned about the license, unless you intend to distribute compiled versions of LBBS or make modifications to it. If you make modifications to the source and distribute the result, you must make the source code available under a license at least as restrictive as the GPLv2. If you are merely using LBBS or are a sysop running LBBS, then there is nothing special you need to do to comply with the GPL. Obviously, this is not legal advice, and you should consult a lawyer if you have licensing questions or concerns.

Development Notes

Architecture

LBBS is a single-process multithreaded program. The BBS "core" is the lbbs binary comprised of all the source files in the bbs directory. The core is designed to be small, with additional functionality provided by modules that can be dynamically loaded and unloaded as desired. This makes it easy for functionality to be added in a self-contained manner.

For example, the sysop console is provided by the mod_sysop module. It is not built in to the core. This makes it easy to modify the sysop console, and you could even write your own sysop console and use that instead!

This approach is also relied on for key functionality that could be implemented in different ways. For example, the mod_auth_mysql is an authentication provider that can process user login requests, backed by a MySQL/MariaDB database. However, maybe you use a PostgreSQL database instead, or SQLite, or some other kind of authentication mechanism entirely. LBBS doesn't dictate that users be stored in a certain type of file on disk, or even locally at all. Since auth providers can use any DBMS, API, etc. you could easily set up a BBS server fleet, all sharing the same users. The point is authentication is handled in a very flexible manner. (Obviously, somebody will need to write a module to handle authentication the way you want to, but this can be done without touching the BBS core at all.)

At a high level, incoming connections are accepted by a network comm driver using a socket. The connection is accepted and each network driver does its own preliminary handling of the connection, such as getting the terminal size. Then, a thread is spawned to handle the node and a pseudoterminal (PTY) is created, with the master side connected to the socket file descriptor and the slave side used for all node I/O. For example, to put the terminal in non-canonical mode or enable/disable echo, these operations are performed on the slave side of the node's PTY.

Some network drivers, such as net_ssh currently create a pseudoterminal internally, such that the master end of the SSH pseudoterminal is connected to the libssh file descriptor, and the slave side is used as the node's master PTY fd (as opposed to the socket fd directly).

LBBS does not use ncurses to draw to the screen, partly for simplicity, and partly because ncurses is not multithread safe. While it is possible to compile ncurses such that it has support for threading, this version is not highly portable or often used, and even the maintainer of ncurses discourages using it. Instead, menus are generally generated dynamically directly by LBBS, based on the node's terminal dimensions, although sysops may also manually create menus that are displayed instead.

Menus are the heart of the BBS and where a lot of the action is, both for users and from an architecture perspective. After a user logs in, the BBS node is dropped into the menu routines which handle all the work of generating and displaying menus and options, reading options from users, and taking the appropriate action, such as executing a program, another module, or displaying a submenu.

Directory Structure

Most code is documented using doxygen, and each source file describes its purpose. The LBBS source is organized into several key directories:

  • bbs - Source files that comprise the main lbbs binary. This is the "BBS core".
  • configs - Sample config files for LBBS modules and settings
  • doors - Door modules (both internal and external doors). In BBSing, the concept of a "door" refers to an interface between the BBS and an external application, used to access games, utilities, and other functionality not part of the BBS program itself. In LBBS, door modules are actually BBS modules, but they are not part of the BBS core, so are external in that sense only. Door modules can call LBBS functions, however, and run within the BBS process, so LBBS door modules offer enhanced functionality beyond that provided with a raw door. To execute a true external program, use exec rather than door in menus.conf.
  • external - External programs that are not part of the BBS itself, but may be useful supplements or programs to use in conjunction with it. For example, these can be executed as external programs from within the BBS, but they could also be run on their own.
  • include - Header files for core files
  • modules - General modules
  • nets - Network login services / communication driver modules
  • scripts - Useful scripts for use with LBBS
  • terms - Reserved for possible future terminal modules, not yet used
  • tests - Test framework for black box testing

LBBS, once installed, uses several system directories:

  • /etc/lbbs/ - config files
  • /usr/sbin/lbbs - LBBS binary
  • /usr/lib/lbbs/modules/ - shared object modules
  • /var/lib/lbbs/ - General LBBS resources
    • /var/lib/lbbs/external - External programs
    • /var/lib/lbbs/scripts - Useful scripts for use with LBBS
  • /var/log/lbbs/ - log directory

Additionally, modules (e.g. the mail server, newsgroup server, etc.) may use their own directories for storing data. These directories are configurable.

Make Targets

You can compile and link all the files in a directory containing source files simply by specifying the directory, e.g.:

  • make bbs
  • make doors
  • make modules
  • make nets

To compile everything, run make all, or simply make.

To install the LBBS binary, all shared object modules, and all external programs, run make install.

To create the config directory with sample configuration files, run make samples.

To delete all compiled code to ensure all source code is cleanly recompiled, run make clean.

Some targets are also included to aid developers in debugging the BBS or sysops in tracking down bugs. You will need valgrind installed (apt-get install valgrind):

  • make valgrind - Run valgrind and log all results to valgrind.txt. If you suspect a memory leak, you must attach this file when opening an issue.
  • make valgrindsupp - Generate suppression list from valgrind findings. You should not do this without a good understanding of the findings from the previous step.
  • make valgrindfd - Run valgrind but show findings in the foreground, rather than redirecting them to a log file.
  • make helgrind - Run helgrind in the foreground. This is useful for debugging locking.

Most stuff is commented for doxygen. You can generate the doxygen docs by running make doxygen (you may need to run apt-get install -y doxygen graphviz first)

Debugging

LBBS includes a number of builtin tools to assist with debugging, in addition to using valgrind as described above. You can turn on debugging by using the -d option on startup (up to 10 d's), setting a debug level in bbs.conf, or changing the debug level at runtime using the /debug command. If you submit an issue, you must provide full debug (:code:`debug=10`).

From the sysop console, you can run /threads to show running threads, helpful if you suspect threading-related issues. Running /fds will show all open file descriptors.

Tests

LBBS includes unit tests for functionality that can be tested individually. These can be run using /runtests from the sysop console.

A test framework is also included for black box testing of modules. The tests can be compiled using make tests and run using tests/test from the source directory. To run just a specific test, you can use the -t option: consult the help (tests/test -?) for program usage.

Note that although the tests use isolated configuration and runtime directories, they currently do not log to a separate log file, so you may wish to avoid running the test framework on a production system to avoid any "mingling" of test executions and normal production usage. The test framework will also stop the BBS before running, so it is best run in a dedicated development environment.

The test framework will return 0 if all tests (or the specified test) completed successfully and nonzero if any test(s) failed.

Dumper Script

The /var/lib/lbbs/scripts/bbs_dumper.sh script can be helpful when trying to get backtraces of LBBS.

Usage:

  • ./bbs_dumper.sh pid - Get PID of running BBS process
  • ./bbs_dumper.sh term - Terminate running BBS process (SIGKILL)
  • ./bbs_dumper.sh term - Quit running BBS process (SIGQUIT)
  • ./bbs_dumper.sh postdump - Obtain a backtrace from a core dump file
  • ./bbs_dumper.sh livedump - Obtain a backtrace from a currently running LBBS process

Note that if the BBS was compiled with optimizations enabled (anything except -O0, e.g -Og, -O1, -O2, -O3), then some variables may be optimized out in the backtrace. If you submit an issue, please recompile the BBS without optimization (change to -O0 in the top-level Makefile) and get a backtrace from an unoptimized system. Otherwise, important details may be missing as the backtrace is incomplete.

If you are not getting core dumps, ensure the current directory (in which the BBS was started or is currently running) is writable by the BBS user. Otherwise, it cannot dump a core there.

ABI Compatibility

Some projects strive to preserve ABI (Application Binary Interface) compatibility as much as possible when making changes (e.g. no breaking ABI changes allowed within a major revision).

While it is certainly not an objective to break ABI, it should be preferred to break ABI if necessary when making changes (e.g. adding arguments to a function) when doing it a different way would result in less maintainable or clunkier code in the long run.

For example, if the original function is still useful, it can still call the new function under the hood (which would preserve ABI), but if not, the original prototype should simply be expanded.

Likewise, when adding members to a struct (which can break ABI if not placed at the end), members should be added at the most logical place, not necessarily at the end.

In essence, changes will not strive to preserve ABI if that is the sole purpose of making a change a particular way.

The implication of this development philosophy is that users should not expect any ABI compatibility between versions from different points in time. Mixing files from different source revisions may result in an unstable system. You should always fully recompile LBBS from source when building a new or updated version.

To make it easier for people to keep track of breaking changes, the following policies should be adhered to:

  • If any ABI compatibility (i.e. C code) is broken, at least the minor version number (and possibly the major one) must be incremented.
  • In general, if any user-facing functionality becomes backwards-incompatible, the major version number must be incremented.

Coding Guidelines

Please follow the coding guidelines used in this repository. They are by and large K&R C, importantly:

  • Use tabs, not spaces.
  • Indent properly. Functions (only) should have the opening brace on their own line.
  • Braces denoting code blocks are always required, even for single-statement if, for, while, etc. where the braces are technically optional.
  • Use /* multi-line C89 */ comments only, not // single-line C99 comments.
  • Trim all trailing whitespace.
  • All public functions (anything in header files) should be documented using doxygen.
  • Add unit tests if possible (modules only).
  • For complex functionality, add black box tests in the test framework.
  • Avoid C functions that are not multi-thread safe.
  • Do not typedef structs
  • If there is a BBS function to do something, use it. (e.g. use the bbs_pthread_create wrapper, not pthread_create directly).
  • All source files should use UNIX line endings (LF). However, config files should use DOS/Windows line endings (CR LF). This is so that if Windows users open a config file in an old version of Notepad, it displays properly.

lbbs's People

Contributors

interlinked1 avatar larsks avatar marrold avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

lbbs's Issues

net_ssh: Use after free on node cleanup

Use after free on node cleanup for SSH sessions. Stack traces from valgrind:

DEBUG[86175]: thread.c:136 __thread_unregister: Thread 86176 has been joined by thread 86175 at net_ssh.c:871 handle_session()
==86147== Thread 16:
==86147== Invalid read of size 8
==86147==    at 0xD3131D1: handle_session (net_ssh.c:879)
==86147==    by 0xD3136FB: ssh_connection (net_ssh.c:1499)
==86147==    by 0x147A16: thread_run (thread.c:375)
==86147==    by 0x50F8043: start_thread (pthread_create.c:442)
==86147==    by 0x517787F: clone (clone.S:100)
==86147==  Address 0xc95a378 is 152 bytes inside a block of size 352 free'd
==86147==    at 0x484317B: free (vg_replace_malloc.c:872)
==86147==    by 0x1348F0: bbs_node_unlink (node.c:602)
==86147==    by 0x136176: bbs_node_handler (node.c:1432)
==86147==    by 0x147A16: thread_run (thread.c:375)
==86147==    by 0x50F8043: start_thread (pthread_create.c:442)
==86147==    by 0x517787F: clone (clone.S:100)
==86147==  Block was alloc'd at
==86147==    at 0x48455EF: calloc (vg_replace_malloc.c:1328)
==86147==    by 0x117963: __bbs_calloc (alloc.c:83)
==86147==    by 0x13372C: __bbs_node_request (node.c:226)
==86147==    by 0xD3139CF: pty_request (net_ssh.c:476)
==86147==    by 0xD34E822: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86147==    by 0xD34FAEF: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86147==    by 0xD33DE06: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86147==    by 0xD3556AF: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86147==    by 0xD355E96: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86147==    by 0xD3607DF: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86147==    by 0xD35C8D9: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86147==    by 0xD31305C: handle_session (net_ssh.c:776)
==86147==

 1 errors in context 1 of 4:
==86366== Thread 16:
==86366== Invalid read of size 8
==86366==    at 0xD3131D1: handle_session (net_ssh.c:879)
==86366==    by 0xD3136FB: ssh_connection (net_ssh.c:1499)
==86366==    by 0x147A16: thread_run (thread.c:375)
==86366==    by 0x50F8043: start_thread (pthread_create.c:442)
==86366==    by 0x517787F: clone (clone.S:100)
==86366==  Address 0xc946588 is 152 bytes inside a block of size 352 free'd
==86366==    at 0x484317B: free (vg_replace_malloc.c:872)
==86366==    by 0x136176: bbs_node_handler (node.c:1432)
==86366==    by 0x147A16: thread_run (thread.c:375)
==86366==    by 0x50F8043: start_thread (pthread_create.c:442)
==86366==    by 0x517787F: clone (clone.S:100)
==86366==  Block was alloc'd at
==86366==    at 0x48455EF: calloc (vg_replace_malloc.c:1328)
==86366==    by 0x117963: __bbs_calloc (alloc.c:83)
==86366==    by 0x13372C: __bbs_node_request (node.c:226)
==86366==    by 0xD3139CF: pty_request (net_ssh.c:476)
==86366==    by 0xD34E822: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86366==    by 0xD34FAEF: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86366==    by 0xD33DE06: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86366==    by 0xD3556AF: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86366==    by 0xD355E96: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86366==    by 0xD3607DF: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86366==    by 0xD35C8D9: ??? (in /usr/lib/x86_64-linux-gnu/libssh.so.4.9.5)
==86366==    by 0xD31305C: handle_session (net_ssh.c:776)

Errors when trying to compile LBBS from source

Hi,
I'm getting the following errors in Ubuntu 20.04 when trying to compile LBBS. I made sure all packages were up-to-date before proceeding, and ran the install_prereq.sh script to ensure all the required compilation libraries were installer. However, when I run the make command, I get these errors.

/bin/sh: 1: valgrind: not found
/bin/sh: 1: valgrind: not found
/bin/sh: 1: test: -ge: unexpected operator
+--------- make bbs ---------+
make --no-builtin-rules -C bbs all
make[1]: Entering directory '/usr/src/lbbs/bbs'
== Compiling bbs/history.o
gcc -Wall -Werror -Wunused -Wextra -Wmaybe-uninitialized -Wstrict-prototypes -Wm
issing-prototypes -Wdangling-else -Wdeclaration-after-statement -Wmissing-declar
ations -Wno-deprecated-declarations -Wmissing-format-attribute -Wnull-dereferenc
e -Wformat=2 -Wshadow -Wsizeof-pointer-memaccess -std=gnu99 -pthread -O0 -g -Wst
ack-protector -fno-omit-frame-pointer -fwrapv -D_FORTIFY_SOURCE=2 -DBBS_IN_CORE
-I.. -c history.c
history.c:25:10: fatal error: readline/history.h: No such file or directory
25 | #include <readline/history.h>
| ^~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [Makefile:16: history.o] Error 1
make[1]: Leaving directory '/usr/src/lbbs/bbs'
make: *** [Makefile:55: bbs] Error 2

I cloned everything into /usr/src/lbbs as highlighted in the readme.

Mail not working

Mail doesn't seem to work on my system, do you know what I am missing?

Thanks

[2024-04-12 00:35:49.852]   DEBUG[66]: socket.c:1652 bbs_node_poll: Node 2: poll returned 1
[2024-04-12 00:35:49.852]   DEBUG[66]: socket.c:1782 bbs_node_read: Node 2: read 1 byte (77)
[2024-04-12 00:35:49.853]    -- Node 2 selected option 'M' at menu(1) 'main'
[2024-04-12 00:35:49.853]   DEBUG[66]: variables.c:570 substitute_vars: Substituted 'Mail' to 'Mail'
[2024-04-12 00:35:49.854]   DEBUG[66]: variables.c:570 substitute_vars: Substituted 'mail' to 'mail'
[2024-04-12 00:35:49.854]   DEBUG[66]: handler.c:161 menu_handler_exec: Executing menu handler door (mail)
[2024-04-12 00:35:49.854]    -- Created semi-permanent login token for marrold
[2024-04-12 00:35:49.854]   DEBUG[66]: system.c:777 __bbs_execvpe_fd: node: 0x7ff234000c50, usenode: 1, fdin: -1, fdout: -1, filename: evergreen, isolated: no
[2024-04-12 00:35:49.854]   DEBUG[66]: system.c:796 __bbs_execvpe_fd: sid: 1, tcpgrp: -1, term: syncterm
[2024-04-12 00:35:49.856]   DEBUG[66]: node.c:1130 bbs_node_update_winsize: Sending SIGWINCH to foreground process 81 for node 2
[2024-04-12 00:35:49.857]   DEBUG[66]: system.c:1157 __bbs_execvpe_fd: Waiting for process 81 to exit
[2024-04-12 00:35:49.863]   DEBUG[66]: system.c:239 waitpidexit: Process 81 (evergreen) exited, status 0
[2024-04-12 00:35:49.864]   DEBUG[66]: system.c:266 waitpidexit: Command execution finished (evergreen): res = 0
[2024-04-12 00:35:49.864]   DEBUG[66]: auth.c:309 auth_token_destory: Purging temporary login token for marrold
[2024-04-12 00:35:49.864]   DEBUG[66]: handler.c:163 menu_handler_exec: Menu handler door returned 0
[2024-04-12 00:35:49.865]    -- Node 2 executing menu(1) 'main'
[2024-04-12 00:35:49.865]   DEBUG[66]: menu.c:263 display_menu: Menu has 11 total options

net_imap: Thunderbird clients infinite loop if BODY[] not returned

Thunderbird-based clients will enter an infinite loop trying to fetch the BODY[] is they ask for it, since net_imap does not yet support this. The FETCH response will be empty, causing clients to loop forever until the user manually closes them.

[2023-06-03 15:24:40.630]   DEBUG[8163]: net_imap.c:4667 process_fetch: 0x7fb3fdc575d0 <= * 44 FETCH (RFC822.SIZE 172442 UID 96)
[2023-06-03 15:24:40.630]   DEBUG[8163]: net_imap.c:4705 process_fetch: 0x7fb3fdc575d0 <= 1551 OK UID FETCH Completed
[2023-06-03 15:24:40.649]   DEBUG[8163]: net_imap.c:9125 handle_client: 0x7fb3fdc575d0 => 1552 UID fetch 96 (UID RFC822.SIZE BODY.PEEK[]<99614720.65536>)
[2023-06-03 15:24:40.650] WARNING[8163]: net_imap.c:4564 process_fetch: Unsupported BODY[] argument: []<99614720.65536>
[2023-06-03 15:24:40.650]   DEBUG[8163]: net_imap.c:4667 process_fetch: 0x7fb3fdc575d0 <= * 44 FETCH (RFC822.SIZE 172442 U

A surface level fix would prevent clients from infinite looping in this manner, ideally disconnecting them after some number of failed fetches in a row, but of course the real fix is to support this mandatory FETCH argument.

mod_webmail.c:312:71: error: 'MAILIMAP_STATUS_ATT_SIZE' undeclared

enviroment : actual debian, did the install_prereq.sh then when i try to make it i get this error.

mod_webmail.c:312:71: error: 'MAILIMAP_STATUS_ATT_SIZE' undeclared (first use in this function); did you mean 'MAILIMAP_STATUS_ATT_UNSEEN'?
312 | res |= mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_SIZE);
| ^~~~~~~~~~~~~~~~~~~~~~~~
|

any ideas?

Set cap ssl not working

I'll show you some screenshots of the log later, but I'm having problems with pointing it at an SSL certificate and a few other module errors.

net_imap: Unresolved dependencies at startup

On one system, I observed net_imap declining to load at startup due to mod_mimeparse not being loaded at the time.
This is a bug because dependencies should be loaded automatically during startup if they are not running:

[2023-07-15 23:30:15.356] WARNING[26309]: module.c:269 load_dlopen: Module net_imap.so didn't register itself during load?
[2023-07-15 23:30:15.356]   ERROR[26309]: module.c:276 load_dlopen: Error loading module 'net_imap.so': /usr/lib/lbbs/modules/net_imap.so: undefined symbol: mime_make_bodystructure
[2023-07-15 23:30:15.356] WARNING[26309]: module.c:526 load_resource: Could not load dynamic module net_imap.so
[2023-07-15 23:30:15.356]   ERROR[26309]: module.c:786 on_file_autoload: Failed to autoload net_imap.so

tls.c: Segfault when calling SSL_read after a while?

Segfault that I've observed a few times, when calling SSL_read, specifically when receiving emails, but most likely related to the amount or velocity of data going through tls.c:

Prior to crash:

[2023-06-03 14:34:09.003]   DEBUG[4807]: net_smtp.c:2791 smtp_process: 0x7f456e7f3030 <= 354 Start mail input; end with a period on a line by itself
[2023-06-03 14:34:10.009]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [229 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [68 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [123 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [209 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [29 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [83 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [44 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [75 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [88 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [82 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [62 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [60 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [69 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [49 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [56 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [76 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [184 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [15 data bytes]
[2023-06-03 14:34:10.011]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [76 data bytes]
[2023-06-03 14:34:10.011]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [57 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [127 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [45 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [45 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [66 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [33 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [75 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [44 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [98 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [123 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [45 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [51 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [37 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [76 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [15 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [90 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [70 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [56 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [76 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [77 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [15 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [47 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [62 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [187 data bytes]
[2023-06-03 14:34:10.012]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [84 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [112 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [34 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [45 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [155 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [38 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [62 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [187 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [200 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [188 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [192 data bytes]
[2023-06-03 14:34:10.014]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [36 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [51 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [23 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [74 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [51 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [17 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [23 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [0 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [6 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [7 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [8 data bytes]
[2023-06-03 14:34:10.015]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [28 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [15 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [15 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [16 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [14 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [21 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [24 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [24 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [18 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [18 data bytes]
[2023-06-03 14:34:10.016]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [18 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [1 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [8 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [68 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4807]: net_smtp.c:2825 handle_client: 0x7f456e7f3030 => [12 data bytes]
[2023-06-03 14:34:10.010]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [87 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [131 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [192 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [158 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [167 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [72 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [121 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [244 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [121 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [215 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [392 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [121 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [244 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [336 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [149 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [215 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [149 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [216 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [149 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [244 data bytes]
[2023-06-03 14:34:10.017]   DEBUG[4810]: net_smtp.c:2825 handle_client: 0x7f45707f7030 => [121 data bytes]
BBS server disconnected

Backtrace:

Thread 1 (Thread 0x7f459b515700 (LWP 3835)):
#0  0x00007f4580000710 in  ()
#1  0x00007f459cb0b0fa in  () at /lib/x86_64-linux-gnu/libssl.so.1.1
#2  0x00007f459cb0b203 in SSL_read () at /lib/x86_64-linux-gnu/libssl.so.1.1
#3  0x0000557d69349e83 in ssl_io_thread (unused=unused@entry=0x0) at tls.c:333
        ssl = 0x7f4580003a90
        readpipe = 61
        ores = <optimized out>
        wres = <optimized out>
        sfd = <optimized out>
        i = 11
        res = 1
        pfds = 0x7f459402dc80
        readpipes = 0x7f459401c420
        ssl_list = 0x7f459402dcf0
        prevfds = 13
        oldnumfds = <optimized out>
        numfds = 13
        numssl = <optimized out>
        needcreate = 1
        buf = "250-REDACTED at your service [127.0.0.1]\r\n172.google.com [209.85.221.172])\r\n\tby REDACTED (Postfix) with ESMTPS id 0E26B22282\r\n\tfor REDACTED; Sat,  3 Jun 2023 13:56:02 +0000"...
        pending = <optimized out>
        inovertime = 0
        overtime = 0
        needprune = <optimized out>
        err_msg = '\000' <repeats 1023 times>
        __func__ = "ssl_io_thread"
#4  0x0000557d6934874a in thread_run (data=<optimized out>) at thread.c:352
        __cancel_buf =
            {__cancel_jmp_buf = {{__cancel_jmp_buf = {139936812501792, -132307393922977715, 0, 93997147288832, 139936935270144, 93997147292448, -132307393665028019, -6172156987892682675}, __mask_was_saved = 0}}, __pad = {0x7f459b514c90, 0x0, 0x0, 0x0}}
        __cancel_routine = 0x557d69348a20 <thread_unregister>
        __cancel_arg = 0x7f459b515700
        __not_first_call = <optimized out>
        ret = <optimized out>
        a =
          {start_routine = <optimized out>, data = <optimized out>, name = 0x557d6a92f500 "ssl_io_thread         started by thread 3832 at tls.c:666 setup_ssl_io()", detached = <optimized out>, killable = <optimized out>}
#5  0x00007f459c4dcfa3 in start_thread (arg=<optimized out>) at pthread_create.c:486
        ret = <optimized out>
        pd = <optimized out>
        now = <optimized out>
        unwind_buf =
              {cancel_jmp_buf = {{jmp_buf = {139936935270144, 45816111734730829, 140724971867070, 140724971867071, 139936935270144, 93997147292448, -132307393891520435, -132296428765433779}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
        not_first_call = <optimized out>
#6  0x00007f459c40c06f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

valgrind backtrace:

==384202== 1 errors in context 1 of 26:
==384202== Thread 2:
==384202== Invalid read of size 4
==384202==    at 0x4A475AD: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x104 is not stack'd, malloc'd or (recently) free'd
==384202==
==384202==
==384202== 1 errors in context 2 of 26:
==384202== Invalid read of size 8
==384202==    at 0x4A475A6: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x10cdaec8 is 168 bytes inside a block of size 6,280 free'd
==384202==    at 0x48399AB: free (vg_replace_malloc.c:538)
==384202==    by 0x1423C6: ssl_close (tls.c:628)
==384202==    by 0xAA5B121: smtp_handler (net_smtp.c:2877)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Block was alloc'd at
==384202==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==384202==    by 0x4C45349: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==384202==    by 0x4A56BD4: SSL_new (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x141BC5: ssl_new_accept (tls.c:479)
==384202==    by 0xAA5AF7C: handle_client (net_smtp.c:2835)
==384202==    by 0xAA5B10A: smtp_handler (net_smtp.c:2872)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==
==384202==
==384202== 1 errors in context 3 of 26:
==384202== Invalid read of size 8
==384202==    at 0x4A52474: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x10cdae28 is 8 bytes inside a block of size 6,280 free'd
==384202==    at 0x48399AB: free (vg_replace_malloc.c:538)
==384202==    by 0x1423C6: ssl_close (tls.c:628)
==384202==    by 0xAA5B121: smtp_handler (net_smtp.c:2877)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Block was alloc'd at
==384202==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==384202==    by 0x4C45349: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==384202==    by 0x4A56BD4: SSL_new (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x141BC5: ssl_new_accept (tls.c:479)
==384202==    by 0xAA5AF7C: handle_client (net_smtp.c:2835)
==384202==    by 0xAA5B10A: smtp_handler (net_smtp.c:2872)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==
==384202==
==384202== 1 errors in context 4 of 26:
==384202== Invalid read of size 1
==384202==    at 0x4A52449: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x10cdb3f9 is 1,497 bytes inside a block of size 6,280 free'd
==384202==    at 0x48399AB: free (vg_replace_malloc.c:538)
==384202==    by 0x1423C6: ssl_close (tls.c:628)
==384202==    by 0xAA5B121: smtp_handler (net_smtp.c:2877)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Block was alloc'd at
==384202==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==384202==    by 0x4C45349: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==384202==    by 0x4A56BD4: SSL_new (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x141BC5: ssl_new_accept (tls.c:479)
==384202==    by 0xAA5AF7C: handle_client (net_smtp.c:2835)
==384202==    by 0xAA5B10A: smtp_handler (net_smtp.c:2872)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==
==384202==
==384202== 1 errors in context 5 of 26:
==384202== Invalid read of size 4
==384202==    at 0x4A68E68: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A52448: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x10cdaea4 is 132 bytes inside a block of size 6,280 free'd
==384202==    at 0x48399AB: free (vg_replace_malloc.c:538)
==384202==    by 0x1423C6: ssl_close (tls.c:628)
==384202==    by 0xAA5B121: smtp_handler (net_smtp.c:2877)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Block was alloc'd at
==384202==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==384202==    by 0x4C45349: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==384202==    by 0x4A56BD4: SSL_new (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x141BC5: ssl_new_accept (tls.c:479)
==384202==    by 0xAA5AF7C: handle_client (net_smtp.c:2835)
==384202==    by 0xAA5B10A: smtp_handler (net_smtp.c:2872)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==
==384202==
==384202== 1 errors in context 6 of 26:
==384202== Invalid read of size 4
==384202==    at 0x4A68E15: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A52448: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x10cdae58 is 56 bytes inside a block of size 6,280 free'd
==384202==    at 0x48399AB: free (vg_replace_malloc.c:538)
==384202==    by 0x1423C6: ssl_close (tls.c:628)
==384202==    by 0xAA5B121: smtp_handler (net_smtp.c:2877)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Block was alloc'd at
==384202==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==384202==    by 0x4C45349: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==384202==    by 0x4A56BD4: SSL_new (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x141BC5: ssl_new_accept (tls.c:479)
==384202==    by 0xAA5AF7C: handle_client (net_smtp.c:2835)
==384202==    by 0xAA5B10A: smtp_handler (net_smtp.c:2872)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==
==384202==
==384202== 1 errors in context 7 of 26:
==384202== Invalid read of size 4
==384202==    at 0x4A52429: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x10cdaea4 is 132 bytes inside a block of size 6,280 free'd
==384202==    at 0x48399AB: free (vg_replace_malloc.c:538)
==384202==    by 0x1423C6: ssl_close (tls.c:628)
==384202==    by 0xAA5B121: smtp_handler (net_smtp.c:2877)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Block was alloc'd at
==384202==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==384202==    by 0x4C45349: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==384202==    by 0x4A56BD4: SSL_new (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x141BC5: ssl_new_accept (tls.c:479)
==384202==    by 0xAA5AF7C: handle_client (net_smtp.c:2835)
==384202==    by 0xAA5B10A: smtp_handler (net_smtp.c:2872)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==
==384202==
==384202== 1 errors in context 8 of 26:
==384202== Invalid read of size 4
==384202==    at 0x4A52418: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x10cdae64 is 68 bytes inside a block of size 6,280 free'd
==384202==    at 0x48399AB: free (vg_replace_malloc.c:538)
==384202==    by 0x1423C6: ssl_close (tls.c:628)
==384202==    by 0xAA5B121: smtp_handler (net_smtp.c:2877)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Block was alloc'd at
==384202==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==384202==    by 0x4C45349: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==384202==    by 0x4A56BD4: SSL_new (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x141BC5: ssl_new_accept (tls.c:479)
==384202==    by 0xAA5AF7C: handle_client (net_smtp.c:2835)
==384202==    by 0xAA5B10A: smtp_handler (net_smtp.c:2872)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==
==384202==
==384202== 1 errors in context 9 of 26:
==384202== Invalid read of size 8
==384202==    at 0x4A5240D: ??? (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x4A525A2: SSL_read (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x1413A3: ssl_io_thread (tls.c:333)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Address 0x10cdae50 is 48 bytes inside a block of size 6,280 free'd
==384202==    at 0x48399AB: free (vg_replace_malloc.c:538)
==384202==    by 0x1423C6: ssl_close (tls.c:628)
==384202==    by 0xAA5B121: smtp_handler (net_smtp.c:2877)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)
==384202==  Block was alloc'd at
==384202==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==384202==    by 0x4C45349: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==384202==    by 0x4A56BD4: SSL_new (in /usr/lib/x86_64-linux-gnu/libssl.so.1.1)
==384202==    by 0x141BC5: ssl_new_accept (tls.c:479)
==384202==    by 0xAA5AF7C: handle_client (net_smtp.c:2835)
==384202==    by 0xAA5B10A: smtp_handler (net_smtp.c:2872)
==384202==    by 0xAA5B1D0: __smtp_handler (net_smtp.c:2893)
==384202==    by 0x1401B3: thread_run (thread.c:352)
==384202==    by 0x4EA7EA6: start_thread (pthread_create.c:477)
==384202==    by 0x4FBDA2E: clone (clone.S:95)

system.c: SIGINT sent to child process can cause entire BBS to shut down

I've seen several instances where an entire BBS server shuts down (cleanly) because a child process exited, but this shouldn't be happening.

e.g.:

[2023-08-17 12:30:45.829] VERBOSE[826200]: menu.c:606 bbs_menu_run: Node 4 selected option 'F' at menu(2) 'games'
[2023-08-17 12:30:45.831]   DEBUG[826200]: variables.c:496 bbs_node_substitute_vars: Substituted '/usr/games/go-fish' to '/usr/games/go-fish'
[2023-08-17 12:30:45.831]   DEBUG[826200]: handler.c:176 menu_handler_exec: Executing menu handler exec (/usr/games/go-fish)
[2023-08-17 12:30:45.831]   DEBUG[826200]: term.c:116 bbs_node_set_input: Node 4 (fd 103): input now buffered, echo enabled
[2023-08-17 12:30:45.831]   DEBUG[826200]: system.c:646 __bbs_execvpe_fd: node: 0x7fdb7c00f700, usenode: 1, fdin: -1, fdout: -1, filename: /usr/games/go-fish, isolated: no
[2023-08-17 12:30:45.831]   DEBUG[826200]: system.c:665 __bbs_execvpe_fd: sid: 56685, tcpgrp: -1
[2023-08-17 12:30:45.834]   DEBUG[826200]: node.c:876 bbs_node_update_winsize: Sending SIGWINCH to foreground process 826222 for node 4
[2023-08-17 12:30:45.837]   DEBUG[826200]: system.c:931 __bbs_execvpe_fd: Waiting for process 826222 to exit
[2023-08-17 12:30:51.994]   DEBUG[826200]: system.c:180 waitpidexit: Process 826222 (/usr/games/go-fish) killed, signal 2
[2023-08-17 12:30:51.994]   DEBUG[826200]: system.c:197 waitpidexit: Command execution finished (/usr/games/go-fish): res = 0
[2023-08-17 12:30:51.994]   DEBUG[826200]: socket.c:2368 bbs_node_wait_key: Waiting 120000 ms for any input
[2023-08-17 12:30:51.994]   DEBUG[826200]: term.c:116 bbs_node_set_input: Node 4 (fd 103): input now unbuffered, echo disabled
[2023-08-17 12:30:51.994]   DEBUG[826201]: pty.c:659 pty_master: Sending SIGINT to process 826222
[2023-08-17 12:30:51.995]   DEBUG[779131]: bbs.c:620 __sigint_handler: Got SIGINT, requesting shutdown
[2023-08-17 12:30:51.995]   DEBUG[779131]: bbs.c:718 monitor_sig_flags: Shutdown requested
[2023-08-17 12:30:51.995]   DEBUG[779131]: event.c:127 bbs_event_broadcast: Event SHUTDOWN dispatched and not consumed
[2023-08-17 12:30:51.995] VERBOSE[779131]: bbs.c:554 bbs_shutdown: Shutting down BBS
[2023-08-17 12:30:51.995]   DEBUG[779131]: node.c:489 node_shutdown: Terminating node 1
[2023-08-17 12:30:51.995]   DEBUG[779131]: node.c:552 node_shutdown: Waiting for node 1 to exit

pty.c/mod_sysop: File descriptor leak on shutdown

If a remote console is active during shutdown, a file descriptor leak (sometimes?) occurs of the PTY master, as shown here:

BBS has exited
==24657==
==24657== FILE DESCRIPTORS: 7 open (3 std) at exit.
==24657== Open file descriptor 19: /dev/ptmx
==24657==    at 0x5161E60: open (open64.c:41)
==24657==    by 0x13567D: posix_openpty (pty.c:61)
==24657==    by 0x136C1F: bbs_openpty (pty.c:94)
==24657==    by 0x136C1F: bbs_spawn_pty_master (pty.c:212)
==24657==    by 0x8417815: remote_sysop_listener (mod_sysop.c:508)
==24657==    by 0x145596: thread_run (thread.c:357)
==24657==    by 0x50F3043: start_thread (pthread_create.c:442)
==24657==    by 0x517285F: clone (clone.S:100)
==24657==
==24657== Open file descriptor 18: /dev/ptmx
==24657==    at 0x5161E60: open (open64.c:41)
==24657==    by 0x13567D: posix_openpty (pty.c:61)
==24657==    by 0x136C1F: bbs_openpty (pty.c:94)
==24657==    by 0x136C1F: bbs_spawn_pty_master (pty.c:212)
==24657==    by 0x8417815: remote_sysop_listener (mod_sysop.c:508)
==24657==    by 0x145596: thread_run (thread.c:357)
==24657==    by 0x50F3043: start_thread (pthread_create.c:442)
==24657==    by 0x517285F: clone (clone.S:100)
==24657==
==24657== Open file descriptor 16: /dev/ptmx
==24657==    at 0x5161E60: open (open64.c:41)
==24657==    by 0x13567D: posix_openpty (pty.c:61)
==24657==    by 0x136C1F: bbs_openpty (pty.c:94)
==24657==    by 0x136C1F: bbs_spawn_pty_master (pty.c:212)
==24657==    by 0x8417815: remote_sysop_listener (mod_sysop.c:508)
==24657==    by 0x145596: thread_run (thread.c:357)
==24657==    by 0x50F3043: start_thread (pthread_create.c:442)
==24657==    by 0x517285F: clone (clone.S:100)
==24657==
==24657== Open file descriptor 17: /dev/ptmx
==24657==    at 0x5161E60: open (open64.c:41)
==24657==    by 0x13567D: posix_openpty (pty.c:61)
==24657==    by 0x136C1F: bbs_openpty (pty.c:94)
==24657==    by 0x136C1F: bbs_spawn_pty_master (pty.c:212)
==24657==    by 0x8417815: remote_sysop_listener (mod_sysop.c:508)
==24657==    by 0x145596: thread_run (thread.c:357)
==24657==    by 0x50F3043: start_thread (pthread_create.c:442)
==24657==    by 0x517285F: clone (clone.S:100)
==24657==
==24657==
==24657== HEAP SUMMARY:
==24657==     in use at exit: 82,913 bytes in 764 blocks
==24657==   total heap usage: 14,851 allocs, 14,087 frees, 1,977,640 bytes allocated
==24657==

This is reflected in the (recently added) FD dump at shutdown, where /dev/ptmx is still open:

   16 => /dev/ptmx
Open files: 2 (7) / 1024
[2023-10-06 07:02:04.851]  === Finalizing shutdown

socket.c: SEGV in bbs_node_readline

[2023-10-08 22:46:26.199]   DEBUG[1833151]: socket.c:906 __bbs_tcp_listener: Accepting new TELNET connection from 218.150.111.190
[2023-10-08 22:46:26.199]   DEBUG[1833151]: socket.c:907 __bbs_tcp_listener: accepted fd = 54
[2023-10-08 22:46:26.199]   DEBUG[1833151]: node.c:275 __bbs_node_request: Allocated new node with ID 3
[2023-10-08 22:46:26.200]   DEBUG[1833151]: net_telnet.c:69 telnet_send_command: Sent Telnet command: IAC WILL ECHO
[2023-10-08 22:46:26.200]   DEBUG[1833151]: net_telnet.c:69 telnet_send_command: Sent Telnet command: IAC DO NAWS
[2023-10-08 22:46:26.400]   DEBUG[1861098]: thread.c:95 thread_register: Thread 1861098 spawned from handler               started by thread 1833151 at socket.c:916 __bbs_tcp_listener()
[2023-10-08 22:46:26.401]   DEBUG[1861098]: node.c:1401 bbs_node_begin: Running BBS for node 3
[2023-10-08 22:46:26.401]    AUTH[1861098]: node.c:1402 bbs_node_begin: New TELNET connection to node 3 from 218.150.111.190:43329
[2023-10-08 22:46:26.401]   DEBUG[1861098]: node.c:389 bbs_node_safe_sleep: Sleeping on node 3 for 300 ms
[2023-10-08 22:46:26.402]   DEBUG[1861099]: thread.c:95 thread_register: Thread 1861099 spawned from pty_master            started by thread 1861098 at pty.c:241 bbs_pty_allocate()
[2023-10-08 22:46:27.153]   DEBUG[1861098]: socket.c:2462 bbs_node_wait_key: Waiting 75000 ms for any input
[2023-10-08 22:46:27.153]   DEBUG[1861098]: term.c:116 bbs_node_set_input: Node 3 (fd 58): input now unbuffered, echo disabled
[2023-10-08 22:46:28.303] WARNING[1861094]: socket.c:1497 bbs_node_read: Node 4 has no active slave fd
[2023-10-08 22:46:28.316]   DEBUG[1861098]: socket.c:1951 bbs_node_flush_input: Flushed 3 bytes
Segmentation fault (core dumped)

Thread 1 (Thread 0x7fa2f27f46c0 (LWP 1861094)):
#0  __memchr_avx2 () at ../sysdeps/x86_64/multiarch/memchr-avx2.S:224
#1  0x0000562acfeaa45d in bbs_node_readline (node=node@entry=0x7fa2f8004be0, ms=ms@entry=60000, buf=<optimized out>, buf@entry=0x7fa2f27f3990 "\377\373\037\377\372\037", len=len@entry=64) at socket.c:1772
        bytes = 18446744073709551615
        res = <optimized out>
        left = <optimized out>
        bytes_read = <optimized out>
        startbuf = 0x7fa2f27f3990 "\377\373\037\377\372\037"
        term = <optimized out>
        nterm = 0x7fa2f27f3996 ""
        keep_trying = <optimized out>
        __func__ = "bbs_node_readline"
#2  0x0000562acfe9d6f2 in authenticate (node=node@entry=0x7fa2f8004be0) at node.c:1086
        attempts = 1
        username = "\377\373\037\377\372\037\000P\000\030\377\360telnet\000\000\000\000\000\000\340K\000\370\242\177\000\000\001\005\354\317*V\000\0008@\354\317*V\000\0000;\177\362\242\177\000\000\237m;\036\243\177\000"
        password = '\000' <repeats 63 times>
        __func__ = "authenticate"
#3  0x0000562acfe9f708 in node_intro (node=<optimized out>) at node.c:1224
        timebuf = "Sun Oct  8 2023 10:46 pm UTC"
        __func__ = "node_intro"
        __func__ = "node_handler_term"
        node = 0x7fa2f8004be0
#4  node_handler_term (node=0x7fa2f8004be0) at node.c:1371
        __func__ = "node_handler_term"
        node = 0x7fa2f8004be0
#5  bbs_node_handler (varg=varg@entry=0x7fa2f8004be0) at node.c:1425
        node = 0x7fa2f8004be0
#6  0x0000562acfeb07c7 in thread_run (data=<optimized out>) at thread.c:357
        __cancel_buf = {__cancel_jmp_buf = {{__cancel_jmp_buf = {140338061571952, 5789364465541002948, 1, 140337922250224, 140337922172976, 140337821466624, 5789364465413076676, 236315176599500484}, __mask_was_saved = 0}}, __pad = {0x7fa>
        __cancel_routine = 0x562acfeb0a80 <thread_unregister>
        __cancel_arg = 0x7fa2f27f46c0
        __not_first_call = <optimized out>
        ret = <optimized out>
        a = {start_routine = <optimized out>, data = <optimized out>, name = 0x7fa2f80115f0 "handler", ' ' <repeats 15 times>, "started by thread 1833151 at socket.c:916 __bbs_tcp_listener()", detached = <optimized out>}

socket.c: SEGV due to integer overflows

If bbs_node_read returns a negative value, this causes integer overflow since it is stored in a size_t, so the abort check is skipped and memchr attempts to scan 18446744073709551615 (== -1) bytes, causing the segfault.

Example 1:

[2023-10-19 03:21:19.696]   DEBUG[2042509]: node.c:562 node_shutdown: Shutdown pending finalization for node 2
[2023-10-19 03:21:19.696]   DEBUG[2042509]: node.c:579 node_free: Node 2 now freed
[2023-10-19 03:21:19.696]   == Node 2 has exited
[2023-10-19 03:21:19.696]   DEBUG[2042509]: thread.c:122 __thread_unregister: Thread 2042509 is exiting (detached)
[2023-10-19 03:21:21.194]   DEBUG[2042511]: socket.c:1791 bbs_node_readline: Received CR and/or LF from client, but no NUL?
[2023-10-19 03:21:21.194]   DEBUG[2042511]: socket.c:1791 bbs_node_readline: Received CR and/or LF from client, but no NUL?
[2023-10-19 03:21:21.194]   DEBUG[2042511]: socket.c:1791 bbs_node_readline: Received CR and/or LF from client, but no NUL?
[2023-10-19 03:21:21.194]   DEBUG[2042511]: socket.c:1791 bbs_node_readline: Received CR and/or LF from client, but no NUL?
[2023-10-19 03:21:22.332]   DEBUG[2042511]: socket.c:1791 bbs_node_readline: Received CR and/or LF from client, but no NUL?
[2023-10-19 03:21:22.337]   DEBUG[2042511]: auth.c:238 do_authenticate: Attempting password authentication for user 'root'
[2023-10-19 03:21:22.339]   DEBUG[2042511]: mod_mysql.c:361 sql_stmt_fetch: SQL STMT fetch returned no more data
[2023-10-19 03:21:22.473]   DEBUG[2042511]: auth.c:261 do_authenticate: Login rejected by all (1) auth provider
[2023-10-19 03:21:22.474]    AUTH[2042511]: auth.c:566 bbs_user_authenticate: Login attempt rejected for user root (wrong password)
[2023-10-19 03:21:22.474]   DEBUG[2042511]: socket.c:1073 bbs_cidr_match_ipv4: IP comparison (24): 007dacd2/000a7400
[2023-10-19 03:21:22.474]   DEBUG[2042511]: mod_events.c:175 process_bad_ip: IP address 125.172.210.217 blacklist score: 7/0/0/0 (last offense: 18s/17793306us ago
[2023-10-19 03:21:22.474]   DEBUG[2042511]: event.c:127 bbs_event_broadcast: Event NODE_LOGIN_FAILED dispatched and consumed
[2023-10-19 03:21:22.474]   DEBUG[2042511]: term.c:109 bbs_node_set_input: Buffering/echo settings (1/1) have not changed for node 1
[2023-10-19 03:21:31.831]   DEBUG[2042512]: thread.c:129 __thread_unregister: Thread 2042512 is exiting (must be joined)
[2023-10-19 03:21:37.394]   DEBUG[2038892]: socket.c:906 __bbs_tcp_listener: Accepting new TELNET connection from 125.172.210.217
[2023-10-19 03:21:37.394]   DEBUG[2038892]: socket.c:907 __bbs_tcp_listener: accepted fd = 48
[2023-10-19 03:21:37.395]   DEBUG[2038892]: node.c:275 __bbs_node_request: Allocated new node with ID 2
[2023-10-19 03:21:37.395]   DEBUG[2038892]: net_telnet.c:69 telnet_send_command: Sent Telnet command: IAC WILL ECHO
[2023-10-19 03:21:37.395]   DEBUG[2038892]: net_telnet.c:69 telnet_send_command: Sent Telnet command: IAC DO NAWS
[2023-10-19 03:21:37.595]   DEBUG[2042516]: thread.c:95 thread_register: Thread 2042516 spawned from handler               started by thread 2038892 at socket.c:916 __bbs_tcp_listener()
[2023-10-19 03:21:37.595]   DEBUG[2042516]: node.c:1401 bbs_node_begin: Running BBS for node 2
[2023-10-19 03:21:37.595]    AUTH[2042516]: node.c:1402 bbs_node_begin: New TELNET connection to node 2 from 125.172.210.217:60281
[2023-10-19 03:21:37.595]   DEBUG[2042516]: node.c:389 bbs_node_safe_sleep: Sleeping on node 2 for 300 ms
[2023-10-19 03:21:37.595]   DEBUG[2042517]: thread.c:95 thread_register: Thread 2042517 spawned from pty_master            started by thread 2042516 at pty.c:241 bbs_pty_allocate()
[2023-10-19 03:21:38.346]   DEBUG[2042516]: socket.c:2462 bbs_node_wait_key: Waiting 75000 ms for any input
[2023-10-19 03:21:38.346]   DEBUG[2042516]: term.c:116 bbs_node_set_input: Node 2 (fd 51): input now unbuffered, echo disabled
[2023-10-19 03:21:38.506] WARNING[2042511]: socket.c:1497 bbs_node_read: Node 1 has no active slave fd
[2023-10-19 03:21:38.518]   DEBUG[2042516]: socket.c:1951 bbs_node_flush_input: Flushed 3 bytes
[2023-10-19 03:21:38.518]   DEBUG[2042516]: term.c:116 bbs_node_set_input: Node 2 (fd 51): input now buffered, echo enabled
Segmentation fault (core dumped)

Thread 1 (Thread 0x7fbfe2fed6c0 (LWP 2042511)):
#0  __memchr_avx2 () at ../sysdeps/x86_64/multiarch/memchr-avx2.S:224
#1  0x000055b74e20f5dd in bbs_node_readline (node=node@entry=0x7fbfec015950, ms=ms@entry=60000, buf=<optimized out>, buf@entry=0x7fbfe2fec990 "root", len=len@entry=64) at socket.c:1772
        bytes = 18446744073709551615
        res = <optimized out>
        left = <optimized out>
        bytes_read = <optimized out>
        startbuf = 0x7fbfe2fec990 "root"
        term = <optimized out>
        nterm = 0x7fbfe2fec994 ""
        keep_trying = <optimized out>
        __func__ = "bbs_node_readline"
#2  0x000055b74e202872 in authenticate (node=node@entry=0x7fbfec015950) at node.c:1086
        attempts = 1
        username = "root\00012345\nenable\nsystem\nY\001\354\277\177\000\000\001U\"N\267U\000\0008\221\"N\267U\000\0000\313\376\342\277\177\000\000\237\375\345\022\300\177\000"
        password = '\000' <repeats 63 times>
        __func__ = "authenticate"
#3  0x000055b74e204888 in node_intro (node=<optimized out>) at node.c:1224
        timebuf = "Thu Oct 19 2023 03:21 am UTC"
        __func__ = "node_intro"
        __func__ = "node_handler_term"
        node = 0x7fbfec015950
#4  node_handler_term (node=0x7fbfec015950) at node.c:1371
        __func__ = "node_handler_term"
        node = 0x7fbfec015950
#5  bbs_node_handler (varg=varg@entry=0x7fbfec015950) at node.c:1425
        node = 0x7fbfec015950
#6  0x000055b74e215987 in thread_run (data=<optimized out>) at thread.c:357
        __cancel_buf = {__cancel_jmp_buf = {{__cancel_jmp_buf = {140462410996736, -825731675087032409, 1, 140462274910272, 140462633838640, 140462115442688, -825731675177209945, -6873846711898460249}, _>
        __cancel_routine = 0x55b74e215c40 <thread_unregister>
        __cancel_arg = 0x7fbfe2fed6c0
        __not_first_call = <optimized out>
        ret = <optimized out>
        a = {start_routine = <optimized out>, data = <optimized out>, name = 0x7fbfec001840 "handler", ' ' 

Example 2:

[2023-10-20 14:50:15.110]   DEBUG[2062868]: thread.c:122 __thread_unregister: Thread 2062868 is exiting (detached)
[2023-10-20 14:50:26.339] WARNING[2062862]: socket.c:1497 bbs_node_read: Node 1 has no active slave fd
Segmentation fault (core dumped)

Thread 1 (Thread 0x7fba557f26c0 (LWP 2062862)):
#0  __memchr_avx2 () at ../sysdeps/x86_64/multiarch/memchr-avx2.S:224
#1  0x000056265c2775dd in bbs_node_readline (node=node@entry=0x7fba5c0019d0, ms=ms@entry=60000, buf=<optimized out>, buf@entry=0x7fba557f1990 "sh", len=len@entry=64) at socket.c:1772
        bytes = 18446744073709551615
        res = <optimized out>
        left = <optimized out>
        bytes_read = <optimized out>
        startbuf = 0x7fba557f1990 "sh"
        term = <optimized out>
        nterm = 0x7fba557f1992 ""
        keep_trying = <optimized out>
        __func__ = "bbs_node_readline"
#2  0x000056265c26a872 in authenticate (node=node@entry=0x7fba5c0019d0) at node.c:1086
        attempts = 2
        username = "sh\000uxshell\000\377\377\377\377\377\000\000\000\000\000\000\000\000\320\031\000\\\272\177\000\000\001\325(\\&V\000\0008\021)\\&V\000\0000\033\177U\272\177\000\000\237}๋‚บ\177\000"
        password = '\000' <repeats 63 times>
        __func__ = "authenticate"
#3  0x000056265c26c888 in node_intro (node=<optimized out>) at node.c:1224
        timebuf = "Fri Oct 20 2023 02:50 pm UTC"
        __func__ = "node_intro"
        __func__ = "node_handler_term"
        node = 0x7fba5c0019d0
#4  node_handler_term (node=0x7fba5c0019d0) at node.c:1371

logger.c: Logging can get stuck on remote consoles

Split off from #12, since this is a separate issue:

Logging can also get stuck here due to write blocking forever:

RWLIST_RDLOCK(&remote_log_fds);
RWLIST_TRAVERSE(&remote_log_fds, rfd, entry) {
	if (fd_logging[rfd->fd]) {
		write(rfd->fd, fullbuf, (size_t) bytes);
	}
}
RWLIST_UNLOCK(&remote_log_fds);

A somewhat easy way to reproduce this (a scenario where this happens frequently) is if the consoles are being spammed with log messages and you exit a remote sysop console using ^C. Perhaps the console file descriptors are going away while they are being logged to, but that doesn't entirely make sense either.

This causes a deadlock, but only at the thread level, i.e. not all logging is broken. Because threads get stuck with a RDLOCK held on the remote logger fd's, it becomes impossible to obtain a WRLOCK, which blocks sysop console registration/unregistration. Otherwise, other logging and other threads remain nominally unaffected.

Action message isn't handled correctly on IRC to Discord Bridge

On IRC people use /me fairly frequently to describe something they're doing. e.g /me screams - I believe this is referred to as ACTION command.

Most clients display the message in italics, but on Discord it shows as:

<libera/exampleuser> ๏ฟฝACTION screams๏ฟฝ

It would be great if the message was displayed in italics, e.g screams

net_telnet: Dead sessions can linger around

I've noticed that the Telnet module seems prone to having dead sessions lingering around. This here appears to be the result of a port scan or some other kind of bot activity:

  # PROTOCOL   ELAPSED TRM SZE USER            MENU/PAGE            IP ADDRESS RPORT E B    TID RFD WFD MST SLV SPY SLV NAME
  1      TDD  38:29:32   0x  0 <Not Logged In>                  15.235.130.209 50694 Y Y     -1  25  25  -1  -1  -1
  2      TDD  63:14:15   0x  0 <Not Logged In>                 103.138.109.148 51092 Y Y     -1  29  29  -1  -1  -1
  3      TDD  63:14:15   0x  0 <Not Logged In>                 103.138.109.148 51093 Y Y     -1  30  30  -1  -1  -1
  4      TDD  63:13:59   0x  0 <Not Logged In>                 103.138.109.148 52258 Y Y  24246  31  31  -1  -1  -1
  5      TDD  63:13:59   0x  0 <Not Logged In>                 103.138.109.148 52263 Y Y  24246  32  32  -1  -1  -1
  6  TELNETS  62:38:06   0x  0 <Not Logged In>                 103.138.109.148 53791 Y Y     -1  33  33  -1  -1  -1
  7  TELNETS  62:38:06   0x  0 <Not Logged In>                 103.138.109.148 53790 Y Y     -1  34  34  -1  -1  -1
  8  TELNETS  62:37:51   0x  0 <Not Logged In>                 103.138.109.148 54326 Y Y     -1  35  35  -1  -1  -1
  9  TELNETS  62:37:51   0x  0 <Not Logged In>                 103.138.109.148 54325 Y Y     -1  36  36  -1  -1  -1
 10      TDD  38:29:16   0x  0 <Not Logged In>                  15.235.130.209 52215 Y Y     -1  26  26  -1  -1  -1
 11      TDD  38:29:16   0x  0 <Not Logged In>                  15.235.130.209 52224 Y Y     -1  27  27  -1  -1  -1
 12  TELNETS  37:54:36   0x  0 <Not Logged In>                  15.235.130.209 57809 Y Y     -1  28  28  -1  -1  -1
 13      TDD  38:29:32   0x  0 <Not Logged In>                  15.235.130.209 50682 Y Y     -1  39  39  -1  -1  -1
 14  TELNETS  37:54:36   0x  0 <Not Logged In>                  15.235.130.209 57810 Y Y     -1  37  37  -1  -1  -1
 15  TELNETS  37:54:20   0x  0 <Not Logged In>                  15.235.130.209 58325 Y Y     -1  38  38  -1  -1  -1
 16  TELNETS  37:54:20   0x  0 <Not Logged In>                  15.235.130.209 58326 Y Y     -1  40  40  -1  -1  -1
 17      TDD  15:17:21   0x  0 <Not Logged In>                     51.79.169.4 61699 Y Y     -1  41  41  -1  -1  -1
 18  TELNETS  30:53:21   0x  0 <Not Logged In>                  159.203.71.159 56398 Y Y     -1  48  48  -1  -1  -1
 19      TDD  15:17:06   0x  0 <Not Logged In>                     51.79.169.4 62358 Y Y     -1  42  42  -1  -1  -1
 20      TDD  22:04:58   0x  0 <Not Logged In>                   178.32.43.185 60000 Y Y     -1  53  53  -1  -1  -1
 21      TDD  15:17:06   0x  0 <Not Logged In>                     51.79.169.4 62360 Y Y     -1  43  43  -1  -1  -1
 22  TELNETS  14:42:18   0x  0 <Not Logged In>                     51.79.169.4 51540 Y Y     -1  44  44  -1  -1  -1
 23      TDD  15:17:21   0x  0 <Not Logged In>                     51.79.169.4 61694 Y Y     -1  47  47  -1  -1  -1
 24  TELNETS  14:42:18   0x  0 <Not Logged In>                     51.79.169.4 51542 Y Y     -1  45  45  -1  -1  -1
 25  TELNETS  14:42:03   0x  0 <Not Logged In>                     51.79.169.4 52100 Y Y     -1  46  46  -1  -1  -1
 26  TELNETS  14:42:03   0x  0 <Not Logged In>                     51.79.169.4 52101 Y Y     -1  49  49  -1  -1  -1

The dead sessions linger forever, although if kicked the nodes will go away. Some red flags here are:

  • Node sessions with either the same thread or no thread at all (-1)
  • Excessively long session length with no activity
  • No PTY slave (or PTY at all)

Old machines without ANSI support cause strange behaviour

I'm attempting to connect a BBC Micro (Emulator) up to the public Phreaknet BBS. It's from the early 1980s and doesn't support ANSI.

It asks me to hit enter twice. It then asks if I want ANSI support. When I hit N, it freezes for a while and then the connection closes.

It would be great if these old machines could be supported.

image

date and cal utilities don't work on a "stock" install

Hi,

I noticed the date and cal don't work on a "stock" install.

For both the screen "blinks" but no output is shown and I am returned to the utilities menu. There is nothing obvious in the logs so I'm not sure if I'm missing a dependency or something else.

Cheers

tls.c: SEGV on abrupt TLS session termination

3-10-04 00:07:18.710]   == Node 3 has exited
[2023-10-04 00:07:18.710]   DEBUG[1779897]: thread.c:122 __thread_unregister: Thread 1779897 is exiting (detached)
[2023-10-04 00:07:41.814]   ERROR[1762653]: tls.c:492 ssl_io_thread: TLS error: error:0A000126:SSL routines::unexpected eof while reading
[2023-10-04 00:07:41.814]   DEBUG[1762653]: tls.c:496 ssl_io_thread: SSL connection 0x7f7cb8012380 now marked as dead
[2023-10-04 00:07:41.814]   DEBUG[1762653]: tls.c:501 ssl_io_thread: SSL_read for 0x7f7cb8012380 returned 0 (SSL_ERROR_SSL)
[2023-10-04 00:07:41.814]   DEBUG[1762653]: tls.c:387 ssl_io_thread: Skipping dead SSL read connection 0x7f7cb8012380 at index 1 / 0
[2023-10-04 00:07:41.814]   DEBUG[1779902]: net_imap.c:4520 handle_client: 0x7f7c94ff66b0 => 4.7 LOGOUT
[2023-10-04 00:07:41.814]   DEBUG[1779902]: net_imap.c:4054 imap_process: 0x7f7c94ff66b0 <= * BYE IMAP4 Server logging out
[2023-10-04 00:07:41.814] WARNING[1762653]: tls.c:543 ssl_io_thread: Can't write to dead SSL connection 0x7f7cb8012380, discarding 32 bytes
[2023-10-04 00:07:41.814]   DEBUG[1779902]: net_imap.c:4055 imap_process: 0x7f7c94ff66b0 <= 4.7 OK LOGOUT completed
[2023-10-04 00:07:41.814] WARNING[1762653]: tls.c:543 ssl_io_thread: Can't write to dead SSL connection 0x7f7cb8012380, discarding 25 bytes
[2023-10-04 00:07:41.814]   DEBUG[1779902]: mod_mail.c:227 mailbox_dispatch_event: Dispatching mailbox event 'Logout'
[2023-10-04 00:07:41.814]   DEBUG[1762653]: tls.c:446 ssl_io_thread: SSL at index 2 / 1 = POLLHUP
[2023-10-04 00:07:41.814]   DEBUG[1762653]: tls.c:533 ssl_io_thread: read returned 0
[2023-10-04 00:07:41.814]   DEBUG[1762653]: tls.c:404 ssl_io_thread: SSL I/O thread now polling 9 -> 7 fds (3 connections)
[2023-10-04 00:07:41.814]   DEBUG[1779902]: net_imap.c:4599 __imap_handler: Node 5 has ended its IMAPS session
[2023-10-04 00:07:41.814]   DEBUG[1779902]: node.c:491 node_shutdown: Terminating node 5
[2023-10-04 00:07:41.814]   DEBUG[1779902]: node.c:562 node_shutdown: Shutdown pending finalization for node 5
[2023-10-04 00:07:41.814]   DEBUG[1779902]: node.c:579 node_free: Node 5 now freed
[2023-10-04 00:07:41.814]   == Node 5 has exited
[2023-10-04 00:07:41.814]   DEBUG[1779902]: thread.c:122 __thread_unregister: Thread 1779902 is exiting (detached)
[2023-10-04 00:07:41.819]   DEBUG[1779900]: net_imap.c:4520 handle_client: 0x7f7c8efea6b0 => DONE
[2023-10-04 00:07:41.819]   DEBUG[1779900]: net_imap.c:3767 idle_stop: 0x7f7c8efea6b0 <= 14.4 OK IDLE terminated
[2023-10-04 00:07:41.903]   DEBUG[1779900]: net_imap.c:4520 handle_client: 0x7f7c8efea6b0 => 15.4 CLOSE
[2023-10-04 00:07:41.903]   DEBUG[1779900]: net_imap.c:4181 imap_process: 0x7f7c8efea6b0 <= 15.4 OK CLOSE completed
[2023-10-04 00:07:41.990]   DEBUG[1779900]: net_imap.c:4520 handle_client: 0x7f7c8efea6b0 => 16.4 LOGOUT
[2023-10-04 00:07:41.990]   DEBUG[1779900]: net_imap.c:4054 imap_process: 0x7f7c8efea6b0 <= * BYE IMAP4 Server logging out
[2023-10-04 00:07:41.990]   DEBUG[1779900]: net_imap.c:4055 imap_process: 0x7f7c8efea6b0 <= 16.4 OK LOGOUT completed
[2023-10-04 00:07:41.990]   DEBUG[1779900]: mod_mail.c:227 mailbox_dispatch_event: Dispatching mailbox event 'Logout'
[2023-10-04 00:07:41.990]   DEBUG[1779900]: net_imap.c:4599 __imap_handler: Node 4 has ended its IMAPS session
[2023-10-04 00:07:41.990]   DEBUG[1779900]: node.c:491 node_shutdown: Terminating node 4
[2023-10-04 00:07:41.990]   DEBUG[1779900]: node.c:562 node_shutdown: Shutdown pending finalization for node 4
[2023-10-04 00:07:41.990]   DEBUG[1779900]: node.c:579 node_free: Node 4 now freed
[2023-10-04 00:07:41.990]   == Node 4 has exited
[2023-10-04 00:07:41.990]   DEBUG[1779900]: thread.c:122 __thread_unregister: Thread 1779900 is exiting (detached)
Segmentation fault (core dumped)

Thread 1 (Thread 0x7f7cbf63b6c0 (LWP 1762653)):
#0  0x0000000000000000 in  ()
#1  0x00007f7cc086c763 in SSL_read () at /lib/x86_64-linux-gnu/libssl.so.3
#2  0x000056471828e4c0 in ssl_io_thread (unused=unused@entry=0x0) at tls.c:479
        ssl = 0x7f7cb0576ec0
        readpipe = 59
        ores = <optimized out>
        wres = <optimized out>
        sfd = <optimized out>
        i = 1
        res = 1
        pfds = 0x7f7cb800a0a0
        readpipes = 0x7f7cb8002e40
        ssl_list = 0x7f7cb8015bd0
        prevfds = 7
        oldnumfds = <optimized out>
        numfds = 7
        numssl = <optimized out>
        needcreate = 0
        buf = "16.4 LOGOUT\r\n completed\r\ng out\r\nUsers\" \".\")) ((\"Shared Folders\" \".\"))\r\n13.4 NAMESPACE command completed\r\nST CHILDREN IDLE NOTIFY NAMESPACE QUOTA QUOTA=RES-STORAGE ID SASL-IR ACL SOR>
        pending = <optimized out>
        inovertime = 0
        overtime = 0
        err_msg = "error:0A000126:SSL routines::unexpected eof while reading", '\000' <repeats 966 times>
        __func__ = "ssl_io_thread"
#3  0x000056471828c3a7 in thread_run (data=<optimized out>) at thread.c:357
        __cancel_buf = {__cancel_jmp_buf = {{__cancel_jmp_buf = {140173639682928, -8880879192134578050, 0, 94863378829664, 140734316593216, 140173755265024, -8880879192258310018, -2974757314973593474}, __mask_was_>
        __cancel_routine = 0x56471828c660 <thread_unregister>
        __cancel_arg = 0x7f7cbf63b6c0
        __not_first_call = <optimized out>
        ret = <optimized out>
        a = {start_routine = <optimized out>, data = <optimized out>, name = 0x564719ff5160 "ssl_io_thread         started by thread 1762652 at tls.c:1067 setup_ssl_io()", detached = <optimized out>}
#4  0x00007f7cc00a8044 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442

Missing dependencies for bookworm-slim docker container

Hi,

I noticed the install_prereq.sh script doesn't install the following dependencies which are missing for the bookworm-slim docker image:

wget
bc

I would submit a PR but I don't know if you think these should be included for Fedora / FreeBSD etc or if this is an edge case and they shouldn't be included at all

Cheers

Reply function on Discord doesn't translate well to IRC

When people reply to message on Discord its contextless on IRC, as you just see the reply without any reference to the original message.

There's a few ways this could be improved:

  1. Warn them not to do that, like multi line messages
  2. Mention the user that's being replied to
  3. Quote the message that's being replied to

A few of us spoke about this and concluded #3 might be difficult due to character limits enforced by some IRC servers, and as multi-line messages aren't a thing you can't put the quote on one line and the reply on another without the risk of someone else's message appearing in between.

I think my preference would be #2, or perhaps #1 and #2 with the behaviour specified in the config.

Cheers

modify new user prompts

i would like to change the new user prompts to only ask for IRL name birthday town and city

mod_sysop: Segmentation fault on shutdown

If any remote consoles are active at shutdown, any attempts to shutdown or restart (whether from the foreground or a remote console) will cause a segfault during module unload. No segfault when replicated with valgrind.

This is likely more serious memory corruption since there appears to be stack corruption in the backtrace, no further details are available:

Other threads appear to be all right, which is a strong hint this is corruption caused when trying to unload mod_sysop. Possibly related to recent changes to try to move away from pthread_cancel in that module and some others?

Thread 1 (Thread 0x7f99cdffb6c0 (LWP 88031)):
#0  0x00007f99f0401a2a in  ()
#1  0x00007f99d8001270 in  ()
#2  0x0000002000000020 in  ()
#3  0x7900000000000000 in  ()
#4  0x0001003b00000020 in  ()
#5  0x0000000000000020 in  ()
#6  0x26bdeb69d0b5d354 in  ()
#7  0x00007f99cdffabc0 in  ()
#8  0x00007f99d80012c0 in  ()
#9  0x00007f99eaffc850 in  ()
#10 0x00007f99cd7fb000 in  ()
#11 0x26bdeb69d435d354 in  ()
#12 0x26bd9016a3e1d354 in  ()
#13 0x0000000000000000 in  ()

node.c: Invalid reads on node kicks from modules

Invalid memory accesses can occur if a node is kicked from a module by using /reload.

No noticeable functionality errors occur but it's certainly best not to read from freed memory. This logic will need to be refined to avoid that:

/reload net_nntp
[2023-03-12 12:16:29.937]   DEBUG[1825104]: module.c:568 unload_resource_nolock: Module net_nntp.so has use count 1
[2023-03-12 12:16:29.940]   DEBUG[1825104]: node.c:445 node_shutdown: Terminating node 1
[2023-03-12 12:16:29.941]   DEBUG[1825122]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-12 12:16:29.941]   DEBUG[1825122]: utils.c:128 bbs_fd_readline: read returned 0
[2023-03-12 12:16:29.943]   DEBUG[1825122]: net_nntp.c:1338 __nnsp_handler: Node 1 has ended its NNSP session
[2023-03-12 12:16:29.946]   DEBUG[1825122]: node.c:529 node_free: Node 1 now freed
[2023-03-12 12:16:29.947]   == Node 1 has exited
==1825098== Thread 7:
==1825098== Invalid read of size 4
==1825098==    at 0x12C4A0: node_shutdown (node.c:496)
==1825098==    by 0x12CAF0: bbs_node_shutdown_mod (node.c:597)
==1825098==    by 0x12999A: unload_resource_nolock (module.c:581)
==1825098==    by 0x129CB1: unload_resource (module.c:634)
==1825098==    by 0x12A886: bbs_module_reload (module.c:864)
==1825098==    by 0x689089A: sysop_command (mod_sysop.c:95)
==1825098==    by 0x6891BC1: sysop_handler (mod_sysop.c:394)
==1825098==    by 0x13900E: thread_run (thread.c:269)
==1825098==    by 0x4FE7EA6: start_thread (pthread_create.c:477)
==1825098==    by 0x5100A2E: clone (clone.S:95)
==1825098==  Address 0x5ef8df0 is 240 bytes inside a block of size 296 free'd
==1825098==    at 0x48399AB: free (vg_replace_malloc.c:538)
==1825098==    by 0x12C711: node_free (node.c:533)
==1825098==    by 0x12F7DF: bbs_node_exit (node.c:1254)
==1825098==    by 0xA1C3595: __nnsp_handler (net_nntp.c:1339)
==1825098==    by 0x13900E: thread_run (thread.c:269)
==1825098==    by 0x4FE7EA6: start_thread (pthread_create.c:477)
==1825098==    by 0x5100A2E: clone (clone.S:95)
==1825098==  Block was alloc'd at
==1825098==    at 0x483AB65: calloc (vg_replace_malloc.c:760)
==1825098==    by 0x12B7D1: __bbs_node_request (node.c:227)
==1825098==    by 0x133107: __bbs_tcp_listener (socket.c:472)
==1825098==    by 0x13329C: bbs_tcp_listener (socket.c:494)
==1825098==    by 0xA1C3614: nnsp_listener (net_nntp.c:1354)
==1825098==    by 0x13900E: thread_run (thread.c:269)
==1825098==    by 0x4FE7EA6: start_thread (pthread_create.c:477)
==1825098==    by 0x5100A2E: clone (clone.S:95)

A silly idea involving an SIP server

I think this might be kind of a ridiculous idea, but hear me out. How about integrate an SIP server into the bbs server and each user receives a randomly generated number between a certain set range and that will be there sip number ๐Ÿ˜€

net_imap, net_smtp: Problems with Eudora 7.1.0.9

Some incompatibilities noted while testing the BBS email servers (IMAP and SMTP, but not POP), with Eudora 7.1.0.9 on Windows 7. SSL connections did not work at all out of the box for me so these are only with plain text connections.

I know Eudora hasn't been updated since 2006, but these are generally issues on the server side, not with the client.

Trying to get the mailbox structure (IMAP) - stuck in infinite loop until cancelled:

[2023-03-15 20:04:03.186]   DEBUG[1924800]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:04:03.186]   DEBUG[1924800]: utils.c:145 bbs_fd_readline: Read 24 bytes (24 just now), processing 22 and leaving 0 leftover
[2023-03-15 20:04:03.187]   DEBUG[1924800]: net_imap.c:2405 handle_client: 0x7fad9affc4b0 => 00146 LIST "" Drafts.%
[2023-03-15 20:04:03.187]   DEBUG[1924800]: net_imap.c:940 handle_list: LIST traversal for '' 'Drafts.%' => Drafts.%
[2023-03-15 20:04:03.187]   DEBUG[1924800]: net_imap.c:985 handle_list: 0x7fad9affc4b0 <= * LIST (\HasChildren) "." "Drafts"
[2023-03-15 20:04:03.187]   DEBUG[1924800]: net_imap.c:991 handle_list: 0x7fad9affc4b0 <= 00146 OK LIST completed.
[2023-03-15 20:04:03.416]   DEBUG[1924800]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:04:03.416]   DEBUG[1924800]: utils.c:145 bbs_fd_readline: Read 24 bytes (24 just now), processing 22 and leaving 0 leftover
[2023-03-15 20:04:03.416]   DEBUG[1924800]: net_imap.c:2405 handle_client: 0x7fad9affc4b0 => 00147 LIST "" Drafts.%
[2023-03-15 20:04:03.416]   DEBUG[1924800]: net_imap.c:940 handle_list: LIST traversal for '' 'Drafts.%' => Drafts.%
[2023-03-15 20:04:03.417]   DEBUG[1924800]: net_imap.c:985 handle_list: 0x7fad9affc4b0 <= * LIST (\HasChildren) "." "Drafts"
[2023-03-15 20:04:03.417]   DEBUG[1924800]: net_imap.c:991 handle_list: 0x7fad9affc4b0 <= 00147 OK LIST completed.
[2023-03-15 20:04:03.646]   DEBUG[1924800]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:04:03.646]   DEBUG[1924800]: utils.c:145 bbs_fd_readline: Read 24 bytes (24 just now), processing 22 and leaving 0 leftover
[2023-03-15 20:04:03.646]   DEBUG[1924800]: net_imap.c:2405 handle_client: 0x7fad9affc4b0 => 00148 LIST "" Drafts.%
[2023-03-15 20:04:03.646]   DEBUG[1924800]: net_imap.c:940 handle_list: LIST traversal for '' 'Drafts.%' => Drafts.%
[2023-03-15 20:04:03.646]   DEBUG[1924800]: net_imap.c:985 handle_list: 0x7fad9affc4b0 <= * LIST (\HasChildren) "." "Drafts"
[2023-03-15 20:04:03.646]   DEBUG[1924800]: net_imap.c:991 handle_list: 0x7fad9affc4b0 <= 00148 OK LIST completed.
[2023-03-15 20:04:03.875]   DEBUG[1924800]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:04:03.875]   DEBUG[1924800]: utils.c:145 bbs_fd_readline: Read 24 bytes (24 just now), processing 22 and leaving 0 leftover
[2023-03-15 20:04:03.875]   DEBUG[1924800]: net_imap.c:2405 handle_client: 0x7fad9affc4b0 => 00149 LIST "" Drafts.%
[2023-03-15 20:04:03.875]   DEBUG[1924800]: net_imap.c:940 handle_list: LIST traversal for '' 'Drafts.%' => Drafts.%
[2023-03-15 20:04:03.875]   DEBUG[1924800]: net_imap.c:985 handle_list: 0x7fad9affc4b0 <= * LIST (\HasChildren) "." "Drafts"
[2023-03-15 20:04:03.875]   DEBUG[1924800]: net_imap.c:991 handle_list: 0x7fad9affc4b0 <= 00149 OK LIST completed.
[2023-03-15 20:04:04.100]   DEBUG[1924800]: socket.c:669 bbs_std_poll: poll returned 1

Trying to send an email:

[2023-03-15 20:04:47.315]   DEBUG[1924787]: socket.c:457 __bbs_tcp_listener: Accepting new SMTP (MSA) connection from 10.55.3.84
[2023-03-15 20:04:47.315]   DEBUG[1924787]: socket.c:470 __bbs_tcp_listener: accepted fd = 33
[2023-03-15 20:04:47.315]   DEBUG[1924787]: node.c:271 __bbs_node_request: Allocated new node with ID 3
[2023-03-15 20:04:47.316]   DEBUG[1924816]: thread.c:84 thread_register: Thread 1924816 spawned from handler               started by thread 1924787 at socket.c:479 __bbs_tcp_listener()
[2023-03-15 20:04:47.317]   DEBUG[1924816]: node.c:1236 bbs_node_begin: Running BBS for node 3
[2023-03-15 20:04:47.317]    AUTH[1924816]: node.c:1237 bbs_node_begin: New SMTP (MSA) connection to node 3 from 10.55.3.84
[2023-03-15 20:04:47.318]   DEBUG[1924816]: net_smtp.c:1880 handle_client: 0x7fad9a7fbab0 <= 220 10.55.1.38 ESMTP Service Ready
[2023-03-15 20:04:47.332]   DEBUG[1924816]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:04:47.333]   DEBUG[1924816]: utils.c:145 bbs_fd_readline: Read 33 bytes (33 just now), processing 31 and leaving 0 leftover
[2023-03-15 20:04:47.333]   DEBUG[1924816]: net_smtp.c:1895 handle_client: 0x7fad9a7fbab0 => EHLO INTERLINKED-PC2.10.55.1.38
[2023-03-15 20:04:47.333]   DEBUG[1924816]: net_smtp.c:235 handle_helo: 0x7fad9a7fbab0 <= 250-10.55.1.38 at your service [10.55.3.84]
[2023-03-15 20:04:47.333]   DEBUG[1924816]: net_smtp.c:240 handle_helo: 0x7fad9a7fbab0 <= 250-SIZE 300000
[2023-03-15 20:04:47.333]   DEBUG[1924816]: net_smtp.c:244 handle_helo: 0x7fad9a7fbab0 <= 250 ENHANCEDSTATUSCODES
[2023-03-15 20:04:47.548]   DEBUG[1924816]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:04:47.548]   DEBUG[1924816]: utils.c:145 bbs_fd_readline: Read 6 bytes (6 just now), processing 4 and leaving 0 leftover
[2023-03-15 20:04:47.548]   DEBUG[1924816]: net_smtp.c:1895 handle_client: 0x7fad9a7fbab0 => RSET
[2023-03-15 20:04:47.549]   DEBUG[1924816]: net_smtp.c:1703 smtp_process: 0x7fad9a7fbab0 <= 250 2.1.5 Flushed
[2023-03-15 20:04:47.559]   DEBUG[1924816]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:04:47.560]   DEBUG[1924816]: utils.c:145 bbs_fd_readline: Read 36 bytes (36 just now), processing 34 and leaving 0 leftover
[2023-03-15 20:04:47.560]   DEBUG[1924816]: net_smtp.c:1895 handle_client: 0x7fad9a7fbab0 => MAIL FROM:<[email protected]>
[2023-03-15 20:04:47.560]   DEBUG[1924816]: net_smtp.c:1753 smtp_process: 0x7fad9a7fbab0 <= 503 5.5.1 EHLO/HELO first.
[2023-03-15 20:04:47.572]   DEBUG[1924816]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:04:47.572]   DEBUG[1924816]: utils.c:145 bbs_fd_readline: Read 6 bytes (6 just now), processing 4 and leaving 0 leftover
[2023-03-15 20:04:47.572]   DEBUG[1924816]: net_smtp.c:1895 handle_client: 0x7fad9a7fbab0 => QUIT
[2023-03-15 20:04:47.572]   DEBUG[1924816]: net_smtp.c:1707 smtp_process: 0x7fad9a7fbab0 <= 221 2.0.0 Closing connection
[2023-03-15 20:04:47.572]   DEBUG[1924816]: net_smtp.c:1979 __msa_handler: Node 3 has ended its SMTP (MSA) session
[2023-03-15 20:04:47.572]   DEBUG[1924816]: node.c:445 node_shutdown: Terminating node 3
[2023-03-15 20:04:47.572]   DEBUG[1924816]: mod_events.c:52 event_cb: 86552 ms elapsed since last short session
[2023-03-15 20:04:47.572]   DEBUG[1924816]: event.c:130 bbs_event_broadcast: Event NODE_SHORT_SESSION dispatched and consumed
[2023-03-15 20:04:47.572]   DEBUG[1924816]: node.c:511 node_shutdown: Shutdown pending finalization for node 3
[2023-03-15 20:04:47.573]   DEBUG[1924816]: node.c:529 node_free: Node 3 now freed

Trying to download an email, with default configuration of downloading headers only when fetching messages:

[2023-03-15 20:06:24.334]   DEBUG[1924815]: socket.c:669 bbs_std_poll: poll returned 1
[2023-03-15 20:06:24.334]   DEBUG[1924815]: utils.c:145 bbs_fd_readline: Read 40 bytes (40 just now), processing 38 and leaving 0 leftover
[2023-03-15 20:06:24.334]   DEBUG[1924815]: net_imap.c:2405 handle_client: 0x7fad9affc4b0 => 00034 UID FETCH 23 (UID BODYSTRUCTURE)
[2023-03-15 20:06:24.335]   DEBUG[1924815]: net_imap.c:1678 process_fetch: 0x7fad9affc4b0 <= * 14 FETCH (UID 23)
[2023-03-15 20:06:24.335]   DEBUG[1924815]: net_imap.c:1687 process_fetch: 0x7fad9affc4b0 <= 00034 OK UID FETCH Completed

mod_sysop: Segfault on unload for foreground console

This is, in some ways, a continuation of issue #12, which resolved segfaults for remote consoles, but this is an issue with the foreground console. Predictably, it's due to pthread_cancel, which is a priority for phase out:

No segfault with valgrind.

Thread 1 (Thread 0x7f4f33fff700 (LWP 1003817) (Exiting)):
#0  0x00007f4f3829a790 in  () at /lib/x86_64-linux-gnu/libgcc_s.so.1
#1  0x00007f4f3829b842 in  () at /lib/x86_64-linux-gnu/libgcc_s.so.1
#2  0x00007f4f3829bf4e in _Unwind_ForcedUnwind () at /lib/x86_64-linux-gnu/libgcc_s.so.1
#3  0x00007f4f3bac2c30 in __GI___pthread_unwind (buf=<optimized out>) at unwind.c:121
        ibuf = <optimized out>
        self = <optimized out>
#4  0x00007f4f3bab7729 in __do_cancel () at ./pthreadP.h:310
        self = <optimized out>
        newval = <optimized out>
        curval = <optimized out>
        self = <optimized out>
        oldval = <optimized out>
#5  sigcancel_handler (sig=32, si=0x7f4f33ffe430, ctx=<optimized out>) at nptl-init.c:177
        newval = <optimized out>
        curval = <optimized out>
        self = <optimized out>
        oldval = <optimized out>
#6  sigcancel_handler (sig=<optimized out>, si=0x7f4f33ffe430, ctx=<optimized out>) at nptl-init.c:142
#7  0x00007f4f3bac4140 in <signal handler called> () at /lib/x86_64-linux-gnu/libpthread.so.0
#8  0x00007f4f3b9cc96f in __GI___poll (fds=0x7f4f33ffea08, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
        resultvar = 18446744073709551612
        sc_cancel_oldtype = 0
#9  0x00007f4f38ef49d5 in  ()
#10 0x0000000000000000 in  ()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.