xref: /freebsd/lib/libutil/login_ok.c (revision 0ddf9be1f0723916ebd4feb7313d64dffab0c2bb)
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  *	$Id$
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <ttyent.h>
32 #include <fnmatch.h>
33 
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #include <sys/resource.h>
37 #include <sys/param.h>
38 #include <login_cap.h>
39 
40 
41 /* -- support functions -- */
42 
43 /* login_strinlist()
44  * This function is intentionally public - reused by TAS.
45  * Returns TRUE (non-zero) if a string matches a pattern
46  * in a given array of patterns. 'flags' is passed directly
47  * to fnmatch(3).
48  */
49 
50 int
51 login_strinlist(char **list, char const *str, int flags)
52 {
53   int rc = 0;
54 
55   if (str != NULL && *str != '\0')
56   {
57     int i = 0;
58     while (rc == 0 && list[i] != NULL)
59       rc = fnmatch(list[i], str, flags) == 0;
60   }
61   return rc;
62 }
63 
64 
65 /* login_str2inlist()
66  * Locate either or two strings in a given list
67  */
68 
69 int
70 login_str2inlist(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 /* login_timelist()
83  * This function is intentinoally public - reused by TAS.
84  * Returns an allocated list of time periods given an array
85  * of time periods in ascii form.
86  */
87 
88 login_time_t *
89 login_timelist(login_cap_t *lc, char const *cap, int *ltno, login_time_t **ltptr)
90 {
91   int j = 0;
92   struct login_time * lt = NULL;
93   char **tl = login_getcaplist(lc, cap, NULL);
94 
95   if (tl)
96   {
97     while (tl[j++] != NULL)
98       ;
99     if (*ltno >= j)
100       lt = *ltptr;
101     else if ((lt = realloc(*ltptr, j)) != NULL)
102     {
103       *ltno = j;
104       *ltptr = lt;
105     }
106     if (lt != NULL)
107     {
108       int i = 0;
109       --j;
110       while (i < j)
111       {
112 	lt[i] = parse_lt(tl[i]);
113 	++i;
114       }
115       lt[i].lt_dow = LTM_NONE;
116     }
117   }
118   return lt;
119 }
120 
121 
122 /* login_ttyok()
123  * This function is a variation of auth_ttyok(), but it checks two
124  * arbitrary capability lists not necessarily related to access.
125  * This hook is provided for the accounted/exclude accounting lists.
126  */
127 
128 int
129 login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap, const char *denycap)
130 {
131   int rc = 1;
132 
133   if (lc != NULL && tty != NULL && *tty != '\0')
134   {
135     struct ttyent * te = getttynam(tty);  /* Need group name */
136     char * grp = te ? te->ty_group : NULL;
137     char **ttl = login_getcaplist(lc, allowcap, NULL);
138 
139     if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0))
140       rc = 0;	/* tty or ttygroup not in allow list */
141     else
142     {
143       ttl = login_getcaplist(lc, denycap, NULL);
144       if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0))
145 	rc = 0; /* tty or ttygroup in deny list */
146     }
147   }
148   return rc;
149 }
150 
151 
152 /* auth_ttyok()
153  * Determine whether or not login on a tty is accessible for
154  * a login class
155  */
156 
157 int
158 auth_ttyok(login_cap_t *lc, const char * tty)
159 {
160   return login_ttyok(lc, tty, "ttys.allow", "ttys.deny");
161 }
162 
163 
164 /* login_hostok()
165  * This function is a variation of auth_hostok(), but it checks two
166  * arbitrary capability lists not necessarily related to access.
167  * This hook is provided for the accounted/exclude accounting lists.
168  */
169 
170 int
171 login_hostok(login_cap_t *lc, const char *host, const char *ip, const char *allowcap, const char *denycap)
172 {
173   int rc = 1; /* Default is ok */
174 
175   if (lc != NULL && ((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0')))
176   {
177     char **hl = login_getcaplist(lc, allowcap, NULL);
178 
179     if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD))
180       rc = 0;	/* host or IP not in allow list */
181     else
182     {
183       hl = login_getcaplist(lc, "host.deny", NULL);
184       if (hl != NULL && login_str2inlist(hl, host, ip, FNM_CASEFOLD))
185 	rc = 0; /* host or IP in deny list */
186     }
187   }
188   return rc;
189 }
190 
191 
192 /* auth_hostok()
193  * Determine whether or not login from a host is ok
194  */
195 
196 int
197 auth_hostok(login_cap_t *lc, const char *host, const char *ip)
198 {
199   return login_hostok(lc, host, ip, "host.allow", "host.deny");
200 }
201 
202 
203 /* auth_timeok()
204  * Determine whether or not login is ok at a given time
205  */
206 
207 int
208 auth_timeok(login_cap_t *lc, time_t t)
209 {
210   int rc = 1; /* Default is ok */
211 
212   if (lc != NULL && t != (time_t)0 && t != (time_t)-1)
213   {
214     struct tm * tptr = localtime(&t);
215 
216     static int ltimesno = 0;
217     static struct login_time * ltimes = NULL;
218 
219     if (tptr != NULL)
220     {
221       struct login_time *lt = login_timelist(lc, "times.allow", &ltimesno, &ltimes);
222 
223       if (lt != NULL && in_ltms(lt, tptr, NULL) == -1)
224 	rc = 0;	  /* not in allowed times list */
225       else
226       {
227 	lt = login_timelist(lc, "times.deny", &ltimesno, &ltimes);
228 
229 	if (lt != NULL && in_ltms(lt, tptr, NULL) != -1)
230 	  rc = 0; /* in deny times list */
231       }
232       if (ltimes)
233       {
234 	free(ltimes);
235 	ltimes = NULL;
236 	ltimesno = 0;
237       }
238     }
239   }
240   return rc;
241 }
242 
243