source: openpam/trunk/lib/openpam_dispatch.c @ 16

Last change on this file since 16 was 16, checked in by Dag-Erling Smørgrav, 19 years ago

Whitespace cleanup + keyword expansion sweep.

Sponsored by: DARPA, NAI Labs

  • Property svn:keywords set to Id LastChangedRevision HeadURL LastChangedDate LastChangedBy
File size: 5.1 KB
Line 
1/*-
2 * Copyright (c) 2002 Networks Associates Technologies, Inc.
3 * All rights reserved.
4 *
5 * This software was developed for the FreeBSD Project by ThinkSec AS and
6 * NAI Labs, the Security Research Division of Network Associates, Inc.
7 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
8 * DARPA CHATS research program.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote
19 *    products derived from this software without specific prior written
20 *    permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $Id: openpam_dispatch.c 16 2002-02-01 22:20:07Z des $
35 */
36
37#include <sys/param.h>
38
39#include <security/pam_appl.h>
40
41#include "openpam_impl.h"
42
43#if !defined(OPENPAM_RELAX_CHECKS)
44static void _openpam_check_error_code(int, int);
45#else
46#define _openpam_check_error_code(a, b)
47#endif /* !defined(OPENPAM_RELAX_CHECKS) */
48
49/*
50 * Execute a module chain
51 */
52
53int
54openpam_dispatch(pam_handle_t *pamh,
55        int primitive,
56        int flags)
57{
58        pam_chain_t *module;
59        int err, fail, r;
60
61        if (pamh == NULL)
62                return (PAM_SYSTEM_ERR);
63
64        switch (primitive) {
65        case PAM_AUTHENTICATE:
66        case PAM_SETCRED:
67                module = pamh->chains[PAM_AUTH];
68                break;
69        case PAM_ACCT_MGMT:
70                module = pamh->chains[PAM_ACCOUNT];
71                break;
72        case PAM_OPEN_SESSION:
73        case PAM_CLOSE_SESSION:
74                module = pamh->chains[PAM_SESSION];
75                break;
76        case PAM_CHAUTHTOK:
77                module = pamh->chains[PAM_PASSWORD];
78                break;
79        default:
80                return (PAM_SYSTEM_ERR);
81        }
82
83        for (err = fail = 0; module != NULL; module = module->next) {
84                if (module->primitive[primitive] == NULL) {
85                        openpam_log(PAM_LOG_ERROR, "%s: no %s()",
86                            module->modpath, _pam_sm_func_name[primitive]);
87                        return (PAM_SYMBOL_ERR);
88                }
89                r = (module->primitive[primitive])(pamh, flags);
90                openpam_log(PAM_LOG_DEBUG, "%s: %s(): %s",
91                    module->modpath, _pam_sm_func_name[primitive],
92                    pam_strerror(pamh, r));
93
94                if (r == PAM_IGNORE)
95                        continue;
96                if (r == PAM_SUCCESS) {
97                        /*
98                         * For pam_setcred(), treat "sufficient" as
99                         * "optional".
100                         *
101                         * Note that Solaris libpam does not terminate
102                         * the chain here if a required module has
103                         * previously failed.  I'm not sure why.
104                         */
105                        if (module->flag == PAM_SUFFICIENT &&
106                            primitive != PAM_SETCRED)
107                                break;
108                }
109
110                _openpam_check_error_code(primitive, r);
111
112                /*
113                 * Record the return code from the first module to
114                 * fail.  If a required module fails, record the
115                 * return code from the first required module to fail.
116                 */
117                if (err == 0)
118                        err = r;
119                if (module->flag == PAM_REQUIRED && !fail) {
120                        fail = 1;
121                        err = r;
122                }
123
124                /*
125                 * If a requisite module fails, terminate the chain
126                 * immediately.
127                 */
128                if (module->flag == PAM_REQUISITE) {
129                        fail = 1;
130                        break;
131                }
132        }
133
134        if (fail)
135                return (err);
136        return (PAM_SUCCESS);
137}
138
139#if !defined(OPENPAM_RELAX_CHECKS)
140static void
141_openpam_check_error_code(int primitive, int r)
142{
143        /* common error codes */
144        if (r == PAM_SERVICE_ERR ||
145            r == PAM_BUF_ERR ||
146            r == PAM_BUF_ERR ||
147            r == PAM_CONV_ERR ||
148            r == PAM_PERM_DENIED)
149                return;
150
151        /* specific error codes */
152        switch (primitive) {
153        case PAM_AUTHENTICATE:
154                if (r == PAM_AUTH_ERR ||
155                    r == PAM_CRED_INSUFFICIENT ||
156                    r == PAM_AUTHINFO_UNAVAIL ||
157                    r == PAM_USER_UNKNOWN ||
158                    r == PAM_MAXTRIES)
159                        return;
160                break;
161        case PAM_SETCRED:
162                if (r == PAM_CRED_UNAVAIL ||
163                    r == PAM_CRED_EXPIRED ||
164                    r == PAM_USER_UNKNOWN ||
165                    r == PAM_CRED_ERR)
166                        return;
167                break;
168        case PAM_ACCT_MGMT:
169                if (r == PAM_USER_UNKNOWN ||
170                    r == PAM_AUTH_ERR ||
171                    r == PAM_NEW_AUTHTOK_REQD ||
172                    r == PAM_ACCT_EXPIRED)
173                        return;
174                break;
175        case PAM_OPEN_SESSION:
176        case PAM_CLOSE_SESSION:
177                if (r == PAM_SESSION_ERR)
178                        return;
179                break;
180        case PAM_CHAUTHTOK:
181                if (r == PAM_PERM_DENIED ||
182                    r == PAM_AUTHTOK_ERR ||
183                    r == PAM_AUTHTOK_RECOVERY_ERR ||
184                    r == PAM_AUTHTOK_LOCK_BUSY ||
185                    r == PAM_AUTHTOK_DISABLE_AGING)
186                        return;
187                break;
188        }
189
190        openpam_log(PAM_LOG_ERROR, "%s(): unexpected return value %d",
191            _pam_sm_func_name[primitive], r);
192}
193#endif /* !defined(OPENPAM_RELAX_CHECKS) */
Note: See TracBrowser for help on using the repository browser.