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