int openpam_configure(pam_handle_t *pamh, const char *service) { pam_facility_t fclt; int serrno; ENTERS(service); if (!valid_service_name(service)) { openpam_log(PAM_LOG_ERROR, "invalid service name"); RETURNC(PAM_SYSTEM_ERR); } if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) < 0) { if (errno != ENOENT) 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) < 0) goto load_err; } RETURNC(PAM_SUCCESS); load_err: serrno = errno; openpam_clear_chains(pamh->chains); errno = serrno; RETURNC(PAM_SYSTEM_ERR); }
int pam_set_data(pam_handle_t *pamh, const char *module_data_name, void *data, void (*cleanup)(pam_handle_t *pamh, void *data, int pam_end_status)) { pam_data_t *dp; ENTERS(module_data_name); if (pamh == NULL) RETURNC(PAM_SYSTEM_ERR); for (dp = pamh->module_data; dp != NULL; dp = dp->next) { if (strcmp(dp->name, module_data_name) == 0) { if (dp->cleanup) (dp->cleanup)(pamh, dp->data, PAM_SUCCESS); dp->data = data; dp->cleanup = cleanup; RETURNC(PAM_SUCCESS); } } if ((dp = malloc(sizeof *dp)) == NULL) RETURNC(PAM_BUF_ERR); if ((dp->name = strdup(module_data_name)) == NULL) { FREE(dp); RETURNC(PAM_BUF_ERR); } dp->data = data; dp->cleanup = cleanup; dp->next = pamh->module_data; pamh->module_data = dp; RETURNC(PAM_SUCCESS); }
/* * Locates the policy file for a given service and reads the given chains * from it. * * Returns the number of policy entries which were found for the specified * service and facility, or -1 if a system error occurred or a syntax * error was encountered. */ static int openpam_load_chain(pam_handle_t *pamh, const char *service, pam_facility_t facility) { const char *p, **path; char filename[PATH_MAX]; size_t len; openpam_style_t style; int ret; ENTERS(facility < 0 ? "any" : pam_facility_name[facility]); /* either absolute or relative to cwd */ if (strchr(service, '/') != NULL) { if ((p = strrchr(service, '.')) != NULL && strcmp(p, ".conf") == 0) style = pam_conf_style; else style = pam_d_style; ret = openpam_load_file(pamh, service, facility, service, style); RETURNN(ret); } /* search standard locations */ for (path = openpam_policy_path; *path != NULL; ++path) { /* construct filename */ len = strlcpy(filename, *path, sizeof filename); if (filename[len - 1] == '/') { len = strlcat(filename, service, sizeof filename); if (len >= sizeof filename) { errno = ENAMETOOLONG; RETURNN(-1); } style = pam_d_style; } else { style = pam_conf_style; } ret = openpam_load_file(pamh, service, facility, filename, style); /* success */ if (ret > 0) RETURNN(ret); /* the file exists, but an error occurred */ if (ret == -1 && errno != ENOENT) RETURNN(ret); /* in pam.d style, an empty file counts as a hit */ if (ret == 0 && style == pam_d_style) RETURNN(ret); } /* no hit */ errno = ENOENT; RETURNN(-1); }
int openpam_set_option(pam_handle_t *pamh, const char *option, const char *value) { pam_chain_t *cur; char *opt, **optv; size_t len; int i; ENTERS(option); if (pamh == NULL || pamh->current == NULL || option == NULL) RETURNC(PAM_SYSTEM_ERR); cur = pamh->current; for (len = 0; option[len] != '\0'; ++len) if (option[len] == '=') break; for (i = 0; i < cur->optc; ++i) { if (strncmp(cur->optv[i], option, len) == 0 && (cur->optv[i][len] == '\0' || cur->optv[i][len] == '=')) break; } if (value == NULL) { /* remove */ if (i == cur->optc) RETURNC(PAM_SUCCESS); for (free(cur->optv[i]); i < cur->optc; ++i) cur->optv[i] = cur->optv[i + 1]; cur->optv[i] = NULL; RETURNC(PAM_SUCCESS); } if (asprintf(&opt, "%.*s=%s", (int)len, option, value) < 0) RETURNC(PAM_BUF_ERR); if (i == cur->optc) { /* add */ optv = realloc(cur->optv, sizeof(*optv) * ((size_t)cur->optc + 2)); if (optv == NULL) { FREE(opt); RETURNC(PAM_BUF_ERR); } optv[i] = opt; optv[i + 1] = NULL; cur->optv = optv; ++cur->optc; } else { /* replace */ FREE(cur->optv[i]); cur->optv[i] = opt; } RETURNC(PAM_SUCCESS); }
TESTCASE() { MAX_WAIT_TIME(0); FUNCT(bounded_buf_get); FUNCT(bounded_buf_put); TVAR(P1); TVAR(C1); TVAR(C2); WAIT_FOR_THREAD(P1, ENTERS(bounded_buf_put), "Wait for a producer."); WAIT_FOR_DISTINCT_THREADS((C1, C2), ENTERS(bounded_buf_get), "Wait for 2 consumers."); RUN_THREAD_THROUGH(P1, RETURNS(bounded_buf_put), "Producer inserts an item."); RUN_THREAD_THROUGH(C1, HITS_MANUAL_PC(42), "First consumer runs first phase."); RUN_THREAD_THROUGH(C2, RETURNS(bounded_buf_get), "Second consumer removes the item."); // ERROR! RUN_THREAD_THROUGH(C1, ENDS(), "First consumer runs the second phase."); }
int openpam_configure(pam_handle_t *pamh, const char *service) { pam_facility_t fclt; int serrno; ENTERS(service); if (!valid_service_name(service)) { openpam_log(PAM_LOG_ERROR, "invalid service name"); RETURNC(PAM_SYSTEM_ERR); } if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) < 0) 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) < 0) goto load_err; } #ifdef __NetBSD__ /* * On NetBSD we require the AUTH chain to have a binding * or a required module. */ { pam_chain_t *this = pamh->chains[PAM_AUTH]; for (; this != NULL; this = this->next) if (this->flag == PAM_BINDING || this->flag == PAM_REQUIRED) break; if (this == NULL) { openpam_log(PAM_LOG_ERROR, "No required or binding component " "in service %s, facility %s", service, pam_facility_name[PAM_AUTH]); goto load_err; } } #endif RETURNC(PAM_SUCCESS); load_err: serrno = errno; openpam_clear_chains(pamh->chains); errno = serrno; RETURNC(PAM_SYSTEM_ERR); }
int pam_get_data(const pam_handle_t *pamh, const char *module_data_name, const void **data) { pam_data_t *dp; ENTERS(module_data_name); if (pamh == NULL) RETURNC(PAM_SYSTEM_ERR); for (dp = pamh->module_data; dp != NULL; dp = dp->next) { if (strcmp(dp->name, module_data_name) == 0) { *data = (void *)dp->data; RETURNC(PAM_SUCCESS); } } RETURNC(PAM_NO_MODULE_DATA); }
const char * pam_getenv(pam_handle_t *pamh, const char *name) { char *str; int i; ENTERS(name); if (pamh == NULL) RETURNS(NULL); if (name == NULL || strchr(name, '=') != NULL) RETURNS(NULL); if ((i = openpam_findenv(pamh, name, strlen(name))) < 0) RETURNS(NULL); for (str = pamh->env[i]; *str != '\0'; ++str) { if (*str == '=') { ++str; break; } } RETURNS(str); }
const char * openpam_get_option(pam_handle_t *pamh, const char *option) { pam_chain_t *cur; size_t len; int i; ENTERS(option); if (pamh == NULL || pamh->current == NULL || option == NULL) RETURNS(NULL); cur = pamh->current; len = strlen(option); for (i = 0; i < cur->optc; ++i) { if (strncmp(cur->optv[i], option, len) == 0) { if (cur->optv[i][len] == '\0') RETURNS(&cur->optv[i][len]); else if (cur->optv[i][len] == '=') RETURNS(&cur->optv[i][len + 1]); } } RETURNS(NULL); }