121288Sdavidn/*- 221288Sdavidn * Copyright (c) 1996 by 321288Sdavidn * David Nugent <davidn@blaze.net.au> 421288Sdavidn * All rights reserved. 521288Sdavidn * 621288Sdavidn * Redistribution and use in source and binary forms, with or without 721288Sdavidn * modification, is permitted provided that the following conditions 821288Sdavidn * are met: 921288Sdavidn * 1. Redistributions of source code must retain the above copyright 1021288Sdavidn * notice immediately at the beginning of the file, without modification, 1121288Sdavidn * this list of conditions, and the following disclaimer. 1221288Sdavidn * 2. Redistributions in binary form must reproduce the above copyright 1321288Sdavidn * notice, this list of conditions and the following disclaimer in the 1421288Sdavidn * documentation and/or other materials provided with the distribution. 1521288Sdavidn * 3. This work was done expressly for inclusion into FreeBSD. Other use 1621288Sdavidn * is permitted provided this notation is included. 1721288Sdavidn * 4. Absolutely no warranty of function or purpose is made by the authors. 1821288Sdavidn * 5. Modifications may be freely made to this file providing the above 1921288Sdavidn * conditions are met. 2021288Sdavidn * 2121288Sdavidn * Support allow/deny lists in login class capabilities 2221288Sdavidn */ 2321288Sdavidn 2484225Sdillon#include <sys/cdefs.h> 2584225Sdillon__FBSDID("$FreeBSD$"); 2684225Sdillon 2721288Sdavidn#include <sys/types.h> 2821288Sdavidn#include <sys/time.h> 2921288Sdavidn#include <sys/resource.h> 3021288Sdavidn#include <sys/param.h> 31116344Smarkm#include <errno.h> 32116344Smarkm#include <fnmatch.h> 3321288Sdavidn#include <login_cap.h> 34116344Smarkm#include <stdlib.h> 35116344Smarkm#include <string.h> 36116344Smarkm#include <ttyent.h> 37116344Smarkm#include <unistd.h> 3821288Sdavidn 3921288Sdavidn 4021288Sdavidn/* -- support functions -- */ 4121288Sdavidn 4225670Sdavidn/* 4325670Sdavidn * login_strinlist() 4421288Sdavidn * This function is intentionally public - reused by TAS. 4521288Sdavidn * Returns TRUE (non-zero) if a string matches a pattern 4621288Sdavidn * in a given array of patterns. 'flags' is passed directly 4721288Sdavidn * to fnmatch(3). 4821288Sdavidn */ 4921288Sdavidn 5021288Sdavidnint 51121193Smarkmlogin_strinlist(const char **list, char const *str, int flags) 5221288Sdavidn{ 5325670Sdavidn int rc = 0; 5421288Sdavidn 5525670Sdavidn if (str != NULL && *str != '\0') { 5625670Sdavidn int i = 0; 5725670Sdavidn 5825670Sdavidn while (rc == 0 && list[i] != NULL) 5926694Sdavidn rc = fnmatch(list[i++], str, flags) == 0; 6025670Sdavidn } 6125670Sdavidn return rc; 6221288Sdavidn} 6321288Sdavidn 6421288Sdavidn 6525670Sdavidn/* 6625670Sdavidn * login_str2inlist() 6721288Sdavidn * Locate either or two strings in a given list 6821288Sdavidn */ 6921288Sdavidn 7021288Sdavidnint 71121193Smarkmlogin_str2inlist(const char **ttlst, const char *str1, const char *str2, int flags) 7221288Sdavidn{ 7325670Sdavidn int rc = 0; 7421288Sdavidn 7525670Sdavidn if (login_strinlist(ttlst, str1, flags)) 7625670Sdavidn rc = 1; 7725670Sdavidn else if (login_strinlist(ttlst, str2, flags)) 7825670Sdavidn rc = 1; 7925670Sdavidn return rc; 8021288Sdavidn} 8121288Sdavidn 8221288Sdavidn 8325670Sdavidn/* 8425670Sdavidn * login_timelist() 85154414Srwatson * This function is intentionally public - reused by TAS. 8621288Sdavidn * Returns an allocated list of time periods given an array 8721288Sdavidn * of time periods in ascii form. 8821288Sdavidn */ 8921288Sdavidn 9021288Sdavidnlogin_time_t * 9125670Sdavidnlogin_timelist(login_cap_t *lc, char const *cap, int *ltno, 9225670Sdavidn login_time_t **ltptr) 9321288Sdavidn{ 9425670Sdavidn int j = 0; 9525670Sdavidn struct login_time *lt = NULL; 96121193Smarkm const char **tl; 9721288Sdavidn 9825670Sdavidn if ((tl = login_getcaplist(lc, cap, NULL)) != NULL) { 9925670Sdavidn 10025670Sdavidn while (tl[j++] != NULL) 10125670Sdavidn ; 10225670Sdavidn if (*ltno >= j) 10325670Sdavidn lt = *ltptr; 10470544Sghelmer else if ((lt = realloc(*ltptr, j * sizeof(struct login_time))) != NULL) { 10525670Sdavidn *ltno = j; 10625670Sdavidn *ltptr = lt; 10725670Sdavidn } 10825670Sdavidn if (lt != NULL) { 10925670Sdavidn int i = 0; 11025670Sdavidn 11125670Sdavidn for (--j; i < j; i++) 11225670Sdavidn lt[i] = parse_lt(tl[i]); 11325670Sdavidn lt[i].lt_dow = LTM_NONE; 11425670Sdavidn } 11521288Sdavidn } 11625670Sdavidn return lt; 11721288Sdavidn} 11821288Sdavidn 11921288Sdavidn 12025670Sdavidn/* 12125670Sdavidn * login_ttyok() 12221288Sdavidn * This function is a variation of auth_ttyok(), but it checks two 12321288Sdavidn * arbitrary capability lists not necessarily related to access. 12421288Sdavidn * This hook is provided for the accounted/exclude accounting lists. 12521288Sdavidn */ 12621288Sdavidn 12721288Sdavidnint 12825670Sdavidnlogin_ttyok(login_cap_t *lc, const char *tty, const char *allowcap, 12925670Sdavidn const char *denycap) 13021288Sdavidn{ 13125670Sdavidn int rc = 1; 13221288Sdavidn 13325670Sdavidn if (lc != NULL && tty != NULL && *tty != '\0') { 13425670Sdavidn struct ttyent *te; 13525670Sdavidn char *grp; 136121193Smarkm const char **ttl; 13721288Sdavidn 13825670Sdavidn te = getttynam(tty); /* Need group name */ 13925670Sdavidn grp = te ? te->ty_group : NULL; 14025670Sdavidn ttl = login_getcaplist(lc, allowcap, NULL); 14125670Sdavidn 14225670Sdavidn if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0)) 14325670Sdavidn rc = 0; /* tty or ttygroup not in allow list */ 14425670Sdavidn else { 14525670Sdavidn 14625670Sdavidn ttl = login_getcaplist(lc, denycap, NULL); 14725670Sdavidn if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0)) 14825670Sdavidn rc = 0; /* tty or ttygroup in deny list */ 14925670Sdavidn } 15021288Sdavidn } 15125670Sdavidn 15225670Sdavidn return rc; 15321288Sdavidn} 15421288Sdavidn 15521288Sdavidn 15625670Sdavidn/* 15725670Sdavidn * auth_ttyok() 15821288Sdavidn * Determine whether or not login on a tty is accessible for 15921288Sdavidn * a login class 16021288Sdavidn */ 16121288Sdavidn 16221288Sdavidnint 16321288Sdavidnauth_ttyok(login_cap_t *lc, const char * tty) 16421288Sdavidn{ 16525670Sdavidn return login_ttyok(lc, tty, "ttys.allow", "ttys.deny"); 16621288Sdavidn} 16721288Sdavidn 16821288Sdavidn 16925670Sdavidn/* 17025670Sdavidn * login_hostok() 17121288Sdavidn * This function is a variation of auth_hostok(), but it checks two 17221288Sdavidn * arbitrary capability lists not necessarily related to access. 17321288Sdavidn * This hook is provided for the accounted/exclude accounting lists. 17421288Sdavidn */ 17521288Sdavidn 17621288Sdavidnint 17725670Sdavidnlogin_hostok(login_cap_t *lc, const char *host, const char *ip, 17825670Sdavidn const char *allowcap, const char *denycap) 17921288Sdavidn{ 18025670Sdavidn int rc = 1; /* Default is ok */ 18121288Sdavidn 18225670Sdavidn if (lc != NULL && 18325670Sdavidn ((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0'))) { 184121193Smarkm const char **hl; 18521288Sdavidn 18625670Sdavidn hl = login_getcaplist(lc, allowcap, NULL); 18725670Sdavidn if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD)) 18825670Sdavidn rc = 0; /* host or IP not in allow list */ 18925670Sdavidn else { 19025670Sdavidn 19170544Sghelmer hl = login_getcaplist(lc, denycap, NULL); 19225670Sdavidn if (hl != NULL && login_str2inlist(hl, host, ip, FNM_CASEFOLD)) 19325670Sdavidn rc = 0; /* host or IP in deny list */ 19425670Sdavidn } 19521288Sdavidn } 19625670Sdavidn 19725670Sdavidn return rc; 19821288Sdavidn} 19921288Sdavidn 20021288Sdavidn 20125670Sdavidn/* 20225670Sdavidn * auth_hostok() 20321288Sdavidn * Determine whether or not login from a host is ok 20421288Sdavidn */ 20521288Sdavidn 20621288Sdavidnint 20721288Sdavidnauth_hostok(login_cap_t *lc, const char *host, const char *ip) 20821288Sdavidn{ 20925670Sdavidn return login_hostok(lc, host, ip, "host.allow", "host.deny"); 21021288Sdavidn} 21121288Sdavidn 21221288Sdavidn 21325670Sdavidn/* 21425670Sdavidn * auth_timeok() 21521288Sdavidn * Determine whether or not login is ok at a given time 21621288Sdavidn */ 21721288Sdavidn 21821288Sdavidnint 21921288Sdavidnauth_timeok(login_cap_t *lc, time_t t) 22021288Sdavidn{ 22125670Sdavidn int rc = 1; /* Default is ok */ 22221288Sdavidn 22325670Sdavidn if (lc != NULL && t != (time_t)0 && t != (time_t)-1) { 22425670Sdavidn struct tm *tptr; 22521288Sdavidn 22625670Sdavidn static int ltimesno = 0; 22725670Sdavidn static struct login_time *ltimes = NULL; 22821288Sdavidn 22925670Sdavidn if ((tptr = localtime(&t)) != NULL) { 23025670Sdavidn struct login_time *lt; 23121288Sdavidn 23225670Sdavidn lt = login_timelist(lc, "times.allow", <imesno, <imes); 23325670Sdavidn if (lt != NULL && in_ltms(lt, tptr, NULL) == -1) 23425670Sdavidn rc = 0; /* not in allowed times list */ 23525670Sdavidn else { 23621288Sdavidn 23725670Sdavidn lt = login_timelist(lc, "times.deny", <imesno, <imes); 23825670Sdavidn if (lt != NULL && in_ltms(lt, tptr, NULL) != -1) 23925670Sdavidn rc = 0; /* in deny times list */ 24025670Sdavidn } 24125670Sdavidn if (ltimes) { 24225670Sdavidn free(ltimes); 24325670Sdavidn ltimes = NULL; 24425670Sdavidn ltimesno = 0; 24525670Sdavidn } 24625670Sdavidn } 24721288Sdavidn } 24825670Sdavidn 24925670Sdavidn return rc; 25021288Sdavidn} 251