xref: /freebsd/lib/libutil/login_ok.c (revision a2f733abcff64628b7771a47089628b7327a88bd)
168bbf3adSDavid Nugent /*-
268bbf3adSDavid Nugent  * Copyright (c) 1996 by
368bbf3adSDavid Nugent  * David Nugent <davidn@blaze.net.au>
468bbf3adSDavid Nugent  * All rights reserved.
568bbf3adSDavid Nugent  *
668bbf3adSDavid Nugent  * Redistribution and use in source and binary forms, with or without
768bbf3adSDavid Nugent  * modification, is permitted provided that the following conditions
868bbf3adSDavid Nugent  * are met:
968bbf3adSDavid Nugent  * 1. Redistributions of source code must retain the above copyright
1068bbf3adSDavid Nugent  *    notice immediately at the beginning of the file, without modification,
1168bbf3adSDavid Nugent  *    this list of conditions, and the following disclaimer.
1268bbf3adSDavid Nugent  * 2. Redistributions in binary form must reproduce the above copyright
1368bbf3adSDavid Nugent  *    notice, this list of conditions and the following disclaimer in the
1468bbf3adSDavid Nugent  *    documentation and/or other materials provided with the distribution.
1568bbf3adSDavid Nugent  * 3. This work was done expressly for inclusion into FreeBSD.  Other use
1668bbf3adSDavid Nugent  *    is permitted provided this notation is included.
1768bbf3adSDavid Nugent  * 4. Absolutely no warranty of function or purpose is made by the authors.
1868bbf3adSDavid Nugent  * 5. Modifications may be freely made to this file providing the above
1968bbf3adSDavid Nugent  *    conditions are met.
2068bbf3adSDavid Nugent  *
2168bbf3adSDavid Nugent  * Support allow/deny lists in login class capabilities
2268bbf3adSDavid Nugent  */
2368bbf3adSDavid Nugent 
2468bbf3adSDavid Nugent #include <sys/types.h>
2568bbf3adSDavid Nugent #include <sys/time.h>
2668bbf3adSDavid Nugent #include <sys/resource.h>
2768bbf3adSDavid Nugent #include <sys/param.h>
280ebec5d3SMark Murray #include <errno.h>
290ebec5d3SMark Murray #include <fnmatch.h>
3068bbf3adSDavid Nugent #include <login_cap.h>
310ebec5d3SMark Murray #include <stdlib.h>
320ebec5d3SMark Murray #include <string.h>
330ebec5d3SMark Murray #include <ttyent.h>
340ebec5d3SMark Murray #include <unistd.h>
3568bbf3adSDavid Nugent 
3668bbf3adSDavid Nugent 
3768bbf3adSDavid Nugent /* -- support functions -- */
3868bbf3adSDavid Nugent 
3956c04344SDavid Nugent /*
4056c04344SDavid Nugent  * login_strinlist()
4168bbf3adSDavid Nugent  * This function is intentionally public - reused by TAS.
4268bbf3adSDavid Nugent  * Returns TRUE (non-zero) if a string matches a pattern
4368bbf3adSDavid Nugent  * in a given array of patterns. 'flags' is passed directly
4468bbf3adSDavid Nugent  * to fnmatch(3).
4568bbf3adSDavid Nugent  */
4668bbf3adSDavid Nugent 
4768bbf3adSDavid Nugent int
login_strinlist(const char ** list,char const * str,int flags)48547fa0d9SMark Murray login_strinlist(const char **list, char const *str, int flags)
4968bbf3adSDavid Nugent {
5068bbf3adSDavid Nugent     int rc = 0;
5168bbf3adSDavid Nugent 
5256c04344SDavid Nugent     if (str != NULL && *str != '\0') {
5368bbf3adSDavid Nugent 	int	i = 0;
5456c04344SDavid Nugent 
5568bbf3adSDavid Nugent 	while (rc == 0 && list[i] != NULL)
560edf2964SDavid Nugent 	    rc = fnmatch(list[i++], str, flags) == 0;
5768bbf3adSDavid Nugent     }
5868bbf3adSDavid Nugent     return rc;
5968bbf3adSDavid Nugent }
6068bbf3adSDavid Nugent 
6168bbf3adSDavid Nugent 
6256c04344SDavid Nugent /*
6356c04344SDavid Nugent  * login_str2inlist()
6468bbf3adSDavid Nugent  * Locate either or two strings in a given list
6568bbf3adSDavid Nugent  */
6668bbf3adSDavid Nugent 
6768bbf3adSDavid Nugent int
login_str2inlist(const char ** ttlst,const char * str1,const char * str2,int flags)68547fa0d9SMark Murray login_str2inlist(const char **ttlst, const char *str1, const char *str2, int flags)
6968bbf3adSDavid Nugent {
7068bbf3adSDavid Nugent     int	    rc = 0;
7168bbf3adSDavid Nugent 
7268bbf3adSDavid Nugent     if (login_strinlist(ttlst, str1, flags))
7368bbf3adSDavid Nugent 	rc = 1;
7468bbf3adSDavid Nugent     else if (login_strinlist(ttlst, str2, flags))
7568bbf3adSDavid Nugent 	rc = 1;
7668bbf3adSDavid Nugent     return rc;
7768bbf3adSDavid Nugent }
7868bbf3adSDavid Nugent 
7968bbf3adSDavid Nugent 
8056c04344SDavid Nugent /*
8156c04344SDavid Nugent  * login_timelist()
828e3ae6feSRobert Watson  * This function is intentionally public - reused by TAS.
8368bbf3adSDavid Nugent  * Returns an allocated list of time periods given an array
8468bbf3adSDavid Nugent  * of time periods in ascii form.
8568bbf3adSDavid Nugent  */
8668bbf3adSDavid Nugent 
8768bbf3adSDavid Nugent login_time_t *
login_timelist(login_cap_t * lc,char const * cap,int * ltno,login_time_t ** ltptr)8856c04344SDavid Nugent login_timelist(login_cap_t *lc, char const *cap, int *ltno,
8956c04344SDavid Nugent 	       login_time_t **ltptr)
9068bbf3adSDavid Nugent {
9168bbf3adSDavid Nugent     int			j = 0;
9268bbf3adSDavid Nugent     struct login_time	*lt = NULL;
93547fa0d9SMark Murray     const char		**tl;
9468bbf3adSDavid Nugent 
9556c04344SDavid Nugent     if ((tl = login_getcaplist(lc, cap, NULL)) != NULL) {
9656c04344SDavid Nugent 
9768bbf3adSDavid Nugent 	while (tl[j++] != NULL)
9868bbf3adSDavid Nugent 	    ;
9968bbf3adSDavid Nugent 	if (*ltno >= j)
10068bbf3adSDavid Nugent 	    lt = *ltptr;
1014a4ecab1SGuy Helmer 	else if ((lt = realloc(*ltptr, j * sizeof(struct login_time))) != NULL) {
10268bbf3adSDavid Nugent 	    *ltno = j;
10368bbf3adSDavid Nugent 	    *ltptr = lt;
10468bbf3adSDavid Nugent 	}
10556c04344SDavid Nugent 	if (lt != NULL) {
10668bbf3adSDavid Nugent 	    int	    i = 0;
10756c04344SDavid Nugent 
10856c04344SDavid Nugent 	    for (--j; i < j; i++)
10968bbf3adSDavid Nugent 		lt[i] = parse_lt(tl[i]);
11068bbf3adSDavid Nugent 	    lt[i].lt_dow = LTM_NONE;
11168bbf3adSDavid Nugent 	}
11268bbf3adSDavid Nugent     }
11368bbf3adSDavid Nugent     return lt;
11468bbf3adSDavid Nugent }
11568bbf3adSDavid Nugent 
11668bbf3adSDavid Nugent 
11756c04344SDavid Nugent /*
11856c04344SDavid Nugent  * login_ttyok()
11968bbf3adSDavid Nugent  * This function is a variation of auth_ttyok(), but it checks two
12068bbf3adSDavid Nugent  * arbitrary capability lists not necessarily related to access.
12168bbf3adSDavid Nugent  * This hook is provided for the accounted/exclude accounting lists.
12268bbf3adSDavid Nugent  */
12368bbf3adSDavid Nugent 
12468bbf3adSDavid Nugent int
login_ttyok(login_cap_t * lc,const char * tty,const char * allowcap,const char * denycap)12556c04344SDavid Nugent login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap,
12656c04344SDavid Nugent 	    const char *denycap)
12768bbf3adSDavid Nugent {
12868bbf3adSDavid Nugent     int	    rc = 1;
12968bbf3adSDavid Nugent 
13056c04344SDavid Nugent     if (lc != NULL && tty != NULL && *tty != '\0') {
13156c04344SDavid Nugent 	struct ttyent	*te;
13256c04344SDavid Nugent 	char		*grp;
133547fa0d9SMark Murray 	const char	**ttl;
13456c04344SDavid Nugent 
13556c04344SDavid Nugent 	te = getttynam(tty);  /* Need group name */
13656c04344SDavid Nugent 	grp = te ? te->ty_group : NULL;
13756c04344SDavid Nugent 	ttl = login_getcaplist(lc, allowcap, NULL);
13868bbf3adSDavid Nugent 
13968bbf3adSDavid Nugent 	if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0))
14068bbf3adSDavid Nugent 	    rc = 0;	/* tty or ttygroup not in allow list */
14156c04344SDavid Nugent 	else {
14256c04344SDavid Nugent 
14368bbf3adSDavid Nugent 	    ttl = login_getcaplist(lc, denycap, NULL);
14468bbf3adSDavid Nugent 	    if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0))
14568bbf3adSDavid Nugent 		rc = 0; /* tty or ttygroup in deny list */
14668bbf3adSDavid Nugent 	}
14768bbf3adSDavid Nugent     }
14856c04344SDavid Nugent 
14968bbf3adSDavid Nugent     return rc;
15068bbf3adSDavid Nugent }
15168bbf3adSDavid Nugent 
15268bbf3adSDavid Nugent 
15356c04344SDavid Nugent /*
15456c04344SDavid Nugent  * auth_ttyok()
15568bbf3adSDavid Nugent  * Determine whether or not login on a tty is accessible for
15668bbf3adSDavid Nugent  * a login class
15768bbf3adSDavid Nugent  */
15868bbf3adSDavid Nugent 
15968bbf3adSDavid Nugent int
auth_ttyok(login_cap_t * lc,const char * tty)16068bbf3adSDavid Nugent auth_ttyok(login_cap_t *lc, const char * tty)
16168bbf3adSDavid Nugent {
16268bbf3adSDavid Nugent     return login_ttyok(lc, tty, "ttys.allow", "ttys.deny");
16368bbf3adSDavid Nugent }
16468bbf3adSDavid Nugent 
16568bbf3adSDavid Nugent 
16656c04344SDavid Nugent /*
16756c04344SDavid Nugent  * login_hostok()
16868bbf3adSDavid Nugent  * This function is a variation of auth_hostok(), but it checks two
16968bbf3adSDavid Nugent  * arbitrary capability lists not necessarily related to access.
17068bbf3adSDavid Nugent  * This hook is provided for the accounted/exclude accounting lists.
17168bbf3adSDavid Nugent  */
17268bbf3adSDavid Nugent 
17368bbf3adSDavid Nugent int
login_hostok(login_cap_t * lc,const char * host,const char * ip,const char * allowcap,const char * denycap)17456c04344SDavid Nugent login_hostok(login_cap_t *lc, const char *host, const char *ip,
17556c04344SDavid Nugent 	     const char *allowcap, const char *denycap)
17668bbf3adSDavid Nugent {
17768bbf3adSDavid Nugent     int	    rc = 1; /* Default is ok */
17868bbf3adSDavid Nugent 
17956c04344SDavid Nugent     if (lc != NULL &&
18056c04344SDavid Nugent 	((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0'))) {
181547fa0d9SMark Murray 	const char **hl;
18268bbf3adSDavid Nugent 
18356c04344SDavid Nugent 	hl = login_getcaplist(lc, allowcap, NULL);
18468bbf3adSDavid Nugent 	if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD))
18568bbf3adSDavid Nugent 	    rc = 0;	/* host or IP not in allow list */
18656c04344SDavid Nugent 	else {
18756c04344SDavid Nugent 
1884a4ecab1SGuy Helmer 	    hl = login_getcaplist(lc, denycap, NULL);
18968bbf3adSDavid Nugent 	    if (hl != NULL && login_str2inlist(hl, host, ip, FNM_CASEFOLD))
19068bbf3adSDavid Nugent 		rc = 0; /* host or IP in deny list */
19168bbf3adSDavid Nugent 	}
19268bbf3adSDavid Nugent     }
19356c04344SDavid Nugent 
19468bbf3adSDavid Nugent     return rc;
19568bbf3adSDavid Nugent }
19668bbf3adSDavid Nugent 
19768bbf3adSDavid Nugent 
19856c04344SDavid Nugent /*
19956c04344SDavid Nugent  * auth_hostok()
20068bbf3adSDavid Nugent  * Determine whether or not login from a host is ok
20168bbf3adSDavid Nugent  */
20268bbf3adSDavid Nugent 
20368bbf3adSDavid Nugent int
auth_hostok(login_cap_t * lc,const char * host,const char * ip)20468bbf3adSDavid Nugent auth_hostok(login_cap_t *lc, const char *host, const char *ip)
20568bbf3adSDavid Nugent {
20668bbf3adSDavid Nugent     return login_hostok(lc, host, ip, "host.allow", "host.deny");
20768bbf3adSDavid Nugent }
20868bbf3adSDavid Nugent 
20968bbf3adSDavid Nugent 
21056c04344SDavid Nugent /*
21156c04344SDavid Nugent  * auth_timeok()
21268bbf3adSDavid Nugent  * Determine whether or not login is ok at a given time
21368bbf3adSDavid Nugent  */
21468bbf3adSDavid Nugent 
21568bbf3adSDavid Nugent int
auth_timeok(login_cap_t * lc,time_t t)21668bbf3adSDavid Nugent auth_timeok(login_cap_t *lc, time_t t)
21768bbf3adSDavid Nugent {
21868bbf3adSDavid Nugent     int	    rc = 1; /* Default is ok */
21968bbf3adSDavid Nugent 
22056c04344SDavid Nugent     if (lc != NULL && t != (time_t)0 && t != (time_t)-1) {
22156c04344SDavid Nugent 	struct tm	*tptr;
22268bbf3adSDavid Nugent 
22368bbf3adSDavid Nugent 	static int 	ltimesno = 0;
22468bbf3adSDavid Nugent 	static struct login_time *ltimes = NULL;
22568bbf3adSDavid Nugent 
22656c04344SDavid Nugent 	if ((tptr = localtime(&t)) != NULL) {
22756c04344SDavid Nugent 	    struct login_time	*lt;
22868bbf3adSDavid Nugent 
22956c04344SDavid Nugent 	  lt = login_timelist(lc, "times.allow", &ltimesno, &ltimes);
23068bbf3adSDavid Nugent 	  if (lt != NULL && in_ltms(lt, tptr, NULL) == -1)
23168bbf3adSDavid Nugent 	      rc = 0;	  /* not in allowed times list */
23256c04344SDavid Nugent 	  else {
23368bbf3adSDavid Nugent 
23456c04344SDavid Nugent 	      lt = login_timelist(lc, "times.deny", &ltimesno, &ltimes);
23568bbf3adSDavid Nugent 	      if (lt != NULL && in_ltms(lt, tptr, NULL) != -1)
23668bbf3adSDavid Nugent 		  rc = 0; /* in deny times list */
23768bbf3adSDavid Nugent 	  }
23856c04344SDavid Nugent 	  if (ltimes) {
23968bbf3adSDavid Nugent 	      free(ltimes);
24068bbf3adSDavid Nugent 	      ltimes = NULL;
24168bbf3adSDavid Nugent 	      ltimesno = 0;
24268bbf3adSDavid Nugent 	  }
24368bbf3adSDavid Nugent 	}
24468bbf3adSDavid Nugent     }
24556c04344SDavid Nugent 
24668bbf3adSDavid Nugent     return rc;
24768bbf3adSDavid Nugent }
248