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