Mac OSX multiple logins on startup

OSX has a useful feature which lets you automatically log a user in when a machine starts up. There is a second useful feature which lets you start applications when a user logs in. Combining the two you can have a solution to the issue of your machine falling over for some reason (e.g. power cuts, people switching it off etc.)

There is one small limitation here though, if you want to have multiple users logged in (using fast user switching) there’s no way by default to have them all log in at startup.

The reason I want to do this is that our Mac Mini is used as both a communal machine for guests etc. to use, and as a machine for downloading things using Bittorrent. I don’t want people to be able to interfere with or have any awareness of the downloads. I also want to be able to lock the guest account down to an extent, e.g. picking what applications can be run via parental controls, and disabling admin rights.

The solution I came up with is a short AppleScript which runs on startup. This activates fast user switching, picks the guest/non-admin account (which is called Photon, same as the machine) and enters the password. The machine then immediately switches over to that account on login.

The downside to this approach is that it means auto-login must be activated for the admin account (my account on the machine). This isn’t a foolproof way to stop malicious activity, and if the machine was doing anything more important than downloading files I would look for a better solution or just not do this at all. As it is though this works well enough.

The script is:

set password_ to "password_of_photon_account"
set idnumber to do shell script "/usr/bin/id -u photon"
do shell script "/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID " & idnumber
tell application "System Events"
repeat until exists process "SecurityAgent"
delay 0.5
end repeat
keystroke password_
keystroke return
end tell

Simple! This is saved as an application, so it can be put under startup items for my account.

One possible way to make this more secure would be to have the script disable keyboard/mouse input when it starts to run, then re-enable them once the password has been entered. This would prevent someone from alt+tabbing out of the script window and defeating the script.

It’s a shame that there’s no provision for logging in multiple accounts automatically built into OSX, preferably with the ability to pick which one is in the foreground.

Virtual email accounts with Exim4

A while ago I bought a domain to use to provide email services to my family, with firstname@lastname.tld style email addresses (which are just cool). Since then I’ve been slowly getting things set up to make this actually work.

My old email setup was purely for my own use, so I just had Exim deliver mail to my mailbox in /var/mail, and used Dovecot to access this over TLS secured IMAP with the other mailboxes and IMAP files stored in /home/timothy. This works fine and could be easily expanded to give any other user of the system an email account.

However, I wanted to change this for 2 reasons. Firstly I don’t want every email user to be a system user. Secondly I wanted to have all the email data in one place (well, 2 places for now) to allow for easy backups of that information on a more regular basis than the rest of the system.

The scheme I’ve got so far revolves around a new router added to the Exim config (routers are what Exim uses to route email, either to another host (relay) or to a local account) along with a new transport used to deliver to the specific user’s mbox in /var/mail.

The router:

#####################################################
### router/320_exim4-config_dovecot_router
#####################################################

### router/320_exim4-config_dovecot_router
#################################

# This router delivers mail to any dovecot virtual
# user who has a directory under /home/vmail/
# Place after remote router and before localuser router
# + addressing support requires uncommenting
dovecot_router:
driver = accept
#local_part_suffix = +*
#local_part_suffix_optional
require_files = +/home/vmail/$local_part@$domain/
transport = dovecot_transport


#####################################################
### end router/320_exim4-config_dovecot_router
#####################################################

The transport:

#####################################################
### transport/40_exim4-config_dovecot_transport
#####################################################

# Transport to send any mail for virtual dovecot users to correct maildir box
dovecot_transport:
debug_print = "T: dovecot_virtual appendfile for $local_part@$domain"
driver = appendfile
file = /var/mail/$local_part@$domain
delivery_date_add
envelope_to_add
return_path_add
user = vmail
group = mail
mode = 0660
mode_fail_narrower = false

#####################################################
### end transport/40_exim4-config_dovecot_transport
#####################################################

Placement of the transport doesn’t matter. The router needs to go after “real” local delivery (e.g. for system accounts) and before aliases (e.g. mappings of aliases to system accounts or other virtual accounts). This way incoming mail will first be matched against system user accounts, then against the virtual accounts, then against aliases (which can then loop back to one of the two earlier stages).

The router works by checking whether the virtual user exists on the system, it does this by looking under the /home/vmail directory for a directory matching the full email address of the virtual user. In the current configuration it doesn’t cater for a local part suffix (e.g. username+info@domain.tld) but it could be changed so that it does. If a directory is found under /home/vmail then Exim uses the dovecot_transport Transport to deliver the email into the virtual user’s mbox, which is located for the moment under
/var/mail.

I may change this so that all the mailboxes are in the same place, which would make a little more sense.

So the files needed for a user with email address: username@domain.tld are:

/var/mail/username@domain.tld (chown vmail:mail, chmod go+rw)
/home/vmail/username@domain.tld/ (chown vmail:vmail, chmod o+rwx)

Directories under this point can either be left to be created by Dovecot, or copied over from a skeleton set, by default there will be a mail/ subdirectory, with a .subscriptions file listing the subscribed IMAP folders, along with a set of mboxes and a .imap/ directory containing the dovecot caches of the various folders.

Dovecot config also needs to be updated to tell it where to look for the mailboxes. This is done in the auth section:

auth default {
mechanisms = plain

passdb passwd-file {
args = /etc/dovecot/imap.passwd
}
userdb static {
args = uid=vmail gid=vmail home=/home/vmail/%u
}
}

The other change that needs to be made is to specify where we can find the user’s inbox file (same as the location specified in the Exim config):

mail_location = mbox:~/mail:INBOX=/var/mail/%u

We’re specifying a passdb here (which is where Dovecot looks for user passwords). Since we’re using virtual users the actual user accounts need to be defined staticly. This means they’ll all get the same uid/gid (which is the vmail user) and the same home directory (though the %u wildcard subtitutes in the username, and given that the usernames are specified in username@domain.tld format this will include the full path to their home directory).

Unfortunately you can’t use the same passwd file for Exim4 and Dovecot since they use different schemes for the password file.

This script adds new users to the email system:

#!/bin/sh
# Steps to make new mail user:

read -p " Enter user's domain: " domain
read -p " Enter user's username: " username
read -sp " Enter password: " passwd

sudo mkdir /home/vmail/$username@$domain
sudo chown vmail:vmail /home/vmail/$username@$domain
sudo chmod go-rwx /home/vmail/$username@$domain
sudo echo $username@$domain:`dovecotpw -s crypt -p $passwd` >> /etc/dovecot/imap.passwd
sudo echo `htpasswd -nb $username@$domain $passwd` >> /etc/exim4/passwd

Still to do is some kind of webmail interface, quotaing and some kind of spam filtering.

Some other notes:

The vmail account needs to be created, on Debian this can be done with:

adduser $username

After creation I removed remote login ability for this user by editing the master passwd file using vipw and changing the login shell to /bin/false, then using vipw -s I changed the password for the vmail user to *, this indicates that the user has no password and so effectively disables both local and remote login.

Also check that both passwd and imap.passwd files are chown root:root and chmod go-rwx, only root should be able to read and write these files.

Find non-ASCII characters

find . -print | grep “[^A-Za-z0-9.,-_=+ @*;:\$\”‘()&#!%^?~\`|{}]”

This will find all files from the current directory down whose name contains non-printable ASCII characters (e.g. unicode) and print them out with a relative path.

(It’s worth pointing out that on Debian at least this command will fail if your environment’s $LANG variable is set to anything other than blank, e.g. “export LANG=” before running it. I am not sure why…)

This is useful since the backup I made ages ago of the Simutrans Forum (hosted here: http://archive.forum.simutrans.com) appears to have broken unicode characters in a number of the filenames. This means the files don’t load properly. So I have to go and fix the filenames.

Fortunately there are only 78 of them to fix.

I had originally believed this to be a webserver config issue, but it turns out that it’s actually the files themselves. E.g. this is one I’ve fixed:

estádio projeto11.PNG
est?dio projeto11.PNG

The former is the fixed copy, the latter the unfixed one (as printed by ls). Here’s what they look like with octal-escaped non-ASCII (ls -b):

est\303\241dio\ projeto11.PNG
est\341dio\ projeto11.PNG

Or hex:

\xC3\xF1
\xE1

The URLs are encoded as:

est%C3%A1dio%20projeto11.PNG

Which matches the fixed version. I wonder why/how the filenames become corrupted in the first place.

Another example is:

Semt\303\255tulo1.jpg
Semt\355tulo1.jpg

Again, correct followed by incorrect… Odd that in both of these cases the first sequence (\303\255) seems to get shortened to \355, almost like it’s dropping the middle bit? Maybe that’s just coincidence.

I originally downloaded the files on Windows, using a Python script. So there’s plenty of ways this could’ve gone wrong…

Out with the new

I’ve decided to return the RouterBoard. In its place I’ve gone back to what was my original plan and bought an Airport Extreme. I’m very impressed with this so far, all of the problems I was having with my laptop have magically vanished and been replaced with very very fast wireless.

The configuration utility that comes with the Airport Extreme is very nice, discovers the device using mDNS and allows all the configuration one could need from a WAP. I was worried before that it wouldn’t be configurable enough and really from what I’ve seen this was a silly thing to think. I’ve learnt a valuable lesson from this – think about the entire situation, not just technological shininess. There’s a lot of value in things just working.

Performance also counts for a lot, and it has that in droves. Using the 5Ghz band is also nice as nobody else around here seems to be using it at all, giving us much more bandwidth to play with. Chris has shown throughput around the 150mbit mark, which is pretty stonking really. Easily enough to stream a DVD over.

On its way out

My Mac Mini has been crashing for the past few days, overnight while running Bittorrent. It looks like this may be the HDD on its way out. I’m running a SMART test on it at the moment, and the SMART data has thrown up an interesting statistic. The Power On Hours value is 32934, which works out at 3.75 years. Which is about right really.

Given that it has a 2.5″ laptop HDD in it, I’m not surprised it’s on its way out – more surprised it’s lasted this long!

Lock down your Mac

Macs are pretty secure things (they don’t come close to a default install of OpenBSD, but they’re less sieve-like than Windows) but there are some important things to do to keep a really tight ship:

1. Disable automatic login
2. Ensure secure virtual memory is turned on
3. Require a password whenever your machine wakes up
4. Turn on FileVault and set a Master Password (FileVault takes a while to enable, so best to do this ASAP after installing OSX or getting a new mac, since it takes longer the more stuff you have on your disk)
5. Switch the firewall on (you never know what random things may be listening for incoming network connections)
6. Check sharing – turn off anything which doesn’t need to be on
7. Turn off wake-on-network and wake-on-bluetooth (unless you really need these)
8. Set a firmware password (to stop someone potentially stealing the contents of memory via a reboot attack)

SSH Agent Forwarding

SSH is a wonderful tool, secure and simple to use.

When you use it a lot though typing in your password becomes tedious. Remembering your password for half a dozen different servers is also tedious.

There’s a solution to this, use keys to authenticate in place of passwords. You can generate a key pair easily enough, just run:

ssh-keygen

And supply a passphrase. It’ll generate an RSA public/private key pair. On Mac OSX it’ll even put these in the right place for you. The public part is just that, public, the private part should be guarded with your life as it provides (or will provide) access to all your servers.

You simply copy the id_rsa.pub file onto any server you wish to log into, e.g.:

scp ~/.ssh/id_rsa.pub username@remoteserver:~/.ssh/

Then SSH into that server and run the command:

cat .ssh/id_rsa.pub >> .ssh/authorized_keys

Log out, then log back in, notice the difference? On OSX 10.6 you’ll be prompted to enter the passphrase by KeyChain. This is because SSH Agent is already set up, and the passphrase will be remembered in the KeyChain for you. SSH Agent is a tool that takes care of your private key for you, saving you from needing to enter the passphrase every time you log into a remote machine. There’s an extremely good explanation of it here:

http://www.unixwiz.net/techtips/ssh-agent-forwarding.html

SSH Agent Forwarding is a feature whereby you can log into a remote server, then log into another remote machine from there without needing to type your passphrase in, or have your private key stored remotely. The authentication requests are all passed back to your local machine. This is great since it means you can keep your key safely stashed away on your Mac in KeyChain, and all you need to do to set up a user account on a remote server for login is:

1. Copy over the public key
2. Add it to .ssh/authorized_keys
3. Edit .ssh/config to add this line:

ForwardAgent yes

4. Job done!

I’d recommend setting:

VisualHostKey yes

In .ssh/config as well. This displays a little picture generated from the Host Key fingerprint whenever you log into a server. It’s a lot easier to memorise a picture than it is a long hexadecimal string, and since even a tiny change to the host key will produce a big change to the image it’s easy to spot if someone is trying to perform a man-in-the-middle attack. (Though with public/private key based login, the risks of this are somewhat mitigated since you don’t give away any information during login).