PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char *argv[]) { int ret; int faked = 0; const char *dir = NULL; const char *fake_suite = NULL; char *questions; const char *user; char *response = NULL; char fmt[512]; (void)flags; (void)argc; (void)argv; pam_get_item(pamh, PAM_USER, (const void **)&user); openlog("pam_ocra", 0, LOG_AUTHPRIV); fake_suite = openpam_get_option(pamh, "fake_prompt"); dir = openpam_get_option(pamh, "dir"); if (PAM_SUCCESS != (ret = challenge(dir, user, &questions))) { if (PAM_NO_MODULE_DATA == ret && NULL != fake_suite) { if (PAM_SUCCESS != (ret = fake_challenge(fake_suite, &questions))) goto end; faked = 1; } else goto end; } snprintf(fmt, 512, "OCRA Challenge: %s\nOCRA Response: ", questions); if (PAM_SUCCESS != (ret = get_response(pamh, fmt, &response))) goto end; if (1 == faked) ret = PAM_AUTH_ERR; else ret = verify(dir, user, questions, response); free(response); end: closelog(); return ret; }
int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) { char prompt_buf[1024]; size_t prompt_size; const void *promptp; char *resp; int r; ENTER(); if (pamh == NULL || user == NULL) RETURNC(PAM_SYSTEM_ERR); r = pam_get_item(pamh, PAM_USER, (const void **)user); if (r == PAM_SUCCESS && *user != NULL) RETURNC(PAM_SUCCESS); /* pam policy overrides the module's choice */ if ((promptp = openpam_get_option(pamh, "user_prompt")) != NULL) prompt = promptp; /* no prompt provided, see if there is one tucked away somewhere */ if (prompt == NULL) if (pam_get_item(pamh, PAM_USER_PROMPT, &promptp) && promptp != NULL) prompt = promptp; /* fall back to hardcoded default */ if (prompt == NULL) prompt = user_prompt; /* expand */ prompt_size = sizeof prompt_buf; r = openpam_subst(pamh, prompt_buf, &prompt_size, prompt); if (r == PAM_SUCCESS && prompt_size <= sizeof prompt_buf) prompt = prompt_buf; r = pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, "%s", prompt); if (r != PAM_SUCCESS) RETURNC(r); r = pam_set_item(pamh, PAM_USER, resp); FREE(resp); if (r != PAM_SUCCESS) RETURNC(r); r = pam_get_item(pamh, PAM_USER, (const void **)user); RETURNC(r); }
/* Print a verbose error, including the function name and a * cleaned up filename. */ void _pam_verbose_error(pam_handle_t *pamh, int flags, const char *file, const char *function, const char *format, ...) { va_list ap; char *fmtbuf, *modname, *period; if (!(flags & PAM_SILENT) && !openpam_get_option(pamh, "no_warn")) { modname = basename(file); period = strchr(modname, '.'); if (period == NULL) period = strchr(modname, '\0'); va_start(ap, format); asprintf(&fmtbuf, "%.*s: %s: %s\n", (int)(period - modname), modname, function, format); pam_verror(pamh, fmtbuf, ap); free(fmtbuf); va_end(ap); } }
int openpam_dispatch(pam_handle_t *pamh, int primitive, int flags) { pam_chain_t *chain; int err, fail, nsuccess, r; int debug; ENTER(); /* prevent recursion */ if (pamh->current != NULL) { openpam_log(PAM_LOG_ERROR, "%s() called while %s::%s() is in progress", pam_func_name[primitive], pamh->current->module->path, pam_sm_func_name[pamh->primitive]); RETURNC(PAM_ABORT); } /* pick a chain */ switch (primitive) { case PAM_SM_AUTHENTICATE: case PAM_SM_SETCRED: chain = pamh->chains[PAM_AUTH]; break; case PAM_SM_ACCT_MGMT: chain = pamh->chains[PAM_ACCOUNT]; break; case PAM_SM_OPEN_SESSION: case PAM_SM_CLOSE_SESSION: chain = pamh->chains[PAM_SESSION]; break; case PAM_SM_CHAUTHTOK: chain = pamh->chains[PAM_PASSWORD]; break; default: RETURNC(PAM_SYSTEM_ERR); } /* execute */ err = PAM_SUCCESS; fail = nsuccess = 0; for (; chain != NULL; chain = chain->next) { if (chain->module->func[primitive] == NULL) { openpam_log(PAM_LOG_ERROR, "%s: no %s()", chain->module->path, pam_sm_func_name[primitive]); r = PAM_SYMBOL_ERR; } else { pamh->primitive = primitive; pamh->current = chain; debug = (openpam_get_option(pamh, "debug") != NULL); if (debug) ++openpam_debug; openpam_log(PAM_LOG_LIBDEBUG, "calling %s() in %s", pam_sm_func_name[primitive], chain->module->path); r = (chain->module->func[primitive])(pamh, flags, chain->optc, (const char **)(intptr_t)chain->optv); pamh->current = NULL; openpam_log(PAM_LOG_LIBDEBUG, "%s: %s(): %s", chain->module->path, pam_sm_func_name[primitive], pam_strerror(pamh, r)); if (debug) --openpam_debug; } if (r == PAM_IGNORE) continue; if (r == PAM_SUCCESS) { ++nsuccess; /* * For pam_setcred() and pam_chauthtok() with the * PAM_PRELIM_CHECK flag, treat "sufficient" as * "optional". */ if ((chain->flag == PAM_SUFFICIENT || chain->flag == PAM_BINDING) && !fail && primitive != PAM_SM_SETCRED && !(primitive == PAM_SM_CHAUTHTOK && (flags & PAM_PRELIM_CHECK))) break; continue; } openpam_check_error_code(primitive, r); /* * Record the return code from the first module to * fail. If a required module fails, record the * return code from the first required module to fail. */ if (err == PAM_SUCCESS) err = r; if ((chain->flag == PAM_REQUIRED || chain->flag == PAM_BINDING) && !fail) { openpam_log(PAM_LOG_LIBDEBUG, "required module failed"); fail = 1; err = r; } /* * If a requisite module fails, terminate the chain * immediately. */ if (chain->flag == PAM_REQUISITE) { openpam_log(PAM_LOG_LIBDEBUG, "requisite module failed"); fail = 1; break; } } if (!fail && err != PAM_NEW_AUTHTOK_REQD) err = PAM_SUCCESS; /* * Require the chain to be non-empty, and at least one module * in the chain to be successful, so that we don't fail open. */ if (err == PAM_SUCCESS && nsuccess < 1) { openpam_log(PAM_LOG_ERROR, "all modules were unsuccessful for %s()", pam_sm_func_name[primitive]); err = PAM_SYSTEM_ERR; } RETURNC(err); }
static int pam_group(pam_handle_t *pamh) { int local, remote; const char *group, *user; const void *ruser; char *const *list; struct passwd *pwd; struct group *grp; /* get target account */ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL || (pwd = getpwnam(user)) == NULL) return (PAM_AUTH_ERR); if (pwd->pw_uid != 0 && openpam_get_option(pamh, "root_only")) return (PAM_IGNORE); /* check local / remote */ local = openpam_get_option(pamh, "luser") ? 1 : 0; remote = openpam_get_option(pamh, "ruser") ? 1 : 0; if (local && remote) { openpam_log(PAM_LOG_ERROR, "(pam_group) " "the luser and ruser options are mutually exclusive"); return (PAM_SERVICE_ERR); } else if (local) { /* we already have the correct struct passwd */ } else { if (!remote) openpam_log(PAM_LOG_NOTICE, "(pam_group) " "neither luser nor ruser specified, assuming ruser"); /* default / historical behavior */ if (pam_get_item(pamh, PAM_RUSER, &ruser) != PAM_SUCCESS || ruser == NULL || (pwd = getpwnam(ruser)) == NULL) return (PAM_AUTH_ERR); } /* get regulating group */ if ((group = openpam_get_option(pamh, "group")) == NULL) group = "wheel"; if ((grp = getgrnam(group)) == NULL || grp->gr_mem == NULL) goto failed; /* check if user's own primary group */ if (pwd->pw_gid == grp->gr_gid) goto found; /* iterate over members */ for (list = grp->gr_mem; list != NULL && *list != NULL; ++list) if (strcmp(*list, pwd->pw_name) == 0) goto found; not_found: if (openpam_get_option(pamh, "deny")) return (PAM_SUCCESS); return (PAM_AUTH_ERR); found: if (openpam_get_option(pamh, "deny")) return (PAM_AUTH_ERR); return (PAM_SUCCESS); failed: if (openpam_get_option(pamh, "fail_safe")) goto found; else goto not_found; }
int pam_get_authtok(pam_handle_t *pamh, int item, const char **authtok, const char *prompt) { char prompt_buf[1024]; size_t prompt_size; const void *oldauthtok, *prevauthtok, *promptp; const char *prompt_option, *default_prompt; const void *lhost, *rhost; char *resp, *resp2; int pitem, r, style, twice; ENTER(); if (pamh == NULL || authtok == NULL) RETURNC(PAM_SYSTEM_ERR); *authtok = NULL; twice = 0; switch (item) { case PAM_AUTHTOK: pitem = PAM_AUTHTOK_PROMPT; prompt_option = "authtok_prompt"; default_prompt = authtok_prompt; r = pam_get_item(pamh, PAM_RHOST, &rhost); if (r == PAM_SUCCESS && rhost != NULL) { r = pam_get_item(pamh, PAM_HOST, &lhost); if (r == PAM_SUCCESS && lhost != NULL) { if (strcmp(rhost, lhost) != 0) default_prompt = authtok_prompt_remote; } } r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok); if (r == PAM_SUCCESS && oldauthtok != NULL) { default_prompt = newauthtok_prompt; twice = 1; } break; case PAM_OLDAUTHTOK: pitem = PAM_OLDAUTHTOK_PROMPT; prompt_option = "oldauthtok_prompt"; default_prompt = oldauthtok_prompt; twice = 0; break; default: RETURNC(PAM_SYMBOL_ERR); } if (openpam_get_option(pamh, "try_first_pass") || openpam_get_option(pamh, "use_first_pass")) { r = pam_get_item(pamh, item, &prevauthtok); if (r == PAM_SUCCESS && prevauthtok != NULL) { *authtok = prevauthtok; RETURNC(PAM_SUCCESS); } else if (openpam_get_option(pamh, "use_first_pass")) { RETURNC(r == PAM_SUCCESS ? PAM_AUTH_ERR : r); } } /* pam policy overrides the module's choice */ if ((promptp = openpam_get_option(pamh, prompt_option)) != NULL) prompt = promptp; /* no prompt provided, see if there is one tucked away somewhere */ if (prompt == NULL) if (pam_get_item(pamh, pitem, &promptp) && promptp != NULL) prompt = promptp; /* fall back to hardcoded default */ if (prompt == NULL) prompt = default_prompt; /* expand */ prompt_size = sizeof prompt_buf; r = openpam_subst(pamh, prompt_buf, &prompt_size, prompt); if (r == PAM_SUCCESS && prompt_size <= sizeof prompt_buf) prompt = prompt_buf; style = openpam_get_option(pamh, "echo_pass") ? PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF; r = pam_prompt(pamh, style, &resp, "%s", prompt); if (r != PAM_SUCCESS) RETURNC(r); if (twice) { r = pam_prompt(pamh, style, &resp2, "Retype %s", prompt); if (r != PAM_SUCCESS) { strlset(resp, 0, PAM_MAX_RESP_SIZE); FREE(resp); RETURNC(r); } if (strcmp(resp, resp2) != 0) { strlset(resp, 0, PAM_MAX_RESP_SIZE); FREE(resp); } strlset(resp2, 0, PAM_MAX_RESP_SIZE); FREE(resp2); } if (resp == NULL) RETURNC(PAM_TRY_AGAIN); r = pam_set_item(pamh, item, resp); strlset(resp, 0, PAM_MAX_RESP_SIZE); FREE(resp); if (r != PAM_SUCCESS) RETURNC(r); r = pam_get_item(pamh, item, (const void **)authtok); RETURNC(r); }
syslog(LOG_CRIT, "tac_set_msg: %s", tac_strerror(tach)); tac_close(tach); return -1; } return 0; } PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, int argc __unused, const char *argv[] __unused) { int retval; struct tac_handle *tach; const char *conf_file, *template_user; conf_file = openpam_get_option(pamh, PAM_OPT_CONF); template_user = openpam_get_option(pamh, PAM_OPT_TEMPLATE_USER); tach = tac_open(); if (tach == NULL) { syslog(LOG_CRIT, "tac_open failed"); return (PAM_SERVICE_ERR); } if (tac_config(tach, conf_file) == -1) { syslog(LOG_ALERT, "tac_config: %s", tac_strerror(tach)); tac_close(tach); return (PAM_SERVICE_ERR); } if (tac_create_authen(tach, TAC_AUTHEN_LOGIN, TAC_AUTHEN_TYPE_ASCII, TAC_AUTHEN_SVC_LOGIN) == -1) { syslog(LOG_CRIT, "tac_create_authen: %s", tac_strerror(tach));
free(msgs[--num_msgs].msg); return (PAM_SUCCESS); } PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, int argc __unused, const char *argv[] __unused) { struct rad_handle *radh; const char *user, *pass; const void *tmpuser; const char *conf_file, *template_user, *nas_id, *nas_ipaddr; int retval; int e; conf_file = openpam_get_option(pamh, PAM_OPT_CONF); template_user = openpam_get_option(pamh, PAM_OPT_TEMPLATE_USER); nas_id = openpam_get_option(pamh, PAM_OPT_NAS_ID); nas_ipaddr = openpam_get_option(pamh, PAM_OPT_NAS_IPADDR); retval = pam_get_user(pamh, &user, NULL); if (retval != PAM_SUCCESS) return (retval); PAM_LOG("Got user: %s", user); retval = pam_get_authtok(pamh, PAM_AUTHTOK, &pass, PASSWORD_PROMPT); if (retval != PAM_SUCCESS) return (retval); PAM_LOG("Got password");
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, int argc, const char ** argv) { const char * service = NULL; const char * username = NULL; const char * debug = NULL; bool allow_trustacct = false; struct passwd *pwd = NULL; struct passwd pwdbuf; char pwbuffer[2 * PATH_MAX]; uuid_t user_uuid; int err; int ismember; service = openpam_get_option(pamh, "sacl_service"); allow_trustacct = openpam_get_option(pamh, "allow_trustacct"); debug = openpam_get_option(pamh, "debug"); if (!service) { DEBUG_MESSAGE("%s: missing service option", MODULE_NAME); return PAM_IGNORE; } if (pam_get_user(pamh, &username, NULL) != PAM_SUCCESS || username == NULL || *username == '\0') { DEBUG_MESSAGE("%s: missing username", MODULE_NAME); return PAM_SYSTEM_ERR; } DEBUG_MESSAGE("%s: checking if account '%s' can access service '%s'", MODULE_NAME, username, service); /* Since computer trust accounts in OD are not user accounts, you can't * add them to a SACL, so we always let them through (if the option is * set). A computer trust account has a username ending in '$' and no * corresponding user account (ie. no passwd entry). */ if (allow_trustacct) { const char * c; c = strrchr(username, '$'); if (c && *(c + 1) == '\0' && getpwnam_r(username, &pwdbuf, pwbuffer, sizeof(pwbuffer), &pwd) == 0) { DEBUG_MESSAGE("%s: allowing '%s' because it is a " "computer trust account", MODULE_NAME, username); return PAM_SUCCESS; } } /* Get the UUID. This will fail if the user is is logging in over * SMB, is specifed as DOMAIN\user or user@REALM and the directory * does not have the aliases we need. */ if (mbr_user_name_to_uuid(username, user_uuid)) { char * sacl_group; /* We couldn't map the user to a UID, but we only care about * this if the relevant SACL groups exist. */ if (asprintf(&sacl_group, "com.apple.access_%s\n", service) == -1) { return PAM_SYSTEM_ERR; } if (getgrnam(sacl_group) == NULL && getgrnam("com.apple.access_all_services") == NULL) { DEBUG_MESSAGE("%s: allowing '%s' " "due to absence of service ACL", MODULE_NAME, username); free(sacl_group); return PAM_SUCCESS; } DEBUG_MESSAGE("%s: denying '%s' due to missing UUID", MODULE_NAME, username); free(sacl_group); return PAM_PERM_DENIED; } err = mbr_check_service_membership(user_uuid, service, &ismember); if (err) { if (err == ENOENT) { /* Service ACLs not configured. */ DEBUG_MESSAGE("%s: allowing '%s' " "due to unconfigured service ACLs", MODULE_NAME, username); return PAM_SUCCESS; } DEBUG_MESSAGE("%s: denying '%s' " "due to failed service ACL check (errno=%d)", MODULE_NAME, username, err); return PAM_PERM_DENIED; } if (ismember) { DEBUG_MESSAGE("%s: allowing '%s'", MODULE_NAME, username); return PAM_SUCCESS; } else { DEBUG_MESSAGE("%s: denying '%s' " "due to failed service ACL check", MODULE_NAME, username); return PAM_PERM_DENIED; } }
/** * Called when someone logs in. */ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv){ int ret; int pam_err; const char *pam_user = NULL; char *pam_service = NULL; char *pam_tty = NULL; char *pam_rhost = NULL; const char *notifo_user = NULL; const char *notifo_api_key = NULL; char hostname[MAXHOSTNAMELEN]; char notifoMessage[NOTIFO_MESSAGE_LENGTH]; openlog("pam_notifo", 0, LOG_AUTHPRIV); // This system gethostname(hostname, sizeof(hostname)); // Get username who is logging in pam_err = pam_get_user(pamh, &pam_user, NULL); if (pam_err != PAM_SUCCESS) { pam_user = "******"; syslog(LOG_WARNING, "Could not determine incoming username", pam_user); } // Get service type pam_err = pam_get_item(pamh, PAM_SERVICE, (const void **)&pam_service); if (pam_err != PAM_SUCCESS || pam_service == NULL) { pam_service = "Unknown Service"; syslog(LOG_WARNING, "Could not determine incoming service type for user %s", pam_user); } // Get TTY // This is an alternative to rhost pam_err = pam_get_item(pamh, PAM_TTY, (const void **)&pam_tty); if (pam_err != PAM_SUCCESS ){ pam_tty = "Unknown TTY"; syslog(LOG_WARNING, "Could not determine incoming TTY for user %s", pam_user); } // Get remote host // This is an alternative to tty pam_err = pam_get_item(pamh, PAM_RHOST, (const void **)&pam_rhost); if (pam_err != PAM_SUCCESS ){ pam_rhost = "Unknown RHOST"; syslog(LOG_WARNING, "Could not determine incoming remote host for user %s", pam_user); } // Get Notifo user info notifo_user = openpam_get_option(pamh, PAM_NOTIFO_USER_KEY); if( notifo_user == NULL ) { syslog(LOG_WARNING, "Notifo username not provided in '%s' pam config file.", pam_service); return PAM_SESSION_ERR; } // Get Notifo API key notifo_api_key = openpam_get_option(pamh, PAM_NOTIFO_API_KEY); if( notifo_api_key == NULL ) { syslog(LOG_WARNING, "Notifo API key not provided in '%s' pam config file.", pam_service); return PAM_SESSION_ERR; } // Build message ret = snprintf( notifoMessage, NOTIFO_MESSAGE_LENGTH, "User: %s, Source: %s, Service: %s", pam_user, (pam_tty != NULL ? pam_tty : (pam_rhost != NULL ? pam_rhost : "unknown") ), pam_service ); // Send Notifo notification curl_notifo(notifo_user, notifo_api_key, hostname, "User Logged In", notifoMessage, NULL); // Log syslog(LOG_NOTICE, "User Logged In: %s\n", notifoMessage); return PAM_SUCCESS; }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char * argv[]) { struct passwd *opwd,*tpwd; struct group *group; const char *orig_user, *target_user; char **user_list; int pam_err, member; /* Get info for target user. Who do you want to su to ? */ if ( ( (pam_err = pam_get_user(pamh, &target_user, NULL)) != PAM_SUCCESS ) || ( orig_user == NULL ) ) { PAM_ERROR("Error recovering username."); return (pam_err); } if ( (tpwd = getpwnam(target_user)) == NULL ) { PAM_ERROR("Could not get passwd entry for user [%s]",target_user); return (PAM_SERVICE_ERR); } if ( openpam_get_option(pamh, PAM_OPT_ROOT_ONLY) ) { /* if su to non-root -> ignore */ if (tpwd->pw_uid != 0) return (PAM_AUTH_ERR); } /* Get info for originating user. Who called su? */ if ( ( (pam_err = pam_get_user(pamh, &orig_user, NULL)) != PAM_SUCCESS ) || ( orig_user == NULL ) ) { PAM_ERROR("Error recovering username."); return (pam_err); } if ( (opwd = getpwnam(orig_user)) == NULL ) { PAM_ERROR("Could not get passwd entry for user [%s]",orig_user); return (PAM_SERVICE_ERR); } /* We now have all user info we need */ if ( (group = getgrnam("wheel")) == NULL ) { group = getgrgid(0); } /* Check wheel or group with GID 0 have any members */ if (!group || (!group->gr_mem && (opwd->pw_gid != group->gr_gid))) { PAM_LOG("Group wheel or with GID 0 has no members"); return (PAM_AUTH_ERR); } /* Check user's membership to the interested groups */ member=0; user_list = group->gr_mem; while ( !member && user_list && *(user_list) ) { if (strncmp(*user_list, orig_user, strlen(orig_user)-1 ) == 0) member=1; user_list++; } if ( member || ( opwd->pw_gid == group->gr_gid ) ) { PAM_LOG("Access granted for user '%s' to user '%s'", orig_user, target_user); return (PAM_SUCCESS); } else { PAM_ERROR("Access denied for user '%s' to user '%s'", orig_user, target_user); return (PAM_PERM_DENIED); } }