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 24 #include <sys/cdefs.h> 25 __FBSDID("$FreeBSD$"); 26 27 #include <sys/types.h> 28 #include <sys/time.h> 29 #include <sys/resource.h> 30 #include <sys/param.h> 31 #include <errno.h> 32 #include <fnmatch.h> 33 #include <login_cap.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <ttyent.h> 37 #include <unistd.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(const 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(const 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 intentionally 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 const 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 const 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 const 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", <imesno, <imes); 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", <imesno, <imes); 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 } 251