1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
static const char rcsid[] = "$Id: pam.c,v 1.6 2004/04/30 17:00:58 will Exp $";
/* The code should compile with either ANSI C or K&R compilers. */
/*
* Copyright (c) 1993 by California Institute of Technology.
* Written by William Deich. Not derived from licensed software.
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*/
#include "super.h"
#include "version.h"
#ifndef HAVE_PAM_START
int
get_pam(cmd, caller, user)
char *cmd;
char *caller; /* the person who invoked super */
char *user; /* the person whose authentication is required */
{
Error(0, 1,
"Error in super.tab file -- this copy of super was compiled on a host without support for authtype=pam\n");
}
#else
#ifndef HAVE_PAM_STRERROR
/* pam_strerror converts a PAM status code to a string, and a returns
* a ptr to a static string. This is the Linux pam_strerror() code,
* except that I've #ifdef'd everything so that it compiles on systems
* that don't have all of the PAM_xxx values. (Note that this only
* works if #define is used; an enum would break this.)
*/
char *
pam_strerror(pam_handle_t *pamh, int status)
{
switch (errnum) {
#ifdef PAM_SUCCESS
case PAM_SUCCESS:
return "Success";
#endif
#ifdef PAM_ABORT
case PAM_ABORT: return "Critical error - immediate abort";
#endif
#ifdef PAM_OPEN_ERR
case PAM_OPEN_ERR: return "dlopen() failure";
#endif
#ifdef PAM_SYMBOL_ERR
case PAM_SYMBOL_ERR: return "Symbol not found";
#endif
#ifdef PAM_SERVICE_ERR
case PAM_SERVICE_ERR: return "Error in service module";
#endif
#ifdef PAM_SYSTEM_ERR
case PAM_SYSTEM_ERR: return "System error";
#endif
#ifdef PAM_BUF_ERR
case PAM_BUF_ERR: return "Memory buffer error";
#endif
#ifdef PAM_PERM_DENIED
case PAM_PERM_DENIED: return "Permission denied";
#endif
#ifdef PAM_AUTH_ERR
case PAM_AUTH_ERR: return "Authentication failure";
#endif
#ifdef PAM_CRED_INSUFFICIENT
case PAM_CRED_INSUFFICIENT:
return "Insufficient credentials to access authentication data";
#endif
#ifdef PAM_AUTHINFO_UNAVAIL
case PAM_AUTHINFO_UNAVAIL:
return "Authentication service cannot retrieve authentication info.";
#endif
#ifdef PAM_USER_UNKNOWN
case PAM_USER_UNKNOWN:
return "User not known to the underlying authentication module";
#endif
#ifdef PAM_MAXTRIES
case PAM_MAXTRIES:
return "Have exhasted maximum number of retries for service.";
#endif
#ifdef PAM_NEW_AUTHTOK_REQD
case PAM_NEW_AUTHTOK_REQD:
return "Authentication token is no longer valid; new one required.";
#endif
#ifdef PAM_ACCT_EXPIRED
case PAM_ACCT_EXPIRED: return "User account has expired";
#endif
#ifdef PAM_SESSION_ERR
case PAM_SESSION_ERR:
return "Cannot make/remove an entry for the specified session";
#endif
#ifdef PAM_CRED_UNAVAIL
case PAM_CRED_UNAVAIL:
return "Authentication service cannot retrieve user credentials";
#endif
#ifdef PAM_CRED_EXPIRED
case PAM_CRED_EXPIRED: return "User credentials expired";
#endif
#ifdef PAM_CRED_ERR
case PAM_CRED_ERR: return "Failure setting user credentials";
#endif
#ifdef PAM_NO_MODULE_DATA
case PAM_NO_MODULE_DATA: return "No module specific data is present";
#endif
#ifdef PAM_BAD_ITEM
case PAM_BAD_ITEM: return "Bad item passed to pam_*_item()";
#endif
#ifdef PAM_CONV_ERR
case PAM_CONV_ERR: return "Conversation error";
#endif
#ifdef PAM_AUTHTOK_ERR
case PAM_AUTHTOK_ERR: return "Authentication token manipulation error";
#endif
#ifdef PAM_AUTHTOK_LOCK_BUSY
case PAM_AUTHTOK_LOCK_BUSY: return "Authentication token lock busy";
#endif
#ifdef PAM_AUTHTOK_DISABLE_AGING
case PAM_AUTHTOK_DISABLE_AGING:
return "Authentication token aging disabled";
#endif
#ifdef PAM_TRY_AGAIN
case PAM_TRY_AGAIN: return "Failed preliminary check by password service";
#endif
#ifdef PAM_IGNORE
case PAM_IGNORE: return "Please ignore underlying account module";
#endif
#ifdef PAM_MODULE_UNKNOWN
case PAM_MODULE_UNKNOWN: return "Module is unknown";
#endif
#ifdef PAM_AUTHTOK_EXPIRED
case PAM_AUTHTOK_EXPIRED: return "Authentication token expired";
#endif
#ifdef PAM_CONV_AGAIN
case PAM_CONV_AGAIN: return "Conversation is waiting for event";
#endif
#ifdef PAM_INCOMPLETE
case PAM_INCOMPLETE: return "Application needs to call libpam again";
#endif
}
return "Unknown PAM error (need to upgrade libpam?)";
}
#endif /* !HAVE_PAM_STRERROR */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Get authentication via PAM */
/* Return 1 on success, -1 on error. */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int
get_pam(cmd, caller, user)
char *cmd;
char *caller; /* the person who invoked super */
char *user; /* the person whose authentication is required */
{
int misc_conv(int num_msg, const struct pam_message **msgm,
struct pam_response **response, void *appdata_ptr);
static struct pam_conv conv = {
misc_conv,
NULL
};
pam_handle_t *pamh = NULL;
int ntry, pamstatus;
char msg[500];
FILE *prompt_fp = NULL;
char *prompt_dev="/dev/tty";
if (pam_start(ONETRUENAME, user, &conv, &pamh) != PAM_SUCCESS) {
return Error(0, 0, "Internal error: can't start PAM authentication!\n");
}
if (!(prompt_fp = fopen(prompt_dev, "r+"))) {
return Error(0, 0,
"Can't open %s for authentication message!\n", prompt_dev);
}
/* Note that the actual number of tries is the lesser of our MAXTRY
* and the PAM module's maximum...
*/
for (ntry=0, pamstatus = PAM_AUTH_ERR;
ntry < MAXTRY && pamstatus == PAM_AUTH_ERR; ntry++) {
if (ntry == 0) {
if (localinfo.authinfo.prompt && localinfo.authinfo.prompt[0]) {
stringcopy(msg,
do_variables(localinfo.authinfo.prompt), sizeof(msg));
} else if (strcmp(caller, user) == 0) {
(void) sprintf(msg,
"Authentication is required for super command `%.400s'...",
cmd);
} else {
(void) sprintf(msg,
"Authentication for user %s is required for super command `%.400s'...",
user, cmd);
}
fprintf(prompt_fp, "%s\n", msg);
} else {
fprintf(prompt_fp, "Authentication failed; try again...\n");
}
pamstatus = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK);
}
fclose(prompt_fp);
if (pamstatus != PAM_SUCCESS) {
pam_end(pamh, pamstatus);
return Error(0, 0, "Authentication failed: %s\n",
pam_strerror(pamh, pamstatus));
}
if ((pamstatus=pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) {
pam_end(pamh, pamstatus);
return Error(0, 0, "Authentication succeeded, \
but PAM doesn't grant access:\n\t%s\n", pam_strerror(pamh, pamstatus));
}
if (pam_end(pamh, pamstatus) != PAM_SUCCESS) {
return Error(0, 0, "Internal error: failed to release authenticator\n");
}
return 1;
}
#endif /* HAVE_PAM_START */
|