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