/* Copyright (C) 1998,2001 Free Software Foundation, Inc. This file is part of GNU Inetutils. GNU Inetutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Inetutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Inetutils; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "telnetd.h" #include #include #ifdef AUTHENTICATION # include #endif extern char line[256]; void setup_utmp (char *line) { char *ut_id = utmp_ptsid (line, "tn"); utmp_init (line + sizeof ("/dev/") - 1, ".telnet", ut_id); } int startslave (char *host, int autologin, char *autoname) { pid_t pid; static int master; int slave_pty; char *slave; char bbuf[1024]; #ifdef AUTHENTICATION if (!autoname || !autoname[0]) autologin = 0; if (autologin < auth_level) { fatal (net, "Authorization failed"); exit (1); } #endif #define SOFLGS O_RDWR | O_NOCTTY slave_pty = open("/dev/ptc",SOFLGS); if((slave_pty == 0) || (slave_pty < 0)) { sprintf(bbuf,"openpty: %d",errno); fatal(net, bbuf); } if(grantpt(slave_pty) < 0) { sprintf(bbuf,"grant: %d",errno); fatal (net, bbuf); pid = -1; } else { if(unlockpt(slave_pty) < 0) { fatal (net, "unlock pty"); pid = -1; } else { slave = ptsname(slave_pty); strncpy(line,slave,256); #define MASTER_OUTSIDE_FORK 1 #ifdef MASTER_OUTSIDE_FORK master = open(slave, SOFLGS); if(master < 0) { fatal (net, "open slave"); debug_output_data("fatal: failed to open %s\n",slave); pid = -1; } else { #endif pid = fork(); if(pid) { #ifdef MASTER_OUTSIDE_FORK //ioctl(master, TIOCUCNTL, 1); ioctl(master, I_PUSH, "ldterm"); #endif debug_output_data("fork() called - child is pid %d master is %d slave is %s slave_pty is %d\n",pid,master,slave,slave_pty); } else { #ifndef MASTER_OUTSIDE_FORK master = open(slave, SOFLGS); if(master < 0) { fatal(net, "open master"); pid = -1; } #endif if(login_tty(master)) { fatal(net, "login_tty"); pid = -1; } debug_output_data("login_tty called for master\n"); } #ifdef MASTER_OUTSIDE_FORK } #endif } } if (pid < 0) { if (errno == ENOENT) { syslog (LOG_ERR, "Out of ptys (sheer)"); fatal (net, "Out of ptys (Sheer) "); } else { syslog (LOG_ERR, "forkpty: %m"); fatal (net, "Forkpty"); } } if (pid == 0) { /* Child */ debug_output_data("CHILD: Net: %d master: %d\n",net,master); if (net > 2) close (net); #ifdef UTMPX setup_utmp (line); #endif start_login (host, autologin, line); } /* Master */ return master; // return slave_pty; } extern char **environ; /* * scrub_env() * * Remove a few things from the environment that * don't need to be there. * * Security fix included in telnet-95.10.23.NE of David Borman . */ static void scrub_env () { register char **cpp, **cpp2; for (cpp2 = cpp = environ; *cpp; cpp++) { if (strncmp (*cpp, "LD_", 3) && strncmp (*cpp, "_RLD_", 5) && strncmp (*cpp, "LIBPATH=", 8) && strncmp (*cpp, "IFS=", 4)) *cpp2++ = *cpp; } *cpp2 = 0; } void start_login (char *host, int autologin, char *name) { char *cmd; int argc; char **argv; scrub_env (); debug_output_data("start_login %s\n", name); /* Set the environment variable "LINEMODE" to indicate our linemode */ if (lmodetype == REAL_LINEMODE) setenv ("LINEMODE", "real", 1); else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) setenv ("LINEMODE", "kludge", 1); cmd = expand_line (login_invocation); if (!cmd) fatal (net, "can't expand login command line"); argcv_get (cmd, "", &argc, &argv); debug_output_data("execute command: %s\n", cmd); execv (argv[0], argv); syslog (LOG_ERR, "%s: %m\n", cmd); fatalperror (net, cmd); } void cleanup (int sig) { char *p; if (sig) { int status; pid_t pid = waitpid((pid_t)-1, &status, WNOHANG); syslog (LOG_INFO, "child process %ld exited: %d", (long) pid, WEXITSTATUS(status)); } p = line + sizeof (PATH_DEV) - 1; utmp_logout (p); chmod (line, 0644); chown (line, 0, 0); shutdown (net, 2); exit (1); }