static uint parse_args (pam_handle_t *ph, int argc, const char **argv) { uint args = 0; const void *svc; int only_if_len; int i; svc = NULL; if (pam_get_item (ph, PAM_SERVICE, &svc) != PAM_SUCCESS) svc = NULL; only_if_len = strlen ("only_if="); /* Parse the arguments */ for (i = 0; i < argc; i++) { if (strcmp (argv[i], "auto_start") == 0) { args |= ARG_AUTO_START; } else if (strncmp (argv[i], "only_if=", only_if_len) == 0) { const char *value = argv[i] + only_if_len; if (!evaluate_inlist (svc, value)) args |= ARG_IGNORE_SERVICE; } else if (strcmp (argv[i], "use_authtok") == 0) { args |= ARG_USE_AUTHTOK; } else { syslog (GKR_LOG_WARN, "gkr-pam: invalid option: %s", argv[i]); } } return args; }
/* Match a triple. */ static int evaluate(pam_handle_t *pamh, int debug, const char *left, const char *qual, const char *right, struct passwd *pwd, const char *user) { char buf[LINE_MAX] = ""; const char *attribute = left; /* Figure out what we're evaluating here, and convert it to a string.*/ if ((strcasecmp(left, "login") == 0) || (strcasecmp(left, "name") == 0) || (strcasecmp(left, "user") == 0)) { snprintf(buf, sizeof(buf), "%s", user); left = buf; } if (strcasecmp(left, "uid") == 0) { snprintf(buf, sizeof(buf), "%lu", (unsigned long) pwd->pw_uid); left = buf; } if (strcasecmp(left, "gid") == 0) { snprintf(buf, sizeof(buf), "%lu", (unsigned long) pwd->pw_gid); left = buf; } if (strcasecmp(left, "shell") == 0) { snprintf(buf, sizeof(buf), "%s", pwd->pw_shell); left = buf; } if ((strcasecmp(left, "home") == 0) || (strcasecmp(left, "dir") == 0) || (strcasecmp(left, "homedir") == 0)) { snprintf(buf, sizeof(buf), "%s", pwd->pw_dir); left = buf; } if (strcasecmp(left, "service") == 0) { const void *svc; if (pam_get_item(pamh, PAM_SERVICE, &svc) != PAM_SUCCESS) svc = ""; snprintf(buf, sizeof(buf), "%s", (const char *)svc); left = buf; } /* If we have no idea what's going on, return an error. */ if (left != buf) { pam_syslog(pamh, LOG_CRIT, "unknown attribute \"%s\"", left); return PAM_SERVICE_ERR; } if (debug) { pam_syslog(pamh, LOG_DEBUG, "'%s' resolves to '%s'", attribute, left); } /* Attribute value < some threshold. */ if ((strcasecmp(qual, "<") == 0) || (strcasecmp(qual, "lt") == 0)) { return evaluate_lt(pamh, left, right); } /* Attribute value <= some threshold. */ if ((strcasecmp(qual, "<=") == 0) || (strcasecmp(qual, "le") == 0)) { return evaluate_le(pamh, left, right); } /* Attribute value > some threshold. */ if ((strcasecmp(qual, ">") == 0) || (strcasecmp(qual, "gt") == 0)) { return evaluate_gt(pamh, left, right); } /* Attribute value >= some threshold. */ if ((strcasecmp(qual, ">=") == 0) || (strcasecmp(qual, "ge") == 0)) { return evaluate_ge(pamh, left, right); } /* Attribute value == some threshold. */ if (strcasecmp(qual, "eq") == 0) { return evaluate_eqn(pamh, left, right); } /* Attribute value = some string. */ if (strcasecmp(qual, "=") == 0) { return evaluate_eqs(left, right); } /* Attribute value != some threshold. */ if (strcasecmp(qual, "ne") == 0) { return evaluate_nen(pamh, left, right); } /* Attribute value != some string. */ if (strcasecmp(qual, "!=") == 0) { return evaluate_nes(left, right); } /* Attribute value matches some pattern. */ if ((strcasecmp(qual, "=~") == 0) || (strcasecmp(qual, "glob") == 0)) { return evaluate_glob(left, right); } if ((strcasecmp(qual, "!~") == 0) || (strcasecmp(qual, "noglob") == 0)) { return evaluate_noglob(left, right); } /* Attribute value matches item in list. */ if (strcasecmp(qual, "in") == 0) { return evaluate_inlist(left, right); } if (strcasecmp(qual, "notin") == 0) { return evaluate_notinlist(left, right); } /* User is in this group. */ if (strcasecmp(qual, "ingroup") == 0) { return evaluate_ingroup(pamh, user, right); } /* User is not in this group. */ if (strcasecmp(qual, "notingroup") == 0) { return evaluate_notingroup(pamh, user, right); } /* (Rhost, user) is in this netgroup. */ if (strcasecmp(qual, "innetgr") == 0) { const void *rhost; if (pam_get_item(pamh, PAM_RHOST, &rhost) != PAM_SUCCESS) rhost = NULL; return evaluate_innetgr(rhost, user, right); } /* (Rhost, user) is not in this group. */ if (strcasecmp(qual, "notinnetgr") == 0) { const void *rhost; if (pam_get_item(pamh, PAM_RHOST, &rhost) != PAM_SUCCESS) rhost = NULL; return evaluate_notinnetgr(rhost, user, right); } /* Fail closed. */ return PAM_SERVICE_ERR; }
/* Check for list mismatch. */ static int evaluate_notinlist(const char *left, const char *right) { return evaluate_inlist(left, right) != PAM_SUCCESS ? PAM_SUCCESS : PAM_AUTH_ERR; }