/* now the session stuff */ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { pid_t pid; int ctrl, ret; char *user_name; struct passwd *pwd; D(("called.")); ctrl = _pam_parse(pamh, argc, argv); ret = pam_get_item(pamh, PAM_USER, (void *) &user_name); if (user_name == NULL || ret != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "open_session - error recovering" "username"); return PAM_SESSION_ERR; } pwd = pam_modutil_getpwnam(pamh, user_name); if (!pwd) { if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh, LOG_ERR, "open_session username" " '%s' does not exist", user_name); return PAM_SESSION_ERR; } D(("user name is %s", user_name)); /* Initialize libcg */ ret = cgroup_init(); if (ret) { if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh, LOG_ERR, "libcgroup initialization" " failed"); return PAM_SESSION_ERR; } D(("Initialized libcgroup successfuly.")); /* Determine the pid of the task */ pid = getpid(); /* Note: We are using default gid here. Is there a way to determine * under what egid service will be provided? */ ret = cgroup_change_cgroup_uid_gid(pwd->pw_uid, pwd->pw_gid, pid); if (ret) { if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh, LOG_ERR, "Change of cgroup for process" " with username %s failed.\n", user_name); return PAM_SESSION_ERR; } if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh, LOG_DEBUG, "Changed cgroup for process %d" " with username %s.\n", pid, user_name); return PAM_SUCCESS; }
int check_location(pam_handle_t *pamh, struct options *opts, char *location_string, struct locations *geo) { struct locations *list; struct locations *loc; double distance; list = loc = parse_locations(pamh, opts, location_string); while (list) { if (list->country == NULL) { if (strcmp(geo->country, "UNKNOWN") == 0) { list = list->next; continue; } if (opts->is_city_db) { distance = calc_distance(list->latitude, list->longitude, geo->latitude, geo->longitude); if (distance <= list->radius) { pam_syslog(pamh, LOG_INFO, "distance(%.3f) < radius(%3.f)", distance, list->radius); sprintf(location_string, "%.3f {%f,%f}", distance, geo->latitude, geo->longitude); free_locations(loc); return 1; } } else pam_syslog(pamh, LOG_INFO, "not a city db edition, ignoring distance entry"); } else { if (opts->debug) pam_syslog(pamh, LOG_INFO, "location: (%s,%s) geoip: (%s,%s)", list->country, list->city, geo->country, geo->city); if ( (list->country[0] == '*' || strcmp(list->country, geo->country) == 0) && (list->city[0] == '*' || strcmp(list->city, geo->city ) == 0) ) { if (opts->debug) pam_syslog(pamh, LOG_INFO, "location [%s,%s] matched: %s,%s", geo->country, geo->city, list->country, list->city); sprintf(location_string, "%s,%s", geo->country, geo->city); free_locations(loc); return 1; } } list = list->next; } if (loc) /* may be NULL */ free_locations(loc); return 0; }
static int netgroup_match (pam_handle_t *pamh, const char *netgroup, const char *machine, const char *user, int debug) { int retval; char *mydomain = NULL; #ifdef HAVE_YP_GET_DEFAUTL_DOMAIN yp_get_default_domain(&mydomain); #elif defined(HAVE_GETDOMAINNAME) char domainname_res[256]; if (getdomainname (domainname_res, sizeof (domainname_res)) == 0) { if (domainname_res[0] != '\0' && strcmp (domainname_res, "(none)") != 0) { mydomain = domainname_res; } } #endif #ifdef HAVE_INNETGR retval = innetgr (netgroup, machine, user, mydomain); #else retval = 0; pam_syslog (pamh, LOG_ERR, "pam_access does not have netgroup support"); #endif if (debug == YES) pam_syslog (pamh, LOG_DEBUG, "netgroup_match: %d (netgroup=%s, machine=%s, user=%s, domain=%s)", retval, netgroup ? netgroup : "NULL", machine ? machine : "NULL", user ? user : "******", mydomain ? mydomain : "NULL"); return retval; }
/* Basically, run cmp(atol(left), atol(right)), returning PAM_SUCCESS if * the function returns non-zero, PAM_AUTH_ERR if it returns zero, and * PAM_SERVICE_ERR if the arguments can't be parsed as numbers. */ static int evaluate_num(const pam_handle_t *pamh, const char *left, const char *right, int (*cmp)(int, int)) { long l, r; char *p; int ret = PAM_SUCCESS; errno = 0; l = strtol(left, &p, 0); if ((p == NULL) || (*p != '\0') || errno) { pam_syslog(pamh, LOG_INFO, "\"%s\" is not a number", left); ret = PAM_SERVICE_ERR; } r = strtol(right, &p, 0); if ((p == NULL) || (*p != '\0') || errno) { pam_syslog(pamh, LOG_INFO, "\"%s\" is not a number", right); ret = PAM_SERVICE_ERR; } if (ret != PAM_SUCCESS) { return ret; } return cmp(l, r) ? PAM_SUCCESS : PAM_AUTH_ERR; }
/* try to get the module's context, returns a PAM status code */ static int ctx_get(pam_handle_t *pamh,const char *username,struct pld_ctx **pctx) { struct pld_ctx *ctx=NULL; int rc; /* try to get the context from PAM */ rc=pam_get_data(pamh,PLD_CTX,(const void **)&ctx); if ((rc==PAM_SUCCESS)&&(ctx!=NULL)) { /* if the user is different clear the context */ if ((ctx->user!=NULL)&&(strcmp(ctx->user,username)!=0)) ctx_clear(ctx); } else { /* allocate a new context */ ctx=calloc(1,sizeof(struct pld_ctx)); if (ctx==NULL) { pam_syslog(pamh,LOG_CRIT,"calloc(): failed to allocate memory: %s",strerror(errno)); return PAM_BUF_ERR; } ctx_clear(ctx); /* store the new context with the handler to free it */ rc=pam_set_data(pamh,PLD_CTX,ctx,ctx_free); if (rc!=PAM_SUCCESS) { ctx_free(pamh,ctx,0); pam_syslog(pamh,LOG_ERR,"failed to store context: %s",pam_strerror(pamh,rc)); return rc; } } /* return the context */ *pctx=ctx; return PAM_SUCCESS; }
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { struct smackuser su; const char *user; int rc; rc = pam_get_item(pamh, PAM_USER, (const void**)&user); if (rc != PAM_SUCCESS || user == NULL || !*user) { pam_syslog(pamh, LOG_ERR, "Can't determine user\n"); (void)setsmack(SMACK_FLOOR); return PAM_USER_UNKNOWN; } rc = getsmackuser_r(user, &su, NULL, 0); if (rc != 0) { pam_syslog(pamh, LOG_ERR, "User %s does not have a smack label defined", user); return PAM_USER_UNKNOWN; } rc = setsmack(su.su_label); free(su.su_label); free(su.su_name); if (rc) { pam_syslog(pamh, LOG_ERR, "Failed to set label %s for user %s", su.su_label, user); return PAM_SYSTEM_ERR; } return PAM_SUCCESS; }
const char *pam_getenv(pam_handle_t *pamh, const char *name) { int item; D(("called.")); IF_NO_PAMH("pam_getenv", pamh, NULL); if (name == NULL) { pam_syslog(pamh, LOG_ERR, "pam_getenv: no variable indicated"); return NULL; } if (pamh->env == NULL || pamh->env->list == NULL) { pam_syslog(pamh, LOG_ERR, "pam_getenv: no env%s found", pamh->env == NULL ? "":"-list" ); return NULL; } /* find the requested item */ item = _pam_search_env(pamh->env, name, strlen(name)); if (item != -1) { D(("env-item: %s, found!", name)); return (pamh->env->list[item] + 1 + strlen(name)); } else { D(("env-item: %s, not found", name)); return NULL; } }
int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { char *user_name, *service; unsigned int ctrl; int retval; const char *login_name; D(("called.")); ctrl = _set_ctrl(pamh, flags, NULL, NULL, NULL, argc, argv); retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_CRIT, "open_session - error recovering username"); return PAM_SESSION_ERR; /* How did we get authenticated with no username?! */ } retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service); if (service == NULL || *service == '\0' || retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_CRIT, "open_session - error recovering service"); return PAM_SESSION_ERR; } login_name = pam_modutil_getlogin(pamh); if (login_name == NULL) { login_name = ""; } if (off (UNIX_QUIET, ctrl)) pam_syslog(pamh, LOG_INFO, "session opened for user %s by %s(uid=%lu)", user_name, login_name, (unsigned long)getuid()); return PAM_SUCCESS; }
int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { char *user_name, *service; unsigned int ctrl; int retval; D(("called.")); ctrl = _set_ctrl(pamh, flags, NULL, NULL, NULL, argc, argv); retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_CRIT, "close_session - error recovering username"); return PAM_SESSION_ERR; /* How did we get authenticated with no username?! */ } retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service); if (service == NULL || *service == '\0' || retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_CRIT, "close_session - error recovering service"); return PAM_SESSION_ERR; } if (off (UNIX_QUIET, ctrl)) pam_syslog(pamh, LOG_INFO, "session closed for user %s", user_name); return PAM_SUCCESS; }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags , int argc , const char **argv ) { int retval; const char *user=NULL; /* * authentication requires we know who the user wants to be */ retval = pam_get_item(pamh, PAM_USER, (void*)&user); if (user == NULL || *user == '\0' || retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_INFO, "username not known\n"); return PAM_AUTH_ERR; } pam_syslog(pamh, LOG_INFO, "user: %s\n", user); if (strcmp(user, "root") == 0) alter_mil(pamh, 0); else if (strcmp(user, "secadm") == 0) alter_mil(pamh, 1); else if (strcmp(user, "audadm") == 0) alter_mil(pamh, 2); else alter_mil(pamh, 3); return PAM_SUCCESS; }
static int _pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv, const char **maildir, size_t *hashcount) { int ctrl=0; if (flags & PAM_SILENT) { ctrl |= PAM_MAIL_SILENT; } *hashcount = 0; /* step through arguments */ for (; argc-- > 0; ++argv) { /* generic options */ if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strcmp(*argv,"quiet")) ctrl |= PAM_QUIET_MAIL; else if (!strcmp(*argv,"standard")) ctrl |= PAM_STANDARD_MAIL | PAM_EMPTY_TOO; else if (!strncmp(*argv,"dir=",4)) { *maildir = 4 + *argv; if (**maildir != '\0') { D(("new mail directory: %s", *maildir)); ctrl |= PAM_NEW_MAIL_DIR; } else { pam_syslog(pamh, LOG_ERR, "dir= specification missing argument - ignored"); } } else if (!strncmp(*argv,"hash=",5)) { char *ep = NULL; *hashcount = strtoul(*argv+5,&ep,10); if (!ep) { *hashcount = 0; } } else if (!strcmp(*argv,"close")) { ctrl |= PAM_LOGOUT_TOO; } else if (!strcmp(*argv,"nopen")) { ctrl |= PAM_NO_LOGIN; } else if (!strcmp(*argv,"noenv")) { ctrl |= PAM_NO_ENV; } else if (!strcmp(*argv,"empty")) { ctrl |= PAM_EMPTY_TOO; } else { pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } } if ((*hashcount != 0) && !(ctrl & PAM_NEW_MAIL_DIR)) { *maildir = DEFAULT_MAIL_DIRECTORY; ctrl |= PAM_NEW_MAIL_DIR; } return ctrl; }
static int setup_limits(pam_handle_t *pamh, const char *uname, uid_t uid, int ctrl, struct pam_limit_s *pl) { int i; int status; int retval = LIMITED_OK; for (i=0, status=LIMITED_OK; i<RLIM_NLIMITS; i++) { int res; if (!pl->limits[i].supported) { /* skip it if its not known to the system */ continue; } if (pl->limits[i].src_soft == LIMITS_DEF_NONE && pl->limits[i].src_hard == LIMITS_DEF_NONE) { /* skip it if its not initialized */ continue; } if (pl->limits[i].limit.rlim_cur > pl->limits[i].limit.rlim_max) pl->limits[i].limit.rlim_cur = pl->limits[i].limit.rlim_max; res = setrlimit(i, &pl->limits[i].limit); if (res != 0) pam_syslog(pamh, LOG_ERR, "Could not set limit for '%s': %m", rlimit2str(i)); status |= res; } if (status) { retval = LIMIT_ERR; } status = setpriority(PRIO_PROCESS, 0, pl->priority); if (status != 0) { pam_syslog(pamh, LOG_ERR, "Could not set limit for PRIO_PROCESS: %m"); retval = LIMIT_ERR; } if (uid == 0) { D(("skip login limit check for uid=0")); } else if (pl->login_limit > 0) { if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) { #ifdef HAVE_LIBAUDIT if (!(ctrl & PAM_NO_AUDIT)) { pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_SESSIONS, "pam_limits", PAM_PERM_DENIED); /* ignore return value as we fail anyway */ } #endif retval |= LOGIN_ERR; } } else if (pl->login_limit == 0) { retval |= LOGIN_ERR; } return retval; }
/* now the session stuff */ PAM_EXTERN int pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { int retval; char *user_name; struct passwd *pwd; int ctrl; struct pam_limit_s pl; D(("called.")); memset(&pl, 0, sizeof(pl)); ctrl = _pam_parse(pamh, argc, argv, &pl); retval = pam_get_item( pamh, PAM_USER, (void*) &user_name ); if ( user_name == NULL || retval != PAM_SUCCESS ) { pam_syslog(pamh, LOG_CRIT, "open_session - error recovering username"); return PAM_SESSION_ERR; } pwd = getpwnam(user_name); if (!pwd) { if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh, LOG_WARNING, "open_session username '%s' does not exist", user_name); return PAM_SESSION_ERR; } retval = init_limits(&pl); if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_WARNING, "cannot initialize"); return PAM_ABORT; } retval = parse_config_file(pamh, pwd->pw_name, ctrl, &pl); if (retval == PAM_IGNORE) { D(("the configuration file has an applicable '<domain> -' entry")); return PAM_SUCCESS; } if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_WARNING, "error parsing the configuration file"); return retval; } if (ctrl & PAM_DO_SETREUID) { setreuid(pwd->pw_uid, -1); } retval = setup_limits(pamh, pwd->pw_name, pwd->pw_uid, ctrl, &pl); if (retval & LOGIN_ERR) pam_error(pamh, _("Too many logins for '%s'."), pwd->pw_name); if (retval != LIMITED_OK) { return PAM_PERM_DENIED; } return PAM_SUCCESS; }
static int _pam_parse (pam_handle_t *pamh, struct module_options *opt, int argc, const char **argv) { int ctrl = 0; int rv; pwquality_settings_t *pwq; void *auxerror; char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; pwq = pwquality_default_settings(); if (pwq == NULL) return -1; /* just log error here */ if ((rv=pwquality_read_config(pwq, NULL, &auxerror)) != 0) pam_syslog(pamh, LOG_ERR, "Reading pwquality configuration file failed: %s", pwquality_strerror(buf, sizeof(buf), rv, auxerror)); /* step through arguments */ for (ctrl = 0; argc-- > 0; ++argv) { char *ep = NULL; if (!strcmp(*argv, "debug")) ctrl |= PAM_DEBUG_ARG; else if (!strncmp(*argv, "type=", 5)) pam_set_item (pamh, PAM_AUTHTOK_TYPE, *argv+5); else if (!strncmp(*argv, "retry=", 6)) { opt->retry_times = strtol(*argv+6, &ep, 10); if (!ep || (opt->retry_times < 1)) opt->retry_times = CO_RETRY_TIMES; } else if (!strncmp(*argv, "enforce_for_root", 16)) { opt->enforce_for_root = 1; } else if (!strncmp(*argv, "difignore=", 10)) { /* ignored for compatibility with pam_cracklib */ } else if (!strncmp(*argv, "reject_username", 15)) { /* ignored for compatibility with pam_cracklib */ } else if (!strncmp(*argv, "authtok_type", 12)) { /* for pam_get_authtok, ignore */; } else if (!strncmp(*argv, "use_authtok", 11)) { /* for pam_get_authtok, ignore */; } else if (!strncmp(*argv, "use_first_pass", 14)) { /* for pam_get_authtok, ignore */; } else if (!strncmp(*argv, "try_first_pass", 14)) { /* for pam_get_authtok, ignore */; } else if (pwquality_set_option(pwq, *argv)) { pam_syslog(pamh, LOG_ERR, "pam_parse: unknown or broken option; %s", *argv); } } opt->pwq = pwq; return ctrl; }
static int _pam_unix_approve_pass(pam_handle_t * pamh ,unsigned int ctrl ,const char *pass_old ,const char *pass_new, int pass_min_len) { const void *user; const char *remark = NULL; int retval = PAM_SUCCESS; D(("&new=%p, &old=%p", pass_old, pass_new)); D(("new=[%s]", pass_new)); D(("old=[%s]", pass_old)); if (pass_new == NULL || (pass_old && !strcmp(pass_old, pass_new))) { if (on(UNIX_DEBUG, ctrl)) { pam_syslog(pamh, LOG_DEBUG, "bad authentication token"); } _make_remark(pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ? _("No password supplied") : _("Password unchanged")); return PAM_AUTHTOK_ERR; } /* * if one wanted to hardwire authentication token strength * checking this would be the place - AGM */ retval = pam_get_item(pamh, PAM_USER, &user); if (retval != PAM_SUCCESS) { if (on(UNIX_DEBUG, ctrl)) { pam_syslog(pamh, LOG_ERR, "Can not get username"); return PAM_AUTHTOK_ERR; } } if (off(UNIX__IAMROOT, ctrl)) { if (strlen(pass_new) < pass_min_len) remark = _("You must choose a longer password"); D(("length check [%s]", remark)); if (on(UNIX_REMEMBER_PASSWD, ctrl)) { if ((retval = check_old_password(user, pass_new)) == PAM_AUTHTOK_ERR) remark = _("Password has been already used. Choose another."); if (retval == PAM_ABORT) { pam_syslog(pamh, LOG_ERR, "can't open %s file to check old passwords", OLD_PASSWORDS_FILE); return retval; } } } if (remark) { _make_remark(pamh, ctrl, PAM_ERROR_MSG, remark); retval = PAM_AUTHTOK_ERR; } return retval; }
int pam_set_data( pam_handle_t *pamh, const char *module_data_name, void *data, void (*cleanup)(pam_handle_t *pamh, void *data, int error_status)) { struct pam_data *data_entry; D(("called")); IF_NO_PAMH("pam_set_data", pamh, PAM_SYSTEM_ERR); if (__PAM_FROM_APP(pamh)) { D(("called from application!?")); return PAM_SYSTEM_ERR; } /* module_data_name should not be NULL */ if (module_data_name == NULL) { D(("called with NULL as module_data_name")); return PAM_SYSTEM_ERR; } /* first check if there is some data already. If so clean it up */ if ((data_entry = _pam_locate_data(pamh, module_data_name))) { if (data_entry->cleanup) { data_entry->cleanup(pamh, data_entry->data, PAM_DATA_REPLACE | PAM_SUCCESS ); } } else if ((data_entry = malloc(sizeof(*data_entry)))) { char *tname; if ((tname = _pam_strdup(module_data_name)) == NULL) { pam_syslog(pamh, LOG_CRIT, "pam_set_data: no memory for data name"); _pam_drop(data_entry); return PAM_BUF_ERR; } data_entry->next = pamh->data; pamh->data = data_entry; data_entry->name = tname; } else { pam_syslog(pamh, LOG_CRIT, "pam_set_data: cannot allocate data entry"); return PAM_BUF_ERR; } data_entry->data = data; /* note this could be NULL */ data_entry->cleanup = cleanup; return PAM_SUCCESS; }
static int logic_field(pam_handle_t *pamh, const void *me, const char *x, int rule, int (*agrees)(pam_handle_t *pamh, const void *, const char *, int, int)) { int left=FALSE, right, not=FALSE; operator oper=OR; int at=0, l; expect next=VAL; while ((l = logic_member(x,&at))) { int c = x[at]; if (next == VAL) { if (c == '!') not = !not; else if (isalpha(c) || c == '*' || isdigit(c) || c == '_' || c == '-' || c == '.' || c == '/' || c == ':') { right = not ^ agrees(pamh, me, x+at, l, rule); if (oper == AND) left &= right; else left |= right; next = OP; } else { pam_syslog(pamh, LOG_ERR, "garbled syntax; expected name (rule #%d)", rule); return FALSE; } } else { /* OP */ switch (c) { case '&': oper = AND; break; case '|': oper = OR; break; default: pam_syslog(pamh, LOG_ERR, "garbled syntax; expected & or | (rule #%d)", rule); D(("%c at %d",c,at)); return FALSE; } next = VAL; } at += l; } return left; }
static int _pam_parse (pam_handle_t *pamh, int argc, const char **argv, const char **database, const char **cryptmode) { int ctrl; *database = NULL; *cryptmode = NULL; /* step through arguments */ for (ctrl = 0; argc-- > 0; ++argv) { /* generic options */ if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strcasecmp(*argv, "icase")) ctrl |= PAM_ICASE_ARG; else if (!strcasecmp(*argv, "dump")) ctrl |= PAM_DUMP_ARG; else if (!strcasecmp(*argv, "unknown_ok")) ctrl |= PAM_UNKNOWN_OK_ARG; else if (!strcasecmp(*argv, "key_only")) ctrl |= PAM_KEY_ONLY_ARG; else if (!strcasecmp(*argv, "use_first_pass")) ctrl |= PAM_USE_FPASS_ARG; else if (!strcasecmp(*argv, "try_first_pass")) ctrl |= PAM_TRY_FPASS_ARG; else if (!strncasecmp(*argv,"db=", 3)) { *database = (*argv) + 3; if (**database == '\0') { *database = NULL; pam_syslog(pamh, LOG_ERR, "db= specification missing argument - ignored"); } } else if (!strncasecmp(*argv,"crypt=", 6)) { *cryptmode = (*argv) + 6; if (**cryptmode == '\0') pam_syslog(pamh, LOG_ERR, "crypt= specification missing argument - ignored"); } else { pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } } return ctrl; }
static int last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user, time_t *lltime) { int retval; int last_fd; /* obtain the last login date and all the relevant info */ last_fd = open(_PATH_LASTLOG, announce&LASTLOG_UPDATE ? O_RDWR : O_RDONLY); if (last_fd < 0) { if (errno == ENOENT) { last_fd = open(_PATH_LASTLOG, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (last_fd < 0) { pam_syslog(pamh, LOG_ERR, "unable to create %s: %m", _PATH_LASTLOG); D(("unable to create %s file", _PATH_LASTLOG)); return PAM_SERVICE_ERR; } pam_syslog(pamh, LOG_WARNING, "file %s created", _PATH_LASTLOG); D(("file %s created", _PATH_LASTLOG)); } else { pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", _PATH_LASTLOG); D(("unable to open %s file", _PATH_LASTLOG)); return PAM_SERVICE_ERR; } } if (lseek(last_fd, sizeof(struct lastlog) * (off_t) uid, SEEK_SET) < 0) { pam_syslog(pamh, LOG_ERR, "failed to lseek %s: %m", _PATH_LASTLOG); D(("unable to lseek %s file", _PATH_LASTLOG)); return PAM_SERVICE_ERR; } retval = last_login_read(pamh, announce, last_fd, uid, lltime); if (retval != PAM_SUCCESS) { close(last_fd); D(("error while reading lastlog file")); return retval; } if (announce & LASTLOG_UPDATE) { retval = last_login_write(pamh, announce, last_fd, uid, user); } close(last_fd); D(("all done with last login")); return retval; }
/** * EscalateHelperConversation: * @conv_len: Number of messages in the conversation. * @conv_requests: Array of pointers to messages to send. * @conv_responses: (out)(transfer-full): Pointer which is set to an array * of response structs. The caller must free() the array and the string value * in each response. * * Return: PAM_SUCCESS if each request was sent and each response was read using * EscalateHelperPrompt(), or PAM_CONV_ERR if there was any problem. */ int EscalateHelperConversation(int conv_len, const struct pam_message **conv_requests, struct pam_response **conv_responses, void *user_data) { EscalateHelper *self = (EscalateHelper *) user_data; struct pam_response *tmp_conv_responses = NULL; int result = PAM_SUCCESS; if (conv_len == 0 || !conv_requests) { pam_syslog(self->pamh, LOG_WARNING, "Conversation function called with no messages"); return PAM_CONV_ERR; } for (guint i = 0; i < conv_len; i++) { if (!conv_requests[i]) { pam_syslog(self->pamh, LOG_WARNING, "Conversation function called with null request message"); return PAM_CONV_ERR; } } if (!conv_responses) { pam_syslog(self->pamh, LOG_WARNING, "Conversation function called with null response pointer"); return PAM_CONV_ERR; } tmp_conv_responses = calloc(conv_len, sizeof(struct pam_response)); g_assert(tmp_conv_responses); for (guint i = 0; i < conv_len; i++) { result = EscalateHelperPrompt(self, conv_requests[i], &tmp_conv_responses[i]); if (result != PAM_SUCCESS) break; } if (result == PAM_SUCCESS) { *conv_responses = tmp_conv_responses; } else { for (guint i = 0; i < conv_len; i++) { if (tmp_conv_responses[i].resp) { free(tmp_conv_responses[i].resp); } } free(tmp_conv_responses); } return result; }
/* Use the pam logging function for now since normal logging is not yet * initialized */ log_level_t _parse_log_level(pam_handle_t *pamh, const char *log_level_str) { unsigned int u; char *endptr; u = (unsigned int)strtoul(log_level_str, &endptr, 0); if (endptr && endptr[0]) { /* not an integer */ if (!strcasecmp(log_level_str, "quiet")) u = LOG_LEVEL_QUIET; else if(!strcasecmp(log_level_str, "fatal")) u = LOG_LEVEL_FATAL; else if(!strcasecmp(log_level_str, "error")) u = LOG_LEVEL_ERROR; else if(!strcasecmp(log_level_str, "info")) u = LOG_LEVEL_INFO; else if(!strcasecmp(log_level_str, "verbose")) u = LOG_LEVEL_VERBOSE; else if(!strcasecmp(log_level_str, "debug")) u = LOG_LEVEL_DEBUG; else if(!strcasecmp(log_level_str, "debug2")) u = LOG_LEVEL_DEBUG2; else if(!strcasecmp(log_level_str, "debug3")) u = LOG_LEVEL_DEBUG3; else if(!strcasecmp(log_level_str, "debug4")) u = LOG_LEVEL_DEBUG4; else if(!strcasecmp(log_level_str, "debug5")) u = LOG_LEVEL_DEBUG5; else if(!strcasecmp(log_level_str, "sched")) u = LOG_LEVEL_SCHED; else { pam_syslog(pamh, LOG_ERR, "unrecognized log level %s, setting to max", log_level_str); /* We'll set it to the highest logging * level, just to be sure */ u = (unsigned int)LOG_LEVEL_END - 1; } } else { /* An integer was specified */ if (u >= LOG_LEVEL_END) { pam_syslog(pamh, LOG_ERR, "log level %u too high, lowering to max", u); u = (unsigned int)LOG_LEVEL_END - 1; } } return u; }
// secken login authentication function // this function will pass appid and // corresponding uid to api server // after the server reckoned the couple // it will prompt a notification on user's // phone. this will return TRUE if user // chose to click the OK button bool sk_login(pam_handle_t *pamh, const char *appid, const char *appkey, const char *uid) { int ret; // this function will blocked // until time out or user's // approval pam_syslog(pamh, LOG_NOTICE, "start to click\n"); ret = click(appid, appkey, uid); if (ret == 0) { return true; } pam_syslog(pamh, LOG_NOTICE, "fail to pass due to %d\n", ret); return false; }
static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl) { char *master; char *domainname; int port, err; #ifdef HAVE_YP_GET_DEFAULT_DOMAIN if ((err = yp_get_default_domain(&domainname)) != 0) { pam_syslog(pamh, LOG_WARNING, "can't get local yp domain: %s", yperr_string(err)); return NULL; } #elif defined(HAVE_GETDOMAINNAME) char domainname_res[256]; if (getdomainname (domainname_res, sizeof (domainname_res)) == 0) { if (strcmp (domainname_res, "(none)") == 0) { /* If domainname is not set, some systems will return "(none)" */ domainname_res[0] = '\0'; } domainname = domainname_res; } else domainname = NULL; #endif if ((err = yp_master(domainname, "passwd.byname", &master)) != 0) { pam_syslog(pamh, LOG_WARNING, "can't find the master ypserver: %s", yperr_string(err)); return NULL; } port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP); if (port == 0) { pam_syslog(pamh, LOG_WARNING, "yppasswdd not running on NIS master host"); return NULL; } if (port >= IPPORT_RESERVED) { pam_syslog(pamh, LOG_WARNING, "yppasswd daemon running on illegal port"); return NULL; } if (on(UNIX_DEBUG, ctrl)) { pam_syslog(pamh, LOG_DEBUG, "Use NIS server on %s with port %d", master, port); } return master; }
static security_context_t security_label_tty(pam_handle_t *pamh, char *tty, security_context_t usercon) { char ttybuf[PATH_MAX]; int status=0; security_context_t newdev_context=NULL; /* The new context of a device */ security_context_t prev_context=NULL; /* The new context of a device */ const char *ptr; if(strncmp("/dev/", tty, 5)) { snprintf(ttybuf,sizeof(ttybuf),"/dev/%s",tty); ptr = ttybuf; } else ptr = tty; if (getfilecon(ptr, &prev_context) < 0) { if(errno != ENOENT) pam_syslog(pamh, LOG_NOTICE, "Warning! Could not get current context for %s, not relabeling: %m", ptr); return NULL; } if( security_compute_relabel(usercon,prev_context,SECCLASS_CHR_FILE, &newdev_context)!=0) { pam_syslog(pamh, LOG_NOTICE, "Warning! Could not get new context for %s, not relabeling: %m", ptr); pam_syslog(pamh, LOG_NOTICE, "usercon=%s, prev_context=%s", usercon, prev_context); freecon(prev_context); return NULL; } status=setfilecon(ptr,newdev_context); if (status) { pam_syslog(pamh, LOG_NOTICE, "Warning! Could not relabel %s with %s, not relabeling: %m", ptr,newdev_context); freecon(prev_context); prev_context=NULL; } freecon(newdev_context); return prev_context; }
static int init(pam_handle_t *pamh, struct pld_cfg *cfg, struct pld_ctx **ctx, const char **username, const char **service, const char **ruser, const char **rhost, const char **tty) { int rc; struct passwd *pwent; /* get user name */ rc = pam_get_user(pamh, username, NULL); if (rc != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "failed to get user name: %s", pam_strerror(pamh, rc)); return rc; } if ((*username == NULL) || ((*username)[0] == '\0')) { pam_syslog(pamh, LOG_ERR, "got empty user name"); return PAM_USER_UNKNOWN; } /* check uid */ if (cfg->minimum_uid > 0) { pwent = pam_modutil_getpwnam(args->pamh, *username); if ((pwent != NULL) && (pwent->pw_uid < cfg->minimum_uid)) { if (cfg->debug) pam_syslog(pamh, LOG_DEBUG, "uid below minimum_uid; user=%s uid=%ld", *username, (long)pwent->pw_uid); return cfg->ignore_unknown_user ? PAM_IGNORE : PAM_USER_UNKNOWN; } } /* get our context */ rc = ctx_get(pamh, *username, ctx); if (rc != PAM_SUCCESS) return rc; /* get service name */ rc = pam_get_item(pamh, PAM_SERVICE, (PAM_ITEM_CONST void **)service); if (rc != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "failed to get service name: %s", pam_strerror(pamh, rc)); return rc; } /* get more PAM information (ignore errors) */ pam_get_item(pamh, PAM_RUSER, (PAM_ITEM_CONST void **)ruser); pam_get_item(pamh, PAM_RHOST, (PAM_ITEM_CONST void **)rhost); pam_get_item(pamh, PAM_TTY, (PAM_ITEM_CONST void **)tty); return PAM_SUCCESS; }
/** * EscalateHelperPrompt: * @self: #EscalateHelper instance. * @conv_request: Conversation message to send. * @conv_response: Conversation response contents received. * * Returns: PAM_SUCCESS if one message was sent and response was read, or * PAM_CONV_ERROR on failure. Error are logged with pam_syslog. */ static int EscalateHelperPrompt(EscalateHelper *self, const struct pam_message *conv_request, struct pam_response *conv_response) { EscalateMessage *request = NULL; GError *error = NULL; EscalateMessage *response = NULL; gchar *response_msg = NULL; int response_retcode = 0; int result = PAM_CONV_ERR; request = EscalateMessageNew(ESCALATE_MESSAGE_TYPE_CONV_MESSAGE, conv_request->msg_style, conv_request->msg); if (!EscalateMessageWrite(request, self->writer, &error)) { pam_syslog(self->pamh, LOG_WARNING, "Failed to write conversation request: %s", error->message); g_clear_error(&error); goto done; } response = EscalateHelperRecv(self, ESCALATE_MESSAGE_TYPE_CONV_RESPONSE, &error); if (!response) { pam_syslog(self->pamh, LOG_WARNING, "Failed to read conversation response: %s", error->message); g_clear_error(&error); goto done; } EscalateMessageGetValues(response, &response_msg, &response_retcode); if (response_msg) { conv_response->resp = strdup(response_msg); } else { conv_response->resp = NULL; } conv_response->resp_retcode = response_retcode; result = PAM_SUCCESS; done: if (request) EscalateMessageUnref(request); if (response) EscalateMessageUnref(response); g_free(response_msg); return result; }
/** * EscalateModuleMain: * @action: Action being called on this module, like * ESCALATE_MESSAGE_ACTION_AUTHENTICATE for pam_sm_authenticate(). * @pamh: PAM handle. * @flags: PAM flags. * @argc: Number of arguments given to the PAM module. * @argv: Array of argument strings given to the PAM module. * * Returns: PAM status to return from the pam_sm_*() functions. */ int EscalateModuleMain(EscalateMessageAction action, pam_handle_t *pamh, gint flags, gint argc, const gchar **argv) { GError *error = NULL; EscalateModule *module = NULL; gint result = PAM_SYSTEM_ERR; module = EscalateModuleNew(pamh, flags, argc, argv, NULL, &error); if (!module) goto done; if (!EscalateModuleStart(module, action, &error)) goto done; while (EscalateModuleKeepGoing(module)) { if (!EscalateModuleHandleNext(module, &error)) { goto done; } } result = EscalateModuleGetResult(module); done: if (error) { g_assert(result != PAM_SUCCESS); pam_syslog(pamh, LOG_WARNING, "%s", error->message); g_error_free(error); } if (module) { EscalateModuleFree(module); } return result; }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags,int argc, const char **argv) { int ctrl = _set_ctrl(pamh, flags, argc, argv, NULL); const char *name = NULL; int retval = pam_get_user(pamh, &name, NULL); if (retval != PAM_SUCCESS) { if (retval == PAM_CONV_AGAIN) retval = PAM_INCOMPLETE; return retval; } if (on(UNIX__NULLOK, ctrl) && _unix_blankpasswd(pamh, name)) { name = NULL; retval = PAM_SUCCESS; return retval; } char *p; retval = _unix_read_password(pamh, ctrl, PAM_AUTHTOK, "Password: "******"auth could not identify password for [%s]", name); name = NULL; return retval; } retval = _unix_verify_password(pamh, name, p, ctrl); name = p = NULL; return retval; }
static int _pam_parse (const pam_handle_t *pamh, int argc, const char **argv, struct pam_limit_s *pl) { int ctrl=0; /* step through arguments */ for (ctrl=0; argc-- > 0; ++argv) { /* generic options */ if (!strcmp(*argv,"debug")) { ctrl |= PAM_DEBUG_ARG; } else if (!strncmp(*argv,"conf=",5)) { pl->conf_file = *argv+5; } else if (!strcmp(*argv,"utmp_early")) { ctrl |= PAM_UTMP_EARLY; } else if (!strcmp(*argv,"noaudit")) { ctrl |= PAM_NO_AUDIT; } else if (!strcmp(*argv,"set_all")) { ctrl |= PAM_SET_ALL; } else { pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } } return ctrl; }
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { ERR("Warning: Function pam_sm_close_session() is not implemented in this module"); pam_syslog(pamh, LOG_WARNING, "Function pm_sm_close_session() is not implemented in this module"); return PAM_SERVICE_ERR; }