oreilly.comSafari Books Online.Conferences.


Writing PAM Modules, Part Two
Pages: 1, 2, 3

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() function.

Use 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 PAM_CONV_AGAIN.

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.

The 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 PAM_NO_MODULE_DATA.

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_value argument is a NUL terminated (C style) string. Valid formats are:
Sets 'name' to 'value'
Sets 'name' to the empty string
Deletes 'name'

Memory Security

Any memory that your module does not personally free must be allocated with the std::malloc() family of functions from the Standard C library. new and delete can be used, but only for memory you will be releasing yourself.

Final Words

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.

Further Reading

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.

Linux Online Certification

Linux/Unix System Administration Certificate Series
Linux/Unix System Administration Certificate Series — This course series targets both beginning and intermediate Linux/Unix users who want to acquire advanced system administration skills, and to back those skills up with a Certificate from the University of Illinois Office of Continuing Education.

Enroll today!

Linux Resources
  • Linux Online
  • The Linux FAQ
  • Linux Kernel Archives
  • Kernel Traffic

  • Sponsored by: