API
上传用户:pycemail
上传日期:2007-01-04
资源大小:329k
文件大小:11k
- ProFTPD Application Programmer Interface
- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- NOTE: This API documentation ONLY applies to proftpd versions 1.1.5 and
- greater, wherein the module interface was significantly enhanced.
- ProFTPD modules are designed to handle and respond to configuration
- directives (at startup), FTP commands sent over the control connection by
- FTP clients, and authentication requests.
- Module are prioritized in the *inverse* order of which they were loaded.
- In other words, the last loaded module is the FIRST to receive calls for a
- particular configuration directive, ftp command or authentication request.
- This can be used to allow later loaded modules (higher priority) to
- (optionally) "override" lower priority modules. Thus, load order of the
- modules can be VERY important.
- Module handler functions are _always_ declared as:
- MODRET my_handler_func(cmd_rec *cmd);
- In include/modules.h, MODRET is defined as 'static modret_t *'. cmd_rec
- is a structure created by the engine and passed to the handler which
- contains all information regarding the command, etc. modret_t is a
- special structure that is created by the handler and returned to the
- engine in order to tell the engine how to proceed. There are a few macros
- in include/modules.h which allow the module programmer to easily create
- return structures. The `cmd' argument to each macro is a pointer to
- the current module function's cmd_rec structure.
- HANDLED(cmd)
- - indicates that the handler properly handled the command, and that the
- engine should consider the command completed and continue processing.
- Note that if a module handler returns HANDLED, POST_CMD handlers
- will be called for the command (see below for handler types).
- DECLINED(cmd)
- - indicates that the engine should act as though the handler was never
- called and continue processing. POST_CMD type handlers will NOT
- be called in this case.
- ERROR(cmd)
- - A protocol error occured. POST_CMD type handlers are NOT
- called.
- ERROR_MSG(cmd,numeric,message)
- - Same as above, however the string composed of "numeric message" is sent
- to the client. In the case of directive configuration handlers, the
- "numeric" argument is ignored, "message" is displayed to the user (or
- logged via syslog), and proftpd terminates.
- ERROR_INT(cmd,n)
- - Same as above, however this indicates a single integer numeric error.
- (Used only in authentication/mapping handlers [see mod_unixpw.c])
- Handler Tables
- --------------
- Each module can define up to three different handler tables (which are
- registered via the module structure). These need not all be supplied.
- They are grouped by handler class:
- conftable[]: For configuration directive handlers.
- cmdtable[]: For command handlers, including POST_CMD and PRE_CMD
- (see below)
- authtable[]: For authentication handlers.
- The "conftable" is a structure which lists all configuration directive
- handlers for the module.
- The "cmdtable" is a structure which lists all FTP command handlers for the
- module. Each entry in this table contains a special "command type" field
- which determines the general 'type' of handler. There are currently four
- types: CMD, PRE_CMD, and POST_CMD and LOG_CMD. When proftpd receives a
- command for a client, it enters a five (eight?) step command->module
- cascading delivery process:
- 1. Call any PRE_CMD type handlers which match the special "*"
- command wildcard
- 1a. Call any PRE_CMD type handlers which match the command.
- 2. Call any CMD type handlers which match the special "*"
- command wildcard
- 2a. Call any CMD type handlers which match the command.
- 3. Call any POST_CMD type handlers which match the special "*"
- command wildcard
- 3a. Call any POST_CMD type handlers which match the command.
- 4. Call any LOG_CMD type handlers which match the special "*" wildcard.
- 5. Call any LOG_CMD type handlers which match the command.
- Further more, the return type of a particular command can allow or
- disallow further dispatching. Rules:
- PRE_CMD:
- 1. If DECLINED is returned, all other PRE_CMD handlers are called.
- 2. If ERROR is returned, command handler dispatching stops completely.
- CMD:
- 1. If DECLINED is returned, all other CMD handlers are called.
- 2. If ERROR is returned, command handler dispatching stops completely.
- POST_CMD:
- 1. If ERROR is returned, the message (if any) is sent to syslog,
- however because the CMD handler already executed, nothing further
- can be done.
-
- As you can no doubt see, this allows a higher priority module to
- "overload" a PRE_CMD handler for a particular command and allow/disallow
- the command as desired.
- As a general rule of thumb, PRE_CMD handlers should check syntax/basic
- applicability of the command, while CMD type handlers should actually
- do the 'work'. POST_CMD handlers generally handle any kind of cleanup,
- while LOG_CMD handlers handle logging successful completion of the
- command.
- Responding to client requests in command handlers
- =================================================
- There are two main ways to respond to a client command inside a command
- handler. The first way is incompatible with other other handlers, and
- should only be used if the handler is about to terminate the current
- connection (and thus kill the child, usually with end_login()). This
- first method, using one of the core functions outlined below, must be used
- because in the event that a handler is about to terminate proftpd, the
- internal response lists will never be processed by the proftpd engine.
- Method 1 (Use only in conjunction with end_login() or similar
- termination)
- send_response(char *numeric, char *format, ...);
- -- immediately sends the given response with the indicated numeric
- to the client
- send_response_ml_start(char *numeric, char *format, ...);
- -- starts a multiline ftp protocol with the given numeric
- send_response_ml(char *format, ...);
- -- continues a multiline response using the numeric specified
- in send_response_ml_start();
- send_response_ml_end(char *format, ...);
- -- completes a multiline response
- send_response_async(char *numeric, char *format, ...);
- -- send an asyncronous message to the client, this function is
- suitable for use inside signal handlers
- The second, and prefered, method of transmitting numeric + text message
- responses to clients is via the internal response chain. Using this
- allows all handlers to add their own individual responses which will all
- be sent en masse after the command successfully completes (or fails).
- Proftpd maintains two such chains, one response chain for success
- messages, and one for error messages. However, when all handlers for a
- given command have been called, proftpd evaluates the final condition of
- the command. If it has failed (caused by a handler returning one of the
- available ERROR* macros), all responses pending in the error response
- chain are sent. If the command has successfully completed, the normal
- (success) response chain is sent. If a command has neither completed
- successfully nor resulted in an error, proftpd assumes the command is
- invalid and informs the client appropriately. Either way, once the
- "lifetime" of the command is over, and one (or none) of the response
- chains has been sent, BOTH chains are destroyed.
- Method 2 (using response chains)
- add_response(char *numeric, char *format, ...);
- -- adds the given numeric + message to the end of the _success_
- chain, to be sent if the command successfully completes.
- add_response_err(char *numeric, char *format, ...);
- -- adds the given numeric + message to the end of the _error_
- chain, to be sent if the command results in a final error.
- As you can see, with method 2, there is no corresponding _ml* functions
- for multiline replies. This is because proftpd automatically generates a
- multiline format reply if it detects that there are two or more responses
- with the same numeric waiting to be sent to the client. In many cases,
- you may be writing a handler (post_cmd, for example) that neither cares
- nor specifically knows what numerics other handlers are using during their
- responses. In this case, you can use the special R_DUP response numeric,
- which tells proftpd that your response should be _assumed_ to be part of a
- multiline response started by another handler. For example, if the
- following add_response() calls were made from different modules:
- module a:
- add_response(R_200,"Command successfully completed.");
- module b:
- add_response(R_DUP,"Statistics for command '%s': none.",cmd->argv[0]);
- module c:
- add_response(R_DUP,"XFOO post_cmd handler ran.");
- The final output sent to the client (assuming the command was successfully
- handled) would be (assuming your command is named 'XFOO'):
- 200-Command successfully completed.
- Statistics for command 'XFOO': none.
- 200 XFOO post_cmd handler ran.
- Authentication Handlers
- =======================
- Authentication handlers allow a module to provide (or overload)
- authentication, uid/gid to name and name to uid/gid mappings.
- In order for a module to provide this functionality, it must export an
- authtable (via the module structure), and define one or more of the
- following handler "names" (authtable.name).
- Each handler accepts data in the cmd structure and should return it's
- data in the modret->data field. The core function mod_create_data()
- can create this data structure properly for return to the caller.
- Defined 'names' are:
- "setpwent" : low-level emulation of setpwent libc function
- "setgrent" : low-level emulation of setgrent libc function
- "endpwent" : low-level emulation of endpwent libc function
- "endgrent" : low-level emulation of endgrent libc function
- "getpwent" : low-level emulation of getpwent libc function
- "getgrent" : low-level emulation of getgrent libc function
- "getpwnam" : low-level emulation of getpwnam libc function
- "getgrnam" : low-level emulation of getgrnam libc function
- "getpwuid" : low-level emulation of getpwuid libc function
- "getgrgid" : low-level emulation of getgrgid libc function
- "auth" : authenticate user
- (cmd->argv[0] = user,
- cmd->argv[1] = cleartext password)
- "check" : compare supplied passwords
- (cmd->argv[0] = hashed password,
- cmd->argv[1] = user,
- cmd->argv[2] = cleartext password)
- "uid_name" : map uid to name
- (cmd->argv[0] = (char*)uid)
- "gid_name" : map gid to group
- (cmd->argv[0] = (char*)gid)
- "name_uid" : map name to uid
- (cmd->argv[0] = name)
- "name_gid" : map group to gid
- (cmd->argv[0] = name)
- The cascaded order of authentication handlers is similar to command
- handlers, but slightly different. Rules:
- 1. If an authentication handler returns DECLINED, handlers in other
- modules are called (in priority load order, just as with command
- handlers). If ALL handlers for a particular function return
- DECLINED, proftpd will assume that the operation failed.
- 2. If an authentication handler returns HANDLED, proftpd assumes
- that the operation completed successfully, and will stop calling
- auth handlers. Most auth handlers MUST return data if they complete
- successfully (note that some void-style handlers do not have this
- requirement; i.e. "setpwent" and friends).
- 3. If an authentication handler returns ERROR, proftpd assumes an
- error has occured and discontinues calling other handlers. Some
- functions ("auth", for example), should use the ERROR_INT macro
- to return a numeric error code (one of the AUTH_* macros in
- include/modules.h) indicating the reason for failure.