AnotherOS

Documentation

Network shares — SMB and NFS

Mounting a Windows or Samba share with the in-kernel SMB2 client.

AnotherOS mounts a Windows or Samba file share with its own in-kernel SMB2 client. There is no Samba, no mount.cifs and no userspace daemon: the client speaks SMB 2.0.2 and 2.1, and mount(2) reaches it from an ordinary program.

From the Finder

Go → Connect to Server…, or Cmd-K.

  1. Type the address — smb://fileserver/share, or smb://bob@fileserver/share to fill the name in for the next step. A bare fileserver/share is taken as SMB. Servers you have used before are in the Recent Servers pop-up.
  2. Connect opens the authentication sheet: connect as guest, or give a name, password and workgroup.
  3. Connect again starts the connection. The sheet stays up with a spinner, and the rest of the Finder keeps working while it runs — other windows repaint, you can browse, and nothing is frozen.
  4. The share is mounted under /Volumes/<share> and the window navigates to it. It also appears in the sidebar under Devices, because that list is the real mount table and this is a real mount.

Cancel means cancel

Cancel during a connection cancels the connection, not just the dialog.

The mount is bounded but genuinely slow — a TCP connect of about five seconds, then several SMB exchanges with a twenty-second ceiling each — so there is real waiting to interrupt.

  • It interrupts the wait. A mount parked in an SMB exchange gives up at once, because the kernel tests for a pending signal every fraction of a millisecond.
  • A mount parked in the TCP connect finishes its own budget of about five seconds first. That part of a cancel is bounded, not instant.
  • If the mount lands anyway — the signal can arrive after the last round trip — it is unmounted again and its mount point removed. A cancel never leaves behind a volume you did not ask for.
  • A share that was already mounted before you asked is never unmounted by a cancel. Connecting to it again simply opens it, and ejecting it would take a volume away from whoever is using it.

Closing the sheet, pressing Escape, or quitting the Finder while a connection runs all do the same thing. Up to four connections may be in flight at once; a fifth is refused with a sentence rather than queued behind one you have already given up on.

When the server refuses, the reason is said in plain words — "The server rejected the user name or password", "There is no route to host", "host refused the connection. Is file sharing switched on there?" These are different problems, and a dialog that reports "Invalid argument" for all of them teaches nothing.

There is deliberately no Browse button and no "remember this password." Browsing a workgroup needs name-service and server-enumeration protocols this system does not have, and there is no keychain, so a saved password would be a plaintext file. Both return when the thing behind them does. Until then they are absent rather than present and inert.

From a shell

amount smb://bob@fileserver/aos /Volumes/aos    # prompts for the password
amount -t smb //192.0.2.10/aos /Volumes/aos -o user=bob,pass=s3cret,domain=WORKGROUP
amount -t nfs 192.0.2.10:/export /Volumes/nfs
amount                                          # what is mounted
amount -u /Volumes/aos                          # disconnect

amount resolves the host name and hands the kernel an address: there is no resolver in the kernel, and putting one there would be a second DNS implementation.

Prefer the prompt to -o pass=. An option string is visible in the process table for as long as the mount runs. The password never reaches the mount table either way — the kernel parses the option string, keeps only the one hash NTLMv2 actually needs, and wipes the rest.

From C

mount("//192.0.2.10/aos", "/Volumes/aos", "smb", 0, "user=bob,pass=s3cret");
mount("192.0.2.10:/export", "/Volumes/nfs", "nfs", 0, NULL);
  • The type is smb, cifs or smb3 — all three reach the one client — or nfs.
  • The source carries an IPv4 address, not a host name.
  • Options are Linux cifs's: user=, pass= or password=, domain= or dom=, port=.
  • Requires effective uid 0, as every other mount here does.

Errors are specific: EACCES the credentials were refused, ENOENT no such share, EHOSTUNREACH, ECONNREFUSED or ETIMEDOUT from the connect, EPROTO the server speaks no dialect we do, EBUSY already mounted there, EMFILE four shares are mounted already.

umount(2) disconnects, and refuses with EBUSY while anything under it is still open.

What works, and what is not there

Mounted shares are browsable, readable and writable: open, read, write, truncate, create, delete, mkdir, rmdir and rename all reach the server, and a directory listing is re-read every few seconds so a file another machine creates appears without reconnecting.

Not implemented — and the client says so rather than pretending:

  • SMB 3.x. No AES-CMAC signing, no encryption, no multichannel, no leases, no durable handles. A server configured to require SMB3 is refused during negotiation.
  • SMB1. A dead protocol, off by default in Samba and Windows alike.
  • Kerberos. NTLMv2 only, and the advertised mechanism list says exactly that — so a server requiring Kerberos fails at authentication instead of silently falling back to something weaker.
  • Oplocks and leases, so the only cache coherency is the directory refresh and a write-through data path.
  • Capacity figures. The share's size belongs to the server and this client does not ask for it, so df prints a dash. An invented number would be worse, because df would print it.

Signing is supported and is used when the server declares it required. Server signatures are then verified, and a mismatch fails the operation rather than being logged and used anyway.

When something is wrong

Boot with smbdebug for one kernel line per SMB exchange, carrying the server's own status code — which is the only thing that holds the server's actual explanation:

smbfs: negotiated SMB dialect 0x210, max read 65536 / write 65536, signing off
smbfs: SESSION_SETUP refused for user 'bob' — wrong user name or password

Boot with smbtest to check the authentication arithmetic against published test vectors. This exists because a hash that is wrong by one bit fails authentication in a way that is indistinguishable from a wrong password.