login_ok.c revision 26694
121288Sdavidn/*-
221288Sdavidn * Copyright (c) 1996 by
321288Sdavidn * David Nugent <davidn@blaze.net.au>
421288Sdavidn * All rights reserved.
521288Sdavidn *
621288Sdavidn * Redistribution and use in source and binary forms, with or without
721288Sdavidn * modification, is permitted provided that the following conditions
821288Sdavidn * are met:
921288Sdavidn * 1. Redistributions of source code must retain the above copyright
1021288Sdavidn *    notice immediately at the beginning of the file, without modification,
1121288Sdavidn *    this list of conditions, and the following disclaimer.
1221288Sdavidn * 2. Redistributions in binary form must reproduce the above copyright
1321288Sdavidn *    notice, this list of conditions and the following disclaimer in the
1421288Sdavidn *    documentation and/or other materials provided with the distribution.
1521288Sdavidn * 3. This work was done expressly for inclusion into FreeBSD.  Other use
1621288Sdavidn *    is permitted provided this notation is included.
1721288Sdavidn * 4. Absolutely no warranty of function or purpose is made by the authors.
1821288Sdavidn * 5. Modifications may be freely made to this file providing the above
1921288Sdavidn *    conditions are met.
2021288Sdavidn *
2121288Sdavidn * Support allow/deny lists in login class capabilities
2221288Sdavidn *
2326694Sdavidn *	$Id: login_ok.c,v 1.4 1997/05/10 18:55:38 davidn Exp $
2421288Sdavidn */
2521288Sdavidn
2621288Sdavidn#include <stdio.h>
2721288Sdavidn#include <stdlib.h>
2821288Sdavidn#include <string.h>
2921288Sdavidn#include <errno.h>
3021288Sdavidn#include <unistd.h>
3121288Sdavidn#include <ttyent.h>
3221288Sdavidn#include <fnmatch.h>
3321288Sdavidn
3421288Sdavidn#include <sys/types.h>
3521288Sdavidn#include <sys/time.h>
3621288Sdavidn#include <sys/resource.h>
3721288Sdavidn#include <sys/param.h>
3821288Sdavidn#include <login_cap.h>
3921288Sdavidn
4021288Sdavidn
4121288Sdavidn/* -- support functions -- */
4221288Sdavidn
4325670Sdavidn/*
4425670Sdavidn * login_strinlist()
4521288Sdavidn * This function is intentionally public - reused by TAS.
4621288Sdavidn * Returns TRUE (non-zero) if a string matches a pattern
4721288Sdavidn * in a given array of patterns. 'flags' is passed directly
4821288Sdavidn * to fnmatch(3).
4921288Sdavidn */
5021288Sdavidn
5121288Sdavidnint
5221288Sdavidnlogin_strinlist(char **list, char const *str, int flags)
5321288Sdavidn{
5425670Sdavidn    int rc = 0;
5521288Sdavidn
5625670Sdavidn    if (str != NULL && *str != '\0') {
5725670Sdavidn	int	i = 0;
5825670Sdavidn
5925670Sdavidn	while (rc == 0 && list[i] != NULL)
6026694Sdavidn	    rc = fnmatch(list[i++], str, flags) == 0;
6125670Sdavidn    }
6225670Sdavidn    return rc;
6321288Sdavidn}
6421288Sdavidn
6521288Sdavidn
6625670Sdavidn/*
6725670Sdavidn * login_str2inlist()
6821288Sdavidn * Locate either or two strings in a given list
6921288Sdavidn */
7021288Sdavidn
7121288Sdavidnint
7221288Sdavidnlogin_str2inlist(char **ttlst, const char *str1, const char *str2, int flags)
7321288Sdavidn{
7425670Sdavidn    int	    rc = 0;
7521288Sdavidn
7625670Sdavidn    if (login_strinlist(ttlst, str1, flags))
7725670Sdavidn	rc = 1;
7825670Sdavidn    else if (login_strinlist(ttlst, str2, flags))
7925670Sdavidn	rc = 1;
8025670Sdavidn    return rc;
8121288Sdavidn}
8221288Sdavidn
8321288Sdavidn
8425670Sdavidn/*
8525670Sdavidn * login_timelist()
8621288Sdavidn * This function is intentinoally public - reused by TAS.
8721288Sdavidn * Returns an allocated list of time periods given an array
8821288Sdavidn * of time periods in ascii form.
8921288Sdavidn */
9021288Sdavidn
9121288Sdavidnlogin_time_t *
9225670Sdavidnlogin_timelist(login_cap_t *lc, char const *cap, int *ltno,
9325670Sdavidn	       login_time_t **ltptr)
9421288Sdavidn{
9525670Sdavidn    int			j = 0;
9625670Sdavidn    struct login_time	*lt = NULL;
9725670Sdavidn    char		**tl;
9821288Sdavidn
9925670Sdavidn    if ((tl = login_getcaplist(lc, cap, NULL)) != NULL) {
10025670Sdavidn
10125670Sdavidn	while (tl[j++] != NULL)
10225670Sdavidn	    ;
10325670Sdavidn	if (*ltno >= j)
10425670Sdavidn	    lt = *ltptr;
10525670Sdavidn	else if ((lt = realloc(*ltptr, j)) != NULL) {
10625670Sdavidn	    *ltno = j;
10725670Sdavidn	    *ltptr = lt;
10825670Sdavidn	}
10925670Sdavidn	if (lt != NULL) {
11025670Sdavidn	    int	    i = 0;
11125670Sdavidn
11225670Sdavidn	    for (--j; i < j; i++)
11325670Sdavidn		lt[i] = parse_lt(tl[i]);
11425670Sdavidn	    lt[i].lt_dow = LTM_NONE;
11525670Sdavidn	}
11621288Sdavidn    }
11725670Sdavidn    return lt;
11821288Sdavidn}
11921288Sdavidn
12021288Sdavidn
12125670Sdavidn/*
12225670Sdavidn * login_ttyok()
12321288Sdavidn * This function is a variation of auth_ttyok(), but it checks two
12421288Sdavidn * arbitrary capability lists not necessarily related to access.
12521288Sdavidn * This hook is provided for the accounted/exclude accounting lists.
12621288Sdavidn */
12721288Sdavidn
12821288Sdavidnint
12925670Sdavidnlogin_ttyok(login_cap_t *lc, const char *tty, const char *allowcap,
13025670Sdavidn	    const char *denycap)
13121288Sdavidn{
13225670Sdavidn    int	    rc = 1;
13321288Sdavidn
13425670Sdavidn    if (lc != NULL && tty != NULL && *tty != '\0') {
13525670Sdavidn	struct ttyent	*te;
13625670Sdavidn	char		*grp;
13725670Sdavidn	char		**ttl;
13821288Sdavidn
13925670Sdavidn	te = getttynam(tty);  /* Need group name */
14025670Sdavidn	grp = te ? te->ty_group : NULL;
14125670Sdavidn	ttl = login_getcaplist(lc, allowcap, NULL);
14225670Sdavidn
14325670Sdavidn	if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0))
14425670Sdavidn	    rc = 0;	/* tty or ttygroup not in allow list */
14525670Sdavidn	else {
14625670Sdavidn
14725670Sdavidn	    ttl = login_getcaplist(lc, denycap, NULL);
14825670Sdavidn	    if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0))
14925670Sdavidn		rc = 0; /* tty or ttygroup in deny list */
15025670Sdavidn	}
15121288Sdavidn    }
15225670Sdavidn
15325670Sdavidn    return rc;
15421288Sdavidn}
15521288Sdavidn
15621288Sdavidn
15725670Sdavidn/*
15825670Sdavidn * auth_ttyok()
15921288Sdavidn * Determine whether or not login on a tty is accessible for
16021288Sdavidn * a login class
16121288Sdavidn */
16221288Sdavidn
16321288Sdavidnint
16421288Sdavidnauth_ttyok(login_cap_t *lc, const char * tty)
16521288Sdavidn{
16625670Sdavidn    return login_ttyok(lc, tty, "ttys.allow", "ttys.deny");
16721288Sdavidn}
16821288Sdavidn
16921288Sdavidn
17025670Sdavidn/*
17125670Sdavidn * login_hostok()
17221288Sdavidn * This function is a variation of auth_hostok(), but it checks two
17321288Sdavidn * arbitrary capability lists not necessarily related to access.
17421288Sdavidn * This hook is provided for the accounted/exclude accounting lists.
17521288Sdavidn */
17621288Sdavidn
17721288Sdavidnint
17825670Sdavidnlogin_hostok(login_cap_t *lc, const char *host, const char *ip,
17925670Sdavidn	     const char *allowcap, const char *denycap)
18021288Sdavidn{
18125670Sdavidn    int	    rc = 1; /* Default is ok */
18221288Sdavidn
18325670Sdavidn    if (lc != NULL &&
18425670Sdavidn	((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0'))) {
18525670Sdavidn	char	**hl;
18621288Sdavidn
18725670Sdavidn	hl = login_getcaplist(lc, allowcap, NULL);
18825670Sdavidn	if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD))
18925670Sdavidn	    rc = 0;	/* host or IP not in allow list */
19025670Sdavidn	else {
19125670Sdavidn
19225670Sdavidn	    hl = login_getcaplist(lc, "host.deny", NULL);
19325670Sdavidn	    if (hl != NULL && login_str2inlist(hl, host, ip, FNM_CASEFOLD))
19425670Sdavidn		rc = 0; /* host or IP in deny list */
19525670Sdavidn	}
19621288Sdavidn    }
19725670Sdavidn
19825670Sdavidn    return rc;
19921288Sdavidn}
20021288Sdavidn
20121288Sdavidn
20225670Sdavidn/*
20325670Sdavidn * auth_hostok()
20421288Sdavidn * Determine whether or not login from a host is ok
20521288Sdavidn */
20621288Sdavidn
20721288Sdavidnint
20821288Sdavidnauth_hostok(login_cap_t *lc, const char *host, const char *ip)
20921288Sdavidn{
21025670Sdavidn    return login_hostok(lc, host, ip, "host.allow", "host.deny");
21121288Sdavidn}
21221288Sdavidn
21321288Sdavidn
21425670Sdavidn/*
21525670Sdavidn * auth_timeok()
21621288Sdavidn * Determine whether or not login is ok at a given time
21721288Sdavidn */
21821288Sdavidn
21921288Sdavidnint
22021288Sdavidnauth_timeok(login_cap_t *lc, time_t t)
22121288Sdavidn{
22225670Sdavidn    int	    rc = 1; /* Default is ok */
22321288Sdavidn
22425670Sdavidn    if (lc != NULL && t != (time_t)0 && t != (time_t)-1) {
22525670Sdavidn	struct tm	*tptr;
22621288Sdavidn
22725670Sdavidn	static int 	ltimesno = 0;
22825670Sdavidn	static struct login_time *ltimes = NULL;
22921288Sdavidn
23025670Sdavidn	if ((tptr = localtime(&t)) != NULL) {
23125670Sdavidn	    struct login_time	*lt;
23221288Sdavidn
23325670Sdavidn	  lt = login_timelist(lc, "times.allow", &ltimesno, &ltimes);
23425670Sdavidn	  if (lt != NULL && in_ltms(lt, tptr, NULL) == -1)
23525670Sdavidn	      rc = 0;	  /* not in allowed times list */
23625670Sdavidn	  else {
23721288Sdavidn
23825670Sdavidn	      lt = login_timelist(lc, "times.deny", &ltimesno, &ltimes);
23925670Sdavidn	      if (lt != NULL && in_ltms(lt, tptr, NULL) != -1)
24025670Sdavidn		  rc = 0; /* in deny times list */
24125670Sdavidn	  }
24225670Sdavidn	  if (ltimes) {
24325670Sdavidn	      free(ltimes);
24425670Sdavidn	      ltimes = NULL;
24525670Sdavidn	      ltimesno = 0;
24625670Sdavidn	  }
24725670Sdavidn	}
24821288Sdavidn    }
24925670Sdavidn
25025670Sdavidn    return rc;
25121288Sdavidn}
252