File: pam.c

package info (click to toggle)
super 3.30.0-2+lenny1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 1,072 kB
  • ctags: 755
  • sloc: ansic: 10,089; sh: 288; makefile: 204
file content (222 lines) | stat: -rw-r--r-- 7,164 bytes parent folder | download | duplicates (7)
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 */