]>
Commit | Line | Data |
---|---|---|
2fc1e207 A |
1 | /* $NetBSD: utmp_update.c,v 1.6 2003/02/26 18:16:50 christos Exp $ */ |
2 | ||
3 | /*- | |
4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | |
6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Christos Zoulas. | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | |
18 | * 3. All advertising materials mentioning features or use of this software | |
19 | * must display the following acknowledgement: | |
20 | * This product includes software developed by the NetBSD | |
21 | * Foundation, Inc. and its contributors. | |
22 | * 4. Neither the name of The NetBSD Foundation nor the names of its | |
23 | * contributors may be used to endorse or promote products derived | |
24 | * from this software without specific prior written permission. | |
25 | * | |
26 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
36 | * POSSIBILITY OF SUCH DAMAGE. | |
37 | */ | |
38 | #include <sys/cdefs.h> | |
39 | ||
40 | __RCSID("$NetBSD: utmp_update.c,v 1.6 2003/02/26 18:16:50 christos Exp $"); | |
41 | ||
42 | #include <sys/types.h> | |
43 | #include <sys/param.h> | |
44 | #include <sys/stat.h> | |
45 | ||
46 | #include <stdio.h> | |
47 | #include <vis.h> | |
48 | #include <err.h> | |
49 | #include <fcntl.h> | |
50 | #include <pwd.h> | |
51 | #include <utmpx.h> | |
52 | #include <stdlib.h> | |
53 | #include <string.h> | |
54 | #include <unistd.h> | |
55 | #include <paths.h> | |
56 | ||
57 | int main(int, char *[]); | |
58 | ||
59 | int | |
60 | main(int argc, char *argv[]) | |
61 | { | |
62 | struct utmpx *utx; | |
63 | size_t len; | |
64 | struct passwd *pwd; | |
65 | struct stat st; | |
66 | int fd; | |
67 | uid_t euid, ruid; | |
68 | char tty[MAXPATHLEN]; | |
69 | ||
70 | euid = geteuid(); | |
71 | ruid = getuid(); | |
72 | if (seteuid(ruid) == -1) | |
73 | err(1, "seteuid"); | |
74 | ||
75 | if (argc != 2) { | |
76 | (void)fprintf(stderr, "Usage: %s <vis-utmpx-entry>\n", | |
77 | getprogname()); | |
78 | exit(1); | |
79 | } | |
80 | ||
81 | len = strlen(argv[1]); | |
82 | ||
83 | // arg string can't be greater the 4x the size of struct utmpx | |
84 | // nor less that the size of struct utmpx | |
85 | if (len > sizeof(*utx) * 4 || len < sizeof(*utx)) | |
86 | errx(1, "Bad argument"); | |
87 | ||
88 | // need an extra byte because strunvis will null terminate | |
89 | if ((utx = malloc(len + 1)) == NULL) | |
90 | err(1, NULL); | |
91 | ||
92 | if (strunvis((char *)utx, argv[1]) != sizeof(*utx)) | |
93 | errx(1, "Decoding error"); | |
94 | ||
95 | switch (utx->ut_type) { | |
96 | case USER_PROCESS: | |
97 | case DEAD_PROCESS: | |
98 | break; | |
99 | default: | |
100 | errx(1, "Invalid utmpx type %d", (int)utx->ut_type); | |
101 | } | |
102 | ||
103 | if (ruid != 0) { | |
104 | if ((pwd = getpwuid(ruid)) == NULL) | |
105 | errx(1, "User %lu does not exist in password database", | |
106 | (long)ruid); | |
107 | ||
108 | if (strcmp(pwd->pw_name, utx->ut_user) != 0) | |
109 | errx(1, "Current user `%s' does not match " | |
110 | "`%s' in utmpx entry", pwd->pw_name, utx->ut_user); | |
111 | } | |
112 | ||
113 | (void)snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, utx->ut_line); | |
114 | fd = open(tty, O_RDONLY, 0); | |
115 | if (fd != -1) { | |
116 | if (fstat(fd, &st) == -1) | |
117 | err(1, "Cannot stat `%s'", tty); | |
118 | if (ruid != 0 && st.st_uid != ruid) | |
119 | errx(1, "%s: Is not owned by you", tty); | |
120 | if (!isatty(fd)) | |
121 | errx(1, "%s: Not a tty device", tty); | |
122 | (void)close(fd); | |
123 | if (access(tty, W_OK|R_OK) == -1) | |
124 | err(1, "%s", tty); | |
125 | } else { | |
126 | struct utmpx utold, *utoldp; | |
127 | /* | |
128 | * A daemon like ftpd that does not use a tty line? | |
129 | * We only allow it to kill its own existing entries | |
130 | */ | |
131 | if (utx->ut_type != DEAD_PROCESS) | |
132 | err(1, "Cannot open `%s'", tty); | |
133 | ||
134 | (void)memcpy(utold.ut_line, utx->ut_line, sizeof(utx->ut_line)); | |
135 | if ((utoldp = getutxline(&utold)) == NULL) | |
136 | err(1, "Cannot find existing entry for `%s'", | |
137 | utx->ut_line); | |
138 | if (utoldp->ut_pid != getppid()) | |
139 | err(1, "Cannot modify entry for `%s'", tty); | |
140 | } | |
141 | ||
142 | (void)seteuid(euid); | |
143 | if (pututxline(utx) == NULL) | |
144 | err(1, "Cannot update utmp entry"); | |
145 | ||
146 | return 0; | |
147 | } |