~ubuntu-branches/ubuntu/breezy/pam/breezy

« back to all changes in this revision

Viewing changes to Linux-PAM/modules/pam_unix/pam_unix_auth.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2004-06-28 14:28:08 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20040628142808-adikk7vtfg3pzcjw
Tags: 0.76-22
* Add uploaders
* Document location of repository
* Fix options containing arguments in pam_unix, Closes: #254904

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright Alexander O. Yuriev, 1996.  All rights reserved.
 
3
 * NIS+ support by Thorsten Kukuk <kukuk@weber.uni-paderborn.de>
 
4
 * Copyright Jan R�korajski, 1999.  All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 * 1. Redistributions of source code must retain the above copyright
 
10
 *    notice, and the entire permission notice in its entirety,
 
11
 *    including the disclaimer of warranties.
 
12
 * 2. Redistributions in binary form must reproduce the above copyright
 
13
 *    notice, this list of conditions and the following disclaimer in the
 
14
 *    documentation and/or other materials provided with the distribution.
 
15
 * 3. The name of the author may not be used to endorse or promote
 
16
 *    products derived from this software without specific prior
 
17
 *    written permission.
 
18
 * 
 
19
 * ALTERNATIVELY, this product may be distributed under the terms of
 
20
 * the GNU Public License, in which case the provisions of the GPL are
 
21
 * required INSTEAD OF the above restrictions.  (This clause is
 
22
 * necessary due to a potential bad interaction between the GPL and
 
23
 * the restrictions contained in a BSD-style copyright.)
 
24
 * 
 
25
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
26
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
27
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
28
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 
29
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
30
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
31
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
32
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
33
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
34
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 
35
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 
36
 */
 
37
 
 
38
/* #define DEBUG */
 
39
 
 
40
#include <security/_pam_aconf.h>
 
41
 
 
42
#include <stdio.h>
 
43
#include <stdlib.h>
 
44
#include <stdarg.h>
 
45
#include <string.h>
 
46
#include <unistd.h>
 
47
#include <fcntl.h>
 
48
#include <ctype.h>
 
49
#include <sys/types.h>
 
50
#include <sys/stat.h>
 
51
 
 
52
/* indicate the following groups are defined */
 
53
 
 
54
#define PAM_SM_AUTH
 
55
 
 
56
#define _PAM_EXTERN_FUNCTIONS
 
57
#include <security/_pam_macros.h>
 
58
#include <security/pam_modules.h>
 
59
 
 
60
#ifndef LINUX_PAM
 
61
#include <security/pam_appl.h>
 
62
#endif                          /* LINUX_PAM */
 
63
 
 
64
#include "support.h"
 
65
 
 
66
/*
 
67
 * PAM framework looks for these entry-points to pass control to the
 
68
 * authentication module.
 
69
 */
 
70
 
 
71
/* Fun starts here :)
 
72
 
 
73
 * pam_sm_authenticate() performs UNIX/shadow authentication
 
74
 *
 
75
 *      First, if shadow support is available, attempt to perform
 
76
 *      authentication using shadow passwords. If shadow is not
 
77
 *      available, or user does not have a shadow password, fallback
 
78
 *      onto a normal UNIX authentication
 
79
 */
 
80
 
 
81
#define _UNIX_AUTHTOK  "-UN*X-PASS"
 
82
 
 
83
#define AUTH_RETURN                                             \
 
84
do {                                                            \
 
85
        if (on(UNIX_LIKE_AUTH, ctrl) && ret_data) {             \
 
86
                D(("recording return code for next time [%d]",  \
 
87
                                        retval));               \
 
88
                *ret_data = retval;                             \
 
89
                pam_set_data(pamh, "unix_setcred_return",       \
 
90
                             (void *) ret_data, setcred_free);  \
 
91
        }                                                       \
 
92
        D(("done. [%s]", pam_strerror(pamh, retval)));          \
 
93
        return retval;                                          \
 
94
} while (0)
 
95
 
 
96
 
 
97
static void setcred_free (pam_handle_t * pamh, void *ptr, int err)
 
98
{
 
99
        if (ptr)
 
100
                free (ptr);
 
101
}
 
102
 
 
103
 
 
104
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags
 
105
                                   ,int argc, const char **argv)
 
106
{
 
107
        unsigned int ctrl;
 
108
        int retval, *ret_data = NULL;
 
109
        const char *name, *p;
 
110
 
 
111
        D(("called."));
 
112
 
 
113
        ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
 
114
 
 
115
        /* Get a few bytes so we can pass our return value to
 
116
           pam_sm_setcred(). */
 
117
        if (on(UNIX_LIKE_AUTH, ctrl))
 
118
                ret_data = malloc(sizeof(int));
 
119
 
 
120
        /* get the user'name' */
 
121
 
 
122
        retval = pam_get_user(pamh, &name, NULL);
 
123
        if (retval == PAM_SUCCESS) {
 
124
                /*
 
125
                 * Various libraries at various times have had bugs related to
 
126
                 * '+' or '-' as the first character of a user name. Don't take
 
127
                 * any chances here. Require that the username starts with an
 
128
                 * alphanumeric character.
 
129
                 */
 
130
                if (name == NULL || !isalnum(*name)) {
 
131
                        _log_err(LOG_ERR, pamh, "bad username [%s]", name);
 
132
                        retval = PAM_USER_UNKNOWN;
 
133
                        AUTH_RETURN;
 
134
                }
 
135
                if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
 
136
                        D(("username [%s] obtained", name));
 
137
        } else {
 
138
                D(("trouble reading username"));
 
139
                if (retval == PAM_CONV_AGAIN) {
 
140
                        D(("pam_get_user/conv() function is not ready yet"));
 
141
                        /* it is safe to resume this function so we translate this
 
142
                         * retval to the value that indicates we're happy to resume.
 
143
                         */
 
144
                        retval = PAM_INCOMPLETE;
 
145
                }
 
146
                AUTH_RETURN;
 
147
        }
 
148
 
 
149
        /* if this user does not have a password... */
 
150
 
 
151
        if (_unix_blankpasswd(ctrl, pamh, name)) {
 
152
                D(("user '%s' has blank passwd", name));
 
153
                name = NULL;
 
154
                retval = PAM_SUCCESS;
 
155
                AUTH_RETURN;
 
156
        }
 
157
        /* get this user's authentication token */
 
158
 
 
159
        retval = _unix_read_password(pamh, ctrl, NULL, "Password: ", NULL
 
160
                                     ,_UNIX_AUTHTOK, &p);
 
161
        if (retval != PAM_SUCCESS) {
 
162
                if (retval != PAM_CONV_AGAIN) {
 
163
                        _log_err(LOG_CRIT, pamh, "auth could not identify password for [%s]"
 
164
                                 ,name);
 
165
                } else {
 
166
                        D(("conversation function is not ready yet"));
 
167
                        /*
 
168
                         * it is safe to resume this function so we translate this
 
169
                         * retval to the value that indicates we're happy to resume.
 
170
                         */
 
171
                        retval = PAM_INCOMPLETE;
 
172
                }
 
173
                name = NULL;
 
174
                AUTH_RETURN;
 
175
        }
 
176
        D(("user=%s, password=[%s]", name, p));
 
177
 
 
178
        /* verify the password of this user */
 
179
        retval = _unix_verify_password(pamh, name, p, ctrl);
 
180
        name = p = NULL;
 
181
 
 
182
        AUTH_RETURN;
 
183
}
 
184
 
 
185
 
 
186
/* 
 
187
 * The only thing _pam_set_credentials_unix() does is initialization of
 
188
 * UNIX group IDs.
 
189
 *
 
190
 * Well, everybody but me on linux-pam is convinced that it should not
 
191
 * initialize group IDs, so I am not doing it but don't say that I haven't
 
192
 * warned you. -- AOY
 
193
 */
 
194
 
 
195
PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags
 
196
                              ,int argc, const char **argv)
 
197
{
 
198
        int retval;
 
199
        int *pretval = NULL;
 
200
 
 
201
        D(("called."));
 
202
 
 
203
        retval = PAM_SUCCESS;
 
204
 
 
205
        D(("recovering return code from auth call"));
 
206
        /* We will only find something here if UNIX_LIKE_AUTH is set -- 
 
207
           don't worry about an explicit check of argv. */
 
208
        pam_get_data(pamh, "unix_setcred_return", (const void **) &pretval);
 
209
        if(pretval) {
 
210
                retval = *pretval;
 
211
                pam_set_data(pamh, "unix_setcred_return", NULL, NULL);
 
212
                D(("recovered data indicates that old retval was %d", retval));
 
213
        }
 
214
 
 
215
        return retval;
 
216
}
 
217
 
 
218
#ifdef PAM_STATIC
 
219
struct pam_module _pam_unix_auth_modstruct = {
 
220
    "pam_unix_auth",
 
221
    pam_sm_authenticate,
 
222
    pam_sm_setcred,
 
223
    NULL,
 
224
    NULL,
 
225
    NULL,
 
226
    NULL,
 
227
};
 
228
#endif