Deleted Added
full compact
openpam_configure.c (186063) openpam_configure.c (228690)
1/*-
2 * Copyright (c) 2001-2003 Networks Associates Technology, Inc.
1/*-
2 * Copyright (c) 2001-2003 Networks Associates Technology, Inc.
3 * Copyright (c) 2004-2007 Dag-Erling Sm��rgrav
3 * Copyright (c) 2004-2011 Dag-Erling Sm��rgrav
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by ThinkSec AS and
7 * Network Associates Laboratories, the Security Research Division of
8 * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
9 * ("CBOSS"), as part of the DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without

--- 15 unchanged lines hidden (view full) ---

27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by ThinkSec AS and
7 * Network Associates Laboratories, the Security Research Division of
8 * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
9 * ("CBOSS"), as part of the DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without

--- 15 unchanged lines hidden (view full) ---

27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * $Id: openpam_configure.c 408 2007-12-21 11:36:24Z des $
35 * $Id: openpam_configure.c 500 2011-11-22 12:07:03Z des $
36 */
37
36 */
37
38#ifdef HAVE_CONFIG_H
39# include "config.h"
40#endif
41
38#include <ctype.h>
39#include <errno.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43
44#include <security/pam_appl.h>
45
46#include "openpam_impl.h"
42#include <ctype.h>
43#include <errno.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47
48#include <security/pam_appl.h>
49
50#include "openpam_impl.h"
51#include "openpam_strlcmp.h"
47
52
48const char *_pam_facility_name[PAM_NUM_FACILITIES] = {
49 [PAM_ACCOUNT] = "account",
50 [PAM_AUTH] = "auth",
51 [PAM_PASSWORD] = "password",
52 [PAM_SESSION] = "session",
53};
53static int openpam_load_chain(pam_handle_t *, const char *, pam_facility_t);
54
54
55const char *_pam_control_flag_name[PAM_NUM_CONTROL_FLAGS] = {
56 [PAM_BINDING] = "binding",
57 [PAM_OPTIONAL] = "optional",
58 [PAM_REQUIRED] = "required",
59 [PAM_REQUISITE] = "requisite",
60 [PAM_SUFFICIENT] = "sufficient",
61};
55/*
56 * Evaluates to non-zero if the argument is a linear whitespace character.
57 */
58#define is_lws(ch) \
59 (ch == ' ' || ch == '\t')
62
60
63static int openpam_load_chain(pam_handle_t *, const char *, pam_facility_t);
61/*
62 * Evaluates to non-zero if the argument is a printable ASCII character.
63 * Assumes that the execution character set is a superset of ASCII.
64 */
65#define is_p(ch) \
66 (ch >= '!' && ch <= '~')
64
65/*
67
68/*
66 * Matches a word against the first one in a string.
67 * Returns non-zero if they match.
69 * Returns non-zero if the argument belongs to the POSIX Portable Filename
70 * Character Set. Assumes that the execution character set is a superset
71 * of ASCII.
68 */
72 */
73#define is_pfcs(ch) \
74 ((ch >= '0' && ch <= '9') || \
75 (ch >= 'A' && ch <= 'Z') || \
76 (ch >= 'a' && ch <= 'z') || \
77 ch == '.' || ch == '_' || ch == '-')
78
79/*
80 * Parse the service name.
81 *
82 * Returns the length of the service name, or 0 if the end of the string
83 * was reached or a disallowed non-whitespace character was encountered.
84 *
85 * If parse_service_name() is successful, it updates *service to point to
86 * the first character of the service name and *line to point one
87 * character past the end. If it reaches the end of the string, it
88 * updates *line to point to the terminating NUL character and leaves
89 * *service unmodified. In all other cases, it leaves both *line and
90 * *service unmodified.
91 *
92 * Allowed characters are all characters in the POSIX portable filename
93 * character set.
94 */
69static int
95static int
70match_word(const char *str, const char *word)
96parse_service_name(char **line, char **service)
71{
97{
98 char *b, *e;
72
99
73 while (*str && tolower(*str) == tolower(*word))
74 ++str, ++word;
75 return (*str == ' ' && *word == '\0');
100 for (b = *line; *b && is_lws(*b); ++b)
101 /* nothing */ ;
102 if (!*b) {
103 *line = b;
104 return (0);
105 }
106 for (e = b; *e && !is_lws(*e); ++e)
107 if (!is_pfcs(*e))
108 return (0);
109 if (e == b)
110 return (0);
111 *line = e;
112 *service = b;
113 return (e - b);
76}
77
78/*
114}
115
116/*
79 * Return a pointer to the next word (or the final NUL) in a string.
117 * Parse the facility name.
118 *
119 * Returns the corresponding pam_facility_t value, or -1 if the end of the
120 * string was reached, a disallowed non-whitespace character was
121 * encountered, or the first word was not a recognized facility name.
122 *
123 * If parse_facility_name() is successful, it updates *line to point one
124 * character past the end of the facility name. If it reaches the end of
125 * the string, it updates *line to point to the terminating NUL character.
126 * In all other cases, it leaves *line unmodified.
80 */
127 */
81static const char *
82next_word(const char *str)
128static pam_facility_t
129parse_facility_name(char **line)
83{
130{
131 char *b, *e;
132 int i;
84
133
85 /* skip current word */
86 while (*str && *str != ' ')
87 ++str;
88 /* skip whitespace */
89 while (*str == ' ')
90 ++str;
91 return (str);
134 for (b = *line; *b && is_lws(*b); ++b)
135 /* nothing */ ;
136 if (!*b) {
137 *line = b;
138 return ((pam_facility_t)-1);
139 }
140 for (e = b; *e && !is_lws(*e); ++e)
141 /* nothing */ ;
142 if (e == b)
143 return ((pam_facility_t)-1);
144 for (i = 0; i < PAM_NUM_FACILITIES; ++i)
145 if (strlcmp(pam_facility_name[i], b, e - b) == 0)
146 break;
147 if (i == PAM_NUM_FACILITIES)
148 return ((pam_facility_t)-1);
149 *line = e;
150 return (i);
92}
93
94/*
151}
152
153/*
95 * Return a malloc()ed copy of the first word in a string.
154 * Parse the word "include".
155 *
156 * If the next word on the line is "include", parse_include() updates
157 * *line to point one character past "include" and returns 1. Otherwise,
158 * it leaves *line unmodified and returns 0.
96 */
159 */
160static int
161parse_include(char **line)
162{
163 char *b, *e;
164
165 for (b = *line; *b && is_lws(*b); ++b)
166 /* nothing */ ;
167 if (!*b) {
168 *line = b;
169 return (-1);
170 }
171 for (e = b; *e && !is_lws(*e); ++e)
172 /* nothing */ ;
173 if (e == b)
174 return (0);
175 if (strlcmp("include", b, e - b) != 0)
176 return (0);
177 *line = e;
178 return (1);
179}
180
181/*
182 * Parse the control flag.
183 *
184 * Returns the corresponding pam_control_t value, or -1 if the end of the
185 * string was reached, a disallowed non-whitespace character was
186 * encountered, or the first word was not a recognized control flag.
187 *
188 * If parse_control_flag() is successful, it updates *line to point one
189 * character past the end of the control flag. If it reaches the end of
190 * the string, it updates *line to point to the terminating NUL character.
191 * In all other cases, it leaves *line unmodified.
192 */
193static pam_control_t
194parse_control_flag(char **line)
195{
196 char *b, *e;
197 int i;
198
199 for (b = *line; *b && is_lws(*b); ++b)
200 /* nothing */ ;
201 if (!*b) {
202 *line = b;
203 return ((pam_control_t)-1);
204 }
205 for (e = b; *e && !is_lws(*e); ++e)
206 /* nothing */ ;
207 if (e == b)
208 return ((pam_control_t)-1);
209 for (i = 0; i < PAM_NUM_CONTROL_FLAGS; ++i)
210 if (strlcmp(pam_control_flag_name[i], b, e - b) == 0)
211 break;
212 if (i == PAM_NUM_CONTROL_FLAGS)
213 return ((pam_control_t)-1);
214 *line = e;
215 return (i);
216}
217
218/*
219 * Parse a file name.
220 *
221 * Returns the length of the file name, or 0 if the end of the string was
222 * reached or a disallowed non-whitespace character was encountered.
223 *
224 * If parse_filename() is successful, it updates *filename to point to the
225 * first character of the filename and *line to point one character past
226 * the end. If it reaches the end of the string, it updates *line to
227 * point to the terminating NUL character and leaves *filename unmodified.
228 * In all other cases, it leaves both *line and *filename unmodified.
229 *
230 * Allowed characters are all characters in the POSIX portable filename
231 * character set, plus the path separator (forward slash).
232 */
233static int
234parse_filename(char **line, char **filename)
235{
236 char *b, *e;
237
238 for (b = *line; *b && is_lws(*b); ++b)
239 /* nothing */ ;
240 if (!*b) {
241 *line = b;
242 return (0);
243 }
244 for (e = b; *e && !is_lws(*e); ++e)
245 if (!is_pfcs(*e) && *e != '/')
246 return (0);
247 if (e == b)
248 return (0);
249 *line = e;
250 *filename = b;
251 return (e - b);
252}
253
254/*
255 * Parse an option.
256 *
257 * Returns a dynamically allocated string containing the next module
258 * option, or NULL if the end of the string was reached or a disallowed
259 * non-whitespace character was encountered.
260 *
261 * If parse_option() is successful, it updates *line to point one
262 * character past the end of the option. If it reaches the end of the
263 * string, it updates *line to point to the terminating NUL character. In
264 * all other cases, it leaves *line unmodified.
265 *
266 * If parse_option() fails to allocate memory, it will return NULL and set
267 * errno to a non-zero value.
268 *
269 * Allowed characters for option names are all characters in the POSIX
270 * portable filename character set. Allowed characters for option values
271 * are any printable non-whitespace characters. The option value may be
272 * quoted in either single or double quotes, in which case space
273 * characters and whichever quote character was not used are allowed.
274 * Note that the entire value must be quoted, not just part of it.
275 */
97static char *
276static char *
98dup_word(const char *str)
277parse_option(char **line)
99{
278{
100 const char *end;
101 char *word;
279 char *nb, *ne, *vb, *ve;
280 unsigned char q = 0;
281 char *option;
282 size_t size;
102
283
103 for (end = str; *end && *end != ' '; ++end)
284 errno = 0;
285 for (nb = *line; *nb && is_lws(*nb); ++nb)
104 /* nothing */ ;
286 /* nothing */ ;
105 if (asprintf(&word, "%.*s", (int)(end - str), str) < 0)
287 if (!*nb) {
288 *line = nb;
106 return (NULL);
289 return (NULL);
107 return (word);
290 }
291 for (ne = nb; *ne && !is_lws(*ne) && *ne != '='; ++ne)
292 if (!is_pfcs(*ne))
293 return (NULL);
294 if (ne == nb)
295 return (NULL);
296 if (*ne == '=') {
297 vb = ne + 1;
298 if (*vb == '"' || *vb == '\'')
299 q = *vb++;
300 for (ve = vb;
301 *ve && *ve != q && (is_p(*ve) || (q && is_lws(*ve)));
302 ++ve)
303 /* nothing */ ;
304 if (q && *ve != q)
305 /* non-printable character or missing endquote */
306 return (NULL);
307 if (q && *(ve + 1) && !is_lws(*(ve + 1)))
308 /* garbage after value */
309 return (NULL);
310 } else {
311 vb = ve = ne;
312 }
313 size = (ne - nb) + 1;
314 if (ve > vb)
315 size += (ve - vb) + 1;
316 if ((option = malloc(size)) == NULL)
317 return (NULL);
318 strncpy(option, nb, ne - nb);
319 if (ve > vb) {
320 option[ne - nb] = '=';
321 strncpy(option + (ne - nb) + 1, vb, ve - vb);
322 }
323 option[size - 1] = '\0';
324 *line = q ? ve + 1 : ve;
325 return (option);
108}
109
110/*
326}
327
328/*
111 * Return the length of the first word in a string.
329 * Consume trailing whitespace.
330 *
331 * If there are no non-whitespace characters left on the line, parse_eol()
332 * updates *line to point at the terminating NUL character and returns 0.
333 * Otherwise, it leaves *line unmodified and returns a non-zero value.
112 */
113static int
334 */
335static int
114wordlen(const char *str)
336parse_eol(char **line)
115{
337{
116 int i;
338 char *p;
117
339
118 for (i = 0; str[i] && str[i] != ' '; ++i)
340 for (p = *line; *p && is_lws(*p); ++p)
119 /* nothing */ ;
341 /* nothing */ ;
120 return (i);
342 if (*p)
343 return ((unsigned char)*p);
344 *line = p;
345 return (0);
121}
122
123typedef enum { pam_conf_style, pam_d_style } openpam_style_t;
124
125/*
126 * Extracts given chains from a policy file.
127 */
128static int
346}
347
348typedef enum { pam_conf_style, pam_d_style } openpam_style_t;
349
350/*
351 * Extracts given chains from a policy file.
352 */
353static int
129openpam_read_chain(pam_handle_t *pamh,
354openpam_parse_chain(pam_handle_t *pamh,
130 const char *service,
131 pam_facility_t facility,
132 const char *filename,
133 openpam_style_t style)
134{
135 pam_chain_t *this, **next;
355 const char *service,
356 pam_facility_t facility,
357 const char *filename,
358 openpam_style_t style)
359{
360 pam_chain_t *this, **next;
136 const char *p, *q;
137 int count, i, lineno, ret;
138 pam_facility_t fclt;
139 pam_control_t ctlf;
361 pam_facility_t fclt;
362 pam_control_t ctlf;
140 char *line, *name;
363 char *line, *str, *name;
364 char *option, **optv;
365 int len, lineno, ret;
141 FILE *f;
142
143 if ((f = fopen(filename, "r")) == NULL) {
144 openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_NOTICE,
145 "%s: %m", filename);
366 FILE *f;
367
368 if ((f = fopen(filename, "r")) == NULL) {
369 openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_NOTICE,
370 "%s: %m", filename);
146 return (0);
371 return (PAM_SUCCESS);
147 }
372 }
373 if (openpam_check_desc_owner_perms(filename, fileno(f)) != 0) {
374 fclose(f);
375 return (PAM_SYSTEM_ERR);
376 }
148 this = NULL;
377 this = NULL;
149 count = lineno = 0;
378 name = NULL;
379 lineno = 0;
150 while ((line = openpam_readline(f, &lineno, NULL)) != NULL) {
380 while ((line = openpam_readline(f, &lineno, NULL)) != NULL) {
151 p = line;
152
153 /* match service name */
381 /* get service name if necessary */
154 if (style == pam_conf_style) {
382 if (style == pam_conf_style) {
155 if (!match_word(p, service)) {
383 if ((len = parse_service_name(&line, &str)) == 0) {
384 openpam_log(PAM_LOG_NOTICE,
385 "%s(%d): invalid service name (ignored)",
386 filename, lineno);
156 FREE(line);
157 continue;
158 }
387 FREE(line);
388 continue;
389 }
159 p = next_word(p);
390 if (strlcmp(service, str, len) != 0) {
391 FREE(line);
392 continue;
393 }
160 }
161
394 }
395
162 /* match facility name */
163 for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt)
164 if (match_word(p, _pam_facility_name[fclt]))
165 break;
166 if (fclt == PAM_NUM_FACILITIES) {
167 openpam_log(PAM_LOG_NOTICE,
168 "%s(%d): invalid facility '%.*s' (ignored)",
169 filename, lineno, wordlen(p), p);
396 /* get facility name */
397 if ((fclt = parse_facility_name(&line)) == (pam_facility_t)-1) {
398 openpam_log(PAM_LOG_ERROR,
399 "%s(%d): missing or invalid facility",
400 filename, lineno);
170 goto fail;
171 }
172 if (facility != fclt && facility != PAM_FACILITY_ANY) {
173 FREE(line);
174 continue;
175 }
401 goto fail;
402 }
403 if (facility != fclt && facility != PAM_FACILITY_ANY) {
404 FREE(line);
405 continue;
406 }
176 p = next_word(p);
177
407
178 /* include other chain */
179 if (match_word(p, "include")) {
180 p = next_word(p);
181 if (*next_word(p) != '\0')
182 openpam_log(PAM_LOG_NOTICE,
183 "%s(%d): garbage at end of 'include' line",
408 /* check for "include" */
409 if (parse_include(&line)) {
410 if ((len = parse_service_name(&line, &str)) == 0) {
411 openpam_log(PAM_LOG_ERROR,
412 "%s(%d): missing or invalid filename",
184 filename, lineno);
413 filename, lineno);
185 if ((name = dup_word(p)) == NULL)
414 goto fail;
415 }
416 if ((name = strndup(str, len)) == NULL)
186 goto syserr;
417 goto syserr;
418 if (parse_eol(&line) != 0) {
419 openpam_log(PAM_LOG_ERROR,
420 "%s(%d): garbage at end of line",
421 filename, lineno);
422 goto fail;
423 }
187 ret = openpam_load_chain(pamh, name, fclt);
188 FREE(name);
424 ret = openpam_load_chain(pamh, name, fclt);
425 FREE(name);
189 if (ret < 0)
426 if (ret != PAM_SUCCESS)
190 goto fail;
427 goto fail;
191 count += ret;
192 FREE(line);
193 continue;
194 }
195
428 FREE(line);
429 continue;
430 }
431
196 /* allocate new entry */
197 if ((this = calloc(1, sizeof *this)) == NULL)
198 goto syserr;
432 /* get control flag */
433 if ((ctlf = parse_control_flag(&line)) == (pam_control_t)-1) {
434 openpam_log(PAM_LOG_ERROR,
435 "%s(%d): missing or invalid control flag",
436 filename, lineno);
437 goto fail;
438 }
199
439
200 /* control flag */
201 for (ctlf = 0; ctlf < PAM_NUM_CONTROL_FLAGS; ++ctlf)
202 if (match_word(p, _pam_control_flag_name[ctlf]))
203 break;
204 if (ctlf == PAM_NUM_CONTROL_FLAGS) {
440 /* get module name */
441 if ((len = parse_filename(&line, &str)) == 0) {
205 openpam_log(PAM_LOG_ERROR,
442 openpam_log(PAM_LOG_ERROR,
206 "%s(%d): invalid control flag '%.*s'",
207 filename, lineno, wordlen(p), p);
443 "%s(%d): missing or invalid module name",
444 filename, lineno);
208 goto fail;
209 }
445 goto fail;
446 }
447 if ((name = strndup(str, len)) == NULL)
448 goto syserr;
449
450 /* allocate new entry */
451 if ((this = calloc(1, sizeof *this)) == NULL)
452 goto syserr;
210 this->flag = ctlf;
211
453 this->flag = ctlf;
454
212 /* module name */
213 p = next_word(p);
214 if (*p == '\0') {
455 /* get module options */
456 if ((this->optv = malloc(sizeof *optv)) == NULL)
457 goto syserr;
458 this->optc = 0;
459 while ((option = parse_option(&line)) != NULL) {
460 optv = realloc(this->optv,
461 (this->optc + 2) * sizeof *optv);
462 if (optv == NULL)
463 goto syserr;
464 this->optv = optv;
465 this->optv[this->optc++] = option;
466 }
467 this->optv[this->optc] = NULL;
468 if (*line != '\0') {
215 openpam_log(PAM_LOG_ERROR,
469 openpam_log(PAM_LOG_ERROR,
216 "%s(%d): missing module name",
470 "%s(%d): syntax error in module options",
217 filename, lineno);
218 goto fail;
219 }
471 filename, lineno);
472 goto fail;
473 }
220 if ((name = dup_word(p)) == NULL)
221 goto syserr;
474
475 /* load module */
222 this->module = openpam_load_module(name);
223 FREE(name);
224 if (this->module == NULL)
225 goto fail;
226
476 this->module = openpam_load_module(name);
477 FREE(name);
478 if (this->module == NULL)
479 goto fail;
480
227 /* module options */
228 p = q = next_word(p);
229 while (*q != '\0') {
230 ++this->optc;
231 q = next_word(q);
232 }
233 this->optv = calloc(this->optc + 1, sizeof(char *));
234 if (this->optv == NULL)
235 goto syserr;
236 for (i = 0; i < this->optc; ++i) {
237 if ((this->optv[i] = dup_word(p)) == NULL)
238 goto syserr;
239 p = next_word(p);
240 }
241
242 /* hook it up */
243 for (next = &pamh->chains[fclt]; *next != NULL;
244 next = &(*next)->next)
245 /* nothing */ ;
246 *next = this;
247 this = NULL;
481 /* hook it up */
482 for (next = &pamh->chains[fclt]; *next != NULL;
483 next = &(*next)->next)
484 /* nothing */ ;
485 *next = this;
486 this = NULL;
248 ++count;
249
250 /* next please... */
251 FREE(line);
252 }
253 if (!feof(f))
254 goto syserr;
255 fclose(f);
487
488 /* next please... */
489 FREE(line);
490 }
491 if (!feof(f))
492 goto syserr;
493 fclose(f);
256 return (count);
257 syserr:
494 return (PAM_SUCCESS);
495syserr:
258 openpam_log(PAM_LOG_ERROR, "%s: %m", filename);
496 openpam_log(PAM_LOG_ERROR, "%s: %m", filename);
259 fail:
497fail:
498 if (this && this->optc) {
499 while (this->optc--)
500 FREE(this->optv[this->optc]);
501 FREE(this->optv);
502 }
260 FREE(this);
261 FREE(line);
503 FREE(this);
504 FREE(line);
505 FREE(name);
262 fclose(f);
506 fclose(f);
263 return (-1);
507 return (PAM_SYSTEM_ERR);
264}
265
266static const char *openpam_policy_path[] = {
267 "/etc/pam.d/",
268 "/etc/pam.conf",
269 "/usr/local/etc/pam.d/",
270 "/usr/local/etc/pam.conf",
271 NULL

--- 6 unchanged lines hidden (view full) ---

278static int
279openpam_load_chain(pam_handle_t *pamh,
280 const char *service,
281 pam_facility_t facility)
282{
283 const char **path;
284 char *filename;
285 size_t len;
508}
509
510static const char *openpam_policy_path[] = {
511 "/etc/pam.d/",
512 "/etc/pam.conf",
513 "/usr/local/etc/pam.d/",
514 "/usr/local/etc/pam.conf",
515 NULL

--- 6 unchanged lines hidden (view full) ---

522static int
523openpam_load_chain(pam_handle_t *pamh,
524 const char *service,
525 pam_facility_t facility)
526{
527 const char **path;
528 char *filename;
529 size_t len;
286 int r;
530 int ret;
287
288 for (path = openpam_policy_path; *path != NULL; ++path) {
289 len = strlen(*path);
290 if ((*path)[len - 1] == '/') {
291 if (asprintf(&filename, "%s%s", *path, service) < 0) {
292 openpam_log(PAM_LOG_ERROR, "asprintf(): %m");
531
532 for (path = openpam_policy_path; *path != NULL; ++path) {
533 len = strlen(*path);
534 if ((*path)[len - 1] == '/') {
535 if (asprintf(&filename, "%s%s", *path, service) < 0) {
536 openpam_log(PAM_LOG_ERROR, "asprintf(): %m");
293 return (-PAM_BUF_ERR);
537 return (PAM_BUF_ERR);
294 }
538 }
295 r = openpam_read_chain(pamh, service, facility,
539 ret = openpam_parse_chain(pamh, service, facility,
296 filename, pam_d_style);
297 FREE(filename);
298 } else {
540 filename, pam_d_style);
541 FREE(filename);
542 } else {
299 r = openpam_read_chain(pamh, service, facility,
543 ret = openpam_parse_chain(pamh, service, facility,
300 *path, pam_conf_style);
301 }
544 *path, pam_conf_style);
545 }
302 if (r != 0)
303 return (r);
546 if (ret != PAM_SUCCESS)
547 return (ret);
304 }
548 }
305 return (0);
549 return (PAM_SUCCESS);
306}
307
308/*
309 * OpenPAM internal
310 *
311 * Configure a service
312 */
313
314int
315openpam_configure(pam_handle_t *pamh,
316 const char *service)
317{
318 pam_facility_t fclt;
550}
551
552/*
553 * OpenPAM internal
554 *
555 * Configure a service
556 */
557
558int
559openpam_configure(pam_handle_t *pamh,
560 const char *service)
561{
562 pam_facility_t fclt;
563 const char *p;
319
564
320 if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) < 0)
565 for (p = service; *p; ++p)
566 if (!is_pfcs(*p))
567 return (PAM_SYSTEM_ERR);
568
569 if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) != PAM_SUCCESS)
321 goto load_err;
322
323 for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) {
324 if (pamh->chains[fclt] != NULL)
325 continue;
570 goto load_err;
571
572 for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) {
573 if (pamh->chains[fclt] != NULL)
574 continue;
326 if (openpam_load_chain(pamh, PAM_OTHER, fclt) < 0)
575 if (openpam_load_chain(pamh, PAM_OTHER, fclt) != PAM_SUCCESS)
327 goto load_err;
328 }
329 return (PAM_SUCCESS);
576 goto load_err;
577 }
578 return (PAM_SUCCESS);
330 load_err:
579load_err:
331 openpam_clear_chains(pamh->chains);
332 return (PAM_SYSTEM_ERR);
333}
334
335/*
336 * NODOC
337 *
338 * Error codes:
339 * PAM_SYSTEM_ERR
340 */
580 openpam_clear_chains(pamh->chains);
581 return (PAM_SYSTEM_ERR);
582}
583
584/*
585 * NODOC
586 *
587 * Error codes:
588 * PAM_SYSTEM_ERR
589 */