Intro

In this third installment we’ll do some more NeXT hacking with our nextcube setup and make it more livable.

  • In Part 1, we got OpenStep installed and booting cleanly on VirtualBox.

  • In Part 2, we configured the Unix and network environments, installed development tools, and added some Unix ports.

  • The complete OVA Appliance build published on Archive.org is available if you want to hop right in.


Telnet Refresher

Before SSH and encryption became standard security practices, Telnet was the default way to access remote systems. It uses plain TCP connections and transmits everything — including usernames and passwords — in plaintext. Despite that (or because of it), it was widely used for administration, file transfers, and troubleshooting and testing network services.

At its simplest, Telnet connects to a host and port number as a generic TCP client:

telnet host-or-ip [port-number]

Examples:

telnet nextcube
telnet nextcube 25
telnet 127.0.0.1 9

Yes, you can telnet into 127.0.0.1 or localhost as well as your own IP. This works because the inetd super-server automatically starts telnetd at boot and binds to all available interfaces. The configuration line that enables it is found in /etc/inetd.conf:

telnet  stream  tcp     nowait  root    /usr/etc/telnetd        telnetd

The actual telnetd binary lives in /usr/etc, and is launched by inetd whenever a connection request comes in on TCP port 23.

Telnet’s simplicity makes it an excellent tool for exploring how old network services work. You can use it to:

  • Log in to the OpenStep system from another host.
  • Connect to local ports for debugging or service checks (telnet localhost 80).
  • Interact with simple text-based protocols such as SMTP (telnet host 25), POP3 (telnet host 110), or even the built-in services like finger, daytime, or echo.

Because Telnet sends everything unencrypted, you can easily visualize what’s happening with a packet capture tool like tshark or Wireshark. A short capture of a login attempt clearly shows the username and password as ASCII text — a powerful reminder of why SSH replaced it.

👀 sniffing a Telnet login session

Telnet made troubleshooting a lot easier but it transmitted everything, including passwords, in the clear.

sudo tcpdump -i eth0 -n -s 0 -w telnet_nextcube.pcap host 192.168.1.50 and port 23

After telnetting in and exiting normally, the tcpdump session was stopped and examined with tshark:

┌──[ grumble@shinobi ]:~
└─$ tshark -r telnet_nextcube.pcap -Y "telnet" -T fields -e frame.number -e telnet.data
4
6
8
9
11
12
14
15
16
17
18
19
20
21
22
23      \r\n,\r\n,NeXT Mach (nextcube) (ttyp1)\r\n,\r,\r\n,\r
24
25      login:
27      me\r\n
28
30
31      Password:
34      password\r\n
35      \r\n
37
39
40      Last login: Thu Nov 13 15:35:16 from 192.168.1.51\r\n
42      \r\n
44      \tThe Priest's grey nimbus in a niche where he dressed discreetly.\r\n
46      I will not sleep here tonight. Home also I cannot go.\r\n,\tA voice, sweetened and sustained, called to him from the sea.\r\n,Turning the curve he waved his hand.  A sleek brown head, a seal's, far\r\n,out on the water, round.  Usurper.\r\n,\t\t-- James Joyce, "Ulysses"\r\n,\r\n
48      ����
50      ��
51      [ me@nextcube ]:~ $
53

So keep that in mind. OpenSTEP was built for a kinder, gentler network environment.


This makes for a striking visual demonstration in Wireshark: open the .pcap and follow Telnet → Follow TCP Stream — you’ll see your username and password scroll past in red and blue plaintext.

If you want to know more, you can take a look at the following:

👀 Telnet RTFM Reference

🧠 Telnetd (OpenStep 4.2) Reference

Path: /usr/etc/telnetd
Managed by: inetd(8) via /etc/inetd.conf
Service mapping: telnet 23/tcp in /etc/services

Usage:

/usr/etc/telnetd [-debug] [-h] [-l] [port]
  • -debug — run in foreground, print diagnostic output
  • -h(listed, but nonfunctional — legacy stub option)
  • -l — disable reverse hostname lookup on incoming connections
  • port — optional alternate TCP port (for testing)

Version: NeXT telnetd 5.65 (NeXT 1.0) — 4.3BSD–Net/2 derivative
(Built Jan 26 1999, same toolchain as OpenStep 4.2 Developer CD)

Documentation:

Notes:

  • No encryption; credentials and session data transmitted in plaintext.
  • Typically launched by inetd, not standalone.
  • Uses /usr/etc/login for authentication, /etc/motd for post-login message.
  • Logs via syslogd (facility daemon.notice) if configured.
  • Relies on BSD getty and tty infrastructure for pseudo-terminals.
  • Safe to use only on an isolated or NATed virtual network.


Working with Files

Next up, let’s explore how to work with files on nextcube. Since we don’t have the benefit of VirtualBox Shared Folders, we’ll start by looking at ftp.

FTP refresher

OpenSTEP runs ftpd out of the box thanks to this line in /etc/inetd.conf

ftp     stream  tcp     nowait  root    /usr/etc/ftpd           ftpd

That makes it easy to transfer files between your VirtualBox host and the nextcube guest. Again I would suggest a nice modern ftp client like FileZilla.

You can connect to another host directly from OpenStep using the BSD client:

/usr/ucb/ftp hostname

Remote operations

  • open host [port] — connect to a remote FTP server
  • user name [password] — authenticate manually
  • cd dirname — change remote directory
  • cdup — go up one directory
  • pwd — print current remote directory
  • ls [dir] — list files on the remote side
  • dir [dir] — long listing (like ls -l)
  • get remote [local] — download a file
  • put local [remote] — upload a file
  • mget pattern — download multiple files (with prompt off)
  • mput pattern — upload multiple files
  • delete file — remove a file on the remote system
  • rmdir dirname — remove a directory
  • mkdir dirname — create a directory
  • rename old new — rename a remote file
  • status — show current connection and mode
  • close or bye — end the session

Local operations

  • lcd dirname — change local working directory
  • lpwd — print local working directory
  • !command — run a shell command locally (e.g. !ls, !cat file)
  • ! — open an interactive shell temporarily
  • ls with no ! — still shows remote files; prefix with ! for local

Transfer mode

  • ascii — convert text line endings; use only for .txt or config files
  • binary — raw byte transfer; always use for .app, .tar, .gz, .iso, etc.

To switch:

ftp> binary
ftp> get archive.tar.gz

Example: Fetching the FTP Specification (RFC 959)

You can use OpenStep’s native /usr/ucb/ftp client to retrieve files directly from ftp servers like RFC Editor FTP archive.

Lets fetch RFC 959, the original File Transfer Protocol specification so we have a local copy:

[ me@nextcube ]:~ $ ftp ftp.rfc-editor.org
Connected to rsync.rfc-editor.org.
220 "FTP Server Ready"
Name (ftp.rfc-editor.org:me): anonymous
331 Please specify the password.
Password:
230 Login successful.
ftp> cd in-notes
250 Directory successfully changed.
ftp> get rfc959.txt
200 PORT command successful. Consider using PASV.
150 Opening ASCII mode data connection for rfc959.txt (147316 bytes).
226 Transfer complete.
local: rfc959.txt remote: rfc959.txt
151249 bytes received in 1.59 seconds (92.83 Kbytes/s)
ftp> bye
221 Goodbye.

Verify the download:

[ me@nextcube ]:~ $ more rfc959.txt
Network Working Group                                          J. Postel
Request for Comments: 959                                    J. Reynolds
                                                                     ISI
Obsoletes RFC: 765 (IEN 149)                                October 1985

                      FILE TRANSFER PROTOCOL (FTP)

Notes

  • The client uses /usr/ucb/ftp, while the server runs /usr/etc/ftpd.
  • All credentials and data are unencrypted.
  • Use binary mode for any non-text file to avoid corruption.

FUN FACT:
ftp and many other OpenStep binaries live in /usr/ucb — named after the University of California, Berkeley, origin of BSD UNIX. Sun Solaris also kept a ucb/ directory for legacy BSD compatibility.

👀 FTP RTFM Reference

🧠 Ftpd (OpenStep 4.2) Reference

Path: /usr/etc/ftpd
Managed by: inetd(8) via /etc/inetd.conf
Service mapping: ftp 21/tcp in /etc/services

Usage:

/usr/etc/ftpd [ -d ] [ -l ] [ -t timeout ] [ -u umask ] [ -T maxtimeout ]
  • -d — debug mode (log each command)
  • -l — log each FTP session via syslog
  • -t — set idle timeout in seconds
  • -u — set default file-creation umask
  • -T — set maximum timeout

Version:
@(#)PROGRAM:ftpd PROJECT:etc-113.2 BUILT:Tue Jan 26 17:59:07 PST 1999
Based on 4.3BSD ftpd 5.28 (4/20/89) — same lineage as BSD-Reno.
Implements classic commands: USER, PASS, PORT, PASV, STOR, RETR, LIST, CHMOD, UMASK, IDLE, etc.

Documentation:

Notes:

  • No encryption; credentials and data channels are plaintext.
  • Supports anonymous logins (ftpusers restricts disallowed accounts).
  • Logs sessions to /usr/adm/wtmp and syslog.
  • Uses /bin/sh or /bin/csh for shell commands (LIST, NLST).
  • Consult /etc/ftpusers to deny system accounts (root, daemon, etc.).
  • Safe only on isolated or NATed networks.

Related files:

/etc/inetd.conf     # service entry
/etc/ftpusers       # disallowed accounts
/etc/shells         # valid shells
/usr/adm/wtmp       # login accounting

Source lineage (SCCS tags in binary):

ftpcmd.y     5.20  (Berkeley)  2/28/89
ftpd.c       5.28  (Berkeley)  4/20/89
glob.c       5.7   (Berkeley) 12/14/88
logwtmp.c    5.5   (Berkeley)  4/2/89
popen.c      5.7   (Berkeley)  2/14/89

Fun fact: You can telnet directly to port 21 and type FTP commands by hand to watch the RFC 959 dialogue — a great demo of the protocol’s simplicity.


Network File System (NFS)

OpenStep includes a complete BSD-style NFSv2 implementation. File systems can be shared directly from the command line with /usr/etc/exportfs or through the graphical NFSManager.app located at /NextAdmin/NFSManager.app.
The GUI stores its configuration in NetInfo under /exports and /mounts, applying it immediately with exportfs. (See System Administration, Chapter 9: “Setting Up the Network File System” in the Librarian app for the original instructions.)

It’s not really useful in a modern network which is a shame since it has a really nice GUI and good documentation. I was hoping to make a side-channel VirtualBox shared folder.

OpenSTEP has a nice gui for managing NFS

Scanning the NFS Service

After creating an NFS export on nextcube, we are unable to connect from Linux.

┌──[ grumble@shinobi ]:~/codelab/NeXT
└─$ mount -t nfs nextcube:/Public ./Public/
mount.nfs: failed to apply fstab options

From our remote machine, nmap reveals the following:

┌──[ grumble@shinobi ]:~/codelab/NeXT
└─$ sudo nmap -sU -sT -p 111,2049 --script nfs-ls,nfs-showmount,nfs-statfs nextcube
Starting Nmap 7.80 ( https://nmap.org ) at 2025-11-15 15:15 CST
Nmap scan report for nextcube (192.168.1.50)
Host is up (0.12s latency).
rDNS record for 192.168.1.50: nextcube.darkstar.home

PORT     STATE  SERVICE
111/tcp  open   rpcbind
2049/tcp closed nfs
111/udp  open   rpcbind
2049/udp open   nfs

Nmap done: 1 IP address (1 host up) scanned in 3.36 seconds

Again from our (modern Linux) host, rpcinfo clearly shows which RPC programs are registered on the OpenStep server:

┌──[ grumble@shinobi ]:~/codelab/NeXT
└─$ rpcinfo -p nextcube
   program vers proto   port  service
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
 200100001    1   udp    706
 200100001    1   tcp    709
    100026    1   udp    741  bootparam
    100011    1   udp   2585  rquotad
    100001    1   udp   2586  rstatd
    100001    2   udp   2586  rstatd
    100001    3   udp   2586  rstatd
    100002    1   udp   2587  rusersd
    100002    2   udp   2587  rusersd
    100012    1   udp   2589  sprayd
    100008    1   udp   2590  walld
 200100002    1   udp   2592
    100003    2   udp   2049  nfs
    100005    1   udp    659  mountd
    100005    1   tcp    663  mountd

Only the mountd service (100005) registers on TCP; the main NFS daemon (100003) provides version 2 over UDP only.
Modern Linux and BSD clients, which default to NFSv3 or NFSv4 over TCP, can contact mountd but fail when the file transfer channel negotiates—resulting in the message
mount.nfs: requested NFS version or transport protocol is not supported.

Interestingly, our NFS settings get stored in netinfo:

su-2.00# nidump exports /
/me/Public      -access=shinobi

Compatibility Notes

  • ✅ Two OpenStep or NeXTSTEP systems on the same LAN can mount each other’s exports normally.
    Example:
    su
    mkdir -p /Net/nextcube/Public
    mount -t nfs nextcube:/Public /Net/nextcube/Public
    
  • ⚠️ Modern NFS clients cannot mount from OpenStep because they no longer support NFSv2/UDP.
  • 📚 Reference: RFC 1094 – Network File System Specification

On modern systems, NFSv2 has been removed from the kernel and would require recompiling in order to talk to NeXT. So move on and use ftp unless you are talking to other vintage OSes.

┌──[ grumble@shinobi ]:~/codelab/NeXT
└─$ sudo mount -t nfs -o vers=2,udp,proto=udp nextcube:/Public ./Public/
mount.nfs: requested NFS version or transport protocol is not supported

The Workspace Manager File Viewer

The File Viewer in OpenStep is pretty snazzy for the time. It supported common file operations via drag and drop and the Workspace menu.

The list view is promising, but you'll want to stick with the default icons view for drag and drop simplicity.

👟 Sneakernet ISOs

One handy technique to transfer files is with a sneakernet ISO image. Just build a small ISO on your host containing files you wish to transfer, attach it in VirtualBox, and copy the files inside NeXT.

burning a virtual cd is an easy way to transfer files to NeXT

On the host (macOS/Linux):

genisoimage -r -J -joliet-long -iso-level 3 \
  -V "SNEAKERNET" -o SNEAKERNET.iso /path/to/files/
  • -r Rock Ridge (UNIX metadata)
  • -J -joliet-long long filenames
  • -iso-level 3 long names/deeper dirs
  • -V "SNEAKERNET" sets the volume label
  • -o SNEAKERNET.iso output image

Attach SNEAKERNET.iso as a CD-ROM in VirtualBox.

Inside NeXT:

  • The ISO mounts at /<volume-label>, so here it will be /SNEAKERNET:
  • Copy the files out:
    cp -R /SNEAKERNET/* /me/Downloads/
    

A Tour of the Filesystem

OpenStep inherits its BSD roots but layers on NeXT’s own structure for apps, libraries, and documentation — the ancestor of macOS’s /System and /Library.
The root level is tidy: core UNIX paths alongside distinctive NeXT directories like /NextLibrary, /NextApps, and /NextDeveloper.

Key Areas

Binaries

  • /bin, /usr/bin — core user utilities
  • /usr/etc — system daemons (ftpd, inetd, sendmail, lpd)
  • /usr/ucb — BSD-compatibility commands
  • /usr/gnu/bin — GNU tools (gcc, make, emacs)
  • /usr/local/bin — local additions
    (No /sbin; management tools live in /usr/etc.)

Configuration

  • /etc/private/etc — symbolic link to real configs
  • /etc/hostconfig, /etc/rc* — system identity and startup scripts
  • /etc/netinfo/local.nidb — NetInfo database (users, hosts, mounts)
  • /etc/fstab, /etc/services, /etc/hosts — familiar UNIX files

Logs & Runtime

  • /usr/adm/private/adm — system logs
  • /usr/spool/private/spool — mail and print queues
  • /tmp, /dev/private/* — temporary and device files

Documentation

  • /usr/man/NextLibrary/Documentation/ManPages
  • /NextLibrary/Bookshelves — system and developer manuals

Shared Resources

  • /NextLibrary/Frameworks — AppKit, Foundation, etc.
  • /NextLibrary/ — global assets

Development

  • /NextDeveloper/Apps — Interface Builder, Project Builder
  • /NextDeveloper/Examples, /NextDeveloper/Headers — source and APIs
  • /NextDeveloper/Source/GNU — compiler and toolchain sources

NeXT’s filesystem design was clean, logical, and modular — decades ahead of its time.
It separates binaries, configuration, and writable state clearly, and its /Next* hierarchy became the blueprint for macOS’s modern system layout.


System Documentation

Time to RTFM. OpenSTEP installs a good bit of documentation in the form of Bookshelf files and man pages. You can open the Librarian.app in /NextApps and the documentation for the OS and the Developer Tools lives in /NextLibrary/Bookshelves

Just like the mac, NeXT uses rtf and rtfd bundles

At the terminal you can use man or search for a topic with apropos like so:

[ me@nextcube ]:~ $ man -k inetd
inetd (8)               - internet ``super\-server''

[ me@nextcube ]:~ $ apropos inetd
inetd (8)               - internet ``super\-server''

[ me@nextcube ]:~ $ man inetd

The NeXT System Administration Manual (Release 4.0) closed with a “Suggested Reading” appendix.
Repeated here for historical and vintage-reading pleasure, it reflects the technical canon of the era: the books NeXT engineers themselves considered essential. I had most of these at one point!

General UNIX

  • The UNIX Programming Environment — Brian W. Kernighan & Rob Pike
  • The C Programming Language, 2nd Ed. — Kernighan & Ritchie
  • UNIX Power Tools — Jerry Peek, Mike Loukides, & Tim O’Reilly
  • sed & awk — Dale Dougherty
  • The Design and Implementation of the 4.3BSD UNIX Operating System — Leffler, McKusick, Karels, & Quarterman
  • Programming Perl — Larry Wall & Randal L. Schwartz

System Administration

  • UNIX System Administration Handbook — Nemeth, Snyder, & Seebass
  • TCP/IP Network Administration — Craig Hunt
  • Managing UUCP and Usenet — Grace Todino & Tim O’Reilly

Networking

  • DNS and BIND — Paul Albitz & Cricket Liu
  • Internetworking with TCP/IP (Vols. I–III) — Douglas Comer & David Stevens
  • TCP/IP Illustrated, Vol. 1 — W. Richard Stevens
  • UNIX Network Programming — W. Richard Stevens
  • Managing NFS and NIS — Hal Stern

Security

  • Practical UNIX Security — Simson Garfinkel & Gene Spafford
  • Firewalls and Internet Security — Cheswick & Bellovin
  • The Cuckoo’s Egg — Clifford Stoll

Internet

  • The Whole Internet User’s Guide & Catalog — Ed Krol
  • Zen and the Art of the Internet — Brendan Kehoe
  • The Internet Companion — Tracy LaQuey & Jeanne Ryer

Hardware

  • The Winn L. Rosch Hardware Bible, 3rd Edition — Winn L. Rosch

Preferences

Preferences.app icon from NeXTSTEP/OpenStep

The Preferences.app in /NextApps/ provides a central place to adjust system behavior — window styles, sounds, networking, time, and more — concepts that later evolved into macOS System Preferences.

Most of these options are undocumented but self-explanatory.


Interestingly, the files
/me/.OpenStep/.NeXTdefaults.L (user settings) and
/.NeXT/.NeXTdefaults.L (system-wide settings)
are NeXTSTEP/OPENSTEP’s early equivalent of macOS .plist files — compact binary databases that store preferences and GUI state for both the user and the system.

Each setting inside these files is serialized as key–value pairs used by the Preferences panels and Workspace Manager.

For example, setting the background color and then running strings on these files yields:

NeXT1BackgroundColor .846690 0.903455 0.837703

The OS represents the RGB components of the desktop background color as floating-point values between 0.0 and 1.0 (red, green, blue).
Here, (0.85, 0.90, 0.84) corresponds to a light, slightly greenish gray — the color encoding used by NeXT’s NXColor system long before hex color notation became standard.


There are plenty of settings available.

Another familiar preferences pane.
Unix expert? oh my.
There is no native support for Wallpaper but you can change the background color!
I am delighted everytime my system makes the bullfrog sound!

Network Services

inetd

The Internet Super-Server, inetd, is the master network daemon that spawns dozens of smaller services on demand.
Rather than running separate daemons for each port, OpenStep starts a single lightweight inetd process at boot (from /etc/rc), which listens for incoming TCP and UDP connections defined in /etc/inetd.conf. When a request arrives, inetd looks up the service, forks, and either handles the request internally (for simple services like echo, discard, daytime, or time) or launches the appropriate daemon (telnetd, ftpd, fingerd, etc.).

This model dates back to 4.3BSD and made UNIX systems far more efficient—only the active services consume memory. NeXT’s implementation adds RPC support and retains full compatibility with classic BSD-style configuration.

We can demonstrate their behavior directly from another host with telnet (or nc):

👀 poking at inetd: the small services

echo service (port 7) — reflects input back to the sender. Useful for testing; dangerous when exposed publicly.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 7
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
test
test
echo echo echo
echo echo echo
^]
telnet> quit
Connection closed.

discard service (port 9) — silently receives and discards all data. This was essentially a network version of /dev/null that could simulate a network connection for tests where the response doesn’t matter.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 9
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
this message will self destruct
^]
telnet> quit
Connection closed.

daytime service (port 13) — returns a plain-text timestamp revealing local time, timezone, and uptime.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 13
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
Thu Nov 13 15:16:40 2025
Connection closed by foreign host.

time service (port 37) — sends a 32-bit binary timestamp (seconds since 1900). Obsolete precursor to NTP.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 37
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
���AConnection closed by foreign host.

This returns a 4 byte binary value that gets rendered as visual gibberish. We can convert it into an actual date (accurate according to nextcube) but we need to jump through a few hoops.

┌──[ grumble@shinobi ]:~/codelab/NeXT
└─$ # Perl one-liner (also forces network order)
nc -w1 nextcube 37 | perl -we 'read STDIN, $_, 4 or die; ($n)=unpack("N", $_); print scalar gmtime($n-2208988800), "\n";'
Sat Nov 15 22:23:42 2025

In case your antique perl is rusty, that oneliner takes the 4bytes from port 37 and does the following:

read STDIN, $_, 4 or die;                 # read exactly 4 bytes from stdin (the RFC 868 response)
($n)=unpack("N", $_);                     # unpack them as a 32-bit unsigned integer in network (big-endian) order
print scalar gmtime($n-2208988800), "\n"; # convert from 1900 epoch to 1970 by subtracting 2,208,988,800 seconds,
                                           # then print the corresponding UTC time in human-readable form

finger service (port 79) — leaks detailed user information, including usernames, shells, idle times, and home directories.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 79
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
me
Login name: me                          In real life: My Account
Directory: /me                          Shell: /usr/gnu/bin/bash
On since Nov 12 15:53:07 on console     209 days Idle Time
Plan:

This .plan file has not been set up by its owner yet.

Login name: me                          In real life: My Account
Directory: /me                          Shell: /usr/gnu/bin/bash
On since Nov 13 11:54:35 on ttyp1 from 192.168.1.51
1 minute 50 seconds Idle Time
Plan:

This .plan file has not been set up by its owner yet.

Connection closed by foreign host.

rexecd (port 512) — executes remote commands using plaintext credentials. Disabled by default on most systems today.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 512
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
ls
^]
telnet> quit
Connection closed.

rlogind (port 513) — remote login service using .rhosts trust. Won’t connect without matching trust entries.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 513
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
^]
telnet> quit
Connection closed.

talkd (port 517) — text-based chat between users on a LAN. Connection refused here; often disabled without /etc/hosts setup.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 517
Trying 192.168.1.50...
telnet: Unable to connect to remote host: Connection refused

ident (port 113) — maps connections to usernames. Not active by default on NeXTSTEP.

┌──[ grumble@shinobi ]:/etc
└─$ telnet nextcube 113
Trying 192.168.1.50...
telnet: Unable to connect to remote host: Connection refused

These “small services” were once standard diagnostics — but on a 1990s network, they expose a surprising amount of data.
Today, all of them would be disabled or firewalled off by default.

👀 inetd RTFM Reference

🧠 Inetd (OpenStep 4.2) Reference

Path: /usr/etc/inetd
Managed by: /etc/rc and /etc/rc.standard at boot
Configuration: /etc/inetd.conf → symlinked to ../../usr/etc/inetd
Service mapping: Defined in /etc/services (standard BSD ports 7–37, 79, etc.)

Usage:

/usr/etc/inetd [ -d ] [ configuration file ]
  • -d — debug mode (runs in foreground, logs activity to console)
  • configuration file — optional path to alternate config

Version:
@(#)PROGRAM:inetd PROJECT:etc-113 BUILT:Thu Mar 27 21:30:05 PST 1997
Based on inetd.c 1.2 88/03/10 4.0NFSSRC (BSD 4.3 / NFS Source release lineage)

Internal Services (built in to inetd):

  • echo — returns data sent to it (TCP 7 / UDP 7)
  • discard — silently discards input (TCP 9 / UDP 9)
  • chargen — outputs repeating ASCII stream (TCP 19 / UDP 19)
  • daytime — human-readable date/time (TCP 13 / UDP 13)
  • time — 32-bit machine timestamp (TCP 37 / UDP 37)

External Daemons (default entries):
ftpd, telnetd, rshd, rlogind, rexecd, fingerd, tftpd,
comsat, talkd, ntalkd, NSWSd, plus several RPC services
(rquotad, rstatd, rusersd, sprayd, rwalld, renderd).

Signal Handling:

  • SIGHUP — reload /etc/inetd.conf (add, remove, or modify services)
  • No PID file written under OpenStep

Logging:

  • Logs through syslogd (facility daemon.notice) when invoked with -d
  • No TCP wrappers or host-based access control

Documentation:

Notes:

  • Provides multiple lightweight network services from a single parent daemon.
  • Runs continuously in the background after boot; reconfigurable via SIGHUP.
  • Intended for trusted LAN environments — no encryption or authentication.
  • Foundation for many BSD-derived “super-server” implementations later replaced by xinetd.


Sendmail and Mail.app

Email was a first-class citizen in the NeXT ecosystem. NeXTSTEP and OpenStep treated mail as an essential part of the workstation experience — not an add-on. Every system shipped with a polished graphical mail client, Mail.app, and a fully configured Sendmail daemon running quietly in the background as its local Mail Transfer Agent (MTA). Together they formed a complete messaging stack: Mail.app for the user interface, Sendmail for delivery and routing.

I had a dog-eared copy of the O'reilly bat book on my desk for years

Mail.app

The mail app is pretty self explanatory and obviously the grandaddy of the modern Apple Mail.app.

Sendmail

Beneath the NeXT graphical shell, Sendmail is the workhorse moving every message. It’s installed and enabled by default, acting as both a local delivery agent and a basic SMTP server for the system. You don’t need POP or IMAP here — messages between local accounts move entirely through the Sendmail queue in /usr/spool/mqueue, and each user’s mailbox lives as a simple text file under /usr/spool/mail/.

You can get the version with the following:

[ me@nextcube ]:~ $ /usr/lib/sendmail -bt -d0.4 < /dev/null
Version NX5.67g
canonical name: nextcube
          fqdn: nextcube
using configuration file /etc/sendmail/sendmail.cf -> sendmail.subsidiary.cf
ADDRESS TEST MODE
Enter <ruleset> <address>
[Note: No automatic ruleset 3 call]

The fun part? You can talk to Sendmail directly. It listens on port 25 and speaks plain SMTP, so you can open a connection with telnet, issue commands by hand, and watch your cube deliver its own mail like it’s 1995.

👀 sending and reading mail by hand
telnet localhost 25

Expected banner:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 nextcube Sendmail NX5.67g/NX3.0S ready at Wed, 12 Nov 2025 16:02:11 -0600

Manual SMTP dialog:

HELO nextcube
MAIL FROM:<me@nextcube>
RCPT TO:<me@nextcube>
DATA
Subject: telnet test
From: me@nextcube
To: me@nextcube

hello me, this is your NeXT talking to itself over SMTP.
.
QUIT

Response:

250 OK
221 nextcube closing connection
Connection closed by foreign host.

You can refer to the rfc for the full protocol reference if you really want to poke around. rfc821 – Simple Mail Transfer Protocol

The message is queued and immediately delivered to the local mailbox.
You can verify delivery from the command line with the classic BSD tools:

[ me@nextcube ]:~ $ Mail
Mail version 8.1 6/6/93.  Type ? for help.
"/usr/spool/mail/me": 1 message 1 new
>N  1 me                    Wed Nov 12 15:50  12/299   "telnet test"
& more 1
Message 1:
From me@nextcube  Wed Nov 12 15:50:11 2025
Subject: telnet test
To: me@nextcube

hello me, this is your NeXT talking to itself over SMTP.
& quit
Held 1 message in /usr/spool/mail/me

The same message appears instantly inside Mail.app, proving that both the GUI and the CLI share the same local spool and Sendmail transport layer.

Behind the scenes, Sendmail on NeXT isn’t just a standalone daemon — it’s deeply tied into the NetInfo system.
The designated mail server is identified by the alias mailhost, and every client knows which Sendmail configuration to use via entries in the NetInfo /locations/sendmail directory.
Even Mail.app’s address book and sender pictures come from shared NetInfo data, updated nightly by the mailDBupdate cron job.


the Web Server

In Part 2 we built the w3c-httpd web server for Intel NeXT. It is historically pleasing to see a website served by nextcube. We’ll take a closer look at it in this section.

beautiful 90s web design

As configured, your installation lives entirely under /usr/local/httpd, with a tidy BSD-style layout:

purpose path notes
daemon binary /usr/local/httpd/bin/httpd standalone CERN 3.0A server
configuration file /etc/httpd.conf main configuration
document root /usr/local/httpd/html/ served at /
user directories /me/public_html/ available as http://host/~me/
access log /usr/local/httpd/logs/access_log all requests
error log /usr/local/httpd/logs/error_log startup + runtime diagnostics
startup hook /etc/rc.local auto-launch at boot

The daemon starts as root only long enough to bind port 80, then drops privileges to nobody.
Everything — config, HTML, and logs — lives neatly inside /usr/local/httpd, so it’s easy to back up or snapshot.

When launched, it identifies itself with:

............ This is CERN-HTTPD, version 3.0A, using libwww version 2.17
Reading..... /usr/local/httpd/conf/httpd.conf

From there, you can fetch http://192.168.1.50/ for the system page, or http://192.168.1.50/~me/ for your personal space.

👀 fetching pages manually

You can watch it work the same way you did with Sendmail — by speaking the protocol over Telnet.

┌──[ grumble@shinobi ] :~  
└─$ telnet nextcube 80
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
GET / HTTP/1.0

HTTP/1.0 200 Document follows
Server: CERN/3.0A
Date: Wed, 12 Nov 2025 21:24:40 GMT
Content-Type: text/html
Content-Length: 43
Last-Modified: Sun, 20 Apr 1997 12:42:55 GMT

<h1>Welcome to CERN httpd on OpenStep</h1>
Connection closed by foreign host.

And for a user directory:

┌──[ grumble@shinobi ] :~  
└─$ telnet nextcube 80
Trying 192.168.1.50...
Connected to nextcube.darkstar.home.
Escape character is '^]'.
GET /~me/ HTTP/1.0

HTTP/1.0 200 Document follows
Server: CERN/3.0A
Date: Wed, 12 Nov 2025 21:27:32 GMT
Content-Type: text/html
Content-Length: 24
Last-Modified: Sun, 20 Apr 1997 12:42:55 GMT

<h1>Hello from ~me</h1>
Connection closed by foreign host.


Web Browser

Next we’ll need a web browser so we can surf the Internet super-highway while quoting the movie Hackers!

The VirtualBox OVA appliance from Part 1 already includes OmniWeb, the period-correct browser for NeXTSTEP.
If you’re building your own system, you can find it in the Lighthouse Design Suite from
Lighthouse (NeXTSTEP Applications).

Convert the .mdf image to ISO before mounting:

sudo apt install mdf2iso   # or brew install mdf2iso on macOS
mdf2iso LIGHTHOUSE.mdf LIGHTHOUSE.iso

Mount LIGHTHOUSE.iso in your VM and install OmniWeb (and the rest of the suite).
Once copied into /LocalApps, launch it from Workspace Manager or:

open /LocalApps/OmniWeb.app

You can visit nextcube’s own local site at http://127.0.0.1/ or check out a few fun sites aimed at vintage machines:


Directory and Network Integration

OpenStep supports several legacy directory and authentication systems common in mixed UNIX environments of the 1990s.
NetInfo remains the system’s native database for users, groups, hosts, and network services — roughly analogous to early LDAP.
It can coexist with NIS (Yellow Pages) for compatibility with older UNIX networks, and includes optional NetWare client support for file and print services.

In most standalone setups, only NetInfo is active, but these subsystems illustrate how NeXT aimed to fit seamlessly into larger multi-vendor networks of the time.

For more information, refer to the NFS section of the SysAdmins Guide in the /NextLibrary/Bookshelves folder.


System Hardening

OpenStep was built for a friendlier network era, but NeXT’s own System Administration Guide (Release 4.0) includes several practical ways to tighten things up. Here are a few quick checks worth doing — or at least exploring — before you put your cube on a modern LAN.


🛠 Entering Single-User Mode

On most OpenStep 4.x installations running under VirtualBox or genuine NeXT hardware, the boot screen appears automatically — a gray window with a ten-second countdown and a boot: prompt at the bottom.
You don’t need to hold any special key combinations unless a hardware password is enabled.

When you see the countdown, simply click inside the window (or press any key) to stop the timer.
You can then enter boot arguments directly at the prompt:

mach_kernel -v -s

and press Return.

The options mean:

  • -v — verbose mode (displays detailed startup messages)
  • -s — single-user mode (boots to a root shell instead of multi-user login)

The system loads the kernel, mounts the root filesystem read-only, and drops you at a minimal shell:

sh-2.00#

From here you can perform maintenance tasks such as:

fsck -y /dev/sd0a        # Check and repair the root filesystem
mount -a                 # Mount all local filesystems
passwd <username>        # Reset a user's password

When finished, type:

exit

to continue booting normally, or:

reboot

to restart cleanly.

Note
Earlier NeXTSTEP manuals refer to bsd -s, which was a link to the kernel on older releases.
On OpenStep 4.x, the correct binary name is mach_kernel.
The same prompt can load alternate kernels such as cdrom or floppy for installation or recovery.
If a hardware password is set in Preferences, you must enter it before custom boot arguments are accepted.


Auditing Set-User-ID Programs

NeXT systems ship with dozens of setuid and setgid binaries — around eighty in a default install — many of which allow normal users to perform administrative actions without sudo (which doesn’t exist on NeXT).
You can review them with:

find / -perm -4000 -user root -print

or include all users:

find / -perm -4000 -print

Each file you see runs with elevated privileges. You can remove the bit with chmod u-s, but some tools (like Preferences, PrintManager, or network utilities) rely on it to work properly.
Consider this an exercise in exploration — compare, document, and test rather than disabling everything blindly.


Trimming inetd Services

inetd launches a variety of network services automatically at boot, many of which are only useful for diagnostics or legacy clients.
Review /etc/inetd.conf and comment out anything you don’t plan to use. On a secure setup, you can safely disable:

echo, discard, chargen, daytime, time
finger, rshd, rlogind, rexecd
talkd, ntalkd, tftpd
rusersd, sprayd, walld

After editing, restart the daemon or send it a HUP signal:

kill -HUP `cat /etc/inetd.pid`

That trims away most of the “small services” that modern systems disable by default, leaving just Telnet or FTP if you actually need them.


Strengthening Password Policy

Password rules and login behavior are managed through NetInfo.
In NetInfoManager (or using niutil), you can enable stricter checks by setting the security_options property in the root domain:

niutil -createprop . security_options secure_passwords
niutil -appendprop . security_options lockout
niutil -appendprop . security_options login_accounting

These enable stronger passwords, exponential lockout delays after failed logins, and basic login auditing to /usr/adm/messages.
For convenience, NeXT also offered a “discourage_public_servers” flag to hide sound and display sharing options in Preferences.


These simple changes go a long way toward tightening an OpenStep install while keeping it historically accurate. It will also accurately break under the ping of death and any number of buffer overrun attacks, so keep it off the Internet.

For a full list of available security options and examples, see System Administration, Chapter 12: “Security” in the Librarian documentation.


Project Links

Archives and References

Community


Conclusion

I’ve used the terms NeXT, NeXTSTEP, and OpenStep interchangeably throughout this series — guilty as charged.
Technically, OpenStep is the correct name, but NeXT is just more fun to type (inverse CamelCase has a certain charm).

It’s been a rewarding little trip through a sleek, prohibitively expensive at the time, slice of computing history.
OpenStep runs beautifully under VirtualBox on Linux, and even on my Intel MacBook Pro running Ubuntu it feels snappy and solid.
With a few GNU tools and a sensible shell, it’s a genuinely usable UNIX workstation — elegant in that NeXT way.

VirtualBox’s remote display feature never quite behaved, so I stuck to Telnet and FTP for remote access.
It’s probably not worth the effort to chase perfect mouse capture so it remains too awkward to really use.

After all these years, it’s still easy to see why NeXT inspired so much devotion.
OpenStep remains both a product of its time and a glimpse of the future it quietly became.

Feedback welcome feedback@adminjitsu.com