/ [pam-modules] / trunk / pam_sql / pam_sql.c
To checkout: svn checkout http://svn.gnu.org.ua/sources/pam-modules/trunk/pam_sql/pam_sql.c
Puszcza

Contents of /trunk/pam_sql/pam_sql.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 61 - (show annotations)
Mon Aug 27 22:38:35 2007 UTC (14 years, 5 months ago) by gray
File MIME type: text/plain
File size: 9403 byte(s)
Lots of fixes in pam_mysql
1 /* This file is part of pam-modules.
2 Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17 #if defined(HAVE_CONFIG_H)
18 # include <config.h>
19 #endif
20 #ifdef HAVE__PAM_ACONF_H
21 # include <security/_pam_aconf.h>
22 #endif
23 #include <security/pam_modules.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <ctype.h>
30 #include <syslog.h>
31 #include <errno.h>
32 #if defined(HAVE_CRYPT_H)
33 # include <crypt.h>
34 #endif
35
36 /* indicate the following groups are defined */
37 #define PAM_SM_AUTH
38
39 #include <common.c>
40
41 #define CHKVAR(v) \
42 if (!(v)) { \
43 _pam_log(LOG_ERR, "%s: %s not defined", config_file, #v); \
44 return PAM_SERVICE_ERR; \
45 } \
46 DEBUG(100,("Config: %s=%s", #v, v));
47
48 static int verify_user_pass(const char *username, const char *password);
49
50 #define CNTL_DEBUG 0x0001
51 #define CNTL_AUDIT 0x0002
52 #define CNTL_AUTHTOK 0x0004
53
54 #define CNTL_SET_DEBUG_LEV(cntl,n) (cntl |= ((n)<<16))
55 #define CNTL_DEBUG_LEV() (cntl_flags>>16)
56
57 #define DEBUG(m,c) if (CNTL_DEBUG_LEV()>=(m)) _pam_debug c
58 #define AUDIT(c) if (cntl_flags&CNTL_AUDIT) _pam_debug c
59
60 static int cntl_flags;
61 char *config_file = SYSCONFDIR "/pam_sql.conf";
62
63 static void
64 _pam_parse(int argc, const char **argv)
65 {
66 int ctrl=0;
67
68 /* step through arguments */
69 for (ctrl=0; argc-- > 0; ++argv) {
70
71 /* generic options */
72
73 if (!strncmp(*argv,"debug",5)) {
74 ctrl |= CNTL_DEBUG;
75 if ((*argv)[5] == '=')
76 CNTL_SET_DEBUG_LEV(ctrl,atoi(*argv+6));
77 else
78 CNTL_SET_DEBUG_LEV(ctrl,1);
79 } else if (!strcmp(*argv, "audit"))
80 ctrl |= CNTL_AUDIT;
81 else if (!strncmp(*argv, "waitdebug", 9))
82 WAITDEBUG(*argv + 9);
83 else if (!strcmp(*argv,"use_authtok"))
84 ctrl |= CNTL_AUTHTOK;
85 else if (!strncmp(*argv, "config=", 7))
86 config_file = (char*) (*argv + 7);
87 else {
88 _pam_log(LOG_ERR,"unknown option: %s",
89 *argv);
90 }
91 }
92 cntl_flags = ctrl;
93 }
94
95
96 /* FIXME: Duplicated in pam_fshadow */
97 static int
98 converse(pam_handle_t *pamh,
99 int nargs,
100 struct pam_message **message,
101 struct pam_response **response)
102 {
103 int retval;
104 struct pam_conv *conv;
105
106 DEBUG(100,("enter converse"));
107
108 retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
109 DEBUG(10,("pam_get_item(PAM_CONV): %d", retval));
110 if (retval == PAM_SUCCESS) {
111
112 retval = conv->conv(nargs,
113 (const struct pam_message **) message,
114 response,
115 conv->appdata_ptr);
116
117 DEBUG(10, ("app conversation returned %d", retval));
118
119 if (retval != PAM_SUCCESS) {
120 _pam_log(LOG_ERR,
121 "conversation failure [%s]",
122 pam_strerror(pamh, retval));
123 }
124 } else if (retval != PAM_CONV_AGAIN) {
125 _pam_log(LOG_ERR,
126 "couldn't obtain coversation function: %s",
127 pam_strerror(pamh, retval));
128 }
129
130 DEBUG(100,("exit converse: %d", retval));
131
132 return retval; /* propagate error status */
133 }
134
135 static int
136 _pam_get_password(pam_handle_t *pamh, char **password, const char *prompt)
137 {
138 char *item, *token;
139 int retval;
140 struct pam_message msg[3], *pmsg[3];
141 struct pam_response *resp;
142 int i, replies;
143
144 DEBUG(100,("enter _pam_get_password"));
145
146 if (cntl_flags & CNTL_AUTHTOK) {
147 /*
148 * get the password from the PAM item
149 */
150 retval = pam_get_item(pamh, PAM_AUTHTOK,
151 (const void **) &item);
152 if (retval != PAM_SUCCESS) {
153 /* very strange. */
154 _pam_log(LOG_ALERT,
155 "can't retrieve password item: %s",
156 pam_strerror(pamh, retval));
157 return retval;
158 } else if (item != NULL) {
159 *password = item;
160 item = NULL;
161 return PAM_SUCCESS;
162 } else
163 return PAM_AUTHTOK_RECOVER_ERR;
164 }
165
166 /*
167 * ask user for the password
168 */
169 /* prepare to converse */
170
171 i = 0;
172 pmsg[i] = &msg[i];
173 msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
174 msg[i++].msg = (const void*)prompt;
175 replies = 1;
176
177 /* run conversation */
178 resp = NULL;
179 token = NULL;
180 retval = converse(pamh, i, pmsg, &resp);
181
182 if (resp != NULL) {
183 if (retval == PAM_SUCCESS) { /* a good conversation */
184 token = XSTRDUP(resp[i - replies].resp);
185 DEBUG(10,("app returned [%s]", token));
186 PAM_DROP_REPLY(resp, 1);
187 } else {
188 _pam_log(LOG_ERR, "conversation error: %s",
189 pam_strerror(pamh, retval));
190 }
191
192 } else {
193 retval = (retval == PAM_SUCCESS)
194 ? PAM_AUTHTOK_RECOVER_ERR : retval;
195 }
196
197 if (retval == PAM_SUCCESS) {
198 /*
199 * keep password as data specific to this module. pam_end()
200 * will arrange to clean it up.
201 */
202 retval = pam_set_data(pamh, "password",
203 (void *)token,
204 _cleanup_string);
205 if (retval != PAM_SUCCESS) {
206 _pam_log(LOG_CRIT,
207 "can't keep password: %s",
208 pam_strerror(pamh, retval));
209 _pam_delete(token);
210 } else {
211 *password = token;
212 token = NULL; /* break link to password */
213 }
214 } else {
215 _pam_log(LOG_ERR,
216 "unable to obtain a password: %s",
217 pam_strerror(pamh, retval));
218 }
219
220 DEBUG(100,("exit _pam_get_password: %d", retval));
221 return retval;
222 }
223
224
225 /* Configuration */
226 typedef struct config_env env_t;
227 struct config_env {
228 env_t *next;
229 char *name;
230 char *value;
231 };
232 static env_t *config_env;
233
234 /*
235 * Chop off trailing whitespace. Return length of the resulting string
236 */
237 static int
238 chop(char *str)
239 {
240 int len;
241
242 for (len = strlen(str); len > 0 && isspace(str[len-1]); len--)
243 ;
244 str[len] = 0;
245 return len;
246 }
247
248 char *
249 find_config(const char *name)
250 {
251 env_t *env;
252
253 for (env = config_env; env; env = env->next)
254 if (strcmp(env->name, name) == 0)
255 return env->value;
256 return NULL;
257 }
258
259 void
260 free_config()
261 {
262 env_t *env = config_env;
263 while (env) {
264 env_t *next = env->next;
265 free(env->name);
266 free(env);
267 env = next;
268 }
269 }
270
271 static int
272 boolean_true_p(const char *value)
273 {
274 return strcmp(value, "yes") == 0
275 || strcmp(value, "true") == 0
276 || strcmp(value, "t") == 0;
277 }
278
279 static int
280 check_boolean_config(const char *name, int defval)
281 {
282 const char *value = find_config(name);
283 if (value)
284 defval = boolean_true_p(value);
285 return defval;
286 }
287
288 static int
289 read_config ()
290 {
291 FILE *fp;
292 char *p;
293 int rc = 0;
294 int line = 0;
295 char buf[128];
296
297 fp = fopen (config_file, "r");
298 if (!fp) {
299 _pam_log(LOG_ERR, "cannot open configuration file `%s': %s",
300 config_file, strerror (errno));
301 return 1;
302 }
303
304 while (p = fgets (buf, sizeof buf, fp)) {
305 int len;
306 env_t *env;
307
308 line++;
309 while (*p && isspace(*p))
310 p++;
311 len = strlen(p);
312 if (len == 0)
313 continue;
314 if (p[len-1] != '\n') {
315 _pam_log(LOG_EMERG, "%s:%d: string too long",
316 config_file, line);
317 continue;
318 }
319
320 p[len-1] = 0;
321 chop(p);
322
323 if (*p == 0 || *p == '#')
324 continue;
325
326 env = malloc(sizeof *env);
327 if (!env) {
328 _pam_log(LOG_EMERG, "not enough memory");
329 rc = 1;
330 break;
331 }
332
333 env->name = strdup(p);
334 if (!env->name) {
335 _pam_log(LOG_EMERG, "not enough memory");
336 free(env);
337 rc = 1;
338 break;
339 }
340
341 for (p = env->name; *p && !isspace(*p); p++)
342 ;
343 if (*p)
344 *p++ = 0;
345 for (; *p && isspace(*p); p++)
346 ;
347 if (!*p) {
348 _pam_log(LOG_EMERG, "%s:%d: not enough fields",
349 config_file, line);
350 free(env->name);
351 free(env);
352 continue;
353 }
354 env->value = p;
355 env->next = config_env;
356 config_env = env;
357 }
358
359 fclose(fp);
360 return rc;
361 }
362
363
364
365
366 /* --- authentication management functions (only) --- */
367
368 PAM_EXTERN int
369 pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
370 {
371 const char *username;
372 char *password;
373 int retval = PAM_AUTH_ERR;
374
375 /* parse arguments */
376 _pam_parse(argc, argv);
377
378 /* Get the username */
379 retval = pam_get_user(pamh, &username, NULL);
380 if (retval != PAM_SUCCESS || !username) {
381 _pam_log(LOG_DEBUG, "can not get the username");
382 return PAM_SERVICE_ERR;
383 }
384
385 /* Get the password */
386 if (_pam_get_password(pamh, &password, "Password:"))
387 return PAM_SERVICE_ERR;
388
389 if (retval != PAM_SUCCESS) {
390 _pam_log(LOG_ERR, "Could not retrive user's password");
391 return PAM_SERVICE_ERR;
392 }
393
394 if (read_config())
395 retval = PAM_SERVICE_ERR;
396 else
397 retval = verify_user_pass(username, password);
398 free_config();
399
400 switch (retval) {
401 case PAM_ACCT_EXPIRED:
402 _pam_log(LOG_NOTICE, "user '%s': account expired", username);
403 break;
404 case PAM_SUCCESS:
405 _pam_log(LOG_NOTICE, "user '%s' granted access", username);
406 break;
407 default:
408 _pam_log(LOG_NOTICE, "user '%s' failed to authenticate",
409 username);
410 }
411
412 return retval;
413 }
414
415 PAM_EXTERN
416 int pam_sm_setcred(pam_handle_t *pamh, int flags,
417 int argc, const char **argv)
418 {
419 return PAM_SUCCESS;
420 }
421
422 PAM_EXTERN
423 int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
424 int argc, const char **argv)
425 {
426 return PAM_SUCCESS;
427 }
428
429 #ifdef PAM_STATIC
430
431 /* static module data */
432
433 struct pam_module _pam_fshadow_modstruct = {
434 MODULE_NAME,
435 pam_sm_authenticate,
436 NULL,
437 NULL,
438 NULL,
439 NULL,
440 NULL,
441 };
442
443 #endif

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

Send suggestions and bug reports to Sergey Poznyakoff
ViewVC Help
Powered by ViewVC 1.1.20