1 /* pam_userdb module */
4 * $Id: pam_userdb.c,v 1.4 2000/12/04 15:02:16 baggins Exp $
5 * $FreeBSD: src/contrib/libpam/modules/pam_userdb/pam_userdb.c,v 1.1.1.1.2.2 2001/06/11 15:28:33 markm Exp $
6 * $DragonFly: src/contrib/libpam/modules/pam_userdb/Attic/pam_userdb.c,v 1.2 2003/06/17 04:24:03 dillon Exp $
7 * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10
8 * See the end of the file for Copyright Information
11 #include <security/_pam_aconf.h>
18 #include <sys/types.h>
23 #include "pam_userdb.h"
29 # define DB_DBM_HSEARCH 1 /* use the dbm interface */
32 # error "failed to find a libdb or equivalent"
37 * here, we make a definition for the externally accessible function
38 * in this file (this definition is required for static a module
39 * but strongly encouraged generally) it is used to instruct the
40 * modules include file to define the function prototypes.
44 #define PAM_SM_ACCOUNT
46 #include <security/pam_modules.h>
50 static void _pam_log(int err, const char *format, ...)
54 va_start(args, format);
55 openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH);
56 vsyslog(err, format, args);
61 char * database = NULL;
64 static int _pam_parse(int argc, const char **argv)
66 /* step through arguments */
67 for (ctrl = 0; argc-- > 0; ++argv) {
71 if (!strcmp(*argv,"debug"))
72 ctrl |= PAM_DEBUG_ARG;
73 else if (!strcasecmp(*argv, "icase"))
74 ctrl |= PAM_ICASE_ARG;
75 else if (!strcasecmp(*argv, "dump"))
77 else if (!strncasecmp(*argv,"db=", 3)) {
78 database = strdup((*argv) + 3);
80 _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"",
83 _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
92 * Looks up an user name in a database and checks the password
97 * -1 = Password incorrect
100 static int user_lookup(const char *user, const char *pass)
105 /* Open the DB file. */
106 dbm = dbm_open(database, O_RDONLY, 0644);
108 _pam_log(LOG_ERR, "user_lookup: could not open database `%s'",
113 if (ctrl &PAM_DUMP_ARG) {
114 _pam_log(LOG_INFO, "Database dump:");
115 for (key = dbm_firstkey(dbm); key.dptr != NULL;
116 key = dbm_nextkey(dbm)) {
117 data = dbm_fetch(dbm, key);
118 _pam_log(LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'",
119 key.dsize, key.dptr, data.dsize, data.dptr);
122 /* do some more init work */
124 memset(&key, 0, sizeof(key));
125 memset(&data, 0, sizeof(data));
126 key.dptr = x_strdup(user);
127 key.dsize = strlen(user);
131 data = dbm_fetch(dbm, key);
132 memset(key.dptr, 0, key.dsize);
136 if (ctrl & PAM_DEBUG_ARG) {
137 _pam_log(LOG_INFO, "password in database is [%p]`%s', len is %d",
138 data.dptr, (char *) data.dptr, data.dsize);
141 if (data.dptr != NULL) {
144 if (ctrl & PAM_ICASE_ARG)
145 compare = strncasecmp(pass, data.dptr, data.dsize);
147 compare = strncmp(pass, data.dptr, data.dsize);
150 return 0; /* match */
152 return -1; /* wrong */
154 if (ctrl & PAM_DEBUG_ARG) {
155 _pam_log(LOG_INFO, "error returned by dbm_fetch: %s",
159 /* probably we should check dbm_error() here */
160 return 1; /* not found */
167 /* --- authentication management functions (only) --- */
170 int pam_sm_authenticate(pam_handle_t *pamh, int flags,
171 int argc, const char **argv)
173 const char *username;
174 const char *password;
175 int retval = PAM_AUTH_ERR;
177 /* parse arguments */
178 ctrl = _pam_parse(argc, argv);
180 /* Get the username */
181 retval = pam_get_user(pamh, &username, NULL);
182 if ((retval != PAM_SUCCESS) || (!username)) {
183 if (ctrl & PAM_DEBUG_ARG)
184 _pam_log(LOG_DEBUG,"can not get the username");
185 return PAM_SERVICE_ERR;
188 /* Converse just to be sure we have the password */
189 retval = conversation(pamh);
190 if (retval != PAM_SUCCESS) {
191 _pam_log(LOG_ERR, "could not obtain password for `%s'",
196 /* Get the password */
197 retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password);
198 if (retval != PAM_SUCCESS) {
199 _pam_log(LOG_ERR, "Could not retrive user's password");
203 if (ctrl & PAM_DEBUG_ARG)
204 _pam_log(LOG_INFO, "Verify user `%s' with password `%s'",
207 /* Now use the username to look up password in the database file */
208 retval = user_lookup(username, password);
211 /* some sort of system error. The log was already printed */
212 return PAM_SERVICE_ERR;
214 /* incorrect password */
215 _pam_log(LOG_WARNING,
216 "user `%s' denied access (incorrect password)",
220 /* the user does not exist in the database */
221 if (ctrl & PAM_DEBUG_ARG)
222 _pam_log(LOG_NOTICE, "user `%s' not found in the database",
224 return PAM_USER_UNKNOWN;
226 /* Otherwise, the authentication looked good */
227 _pam_log(LOG_NOTICE, "user '%s' granted acces", username);
230 /* we don't know anything about this return value */
232 "internal module error (retval = %d, user = `%s'",
234 return PAM_SERVICE_ERR;
237 /* should not be reached */
242 int pam_sm_setcred(pam_handle_t *pamh, int flags,
243 int argc, const char **argv)
249 int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
250 int argc, const char **argv)
258 /* static module data */
260 struct pam_module _pam_userdb_modstruct = {
273 * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1999
274 * All rights reserved
276 * Redistribution and use in source and binary forms, with or without
277 * modification, are permitted provided that the following conditions
279 * 1. Redistributions of source code must retain the above copyright
280 * notice, and the entire permission notice in its entirety,
281 * including the disclaimer of warranties.
282 * 2. Redistributions in binary form must reproduce the above copyright
283 * notice, this list of conditions and the following disclaimer in the
284 * documentation and/or other materials provided with the distribution.
285 * 3. The name of the author may not be used to endorse or promote
286 * products derived from this software without specific prior
287 * written permission.
289 * ALTERNATIVELY, this product may be distributed under the terms of
290 * the GNU Public License, in which case the provisions of the GPL are
291 * required INSTEAD OF the above restrictions. (This clause is
292 * necessary due to a potential bad interaction between the GPL and
293 * the restrictions contained in a BSD-style copyright.)
295 * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
296 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
297 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
298 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
299 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
300 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
301 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
302 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
303 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
304 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
305 * OF THE POSSIBILITY OF SUCH DAMAGE.