18626Sguido/************************************************************************
28626Sguido* Copyright 1995 by Wietse Venema.  All rights reserved.
38626Sguido*
48626Sguido* This material was originally written and compiled by Wietse Venema at
58626Sguido* Eindhoven University of Technology, The Netherlands, in 1990, 1991,
68626Sguido* 1992, 1993, 1994 and 1995.
78626Sguido*
88626Sguido* Redistribution and use in source and binary forms are permitted
98626Sguido* provided that this entire copyright notice is duplicated in all such
108874Srgrimes* copies.
118626Sguido*
128626Sguido* This software is provided "as is" and without any expressed or implied
138626Sguido* warranties, including, without limitation, the implied warranties of
148626Sguido* merchantibility and fitness for any particular purpose.
158626Sguido************************************************************************/
162224Sguido/*
172224Sguido    SYNOPSIS
182224Sguido	void login_fbtab(tty, uid, gid)
192224Sguido	char *tty;
202224Sguido	uid_t uid;
212224Sguido	gid_t gid;
222224Sguido
232224Sguido    DESCRIPTION
242224Sguido	This module implements device security as described in the
252224Sguido	SunOS 4.1.x fbtab(5) and SunOS 5.x logindevperm(4) manual
262224Sguido	pages. The program first looks for /etc/fbtab. If that file
272224Sguido	cannot be opened it attempts to process /etc/logindevperm.
28228992Suqs	We expect entries with the following format:
292224Sguido
302224Sguido	    Comments start with a # and extend to the end of the line.
312224Sguido
322224Sguido	    Blank lines or lines with only a comment are ignored.
332224Sguido
342224Sguido	    All other lines consist of three fields delimited by
352224Sguido	    whitespace: a login device (/dev/console), an octal
362224Sguido	    permission number (0600), and a ":"-delimited list of
372224Sguido	    devices (/dev/kbd:/dev/mouse). All device names are
3833358Sjb	    absolute paths. A path that ends in "*" refers to all
392224Sguido	    directory entries except "." and "..".
402224Sguido
412224Sguido	    If the tty argument (relative path) matches a login device
422224Sguido	    name (absolute path), the permissions of the devices in the
432224Sguido	    ":"-delimited list are set as specified in the second
442224Sguido	    field, and their ownership is changed to that of the uid
452224Sguido	    and gid arguments.
462224Sguido
472224Sguido    DIAGNOSTICS
482224Sguido	Problems are reported via the syslog daemon with severity
492224Sguido	LOG_ERR.
502224Sguido
512224Sguido    BUGS
522224Sguido	This module uses strtok(3), which may cause conflicts with other
532224Sguido	uses of that same routine.
542224Sguido
552224Sguido    AUTHOR
562224Sguido	Wietse Venema (wietse@wzv.win.tue.nl)
572224Sguido	Eindhoven University of Technology
582224Sguido	The Netherlands
592224Sguido */
602224Sguido
6187233Smarkm#include <sys/cdefs.h>
6287233Smarkm__FBSDID("$FreeBSD$");
6387233Smarkm
642224Sguido#include <sys/types.h>
6529922Smarkm#include <sys/stat.h>
662224Sguido#include <errno.h>
6785504Srwatson#include <glob.h>
6887180Smarkm#include <stdio.h>
6987180Smarkm#include <string.h>
7087180Smarkm#include <syslog.h>
7129922Smarkm#include <unistd.h>
7287173Smarkm
73200462Sdelphij#include "login.h"
742224Sguido#include "pathnames.h"
752224Sguido
7692920Simpstatic void	login_protect(const char *, char *, int, uid_t, gid_t);
772224Sguido
782224Sguido#define	WSPACE		" \t\n"
792224Sguido
802224Sguido/* login_fbtab - apply protections specified in /etc/fbtab or logindevperm */
812224Sguido
822224Sguidovoid
83201382Sedlogin_fbtab(char *tty, uid_t uid, gid_t gid)
842224Sguido{
852224Sguido    FILE   *fp;
862224Sguido    char    buf[BUFSIZ];
872224Sguido    char   *devname;
882224Sguido    char   *cp;
892224Sguido    int     prot;
9087173Smarkm    const char *table;
912224Sguido
92172261Skevlo    if ((fp = fopen(table = _PATH_FBTAB, "r")) == NULL
93172261Skevlo    && (fp = fopen(table = _PATH_LOGINDEVPERM, "r")) == NULL)
942224Sguido	return;
952224Sguido
962224Sguido    while (fgets(buf, sizeof(buf), fp)) {
9729922Smarkm	if ((cp = strchr(buf, '#')))
982224Sguido	    *cp = 0;				/* strip comment */
992224Sguido	if ((cp = devname = strtok(buf, WSPACE)) == 0)
1002224Sguido	    continue;				/* empty or comment */
10169793Sobrien	if (strncmp(devname, _PATH_DEV, sizeof _PATH_DEV - 1) != 0
102231651Skevlo	       || (cp = strtok(NULL, WSPACE)) == 0
1032224Sguido	       || *cp != '0'
1042224Sguido	       || sscanf(cp, "%o", &prot) == 0
1052224Sguido	       || prot == 0
1062224Sguido	       || (prot & 0777) != prot
107231651Skevlo	       || (cp = strtok(NULL, WSPACE)) == 0) {
1082224Sguido	    syslog(LOG_ERR, "%s: bad entry: %s", table, cp ? cp : "(null)");
1092224Sguido	    continue;
1102224Sguido	}
1112224Sguido	if (strcmp(devname + 5, tty) == 0) {
112231651Skevlo	    for (cp = strtok(cp, ":"); cp; cp = strtok(NULL, ":")) {
1132224Sguido		login_protect(table, cp, prot, uid, gid);
1142224Sguido	    }
1152224Sguido	}
1162224Sguido    }
1172224Sguido    fclose(fp);
1182224Sguido}
1192224Sguido
1202224Sguido/* login_protect - protect one device entry */
1212224Sguido
122288164Sdelphijstatic void
123201382Sedlogin_protect(const char *table, char *pattern, int mask, uid_t uid, gid_t gid)
1242224Sguido{
12585645Srwatson    glob_t  gl;
12685645Srwatson    char   *path;
127169342Sdwmalone    unsigned int     i;
1282224Sguido
12985645Srwatson    if (glob(pattern, GLOB_NOSORT, NULL, &gl) != 0)
13085645Srwatson	return;
13185645Srwatson    for (i = 0; i < gl.gl_pathc; i++) {
13285645Srwatson	path = gl.gl_pathv[i];
13385645Srwatson	/* clear flags of the device */
13485645Srwatson	if (chflags(path, 0) && errno != ENOENT && errno != EOPNOTSUPP)
13585645Srwatson	    syslog(LOG_ERR, "%s: chflags(%s): %m", table, path);
13685645Srwatson	if (chmod(path, mask) && errno != ENOENT)
13785645Srwatson	    syslog(LOG_ERR, "%s: chmod(%s): %m", table, path);
13885645Srwatson	if (chown(path, uid, gid) && errno != ENOENT)
13985645Srwatson	    syslog(LOG_ERR, "%s: chown(%s): %m", table, path);
14085645Srwatson    }
14185645Srwatson    globfree(&gl);
1422224Sguido}
143