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 * $DragonFly: src/lib/libutil/login_ok.c,v 1.3 2005/03/04 04:31:11 cpressey Exp $ 25 */ 26 27 #include <sys/types.h> 28 #include <sys/time.h> 29 #include <sys/resource.h> 30 #include <sys/param.h> 31 32 #include <errno.h> 33 #include <fnmatch.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <ttyent.h> 37 #include <unistd.h> 38 39 #include "login_cap.h" 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 51 int 52 login_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 71 int 72 login_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 91 login_time_t * 92 login_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 * sizeof(struct login_time))) != 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 128 int 129 login_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 163 int 164 auth_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 177 int 178 login_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, denycap, 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 207 int 208 auth_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 219 int 220 auth_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", <imesno, <imes); 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", <imesno, <imes); 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