1 /* pam_userdb module */
5 * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10
6 * See the end of the file for Copyright Information
9 #include <security/_pam_aconf.h>
16 #include <sys/types.h>
21 #include "pam_userdb.h"
27 # define DB_DBM_HSEARCH 1 /* use the dbm interface */
30 # error "failed to find a libdb or equivalent"
35 * here, we make a definition for the externally accessible function
36 * in this file (this definition is required for static a module
37 * but strongly encouraged generally) it is used to instruct the
38 * modules include file to define the function prototypes.
42 #define PAM_SM_ACCOUNT
44 #include <security/pam_modules.h>
48 static void _pam_log(int err, const char *format, ...)
52 va_start(args, format);
53 openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH);
54 vsyslog(err, format, args);
59 char * database = NULL;
62 static int _pam_parse(int argc, const char **argv)
64 /* step through arguments */
65 for (ctrl = 0; argc-- > 0; ++argv) {
69 if (!strcmp(*argv,"debug"))
70 ctrl |= PAM_DEBUG_ARG;
71 else if (!strcasecmp(*argv, "icase"))
72 ctrl |= PAM_ICASE_ARG;
73 else if (!strcasecmp(*argv, "dump"))
75 else if (!strncasecmp(*argv,"db=", 3)) {
76 database = strdup((*argv) + 3);
78 _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"",
81 _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
90 * Looks up an user name in a database and checks the password
95 * -1 = Password incorrect
98 static int user_lookup(const char *user, const char *pass)
103 /* Open the DB file. */
104 dbm = dbm_open(database, O_RDONLY, 0644);
106 _pam_log(LOG_ERR, "user_lookup: could not open database `%s'",
111 if (ctrl &PAM_DUMP_ARG) {
112 _pam_log(LOG_INFO, "Database dump:");
113 for (key = dbm_firstkey(dbm); key.dptr != NULL;
114 key = dbm_nextkey(dbm)) {
115 data = dbm_fetch(dbm, key);
116 _pam_log(LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'",
117 key.dsize, key.dptr, data.dsize, data.dptr);
120 /* do some more init work */
122 memset(&key, 0, sizeof(key));
123 memset(&data, 0, sizeof(data));
124 key.dptr = x_strdup(user);
125 key.dsize = strlen(user);
129 data = dbm_fetch(dbm, key);
130 memset(key.dptr, 0, key.dsize);
134 if (ctrl & PAM_DEBUG_ARG) {
135 _pam_log(LOG_INFO, "password in database is [%p]`%s', len is %d",
136 data.dptr, (char *) data.dptr, data.dsize);
139 if (data.dptr != NULL) {
142 if (strlen(pass) != data.dsize) {
144 } else if (ctrl & PAM_ICASE_ARG) {
145 compare = strncasecmp(data.dptr, pass, data.dsize);
147 compare = strncmp(data.dptr, pass, data.dsize);
151 return 0; /* match */
153 return -1; /* wrong */
155 if (ctrl & PAM_DEBUG_ARG) {
156 _pam_log(LOG_INFO, "error returned by dbm_fetch: %s",
160 /* probably we should check dbm_error() here */
161 return 1; /* not found */
168 /* --- authentication management functions (only) --- */
171 int pam_sm_authenticate(pam_handle_t *pamh, int flags,
172 int argc, const char **argv)
174 const char *username;
175 const char *password;
176 int retval = PAM_AUTH_ERR;
178 /* parse arguments */
179 ctrl = _pam_parse(argc, argv);
181 /* Get the username */
182 retval = pam_get_user(pamh, &username, NULL);
183 if ((retval != PAM_SUCCESS) || (!username)) {
184 if (ctrl & PAM_DEBUG_ARG)
185 _pam_log(LOG_DEBUG,"can not get the username");
186 return PAM_SERVICE_ERR;
189 /* Converse just to be sure we have the password */
190 retval = conversation(pamh);
191 if (retval != PAM_SUCCESS) {
192 _pam_log(LOG_ERR, "could not obtain password for `%s'",
197 /* Get the password */
198 retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password);
199 if (retval != PAM_SUCCESS) {
200 _pam_log(LOG_ERR, "Could not retrive user's password");
204 if (ctrl & PAM_DEBUG_ARG)
205 _pam_log(LOG_INFO, "Verify user `%s' with password `%s'",
208 /* Now use the username to look up password in the database file */
209 retval = user_lookup(username, password);
212 /* some sort of system error. The log was already printed */
213 return PAM_SERVICE_ERR;
215 /* incorrect password */
216 _pam_log(LOG_WARNING,
217 "user `%s' denied access (incorrect password)",
221 /* the user does not exist in the database */
222 if (ctrl & PAM_DEBUG_ARG)
223 _pam_log(LOG_NOTICE, "user `%s' not found in the database",
225 return PAM_USER_UNKNOWN;
227 /* Otherwise, the authentication looked good */
228 _pam_log(LOG_NOTICE, "user '%s' granted acces", username);
231 /* we don't know anything about this return value */
233 "internal module error (retval = %d, user = `%s'",
235 return PAM_SERVICE_ERR;
238 /* should not be reached */
243 int pam_sm_setcred(pam_handle_t *pamh, int flags,
244 int argc, const char **argv)
250 int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
251 int argc, const char **argv)
259 /* static module data */
261 struct pam_module _pam_userdb_modstruct = {
274 * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1999
275 * All rights reserved
277 * Redistribution and use in source and binary forms, with or without
278 * modification, are permitted provided that the following conditions
280 * 1. Redistributions of source code must retain the above copyright
281 * notice, and the entire permission notice in its entirety,
282 * including the disclaimer of warranties.
283 * 2. Redistributions in binary form must reproduce the above copyright
284 * notice, this list of conditions and the following disclaimer in the
285 * documentation and/or other materials provided with the distribution.
286 * 3. The name of the author may not be used to endorse or promote
287 * products derived from this software without specific prior
288 * written permission.
290 * ALTERNATIVELY, this product may be distributed under the terms of
291 * the GNU Public License, in which case the provisions of the GPL are
292 * required INSTEAD OF the above restrictions. (This clause is
293 * necessary due to a potential bad interaction between the GPL and
294 * the restrictions contained in a BSD-style copyright.)
296 * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
297 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
298 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
299 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
300 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
301 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
302 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
303 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
304 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
305 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
306 * OF THE POSSIBILITY OF SUCH DAMAGE.