login_ok.c revision 21673
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 21673 1997-01-14 07:20:47Z jkh $
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
50int
51login_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
69int
70login_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
88login_time_t *
89login_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
128int
129login_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
157int
158auth_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
170int
171login_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
196int
197auth_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
207int
208auth_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