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 */ |