Appendix B. The PDM C API

Note: I am not perfectly happy with this interface, so there might be some changes in the future.

PDM modules are shared libraries. Each module must supply the following functions: pdm_init, pdm_close, pdm_args, and pdm_reload. In addition it must supply at least one of the functions pdm_check or pdm_auth.

The functions must be defined as follows:

char *pdm_init(int argc, char *argv[], struct pdm_mvar *mvar, void **pdmctx);

The pdm_init is called once when the module is loaded. All arguments are supplied in argv, the number of arguments is in argc. The first argument is always the ID (symbolical name) of this module, the second argument is the name of the module (without the prefix "libpdm_" and suffix ".so"). The meaning of the other arguments can be defined by each module according to its needs, for instance it could be used for filenames, the host name of a database and so on.

The parameter pdmctx is a pointer to a void pointer. The module can store a pointer to arbitrary data in this void pointer. This data will not be used by POPular itself, but will be returned to the module with all other function calls.

The function must return NULL if the module was successfully initialized or an error string otherwise.

int pdm_close(void *pdmctx);

If the module isn't needed anymore, POPular will call the close function. It's only parameter is the PDM context set by the init function. The module should close all files, close networks sockets, deallocate memory, and generally do all necessary cleanup. After this function returns POPular will unload the shared library.

char *pdm_args(void *pdmctx);

If POPular needs to know with what arguments a module was initialized, it calls this function. The function must return a string which is the same or equivalent to the string with which the module was originally configured. Normally this is the concatenation of the arguments separated by spaces.

int pdm_reload(void *pdmctx);

This call instructs the module to reinitialize itself. If it has any files or network connections open, it should close and reopen them, etc.

pdm_result_t pdm_check(void *pdmctx, const struct pdm_request *pdmr, struct pdm_data *pdmd);

This function is used to ask the database for a specific user. The PDM context is supplied as well as all available information about the user in the pdmr. The pdm_check must return the result of the lookup and return additional information through the pdmd. See below for a description of the pdm_request and pdm_data structures.

pdm_result_t pdm_auth(void *pdmctx, const struct pdm_request *pdmr, struct pdm_data *pdmd);

This function is used to check a password through the database module. If the user and all the data associated with the user was already established by another module through the pdm_check call, but the user was not authenticated, then this module will be called.

For communication between POPular and the PDM modules two C structs are used:

struct pdm_request {
  char *peer;
  protocol_t prot;
  char *user;
  char *pass;
  char *namespace;
};
    

This struct is used to tell the pdm_check and pdm_auth functions about a user who is to be authenticated. It contains the IP address of the client in dotted quad notation in peer, the protocol the client is using in prot (which can be used to find out whether the session is encrypted), and the username, password and namespace in user, pass, and namespace, respectively. Usually only the last three fields will be used for authenticating a user, but if the module wishes to do so, it can use all fields.

struct pdm_data {
  int flags;
  pdm_fail_reason_t reason;
  char backend[MAXLEN_ID];
  char user[MAXLEN_USERNAME];
  char pass[MAXLEN_PASSWORD];
};
    

The pdm_data struct is used by the pdm_check to return details about this user that have been found in the database. The backend field contains the ID of the backend server this users mailbox is on. If this is a normal POP3 server the fields user and pass contain the username and password, respectively, that are to be used to authenticate to that server. If the POPular server is used, the user field contains the directory name of the mailbox. If the lookup failed, detailed information about the reason should be put into reason. This information will be logged, but is not available to the user. The flags, finally, can be used to set special flags. Currently this is only used for marking a user as authenticated with a master password instead of his normal password. See the description of the POPular server for the meaning of this flag.