int openpam_configure(pam_handle_t *pamh, const char *service) { pam_facility_t fclt; const char *p; for (p = service; *p; ++p) if (!is_pfcs(*p)) return (PAM_SYSTEM_ERR); if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) != PAM_SUCCESS) goto load_err; for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) { if (pamh->chains[fclt] != NULL) continue; if (openpam_load_chain(pamh, PAM_OTHER, fclt) != PAM_SUCCESS) goto load_err; } return (PAM_SUCCESS); load_err: openpam_clear_chains(pamh->chains); return (PAM_SYSTEM_ERR); }
/* * Validate a service name. * * Returns a non-zero value if the argument points to a NUL-terminated * string consisting entirely of characters in the POSIX portable filename * character set, excluding the path separator character. */ static int valid_service_name(const char *name) { const char *p; if (OPENPAM_FEATURE(RESTRICT_SERVICE_NAME)) { /* path separator not allowed */ for (p = name; *p != '\0'; ++p) if (!is_pfcs(*p)) return (0); } else { /* path separator allowed */ for (p = name; *p != '\0'; ++p) if (!is_pfcs(*p) && *p != '/') return (0); } return (1); }
/* * Parse an option. * * Returns a dynamically allocated string containing the next module * option, or NULL if the end of the string was reached or a disallowed * non-whitespace character was encountered. * * If parse_option() is successful, it updates *line to point one * character past the end of the option. If it reaches the end of the * string, it updates *line to point to the terminating NUL character. In * all other cases, it leaves *line unmodified. * * If parse_option() fails to allocate memory, it will return NULL and set * errno to a non-zero value. * * Allowed characters for option names are all characters in the POSIX * portable filename character set. Allowed characters for option values * are any printable non-whitespace characters. The option value may be * quoted in either single or double quotes, in which case space * characters and whichever quote character was not used are allowed. * Note that the entire value must be quoted, not just part of it. */ static char * parse_option(char **line) { char *nb, *ne, *vb, *ve; unsigned char q = 0; char *option; size_t size; errno = 0; for (nb = *line; *nb && is_lws(*nb); ++nb) /* nothing */ ; if (!*nb) { *line = nb; return (NULL); } for (ne = nb; *ne && !is_lws(*ne) && *ne != '='; ++ne) if (!is_pfcs(*ne)) return (NULL); if (ne == nb) return (NULL); if (*ne == '=') { vb = ne + 1; if (*vb == '"' || *vb == '\'') q = *vb++; for (ve = vb; *ve && *ve != q && (is_p(*ve) || (q && is_lws(*ve))); ++ve) /* nothing */ ; if (q && *ve != q) /* non-printable character or missing endquote */ return (NULL); if (q && *(ve + 1) && !is_lws(*(ve + 1))) /* garbage after value */ return (NULL); } else { vb = ve = ne; } size = (ne - nb) + 1; if (ve > vb) size += (ve - vb) + 1; if ((option = malloc(size)) == NULL) return (NULL); strncpy(option, nb, ne - nb); if (ve > vb) { option[ne - nb] = '='; strncpy(option + (ne - nb) + 1, vb, ve - vb); } option[size - 1] = '\0'; *line = q ? ve + 1 : ve; return (option); }
/* * Parse the service name. * * Returns the length of the service name, or 0 if the end of the string * was reached or a disallowed non-whitespace character was encountered. * * If parse_service_name() is successful, it updates *service to point to * the first character of the service name and *line to point one * character past the end. If it reaches the end of the string, it * updates *line to point to the terminating NUL character and leaves * *service unmodified. In all other cases, it leaves both *line and * *service unmodified. * * Allowed characters are all characters in the POSIX portable filename * character set. */ static int parse_service_name(char **line, char **service) { char *b, *e; for (b = *line; *b && is_lws(*b); ++b) /* nothing */ ; if (!*b) { *line = b; return (0); } for (e = b; *e && !is_lws(*e); ++e) if (!is_pfcs(*e)) return (0); if (e == b) return (0); *line = e; *service = b; return (e - b); }
/* * Parse a file name. * * Returns the length of the file name, or 0 if the end of the string was * reached or a disallowed non-whitespace character was encountered. * * If parse_filename() is successful, it updates *filename to point to the * first character of the filename and *line to point one character past * the end. If it reaches the end of the string, it updates *line to * point to the terminating NUL character and leaves *filename unmodified. * In all other cases, it leaves both *line and *filename unmodified. * * Allowed characters are all characters in the POSIX portable filename * character set, plus the path separator (forward slash). */ static int parse_filename(char **line, char **filename) { char *b, *e; for (b = *line; *b && is_lws(*b); ++b) /* nothing */ ; if (!*b) { *line = b; return (0); } for (e = b; *e && !is_lws(*e); ++e) if (!is_pfcs(*e) && *e != '/') return (0); if (e == b) return (0); *line = e; *filename = b; return (e - b); }