GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libutil/login_fbtab.c Lines: 0 58 0.0 %
Date: 2017-11-07 Branches: 0 52 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: login_fbtab.c,v 1.16 2015/11/27 01:57:59 mmcc Exp $	*/
2
3
/************************************************************************
4
* Copyright 1995 by Wietse Venema.  All rights reserved.  Some individual
5
* files may be covered by other copyrights.
6
*
7
* This material was originally written and compiled by Wietse Venema at
8
* Eindhoven University of Technology, The Netherlands, in 1990, 1991,
9
* 1992, 1993, 1994 and 1995.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that this entire copyright notice
13
* is duplicated in all such copies.
14
*
15
* This software is provided "as is" and without any expressed or implied
16
* warranties, including, without limitation, the implied warranties of
17
* merchantibility and fitness for any particular purpose.
18
************************************************************************/
19
/*
20
    SYNOPSIS
21
	void login_fbtab(tty, uid, gid)
22
	char *tty;
23
	uid_t uid;
24
	gid_t gid;
25
26
    DESCRIPTION
27
	This module implements device security as described in the
28
	SunOS 4.1.x fbtab(5) and SunOS 5.x logindevperm(4) manual
29
	pages. The program first looks for /etc/fbtab. If that file
30
	cannot be opened it attempts to process /etc/logindevperm.
31
	We expect entries with the folowing format:
32
33
	    Comments start with a # and extend to the end of the line.
34
35
	    Blank lines or lines with only a comment are ignored.
36
37
	    All other lines consist of three fields delimited by
38
	    whitespace: a login device (/dev/console), an octal
39
	    permission number (0600), and a ":"-delimited list of
40
	    devices (/dev/kbd:/dev/mouse). All device names are
41
	    absolute paths. A path that ends in "*" refers to all
42
	    directory entries except "." and "..".
43
44
	    If the tty argument (relative path) matches a login device
45
	    name (absolute path), the permissions of the devices in the
46
	    ":"-delimited list are set as specified in the second
47
	    field, and their ownership is changed to that of the uid
48
	    and gid arguments.
49
50
    DIAGNOSTICS
51
	Problems are reported via the syslog daemon with severity
52
	LOG_ERR.
53
54
    AUTHOR
55
	Wietse Venema (wietse@wzv.win.tue.nl)
56
	Eindhoven University of Technology
57
	The Netherlands
58
 */
59
60
#include <sys/types.h>
61
#include <sys/stat.h>
62
63
#include <errno.h>
64
#include <dirent.h>
65
#include <limits.h>
66
#include <paths.h>
67
#include <stdio.h>
68
#include <stdlib.h>
69
#include <string.h>
70
#include <syslog.h>
71
#include <unistd.h>
72
#include <util.h>
73
74
#define _PATH_FBTAB	"/etc/fbtab"
75
76
static void login_protect(const char *, mode_t, uid_t, gid_t);
77
78
#define	WSPACE		" \t\n"
79
80
/*
81
 * login_fbtab - apply protections specified in /etc/fbtab or logindevperm
82
 */
83
void
84
login_fbtab(const char *tty, uid_t uid, gid_t gid)
85
{
86
	FILE	*fp;
87
	char	*buf, *toklast, *tbuf, *devnam, *cp;
88
	mode_t	prot;
89
	size_t	len;
90
91
	if ((fp = fopen(_PATH_FBTAB, "r")) == NULL)
92
		return;
93
94
	tbuf = NULL;
95
	while ((buf = fgetln(fp, &len)) != NULL) {
96
		if (buf[len - 1] == '\n')
97
			buf[len - 1] = '\0';
98
		else {
99
			if ((tbuf = malloc(len + 1)) == NULL)
100
				break;
101
			memcpy(tbuf, buf, len);
102
			tbuf[len] = '\0';
103
			buf = tbuf;
104
		}
105
		if ((cp = strchr(buf, '#')))
106
			*cp = '\0';	/* strip comment */
107
		if (buf[0] == '\0' ||
108
		    (cp = devnam = strtok_r(buf, WSPACE, &toklast)) == NULL)
109
			continue;	/* empty or comment */
110
		if (strncmp(devnam, _PATH_DEV, sizeof(_PATH_DEV) - 1) != 0 ||
111
		    (cp = strtok_r(NULL, WSPACE, &toklast)) == NULL ||
112
		    *cp != '0' ||
113
		    sscanf(cp, "%o", &prot) == 0 ||
114
		    prot == 0 ||
115
		    (prot & 0777) != prot ||
116
		    (cp = strtok_r(NULL, WSPACE, &toklast)) == NULL) {
117
			syslog(LOG_ERR, "%s: bad entry: %s", _PATH_FBTAB,
118
			    cp ? cp : "(null)");
119
			continue;
120
		}
121
		if (strcmp(devnam + sizeof(_PATH_DEV) - 1, tty) == 0) {
122
			for (cp = strtok_r(cp, ":", &toklast); cp != NULL;
123
			    cp = strtok_r(NULL, ":", &toklast))
124
				login_protect(cp, prot, uid, gid);
125
		}
126
	}
127
	free(tbuf);
128
	fclose(fp);
129
}
130
131
/*
132
 * login_protect - protect one device entry
133
 */
134
static void
135
login_protect(const char *path, mode_t mask, uid_t uid, gid_t gid)
136
{
137
	char	buf[PATH_MAX];
138
	size_t	pathlen = strlen(path);
139
	DIR	*dir;
140
	struct	dirent *ent;
141
142
	if (pathlen >= sizeof(buf)) {
143
		errno = ENAMETOOLONG;
144
		syslog(LOG_ERR, "%s: %s: %m", _PATH_FBTAB, path);
145
		return;
146
	}
147
148
	if (strcmp("/*", path + pathlen - 2) != 0) {
149
		if (chmod(path, mask) && errno != ENOENT)
150
			syslog(LOG_ERR, "%s: chmod(%s): %m", _PATH_FBTAB, path);
151
		if (chown(path, uid, gid) && errno != ENOENT)
152
			syslog(LOG_ERR, "%s: chown(%s): %m", _PATH_FBTAB, path);
153
	} else {
154
		/*
155
		 * This is a wildcard directory (/path/to/whatever/ * ).
156
		 * Make a copy of path without the trailing '*' (but leave
157
		 * the trailing '/' so we can append directory entries.)
158
		 */
159
		memcpy(buf, path, pathlen - 1);
160
		buf[pathlen - 1] = '\0';
161
		if ((dir = opendir(buf)) == NULL) {
162
			syslog(LOG_ERR, "%s: opendir(%s): %m", _PATH_FBTAB,
163
			    path);
164
			return;
165
		}
166
167
		while ((ent = readdir(dir)) != NULL) {
168
			if (strcmp(ent->d_name, ".")  != 0 &&
169
			    strcmp(ent->d_name, "..") != 0) {
170
				buf[pathlen - 1] = '\0';
171
				if (strlcat(buf, ent->d_name, sizeof(buf))
172
				    >= sizeof(buf)) {
173
					errno = ENAMETOOLONG;
174
					syslog(LOG_ERR, "%s: %s: %m",
175
					    _PATH_FBTAB, path);
176
				} else
177
					login_protect(buf, mask, uid, gid);
178
			}
179
		}
180
		closedir(dir);
181
	}
182
}