ProFTPD Developer's Guide: Module Tips

ProFTPD Version 1.2


Table of Contents

  • style notes: respecting other modules, log_pri() for notices and errors, log_debug() at various levels
  • use command dispatch system, not change core code
  • code submission: documentation, diffs
  • OS dependencies and idiosyncrasies, #defines, autoconf detection
  • Command handlers that handle every command except some...
  • proper log_{pri,auth,debug}() calls -- at least three arguments to prevent format string attacks!
  • preventing mergedown bugs: in general, if directive is allowed in CONF_ANON, CONF_DIR, or CONF_DYNDIR contexts, the CF_MERGEDOWN flag should be set.

    Tips and Tricks
    These are some recommendations and things to keep in mind when programming a module for ProFTPD. Remember that each session is handled by a forked process, and so that child can overwrite/rearrange its configuration tree without affecting the parent. nickh>I was thinking more of a proftpd global _auth_state variable nickh>or something like that. Now that I think more about it, I nickh>guess the only states I care about are pre and post-successful nickh>login. I bet I can get that from the session info somehow. There're some config_recs added/removed during the handling of the USER and PASS commands. I think the one that may interest you is a config_rec that can be retrieved by the name "authenticated". It's used to determine which commands can be used by a client without authentication, and is only set after a successful authentication. Prior to a successful _setup_environment() call, that config_rec isn't present.

    1. Always check function return values for errors.
    2. Always add the proper argument checks to handlers (eg CHECK_ARGS, CHECK_CONF)
    3. Always be aware of the current context when retrieving configuration records.
    4. Keep in mind the lifetime of a pool when allocating memory from it.
    5. respect other modules' configuration records, especially if relevant (e.g. TimesGMT, UserAlias, etc)
    6. use log_debug() for debugging, log_auth() during the authentication/authorization of a connection, and use log_pri() for logging as appropriate
      message: access denied, funny arguments, libc/syscall errors, etc

    7. use the provided string functions of sstrcat(), sstrcpy().

    8. use palloc(), pcalloc(), not ever malloc/free.

    9. sending SIGUSR2 to a running proftpd master daemon will cause it to call debug_walk_pools(), which will cause it to log/print out information about the current memory allocation.

      Example output:
           localhost.localdomain - Memory pool allocation:
           localhost.localdomain - 0x00002600 bytes
           localhost.localdomain - \- 0x00000200 bytes
           localhost.localdomain - \- 0x00000200 bytes
           localhost.localdomain - \- 0x00000200 bytes
           localhost.localdomain -    \- 0x00000200 bytes
           localhost.localdomain -    \- 0x00000400 bytes
           localhost.localdomain - \- 0x00000200 bytes
           localhost.localdomain - \- 0x00000200 bytes
           localhost.localdomain -    \- 0x00000200 bytes
           localhost.localdomain -    \- 0x00000400 bytes
           localhost.localdomain -       \- 0x00000200 bytes
           localhost.localdomain -    \- 0x00000200 bytes
           localhost.localdomain -       \- 0x00000400 bytes
           localhost.localdomain -    \- 0x00000200 bytes
           localhost.localdomain -    \- 0x00000400 bytes
           localhost.localdomain -    \- 0x00000600 bytes
           localhost.localdomain - \- 0x00000200 bytes
           localhost.localdomain - Total 0x00005200 bytes allocated
           localhost.localdomain - Free block list: 0x00000200 bytes
           localhost.localdomain - 37 count blocks malloc'd.
           localhost.localdomain - 109 count blocks reused.
      

    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.

    Table of Contents



    Author: $Author: castaglia $
    Last Updated: $Date: 2003/01/02 17:39:31 $


    © Copyright 2000-2003 TJ Saunders
    All Rights Reserved