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 * Written by Cristian Gafton <gafton@redhat.com> 1996/09/10
7 * See the end of the file for Copyright Information
10 #include <security/_pam_aconf.h>
17 #include <sys/types.h>
22 #include "pam_userdb.h"
28 # define DB_DBM_HSEARCH 1 /* use the dbm interface */
31 # error "failed to find a libdb or equivalent"
36 * here, we make a definition for the externally accessible function
37 * in this file (this definition is required for static a module
38 * but strongly encouraged generally) it is used to instruct the
39 * modules include file to define the function prototypes.
43 #define PAM_SM_ACCOUNT
45 #include <security/pam_modules.h>
49 static void _pam_log(int err, const char *format, ...)
53 va_start(args, format);
54 openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH);
55 vsyslog(err, format, args);
60 char * database = NULL;
63 static int _pam_parse(int argc, const char **argv)
65 /* step through arguments */
66 for (ctrl = 0; argc-- > 0; ++argv) {
70 if (!strcmp(*argv,"debug"))
71 ctrl |= PAM_DEBUG_ARG;
72 else if (!strcasecmp(*argv, "icase"))
73 ctrl |= PAM_ICASE_ARG;
74 else if (!strcasecmp(*argv, "dump"))
76 else if (!strncasecmp(*argv,"db=", 3)) {
77 database = strdup((*argv) + 3);
79 _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"",
82 _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
91 * Looks up an user name in a database and checks the password
96 * -1 = Password incorrect
99 static int user_lookup(const char *user, const char *pass)
104 /* Open the DB file. */
105 dbm = dbm_open(database, O_RDONLY, 0644);
107 _pam_log(LOG_ERR, "user_lookup: could not open database `%s'",
112 if (ctrl &PAM_DUMP_ARG) {
113 _pam_log(LOG_INFO, "Database dump:");
114 for (key = dbm_firstkey(dbm); key.dptr != NULL;
115 key = dbm_nextkey(dbm)) {
116 data = dbm_fetch(dbm, key);
117 _pam_log(LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'",
118 key.dsize, key.dptr, data.dsize, data.dptr);
121 /* do some more init work */
123 memset(&key, 0, sizeof(key));
124 memset(&data, 0, sizeof(data));
125 key.dptr = x_strdup(user);
126 key.dsize = strlen(user);
130 data = dbm_fetch(dbm, key);
131 memset(key.dptr, 0, key.dsize);
135 if (ctrl & PAM_DEBUG_ARG) {
136 _pam_log(LOG_INFO, "password in database is [%p]`%s', len is %d",
137 data.dptr, (char *) data.dptr, data.dsize);
140 if (data.dptr != NULL) {
143 if (ctrl & PAM_ICASE_ARG)
144 compare = strncasecmp(pass, data.dptr, data.dsize);
146 compare = strncmp(pass, data.dptr, data.dsize);
149 return 0; /* match */
151 return -1; /* wrong */
153 if (ctrl & PAM_DEBUG_ARG) {
154 _pam_log(LOG_INFO, "error returned by dbm_fetch: %s",
158 /* probably we should check dbm_error() here */
159 return 1; /* not found */
166 /* --- authentication management functions (only) --- */
169 int pam_sm_authenticate(pam_handle_t *pamh, int flags,
170 int argc, const char **argv)
172 const char *username;
173 const char *password;
174 int retval = PAM_AUTH_ERR;
176 /* parse arguments */
177 ctrl = _pam_parse(argc, argv);
179 /* Get the username */
180 retval = pam_get_user(pamh, &username, NULL);
181 if ((retval != PAM_SUCCESS) || (!username)) {
182 if (ctrl & PAM_DEBUG_ARG)
183 _pam_log(LOG_DEBUG,"can not get the username");
184 return PAM_SERVICE_ERR;
187 /* Converse just to be sure we have the password */
188 retval = conversation(pamh);
189 if (retval != PAM_SUCCESS) {
190 _pam_log(LOG_ERR, "could not obtain password for `%s'",
195 /* Get the password */
196 retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password);
197 if (retval != PAM_SUCCESS) {
198 _pam_log(LOG_ERR, "Could not retrive user's password");
202 if (ctrl & PAM_DEBUG_ARG)
203 _pam_log(LOG_INFO, "Verify user `%s' with password `%s'",
206 /* Now use the username to look up password in the database file */
207 retval = user_lookup(username, password);
210 /* some sort of system error. The log was already printed */
211 return PAM_SERVICE_ERR;
213 /* incorrect password */
214 _pam_log(LOG_WARNING,
215 "user `%s' denied access (incorrect password)",
219 /* the user does not exist in the database */
220 if (ctrl & PAM_DEBUG_ARG)
221 _pam_log(LOG_NOTICE, "user `%s' not found in the database",
223 return PAM_USER_UNKNOWN;
225 /* Otherwise, the authentication looked good */
226 _pam_log(LOG_NOTICE, "user '%s' granted acces", username);
229 /* we don't know anything about this return value */
231 "internal module error (retval = %d, user = `%s'",
233 return PAM_SERVICE_ERR;
236 /* should not be reached */
241 int pam_sm_setcred(pam_handle_t *pamh, int flags,
242 int argc, const char **argv)
248 int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
249 int argc, const char **argv)
257 /* static module data */
259 struct pam_module _pam_userdb_modstruct = {
272 * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1999
273 * All rights reserved
275 * Redistribution and use in source and binary forms, with or without
276 * modification, are permitted provided that the following conditions
278 * 1. Redistributions of source code must retain the above copyright
279 * notice, and the entire permission notice in its entirety,
280 * including the disclaimer of warranties.
281 * 2. Redistributions in binary form must reproduce the above copyright
282 * notice, this list of conditions and the following disclaimer in the
283 * documentation and/or other materials provided with the distribution.
284 * 3. The name of the author may not be used to endorse or promote
285 * products derived from this software without specific prior
286 * written permission.
288 * ALTERNATIVELY, this product may be distributed under the terms of
289 * the GNU Public License, in which case the provisions of the GPL are
290 * required INSTEAD OF the above restrictions. (This clause is
291 * necessary due to a potential bad interaction between the GPL and
292 * the restrictions contained in a BSD-style copyright.)
294 * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
295 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
296 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
297 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
298 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
299 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
300 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
301 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
302 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
303 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
304 * OF THE POSSIBILITY OF SUCH DAMAGE.