2
* Copyright (C) 1998 Caldera, Inc.
3
* Copyright (C) 2003 Oswald Buddenhagen <ossi@kde.org>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* General Public License for more details.
15
* You should have received a copy of the GNU General Public
16
* License along with this program; if not, write to the Free
17
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include "kcheckpass.h"
29
#ifdef HAVE_PAM_PAM_APPL_H
30
#include <pam/pam_appl.h>
32
#include <security/pam_appl.h>
36
char *(*conv) (ConvRequest, const char *);
41
#ifdef PAM_MESSAGE_CONST
42
typedef const struct pam_message pam_message_type;
43
typedef const void *pam_gi_type;
45
typedef struct pam_message pam_message_type;
46
typedef void *pam_gi_type;
50
PAM_conv (int num_msg, pam_message_type **msg,
51
struct pam_response **resp,
55
struct pam_response *repl;
56
struct pam_data *pd = (struct pam_data *)appdata_ptr;
58
if (!(repl = calloc(num_msg, sizeof(struct pam_response))))
61
for (count = 0; count < num_msg; count++)
62
switch (msg[count]->msg_style) {
64
pd->conv(ConvPutInfo, msg[count]->msg);
67
pd->conv(ConvPutError, msg[count]->msg);
70
switch (msg[count]->msg_style) {
71
case PAM_PROMPT_ECHO_ON:
72
repl[count].resp = pd->conv(ConvGetNormal, msg[count]->msg);
74
case PAM_PROMPT_ECHO_OFF:
76
pd->conv(ConvGetHidden, pd->classic ? 0 : msg[count]->msg);
78
#ifdef PAM_BINARY_PROMPT
79
case PAM_BINARY_PROMPT:
80
repl[count].resp = pd->conv(ConvGetBinary, msg[count]->msg);
84
/* Must be an error of some sort... */
87
if (!repl[count].resp) {
91
repl[count].resp_retcode = PAM_SUCCESS;
98
for (; count >= 0; count--)
100
switch (msg[count]->msg_style) {
101
case PAM_PROMPT_ECHO_OFF:
102
dispose(repl[count].resp);
104
#ifdef PAM_BINARY_PROMPT
105
case PAM_BINARY_PROMPT: /* handle differently? */
107
case PAM_PROMPT_ECHO_ON:
108
free(repl[count].resp);
115
static struct pam_data PAM_data;
117
static struct pam_conv PAM_conversation = {
122
#ifdef PAM_FAIL_DELAY
124
fail_delay(int retval ATTR_UNUSED, unsigned usec_delay ATTR_UNUSED,
125
void *appdata_ptr ATTR_UNUSED)
130
AuthReturn Authenticate(const char *caller, const char *method,
131
const char *user, char *(*conv) (ConvRequest, const char *))
135
pam_gi_type pam_item;
136
const char *pam_service;
140
openlog("kcheckpass", LOG_PID, LOG_AUTH);
142
PAM_data.conv = conv;
143
if (strcmp(method, "classic")) {
144
sprintf(pservb, "%.31s-%.31s", caller, method);
145
pam_service = pservb;
147
/* PAM_data.classic = 1; */
148
pam_service = caller;
150
pam_error = pam_start(pam_service, user, &PAM_conversation, &pamh);
151
if (pam_error != PAM_SUCCESS)
156
tty = getenv ("DISPLAY");
158
pam_error = pam_set_item (pamh, PAM_TTY, tty);
159
if (pam_error != PAM_SUCCESS) {
160
pam_end(pamh, pam_error);
164
# ifdef PAM_FAIL_DELAY
165
pam_set_item (pamh, PAM_FAIL_DELAY, (void *)fail_delay);
168
pam_error = pam_authenticate(pamh, 0);
169
if (pam_error != PAM_SUCCESS) {
170
if (PAM_data.abort) {
171
pam_end(pamh, PAM_SUCCESS);
174
pam_end(pamh, pam_error);
176
case PAM_USER_UNKNOWN:
178
case PAM_MAXTRIES: /* should handle this better ... */
179
case PAM_AUTHINFO_UNAVAIL: /* returned for unknown users ... bogus */
186
/* just in case some module is stupid enough to ignore a preset PAM_USER */
187
pam_error = pam_get_item (pamh, PAM_USER, &pam_item);
188
if (pam_error != PAM_SUCCESS) {
189
pam_end(pamh, pam_error);
192
if (strcmp((const char *)pam_item, user)) {
193
pam_end(pamh, PAM_SUCCESS); /* maybe use PAM_AUTH_ERR? */
197
pam_error = pam_setcred(pamh, PAM_REFRESH_CRED);
198
/* ignore errors on refresh credentials. If this did not work we use the old ones. */
200
pam_end(pamh, PAM_SUCCESS);