xref: /f-stack/tools/libutil/login_ok.c (revision 1eaf0ac3)
1*1eaf0ac3Slogwang /*-
2*1eaf0ac3Slogwang  * Copyright (c) 1996 by
3*1eaf0ac3Slogwang  * David Nugent <[email protected]>
4*1eaf0ac3Slogwang  * All rights reserved.
5*1eaf0ac3Slogwang  *
6*1eaf0ac3Slogwang  * Redistribution and use in source and binary forms, with or without
7*1eaf0ac3Slogwang  * modification, is permitted provided that the following conditions
8*1eaf0ac3Slogwang  * are met:
9*1eaf0ac3Slogwang  * 1. Redistributions of source code must retain the above copyright
10*1eaf0ac3Slogwang  *    notice immediately at the beginning of the file, without modification,
11*1eaf0ac3Slogwang  *    this list of conditions, and the following disclaimer.
12*1eaf0ac3Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
13*1eaf0ac3Slogwang  *    notice, this list of conditions and the following disclaimer in the
14*1eaf0ac3Slogwang  *    documentation and/or other materials provided with the distribution.
15*1eaf0ac3Slogwang  * 3. This work was done expressly for inclusion into FreeBSD.  Other use
16*1eaf0ac3Slogwang  *    is permitted provided this notation is included.
17*1eaf0ac3Slogwang  * 4. Absolutely no warranty of function or purpose is made by the authors.
18*1eaf0ac3Slogwang  * 5. Modifications may be freely made to this file providing the above
19*1eaf0ac3Slogwang  *    conditions are met.
20*1eaf0ac3Slogwang  *
21*1eaf0ac3Slogwang  * Support allow/deny lists in login class capabilities
22*1eaf0ac3Slogwang  */
23*1eaf0ac3Slogwang 
24*1eaf0ac3Slogwang #include <sys/cdefs.h>
25*1eaf0ac3Slogwang __FBSDID("$FreeBSD$");
26*1eaf0ac3Slogwang 
27*1eaf0ac3Slogwang #include <sys/types.h>
28*1eaf0ac3Slogwang #include <sys/time.h>
29*1eaf0ac3Slogwang #include <sys/resource.h>
30*1eaf0ac3Slogwang #include <sys/param.h>
31*1eaf0ac3Slogwang #include <errno.h>
32*1eaf0ac3Slogwang #include <fnmatch.h>
33*1eaf0ac3Slogwang #include <login_cap.h>
34*1eaf0ac3Slogwang #include <stdlib.h>
35*1eaf0ac3Slogwang #include <string.h>
36*1eaf0ac3Slogwang #include <ttyent.h>
37*1eaf0ac3Slogwang #include <unistd.h>
38*1eaf0ac3Slogwang 
39*1eaf0ac3Slogwang 
40*1eaf0ac3Slogwang /* -- support functions -- */
41*1eaf0ac3Slogwang 
42*1eaf0ac3Slogwang /*
43*1eaf0ac3Slogwang  * login_strinlist()
44*1eaf0ac3Slogwang  * This function is intentionally public - reused by TAS.
45*1eaf0ac3Slogwang  * Returns TRUE (non-zero) if a string matches a pattern
46*1eaf0ac3Slogwang  * in a given array of patterns. 'flags' is passed directly
47*1eaf0ac3Slogwang  * to fnmatch(3).
48*1eaf0ac3Slogwang  */
49*1eaf0ac3Slogwang 
50*1eaf0ac3Slogwang int
login_strinlist(const char ** list,char const * str,int flags)51*1eaf0ac3Slogwang login_strinlist(const char **list, char const *str, int flags)
52*1eaf0ac3Slogwang {
53*1eaf0ac3Slogwang     int rc = 0;
54*1eaf0ac3Slogwang 
55*1eaf0ac3Slogwang     if (str != NULL && *str != '\0') {
56*1eaf0ac3Slogwang 	int	i = 0;
57*1eaf0ac3Slogwang 
58*1eaf0ac3Slogwang 	while (rc == 0 && list[i] != NULL)
59*1eaf0ac3Slogwang 	    rc = fnmatch(list[i++], str, flags) == 0;
60*1eaf0ac3Slogwang     }
61*1eaf0ac3Slogwang     return rc;
62*1eaf0ac3Slogwang }
63*1eaf0ac3Slogwang 
64*1eaf0ac3Slogwang 
65*1eaf0ac3Slogwang /*
66*1eaf0ac3Slogwang  * login_str2inlist()
67*1eaf0ac3Slogwang  * Locate either or two strings in a given list
68*1eaf0ac3Slogwang  */
69*1eaf0ac3Slogwang 
70*1eaf0ac3Slogwang int
login_str2inlist(const char ** ttlst,const char * str1,const char * str2,int flags)71*1eaf0ac3Slogwang login_str2inlist(const char **ttlst, const char *str1, const char *str2, int flags)
72*1eaf0ac3Slogwang {
73*1eaf0ac3Slogwang     int	    rc = 0;
74*1eaf0ac3Slogwang 
75*1eaf0ac3Slogwang     if (login_strinlist(ttlst, str1, flags))
76*1eaf0ac3Slogwang 	rc = 1;
77*1eaf0ac3Slogwang     else if (login_strinlist(ttlst, str2, flags))
78*1eaf0ac3Slogwang 	rc = 1;
79*1eaf0ac3Slogwang     return rc;
80*1eaf0ac3Slogwang }
81*1eaf0ac3Slogwang 
82*1eaf0ac3Slogwang 
83*1eaf0ac3Slogwang /*
84*1eaf0ac3Slogwang  * login_timelist()
85*1eaf0ac3Slogwang  * This function is intentionally public - reused by TAS.
86*1eaf0ac3Slogwang  * Returns an allocated list of time periods given an array
87*1eaf0ac3Slogwang  * of time periods in ascii form.
88*1eaf0ac3Slogwang  */
89*1eaf0ac3Slogwang 
90*1eaf0ac3Slogwang login_time_t *
login_timelist(login_cap_t * lc,char const * cap,int * ltno,login_time_t ** ltptr)91*1eaf0ac3Slogwang login_timelist(login_cap_t *lc, char const *cap, int *ltno,
92*1eaf0ac3Slogwang 	       login_time_t **ltptr)
93*1eaf0ac3Slogwang {
94*1eaf0ac3Slogwang     int			j = 0;
95*1eaf0ac3Slogwang     struct login_time	*lt = NULL;
96*1eaf0ac3Slogwang     const char		**tl;
97*1eaf0ac3Slogwang 
98*1eaf0ac3Slogwang     if ((tl = login_getcaplist(lc, cap, NULL)) != NULL) {
99*1eaf0ac3Slogwang 
100*1eaf0ac3Slogwang 	while (tl[j++] != NULL)
101*1eaf0ac3Slogwang 	    ;
102*1eaf0ac3Slogwang 	if (*ltno >= j)
103*1eaf0ac3Slogwang 	    lt = *ltptr;
104*1eaf0ac3Slogwang 	else if ((lt = realloc(*ltptr, j * sizeof(struct login_time))) != NULL) {
105*1eaf0ac3Slogwang 	    *ltno = j;
106*1eaf0ac3Slogwang 	    *ltptr = lt;
107*1eaf0ac3Slogwang 	}
108*1eaf0ac3Slogwang 	if (lt != NULL) {
109*1eaf0ac3Slogwang 	    int	    i = 0;
110*1eaf0ac3Slogwang 
111*1eaf0ac3Slogwang 	    for (--j; i < j; i++)
112*1eaf0ac3Slogwang 		lt[i] = parse_lt(tl[i]);
113*1eaf0ac3Slogwang 	    lt[i].lt_dow = LTM_NONE;
114*1eaf0ac3Slogwang 	}
115*1eaf0ac3Slogwang     }
116*1eaf0ac3Slogwang     return lt;
117*1eaf0ac3Slogwang }
118*1eaf0ac3Slogwang 
119*1eaf0ac3Slogwang 
120*1eaf0ac3Slogwang /*
121*1eaf0ac3Slogwang  * login_ttyok()
122*1eaf0ac3Slogwang  * This function is a variation of auth_ttyok(), but it checks two
123*1eaf0ac3Slogwang  * arbitrary capability lists not necessarily related to access.
124*1eaf0ac3Slogwang  * This hook is provided for the accounted/exclude accounting lists.
125*1eaf0ac3Slogwang  */
126*1eaf0ac3Slogwang 
127*1eaf0ac3Slogwang int
login_ttyok(login_cap_t * lc,const char * tty,const char * allowcap,const char * denycap)128*1eaf0ac3Slogwang login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap,
129*1eaf0ac3Slogwang 	    const char *denycap)
130*1eaf0ac3Slogwang {
131*1eaf0ac3Slogwang     int	    rc = 1;
132*1eaf0ac3Slogwang 
133*1eaf0ac3Slogwang     if (lc != NULL && tty != NULL && *tty != '\0') {
134*1eaf0ac3Slogwang 	struct ttyent	*te;
135*1eaf0ac3Slogwang 	char		*grp;
136*1eaf0ac3Slogwang 	const char	**ttl;
137*1eaf0ac3Slogwang 
138*1eaf0ac3Slogwang 	te = getttynam(tty);  /* Need group name */
139*1eaf0ac3Slogwang 	grp = te ? te->ty_group : NULL;
140*1eaf0ac3Slogwang 	ttl = login_getcaplist(lc, allowcap, NULL);
141*1eaf0ac3Slogwang 
142*1eaf0ac3Slogwang 	if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0))
143*1eaf0ac3Slogwang 	    rc = 0;	/* tty or ttygroup not in allow list */
144*1eaf0ac3Slogwang 	else {
145*1eaf0ac3Slogwang 
146*1eaf0ac3Slogwang 	    ttl = login_getcaplist(lc, denycap, NULL);
147*1eaf0ac3Slogwang 	    if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0))
148*1eaf0ac3Slogwang 		rc = 0; /* tty or ttygroup in deny list */
149*1eaf0ac3Slogwang 	}
150*1eaf0ac3Slogwang     }
151*1eaf0ac3Slogwang 
152*1eaf0ac3Slogwang     return rc;
153*1eaf0ac3Slogwang }
154*1eaf0ac3Slogwang 
155*1eaf0ac3Slogwang 
156*1eaf0ac3Slogwang /*
157*1eaf0ac3Slogwang  * auth_ttyok()
158*1eaf0ac3Slogwang  * Determine whether or not login on a tty is accessible for
159*1eaf0ac3Slogwang  * a login class
160*1eaf0ac3Slogwang  */
161*1eaf0ac3Slogwang 
162*1eaf0ac3Slogwang int
auth_ttyok(login_cap_t * lc,const char * tty)163*1eaf0ac3Slogwang auth_ttyok(login_cap_t *lc, const char * tty)
164*1eaf0ac3Slogwang {
165*1eaf0ac3Slogwang     return login_ttyok(lc, tty, "ttys.allow", "ttys.deny");
166*1eaf0ac3Slogwang }
167*1eaf0ac3Slogwang 
168*1eaf0ac3Slogwang 
169*1eaf0ac3Slogwang /*
170*1eaf0ac3Slogwang  * login_hostok()
171*1eaf0ac3Slogwang  * This function is a variation of auth_hostok(), but it checks two
172*1eaf0ac3Slogwang  * arbitrary capability lists not necessarily related to access.
173*1eaf0ac3Slogwang  * This hook is provided for the accounted/exclude accounting lists.
174*1eaf0ac3Slogwang  */
175*1eaf0ac3Slogwang 
176*1eaf0ac3Slogwang int
login_hostok(login_cap_t * lc,const char * host,const char * ip,const char * allowcap,const char * denycap)177*1eaf0ac3Slogwang login_hostok(login_cap_t *lc, const char *host, const char *ip,
178*1eaf0ac3Slogwang 	     const char *allowcap, const char *denycap)
179*1eaf0ac3Slogwang {
180*1eaf0ac3Slogwang     int	    rc = 1; /* Default is ok */
181*1eaf0ac3Slogwang 
182*1eaf0ac3Slogwang     if (lc != NULL &&
183*1eaf0ac3Slogwang 	((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0'))) {
184*1eaf0ac3Slogwang 	const char **hl;
185*1eaf0ac3Slogwang 
186*1eaf0ac3Slogwang 	hl = login_getcaplist(lc, allowcap, NULL);
187*1eaf0ac3Slogwang 	if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD))
188*1eaf0ac3Slogwang 	    rc = 0;	/* host or IP not in allow list */
189*1eaf0ac3Slogwang 	else {
190*1eaf0ac3Slogwang 
191*1eaf0ac3Slogwang 	    hl = login_getcaplist(lc, denycap, NULL);
192*1eaf0ac3Slogwang 	    if (hl != NULL && login_str2inlist(hl, host, ip, FNM_CASEFOLD))
193*1eaf0ac3Slogwang 		rc = 0; /* host or IP in deny list */
194*1eaf0ac3Slogwang 	}
195*1eaf0ac3Slogwang     }
196*1eaf0ac3Slogwang 
197*1eaf0ac3Slogwang     return rc;
198*1eaf0ac3Slogwang }
199*1eaf0ac3Slogwang 
200*1eaf0ac3Slogwang 
201*1eaf0ac3Slogwang /*
202*1eaf0ac3Slogwang  * auth_hostok()
203*1eaf0ac3Slogwang  * Determine whether or not login from a host is ok
204*1eaf0ac3Slogwang  */
205*1eaf0ac3Slogwang 
206*1eaf0ac3Slogwang int
auth_hostok(login_cap_t * lc,const char * host,const char * ip)207*1eaf0ac3Slogwang auth_hostok(login_cap_t *lc, const char *host, const char *ip)
208*1eaf0ac3Slogwang {
209*1eaf0ac3Slogwang     return login_hostok(lc, host, ip, "host.allow", "host.deny");
210*1eaf0ac3Slogwang }
211*1eaf0ac3Slogwang 
212*1eaf0ac3Slogwang 
213*1eaf0ac3Slogwang /*
214*1eaf0ac3Slogwang  * auth_timeok()
215*1eaf0ac3Slogwang  * Determine whether or not login is ok at a given time
216*1eaf0ac3Slogwang  */
217*1eaf0ac3Slogwang 
218*1eaf0ac3Slogwang int
auth_timeok(login_cap_t * lc,time_t t)219*1eaf0ac3Slogwang auth_timeok(login_cap_t *lc, time_t t)
220*1eaf0ac3Slogwang {
221*1eaf0ac3Slogwang     int	    rc = 1; /* Default is ok */
222*1eaf0ac3Slogwang 
223*1eaf0ac3Slogwang     if (lc != NULL && t != (time_t)0 && t != (time_t)-1) {
224*1eaf0ac3Slogwang 	struct tm	*tptr;
225*1eaf0ac3Slogwang 
226*1eaf0ac3Slogwang 	static int 	ltimesno = 0;
227*1eaf0ac3Slogwang 	static struct login_time *ltimes = NULL;
228*1eaf0ac3Slogwang 
229*1eaf0ac3Slogwang 	if ((tptr = localtime(&t)) != NULL) {
230*1eaf0ac3Slogwang 	    struct login_time	*lt;
231*1eaf0ac3Slogwang 
232*1eaf0ac3Slogwang 	  lt = login_timelist(lc, "times.allow", &ltimesno, &ltimes);
233*1eaf0ac3Slogwang 	  if (lt != NULL && in_ltms(lt, tptr, NULL) == -1)
234*1eaf0ac3Slogwang 	      rc = 0;	  /* not in allowed times list */
235*1eaf0ac3Slogwang 	  else {
236*1eaf0ac3Slogwang 
237*1eaf0ac3Slogwang 	      lt = login_timelist(lc, "times.deny", &ltimesno, &ltimes);
238*1eaf0ac3Slogwang 	      if (lt != NULL && in_ltms(lt, tptr, NULL) != -1)
239*1eaf0ac3Slogwang 		  rc = 0; /* in deny times list */
240*1eaf0ac3Slogwang 	  }
241*1eaf0ac3Slogwang 	  if (ltimes) {
242*1eaf0ac3Slogwang 	      free(ltimes);
243*1eaf0ac3Slogwang 	      ltimes = NULL;
244*1eaf0ac3Slogwang 	      ltimesno = 0;
245*1eaf0ac3Slogwang 	  }
246*1eaf0ac3Slogwang 	}
247*1eaf0ac3Slogwang     }
248*1eaf0ac3Slogwang 
249*1eaf0ac3Slogwang     return rc;
250*1eaf0ac3Slogwang }
251