# Setting up Netatalk

## Setting up the AFP file server

AFP
(the Apple Filing Protocol) is a protocol used on the Apple Macintosh for file services
. The protocol has evolved over the years. The final revision of the protocol, AFP 3.4, was introduced with a minor release of OS X Lion
(10.7).

Netatalk's `afpd` daemon offers AFP fileservices to Apple clients. The configuration is managed through the `afp.conf` file which uses an ini style configuration syntax.

Support for Spotlight
has been added in Netatalk 3.1.

Mac OS X 10.5 (Leopard) added support for Time Machine backups over AFP. Two new functions ensure that backups are written to spinning disk, not just in the server's cache. Different host operating systems honour this cache flushing differently. To make a volume a Time Machine target, use the volume option "`time machine = yes`".

Starting with Netatalk 2.1 UNIX symlinks
can be used on the server. Semantics are the same as for e.g. NFS, i.e. they are not resolved on the server side but instead it's completely up to the client to resolve them, resulting in links that point somewhere inside the clients filesystem view.

### afp.conf

`afp.conf` is the configuration file used by afpd to determine the behaviour and configuration of the AFP file server and the AFP volume that it provides.

The `afp.conf` is divided into several sections:

[Global]

- The global section defines general server options

[Homes]

- The homes section defines user home volumes

Any section not called `Global` or `Homes` is interpreted as an AFP volume.

For sharing user homes by defining a `Homes` section you must specify the option `basedir regex` which can be a simple string with the path to the parent directory of all user homes or a regular expression.

Example:

    [Homes]
    basedir regex = /home

Now any user logging into the AFP server will have a user volume available whose path is `/home/NAME`.

A more complex setup would be a server with a large amount of user homes which are split across e.g. two different filesystems:

- /RAID1/homes

- /RAID2/morehomes

The following configuration is required:

    [Homes]
    basedir regex = /RAID./.*homes

If `basedir regex` contains a symlink, set the canonicalized absolute path. When `/home` links to `/usr/home`:

    [Homes]
    basedir regex = /usr/home

For a more detailed explanation of the available options, please refer to the

afp.conf

5 man page.

## CNID
backends

Unlike other protocols like SMB or NFS, the AFP protocol mostly refers to files and directories by ID and not by a path (the IDs are also called CNID, which stand for Catalog Node ID). A typical AFP request uses a directory ID
and a filename, something like "server, please open the file named 'Test' in the directory with id 167". For example "Aliases" on the Mac basically work by ID (with a fallback to the absolute path in more recent AFP clients. But this applies only to Finder, not to applications).

Every file in an AFP volume has to have a unique file ID
, IDs must, according to the specs, never be reused, and IDs are 32 bit numbers (Directory IDs use the same ID pool). So, after ~4 billion files/folders have been written to an AFP volume, the ID pool is depleted and no new file can be written to the volume. No whining please :-)

Netatalk needs to map IDs to files and folders in the host filesystem. To achieve this, several different CNID backends
are available and can be selected with the `cnid scheme`
option in the

afp.conf

5 configuration file. A CNID backend is basically a database storing ID <-> name mappings.

The CNID databases are by default located in `/var/netatalk/CNID`. You can change the location by configuring `localstatedir` at compile time.

There is a command line utility called `dbd` available which can be used to verify, repair and rebuild the CNID database.

There are some CNID related things you should keep in mind when working with netatalk:

- Don't nest volumes
  unless "`vol dbnest = yes`" is set.

- CNID backends are databases, so they turn afpd into a file server/database mix.

- If there's no more space on the filesystem left, the database will get corrupted. You can work around this by using the `vol dbpath` option and put the database files into another location.

- Be careful with CNID databases for volumes that are mounted via NFS. That is a pretty audacious decision to make anyway, but putting a database there as well is really asking for trouble, i.e. database corruption. Use the `vol dbpath` directive to put the databases onto a local disk if you must use NFS
  mounted volumes.

### dbd

The "Database Daemon" backend is built on Berkeley DB. Access to the CNID database is restricted to the cnid_dbd daemon process. afpd processes communicate with the daemon for database reads and updates. The probability for database corruption is practically zero.

This is the default backend since Netatalk 2.1.

### last

The last backend is an in-memory tdb database. It is not persistent. Starting with netatalk 3.0, it operates in read only mode automatically. This is useful e.g. for CD-ROMs.

### mysql

CNID backend using a MySQL server. It gets automatically configured if the MySQL client development libraries are detected. Disable it through the `mysql-config` setting of the build system.

## Charsets
/Unicode

### Why Unicode?

Internally, computers don't know anything about characters and texts, they only know numbers. Therefore, each letter is assigned a number. A character set, often referred to as charset or codepage
, defines the mappings between numbers and letters.

If two or more computer systems need to communicate with each other, the have to use the same character set. In the 1960s the ASCII
(American Standard Code for Information Interchange) character set was defined by the American Standards Association. The original form of ASCII represented 128 characters, more than enough to cover the English alphabet and numerals. Up to date, ASCII has been the normative character scheme used by computers.

Later versions defined 256 characters to produce a more international fluency and to include some slightly esoteric graphical characters. Using this mode of encoding each character takes exactly one byte. Obviously, 256 characters still wasn't enough to map all the characters used in the various languages into one character set.

As a result localized character sets were defined later, e.g the ISO-8859 character sets. Most operating system vendors introduced their own characters sets to satisfy their needs, e.g. IBM defined the codepage 437 (DOSLatinUS), Apple introduced the MacRoman
codepage and so on. The characters that were assigned number larger than 127 were referred to as extended characters. These character sets conflict with another, as they use the same number for different characters, or vice versa.

Almost all of those characters sets defined 256 characters, where the first 128 (0-127) character mappings are identical to ASCII. As a result, communication between systems using different codepages was effectively limited to the ASCII charset.

To solve this problem new, larger character sets were defined. To make room for more character mappings, these character sets use at least 2 bytes to store a character. They are therefore referred to as multibyte character sets.

One standardized multibyte charset encoding scheme is known as unicode. A big advantage of using a multibyte charset is that you only need one. There is no need to make sure two computers use the same charset when they are communicating.

### Character sets used by Apple

In the past, Apple clients used single-byte charsets to communicate over the network. Over the years Apple defined a number of codepages, western users will most likely be using the MacRoman codepage.

Codepages defined by Apple include:

- MacArabic, MacFarsi

- MacCentralEurope

- MacChineseSimple

- MacChineseTraditional

- MacCroatian

- MacCyrillic

- MacDevanagari

- MacGreek

- MacHebrew

- MacIcelandic

- MacJapanese

- MacKorean

- MacRoman

- MacRomanian

- MacThai

- MacTurkish

Starting with Mac OS X and AFP3, UTF-8 is used. UTF-8 encodes Unicode characters in an ASCII compatible way, each Unicode character is encoded into 1-6 ASCII characters. UTF-8 is therefore not really a charset itself, it's an encoding of the Unicode charset.

To complicate things, Unicode defines several normalization forms. While samba
uses precomposed
Unicode, which most Unix tools prefer as well, Apple decided to use the decomposed
normalization.

For example lets take the German character 'ä'. Using the precomposed normalization, Unicode maps this character to 0xE4. In decomposed normalization, 'ä' is actually mapped to two characters, 0x61 and 0x308. 0x61 is the mapping for an 'a', 0x308 is the mapping for a COMBINING DIAERESIS.

Netatalk refers to precomposed UTF-8 as UTF8
and to decomposed UTF-8 as UTF8-MAC
.

### afpd and character sets

To support new AFP 3.x and older AFP 2.x clients at the same time, afpd needs to be able to convert between the various charsets used. AFP 3.x clients always use UTF8-MAC, while AFP 2.x clients use one of the Apple codepages.

At the time of writing, netatalk supports the following Apple codepages:

- MAC_CENTRALEUROPE

- MAC_CHINESE_SIMP

- MAC_CHINESE_TRAD

- MAC_CYRILLIC

- MAC_GREEK

- MAC_HEBREW

- MAC_JAPANESE

- MAC_KOREAN

- MAC_ROMAN

- MAC_TURKISH

afpd handles three different character set options:

unix charset

- This is the codepage used internally by your operating system. If not specified, it defaults to `UTF8`. If `LOCALE` is specified and your system support Unix locales, afpd tries to detect the codepage. afpd uses this codepage to read its configuration files, so you can use extended characters for volume names, login messages, etc. See

  afp.conf

  5 .

mac charset

- As already mentioned, older Mac OS clients (up to AFP 2.2) use codepages to communicate with afpd. However, there is no support for negotiating the codepage used by the client in the AFP protocol. If not specified otherwise, afpd assumes the MacRoman codepage is used. In case you're clients use another codepage, e.g. MacCyrillic, you'll have to explicitly configure this. see

  afp.conf

  5 .

vol charset

- This defines the charset afpd should use for filenames on disk. By default, it is the same as `unix charset`. If you have iconv
  installed, you can use any iconv provided charset as well.

  afpd needs a way to preserve extended Macintosh characters, or characters illegal in Unix filenames, when saving files on a Unix filesystem. Earlier versions used the the so called CAP encoding
  . An extended character (>0x7F) would be converted to a :xx hex sequence, e.g. the Apple Logo (MacRoman: 0xF0) was saved as :f0. Some special characters will be converted as to :xx notation as well. '/' will be encoded to :2f, if `usedots` was not specified, a leading dot '.' will be encoded as :2e.

  Even though this version now uses `UTF8` as the default encoding for filenames, '/' will be converted to ':'. For western users another useful setting could be `vol charset = ISO-8859-15`.

  If a character cannot be converted from the `mac charset` to the selected `vol charset`, you'll receive a -50 error on the mac. Note: Whenever you can, please stick with the default UTF8 volume format. See

  afp.conf

  5 .

## Authentication

### AFP authentication basics

Apple chose a flexible model called "User Authentication Modules"
(UAMs) for authentication purposes between AFP client and server. An AFP client initially connecting to an AFP server will ask for the list of UAMs which the server provides, and will choose the one with strongest encryption that the client supports.

Several UAMs have been developed by Apple over the time, some by 3rd-party developers.

### UAMs supported by Netatalk

Netatalk supports the following ones by default:

- "No User Authent"
  UAM (guest access without authentication)

- "Cleartxt Passwrd"
  UAM (no password encryption)

- "Randnum exchange"
  /"2-Way Randnum exchange"
  UAMs (weak password encryption, separate password storage)

- "DHCAST128"
  UAM (a.k.a. DHX; stronger password encryption)

- "DHX2"
  UAM (successor of DHCAST128)

There exist other optional UAMs as well:

- "PGPuam 1.0"
  UAM (PGP-based authentication for pre-Mac OS X clients. You'll also need the PGPuam client to let this work)

  You may have to enable it at compile time to have this UAM available.

- "Client Krb v2"
  UAM (Kerberos V, suitable for "Single Sign On" Scenarios with OS X clients -- see below)

  You may have to deliberately enable this one too when compiling the code.

You can configure which UAMs should be activated by defining "`uam list`" in `Global` section. `afpd` will log which UAMs it's using and if problems occur while activating them in either `netatalk.log` or syslog at startup time.

asip-status

1 can be used to query the available UAMs of AFP servers as well.

Having a specific UAM available at the server does not automatically mean that a client can use it. Client-side support is also necessary. For older Macintoshes running Mac OS < X DHCAST128 support exists since AppleShare client 3.8.x.

On OS X, there exist some client-side techniques to make the AFP-client more verbose, so one can have a look what's happening while negotiating the UAMs to use. Compare with this hint.

### Which UAMs to activate?

It depends primarily on your needs and on the kind of Mac OS versions you have to support. Basically one should try to use DHCAST128 and DHX2 where possible because of its strength of password encryption.

- Unless you really have to supply guest access to your server's volumes ensure that you disable "No User Authent" since it might lead accidentally to unauthorized access. In case you must enable guest access take care that you enforce this on a per volume base using the access controls.

- The "ClearTxt Passwrd" UAM is as bad as it sounds since passwords go unencrypted over the wire. Try to avoid it at both the server's side as well as on the client's. Note: If you want to provide Mac OS 8/9 clients with NetBoot-services then you need uams_cleartext.so since the AFP-client integrated into the Mac's firmware can only deal with this basic form of authentication.

- Since "Randnum exchange"/"2-Way Randnum exchange" uses only 56 bit DES for encryption it should be avoided as well. Another disadvantage is the fact that the passwords have to be stored in cleartext on the server and that it doesn't integrate into both PAM scenarios or classic /etc/shadow (you have to administrate passwords separately by using the

  afppasswd

  1 utility, in order for clients to use these UAMs)

- "DHCAST128" or "DHX2" should be the sweet spot for most people since it combines stronger encryption with PAM integration.

- Using the Kerberos V
  ("Client Krb v2") UAM, it's possible to implement real single sign on scenarios using Kerberos tickets. The password is not sent over the network. Instead, the user password is used to decrypt a service ticket for the appleshare server. The service ticket contains an encryption key for the client and some encrypted data (which only the appleshare server can decrypt). The encrypted portion of the service ticket is sent to the server and used to authenticate the user. Because of the way that the afpd service principal detection is implemented, this authentication method is vulnerable to man-in-the-middle attacks.

For a more detailed overview over the technical implications of the different UAMs, please have a look at Apple's File Server Security pages.

### Using different authentication sources with specific UAMs

Some UAMs provide the ability to use different authentication "backends", namely `uams_cleartext.so`, `uams_dhx.so` and `uams_dhx2.so`. They can use either classic Unix passwords from `/etc/passwd` (`/etc/shadow`) or PAM if the system supports that. `uams_cleartext.so` can be symlinked to either `uams_passwd.so` or `uams_pam.so`, `uams_dhx.so` to `uams_dhx_passwd.so` or `uams_dhx_pam.so` and `uams_dhx2.so` to `uams_dhx2_passwd.so` or `uams_dhx2_pam.so`.

So, if it looks like this in Netatalk's UAMs folder (per default `/etc/netatalk/uams/`):

    uams_clrtxt.so -> uams_pam.so
    uams_dhx.so -> uams_dhx_pam.so
    uams_dhx2.so -> uams_dhx2_pam.so

then you're using PAM, otherwise classic Unix passwords. The main advantage of using PAM is that one can integrate Netatalk in centralized authentication scenarios, e.g. via LDAP, NIS and the like. Please always keep in mind that the protection of your user's login credentials in such scenarios also depends on the strength of encryption that the UAM in question supplies. So think about eliminating weak UAMs like "ClearTxt Passwrd" and "Randnum exchange" completely from your network.

### Netatalk UAM overview table

A small overview of the most common used UAMs.

### Netatalk UAM overview

UAM | No User Authent | Cleartxt Passwrd | (2-Way) Randnum exchange | DHCAST128 | DHX2 | Client Krb v2
Password length | guest access | max. 8 characters | max. 8 characters | max. 64 characters | max. 256 characters | Kerberos tickets
Client support | built-in into all Mac OS versions | built-in in all Mac OS versions except 10.0. Has to be activated explicitly in recent Mac OS X versions | built-in into almost all Mac OS versions | built-in since AppleShare client 3.8.4, available as a plug-in for 3.8.3, integrated in Mac OS X' AFP client | built-in since Mac OS X 10.2 | built-in since Mac OS X 10.2
Encryption | Enables guest access without authentication between client and server. | Password will be sent in cleartext over the wire. Just as bad as it sounds, therefore avoid at all if possible (note: providing NetBoot services requires the ClearTxt UAM) | 8-byte random numbers are sent over the wire, comparable with DES, 56 bits. Vulnerable to offline dictionary attack. Requires passwords in clear on the server. | Password will be encrypted with 128 bit SSL, user will be authenticated against the server but not vice versa. Therefore weak against man-in-the-middle attacks. | Password will be encrypted using libgcrypt with CAST 128 in CBC mode. User will be authenticated against the server but not vice versa. Therefore weak against man-in-the-middle attacks. | Password is not sent over the network. Due to the service principal detection method, this authentication method is vulnerable to man-in-the-middle attacks.
Server support | uams_guest.so | uams_cleartxt.so | uams_randnum.so | uams_dhx.so | uams_dhx2.so | uams_gss.so
Password storage method | None | Either /etc/passwd (/etc/shadow) or PAM | Passwords stored in clear text in a separate text file | Either /etc/passwd (/etc/shadow) or PAM | Either /etc/passwd (/etc/shadow) or PAM | At the Kerberos Key Distribution Center*

* Have a look at this Kerberos overview

### SSH tunneling

Tunneling and VPNs usually have nothing to do with AFP authentication and UAMs. But since Apple introduced an option called "Allow Secure Connections Using SSH" and many people tend to confuse the two, we'll cover this here.

#### Manually tunneling an AFP session

This works since the first AFP servers that spoke "AFP over TCP" appeared in networks. One simply tunnels the remote server's AFP port to a local port different than 548 and connects locally to this port afterwards. On OS X this can be done by

    ssh -l $USER $SERVER -L 10548:127.0.0.1:548 sleep 3000

After establishing the tunnel one will use `"afp://127.0.0.1:10548"` in the "Connect to server" dialog. All AFP traffic including the initial connection attempts will be sent encrypted over the wire since the local AFP client will connect to the Mac's local port 10548 which will be forwarded to the remote server's AFP port (we used the default 548) over SSH.

This sort of tunnel is an ideal solution if you must access an AFP server through the Internet without having the ability or desire to use a "real" VPN. Note that you can let `ssh` compress the data by using its "-C" switch and that the tunnel endpoints can be different from both AFP client and server (compare with the SSH documentation for details).

#### Automatically establishing a tunneled AFP connection

From Mac OS X 10.2 to 10.4, Apple added an "Allow Secure Connections Using SSH" checkbox to the "Connect to Server" dialog. The idea behind this was: When the server signals that it can be contacted by SSH then Mac OS X's AFP client tries to establish the tunnel and automagically send all AFP traffic through it.

But it took until the release of Mac OS X 10.3 that this feature worked the first time... partly. In case, the SSH tunnel could not be established and the AFP client silently fell back to an unencrypted AFP connection attempt.

Netatalk's afpd will report that it is capable of handling SSH tunneled AFP requests, when both "`advertise ssh`" and "`fqdn`" options are set in the `Global` section (double check with

asip-status

1 after you restarted afpd when you made changes to the settings). But there are a couple of reasons why you don't want to use this option at all:

- Most users who need such a feature are probably already familiar with using a VPN; it might be easier for the user to employ the same VPN software in order to connect to the network on which the AFP server is running, and then to access the AFP server as normal.

  That being said, for the simple case of connecting to one specific AFP server, a direct SSH connection is likely to perform better than a general-purpose VPN; contrary to popular belief, tunneling via SSH does not result in what's called "TCP-over-TCP meltdown", because the AFP data that are being tunneled do not encapsulate TCP data.

- Since this SSH kludge isn't a normal UAM that integrates directly into the AFP authentication mechanisms but instead uses a single flag signalling clients whether they can try to establish a tunnel or not, it makes life harder to see what's happening when things go wrong.

- You cannot control which machines are logged on by Netatalk tools like a `macusers` since all connection attempts seem to be made from localhost.

- Indeed, to ensure that all AFP sessions are encrypted via SSH, you need to limit afpd to connections that originate only from localhost (e.g., by using Wietse Venema's TCP Wrappers, or by using suitable firewall or packet-filtering facilities, etc.).

  Otherwise, when you're using Mac OS X 10.2 through 10.3.3, you get the opposite of what you'd expect: potentially unencrypted AFP communications (including login credentials) being sent across the network without a single notification that establishing the tunnel failed. Apple fixed that with Mac OS X 10.3.4.

- Encrypting all AFP sessions via SSH can lead to a significantly higher load on the computer that is running the AFP server, because that computer must also handle encryption; if the user is connecting through a trusted network, then such encryption might be an unnecessary overhead.

## ACL Support

ACL support for AFP is implemented for ZFS ACLs on Solaris and derived platforms and for POSIX 1e ACLs on Linux.

### Configuration

For a basic mode of operation there's nothing to configure. Netatalk reads ACLs on the fly and calculates effective permissions which are then send to the AFP client via the so called UARights
permission bits. On a Mac, the Finder uses these bits to adjust permission in Finder windows. Example: a folder whose UNIX mode is read-only and an ACL giving the user write access, will display the effective read-write permission. Without the permission mapping the Finder would display a read-only icon and the user wouldn't be able to write to the folder.

By default, the effective permission of the authenticated user are only mapped to the mentioned UARights
permission structure, not the UNIX mode. You can adjust this behaviour with the configuration option map acls.

However, neither in Finder "Get Info" windows nor in the Terminal will you be able to see the ACLs, because of how ACLs in OS X are designed. If you want to be able to display ACLs on the client, things get more involved as you must then setup both client and server to be part on a authentication domain (directory service, e.g. LDAP, OpenDirectory). The reason is, that in OS X ACLs are bound to UUIDs, not just uid's or gid's. Therefore afpd must be able to map every filesystem uid and gid to a UUID so that it can return the server side ACLs which are bound to UNIX uid and gid mapped to OS X UUIDs.

Netatalk can query a directory server using LDAP queries. Either the directory server already provides an UUID attribute for user and groups (Active Directory, Open Directory) or you reuse an unused attribute (or add a new one) to you directory server (eg OpenLDAP).

In detail:

1. For Solaris/ZFS: ZFS Volumes

   You should configure a ZFS ACL know for any volume you want to use with Netatalk:

       aclinherit = passthrough
       aclmode = passthrough

   For an explanation of what this knob does and how to apply it, check your hosts ZFS documentation (eg man zfs).

2. Authentication Domain

   Your server and the clients must be part of a security association where identity data is coming from a common source. ACLs in Darwin are based on UUIDs and so is the ACL specification in AFP 3.2. Therefore your source of identity data has to provide an attribute for every user and group where a UUID is stored as a ASCII string. In other words:

   - you need an Open Directory Server or an LDAP server where you store UUIDs in some attribute

   - your clients must be configured to use this server

   - your server should be configured to use this server via nsswitch and PAM

   - configure Netatalk via the special LDAP options for ACLs in afp.conf so that Netatalk is able to retrieve the UUID for users and groups via LDAP search queries

### OS X ACLs

With Access Control Lists (ACLs) Mac OS X offers a powerful extension of the traditional UNIX permissions model. An ACL is an ordered list of Access Control Entries (ACEs) explicitly granting or denying a set of permissions to a given user or group.

Unlike UNIX permissions, which are bound to user or group IDs, ACLs are tied to UUIDs. For this reason accessing an object's ACL requires server and client to use a common directory service which translates between UUIDs and user/group IDs.

ACLs and UNIX permissions interact in a rather simple way. As ACLs are optional UNIX permissions act as a default mechanism for access control. Changing an objects's UNIX permissions will leave it's ACL intact and modifying an ACL will never change the object's UNIX permissions. While doing access checks, OS X first examines an object's ACL evaluating ACEs in order until all requested rights have been granted, a requested right has been explicitly denied by an ACE or the end of the list has been reached. In case there is no ACL or the permissions granted by the ACL are not sufficient to fulfill the request, OS X next evaluates the object's UNIX permissions. Therefore ACLs always have precedence over UNIX permissions.

### ZFS ACLs

ZFS ACLs closely match OS X ACLs. Both offer mostly identical fine grained permissions and inheritance settings.

### POSIX ACLs

#### Overview

Compared to OS X or NFSv4 ACLs, Posix ACLs represent a different, less versatile approach to overcome the limitations of the traditional UNIX permissions. Implementations are based on the withdrawn Posix 1003.1e standard.

The standard defines two types of ACLs. Files and directories can have access ACLs which are consulted for access checks. Directories can also have default ACLs irrelevant to access checks. When a new object is created inside a directory with a default ACL, the default ACL is applied to the new object as it's access ACL. Subdirectories inherit default ACLs from their parent. There are no further mechanisms of inheritance control.

Architectural differences between Posix ACLs and OS X ACLs especially involve:

- No fine-granular permissions model. Like UNIX permissions Posix ACLs only differentiate between read, write and execute permissions.

- Entries within an ACL are unordered.

- Posix ACLs can only grant rights. There is no way to explicitly deny rights by an entry.

- UNIX permissions are integrated into an ACL as special entries.

Posix 1003.1e defines 6 different types of ACL entries. The first three types are used to integrate standard UNIX permissions. They form a minimal ACL, their presence is mandatory and only one entry of each type is allowed within an ACL.

- ACL_USER_OBJ: the owner's access rights.

- ACL_GROUP_OBJ: the owning group's access rights.

- ACL_OTHER: everybody's access rights.

The remaining entry types expand the traditional permissions model:

- ACL_USER: grants access rights to a certain user.

- ACL_GROUP: grants access rights to a certain group.

- ACL_MASK: limits the maximum access rights which can be granted by entries of type ACL_GROUP_OBJ, ACL_USER and ACL_GROUP. As the name suggests, this entry acts as a mask. Only one ACL_MASK entry is allowed per ACL. If an ACL contains ACL_USER or ACL_GROUP entries, an ACL_MASK entry must be present too, otherwise it is optional.

In order to maintain compatibility with applications not aware of ACLs, Posix 1003.1e changes the semantics of system calls and utilities which retrieve or manipulate an objects UNIX permissions. In case an object only has a minimal ACL, the group permissions bits of the UNIX permissions correspond to the value of the ACL_GROUP_OBJ entry.

However, if the ACL also contains an ACL_MASK entry, the behavior of those system calls and utilities is different. The group permissions bits of the UNIX permissions correspond to the value of the ACL_MASK entry, i. e. calling "chmod g-w" will not only revoke write access for the group, but for all entities which have been granted write access by ACL_USER or ACL_GROUP entries.

#### Mapping POSIX ACLs to OS X ACLs

When a client wants to read an object's ACL, afpd maps it's Posix ACL onto an equivalent OS X ACL. Writing an object's ACL requires afpd to map an OS X ACL onto a Posix ACL. Due to architectural restrictions of Posix ACLs, it is usually impossible to find an exact mapping so that the result of the mapping process will be an approximation of the original ACL's semantic.

- afpd silently discard entries which deny a set of permissions because they they can't be represented within the Posix architecture.

- As entries within Posix ACLs are unordered, it is impossible to preserve order.

- Inheritance control is subject to severe limitations as well:

  - Entries with the only_inherit flag set will only become part of the directory's default ACL.

  - Entries with at least one of the flags file_inherit, directory_inherit or limit_inherit set, will become part of the directory's access and default ACL, but the restrictions they impose on inheritance will be ignored.

- The lack of a fine-granular permission model on the Posix side will normally result in an increase of granted permissions.

As OS X clients aren't aware of the Posix 1003.1e specific relationship between UNIX permissions and ACL_MASK, afpd does not expose this feature to the client to avoid compatibility issues and handles *unix permissions and ACLs the same way as Apple's reference implementation of AFP does. When an object's UNIX permissions are requested, afpd calculates proper group rights and returns the result together with the owner's and everybody's access rights to the caller via "permissions" and "ua_permissions" members of the FPUnixPrivs structure (see Apple Filing Protocol Reference, page 181). Changing an object's permissions, afpd always updates ACL_USER_OBJ, ACL_GROUP_OBJ and ACL_OTHERS. If an ACL_MASK entry is present too, afpd recalculates it's value so that the new group rights become effective and existing entries of type ACL_USER or ACL_GROUP stay intact.

## Filesystem Change Events

Netatalk includes a nifty filesystem change event mechanism where afpd processes notfiy interested listeners about certain filesystem event by UDP network datagrams.

For the format of the UDP packets and for an example C application that demonstrates how to use these in a listener, take a look at the Netatalk source file `bin/misc/fce.c`.

The currently supported FCE v1 events are:

- file modification (fmod)

- file deletion (fdel)

- directory deletion (ddel)

- file creation (fcre)

- directory creation (dcre)

When using FCE v2 you also get:

- file moving (fmov)

- directory moving (dmov)

- user login (login)

- user logout (logout)

For details on the available simple configuration options, take a look at `afp.conf`.

## Spotlight

Starting with version 3.1 Netatalk supports Spotlight searching. Netatalk uses Gnome Tracker as metadata store, indexer and search engine.

### Configuration

You can enable Spotlight and indexing either globally or on a per volume basis with the `spotlight` option.

Once Spotlight is enable for a single volume, all other volumes for which spotlight is disabled won't be searchable at all.

The `dbus-daemon` binary has to be installed for Spotlight feature. The path to dbus-daemon is determined at compile time the dbus-daemon build system option.

In case the `dbus-daemon` binary is installed at the other path, you must use the global option `dbus daemon` to point to the path, e.g. for Solaris with Tracker from OpenCSW:

    dbus daemon = /opt/csw/bin/dbus-daemon

#### Limitations and notes

- Large filesystems

  Tracker on Linux uses the inotify Kernel filesystem change event API for tracking filesystem changes. On large filesystems this may be problematic since the inotify API doesn't offer recursive directory watches but instead requires that for every subdirectoy watches must be added individually.

  On Solaris the FEN file event notification system is used. It is unknown which limitations and resource consumption this Solaris subsystem may have.

  We therefore recommend to disable live filesystem monitoring and let Tracker periodically scan filesystems for changes instead, see the Tracker configuration options enable-monitors and crawling-interval below.

- Indexing home directories

  A known limitation with the current implementation means that shared volumes in a user's home directory does not get indexed by Spotlight.

  As a workaround, keep the shared volumes you want to have indexed elsewhere on the host filesystem.

### Using Tracker commandline tools on the server

Netatalk must be running, commands must be executed as root and some environment variables must be set up.

If the .tracker_profile file does not exist, create it first. If you need to make the environment variables persistent, source .tracker_profile from /root/.profile. If needed, adjust PREFIX to point to the base directory Netatalk is installed to, and replace "/var" with the localstate directory configured at compile time.

    $ su
          # cat .tracker_profile
          PREFIX="/usr/local"
          export XDG_DATA_HOME="$PREFIX/var/netatalk/"
          export XDG_CACHE_HOME="$PREFIX/var/netatalk/"
          export DBUS_SESSION_BUS_ADDRESS="unix:path=$PREFIX/var/netatalk/spotlight.ipc"
          # . .tracker_profile
          #

When using Tracker from OpenCSW you must also update your PATH:

    # export PATH=/opt/csw/bin:$PATH

#### Common Tracker commands

Querying Tracker status:

-     # tracker daemon

Stop Tracker:

-     # tracker daemon -t

Start Tracker:

-     # tracker daemon -s

Reindex directory:

-     # tracker index -f PATH

Query Tracker for information about a file or directory:

-     # tracker info PATH

Search Tracker:

-     # tracker search QUERY

#### Advanced Tracker command line configuration

Tracker stores its configuration via Gnome dconf backend which can be modified with the command `gsettings`.

Gnome dconf settings are per-user settings, so, as Netatalk runs the Tracker processes as root, the settings are stored in the root user context and reading or changing these settings must be performed as root and Netatalk must be running (and again the environment must be set up as shown above).

    # gsettings list-recursively | grep Tracker
    org.freedesktop.Tracker.Writeback verbosity 'debug'
    ...

The following list describes some important Tracker options and their default settings.

org.freedesktop.Tracker.Miner.Files index-recursive-directories

- This option controls which directories Tracker will index. Don't change this option manually as it is automatically set by Netatalk reflecting the setting of the `Spotlight` option of Netatalk volumes.

org.freedesktop.Tracker.Miner.Files enable-monitors `true`

- The value controls whether Tracker watches all configured paths for modification. Depending on the filesystem modification backend (FAM on Linux, FEN on Solaris), this feature may not work as reliable as one might wish, so it may be safer to disable it and instead rely on periodic crawling of Tracker itself. See aslo the option `crawling-interval` .

org.freedesktop.Tracker.Miner.Files crawling-interval `-1`

- Interval in days to check the filesystem is up to date in the database, maximum is 365, default is -1. -2 = crawling is disabled entirely, -1 = crawling *may* occur on startup (if not cleanly shutdown), 0 = crawling is forced

### Supported metadata attributes

The following table lists the supported Spotlight metadata attributes

### Supported Spotlight metadata attributes

Description | Spotlight Key
Name | kMDItemDisplayName, kMDItemFSName
Document content (full text search) | kMDItemTextContent
File type | _kMDItemGroupId, kMDItemContentTypeTree
File modification date | kMDItemFSContentChangeDate, kMDItemContentModificationDate, kMDItemAttributeChangeDate
Content Creation date | kMDItemContentCreationDate
The author, or authors, of the contents of the file | kMDItemAuthors, kMDItemCreator
The name of the country where the item was created | kMDItemCountry
Duration | kMDItemDurationSeconds
Number of pages | kMDItemNumberOfPages
Document title | kMDItemTitle
The width, in pixels, of the contents. For example, the image width or the video frame width | kMDItemPixelWidth
The height, in pixels, of the contents. For example, the image height or the video frame height | kMDItemPixelHeight
The color space model used by the document contents | kMDItemColorSpace
The number of bits per sample | kMDItemBitsPerSample
Focal length of the lens, in millimeters | kMDItemFocalLength
ISO speed | kMDItemISOSpeed
Orientation of the document. Possible values are 0 (landscape) and 1 (portrait) | kMDItemOrientation
Resolution width, in DPI | kMDItemResolutionWidthDPI
Resolution height, in DPI | kMDItemResolutionHeightDPI
Exposure time, in seconds | kMDItemExposureTimeSeconds
The composer of the music contained in the audio file | kMDItemComposer
The musical genre of the song or composition | kMDItemMusicalGenre

#### References

1. MDItem

2. Tracker