NcFTPd Auth Daemon

Starting with version 2.0.0 of NcFTPd, you can use an external process to authenticate user logins. This can be useful if you use a non-standard method of logging users in, such as querying an internal database or some sort of one-time password scheme such as S/KEY. The standard methods are built-in to NcFTPd, which include looking up the user and password in /etc/passwd and the shadow password file, and also using a NcFTPd Password Database built by ncftpd_passwd. Therefore, most sites will be able to use the standard methods and will not have a use for a custom process.

If you do have a need for custom user authentication, then you need to write a program using the Auth Daemon Software Development Kit.  The SDK includes ready-to-use source code for quick deployment using the C or Perl programming languages, so all that needs to be implemented is the code that does your user authentication.  The ncftpd_authd option in the file is used to configure NcFTPd to use your custom authentication rather than built-in methods.


Message Handling

NcFTPd communicates with your process with a series of UDP/IP messages, all of whom share the same structure, which is documented below.  All non-character fields are stored in network byte-order ("big endian"), so C programmers will need to use functions such as htonl() to set the fields of the structure.  Perl programmers do not need to worry about this since the SDK manages this internally.  Perl programmers will actually work with a reference to hash which contains all the fields below.

The mType field of the message is defined to be 3, in network byte order. All integral fields in the structure are to be converted to network byte order before sending. The state field tells which state of the authentication process is in effect.

Each message is cumulative, so that at any state, the results of the previous states are also known. For example, when the password message is received, the message also contains the username field from the previous user message.

Whenever your process sends a message back to NcFTPd, it may set the denied field to 1 to indicate that NcFTPd should immediately deny access and disconnect the user. It should also set the allowed field to 1 as soon as the user has supplied enough information such that the user should be logged in. It is possible that a message exchange will never set denied or allowed to non-zero if the user does not supply a valid username and password.

Whenever a message is received, it must preserve the private field of the sender. For example, if NcFTPd sends a message to the auth daemon, the auth daemon must preserve the contents of the ncftpdPrivate field when it sends the reply for that message.

The message types are detailed below.  It should be noted that the recommended "message mode" is for NcFTPd to only send a single kFTPAuthStatePassMessage.  This simplifies the message exchange protocol, since each login session will only have a single message sent to your Auth Daemon, and the Auth Daemon only sends a single reply message back.  However, for more fine-grained control, you have the option (by tweaking your ncftpd_authd  setting) to have the full message protocol implemented, where your Auth Daemon gets the Init and User messages as NcFTPd has that information available for you.


Init message
The init message is sent by NcFTPd to your process when a new user connects. At this time, the fields rAddr, hostName, ipstr, lAddr, cfname, and connectTime are valid.

The auth daemon init reply should simply be the same message back, optionally setting the denied field.

User message
When NcFTPd has prompted the remote client for a username and received the response from the remote client, it sends the auth daemon a user message with the username.

The auth daemon should either set the denied field, or return back a user reply message, which is the user message. You may also give the remote client a custom prompt, if you set the passPrompt field to other than an empty string. The default value is "331 User okay, need password.\r\n". You may find the passPrompt field is useful for a one-time password scheme, where you would have to present the remote user with the challenge string so that the user could enter the correct password.

Password message
After NcFTPd has prompted and received a response for the password, it sends the auth daemon the password message. At this point the only thing left to do is for the auth daemon to verify the user and password. The auth daemon must return the message back, and set allowed to non-zero if the user authenticated. (It should not set denied unless the user should be immediately disconnected.)

Along with the authentication result, the auth daemon returns the user information if the user is to be logged in. This includes the uid (user ID), gids (group IDs), ngids (number of group IDs in the array), the homedir (directory tree to access), and the restrictedUser flag (indicating if the user is confined to the homedir tree).

The only restriction is that NcFTPd will not accept a root login (uid equal to 0) from the auth daemon.

Message mode

By default NcFTPd will not use the complete message exchange; it will only send the password message (which is a superset of all the other messages). This is to reduce the number of unnecessary messages back and forth between NcFTPd and the auth daemon. If you do need to use the full set, you can configure NcFTPd to send all the messages by appending a ";2" after auth daemon address to indicate message mode 2. Example: "ncftpd_authd=localhost:9723;2"


XOR filter

The message is encoded for transit, by exclusive OR-ing the hex string 7FFFFEFF against the message contents. Upon receipt, the message should then be decoded by the same method. This prevents casual packet sniffers from picking up useful data; however, a determined sniffer would have no problem decoding the messages if they put forth an effort!

Additional security concerns

The auth daemon was designed to run on the same machine as the NcFTPd server. It uses UDP for interprocess communication, but the intent was for the UDP messages to be exchanged by two processes on the same server machine. Nevertheless, you could put the auth daemon on a different machine, although that is definitely not recommended! The messages are essentially sent in the clear, so when the remote client sent its password, it could be intercepted before reaching the auth daemon. It could be argued that it's easier to just snoop for rlogin and telnet sessions, but the point is that the message safety and validity can only be guaranteed when both NcFTPd and the auth daemon are on the same machine.

The software development kit

To get you started, source code for a sample NcFTPd Auth Daemon is available. You can use it to examine how the overall process works so you can then build in support for your own authentication.