pam_duo/pam_extra.c (96 lines of code) (raw):

/* * Adapted from Linux-PAM * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, and the entire permission notice in its entirety, * including the disclaimer of warranties. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * ALTERNATIVELY, this product may be distributed under the terms of * the GNU Public License, in which case the provisions of the GPL are * required INSTEAD OF the above restrictions. (This clause is * necessary due to a potential bad interaction between the GPL and * the restrictions contained in a BSD-style copyright.) * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef HAVE_PAM_VPROMPT #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <syslog.h> #include <unistd.h> #ifdef HAVE_SECURITY_PAM_APPL_H #include <security/pam_appl.h> #endif #ifdef HAVE_SECURITY_PAM_MODULES_H #include <security/pam_modules.h> #endif #include "pam_extra.h" /* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */ #if defined(__LINUX_PAM__) || defined(OPENPAM) # define duopam_const const /* LinuxPAM, OpenPAM */ #else # define duopam_const /* Solaris, HP-UX, AIX */ #endif #define __overwrite(x) \ do { \ register char *__xx__; \ if ((__xx__=(x))) \ while (*__xx__) \ *__xx__++ = '\0'; \ } while (0) #define __drop(X) \ do { \ if (X) { \ free(X); \ X=NULL; \ } \ } while (0) int pam_vprompt(pam_handle_t *pamh, int style, char **response, const char *fmt, va_list args) { struct pam_message msg; struct pam_response *pam_resp = NULL; const struct pam_conv *conv; duopam_const struct pam_message *pmsg; duopam_const void *convp; char *msgbuf; int retval; if (response) { *response = NULL; } retval = pam_get_item(pamh, PAM_CONV, &convp); if (retval != PAM_SUCCESS) { return retval; } conv = convp; if (conv == NULL || conv->conv == NULL) { syslog(LOG_ERR, "no conversation function"); return PAM_SYSTEM_ERR; } if (vasprintf(&msgbuf, fmt, args) < 0) { syslog(LOG_ERR, "vasprintf: %m"); return PAM_BUF_ERR; } msg.msg_style = style; msg.msg = msgbuf; pmsg = &msg; retval = conv->conv(1, &pmsg, &pam_resp, conv->appdata_ptr); if (retval != PAM_SUCCESS && pam_resp != NULL) { syslog(LOG_WARNING, "unexpected response from failed conversation function"); } if (response) { *response = pam_resp == NULL ? NULL : pam_resp->resp; } else if (pam_resp && pam_resp->resp) { __overwrite(pam_resp->resp); __drop(pam_resp->resp); } __overwrite(msgbuf); __drop(pam_resp); free(msgbuf); if (retval != PAM_SUCCESS) { syslog(LOG_ERR, "conversation failed"); } return retval; } int pam_prompt(pam_handle_t *pamh, int style, char **response, const char *fmt, ...) { va_list args; int retval; va_start(args, fmt); retval = pam_vprompt(pamh, style, response, fmt, args); va_end(args); return retval; } #endif /* HAVE_PAM_VPROMPT */