Getting the Username
Getting a username can be involved -- first checking whether it's a PAM item, then calling the conversation function, and identifying the appropriate prompt to ask for the username. Fortunately PAM is willing to do the work for you, in the
pam_get_user rather than doing the work yourself. It's easier, cleaner to read, and if the process changes, you don't have to do a thing!
extern int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt);
Do not free the user data memory. A second call to
pam_get_user() or a call to
pam_end() will do that for you.
The meaning of the return value
PAM_SUCCESS is obvious. Other return values are
PAM_CONV_ERR which means no username could be obtained, and
If you receive
PAM_CONV_AGAIN, return control to the application with
PAM_INCOMPLETE, and, when next invoked with that PAM handle, return to the failed
pam_get_user() and pick up where you left off.
Setting and Getting Data
The module author cannot predict how the module will be loaded, so you should avoid static variables. The functions to set and get data provide a way to associate data with a PAM handle. The data items set using this function are available to other modules, but not to the application.
The cleanup parameter is a function you need to provide to do a proper cleanup of the data item. If no special cleanup is required by this item, it may be set to NULL.
error_status parameter may be logically ORed with
PAM_DATA_REPLACE to signal a second call to set the same item, or
PAM_DATA_SILENT to cause the cleanup function to avoid logging or sending messages to the user.
If an entry is present but has the value NULL,
pam_get_data() will return
extern int pam_set_data(pam_handle_t *pamh, const char *module_data_name, void *data, void (*cleanup)(pam_handle_t *pamh, void *data, int error_status) );
extern int pam_get_data(const pam_handle_t *pamh, const char *module_data_name, const void **data);
Managing the Environment
Linux-PAM comes with a separate environment, associated with the current PAM handle. The environment starts out empty.
extern const char *pam_getenv(pam_handle_t *pamh, const char *name);
- Returns the value of the named Linux-PAM environment variable, or NULL if there is a failure.
extern const char * const *pam_getenvlist(pam_handle_t *pamh);
- Returns a pointer to a read-only list of the current Linux-PAM environment.
extern int pam_putenv(pam_handle_t *pamh, const char *name_value);
- Attempts to set, reset, or delete the named environment variable. The
name_valueargument is a NUL terminated (C style) string. Valid formats are:
- Sets 'name' to 'value'
- Sets 'name' to the empty string
- Deletes 'name'
Any memory that your module does not personally free must be allocated with the
std::malloc() family of functions from the Standard C library.
delete can be used, but only for memory you will be releasing yourself.
This is Part Two of a three-part article on writing PAM modules. Part One discusses the underlying theory of PAM, and what behaviors are required of a module. Part Three discusses the functions a module is required to provide, security issues, and response codes.
Jennifer Vesperman is the author of Essential CVS. She writes for the O'Reilly Network, the Linux Documentation Project, and occasionally Linux.Com.
Return to the Linux DevCenter.