Пример #1
0
static int
match_cfg_line_group(const char *grps, int line, const char *user)
{
	int result = 0;
	struct passwd *pw;

	if (user == NULL)
		goto out;

	if ((pw = getpwnam(user)) == NULL) {
		debug("Can't match group at line %d because user %.100s does "
		    "not exist", line, user);
	} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
		debug("Can't Match group because user %.100s not in any group "
		    "at line %d", user, line);
	} else if (ga_match_pattern_list(grps) != 1) {
		debug("user %.100s does not match group list %.100s at line %d",
		    user, grps, line);
	} else {
		debug("user %.100s matched group list %.100s at line %d", user,
		    grps, line);
		result = 1;
	}
out:
	ga_free();
	return result;
}
Пример #2
0
/*
 * Initialize group access list for user with primary (base) and
 * supplementary groups.  Return the number of groups in the list.
 */
int
ga_init(const char *user, gid_t base)
{
	gid_t *groups_bygid;
	int i, j;
	struct group *gr;

	if (ngroups > 0)
		ga_free();

	ngroups = NGROUPS_MAX;
#if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
	ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX));
#endif

	groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid));
	groups_byname = xcalloc(ngroups, sizeof(*groups_byname));

	if (getgrouplist(user, base, groups_bygid, &ngroups) == -1)
		logit("getgrouplist: groups list too small");
	for (i = 0, j = 0; i < ngroups; i++)
		if ((gr = getgrgid(groups_bygid[i])) != NULL)
			groups_byname[j++] = xstrdup(gr->gr_name);
	xfree(groups_bygid);
	return (ngroups = j);
}
Пример #3
0
int
duo_check_groups(struct passwd *pw, char **groups, int groups_cnt)
{
    int i;

    if (groups_cnt > 0) {
        int matched = 0;

        if (ga_init(pw->pw_name, pw->pw_gid) < 0) {
            duo_log(LOG_ERR, "Couldn't get groups",
                pw->pw_name, NULL, strerror(errno));
            return (-1);
        }
        for (i = 0; i < groups_cnt; i++) {
            if (ga_match_pattern_list(groups[i])) {
                matched = 1;
                break;
            }
        }
        ga_free();

        /* User in configured groups for Duo auth? */
        return matched;
    } else {
        return 1;
    }
}
Пример #4
0
void FATR 
ga_antisymmetrize_(Integer *g_a) {
  
  DoublePrecision alpha = 0.5;
  int i, me = GA_Nodeid();
  extern void * FATR ga_malloc(Integer nelem, int type, char *name);
  extern void FATR ga_free(void *ptr);
  void FATR gai_subtr(int *lo, int *hi, void *a, void *b, DoublePrecision alpha,
                      int type, Integer nelem, int ndim);

  int alo[GA_MAX_DIM], ahi[GA_MAX_DIM], lda[GA_MAX_DIM];
  int blo[GA_MAX_DIM], bhi[GA_MAX_DIM], ldb[GA_MAX_DIM];
  int ndim, dims[GA_MAX_DIM], type;
  Integer nelem=1;
  Logical have_data;
  void *a_ptr, *b_ptr;

  GA_Sync();


  
  NGA_Inquire((int)(*g_a), &type, &ndim, dims);
  
  if (dims[0] != dims[1]) 
    GA_Error("ga_sym: can only sym square matrix", 0L);
  
  /* Find the local distribution */
  NGA_Distribution((int)(*g_a), me, alo, ahi);
 
 
  have_data = ahi[0]>=0;
  for(i=1; i<ndim; i++) have_data = have_data && ahi[i]>=0;
  
  if(have_data) {
    NGA_Access((int)(*g_a), alo, ahi, &a_ptr, lda); 
    
    for(i=0; i<ndim; i++) nelem *= ahi[i]-alo[i] +1;
    b_ptr = (void *) ga_malloc(nelem, MT_C_DBL, "v");
    
    for(i=2; i<ndim; i++) {bhi[i]=ahi[i]; blo[i]=alo[i]; }
    
    /* switch rows and cols */
    blo[1]=alo[0];
    bhi[1]=ahi[0];
    blo[0]=alo[1];
    bhi[0]=ahi[1];

    for (i=0; i < ndim-1; i++) 
      ldb[i] = bhi[i+1] - blo[i+1] + 1; 
    NGA_Get((int)(*g_a), blo, bhi, b_ptr, ldb);
  }
  GA_Sync(); 

  if(have_data) {
    gai_subtr(alo, ahi, a_ptr, b_ptr, alpha, type, nelem, ndim);
    NGA_Release_update((int)(*g_a), alo, ahi);
    ga_free(b_ptr);
  }
  GA_Sync();
}
Пример #5
0
/*
 * Initialize group access list for user with primary (base) and
 * supplementary groups.  Return the number of groups in the list.
 */
int
ga_init(const char *user, gid_t base)
{
	gid_t groups_bygid[NGROUPS_MAX + 1];
	int i, j;
	struct group *gr;

	if (ngroups > 0)
		ga_free();

	ngroups = sizeof(groups_bygid) / sizeof(gid_t);
	if (getgrouplist(user, base, groups_bygid, &ngroups) == -1)
		logit("getgrouplist: groups list too small");
	for (i = 0, j = 0; i < ngroups; i++)
		if ((gr = getgrgid(groups_bygid[i])) != NULL)
			groups_byname[j++] = xstrdup(gr->gr_name);
	return (ngroups = j);
}
Пример #6
0
/*
 * Check if the user is allowed to log in via ssh. If user is listed
 * in DenyUsers or one of user's groups is listed in DenyGroups, false
 * will be returned. If AllowUsers isn't empty and user isn't listed
 * there, or if AllowGroups isn't empty and one of user's groups isn't
 * listed there, false will be returned.
 * If the user's shell is not executable, false will be returned.
 * Otherwise true is returned.
 */
int
allowed_user(struct passwd * pw)
{
#ifdef HAVE_LOGIN_CAP
	extern login_cap_t *lc;
	int match_name, match_ip;
	char *cap_hlist, *hp;
#endif
	struct ssh *ssh = active_state; /* XXX */
	struct stat st;
	const char *hostname = NULL, *ipaddr = NULL;
	int r;
	u_int i;

	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
	if (!pw || !pw->pw_name)
		return 0;

#ifdef HAVE_LOGIN_CAP
	hostname = auth_get_canonical_hostname(ssh, options.use_dns);
	ipaddr = ssh_remote_ipaddr(ssh);

	lc = login_getclass(pw->pw_class);

	/*
	 * Check the deny list.
	 */
	cap_hlist = login_getcapstr(lc, "host.deny", NULL, NULL);
	if (cap_hlist != NULL) {
		hp = strtok(cap_hlist, ",");
		while (hp != NULL) {
			match_name = match_hostname(hostname, hp);
			match_ip = match_hostname(ipaddr, hp);
			/*
			 * Only a positive match here causes a "deny".
			 */
			if (match_name > 0 || match_ip > 0) {
				free(cap_hlist);
				login_close(lc);
				return 0;
			}
			hp = strtok(NULL, ",");
		}
		free(cap_hlist);
	}

	/*
	 * Check the allow list.  If the allow list exists, and the
	 * remote host is not in it, the user is implicitly denied.
	 */
	cap_hlist = login_getcapstr(lc, "host.allow", NULL, NULL);
	if (cap_hlist != NULL) {
		hp = strtok(cap_hlist, ",");
		if (hp == NULL) {
			/* Just in case there's an empty string... */
			free(cap_hlist);
			login_close(lc);
			return 0;
		}
		while (hp != NULL) {
			match_name = match_hostname(hostname, hp);
			match_ip = match_hostname(ipaddr, hp);
			/*
			 * Negative match causes an immediate "deny".
			 * Positive match causes us to break out
			 * of the loop (allowing a fallthrough).
			 */
			if (match_name < 0 || match_ip < 0) {
				free(cap_hlist);
				login_close(lc);
				return 0;
			}
			if (match_name > 0 || match_ip > 0)
				break;
			hp = strtok(NULL, ",");
		}
		free(cap_hlist);
		if (hp == NULL) {
			login_close(lc);
			return 0;
		}
	}

	login_close(lc);
#endif

#ifdef USE_PAM
	if (!options.use_pam) {
#endif
	/*
	 * password/account expiration.
	 */
	if (pw->pw_change || pw->pw_expire) {
		struct timeval tv;

		(void)gettimeofday(&tv, (struct timezone *)NULL);
		if (pw->pw_expire) {
			if (tv.tv_sec >= pw->pw_expire) {
				logit("User %.100s not allowed because account has expired",
				    pw->pw_name);
				return 0;	/* expired */
			}
		}
#ifdef _PASSWORD_CHGNOW
		if (pw->pw_change == _PASSWORD_CHGNOW) {
			logit("User %.100s not allowed because password needs to be changed",
			    pw->pw_name);

			return 0;	/* can't force password change (yet) */
		}
#endif
		if (pw->pw_change) {
			if (tv.tv_sec >= pw->pw_change) {
				logit("User %.100s not allowed because password has expired",
				    pw->pw_name);
				return 0;	/* expired */
			}
		}
	}
#ifdef USE_PAM
	}
#endif

	/*
	 * Deny if shell does not exist or is not executable unless we
	 * are chrooting.
	 */
	/*
	 * XXX Should check to see if it is executable by the
	 * XXX requesting user.  --thorpej
	 */
	if (options.chroot_directory == NULL ||
	    strcasecmp(options.chroot_directory, "none") == 0) {
		char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
		    _PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */

		if (stat(shell, &st) != 0) {
			logit("User %.100s not allowed because shell %.100s "
			    "does not exist", pw->pw_name, shell);
			free(shell);
			return 0;
		}
		if (S_ISREG(st.st_mode) == 0 ||
		    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
			logit("User %.100s not allowed because shell %.100s "
			    "is not executable", pw->pw_name, shell);
			free(shell);
			return 0;
		}
		free(shell);
	}
	/*
	 * XXX Consider nuking {Allow,Deny}{Users,Groups}.  We have the
	 * XXX login_cap(3) mechanism which covers all other types of
	 * XXX logins, too.
	 */

	if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
	    options.num_deny_groups > 0 || options.num_allow_groups > 0) {
		hostname = auth_get_canonical_hostname(ssh, options.use_dns);
		ipaddr = ssh_remote_ipaddr(ssh);
	}

	/* Return false if user is listed in DenyUsers */
	if (options.num_deny_users > 0) {
		for (i = 0; i < options.num_deny_users; i++) {
			r = match_user(pw->pw_name, hostname, ipaddr,
			    options.deny_users[i]);
			if (r < 0) {
				fatal("Invalid DenyUsers pattern \"%.100s\"",
				    options.deny_users[i]);
			} else if (r != 0) {
				logit("User %.100s from %.100s not allowed "
				    "because listed in DenyUsers",
				    pw->pw_name, hostname);
				return 0;
			}
		}
	}
	/* Return false if AllowUsers isn't empty and user isn't listed there */
	if (options.num_allow_users > 0) {
		for (i = 0; i < options.num_allow_users; i++) {
			r = match_user(pw->pw_name, hostname, ipaddr,
			    options.allow_users[i]);
			if (r < 0) {
				fatal("Invalid AllowUsers pattern \"%.100s\"",
				    options.allow_users[i]);
			} else if (r == 1)
				break;
		}
		/* i < options.num_allow_users iff we break for loop */
		if (i >= options.num_allow_users) {
			logit("User %.100s from %.100s not allowed because "
			    "not listed in AllowUsers", pw->pw_name, hostname);
			return 0;
		}
	}
	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
		/* Get the user's group access list (primary and supplementary) */
		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
			logit("User %.100s from %.100s not allowed because "
			    "not in any group", pw->pw_name, hostname);
			return 0;
		}

		/* Return false if one of user's groups is listed in DenyGroups */
		if (options.num_deny_groups > 0)
			if (ga_match(options.deny_groups,
			    options.num_deny_groups)) {
				ga_free();
				logit("User %.100s from %.100s not allowed "
				    "because a group is listed in DenyGroups",
				    pw->pw_name, hostname);
				return 0;
			}
		/*
		 * Return false if AllowGroups isn't empty and one of user's groups
		 * isn't listed there
		 */
		if (options.num_allow_groups > 0)
			if (!ga_match(options.allow_groups,
			    options.num_allow_groups)) {
				ga_free();
				logit("User %.100s from %.100s not allowed "
				    "because none of user's groups are listed "
				    "in AllowGroups", pw->pw_name, hostname);
				return 0;
			}
		ga_free();
	}
	/* We found no reason not to let this user try to log on... */
	return 1;
}
Пример #7
0
/*
 * Check if the user is allowed to log in via ssh. If user is listed
 * in DenyUsers or one of user's groups is listed in DenyGroups, false
 * will be returned. If AllowUsers isn't empty and user isn't listed
 * there, or if AllowGroups isn't empty and one of user's groups isn't
 * listed there, false will be returned.
 * If the user's shell is not executable, false will be returned.
 * Otherwise true is returned.
 */
int
allowed_user(struct passwd * pw)
{
	struct stat st;
	const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
	u_int i;
#ifdef USE_SHADOW
	struct spwd *spw = NULL;
#endif

	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
	if (!pw || !pw->pw_name)
		return 0;

#ifdef USE_SHADOW
	if (!options.use_pam)
		spw = getspnam(pw->pw_name);
#ifdef HAS_SHADOW_EXPIRE
	if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw))
		return 0;
#endif /* HAS_SHADOW_EXPIRE */
#endif /* USE_SHADOW */

	/* grab passwd field for locked account check */
	passwd = pw->pw_passwd;
#ifdef USE_SHADOW
	if (spw != NULL)
#ifdef USE_LIBIAF
		passwd = get_iaf_password(pw);
#else
		passwd = spw->sp_pwdp;
#endif /* USE_LIBIAF */
#endif

	/* check for locked account */
	if (!options.use_pam && passwd && *passwd) {
		int locked = 0;

#ifdef LOCKED_PASSWD_STRING
		if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
			 locked = 1;
#endif
#ifdef LOCKED_PASSWD_PREFIX
		if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
		    strlen(LOCKED_PASSWD_PREFIX)) == 0)
			 locked = 1;
#endif
#ifdef LOCKED_PASSWD_SUBSTR
		if (strstr(passwd, LOCKED_PASSWD_SUBSTR))
			locked = 1;
#endif
#ifdef USE_LIBIAF
		free((void *) passwd);
#endif /* USE_LIBIAF */
		if (locked) {
			logit("User %.100s not allowed because account is locked",
			    pw->pw_name);
			return 0;
		}
	}

	/*
	 * Deny if shell does not exist or is not executable unless we
	 * are chrooting.
	 */
	if (options.chroot_directory == NULL ||
	    strcasecmp(options.chroot_directory, "none") == 0) {
		char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
		    _PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */

		if (stat(shell, &st) != 0) {
			logit("User %.100s not allowed because shell %.100s "
			    "does not exist", pw->pw_name, shell);
			xfree(shell);
			return 0;
		}
		if (S_ISREG(st.st_mode) == 0 ||
		    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
			logit("User %.100s not allowed because shell %.100s "
			    "is not executable", pw->pw_name, shell);
			xfree(shell);
			return 0;
		}
		xfree(shell);
	}

	if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
	    options.num_deny_groups > 0 || options.num_allow_groups > 0) {
		hostname = get_canonical_hostname(options.use_dns);
		ipaddr = get_remote_ipaddr();
	}

	/* Return false if user is listed in DenyUsers */
	if (options.num_deny_users > 0) {
		for (i = 0; i < options.num_deny_users; i++)
			if (match_user(pw->pw_name, hostname, ipaddr,
			    options.deny_users[i])) {
				logit("User %.100s from %.100s not allowed "
				    "because listed in DenyUsers",
				    pw->pw_name, hostname);
				return 0;
			}
	}
	/* Return false if AllowUsers isn't empty and user isn't listed there */
	if (options.num_allow_users > 0) {
		for (i = 0; i < options.num_allow_users; i++)
			if (match_user(pw->pw_name, hostname, ipaddr,
			    options.allow_users[i]))
				break;
		/* i < options.num_allow_users iff we break for loop */
		if (i >= options.num_allow_users) {
			logit("User %.100s from %.100s not allowed because "
			    "not listed in AllowUsers", pw->pw_name, hostname);
			return 0;
		}
	}
	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
		/* Get the user's group access list (primary and supplementary) */
		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
			logit("User %.100s from %.100s not allowed because "
			    "not in any group", pw->pw_name, hostname);
			return 0;
		}

		/* Return false if one of user's groups is listed in DenyGroups */
		if (options.num_deny_groups > 0)
			if (ga_match(options.deny_groups,
			    options.num_deny_groups)) {
				ga_free();
				logit("User %.100s from %.100s not allowed "
				    "because a group is listed in DenyGroups",
				    pw->pw_name, hostname);
				return 0;
			}
		/*
		 * Return false if AllowGroups isn't empty and one of user's groups
		 * isn't listed there
		 */
		if (options.num_allow_groups > 0)
			if (!ga_match(options.allow_groups,
			    options.num_allow_groups)) {
				ga_free();
				logit("User %.100s from %.100s not allowed "
				    "because none of user's groups are listed "
				    "in AllowGroups", pw->pw_name, hostname);
				return 0;
			}
		ga_free();
	}

#ifdef CUSTOM_SYS_AUTH_ALLOWED_USER
	if (!sys_auth_allowed_user(pw, &loginmsg))
		return 0;
#endif

	/* We found no reason not to let this user try to log on... */
	return 1;
}
Пример #8
0
void FATR 
ga_symmetrize_(Integer *g_a) {
  
  DoublePrecision alpha = 0.5;
  Integer i, me = ga_nodeid_();
  Integer alo[GA_MAX_DIM], ahi[GA_MAX_DIM], lda[GA_MAX_DIM], nelem=1;
  Integer blo[GA_MAX_DIM], bhi[GA_MAX_DIM], ldb[GA_MAX_DIM];
  Integer ndim, dims[GA_MAX_DIM], type;
  Logical have_data;
  Integer g_b; /* temporary global array (b = A') */
  Integer num_blocks_a;
  Void *a_ptr, *b_ptr;
  int local_sync_begin,local_sync_end;
  char *tempB = "A_transpose";

  local_sync_begin = _ga_sync_begin; local_sync_end = _ga_sync_end;
  _ga_sync_begin = 1; _ga_sync_end=1; /*remove any previous masking*/
  if(local_sync_begin)ga_sync_();

  GA_PUSH_NAME("ga_symmetrize");
  
  num_blocks_a = ga_total_blocks_(g_a);

  nga_inquire_internal_(g_a, &type, &ndim, dims);

  if (type != C_DBL)
    ga_error("ga_symmetrize: only implemented for double precision",0);

  if (num_blocks_a < 0) {

    if (dims[ndim-1] != dims[ndim-2]) 
      ga_error("ga_sym: can only sym square matrix", 0L);

    /* Find the local distribution */
    nga_distribution_(g_a, &me, alo, ahi);


    have_data = ahi[0]>0;
    for(i=1; i<ndim; i++) have_data = have_data && ahi[i]>0;

    if(have_data) {
      nga_access_ptr(g_a, alo, ahi, &a_ptr, lda); 

      for(i=0; i<ndim; i++) nelem *= ahi[i]-alo[i] +1;
      b_ptr = (Void *) ga_malloc(nelem, MT_F_DBL, "v");

      for(i=0; i<ndim-2; i++) {bhi[i]=ahi[i]; blo[i]=alo[i]; }

      /* switch rows and cols */
      blo[ndim-1]=alo[ndim-2];
      bhi[ndim-1]=ahi[ndim-2];
      blo[ndim-2]=alo[ndim-1];
      bhi[ndim-2]=ahi[ndim-1];

      for (i=0; i < ndim-1; i++) 
        ldb[i] = bhi[i] - blo[i] + 1; 
      nga_get_(g_a, blo, bhi, b_ptr, ldb);
    }
    ga_sync_(); 

    if(have_data) {
      gai_add(alo, ahi, a_ptr, b_ptr, alpha, type, nelem, ndim);
      nga_release_update_(g_a, alo, ahi);
      ga_free(b_ptr);
    }
  } else {
    /* For block-cyclic data, probably most efficient solution is to
       create duplicate copy, transpose it and add the results together */
    DoublePrecision half = 0.5;
    if (!ga_duplicate(g_a, &g_b, tempB))
      ga_error("ga_symmetrize: duplicate failed", 0L);
    ga_transpose_(g_a, &g_b);
    ga_add_(&half, g_a, &half, &g_b, g_a);
    ga_destroy_(&g_b);
  }
  GA_POP_NAME;
  if(local_sync_end)ga_sync_();
}
Пример #9
0
/*
 * Check if the user is allowed to log in via ssh. If user is listed
 * in DenyUsers or one of user's groups is listed in DenyGroups, false
 * will be returned. If AllowUsers isn't empty and user isn't listed
 * there, or if AllowGroups isn't empty and one of user's groups isn't
 * listed there, false will be returned.
 * If the user's shell is not executable, false will be returned.
 * Otherwise true is returned.
 */
int
allowed_user(struct passwd * pw)
{
	struct stat st;
	const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
	char *shell;
	int i;
#ifdef USE_SHADOW
	struct spwd *spw = NULL;
#endif

	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
	if (!pw || !pw->pw_name)
		return 0;

#ifdef USE_SHADOW
	if (!options.use_pam)
		spw = getspnam(pw->pw_name);
#ifdef HAS_SHADOW_EXPIRE
	if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw))
		return 0;
#endif /* HAS_SHADOW_EXPIRE */
#endif /* USE_SHADOW */

	/* grab passwd field for locked account check */
#ifdef USE_SHADOW
	if (spw != NULL)
		passwd = spw->sp_pwdp;
#else
	passwd = pw->pw_passwd;
#endif

	/* check for locked account */
	if (!options.use_pam && passwd && *passwd) {
		int locked = 0;

#ifdef LOCKED_PASSWD_STRING
		if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
			 locked = 1;
#endif
#ifdef LOCKED_PASSWD_PREFIX
		if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
		    strlen(LOCKED_PASSWD_PREFIX)) == 0)
			 locked = 1;
#endif
#ifdef LOCKED_PASSWD_SUBSTR
		if (strstr(passwd, LOCKED_PASSWD_SUBSTR))
			locked = 1;
#endif
		if (locked) {
			logit("User %.100s not allowed because account is locked",
			    pw->pw_name);
			return 0;
		}
	}

	/*
	 * Get the shell from the password data.  An empty shell field is
	 * legal, and means /bin/sh.
	 */
	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;

	/* deny if shell does not exists or is not executable */
	if (stat(shell, &st) != 0) {
		logit("User %.100s not allowed because shell %.100s does not exist",
		    pw->pw_name, shell);
		return 0;
	}
	if (S_ISREG(st.st_mode) == 0 ||
	    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
		logit("User %.100s not allowed because shell %.100s is not executable",
		    pw->pw_name, shell);
		return 0;
	}

	if (options.num_deny_users > 0 || options.num_allow_users > 0) {
		hostname = get_canonical_hostname(options.use_dns);
		ipaddr = get_remote_ipaddr();
	}

	/* Return false if user is listed in DenyUsers */
	if (options.num_deny_users > 0) {
		for (i = 0; i < options.num_deny_users; i++)
			if (match_user(pw->pw_name, hostname, ipaddr,
			    options.deny_users[i])) {
				logit("User %.100s not allowed because listed in DenyUsers",
				    pw->pw_name);
				return 0;
			}
	}
	/* Return false if AllowUsers isn't empty and user isn't listed there */
	if (options.num_allow_users > 0) {
		for (i = 0; i < options.num_allow_users; i++)
			if (match_user(pw->pw_name, hostname, ipaddr,
			    options.allow_users[i]))
				break;
		/* i < options.num_allow_users iff we break for loop */
		if (i >= options.num_allow_users) {
			logit("User %.100s not allowed because not listed in AllowUsers",
			    pw->pw_name);
			return 0;
		}
	}
	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
		/* Get the user's group access list (primary and supplementary) */
		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
			logit("User %.100s not allowed because not in any group",
			    pw->pw_name);
			return 0;
		}

		/* Return false if one of user's groups is listed in DenyGroups */
		if (options.num_deny_groups > 0)
			if (ga_match(options.deny_groups,
			    options.num_deny_groups)) {
				ga_free();
				logit("User %.100s not allowed because a group is listed in DenyGroups",
				    pw->pw_name);
				return 0;
			}
		/*
		 * Return false if AllowGroups isn't empty and one of user's groups
		 * isn't listed there
		 */
		if (options.num_allow_groups > 0)
			if (!ga_match(options.allow_groups,
			    options.num_allow_groups)) {
				ga_free();
				logit("User %.100s not allowed because none of user's groups are listed in AllowGroups",
				    pw->pw_name);
				return 0;
			}
		ga_free();
	}

#ifdef WITH_AIXAUTHENTICATE
	/*
	 * Don't check loginrestrictions() for root account (use
	 * PermitRootLogin to control logins via ssh), or if running as
	 * non-root user (since loginrestrictions will always fail).
	 */
	if ((pw->pw_uid != 0) && (geteuid() == 0)) {
		char *msg;

		if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg) != 0) {
			int loginrestrict_errno = errno;

			if (msg && *msg) {
				buffer_append(&loginmsg, msg, strlen(msg));
				aix_remove_embedded_newlines(msg);
				logit("Login restricted for %s: %.100s",
				    pw->pw_name, msg);
			}
			/* Don't fail if /etc/nologin  set */
			if (!(loginrestrict_errno == EPERM &&
			    stat(_PATH_NOLOGIN, &st) == 0))
				return 0;
		}
	}
#endif /* WITH_AIXAUTHENTICATE */

	/* We found no reason not to let this user try to log on... */
	return 1;
}
Пример #10
0
/*
 * Check if the user is allowed to log in via ssh. If user is listed
 * in DenyUsers or one of user's groups is listed in DenyGroups, false
 * will be returned. If AllowUsers isn't empty and user isn't listed
 * there, or if AllowGroups isn't empty and one of user's groups isn't
 * listed there, false will be returned.
 * If the user's shell is not executable, false will be returned.
 * Otherwise true is returned.
 */
int
allowed_user(struct passwd * pw)
{
	struct stat st;
	const char *hostname = NULL, *ipaddr = NULL;
	char *shell;
	int i;
#ifdef WITH_AIXAUTHENTICATE
	char *loginmsg;
#endif /* WITH_AIXAUTHENTICATE */
#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
	!defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
	struct spwd *spw;

	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
	if (!pw || !pw->pw_name)
		return 0;

#define	DAY		(24L * 60 * 60) /* 1 day in seconds */
	spw = getspnam(pw->pw_name);
	if (spw != NULL) {
		time_t today = time(NULL) / DAY;
		debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
		    " sp_max %d", (int)today, (int)spw->sp_expire,
		    (int)spw->sp_lstchg, (int)spw->sp_max);

		/*
		 * We assume account and password expiration occurs the
		 * day after the day specified.
		 */
		if (spw->sp_expire != -1 && today > spw->sp_expire) {
			log("Account %.100s has expired", pw->pw_name);
			return 0;
		}

		if (spw->sp_lstchg == 0) {
			log("User %.100s password has expired (root forced)",
			    pw->pw_name);
			return 0;
		}

		if (spw->sp_max != -1 &&
		    today > spw->sp_lstchg + spw->sp_max) {
			log("User %.100s password has expired (password aged)",
			    pw->pw_name);
			return 0;
		}
	}
#else
	/* Shouldn't be called if pw is NULL, but better safe than sorry... */
	if (!pw || !pw->pw_name)
		return 0;
#endif

	/*
	 * Get the shell from the password data.  An empty shell field is
	 * legal, and means /bin/sh.
	 */
	shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;

	/* deny if shell does not exists or is not executable */
	if (stat(shell, &st) != 0) {
		log("User %.100s not allowed because shell %.100s does not exist",
		    pw->pw_name, shell);
		return 0;
	}
	if (S_ISREG(st.st_mode) == 0 ||
	    (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
		log("User %.100s not allowed because shell %.100s is not executable",
		    pw->pw_name, shell);
		return 0;
	}

	if (options.num_deny_users > 0 || options.num_allow_users > 0) {
		hostname = get_canonical_hostname(options.verify_reverse_mapping);
		ipaddr = get_remote_ipaddr();
	}

	/* Return false if user is listed in DenyUsers */
	if (options.num_deny_users > 0) {
		for (i = 0; i < options.num_deny_users; i++)
			if (match_user(pw->pw_name, hostname, ipaddr,
			    options.deny_users[i])) {
				log("User %.100s not allowed because listed in DenyUsers",
				    pw->pw_name);
				return 0;
			}
	}
	/* Return false if AllowUsers isn't empty and user isn't listed there */
	if (options.num_allow_users > 0) {
		for (i = 0; i < options.num_allow_users; i++)
			if (match_user(pw->pw_name, hostname, ipaddr,
			    options.allow_users[i]))
				break;
		/* i < options.num_allow_users iff we break for loop */
		if (i >= options.num_allow_users) {
			log("User %.100s not allowed because not listed in AllowUsers",
			    pw->pw_name);
			return 0;
		}
	}
	if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
		/* Get the user's group access list (primary and supplementary) */
		if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
			log("User %.100s not allowed because not in any group",
			    pw->pw_name);
			return 0;
		}

		/* Return false if one of user's groups is listed in DenyGroups */
		if (options.num_deny_groups > 0)
			if (ga_match(options.deny_groups,
			    options.num_deny_groups)) {
				ga_free();
				log("User %.100s not allowed because a group is listed in DenyGroups",
				    pw->pw_name);
				return 0;
			}
		/*
		 * Return false if AllowGroups isn't empty and one of user's groups
		 * isn't listed there
		 */
		if (options.num_allow_groups > 0)
			if (!ga_match(options.allow_groups,
			    options.num_allow_groups)) {
				ga_free();
				log("User %.100s not allowed because none of user's groups are listed in AllowGroups",
				    pw->pw_name);
				return 0;
			}
		ga_free();
	}

#ifdef WITH_AIXAUTHENTICATE
	if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) {
		if (loginmsg && *loginmsg) {
			/* Remove embedded newlines (if any) */
			char *p;
			for (p = loginmsg; *p; p++) {
				if (*p == '\n')
					*p = ' ';
			}
			/* Remove trailing newline */
			*--p = '\0';
			log("Login restricted for %s: %.100s", pw->pw_name, loginmsg);
		}
		return 0;
	}
#endif /* WITH_AIXAUTHENTICATE */

	/* We found no reason not to let this user try to log on... */
	return 1;
}
Пример #11
0
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int pam_flags,
    int argc, const char *argv[])
{
	struct duo_config cfg;
	struct passwd *pw;
	duo_t *duo;
	duo_code_t code;
	duopam_const char *config, *cmd, *ip, *p, *service, *user;
	int i, flags, pam_err;

	memset(&cfg, 0, sizeof(cfg));
        cfg.failmode = DUO_FAIL_SAFE;

	/* Parse configuration */
	config = DUO_CONF;
	for (i = 0; i < argc; i++) {
		if (strncmp("conf=", argv[i], 5) == 0) {
			config = argv[i] + 5;
		} else if (strcmp("debug", argv[i]) == 0) {
			options |= PAM_OPT_DEBUG;
		} else if (strcmp("try_first_pass", argv[i]) == 0) {
			options |= PAM_OPT_TRY_FIRST_PASS;
		} else if (strcmp("use_first_pass", argv[i]) == 0) {
			options |= PAM_OPT_USE_FIRST_PASS|PAM_OPT_TRY_FIRST_PASS;
		} else if (strcmp("use_uid", argv[i]) == 0) {
			options |= PAM_OPT_USE_UID;
		} else if (strcmp("push", argv[i]) == 0) {
			options |= PAM_OPT_PUSH;
		} else {
			_syslog(LOG_ERR, "Invalid pam_duo option: '%s'",
			    argv[i]);
			return (PAM_SERVICE_ERR);
		}
	}
	i = duo_parse_config(config, __ini_handler, &cfg);
	if (i == -2) {
		_syslog(LOG_ERR, "%s must be readable only by user 'root'",
		    config);
		return (PAM_SERVICE_ERR);
	} else if (i == -1) {
		_syslog(LOG_ERR, "Couldn't open %s: %s",
		    config, strerror(errno));
		return (PAM_SERVICE_ERR);
	} else if (i > 0) {
		_syslog(LOG_ERR, "Parse error in %s, line %d", config, i);
		return (PAM_SERVICE_ERR);
	} else if (!cfg.host || !cfg.host[0] ||
            !cfg.skey || !cfg.skey[0] || !cfg.ikey || !cfg.ikey[0]) {
		_syslog(LOG_ERR, "Missing host, ikey, or skey in %s", config);
		return (PAM_SERVICE_ERR);
	}
        
        /* Check user */
        if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS ||
            (pw = getpwnam(user)) == NULL) {
                return (PAM_USER_UNKNOWN);
        }
        /* XXX - Service-specific behavior */
	flags = 0;
        cmd = NULL;
	if (pam_get_item(pamh, PAM_SERVICE, (duopam_const void **)
		(duopam_const void *)&service) != PAM_SUCCESS) {
                return (PAM_SERVICE_ERR);
        }
	if (options & PAM_OPT_USE_UID) {
                /* Check calling user for Duo auth, just like sudo */
                if ((pw = getpwuid(getuid())) == NULL) {
                        return (PAM_USER_UNKNOWN);
                }
                user = pw->pw_name;
	}

        if (strcmp(service, "sshd") == 0) {
                /*
                 * Disable incremental status reporting for sshd :-(
                 * OpenSSH accumulates PAM_TEXT_INFO from modules to send in
                 * an SSH_MSG_USERAUTH_BANNER post-auth, not real-time!
                 */
                flags |= DUO_FLAG_SYNC;
        } else if (strcmp(service, "sudo") == 0) {
                cmd = getenv("SUDO_COMMAND");
        }
	/* Check group membership */
	if (cfg.groups_cnt > 0) {
		int matched = 0;

		if (ga_init(pw->pw_name, pw->pw_gid) < 0) {
			_log(LOG_ERR, "Couldn't get groups",
			    pw->pw_name, NULL, strerror(errno));
			return (PAM_SERVICE_ERR);
		}
		for (i = 0; i < cfg.groups_cnt; i++) {
			if (ga_match_pattern_list(cfg.groups[i])) {
				matched = 1;
				break;
			}
		}
		ga_free();

		/* User in configured groups for Duo auth? */
		if (!matched)
			return (PAM_SUCCESS);
	}

	ip = NULL;
	pam_get_item(pamh, PAM_RHOST,
	    (duopam_const void **)(duopam_const void *)&ip);

	/* Honor configured http_proxy */
	if (cfg.http_proxy != NULL) {
		setenv("http_proxy", cfg.http_proxy, 1);
	}

	/* Try Duo auth */
	if ((duo = duo_open(cfg.host, cfg.ikey, cfg.skey,
                    "pam_duo/" PACKAGE_VERSION,
                    cfg.noverify ? "" : cfg.cafile)) == NULL) {
		_log(LOG_ERR, "Couldn't open Duo API handle", user, ip, NULL);
		return (PAM_SERVICE_ERR);
	}
	duo_set_conv_funcs(duo, __duo_prompt, __duo_status, pamh);

	pam_err = PAM_SERVICE_ERR;
	
	for (i = 0; i < MAX_RETRIES; i++) {
		code = duo_login(duo, user, ip, flags,
                    cfg.pushinfo ? cmd : NULL);
		if (code == DUO_FAIL) {
			_log(LOG_WARNING, "Failed Duo login",
			    user, ip, duo_geterr(duo));
			if ((flags & DUO_FLAG_SYNC) == 0) {
				pam_info(pamh, "%s", "");
                        }
			/* Keep going */
			continue;
		}
		/* Terminal conditions */
		if (code == DUO_OK) {
			if ((p = duo_geterr(duo)) != NULL) {
				_log(LOG_WARNING, "Skipped Duo login",
				    user, ip, p);
			} else {
				_log(LOG_INFO, "Successful Duo login",
				    user, ip, NULL);
			}
			pam_err = PAM_SUCCESS;
		} else if (code == DUO_ABORT) {
			_log(LOG_WARNING, "Aborted Duo login",
			    user, ip, duo_geterr(duo));
			pam_err = PAM_ABORT;
		} else if (cfg.failmode == DUO_FAIL_SAFE &&
                    (code == DUO_CONN_ERROR ||
                     code == DUO_CLIENT_ERROR || code == DUO_SERVER_ERROR)) {
			_log(LOG_WARNING, "Failsafe Duo login",
			    user, ip, duo_geterr(duo));
			pam_err = PAM_SUCCESS;
		} else {
			_log(LOG_ERR, "Error in Duo login",
			    user, ip, duo_geterr(duo));
			pam_err = PAM_SERVICE_ERR;
		}
		break;
	}
	if (i == MAX_RETRIES) {
		pam_err = PAM_MAXTRIES;
	}
	duo_close(duo);
	
	return (pam_err);
}