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 general.cf file is used to configure NcFTPd to use your custom authentication rather than built-in methods.
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.
typedef struct FTPAuthState { authd_int32_t mType; authd_int32_t state; authd_int32_t duplicate; /* Init message. */ struct sockaddr_in rAddr; /* of remote client. */ char hostName[64]; /* of remote client. */ char ipstr[32]; /* of remote client. */ struct sockaddr_in lAddr; /* of FTP server. */ char cfname[64]; /* of FTP server. */ unsigned authd_int32_t connectTime; /* Init reply message. */ /* Username message. */ char username[64]; /* Username reply message. */ char passPrompt[256]; /* Password message. */ char passwd[64]; /* Password reply message. */ authd_int32_t uid; authd_int32_t gids[1 + kAuthdMaxSupplementaryGroups]; /* pri + supp */ unsigned authd_int32_t ngids; authd_int32_t restrictedUser; char homedir[128]; authd_int32_t denied; authd_int32_t allowed; authd_int32_t quotaHardkB; authd_int32_t quotaSoftkB; /* not used yet */ authd_int32_t quotaHardNumFiles; authd_int32_t quotaSoftNumFiles; /* not used yet */ authd_int32_t quotaFlags; /* not used yet */ /* The following fields are new to NcFTPd 2.8.0. * In an attempt to preserve compatibility with unmodified * Authd programs, the ncftpdPrivate field has been adjusted * so the size of the structure remains the same. */ char umask[4]; /* Set by your Authd at PW reply. */ char userPermissions[28]; /* Set by your Authd at PW reply. */ char sessionID[40]; /* Unique. Set by NcFTPd. */ char eventdCookie[80]; /* For future use; set by NcFTPd */ char authdCookie[80]; /* Set by your Authd, sent to Eventd */ authd_int32_t retrBandwidthLimit; /* Set by your Authd at PW reply. */ authd_int32_t storBandwidthLimit; /* Set by your Authd at PW reply. */ char ncftpdPrivate[256 - 4 - 28 - 40 - 80 - 80 - 2 * sizeof(authd_int32_t) /* = 16 */]; char authdPrivate[256]; /* Additional storage for your Authd. */ } FTPAuthState, *FTPAuthStatePtr; #define kFTPAuthStateMType 3 #define kFTPAuthStateInitMessage 1 #define kFTPAuthStateInitReply 2 #define kFTPAuthStateUserMessage 3 #define kFTPAuthStateUserReply 4 #define kFTPAuthStatePassMessage 5 #define kFTPAuthStatePassReply 6
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.