Nginx home directories and PHP

I use nginx as my main HTTP server.  I want the users to be able to publish their own pages in a special directory (public_html) within their home directory. They should also be able to use PHP scripts if they want to. You can access the user webpage (that is the content of their public_html directory) with this URL: http://[server]/~[user]/. Here is a snippet of the configuration I use to do so:

index index.html index.xml index.php;

# PHP in home directory
location ~ ^/~(.+?)(/.*\.php)(.*)$ {
  alias /home/$1/public_html;

  try_files $2 =404;
  fastcgi_split_path_info ^(.+\.php)(.*)$;
  fastcgi_pass unix:/var/run/php5-fpm.sock;
  fastcgi_index index.php;
  fastcgi_intercept_errors on;
  include fastcgi_params;

  fastcgi_param SCRIPT_NAME /~$1$fastcgi_script_name;
}

# Home directories
location ~ ^/~(.+?)(/.*)?$ {
  alias /home/$1/public_html$2;
}

You can see here the two locations that match the user directories. The first one matches the PHP scripts and passes them to the FastCGI process manager. For more information, see PHPFcgiExample. Note that I use a UNIX instead of an INET socket. Why would you bother IP on localhost when you can use an UNIX socket? I also set the SCRIPT_NAME parameter to ensure that it is derived correctly from the user URL. This need to be fixed for pages that point to themselves. I also had to restart php5-fpm to ensure that the changes were taken into account.

 

The rise of man

Quote

This man was never meant to be anything more than a mere animal struggling to survive a world he didn’t comprehend.

And it is now an evidence that this man would never be anything more than a mere animal struggling to survive the world he invented himself in his own delusion.

Fingerprint reader on FreeBSD

This solution is very similar to the way fingerprint readers work under Linux. So if you already configured your fingerprint reader on Linux chances are you will find these instructions familiar. However keep in mind than these instructions are for FreeBSD. In particular I did this on 11-CURRENT but it should also work on 10-RELEASE.

The libfprint library provides the support for the fingerprint readers. In particular it provides drivers for some fingerprint readers (you can find the list on their website), and an API to manipulate the device including the code to enroll/match a fingerprint. This library uses libusb-1.0 for communication with the device. FreeBSD 8 and above already include a reimplementation of this library. This also means that you do not have to enable the device kernel-side. As long as libfprint supports the device and you have access to it (/dev/ugen*), it should work.

The pam_fprint module allows you to use your fingerprint reader for authentication. When correctly configured, you are asked to swipe your fingerprint across the reader instead of a password prompt. This module relies on libfprint to access the device and reads the fingerprints from your home directory. However the sync mechanism used by this module can pose problems when multiple applications try to access the device at the same time.

To address this problem the fprintd daemon offers libfprint functionality via D-Bus. In the same way as pam_fprint, this daemon also provides a PAM module, pam_fprintd, for authentication. This module stores the fingerprints into the /var/lib/fprint directory with permission 700. In other words, this directory is not readable/browsable by other users. Also the fprintd daemon is launched by D-Bus with root permissions. Since it is this daemon in particular that accesses the device, you do not have to change the permissions for your user to access it.

In this article I will present you both method, the direct direct method through libfprint (pam_fprint) and the D-Bus method through fprintd (pam_fprintd). However I would strongly recommend the D-Bus method as it requires less configuration, it is more reliable and also more secure to my opinion.

Note that an application must use PAM in order to authenticate with the fingerprint reader. Some ports, for example xscreensaver, disable PAM authentication by default. So you need to recompile it with PAM enabled as described in a previous article.

Direct method

First you need to install the following ports:

  • security/libfprint
  • security/pam_fprint

You may also install security/fprint_demo which will come up handy to test that your fingerprint reader works correctly with libfprint.

Then you need to ensure that the device is accessible by the users. To do so, we first identify the usb port the fingerprint reader is attached to. Then we create a special group for the users that can access the device. After that we create a devfs rule to change the group and permission of the device’s usb port.

First we identify the usb port of the fingerprint reader:

# usbconfig
...
ugen0.3: <Biometric Coprocessor UPEK> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
...

Now we know it’s on ugen0.3. It’s time to add a special group for this kind of device:

# pw groupadd fprint
# pw groupmod -m user1,user2,user3

In this case, user1, user2 and user3 will have access to the fingerprint reader and so will be authenticated with their fingerprint. We can tell devfs to change the permission and group of ugen0.3 to fingerprint and 660. Note that /dev/ugen0.3 is a symlink to /dev/usb/0.3.0 so we change the group and permission of that file too:

/etc/rc.conf:
devfs_system_ruleset="localrules"

/etc/devfs.rules:
[localrules=10]
add path 'ugen0.3' mode 0660 group fprint
add path 'usb/0.3.0' mode 0660 group fprint

Now we take the changes into account and test that the device is accessible for say user1. However to make sure that the changes are enabled on all active session, you may as well just reboot your system:

# service devfs restart
# su user1
$ usbconfig
ugen0.3: <Biometric Coprocessor UPEK> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)

If you installed fprint_demo you can also test that the fingerprint reader works via libfprint with this command. If it works, it will show the device, in my case “UPEK Eikon 2”, say it is ready to use and propose to enroll your fingerprints.

Note this solution is not ideal since the device may not always be attached to the same port. A better solution would be a devd rule that matches the device more precisely.with vendor/product id. I tried to do so but I’m still fairly new to devd and probably got it wrong. Since I found another method that does not involve changing the permissions, I did not look into this. If someone knows better he’s welcome to post his solution below.

Now that we have access to the device, we can tell PAM to authenticate the users with the fingerprint reader when possible. PAM looks for its modules in /usr/lib. However pam_fprint installs itself in /usr/local/lib. To avoid absolute path in the PAM configuration, I create the following symlink /usr/lib/pam_fprint.so -> /usr/local/lib/pam_fprint.so. It’s time to configure PAM. Most services (slim, xscreensaver, …) will refer to /etc/pam.d/system for their PAM configuration, so we only configure this one. We add the pam_fprint module as sufficient to authenticate the user, just before pam_unix (password authentication):

/etc/pam.d/system:
...
# auth
auth    sufficient   pam_fprint.so
auth    required     pam_unix.so     no_warn try_first_pass nullok local_pass
...

Now we can enroll our fingerprints. You need to do this for each user that will authenticate with the fingerprint reader:

$ pam_fprint_enroll
This program will enroll your finger, unconditionally overwriting any selected print that was enrolled previously. If you want to continue, press enter, otherwise hit Ctrl+C

Found device claimed by UPEK Eikon 2 driver
Opened device. It's now time to enroll your finger.

You will need to successfully scan your Right Index Finger 5 times to complete the process.

Scan your finger now.
Enroll stage passed. Yay!

...

Scan your finger now.
Enroll complete!
Enrollment completed!

Finally we can test if everything works correctly. In this case we use sudo to authenticate with our own user:

$ sudo -i
Swipe your right index finger across the fingerprint reader
#

If you can do this, it works.

D-Bus method

In this method we use the fprintd deamon to access libfprint functionality via D-Bus. To my opinion, this method is simpler, more reliable and more secure than the direct method presented above. The only problems are that the D-Bus daemon is harder to understand and thus debug, also if you have a problem with D-Bus, you are stuck.

First you need to install the following ports:

  • security/libfprint
  • security/fprintd

You do not have to ensure that the device is accessible by the users as the fprintd daemon is launched by D-Bus with root permissions. The only thing we have to do now is to tell PAM to authenticate the users with the fingerprint reader when possible. PAM looks for its modules in /usr/lib. However fprintd installs the pam_fprintd module in /usr/local/lib. To avoid absolute path in the PAM configuration, I create the following symlink /usr/lib/pam_fprintd.so -> /usr/local/lib/pam_fprintd.so. It’s time to configure PAM. Most services (slim, xscreensaver, …) will refer to /etc/pam.d/system for their PAM configuration, so we only configure this one. We add the pam_fprintd module as sufficient to authenticate the user, just before pam_unix (password authentication):

/etc/pam.d/system:
...
# auth
auth    sufficient   pam_fprintd.so
auth    required     pam_unix.so     no_warn try_first_pass nullok local_pass
...

Now we can enroll our fingerprints. You need to do this for each user that will authenticate with the fingerprint reader:

$ fprintd-enroll
Using device /net/reactivated/Fprint/Device/0
Enrolling right-index-finger finger.
Enroll result: enroll-stage-passed
...
Enroll result: enroll-completed

Finally we can test if everything works correctly. In this case we use sudo to authenticate with our own user:

$ sudo -i
Swipe your right index finger across the fingerprint reader
#

If you can do this, it works.

Enroll failed with error -22

I use pam_fprint on my laptop. Somehow my fingerprints disappeared and I could not enroll them back with pam_fprint_enroll. I had this error message:

Enroll failed with error -22

To fix this I switched from pam_fprint to fprintd which uses D-Bus. I also had to change /etc/pam.d/system:

-auth    sufficient   pam_fprint.so
+auth    sufficient   pam_fprintd.so

Then I could enroll my fingerprints with fprint-enroll.

Fingerprint and XScreenSaver

Today I configured the fingerprint reader on my Thinkpad X201. I will not describe the process of configuring the fingerprint reader on FreeBSD as it has been documented many times on the Internet. Though if you want I may describe the process in a separate article, just tell me.

After the configuration, everybody from the display manager to su asked to authenticate with the reader. So it was fine. Except for xscreensaver which still confined itself password authentification. There were no configuration for xscreensaver in /etc/pam.d so I initially thought that it fell back on the “other” configuration. Therefore I added one for xscreensaver but it didn’t change anything.

However I installed xscreensaver as a package, and not from the ports. It turns out that the xscreensaver package does not enable the PAM option. You can check that via pkg info xscreensaver or use ldd /usr/local/bin/xscreensaver to check if xscreensaver is effectively linked with libpam.so.

So you can reinstall xscreensaver from the ports and configure it with the PAM option enabled. However I still wonder why they disabled this by default. I still have a problem with PAM which sometime does not detect the reader and cannot even authenticate with pam_unix. I don’t know what is the cause of this, but I’ll find out.

 

Sigma lenses durability

I question the durability of the Sigma low end zoom lenses. We have two Sigma lenses (18-125/200mm) that got stuck in aperture f5.6 / f22. I somehow managed to free up the first one. The second one, however, is plain dead. Some of the connectors are wandering around between the lenses so I guess this is it.

So which one is better in term of durability for a low end zoom lens? Canon, Sigma or Tamron? I don’t know what duration I should expect for such lenses. They were both 5 years old. I will give a try with a Tamron 18-200mm Di-II instead.

No protocol specified

When using a laptop, it is frequent that you have to switch from one network interface to another. As you do so on FreeBSD, you may find that your X server retreats itself into total mutism, refusing any command (xhost, xrandr…) or any new window. The only message it tells you, if by chance you still had a terminal open, is “No protocol specified”.

The reason behind this? When you switched from one interface to another, dhclient did not send your hostname to the DHCP server. Your ISP provided box-modem-router (connected directly because the gateway is down) wants to play the Good Samaritan and offers you a brand new hostname, say “new-host-7”. The DHCP client dutifully updates your hostname and as a result drives the X server completely nuts.

We can fix this in two ways. By default, the FreeBSD dhclient configuration (/etc/dhclient.conf) is empty. This means that dhclient does not send your hostname and that it requests an hostname from the DHCP server. What we want here is that the DHCP server knows about our hostname and that even if it supplies an hostname value, we supersedes this option with our real hostname. To achieve this, add two lines in /etc/dhclient.conf:

send host-name      "monty-bsd-laptop";
supersede host-name "monty-bsd-laptop";

These two lines are pretty self explanatory. It seems that FreeBSD does not expect you to aggressively switch between multiple interfaces, although it can. An example among others that FreeBSD is not originally intended for laptop usage.

ChangeLog

So I just wanted to post about a few things to come on this blog and my projects. I’m confident this is a better place to tell you about these things than changes coming out without notice on my website. So here it is, a series of bulleted list of things to come, a glimpse on a possible future:

  • I might post more often than I previously did. In particular on different subjects than what I usually posted.
  • I might post more often about FreeBSD (duh…)
  • Some changes in the licensing of my projects (more details in a following post).
  • GCalc becomes RPNC (more details in a following post).
  • If I have time (which I have not) some projects might undergo a major rewrite.
  • Some older projects got nearer to the top of my TODO list.