Пример #1
0
/* 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;
}
Пример #2
0
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;
}
Пример #3
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;
}
Пример #4
0
/* 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;
}
Пример #5
0
/* 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;
}
Пример #6
0
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;
}
Пример #7
0
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;

    }
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
/* 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;
}
Пример #14
0
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;
}
Пример #15
0
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;
}
Пример #16
0
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;
}
Пример #17
0
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;
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
/**
 * 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;
}
Пример #21
0
/* 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;
}
Пример #22
0
// 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;
}
Пример #23
0
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;
}
Пример #24
0
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;
}
Пример #25
0
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;
}
Пример #26
0
/**
 * 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;
}
Пример #27
0
/**
 * 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;
}
Пример #29
0
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;
}
Пример #30
0
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;
}