コード例 #1
0
ファイル: frame.c プロジェクト: commshare/squeezeterisk
/* --------------------------------------------------------------------
   Reads the stated input file bufferwise, calls the function 'work'
   with the proper values, and writes the result to the stated output file.
   Return value: TRUE on success, FALSE otherwise.
   -------------------------------------------------------------------- */
int workloop( FILE *theinfile, FILE *theoutfile,
	      int (*work)( short *buffer, int length) )
{
  short *buffer;
  int length, nowlength;

  length = BUFFSIZE;
  if ((buffer = malloc( sizeof(short) * length)) == NULL)
    fatalperror ("");
  while (TRUE)
    {
      nowlength = fread(buffer, sizeof(short), length, theinfile);
      if (ferror( theinfile) != 0)
	fatalperror("Error reading input file");
      if (nowlength == 0)   /* Reached end of input file */
	break;
      /* Call the routine that does the work */
      if (!work (buffer, nowlength))         /* On error, stop. */
	return FALSE;
      fwrite(buffer, sizeof(short), nowlength, theoutfile);
      if (ferror( theoutfile) != 0)
	fatalperror("Error writing to output file");
    }
  return TRUE;      /* Input file done with, no errors. */
}
コード例 #2
0
int login_tty(int t) {
    if (setsid() < 0) fatalperror(net, "setsid()");
    if (ioctl(t, TIOCSCTTY, (char *)0) < 0) {
	fatalperror(net, "ioctl(sctty)");
    }
    if (t != 0) dup2(t, 0);
    if (t != 1) dup2(t, 1);
    if (t != 2) dup2(t, 2);
    if (t > 2) close(t);
    return 0;
}
コード例 #3
0
/* ARGSUSED */
void
startslave(char *host, int autologin, char *autoname)
{
	int i;

#ifdef AUTHENTICATION
	if (!autoname || !autoname[0])
		autologin = 0;

	if (autologin < auth_level) {
		fatal(net, "Authorization failed");
		exit(1);
	}
#endif


	if ((i = fork()) < 0)
		fatalperror(net, "fork");
	if (i) {
	} else {
		getptyslave();
		start_login(host, autologin, autoname);
		/*NOTREACHED*/
	}
}
コード例 #4
0
ファイル: frame.c プロジェクト: commshare/squeezeterisk
char *parsefilearg( int argcount, char *args[])
{
  int i;
  char *result = NULL;

   for (i = 1; i < argcount; i++)
   {
      if (args[i][0] != '\0' &&
	  (!isoptionchar (args[i][0]) || args[i][1] == '\0' ))
      {
	/*---------------------------------------------*
	 * The argument is a filename:                 *
	 * it is either no dash followed by something, *
	 * or it is a dash following by nothing.       *
	 *---------------------------------------------*/
	result = malloc( strlen( args[i]) + 1);
	if (result == NULL)
	    fatalperror( "Couldn't allocate memory for filename\n");
	strcpy( result, args[i]);
	args[i][0] = '\0';                    /* Mark as used up */
	break;
      }
   }
   return result;
}
コード例 #5
0
/* ARGSUSED */
void startslave(const char *host, int autologin, char *autoname) {
    int i;

#if defined(AUTHENTICATE)
    if (!autoname || !autoname[0]) autologin = 0;
    if (autologin < auth_level) {
	fatal(net, "Authorization failed");
	exit(1);
    }
#endif

    i = fork();
    if (i < 0) fatalperror(net, "fork");
    if (i) {
	/* parent */
	signal(SIGHUP,SIG_IGN);
	close(ptyslavefd);
    } 
    else {
	/* child */
	signal(SIGHUP,SIG_IGN);
	getptyslave();
	start_login(host, autologin, autoname);
	/*NOTREACHED*/
    }
}
コード例 #6
0
ファイル: sys_term.c プロジェクト: 2asoft/freebsd
int login_tty(int t)
{
    /* Dont need to set this as the controlling PTY on steams sockets,
     * don't abort on failure. */
# if defined(TIOCSCTTY) && !defined(__hpux)
    if (ioctl(t, TIOCSCTTY, (char *)0) < 0 && !really_stream)
	fatalperror(net, "ioctl(sctty)");
#  ifdef _CRAY
    /*
     * Close the hard fd to /dev/ttypXXX, and re-open through
     * the indirect /dev/tty interface.
     */
    close(t);
    if ((t = open("/dev/tty", O_RDWR)) < 0)
	fatalperror(net, "open(/dev/tty)");
#  endif
# else
    /*
     * We get our controlling tty assigned as a side-effect
     * of opening up a tty device.  But on BSD based systems,
     * this only happens if our process group is zero.  The
     * setsid() call above may have set our pgrp, so clear
     * it out before opening the tty...
     */
#ifdef HAVE_SETPGID
    setpgid(0, 0);
#else
    setpgrp(0, 0); /* if setpgid isn't available, setpgrp
		      probably takes arguments */
#endif
    close(open(line, O_RDWR));
# endif
    if (t != 0)
	dup2(t, 0);
    if (t != 1)
	dup2(t, 1);
    if (t != 2)
	dup2(t, 2);
    if (t > 2)
	close(t);
    return(0);
}
コード例 #7
0
ファイル: frame.c プロジェクト: commshare/squeezeterisk
void readawaysamples( FILE *in, size_t size)
{
  short *buffer;
  int samplesread, count;

  buffer = malloc( sizeof( *buffer) * BUFFSIZE);
  if (buffer == NULL) fatalperror("Couldn't allocate buffer");

  while (size > 0)
    {
      if (size > BUFFSIZE)
	count = BUFFSIZE;
      else
	count = size;

      samplesread = fread( buffer, sizeof(*buffer), count, in);
      if (ferror( in) != 0)
	fatalperror("Error reading input file");
      size -= samplesread;
    }
  free( buffer);
}
コード例 #8
0
ファイル: sys_term.c プロジェクト: 2asoft/freebsd
static void maybe_push_modules(int fd, char **modules)
{
    char **p;
    int err;

    for(p=modules; *p; p++){
	err = my_find(fd, *p);
	if(err == 1)
	    break;
	if(err < 0 && errno != EINVAL)
	    fatalperror(net, "my_find()");
	/* module not pushed or does not exist */
    }
    /* p points to null or to an already pushed module, now push all
       modules before this one */

    for(p--; p >= modules; p--){
	err = ioctl(fd, I_PUSH, *p);
	if(err < 0 && errno != EINVAL)
	    fatalperror(net, "I_PUSH");
    }
}
コード例 #9
0
ファイル: newm.c プロジェクト: BenjiWiebe/newm
void run_command(char *cmd)
{
	pid_t pid = fork();
	if(pid == 0) /* Child process */
	{
		system(cmd);
		exit(EXIT_SUCCESS);
	}
	else if(pid == -1) /* Error */
	{
		fatalperror("fork");
	}
	else /* Parent, after child was successfully started */
	{
		waitpid((pid_t)-1, NULL, WNOHANG);
	}

}
コード例 #10
0
ファイル: newm.c プロジェクト: BenjiWiebe/newm
void watch_and_wait(int inotifyfd, int stdoutfd)
{
	while(1)
	{
		fd_set read;
		struct timeval watchtimeout;
		FD_ZERO(&read);
		FD_SET(inotifyfd, &read);
		watchtimeout.tv_sec = 30;
		watchtimeout.tv_usec = 0;
		int ret = select(inotifyfd+1, &read, NULL, NULL, &watchtimeout);
		if(ret < 0)
		{
			fatalperror("select");
		}
		if(!isatty(stdoutfd))
			exit(0);
		if(ret > 0)
			break;
	}
}
コード例 #11
0
/*
 * Check a descriptor to see if out of band data exists on it.
 */
int
stilloob(int s)
{
    static struct timeval timeout = { 0, 0 };
    fd_set	excepts;
    int value;

    do {
	FD_ZERO(&excepts);
	FD_SET(s, &excepts);
	memset((char *)&timeout, 0, sizeof timeout);
	value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
    } while ((value == -1) && (errno == EINTR));

    if (value < 0) {
	fatalperror(pty, "select");
    }
    if (FD_ISSET(s, &excepts)) {
	return 1;
    } else {
	return 0;
    }
}
コード例 #12
0
ファイル: telnetd.c プロジェクト: marado/netkit-telnet-ssl
static void
wait_for_connection(const char *service)
{
	struct addrinfo hints;
	struct addrinfo *res, *addr;
	struct pollfd *fds, *fdp;
	int nfds;
	int i;
	int error;
	int on = 1;

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_flags = AI_PASSIVE;
	hints.ai_socktype = SOCK_STREAM;
	error = getaddrinfo(NULL, service, &hints, &res);
	if (error) {
		char *p;
		error = asprintf(&p, "getaddrinfo: %s\n", gai_strerror(error));
		fatal(2, error >= 0 ? p : "");
	}

	for (addr = res, nfds = 0; addr; addr = addr->ai_next, nfds++)
		;
	fds = malloc(sizeof(struct pollfd) * nfds);
	for (addr = res, fdp = fds; addr; addr = addr->ai_next, fdp++) {
		int s;

		if (addr->ai_family == AF_LOCAL) {
nextaddr:
			fdp--;
			nfds--;
			continue;
		}

		s = socket(addr->ai_family, SOCK_STREAM, 0);
		if (s < 0) {
			if (errno == EAFNOSUPPORT || errno == EINVAL) {
				goto nextaddr;
			}
			fatalperror(2, "socket");
		}
		if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) {
			fatalperror(2, "setsockopt");
		}
		if (bind(s, addr->ai_addr, addr->ai_addrlen)) {
#ifdef linux
			if (fdp != fds && errno == EADDRINUSE) {
				close(s);
				goto nextaddr;
			}
#endif
			fatalperror(2, "bind");
		}
		if (listen(s, 1)) {
			fatalperror(2, "listen");
		}
		if (fcntl(s, F_SETFL, O_NONBLOCK)) {
			fatalperror(2, "fcntl");
		}

		fdp->fd = s;
		fdp->events = POLLIN;
	}

	freeaddrinfo(res);

	while (1) {
		if (poll(fds, nfds, -1) < 0) {
			if (errno == EINTR) {
				continue;
			}
			fatalperror(2, "poll");
		}

		for (i = 0, fdp = fds; i < nfds; i++, fdp++) {
			int fd;

			if (!(fdp->revents & POLLIN)) {
				continue;
			}

			fd = accept(fdp->fd, 0, 0);
			if (fd >= 0) {
				dup2(fd, 0);
				close(fd);
				goto out;
			}
			if (errno != EAGAIN) {
				fatalperror(2, "accept");
			}
		}
	}

out:
	for (i = 0, fdp = fds; i < nfds; i++, fdp++) {
		close(fdp->fd);
	}
	free(fds);
}
コード例 #13
0
ファイル: telnetd.c プロジェクト: marado/netkit-telnet-ssl
/*
 * Get a pty, scan input lines.
 */
static void
doit(struct sockaddr *who, socklen_t who_len)
{
	char *host;
	int level;
	char user_name[256];
	int i;
	struct addrinfo hints, *res;

	/*
	 * Find an available pty to use.
	 */
	pty = getpty();
	if (pty < 0)
		fatalperror(net, "getpty");

	/* get name of connected client */
	if (getnameinfo(who, who_len, remote_host_name,
			sizeof(remote_host_name), 0, 0, 
			numeric_hosts ? NI_NUMERICHOST : 0)) {
		syslog(LOG_ERR, "doit: getnameinfo: %m");
		*remote_host_name = 0;
        }

	/* Disallow funnies. */
	for (i=0; remote_host_name[i]; i++) {
	    if (remote_host_name[i]<=32 || remote_host_name[i]>126) 
		remote_host_name[i] = '?';
	}
	host = remote_host_name;

	/* Get local host name */
	gethostname(host_name, sizeof(host_name));
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_flags = AI_CANONNAME;
	if ((i = getaddrinfo(host_name, 0, &hints, &res)))
		syslog(LOG_WARNING, "doit: getaddrinfo: %s", gai_strerror(i));
	else {
		strncpy(host_name, res->ai_canonname, sizeof(host_name)-1);
		host_name[sizeof(host_name)-1] = 0;
	}

#if	defined(AUTHENTICATE) || defined(ENCRYPT)
	auth_encrypt_init(host_name, host, "TELNETD", 1);
#endif

	init_env();
	/*
	 * get terminal type.
	 */
	*user_name = 0;
	level = getterminaltype(user_name);
	setenv("TERM", terminaltype ? terminaltype : "network", 1);

	/* TODO list stuff provided by Laszlo Vecsey <*****@*****.**> */

#ifdef USE_SSL
	if (debug) {
	    fprintf(stderr,"doit - ALIVE\n");
	    fflush(stderr);
	    sleep(2);
	}
#endif /* USE_SSL */


	/*
	 * Set REMOTEHOST environment variable
	 */
	setproctitle("%s", host);
	setenv("REMOTEHOST", host, 0);

#ifdef USE_SSL
	if (debug) {
	    fprintf(stderr,"doit - starting telnet protocol itself\n");
	    fflush(stderr);
	    sleep(2);
	}
#endif /* USE_SSL */

	/*
	 * Start up the login process on the slave side of the terminal
	 */
	startslave(host, level, user_name);

	telnet(net, pty);  /* begin server processing */

	/*NOTREACHED*/
}  /* end of doit */
コード例 #14
0
ファイル: newm.c プロジェクト: BenjiWiebe/newm
int main()
{
	/* Variables */
	int fd;
	int stdout_fileno;
	char *username;
	char *home;
	char *conf_file_name;

	/* Initialize variables */
	afterlist = ul_create(8);
	beforelist = ul_create(8);
	stdout_fileno = fileno(stdout);

	/* Get our username */
	struct passwd *p = getpwuid(getuid());
	if(p == NULL)
		fatalperror("getpwuid");
	/* warning - username will now point to a static area, subsequent getpwuid calls may overwite it */
	username = p->pw_name;

	/* Get our home directory */
	home = getenv("HOME");
	if(home == NULL)
		fatalerror("$HOME is not set.\n");
	conf_file_name = malloc(strlen(home) + 1 + strlen(conf_file_basename) + 1);
	strcpy(conf_file_name, home);
	strcat(conf_file_name, "/");
	strcat(conf_file_name, conf_file_basename);


	/* Set up atexit */
	atexit(free_mem_on_exit);

	/* Read conf file */
	config = load_config(conf_file_name);

	/* If we are supposed to print a user list upon startup, do it now, before fork()ing */
	if(config->initialshow)
	{
		struct userlist *ls = ul_create(8);
		ul_populate(ls);
		ul_sort(ls);
		if(ls->array[0] == NULL)
		{
			printf("No users logged in.\n");
		}
		else
		{
			printf("Users logged in: ");
			for(int i = 0; ls->array[i] != NULL; i++)
			{
				if(i > 0 && !strcmp(ls->array[i], ls->array[i-1]))
					continue;
				printf("%s, ", ls->array[i]);
			}
			printf("\b\b  \n");
		}
		ul_free(ls);
	}

	/* If we aren't supposed to listen to INs *or* OUTs, no point in continuing */
	if(!config->listen_ins && !config->listen_outs)
		exit(EXIT_SUCCESS);

	/* If we are forking, fork() and then exit the parent */
	if(config->forking)
	{
		pid_t pid = fork();
		if(pid > 0)
			exit(0);
		else if(pid == -1)
			fatalperror("fork");
		/* This setpgid() call changes the process-group ID so 'w' reports the shell (not us!) as the current command */
		setpgid(getpid(),getpid());
		/* Close stdin, and hang up the TTY, since we really can't access them from the "background" */
		close(STDIN_FILENO);
		vhangup();
	}

	/* Set up child-reaping for login-command */
	signal(SIGCHLD, SIG_IGN);

	/* Start and setup inotify */
	fd = inotify_init();
	if(fd < 0)
		fatalperror("inotify_init");
	if(inotify_add_watch(fd, _PATH_UTMP, IN_MODIFY) < 0)
		fatalperror("inotify_add_watch");

	while(1)
	{
		ul_populate(beforelist);

		/* If we are fork()ing, we want to monitor stdout, which requires us to use select() with a timeout */
		if(config->forking)
		{
			watch_and_wait(fd, stdout_fileno);
		}

		struct inotify_event evt;
		if(read(fd, &evt, sizeof(struct inotify_event)) < 0)
			fatalperror("read");

		ul_populate(afterlist);

		int firstlen = ul_count(beforelist);
		int secondlen = ul_count(afterlist);

		if(firstlen == secondlen)
		{
			continue;
		}
		else if(firstlen > secondlen)
		{
			char *r = ul_subtract(beforelist, afterlist);
			if(r == NULL)
				continue;
			if(!strcmp(r, username))
				continue;
			if(config->listen_outs)
				on_logout(r);
		}
		else
		{
			char *r = ul_subtract(afterlist, beforelist);
			if(r == NULL)
				continue;
			if(!strcmp(r, username))
				continue;
			if(config->listen_ins)
				on_login(r);
		}

		if(config->oneshot)
		{
			exit(0);
		}
	}

	exit(SUCCESS);
}
コード例 #15
0
ファイル: in.rlogind.c プロジェクト: AlainODea/illumos-gate
static void
doit(int f,
	struct sockaddr_storage *fromp,
	krb5_context krb_context,
	int encr_flag,
	krb5_keytab keytab)
{
	int p, t, on = 1;
	char c;
	char abuf[INET6_ADDRSTRLEN];
	struct sockaddr_in *sin;
	struct sockaddr_in6 *sin6;
	int fromplen;
	in_port_t port;
	struct termios tp;
	boolean_t bad_port;
	boolean_t no_name;
	char rhost_addra[INET6_ADDRSTRLEN];

	if (!(rlbuf = malloc(BUFSIZ))) {
		syslog(LOG_ERR, "rlbuf malloc failed\n");
		exit(EXIT_FAILURE);
	}
	(void) alarm(60);
	if (read(f, &c, 1) != 1 || c != 0) {
		syslog(LOG_ERR, "failed to receive protocol zero byte\n");
		exit(EXIT_FAILURE);
	}
	(void) alarm(0);
	if (fromp->ss_family == AF_INET) {
		sin = (struct sockaddr_in *)fromp;
		port = sin->sin_port = ntohs((ushort_t)sin->sin_port);
		fromplen = sizeof (struct sockaddr_in);

		if (!inet_ntop(AF_INET, &sin->sin_addr,
			    rhost_addra, sizeof (rhost_addra)))
			goto badconversion;
	} else if (fromp->ss_family == AF_INET6) {
		sin6 = (struct sockaddr_in6 *)fromp;
		port = sin6->sin6_port = ntohs((ushort_t)sin6->sin6_port);
		fromplen = sizeof (struct sockaddr_in6);

		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
			struct in_addr ipv4_addr;

			IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
					    &ipv4_addr);
			if (!inet_ntop(AF_INET, &ipv4_addr, rhost_addra,
				    sizeof (rhost_addra)))
				goto badconversion;
		} else {
			if (!inet_ntop(AF_INET6, &sin6->sin6_addr,
				    rhost_addra, sizeof (rhost_addra)))
				goto badconversion;
		}
	} else {
		syslog(LOG_ERR, "unknown address family %d\n",
		    fromp->ss_family);
		fatal(f, "Permission denied");
	}

	/*
	 * Allow connections only from the "ephemeral" reserved
	 * ports(ports 512 - 1023) by checking the remote port
	 * because other utilities(e.g. in.ftpd) can be used to
	 * allow a unprivileged user to originate a connection
	 * from a privileged port and provide untrustworthy
	 * authentication.
	 */
	bad_port = (use_auth != KRB5_RECVAUTH_V5 &&
		    (port >= (in_port_t)IPPORT_RESERVED) ||
		    (port < (in_port_t)(IPPORT_RESERVED/2)));
	no_name = getnameinfo((const struct sockaddr *) fromp,
			    fromplen, hostname, sizeof (hostname),
			    NULL, 0, 0) != 0;

	if (no_name || bad_port) {
		(void) strlcpy(abuf, rhost_addra, sizeof (abuf));
		/* If no host name, use IP address for name later on. */
		if (no_name)
			(void) strlcpy(hostname, abuf, sizeof (hostname));
	}

	if (!no_name) {
		/*
		 * Even if getnameinfo() succeeded, we still have to check
		 * for spoofing.
		 */
		check_address("rlogind", fromp, sin, sin6, rhost_addra,
		    hostname, sizeof (hostname));
	}

	if (bad_port) {
		if (no_name)
			syslog(LOG_NOTICE,
			    "connection from %s - bad port\n",
			    abuf);
		else
			syslog(LOG_NOTICE,
			    "connection from %s(%s) - bad port\n",
			    hostname, abuf);
		fatal(f, "Permission denied");
	}

	if (use_auth == KRB5_RECVAUTH_V5) {
		do_krb_login(f, rhost_addra, hostname,
			    krb_context, encr_flag, keytab);
		if (krusername != NULL && strlen(krusername)) {
			/*
			 * Kerberos Authentication succeeded,
			 * so set the proper program name to use
			 * with pam (important during 'cleanup'
			 * routine later).
			 */
			pam_prog_name = KRB5_PROG_NAME;
		}
	}

	if (write(f, "", 1) != 1) {
		syslog(LOG_NOTICE,
		    "send of the zero byte(to %s) failed:"
		    " cannot start data transfer mode\n",
		    (no_name ? abuf : hostname));
		exit(EXIT_FAILURE);
	}
	if ((p = open("/dev/ptmx", O_RDWR)) == -1)
		fatalperror(f, "cannot open /dev/ptmx");
	if (grantpt(p) == -1)
		fatal(f, "could not grant slave pty");
	if (unlockpt(p) == -1)
		fatal(f, "could not unlock slave pty");
	if ((line = ptsname(p)) == NULL)
		fatal(f, "could not enable slave pty");
	if ((t = open(line, O_RDWR)) == -1)
		fatal(f, "could not open slave pty");
	if (ioctl(t, I_PUSH, "ptem") == -1)
		fatalperror(f, "ioctl I_PUSH ptem");
	if (ioctl(t, I_PUSH, "ldterm") == -1)
		fatalperror(f, "ioctl I_PUSH ldterm");
	if (ioctl(t, I_PUSH, "ttcompat") == -1)
		fatalperror(f, "ioctl I_PUSH ttcompat");
	/*
	 * POP the sockmod and push the rlmod module.
	 *
	 * Note that sockmod has to be removed since readstream assumes
	 * a "raw" TPI endpoint(e.g. it uses getmsg).
	 */
	if (removemod(f, "sockmod") < 0)
		fatalperror(f, "couldn't remove sockmod");

	if (encr_flag) {
		if (ioctl(f, I_PUSH, "cryptmod") < 0)
		    fatalperror(f, "ioctl I_PUSH rlmod");

	}

	if (ioctl(f, I_PUSH, "rlmod") < 0)
		fatalperror(f, "ioctl I_PUSH rlmod");

	if (encr_flag) {
		/*
		 * Make sure rlmod will pass unrecognized IOCTLs to cryptmod
		 */
		uchar_t passthru = 1;
		struct strioctl rlmodctl;

		rlmodctl.ic_cmd = CRYPTPASSTHRU;
		rlmodctl.ic_timout = -1;
		rlmodctl.ic_len = sizeof (uchar_t);
		rlmodctl.ic_dp = (char *)&passthru;

		if (ioctl(f, I_STR, &rlmodctl) < 0)
			fatal(f, "ioctl CRYPTPASSTHRU failed\n");
	}

	/*
	 * readstream will do a getmsg till it receives
	 * M_PROTO type T_DATA_REQ from rloginmodopen()
	 * indicating all data on the stream prior to pushing rlmod has
	 * been drained at the stream head.
	 */
	if ((nsize = readstream(f, rlbuf, BUFSIZ)) < 0)
		fatalperror(f, "readstream failed");
	/*
	 * Make sure the pty doesn't modify the strings passed
	 * to login as part of the "rlogin protocol."  The login
	 * program should set these flags to apropriate values
	 * after it has read the strings.
	 */
	if (ioctl(t, TCGETS, &tp) == -1)
		fatalperror(f, "ioctl TCGETS");
	tp.c_lflag &= ~(ECHO|ICANON);
	tp.c_oflag &= ~(XTABS|OCRNL);
	tp.c_iflag &= ~(IGNPAR|ICRNL);
	if (ioctl(t, TCSETS, &tp) == -1)
		fatalperror(f, "ioctl TCSETS");

	/*
	 * System V ptys allow the TIOC{SG}WINSZ ioctl to be
	 * issued on the master side of the pty.  Luckily, that's
	 * the only tty ioctl we need to do do, so we can close the
	 * slave side in the parent process after the fork.
	 */
	(void) ioctl(p, TIOCSWINSZ, &win);

	pid = fork();
	if (pid < 0)
		fatalperror(f, "fork");
	if (pid == 0) {
		int tt;
		struct utmpx ut;

		/* System V login expects a utmp entry to already be there */
		(void) memset(&ut, 0, sizeof (ut));
		(void) strncpy(ut.ut_user, ".rlogin", sizeof (ut.ut_user));
		(void) strncpy(ut.ut_line, line, sizeof (ut.ut_line));
		ut.ut_pid = getpid();
		ut.ut_id[0] = 'r';
		ut.ut_id[1] = (char)SC_WILDC;
		ut.ut_id[2] = (char)SC_WILDC;
		ut.ut_id[3] = (char)SC_WILDC;
		ut.ut_type = LOGIN_PROCESS;
		ut.ut_exit.e_termination = 0;
		ut.ut_exit.e_exit = 0;
		(void) time(&ut.ut_tv.tv_sec);
		if (makeutx(&ut) == NULL)
			syslog(LOG_INFO, "in.rlogind:\tmakeutx failed");

		/* controlling tty */
		if (setsid() == -1)
			fatalperror(f, "setsid");
		if ((tt = open(line, O_RDWR)) == -1)
			fatalperror(f, "could not re-open slave pty");

		if (close(p) == -1)
			fatalperror(f, "error closing pty master");
		if (close(t) == -1)
			fatalperror(f, "error closing pty slave"
				    " opened before session established");
		/*
		 * If this fails we may or may not be able to output an
		 * error message.
		 */
		if (close(f) == -1)
			fatalperror(f, "error closing deamon stdout");
		if (dup2(tt, STDIN_FILENO) == -1 ||
		    dup2(tt, STDOUT_FILENO) == -1 ||
		    dup2(tt, STDERR_FILENO) == -1)
			exit(EXIT_FAILURE);	/* Disaster! No stderr! */

		(void) close(tt);

		if (use_auth == KRB5_RECVAUTH_V5 &&
		    krusername != NULL && strlen(krusername)) {
			(void) execl(LOGIN_PROGRAM, "login",
				    "-d", line,
				    "-r", hostname,
				    "-u", krusername, /* KRB5 principal name */
				    "-s", pam_prog_name,
				    "-t", term,	/* Remote Terminal */
				    "-U", rusername,	/* Remote User */
				    "-R", KRB5_REPOSITORY_NAME,
				    lusername,  /* local user */
				    NULL);
		} else {
			(void) execl(LOGIN_PROGRAM, "login",
				"-d", line,
				"-r", hostname,
				NULL);
		}

		fatalperror(STDERR_FILENO, "/bin/login");
		/*NOTREACHED*/
	}
	(void) close(t);
	(void) ioctl(f, FIONBIO, &on);
	(void) ioctl(p, FIONBIO, &on);

	/*
	 * Must ignore SIGTTOU, otherwise we'll stop
	 * when we try and set slave pty's window shape
	 * (our controlling tty is the master pty).
	 * Likewise, we don't want any of the tty-generated
	 * signals from chars passing through.
	 */
	(void) sigset(SIGTSTP, SIG_IGN);
	(void) sigset(SIGINT, SIG_IGN);
	(void) sigset(SIGQUIT, SIG_IGN);
	(void) sigset(SIGTTOU, SIG_IGN);
	(void) sigset(SIGTTIN, SIG_IGN);
	(void) sigset(SIGCHLD, cleanup);
	(void) setpgrp();

	if (encr_flag) {
		krb5_data ivec, *ivptr;
		uint_t ivec_usage;
		stop_stream(f, CRYPT_ENCRYPT|CRYPT_DECRYPT);

		/*
		 * Configure the STREAMS crypto module.  For now,
		 * don't use any IV parameter.  KCMDV0.2 support
		 * will require the use of Initialization Vectors
		 * for both encrypt and decrypt modes.
		 */
		if (kcmd_protocol == KCMD_OLD_PROTOCOL) {
			if (session_key->enctype == ENCTYPE_DES_CBC_CRC) {
				/*
				 * This is gross but necessary for MIT compat.
				 */
				ivec.length = session_key->length;
				ivec.data = (char *)session_key->contents;
				ivec_usage = IVEC_REUSE;
				ivptr = &ivec;
			} else {
				ivptr = NULL; /* defaults to all 0's */
				ivec_usage = IVEC_NEVER;
			}
			/*
			 * configure both sides of stream together
			 * since they share the same IV.
			 * This is what makes the OLD KCMD protocol
			 * less secure than the newer one - Bad ivecs.
			 */
			if (configure_stream(f, session_key,
				CRYPT_ENCRYPT|CRYPT_DECRYPT,
				ivptr, ivec_usage) != 0)
				fatal(f, "Cannot initialize encryption -"
					" exiting.\n");
		} else {
			size_t blocksize;
			if (session_key->enctype == ENCTYPE_ARCFOUR_HMAC ||
			    session_key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
				if (configure_stream(f, session_key,
					CRYPT_ENCRYPT|CRYPT_DECRYPT,
					NULL, IVEC_NEVER) != 0)
					fatal(f,
					"Cannot initialize encryption -"
					" exiting.\n");
				goto startcrypto;
			}
			if (krb5_c_block_size(krb_context,
					    session_key->enctype,
					    &blocksize)) {
				syslog(LOG_ERR, "Cannot determine blocksize "
				    "for encryption type %d",
				    session_key->enctype);
				fatal(f, "Cannot determine blocksize "
				    "for encryption - exiting.\n");
			}
			ivec.data = (char *)malloc(blocksize);
			ivec.length = blocksize;
			if (ivec.data == NULL)
				fatal(f, "memory error - exiting\n");
			/*
			 * Following MIT convention -
			 *   encrypt IV = 0x01 x blocksize
			 *   decrypt IV = 0x00 x blocksize
			 *   ivec_usage = IVEC_ONETIME
			 *
			 * configure_stream separately for encrypt and
			 * decrypt because there are 2 different IVs.
			 *
			 * AES uses 0's for IV.
			 */
			if (session_key->enctype ==
				ENCTYPE_AES128_CTS_HMAC_SHA1_96 ||
			    session_key->enctype ==
				ENCTYPE_AES256_CTS_HMAC_SHA1_96)
				(void) memset(ivec.data, 0x00, blocksize);
			else
				(void) memset(ivec.data, 0x01, blocksize);
			if (configure_stream(f, session_key, CRYPT_ENCRYPT,
				&ivec, IVEC_ONETIME) != 0)
				fatal(f, "Cannot initialize encryption -"
					" exiting.\n");
			(void) memset(ivec.data, 0x00, blocksize);
			if (configure_stream(f, session_key, CRYPT_DECRYPT,
				&ivec, IVEC_ONETIME) != 0)
				fatal(f, "Cannot initialize encryption -"
					" exiting.\n");

			(void) free(ivec.data);
		}
startcrypto:
		start_stream(f, CRYPT_ENCRYPT);
		start_stream(f, CRYPT_DECRYPT);
	}
	protocol(f, p, encr_flag);
	cleanup(0);
	/*NOTREACHED*/

badconversion:
	fatalperror(f, "address conversion");
	/*NOTREACHED*/
}
コード例 #16
0
ファイル: sys_term.c プロジェクト: 2asoft/freebsd
/* ARGSUSED */
void
startslave(const char *host, const char *utmp_host,
	   int autologin, char *autoname)
{
    int i;

#ifdef AUTHENTICATION
    if (!autoname || !autoname[0])
	autologin = 0;

    if (autologin < auth_level) {
	fatal(net, "Authorization failed");
	exit(1);
    }
#endif

    {
	char *tbuf =
	    "\r\n*** Connection not encrypted! "
	    "Communication may be eavesdropped. ***\r\n";
#ifdef ENCRYPTION
	if (!no_warn && (encrypt_output == 0 || decrypt_input == 0))
#endif
	    writenet(tbuf, strlen(tbuf));
    }
# ifdef	PARENT_DOES_UTMP
    utmp_sig_init();
# endif	/* PARENT_DOES_UTMP */

    if ((i = fork()) < 0)
	fatalperror(net, "fork");
    if (i) {
# ifdef PARENT_DOES_UTMP
	/*
	 * Cray parent will create utmp entry for child and send
	 * signal to child to tell when done.  Child waits for signal
	 * before doing anything important.
	 */
	int pid = i;
	void sigjob (int);

	setpgrp();
	utmp_sig_reset();		/* reset handler to default */
	/*
	 * Create utmp entry for child
	 */
	wtmp.ut_time = time(NULL);
	wtmp.ut_type = LOGIN_PROCESS;
	wtmp.ut_pid = pid;
	strncpy(wtmp.ut_user,  "LOGIN", sizeof(wtmp.ut_user));
	strncpy(wtmp.ut_host,  utmp_host, sizeof(wtmp.ut_host));
	strncpy(wtmp.ut_line,  clean_ttyname(line), sizeof(wtmp.ut_line));
#ifdef HAVE_STRUCT_UTMP_UT_ID
	strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id));
#endif

	pututline(&wtmp);
	endutent();
	if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
	    write(i, &wtmp, sizeof(struct utmp));
	    close(i);
	}
#ifdef	_CRAY
	signal(WJSIGNAL, sigjob);
#endif
	utmp_sig_notify(pid);
# endif	/* PARENT_DOES_UTMP */
    } else {
	getptyslave();
#if defined(DCE)
	/* if we authenticated via K5, try and join the PAG */
	kerberos5_dfspag();
#endif
	start_login(host, autologin, autoname);
	/*NOTREACHED*/
    }
}
コード例 #17
0
ファイル: in.rlogind.c プロジェクト: AlainODea/illumos-gate
/*
 * rlogin "protocol" machine.
 */
static void
protocol(int f, int p, int encr_flag)
{
	struct	stat	buf;
	struct 	protocol_arg	rloginp;
	struct	strioctl	rloginmod;
	int	ptmfd;	/* fd of logindmux coneected to ptmx */
	int	netfd;	/* fd of logindmux connected to netf */
	static uchar_t	oobdata[] = {TIOCPKT_WINDOW};

	/* indicate new rlogin */
	if (send_oob(f, oobdata, 1) < 0)
		fatalperror(f, "send_oob");
	/*
	 * We cannot send the SECURE_MSG until after the
	 * client has been signaled with the oobdata (above).
	 */
	if (encr_flag) {
		if (write(f, SECURE_MSG, strlen(SECURE_MSG)) < 0)
			fatalperror(f, "Error writing SECURE message");
	}

	/*
	 * Open logindmux driver and link netf and ptmx
	 * underneath logindmux.
	 */
	if ((ptmfd = open("/dev/logindmux", O_RDWR)) == -1)
		fatalperror(f, "open /dev/logindmux");

	if ((netfd = open("/dev/logindmux", O_RDWR)) == -1)
		fatalperror(f, "open /dev/logindmux");

	if (ioctl(ptmfd, I_LINK, p) < 0)
		fatal(f, "ioctl I_LINK of /dev/ptmx failed\n");

	if (ioctl(netfd, I_LINK, f) < 0)
		fatal(f, "ioctl I_LINK of tcp connection failed\n");

	/*
	 * Figure out the device number of the ptm's mux fd, and pass that
	 * to the net's mux.
	 */
	if (fstat(ptmfd, &buf) < 0)
		fatalperror(f, "cannot determine device number"
		    " of pty side of /dev/logindmux");
	rloginp.dev = buf.st_rdev;
	rloginp.flag = 0;

	rloginmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
	rloginmod.ic_timout = -1;
	rloginmod.ic_len = sizeof (struct protocol_arg);
	rloginmod.ic_dp = (char *)&rloginp;

	if (ioctl(netfd, I_STR, &rloginmod) < 0)
		fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of netfd failed\n");

	/*
	 * Figure out the device number of the net's mux fd, and pass that
	 * to the ptm's mux.
	 */
	if (fstat(netfd, &buf))
		fatalperror(f, "cannot determine device number"
		    " of network side of /dev/logindmux");
	rloginp.dev = buf.st_rdev;
	rloginp.flag = 1;

	rloginmod.ic_cmd = LOGDMX_IOC_QEXCHANGE;
	rloginmod.ic_timout = -1;
	rloginmod.ic_len = sizeof (struct protocol_arg);
	rloginmod.ic_dp = (char *)&rloginp;

	if (ioctl(ptmfd, I_STR, &rloginmod) < 0)
		fatal(netfd, "ioctl LOGDMXZ_IOC_QEXCHANGE of ptmfd failed\n");
	/*
	 * Send an ioctl type RL_IOC_ENABLE to reenable the
	 * message queue and reinsert the data read from streamhead
	 * at the time of pushing rloginmod module.
	 * We need to send this ioctl even if no data was read earlier
	 * since we need to reenable the message queue of rloginmod module.
	 */
	rloginmod.ic_cmd = RL_IOC_ENABLE;
	rloginmod.ic_timout = -1;
	if (nsize) {
		rloginmod.ic_len = nsize;
		rloginmod.ic_dp = rlbuf;
	} else {
		rloginmod.ic_len = 0;
		rloginmod.ic_dp = NULL;
	}

	if (ioctl(netfd, I_STR, &rloginmod) < 0)
		fatal(netfd, "ioctl RL_IOC_ENABLE of netfd failed\n");

	/*
	 * User level daemon now pauses till the shell exits.
	 */
	(void) pause();
}
コード例 #18
0
ファイル: in.rlogind.c プロジェクト: AlainODea/illumos-gate
/* ARGSUSED */
int
main(int argc, char *argv[])
{
	int on = 1;
	socklen_t fromlen;
	struct sockaddr_storage from;
	int fd = -1;

	extern char *optarg;
	char c;
	int tos = -1;
	krb5_context krb_context;
	krb5_keytab keytab = NULL;
	krb5_error_code status;
	char *realm = NULL;
	char *keytab_file = NULL;
	int encr_flag = 0;
	struct sockaddr_storage ouraddr;
	socklen_t ourlen;
#ifdef DEBUG
	int debug_port = 0;
#endif /* DEBUG */
	openlog("rlogind", LOG_PID | LOG_ODELAY, LOG_DAEMON);

	while ((c = getopt(argc, argv, ARGSTR)) != -1) {
		switch (c) {
		case 'k':
		case '5':
			use_auth = KRB5_RECVAUTH_V5;
			break;
		case 'e':
		case 'E':
		case 'x':
		case 'X':
			encr_flag = 1;
			break;
		case 'M':
			realm = (char *)strdup(optarg);
			break;
		case 'S':
			keytab_file = (char *)strdup(optarg);
			break;
		case 'c':
			chksum_flag |= CHKSUM_REQUIRED;
			break;
		case 'i':
			chksum_flag |= CHKSUM_IGNORED;
			break;
		case 's':
			if (optarg == NULL || (tos = atoi(optarg)) < 0 ||
			    tos > 255) {
				syslog(LOG_ERR, "%s: illegal tos value: "
				    "%s\n", argv[0], optarg);
			} else {
				if (tos < 0)
					tos = DEFAULT_TOS;
			}
			break;
#ifdef DEBUG
		case 'D':
			debug_port = atoi(optarg);
			break;
#endif /* DEBUG */
		default:
			syslog(LOG_ERR, "Unrecognized command line option "
			    "(-%c), exiting", optopt);
			exit(EXIT_FAILURE);
		}
	}
	if (use_auth == KRB5_RECVAUTH_V5) {
		status = krb5_init_context(&krb_context);
		if (status) {
			syslog(LOG_ERR, "Error initializing krb5: %s",
			    error_message(status));
			exit(EXIT_FAILURE);
		}
		if (realm != NULL)
			(void) krb5_set_default_realm(krb_context, realm);
		if (keytab_file != NULL) {
			if ((status = krb5_kt_resolve(krb_context,
						    keytab_file,
						    &keytab))) {
				com_err(argv[0],
					status,
					"while resolving srvtab file %s",
					keytab_file);
				exit(EXIT_FAILURE);
			}
		}
	}

#ifdef DEBUG
	if (debug_port) {
		int s;
		struct sockaddr_in sin;

		if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
			fatalperror(STDERR_FILENO, "Error in socket");
		}

		(void) memset((char *)&sin, 0, sizeof (sin));
		sin.sin_family = AF_INET;
		sin.sin_port = htons(debug_port);
		sin.sin_addr.s_addr = INADDR_ANY;

		(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
					(char *)&on, sizeof (on));

		if ((bind(s, (struct sockaddr *)&sin, sizeof (sin))) < 0) {
			fatalperror(STDERR_FILENO, "bind error");
		}

		if ((listen(s, 5)) < 0) {
			fatalperror(STDERR_FILENO, "listen error");
		}

		fromlen = sizeof (from);
		if ((fd = accept(s, (struct sockaddr *)&from, &fromlen)) < 0) {
			fatalperror(STDERR_FILENO, "accept error");
		}

		(void) close(s);
	} else
#endif /* DEBUG */
	{
		if (!issock(STDIN_FILENO))
			fatal(STDIN_FILENO,
				"stdin is not a socket file descriptor");
		fd = STDIN_FILENO;
	}

	fromlen = sizeof (from);
	if (getpeername(fd, (struct sockaddr *)&from, &fromlen) < 0)
		fatalperror(STDERR_FILENO, "getpeername");

	if (audit_rlogin_settid(fd))	/* set terminal ID */
		fatalperror(STDERR_FILENO, "audit");

	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
	    sizeof (on)) < 0)
		syslog(LOG_WARNING, "setsockopt(SO_KEEPALIVE): %m");

	if (!VALID_CHKSUM(chksum_flag)) {
		syslog(LOG_ERR, "Configuration error: mutually exclusive "
		    "options specified (-c and -i)");
		fatal(fd, "Checksums are required and ignored (-c and -i);"
		    "these options are mutually exclusive - check "
		    "the documentation.");
	}
	ourlen = sizeof (ouraddr);
	if (getsockname(fd, (struct sockaddr *)&ouraddr, &ourlen) == -1) {
		syslog(LOG_ERR, "getsockname error: %m");
		exit(EXIT_FAILURE);
	}

	if (tos != -1 &&
	    ouraddr.ss_family != AF_INET6 &&
	    setsockopt(fd, IPPROTO_IP, IP_TOS, (char *)&tos,
					sizeof (tos)) < 0 &&
					errno != ENOPROTOOPT) {
		syslog(LOG_ERR, "setsockopt(IP_TOS %d): %m", tos);
	}
	doit(fd, &from, krb_context, encr_flag, keytab);
	return (0);
}
コード例 #19
0
ファイル: sys_term.c プロジェクト: 2asoft/freebsd
/*
 * getptyslave()
 *
 * Open the slave side of the pty, and do any initialization
 * that is necessary.  The return value is a file descriptor
 * for the slave side.
 */
void getptyslave(void)
{
    int t = -1;

    struct winsize ws;
    /*
     * Opening the slave side may cause initilization of the
     * kernel tty structure.  We need remember the state of
     * 	if linemode was turned on
     *	terminal window size
     *	terminal speed
     * so that we can re-set them if we need to.
     */


    /*
     * Make sure that we don't have a controlling tty, and
     * that we are the session (process group) leader.
     */

#ifdef HAVE_SETSID
    if(setsid()<0)
	fatalperror(net, "setsid()");
#else
# ifdef	TIOCNOTTY
    t = open(_PATH_TTY, O_RDWR);
    if (t >= 0) {
	ioctl(t, TIOCNOTTY, (char *)0);
	close(t);
    }
# endif
#endif

# ifdef PARENT_DOES_UTMP
    /*
     * Wait for our parent to get the utmp stuff to get done.
     */
    utmp_sig_wait();
# endif

    t = cleanopen(line);
    if (t < 0)
	fatalperror(net, line);

#ifdef  STREAMSPTY
    ttyfd = t;


    /*
     * Not all systems have (or need) modules ttcompat and pckt so
     * don't flag it as a fatal error if they don't exist.
     */

    if (really_stream)
	{
	    /* these are the streams modules that we want pushed. note
	       that they are in reverse order, ptem will be pushed
	       first. maybe_push_modules() will try to push all modules
	       before the first one that isn't already pushed. i.e if
	       ldterm is pushed, only ttcompat will be attempted.

	       all this is because we don't know which modules are
	       available, and we don't know which modules are already
	       pushed (via autopush, for instance).

	       */

	    char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL };
	    char *ptymodules[] = { "pckt", NULL };

	    maybe_push_modules(t, ttymodules);
	    maybe_push_modules(ourpty, ptymodules);
	}
#endif
    /*
     * set up the tty modes as we like them to be.
     */
    init_termbuf();
# ifdef	TIOCSWINSZ
    if (def_row || def_col) {
	memset(&ws, 0, sizeof(ws));
	ws.ws_col = def_col;
	ws.ws_row = def_row;
	ioctl(t, TIOCSWINSZ, (char *)&ws);
    }
# endif

    /*
     * Settings for sgtty based systems
     */

    /*
     * Settings for UNICOS (and HPUX)
     */
# if defined(_CRAY) || defined(__hpux)
    termbuf.c_oflag = OPOST|ONLCR|TAB3;
    termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
    termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
    termbuf.c_cflag = EXTB|HUPCL|CS8;
# endif

    /*
     * Settings for all other termios/termio based
     * systems, other than 4.4BSD.  In 4.4BSD the
     * kernel does the initial terminal setup.
     */
# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43)
#  ifndef	OXTABS
#   define OXTABS	0
#  endif
    termbuf.c_lflag |= ECHO;
    termbuf.c_oflag |= ONLCR|OXTABS;
    termbuf.c_iflag |= ICRNL;
    termbuf.c_iflag &= ~IXOFF;
# endif
    tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
    tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);

    /*
     * Set the tty modes, and make this our controlling tty.
     */
    set_termbuf();
    if (login_tty(t) == -1)
	fatalperror(net, "login_tty");
    if (net > 2)
	close(net);
    if (ourpty > 2) {
	close(ourpty);
	ourpty = -1;
    }
}
コード例 #20
0
ファイル: telnetd.c プロジェクト: hlyytine/daydream
int
main(int argc, char **argv)
{
    struct sockaddr_storage __ss;
    struct sockaddr *sa = (struct sockaddr *)&__ss;
    int on = 1;
    socklen_t sa_size;
    int ch;
#if	defined(IPPROTO_IP) && defined(IP_TOS)
    int tos __attribute__ ((unused)) = -1;
#endif
#ifdef ENCRYPTION
    extern int des_check_key;
    des_check_key = 1;	/* Kludge for Mac NCSA telnet 2.6 /bg */
#endif

    pfrontp = pbackp = ptyobuf;
    netip = netibuf;
    nfrontp = nbackp = netobuf;

    progname = *argv;
#ifdef ENCRYPTION
    nclearto = 0;
#endif

#ifdef _CRAY
    /*
     * Get number of pty's before trying to process options,
     * which may include changing pty range.
     */
    highpty = getnpty();
#endif /* CRAY */

    while ((ch = getopt(argc, argv, valid_opts)) != -1) {
	switch(ch) {

#ifdef	AUTHENTICATION
	case 'a':
	    /*
	     * Check for required authentication level
	     */
	    if (strcmp(optarg, "debug") == 0) {
		auth_debug_mode = 1;
	    } else if (strcasecmp(optarg, "none") == 0) {
		auth_level = 0;
	    } else if (strcasecmp(optarg, "otp") == 0) {
		auth_level = 0;
		require_otp = 1;
	    } else if (strcasecmp(optarg, "other") == 0) {
		auth_level = AUTH_OTHER;
	    } else if (strcasecmp(optarg, "user") == 0) {
		auth_level = AUTH_USER;
	    } else if (strcasecmp(optarg, "valid") == 0) {
		auth_level = AUTH_VALID;
	    } else if (strcasecmp(optarg, "off") == 0) {
		/*
		 * This hack turns off authentication
		 */
		auth_level = -1;
	    } else {
		fprintf(stderr,
			"telnetd: unknown authorization level for -a\n");
	    }
	    break;
#endif	/* AUTHENTICATION */

	case 'B': /* BFTP mode is not supported any more */
	    break;

#ifdef DIAGNOSTICS
	case 'D':
	    /*
	     * Check for desired diagnostics capabilities.
	     */
	    if (!strcmp(optarg, "report")) {
		diagnostic |= TD_REPORT|TD_OPTIONS;
	    } else if (!strcmp(optarg, "exercise")) {
		diagnostic |= TD_EXERCISE;
	    } else if (!strcmp(optarg, "netdata")) {
		diagnostic |= TD_NETDATA;
	    } else if (!strcmp(optarg, "ptydata")) {
		diagnostic |= TD_PTYDATA;
	    } else if (!strcmp(optarg, "options")) {
		diagnostic |= TD_OPTIONS;
	    } else {
		usage();
		/* NOT REACHED */
	    }
	    break;
#endif /* DIAGNOSTICS */


	case 'g':
	    gettyent = optarg;
	    break;

	case 'k': /* Linemode is not supported any more */
	case 'l':
	    break;

	case 'n':
	    keepalive = 0;
	    break;

#ifdef _CRAY
	case 'r':
	    {
		char *strchr();
		char *c;

		/*
		 * Allow the specification of alterations
		 * to the pty search range.  It is legal to
		 * specify only one, and not change the
		 * other from its default.
		 */
		c = strchr(optarg, '-');
		if (c) {
		    *c++ = '\0';
		    highpty = atoi(c);
		}
		if (*optarg != '\0')
		    lowpty = atoi(optarg);
		if ((lowpty > highpty) || (lowpty < 0) ||
		    (highpty > 32767)) {
		    usage();
		    /* NOT REACHED */
		}
		break;
	    }
#endif	/* CRAY */

	case 'S':
#ifdef	HAVE_PARSETOS
	    if ((tos = parsetos(optarg, "tcp")) < 0)
		fprintf(stderr, "%s%s%s\n",
			"telnetd: Bad TOS argument '", optarg,
			"'; will try to use default TOS");
#else
	    fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
		    "-S flag not supported\n");
#endif
	    break;

	case 'u': {
	    char *eptr;

	    utmp_len = strtol(optarg, &eptr, 0);
	    if (optarg == eptr)
		fprintf(stderr, "telnetd: unknown utmp len (%s)\n", optarg);
	    break;
	}

	case 'U':
	    registerd_host_only = 1;
	    break;

#ifdef	AUTHENTICATION
	case 'X':
	    /*
	     * Check for invalid authentication types
	     */
	    auth_disable_name(optarg);
	    break;
#endif
	case 'y':
	    no_warn = 1;
	    break;
#ifdef AUTHENTICATION
	case 'z':
	    log_unauth = 1;
	    break;

#endif	/* AUTHENTICATION */

	case 'L':
	    new_login = optarg;
	    break;
			
	default:
	    fprintf(stderr, "telnetd: %c: unknown option\n", ch);
	    /* FALLTHROUGH */
	case '?':
	    usage();
	    /* NOTREACHED */
	}
    }

    argc -= optind;
    argv += optind;

    if (argc > 0) {
	usage();
	/* NOT REACHED */
    }

#ifdef _SC_CRAY_SECURE_SYS
    secflag = sysconf(_SC_CRAY_SECURE_SYS);

    /*
     *	Get socket's security label
     */
    if (secflag)  {
	socklen_t szss = sizeof(ss);
	int sock_multi;
	socklen_t szi = sizeof(int);

	memset(&dv, 0, sizeof(dv));

	if (getsysv(&sysv, sizeof(struct sysv)) != 0) 
	    fatalperror(net, "getsysv");

	/*
	 *	Get socket security label and set device values
	 *	   {security label to be set on ttyp device}
	 */
#ifdef SO_SEC_MULTI			/* 8.0 code */
	if ((getsockopt(0, SOL_SOCKET, SO_SECURITY,
			(void *)&ss, &szss) < 0) ||
	    (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI,
			(void *)&sock_multi, &szi) < 0)) 
	    fatalperror(net, "getsockopt");
	else {
	    dv.dv_actlvl = ss.ss_actlabel.lt_level;
	    dv.dv_actcmp = ss.ss_actlabel.lt_compart;
	    if (!sock_multi) {
		dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl;
		dv.dv_valcmp = dv.dv_actcmp;
	    } else {
		dv.dv_minlvl = ss.ss_minlabel.lt_level;
		dv.dv_maxlvl = ss.ss_maxlabel.lt_level;
		dv.dv_valcmp = ss.ss_maxlabel.lt_compart;
	    }
	    dv.dv_devflg = 0;
	}
#else /* SO_SEC_MULTI */		/* 7.0 code */
	if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
		       (void *)&ss, &szss) >= 0) {
	    dv.dv_actlvl = ss.ss_slevel;
	    dv.dv_actcmp = ss.ss_compart;
	    dv.dv_minlvl = ss.ss_minlvl;
	    dv.dv_maxlvl = ss.ss_maxlvl;
	    dv.dv_valcmp = ss.ss_maxcmp;
	}
#endif /* SO_SEC_MULTI */
    }
#endif	/* _SC_CRAY_SECURE_SYS */

    openlog("ddtelnetd", LOG_PID | LOG_ODELAY, LOG_LOCAL2);
    sa_size = sizeof (__ss);
    if (getpeername(STDIN_FILENO, sa, &sa_size) < 0) {
	fprintf(stderr, "%s: ", progname);
	perror("getpeername");
	_exit(1);
    }
    if (keepalive &&
	setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
		   (void *)&on, sizeof (on)) < 0) {
	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
    }

#if	defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
    {
# ifdef HAVE_GETTOSBYNAME
	struct tosent *tp;
	if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
	    tos = tp->t_tos;
# endif
	if (tos < 0)
	    tos = 020;	/* Low Delay bit */
	if (tos
	    && sa->sa_family == AF_INET
	    && (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS,
			   (void *)&tos, sizeof(tos)) < 0)
	    && (errno != ENOPROTOOPT) )
	    syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
    }
#endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
    net = STDIN_FILENO;
    doit(sa, sa_size);
    /* NOTREACHED */
    return 0;
}  /* end of main */
コード例 #21
0
void
getptyslave(void)
{
	int t = -1;

#ifdef	LINEMODE
	int waslm;
#endif
	struct winsize ws;
	/*
	 * Opening the slave side may cause initilization of the
	 * kernel tty structure.  We need remember the state of
	 * 	if linemode was turned on
	 *	terminal window size
	 *	terminal speed
	 * so that we can re-set them if we need to.
	 */
#ifdef	LINEMODE
	waslm = tty_linemode();
#endif

	/*
	 * Make sure that we don't have a controlling tty, and
	 * that we are the session (process group) leader.
	 */
	t = open(_PATH_TTY, O_RDWR);
	if (t >= 0) {
		(void) ioctl(t, TIOCNOTTY, (char *)0);
		(void) close(t);
	}



	t = cleanopen(line);
	if (t < 0)
		fatalperror(net, line);


	/*
	 * set up the tty modes as we like them to be.
	 */
	init_termbuf();
	if (def_row || def_col) {
		memset((char *)&ws, 0, sizeof(ws));
		ws.ws_col = def_col;
		ws.ws_row = def_row;
		(void)ioctl(t, TIOCSWINSZ, (char *)&ws);
	}

	/*
	 * Settings for sgtty based systems
	 */

	/*
	 * Settings for all other termios/termio based
	 * systems, other than 4.4BSD.  In 4.4BSD the
	 * kernel does the initial terminal setup.
	 */
	tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
	tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
#ifdef	LINEMODE
	if (waslm)
		tty_setlinemode(1);
#endif	/* LINEMODE */

	/*
	 * Set the tty modes, and make this our controlling tty.
	 */
	set_termbuf();
	if (login_tty(t) == -1)
		fatalperror(net, "login_tty");
	if (net > 2)
		(void) close(net);
	if (pty > 2) {
		(void) close(pty);
		pty = -1;
	}
}
コード例 #22
0
void
start_login(char *host, int autologin, char *name)
{
	char **argv;
#define	TABBUFSIZ	512
	char	defent[TABBUFSIZ];
	char	defstrs[TABBUFSIZ];
#undef	TABBUFSIZ
	const char *loginprog = NULL;
	extern struct sockaddr_storage from;
	char buf[sizeof(from) * 4 + 1];

	scrub_env();

	/*
	 * -a : pass on the address of the host.
	 * -h : pass on name of host.
	 *	WARNING:  -h and -a are accepted by login
	 *	if and only if getuid() == 0.
	 * -p : don't clobber the environment (so terminal type stays set).
	 *
	 * -f : force this login, he has already been authenticated
	 */
	argv = addarg(0, "login");

	argv = addarg(argv, "-a");
	(void)strvisx(buf, (const char *)(const void *)&from, sizeof(from),
	    VIS_WHITE);
	argv = addarg(argv, buf);

	argv = addarg(argv, "-h");
	argv = addarg(argv, host);

	argv = addarg(argv, "-p");
#ifdef	LINEMODE
	/*
	 * Set the environment variable "LINEMODE" to either
	 * "real" or "kludge" if we are operating in either
	 * real or kludge linemode.
	 */
	if (lmodetype == REAL_LINEMODE)
		setenv("LINEMODE", "real", 1);
# ifdef KLUDGELINEMODE
	else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
		setenv("LINEMODE", "kludge", 1);
# endif
#endif
#ifdef SECURELOGIN
	/*
	 * don't worry about the -f that might get sent.
	 * A -s is supposed to override it anyhow.
	 */
	if (require_secure_login)
		argv = addarg(argv, "-s");
#endif
#ifdef AUTHENTICATION
	if (auth_level >= 0 && autologin == AUTH_VALID) {
		argv = addarg(argv, "-f");
		argv = addarg(argv, "--");
		argv = addarg(argv, name);
	} else
#endif
	if (getenv("USER")) {
		argv = addarg(argv, "--");
		argv = addarg(argv, getenv("USER"));
		/*
		 * Assume that login will set the USER variable
		 * correctly.  For SysV systems, this means that
		 * USER will no longer be set, just LOGNAME by
		 * login.  (The problem is that if the auto-login
		 * fails, and the user then specifies a different
		 * account name, he can get logged in with both
		 * LOGNAME and USER in his environment, but the
		 * USER value will be wrong.
		 */
		unsetenv("USER");
	}
        if (getent(defent, gettyname) == 1) {
                char *cp = defstrs;

                loginprog = getstr("lo", &cp);
        }
        if (loginprog == NULL)
                loginprog = _PATH_LOGIN;
	closelog();
	/*
	 * This sleep(1) is in here so that telnetd can
	 * finish up with the tty.  There's a race condition
	 * the login banner message gets lost...
	 */
	sleep(1);
        execv(loginprog, argv);

        syslog(LOG_ERR, "%s: %m", loginprog);
        fatalperror(net, loginprog);
	/*NOTREACHED*/
}
コード例 #23
0
void start_login(const char *host, int autologin, const char *name) {
    struct argv_stuff avs;
    char *const *argvfoo;
    (void)autologin;

    initarg(&avs);

    /*
     * -h : pass on name of host.
     *		WARNING:  -h is accepted by login if and only if
     *			getuid() == 0.
     * -p : don't clobber the environment (so terminal type stays set).
     *
     * -f : force this login, he has already been authenticated
     */
    addarg(&avs, loginprg);
    addarg(&avs, "-h");
    addarg(&avs, host);
#if !defined(NO_LOGIN_P)
    addarg(&avs, "-p");
#endif
#ifdef BFTPDAEMON
    /*
     * Are we working as the bftp daemon?  If so, then ask login
     * to start bftp instead of shell.
     */
    if (bftpd) {
	addarg(&avs, "-e");
	addarg(&avs, BFTPPATH);
    } 
    else
#endif
    {
#if defined (SecurID)
	/*
	 * don't worry about the -f that might get sent.
	 * A -s is supposed to override it anyhow.
	 */
	if (require_SecurID) addarg(&avs, "-s");
#endif
	if (*name=='-') {
	    syslog(LOG_ERR, "Attempt to login with an option!");
	    name = "";
	}
#if defined (AUTHENTICATE)
	if (auth_level >= 0 && autologin == AUTH_VALID) {
# if !defined(NO_LOGIN_F)
	    addarg(&avs, "-f");
# endif
	    addarg(&avs, name);
	} 
	else
#endif
	{
	    if (getenv("USER")) {
		addarg(&avs, getenv("USER"));
		if (*getenv("USER") == '-') {
		    write(1,"I don't hear you!\r\n",19);
		    syslog(LOG_ERR,"Attempt to login with an option!");
		    exit(1);
		}
	    }
	}
    }
    closelog();
    /* execv() should really take char const* const *, but it can't */ 
    /*argvfoo = argv*/;
    memcpy(&argvfoo, &avs.argv, sizeof(argvfoo));
    execv(loginprg, argvfoo);

    openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
    syslog(LOG_ERR, "%s: %m\n", loginprg);
    closelog();
    fatalperror(net, loginprg);
}
コード例 #24
0
ファイル: telnetd.c プロジェクト: marado/netkit-telnet-ssl
int
main(int argc, char *argv[], char *env[])
{
	struct sockaddr_storage from;
	int on = 1;
	socklen_t fromlen;
	register int ch;
	int i;

#if	defined(HAS_IPPROTO_IP) && defined(IP_TOS)
	int tos = -1;
#endif

	initsetproctitle(argc, argv, env);

	pfrontp = pbackp = ptyobuf;
	netip = netibuf;

#ifdef USE_SSL
	/* we need to know the fullpath to the location of the
	 * certificate that we will be running with as we cannot
	 * be sure of the cwd when we are launched
	 */
	sprintf(cert_filepath,"%s/%s",X509_get_default_cert_dir(),
	        "telnetd.pem");
	ssl_cert_file=cert_filepath;
	ssl_key_file=NULL;
#endif /* USE_SSL */

	while ((ch = getopt(argc, argv, "d:a:e:lhnNr:I:D:B:sS:a:X:L:z:")) != EOF) {
		switch(ch) {

#ifdef USE_SSL
                case 'z':
		        { 
			char *origopt;

			origopt=strdup(optarg);
			optarg=strtok(origopt,",");

			while(optarg!=NULL) {

		        if (strcmp(optarg, "debug") == 0 ) {
			    ssl_debug_flag=1;
			} else if (strcmp(optarg, "ssl") == 0 ) {
			    ssl_only_flag=1;
			} else if (strcmp(optarg, "certsok") == 0 ) {
			    ssl_certsok_flag=1;
			} else if ( (strcmp(optarg, "!ssl") == 0) ||
		             (strcmp(optarg, "nossl") == 0) ) {
			    /* we may want to switch SSL negotiation off
			     * for testing or other reasons 
			     */
			    ssl_disabled_flag=1;
			} else if (strcmp(optarg, "certrequired") == 0 ) {
			    ssl_cert_required=1;
			} else if (strcmp(optarg, "secure") == 0 ) {
			    ssl_secure_flag=1;
			} else if (strncmp(optarg, "verify=", 
			                strlen("verify=")) == 0 ) {
			    ssl_verify_flag=atoi(optarg+strlen("verify="));
			} else if (strncmp(optarg, "cert=", 
			                strlen("cert=")) == 0 ) {
			    ssl_cert_file=optarg+strlen("cert=");
			} else if (strncmp(optarg, "key=", 
			                strlen("key=")) == 0 ) {
			    ssl_key_file=optarg+strlen("key=");
			} else if (strncmp(optarg,"cipher=",
			                strlen("cipher="))==0) {
			    ssl_cipher_list=optarg+strlen("cipher=");
			} else {
			    /* report when we are given rubbish so that
			     * if the user makes a mistake they have to
			     * correct it!
			     */
			    fprintf(stderr,"Unknown SSL option %s\n",optarg);
			    fflush(stderr);
			    exit(1);
			}

			/* get the next one ... */
                        optarg=strtok(NULL,",");

			}

			/*
			if (origopt!=NULL)
			    free(origopt);
			*/

			}
			break;
#endif /* USE_SSL */

#ifdef	AUTHENTICATE
		case 'a':
			/*
			 * Check for required authentication level
			 */
			if (strcmp(optarg, "debug") == 0) {
				extern int auth_debug_mode;
				auth_debug_mode = 1;
			} else if (strcasecmp(optarg, "none") == 0) {
				auth_level = 0;
			} else if (strcasecmp(optarg, "other") == 0) {
				auth_level = AUTH_OTHER;
			} else if (strcasecmp(optarg, "user") == 0) {
				auth_level = AUTH_USER;
			} else if (strcasecmp(optarg, "valid") == 0) {
				auth_level = AUTH_VALID;
			} else if (strcasecmp(optarg, "off") == 0) {
				/*
				 * This hack turns off authentication
				 */
				auth_level = -1;
			} else {
				fprintf(stderr,
			    "telnetd: unknown authorization level for -a\n");
			}
			break;
#endif	/* AUTHENTICATE */

#ifdef BFTPDAEMON
		case 'B':
			bftpd++;
			break;
#endif /* BFTPDAEMON */

		case 'd':
			if (strcmp(optarg, "ebug") == 0) {
				debug++;
				break;
			}
			usage();
			/* NOTREACHED */
			break;

#ifdef DIAGNOSTICS
		case 'D':
			/*
			 * Check for desired diagnostics capabilities.
			 */
			if (!strcmp(optarg, "report")) {
				diagnostic |= TD_REPORT|TD_OPTIONS;
			} else if (!strcmp(optarg, "exercise")) {
				diagnostic |= TD_EXERCISE;
			} else if (!strcmp(optarg, "netdata")) {
				diagnostic |= TD_NETDATA;
			} else if (!strcmp(optarg, "ptydata")) {
				diagnostic |= TD_PTYDATA;
			} else if (!strcmp(optarg, "options")) {
				diagnostic |= TD_OPTIONS;
			} else {
				usage();
				/* NOT REACHED */
			}
			break;
#endif /* DIAGNOSTICS */

#ifdef	AUTHENTICATE
		case 'e':
			if (strcmp(optarg, "debug") == 0) {
				extern int auth_debug_mode;
				auth_debug_mode = 1;
				break;
			}
			usage();
			/* NOTREACHED */
			break;
#endif	/* AUTHENTICATE */

		case 'h':
			hostinfo = 0;
			break;

#ifdef	LINEMODE
		case 'l':
			alwayslinemode = 1;
			break;
#endif	/* LINEMODE */

		case 'L':
			loginprg = strdup(optarg);
			/* XXX what if strdup fails? */
			break;

		case 'n':
			keepalive = 0;
			break;

		case 'N':
		  numeric_hosts = 1;
		  break;

#ifdef	SecurID
		case 's':
			/* SecurID required */
			require_SecurID = 1;
			break;
#endif	/* SecurID */
		case 'S':
#ifdef	HAS_GETTOS
			if ((tos = parsetos(optarg, "tcp")) < 0)
				fprintf(stderr, "%s%s%s\n",
					"telnetd: Bad TOS argument '", optarg,
					"'; will try to use default TOS");
#else
			fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
						"-S flag not supported\n");
#endif
			break;

#ifdef	AUTHENTICATE
		case 'X':
			/*
			 * Check for invalid authentication types
			 */
			auth_disable_name(optarg);
			break;
#endif	/* AUTHENTICATE */

		default:
			fprintf(stderr, "telnetd: %c: unknown option\n", ch);
			/* FALLTHROUGH */
		case '?':
			usage();
			/* NOTREACHED */
		}
	}

#ifdef USE_SSL

        if (ssl_secure_flag || ssl_cert_required || ssl_certsok_flag) {
	    /* in secure mode we *must* switch on the base level
	     * verify checking otherwise we cannot abort connections
	     * at the right place!
	     */
	    if (ssl_verify_flag==0)
		ssl_verify_flag=1;
	}

	/* if we are not running in debug then any error
	 * stuff from SSL debug *must* not go down
	 * the socket (which 0,1,2 are all pointing to by
	 * default)
	 */
	if (ssl_debug_flag)
	    ssl_log_file="/telnetd.log";

	if (!do_ssleay_init(1)) {
	  if (bio_err!=NULL) {
	    BIO_printf(bio_err,"do_ssleay_init() failed\n");
	    ERR_print_errors(bio_err);
	  } else {
	    fflush(stderr);
	    fprintf(stderr,"do_ssleay_init() failed\n");
	    ERR_print_errors_fp(stderr);
	  }
	  exit(1);
	}

	if (ssl_debug_flag) {
	  BIO_printf(bio_err,"secure %d certrequired %d verify %d\n",
	      ssl_secure_flag,ssl_cert_required,ssl_verify_flag);
	  for(i=0;i<argc;i++)
	      BIO_printf(bio_err,"argv[%d]=\"%s\"\n",i,argv[i]);
	}

#endif /* USE_SSL */

	argc -= optind;
	argv += optind;

	if (debug) {
		if (argc > 1) {
			usage();
			/* NOTREACHED */
		}

		wait_for_connection((argc == 1) ? *argv : "telnet");
	}

	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
	fromlen = sizeof (from);
	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
		fatalperror(2, "getpeername");
	}
	if (keepalive &&
	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
	}

#if	defined(HAS_IPPROTO_IP) && defined(IP_TOS)
	{
# if	defined(HAS_GETTOS)
		struct tosent *tp;
		if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
			tos = tp->t_tos;
# endif
		if (tos < 0)
			tos = 020;	/* Low Delay bit */
		if (tos
		   && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
		   && (errno != ENOPROTOOPT) )
			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
	}
#endif	/* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */

#ifdef USE_SSL
        /* do the SSL stuff now ... before we play with pty's */
	SSL_set_fd(ssl_con,0);

	if (ssl_only_flag) {
	    /* hmm ... only when running talking to things like
	     * https servers should we hit this code and then
	     * we really don't care *who* we talk to :-)
	     */
	    SSL_set_verify(ssl_con,ssl_verify_flag,NULL);

	    if (SSL_accept(ssl_con) <= 0) {
		static char errbuf[1024];
	    
	        sprintf(errbuf,"SSL_accept error %s\n",
		    ERR_error_string(ERR_get_error(),NULL));

		syslog(LOG_WARNING, "%s", errbuf);

		BIO_printf(bio_err,"%s",errbuf);

		/* go to sleep to make sure we are noticed */
		sleep(10);
		SSL_free(ssl_con);

		_exit(1);
	    } else {
		ssl_active_flag=1;
	    }
	}
#endif /* USE_SSL */

	net = 0;
	netopen();
	doit((struct sockaddr *)&from, fromlen);
	/* NOTREACHED */
	return 0;
}  /* end of main */
コード例 #25
0
static int getptyslave(void) {
#if 0
    register int t = -1;

# ifdef	LINEMODE
    int waslm;
# endif
# ifdef	TIOCGWINSZ
    struct winsize ws;
# endif
    /*
     * Opening the slave side may cause initilization of the
     * kernel tty structure.  We need remember the state of
     * 	if linemode was turned on
     *	terminal window size
     *	terminal speed
     * so that we can re-set them if we need to.
     */
# ifdef	LINEMODE
    waslm = tty_linemode();
# endif


    /*
     * Make sure that we don't have a controlling tty, and
     * that we are the session (process group) leader.
     */
    t = open(_PATH_TTY, O_RDWR);
    if (t >= 0) {
	ioctl(t, TIOCNOTTY, (char *)0);
	close(t);
    }

    t = cleanopen(line);
    if (t < 0) fatalperror(net, line);
#endif /* 0 */

    struct winsize ws;
    int t = ptyslavefd;

    /*
     * set up the tty modes as we like them to be.
     */
    init_termbuf();
# ifdef	TIOCGWINSZ
    if (def_row || def_col) {
	bzero((char *)&ws, sizeof(ws));
	ws.ws_col = def_col;
	ws.ws_row = def_row;
	ioctl(t, TIOCSWINSZ, (char *)&ws);
    }
# endif

    /*
     * Settings for all other termios/termio based
     * systems, other than 4.4BSD.  In 4.4BSD the
     * kernel does the initial terminal setup.
     *
     * XXX what about linux?
     */
#  ifndef	OXTABS
#   define OXTABS	0
#  endif
    termbuf.c_lflag |= ECHO;
    termbuf.c_oflag |= OPOST|ONLCR|OXTABS;
    termbuf.c_iflag |= ICRNL;
    termbuf.c_iflag &= ~IXOFF;

    tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
    tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
# ifdef	LINEMODE
    if (waslm) tty_setlinemode(1);
# endif	/* LINEMODE */

    /*
     * Set the tty modes, and make this our controlling tty.
     */
    set_termbuf();
    if (login_tty(t) == -1) fatalperror(net, "login_tty");

    if (net > 2) close(net);
    if (pty > 2) close(pty);
    return t;
}