2
* Copyright (c) 2000 David A. Holland.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. All advertising materials mentioning features or use of this software
14
* must display the following acknowledgement:
15
* This product includes software developed by David A. Holland.
16
* 4. Neither the name of the Author nor the names of any contributors
17
* may be used to endorse or promote products derived from this software
18
* without specific prior written permission.
20
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND ANY CONTRIBUTORS ``AS IS'' AND
21
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR ANY CONTRIBUTORS BE LIABLE
24
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
"@(#) Copyright (c) 2000 David A. Holland.\n"
35
"All rights reserved.\n";
38
"$Id: telnetlogin.c,v 1.1 2000/04/13 01:07:22 dholland Exp $";
39
#include "../version.h"
41
#include <sys/types.h>
43
#include <sys/ioctl.h>
56
#define _PATH_LOGIN "/bin/login"
59
static const char *remhost = NULL;
61
static void die(const char *fmt, ...) {
63
fprintf(stderr, "telnetlogin: ");
65
vfprintf(stderr, fmt, ap);
67
fprintf(stderr, "\n");
71
static int check_a_hostname(char *hname) {
73
/* should we check length? */
74
for (i=0; hname[i]; i++) {
75
if (hname[i]<=32 && hname[i]>126) return -1;
80
static int check_term(char *termtype) {
82
if (strlen(termtype) > 32) return -1;
83
for (i=0; termtype[i]; i++) {
84
if (!isalnum(termtype[i]) && !strchr("+._-", termtype[i])) return -1;
89
static int check_display(char *disp) {
94
colon = strchr(disp, ':');
95
if (!colon) return -1;
96
*colon = 0; /* temporarily */
98
if (check_a_hostname(disp)) return -1;
100
hp = gethostbyname(disp);
105
while (*s && isdigit(*s)) s++;
107
if (*s!='.') return -1;
109
while (*s && isdigit(*s)) s++;
114
if (num<0 || num>99) return -1;
119
static int check_posixly_correct(char *val) {
120
if (strlen(val)==0 || !strcmp(val, "1")) return 0;
124
static int check_remotehost(char *val) {
125
if (check_a_hostname(val)) return -1;
126
if (remhost && strcmp(val, remhost)) return -1;
132
int (*validator)(char *);
134
{ "TERM", check_term },
135
{ "DISPLAY", check_display },
136
{ "POSIXLY_CORRECT", check_posixly_correct },
137
{ "REMOTEHOST", check_remotehost },
141
static void validate_tty(void) {
142
struct stat buf, buf2;
147
if (!tty) die("stdin not a tty");
149
if (fstat(0, &buf)) die("fstat stdin");
150
if (!S_ISCHR(buf.st_mode)) die("stdin not char device");
152
if (fstat(1, &buf2)) die("fstat stdout");
153
if (!S_ISCHR(buf2.st_mode)) die("stdout not char device");
154
if (buf.st_rdev!=buf2.st_rdev) die("stdout and stdin not same tty");
156
if (fstat(2, &buf2)) die("fstat stderr");
157
if (!S_ISCHR(buf2.st_mode)) die("stderr not char device");
158
if (buf.st_rdev!=buf2.st_rdev) die("stderr and stdin not same tty");
160
if (ioctl(0, TIOCGPGRP, &pgrp)) die("cannot get tty process group");
161
if (pgrp != getpgrp()) die("not foreground pgrp of tty");
162
if (pgrp != getpid()) die("not process group leader");
165
int main(int argc, char *argv[]) {
166
static char argv0[] = "login";
168
const char *rh = NULL;
169
char **envs = __environ;
171
/* make as sure as possible no library routines or anything can use it */
174
/* first, make sure our stdin/stdout/stderr are aimed somewhere */
175
i = open("/", O_RDONLY);
177
/* Oops. Can't even print an error message... */
185
die("Illegal args: argc < 1");
187
if (argn < argc && !strcmp(argv[argn], "-h")) {
189
if (argn==argc) die("Illegal args: -h requires argument");
190
if (check_a_hostname(argv[argn])) die("Illegal remote host specified");
194
if (argn < argc && !strcmp(argv[argn], "-p")) {
197
if (argn < argc) die("Illegal args: too many args");
200
/* check environment */
201
if (envs) for (i=0; envs[i]; i++) {
202
char *testenv = envs[i];
203
size_t testlen = strlen(testenv);
205
for (j=0; legal_envs[j].name && !ok; j++) {
206
const char *okenv = legal_envs[j].name;
207
size_t oklen = strlen(okenv);
209
if (testlen < oklen) continue;
210
if (testenv[oklen]!='=') continue;
211
if (memcmp(testenv, okenv, oklen)) continue;
212
if (legal_envs[j].validator(testenv+oklen+1)) {
213
die("Invalid environment: bad value for %s", okenv);
218
die("Illegal environment: forbidden variable");
222
/* unignore all signals so they get cleared at exec time */
223
for (i=1; i<NSIG; i++) {
228
if (chdir("/")) die("chdir to / failed");
231
* don't do anything with uids and gids, as login is normally meant
232
* to be able to take care of them.
234
* but, should we insist that ruid==nobody?
238
* don't do anything with limits, itimers, or process priority either
242
* should we check to make sure stdin=stdout=stderr and they're a tty
243
* and it's our controlling tty [hard] and we're the leader of the
244
* foreground process group?
252
* argv[0] was set up above.
254
execve(_PATH_LOGIN, argv, envs);