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