diff options
28 files changed, 0 insertions, 12432 deletions
diff --git a/libexec/telnetd/Makefile b/libexec/telnetd/Makefile deleted file mode 100644 index f20366dff48..00000000000 --- a/libexec/telnetd/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# $OpenBSD: Makefile,v 1.22 2004/11/24 07:35:40 biorn Exp $ -# from: @(#)Makefile 8.2 (Berkeley) 12/15/93 -# $NetBSD: Makefile,v 1.6 1996/02/24 01:22:12 jtk Exp $ - -PROG= telnetd - -CFLAGS+=-DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -CFLAGS+=-DOLD_ENVIRON -DENV_HACK -I${.CURDIR} -Wall -CFLAGS+= -DHAS_CGETENT -Wno-unused -SRCS= authenc.c global.c slc.c state.c sys_term.c telnetd.c \ - termstat.c utility.c mini_inetd.c socket.c \ - auth.c encrypt.c genget.c misc.c -DPADD= ${LIBUTIL} ${LIBCURSES} -LDADD+= -lutil -lcurses -MAN= telnetd.8 - -.include <bsd.own.mk> # for KERBEROS - -.if (${KERBEROS5:L} == "yes") -CFLAGS+=-DENCRYPTION -DKRB5 -DAUTHENTICATION -DDES_ENCRYPTION -I${.CURDIR}/../../lib -SRCS+= kerberos5.c enc_des.c -DPADD+= ${LIBKRB5} ${LIBASN1} ${LIBCRYPTO} ${LIBDES} -LDADD+= -lkrb5 -lasn1 -lcrypto -ldes -.endif - -.include <bsd.prog.mk> diff --git a/libexec/telnetd/auth-proto.h b/libexec/telnetd/auth-proto.h deleted file mode 100644 index fb6487ab206..00000000000 --- a/libexec/telnetd/auth-proto.h +++ /dev/null @@ -1,133 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)auth-proto.h 8.1 (Berkeley) 6/4/93 - * $OpenBSD: auth-proto.h,v 1.2 2003/06/02 19:38:24 millert Exp $ - * $NetBSD: auth-proto.h,v 1.5 1996/02/24 01:15:16 jtk Exp $ - */ - -/* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - * - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America is assumed - * to require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -#include <sys/cdefs.h> -/* $KTH: auth-proto.h,v 1.10 2000/01/18 03:08:55 assar Exp $ */ - -#if defined(AUTHENTICATION) -Authenticator *findauthenticator (int, int); - -int auth_wait (char *, size_t); -void auth_disable_name (char *); -void auth_finished (Authenticator *, int); -void auth_gen_printsub (unsigned char *, int, unsigned char *, int); -void auth_init (const char *, int); -void auth_is (unsigned char *, int); -void auth_name (unsigned char*, int); -void auth_reply (unsigned char *, int); -void auth_request (void); -void auth_send (unsigned char *, int); -void auth_send_retry (void); -void auth_printsub (unsigned char*, int, unsigned char*, int); -int getauthmask (char *type, int *maskp); -int auth_enable (char *type); -int auth_disable (char *type); -int auth_onoff (char *type, int on); -int auth_togdebug (int on); -int auth_status (void); -int auth_sendname (unsigned char *cp, int len); -void auth_debug (int mode); -void auth_gen_printsub (unsigned char *data, int cnt, - unsigned char *buf, int buflen); - -#ifdef UNSAFE -int unsafe_init (Authenticator *, int); -int unsafe_send (Authenticator *); -void unsafe_is (Authenticator *, unsigned char *, int); -void unsafe_reply (Authenticator *, unsigned char *, int); -int unsafe_status (Authenticator *, char *, int); -void unsafe_printsub (unsigned char *, int, unsigned char *, int); -#endif - -#ifdef SRA -int sra_init (Authenticator *, int); -int sra_send (Authenticator *); -void sra_is (Authenticator *, unsigned char *, int); -void sra_reply (Authenticator *, unsigned char *, int); -int sra_status (Authenticator *, char *, int); -void sra_printsub (unsigned char *, int, unsigned char *, int); -#endif - -#ifdef KRB4 -int kerberos4_init (Authenticator *, int); -int kerberos4_send_mutual (Authenticator *); -int kerberos4_send_oneway (Authenticator *); -void kerberos4_is (Authenticator *, unsigned char *, int); -void kerberos4_reply (Authenticator *, unsigned char *, int); -int kerberos4_status (Authenticator *, char *, size_t, int); -void kerberos4_printsub (unsigned char *, int, unsigned char *, int); -int kerberos4_forward (Authenticator *ap, void *); -#endif - -#ifdef KRB5 -int kerberos5_init (Authenticator *, int); -int kerberos5_send_mutual (Authenticator *); -int kerberos5_send_oneway (Authenticator *); -void kerberos5_is (Authenticator *, unsigned char *, int); -void kerberos5_reply (Authenticator *, unsigned char *, int); -int kerberos5_status (Authenticator *, char *, size_t, int); -void kerberos5_printsub (unsigned char *, int, unsigned char *, int); -#endif -#endif diff --git a/libexec/telnetd/auth.c b/libexec/telnetd/auth.c deleted file mode 100644 index 18705da78e7..00000000000 --- a/libexec/telnetd/auth.c +++ /dev/null @@ -1,664 +0,0 @@ -/* $OpenBSD: auth.c,v 1.2 2003/06/02 19:38:24 millert Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/* from: static char sccsid[] = "@(#)auth.c 8.3 (Berkeley) 5/30/95" */ -/* from: static char *rcsid = "$NetBSD: auth.c,v 1.5 1996/02/24 01:15:17 jtk Exp $"; */ -#endif /* not lint */ - -/* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - * - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America is assumed - * to require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -/* "$KTH: auth.c,v 1.23 2000/01/18 03:09:34 assar Exp $" */ - -#if defined(AUTHENTICATION) -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <signal.h> -#define AUTH_NAMES -#include <arpa/telnet.h> -#include <stdlib.h> -#include <string.h> - -#include "encrypt.h" -#include "auth.h" -#include "misc-proto.h" -#include "auth-proto.h" - -#define typemask(x) (1<<((x)-1)) - -#ifdef KRB4_ENCPWD -extern krb4encpwd_init(); -extern krb4encpwd_send(); -extern krb4encpwd_is(); -extern krb4encpwd_reply(); -extern krb4encpwd_status(); -extern krb4encpwd_printsub(); -#endif - -#ifdef RSA_ENCPWD -extern rsaencpwd_init(); -extern rsaencpwd_send(); -extern rsaencpwd_is(); -extern rsaencpwd_reply(); -extern rsaencpwd_status(); -extern rsaencpwd_printsub(); -#endif - -int auth_debug_mode = 0; -int auth_has_failed = 0; -int auth_enable_encrypt = 0; -static const char *Name = "Noname"; -static int Server = 0; -static Authenticator *authenticated = 0; -static int authenticating = 0; -static int validuser = 0; -static unsigned char _auth_send_data[256]; -static unsigned char *auth_send_data; -static int auth_send_cnt = 0; - -/* - * Authentication types supported. Plese note that these are stored - * in priority order, i.e. try the first one first. - */ -Authenticator authenticators[] = { -#ifdef UNSAFE - { AUTHTYPE_UNSAFE, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, - unsafe_init, - unsafe_send, - unsafe_is, - unsafe_reply, - unsafe_status, - unsafe_printsub }, -#endif -#ifdef SRA - { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, - sra_init, - sra_send, - sra_is, - sra_reply, - sra_status, - sra_printsub }, -#endif -#ifdef SPX - { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, - spx_init, - spx_send, - spx_is, - spx_reply, - spx_status, - spx_printsub }, - { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, - spx_init, - spx_send, - spx_is, - spx_reply, - spx_status, - spx_printsub }, -#endif -#ifdef KRB5 - { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, - kerberos5_init, - kerberos5_send_mutual, - kerberos5_is, - kerberos5_reply, - kerberos5_status, - kerberos5_printsub }, - { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, - kerberos5_init, - kerberos5_send_oneway, - kerberos5_is, - kerberos5_reply, - kerberos5_status, - kerberos5_printsub }, -#endif -#ifdef KRB4 - { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, - kerberos4_init, - kerberos4_send_mutual, - kerberos4_is, - kerberos4_reply, - kerberos4_status, - kerberos4_printsub }, - { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, - kerberos4_init, - kerberos4_send_oneway, - kerberos4_is, - kerberos4_reply, - kerberos4_status, - kerberos4_printsub }, -#endif -#ifdef KRB4_ENCPWD - { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, - krb4encpwd_init, - krb4encpwd_send, - krb4encpwd_is, - krb4encpwd_reply, - krb4encpwd_status, - krb4encpwd_printsub }, -#endif -#ifdef RSA_ENCPWD - { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, - rsaencpwd_init, - rsaencpwd_send, - rsaencpwd_is, - rsaencpwd_reply, - rsaencpwd_status, - rsaencpwd_printsub }, -#endif - { 0, }, -}; - -static Authenticator NoAuth = { 0 }; - -static int i_support = 0; -static int i_wont_support = 0; - -Authenticator * -findauthenticator(int type, int way) -{ - Authenticator *ap = authenticators; - - while (ap->type && (ap->type != type || ap->way != way)) - ++ap; - return(ap->type ? ap : 0); -} - -void -auth_init(const char *name, int server) -{ - Authenticator *ap = authenticators; - - Server = server; - Name = name; - - i_support = 0; - authenticated = 0; - authenticating = 0; - while (ap->type) { - if (!ap->init || (*ap->init)(ap, server)) { - i_support |= typemask(ap->type); - if (auth_debug_mode) - printf(">>>%s: I support auth type %d %d\r\n", - Name, - ap->type, ap->way); - } - else if (auth_debug_mode) - printf(">>>%s: Init failed: auth type %d %d\r\n", - Name, ap->type, ap->way); - ++ap; - } -} - -void -auth_disable_name(char *name) -{ - int x; - for (x = 0; x < AUTHTYPE_CNT; ++x) { - if (!strcasecmp(name, AUTHTYPE_NAME(x))) { - i_wont_support |= typemask(x); - break; - } - } -} - -int -getauthmask(char *type, int *maskp) -{ - int x; - - if (!strcasecmp(type, AUTHTYPE_NAME(0))) { - *maskp = -1; - return(1); - } - - for (x = 1; x < AUTHTYPE_CNT; ++x) { - if (!strcasecmp(type, AUTHTYPE_NAME(x))) { - *maskp = typemask(x); - return(1); - } - } - return(0); -} - -int -auth_enable(char *type) -{ - return(auth_onoff(type, 1)); -} - -int -auth_disable(char *type) -{ - return(auth_onoff(type, 0)); -} - -int -auth_onoff(char *type, int on) -{ - int i, mask = -1; - Authenticator *ap; - - if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) { - printf("auth %s 'type'\n", on ? "enable" : "disable"); - printf("Where 'type' is one of:\n"); - printf("\t%s\n", AUTHTYPE_NAME(0)); - mask = 0; - for (ap = authenticators; ap->type; ap++) { - if ((mask & (i = typemask(ap->type))) != 0) - continue; - mask |= i; - printf("\t%s\n", AUTHTYPE_NAME(ap->type)); - } - return(0); - } - - if (!getauthmask(type, &mask)) { - printf("%s: invalid authentication type\n", type); - return(0); - } - if (on) - i_wont_support &= ~mask; - else - i_wont_support |= mask; - return(1); -} - -int -auth_togdebug(int on) -{ - if (on < 0) - auth_debug_mode ^= 1; - else - auth_debug_mode = on; - printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled"); - return(1); -} - -int -auth_status(void) -{ - Authenticator *ap; - int i, mask; - - if (i_wont_support == -1) - printf("Authentication disabled\n"); - else - printf("Authentication enabled\n"); - - mask = 0; - for (ap = authenticators; ap->type; ap++) { - if ((mask & (i = typemask(ap->type))) != 0) - continue; - mask |= i; - printf("%s: %s\n", AUTHTYPE_NAME(ap->type), - (i_wont_support & typemask(ap->type)) ? - "disabled" : "enabled"); - } - return(1); -} - -/* - * This routine is called by the server to start authentication - * negotiation. - */ -void -auth_request(void) -{ - static unsigned char str_request[64] = { IAC, SB, - TELOPT_AUTHENTICATION, - TELQUAL_SEND, }; - Authenticator *ap = authenticators; - unsigned char *e = str_request + 4; - - if (!authenticating) { - authenticating = 1; - while (ap->type) { - if (i_support & ~i_wont_support & typemask(ap->type)) { - if (auth_debug_mode) { - printf(">>>%s: Sending type %d %d\r\n", - Name, ap->type, ap->way); - } - *e++ = ap->type; - *e++ = ap->way; - } - ++ap; - } - *e++ = IAC; - *e++ = SE; - telnet_net_write(str_request, e - str_request); - printsub('>', &str_request[2], e - str_request - 2); - } -} - -/* - * This is called when an AUTH SEND is received. - * It should never arrive on the server side (as only the server can - * send an AUTH SEND). - * You should probably respond to it if you can... - * - * If you want to respond to the types out of order (i.e. even - * if he sends LOGIN KERBEROS and you support both, you respond - * with KERBEROS instead of LOGIN (which is against what the - * protocol says)) you will have to hack this code... - */ -void -auth_send(unsigned char *data, int cnt) -{ - Authenticator *ap; - static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION, - TELQUAL_IS, AUTHTYPE_NULL, 0, - IAC, SE }; - if (Server) { - if (auth_debug_mode) { - printf(">>>%s: auth_send called!\r\n", Name); - } - return; - } - - if (auth_debug_mode) { - printf(">>>%s: auth_send got:", Name); - printd(data, cnt); printf("\r\n"); - } - - /* - * Save the data, if it is new, so that we can continue looking - * at it if the authorization we try doesn't work - */ - if (data < _auth_send_data || - data > _auth_send_data + sizeof(_auth_send_data)) { - auth_send_cnt = cnt > sizeof(_auth_send_data) - ? sizeof(_auth_send_data) - : cnt; - memmove(_auth_send_data, data, auth_send_cnt); - auth_send_data = _auth_send_data; - } else { - /* - * This is probably a no-op, but we just make sure - */ - auth_send_data = data; - auth_send_cnt = cnt; - } - while ((auth_send_cnt -= 2) >= 0) { - if (auth_debug_mode) - printf(">>>%s: He supports %d\r\n", - Name, *auth_send_data); - if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) { - ap = findauthenticator(auth_send_data[0], - auth_send_data[1]); - if (ap && ap->send) { - if (auth_debug_mode) - printf(">>>%s: Trying %d %d\r\n", - Name, auth_send_data[0], - auth_send_data[1]); - if ((*ap->send)(ap)) { - /* - * Okay, we found one we like - * and did it. - * we can go home now. - */ - if (auth_debug_mode) - printf(">>>%s: Using type %d\r\n", - Name, *auth_send_data); - auth_send_data += 2; - return; - } - } - /* else - * just continue on and look for the - * next one if we didn't do anything. - */ - } - auth_send_data += 2; - } - telnet_net_write(str_none, sizeof(str_none)); - printsub('>', &str_none[2], sizeof(str_none) - 2); - if (auth_debug_mode) - printf(">>>%s: Sent failure message\r\n", Name); - auth_finished(0, AUTH_REJECT); - auth_has_failed = 1; -#ifdef KANNAN - /* - * We requested strong authentication, however no mechanisms worked. - * Therefore, exit on client end. - */ - printf("Unable to securely authenticate user ... exit\n"); - exit(0); -#endif /* KANNAN */ -} - -void -auth_send_retry(void) -{ - /* - * if auth_send_cnt <= 0 then auth_send will end up rejecting - * the authentication and informing the other side of this. - */ - auth_send(auth_send_data, auth_send_cnt); -} - -void -auth_is(unsigned char *data, int cnt) -{ - Authenticator *ap; - - if (cnt < 2) - return; - - if (data[0] == AUTHTYPE_NULL) { - auth_finished(0, AUTH_REJECT); - return; - } - - if ((ap = findauthenticator(data[0], data[1]))) { - if (ap->is) - (*ap->is)(ap, data+2, cnt-2); - } else if (auth_debug_mode) - printf(">>>%s: Invalid authentication in IS: %d\r\n", - Name, *data); -} - -void -auth_reply(unsigned char *data, int cnt) -{ - Authenticator *ap; - - if (cnt < 2) - return; - - if ((ap = findauthenticator(data[0], data[1]))) { - if (ap->reply) - (*ap->reply)(ap, data+2, cnt-2); - } else if (auth_debug_mode) - printf(">>>%s: Invalid authentication in SEND: %d\r\n", - Name, *data); -} - -void -auth_name(unsigned char *data, int cnt) -{ - char savename[256]; - - if (cnt < 1) { - if (auth_debug_mode) - printf(">>>%s: Empty name in NAME\r\n", Name); - return; - } - if (cnt > sizeof(savename) - 1) { - if (auth_debug_mode) - printf(">>>%s: Name in NAME (%d) exceeds %lu length\r\n", - Name, cnt, (unsigned long)(sizeof(savename)-1)); - return; - } - memmove(savename, data, cnt); - savename[cnt] = '\0'; /* Null terminate */ - if (auth_debug_mode) - printf(">>>%s: Got NAME [%s]\r\n", Name, savename); - auth_encrypt_user(savename); -} - -int -auth_sendname(unsigned char *cp, int len) -{ - static unsigned char str_request[256+6] - = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; - unsigned char *e = str_request + 4; - unsigned char *ee = &str_request[sizeof(str_request)-2]; - - while (--len >= 0) { - if ((*e++ = *cp++) == IAC) - *e++ = IAC; - if (e >= ee) - return(0); - } - *e++ = IAC; - *e++ = SE; - telnet_net_write(str_request, e - str_request); - printsub('>', &str_request[2], e - &str_request[2]); - return(1); -} - -void -auth_finished(Authenticator *ap, int result) -{ - if (!(authenticated = ap)) - authenticated = &NoAuth; - validuser = result; -} - -/* ARGSUSED */ -static void -auth_intr(int sig) -{ - auth_finished(0, AUTH_REJECT); -} - -int -auth_wait(char *name, size_t name_sz) -{ - if (auth_debug_mode) - printf(">>>%s: in auth_wait.\r\n", Name); - - if (Server && !authenticating) - return(0); - - signal(SIGALRM, auth_intr); - alarm(30); - while (!authenticated) - if (telnet_spin()) - break; - alarm(0); - signal(SIGALRM, SIG_DFL); - - /* - * Now check to see if the user is valid or not - */ - if (!authenticated || authenticated == &NoAuth) - return(AUTH_REJECT); - - if (validuser == AUTH_VALID) - validuser = AUTH_USER; - - if (authenticated->status) - validuser = (*authenticated->status)(authenticated, - name, name_sz, - validuser); - return(validuser); -} - -void -auth_debug(int mode) -{ - auth_debug_mode = mode; -} - -void -auth_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) -{ - Authenticator *ap; - - if ((ap = findauthenticator(data[1], data[2])) && ap->printsub) - (*ap->printsub)(data, cnt, buf, buflen); - else - auth_gen_printsub(data, cnt, buf, buflen); -} - -void -auth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) -{ - unsigned char *cp; - unsigned char tbuf[16]; - - cnt -= 3; - data += 3; - buf[buflen-1] = '\0'; - buf[buflen-2] = '*'; - buflen -= 2; - for (; cnt > 0; cnt--, data++) { - snprintf(tbuf, sizeof(tbuf), " %d", *data); - for (cp = tbuf; *cp && buflen > 0; --buflen) - *buf++ = *cp++; - if (buflen <= 0) - return; - } - *buf = '\0'; -} -#endif diff --git a/libexec/telnetd/auth.h b/libexec/telnetd/auth.h deleted file mode 100644 index 888e4e9a407..00000000000 --- a/libexec/telnetd/auth.h +++ /dev/null @@ -1,91 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)auth.h 8.1 (Berkeley) 6/4/93 - * $OpenBSD: auth.h,v 1.2 2003/06/02 19:38:24 millert Exp $ - * $NetBSD: auth.h,v 1.5 1996/02/24 01:15:18 jtk Exp $ - */ - -/* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - * - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America is assumed - * to require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -/* $KTH: auth.h,v 1.4 1998/06/09 19:24:41 joda Exp $ */ - -#ifndef __AUTH__ -#define __AUTH__ - -#define AUTH_REJECT 0 /* Rejected */ -#define AUTH_UNKNOWN 1 /* We don't know who he is, but he's okay */ -#define AUTH_OTHER 2 /* We know him, but not his name */ -#define AUTH_USER 3 /* We know he name */ -#define AUTH_VALID 4 /* We know him, and he needs no password */ - -typedef struct XauthP { - int type; - int way; - int (*init) (struct XauthP *, int); - int (*send) (struct XauthP *); - void (*is) (struct XauthP *, unsigned char *, int); - void (*reply) (struct XauthP *, unsigned char *, int); - int (*status) (struct XauthP *, char *, size_t, int); - void (*printsub) (unsigned char *, int, unsigned char *, int); -} Authenticator; - -#include "auth-proto.h" - -extern int auth_debug_mode; -#endif diff --git a/libexec/telnetd/authenc.c b/libexec/telnetd/authenc.c deleted file mode 100644 index 3e91789e34d..00000000000 --- a/libexec/telnetd/authenc.c +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "telnetd.h" - -/* RCSID("$KTH: authenc.c,v 1.10 2000/11/15 23:20:43 assar Exp $"); */ - -int -telnet_net_write(unsigned char *str, int len) -{ - if (nfrontp + len < netobuf + BUFSIZ) { - memmove(nfrontp, str, len); - nfrontp += len; - return(len); - } - return(0); -} - -#ifdef AUTHENTICATION -void -net_encrypt(void) -{ -#ifdef ENCRYPTION - char *s = (nclearto > nbackp) ? nclearto : nbackp; - if (s < nfrontp && encrypt_output) { - (*encrypt_output)((unsigned char *)s, nfrontp - s); - } - nclearto = nfrontp; -#endif -} - -int -telnet_spin(void) -{ - return ttloop(); -} - -char * -telnet_getenv(const char *val) -{ - return(getenv(val)); -} - -char * -telnet_gets(char *prompt, char *result, int length, int echo) -{ - return NULL; -} -#endif diff --git a/libexec/telnetd/defs.h b/libexec/telnetd/defs.h deleted file mode 100644 index db312be384a..00000000000 --- a/libexec/telnetd/defs.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)defs.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * Telnet server defines - */ - -#ifndef __DEFS_H__ -#define __DEFS_H__ - -#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS) -#define TELOPTS -#define TELCMDS -#define SLC_NAMES -#endif - -#if !defined(TIOCSCTTY) && defined(TCSETCTTY) -# define TIOCSCTTY TCSETCTTY -#endif - -#ifndef TIOCPKT_FLUSHWRITE -#define TIOCPKT_FLUSHWRITE 0x02 -#endif - -#ifndef TIOCPKT_NOSTOP -#define TIOCPKT_NOSTOP 0x10 -#endif - -#ifndef TIOCPKT_DOSTOP -#define TIOCPKT_DOSTOP 0x20 -#endif - -/* - * I/O data buffers defines - */ -#define NETSLOP 4096 -#ifdef _CRAY -#undef BUFSIZ -#define BUFSIZ 2048 -#endif - -#define NIACCUM(c) { *netip++ = c; \ - ncc++; \ - } - -/* clock manipulations */ -#define settimer(x) (clocks.x = ++clocks.system) -#define sequenceIs(x,y) (clocks.x < clocks.y) - -/* - * Structures of information for each special character function. - */ -typedef struct { - unsigned char flag; /* the flags for this function */ - cc_t val; /* the value of the special character */ -} slcent, *Slcent; - -typedef struct { - slcent defset; /* the default settings */ - slcent current; /* the current settings */ - cc_t *sptr; /* a pointer to the char in */ - /* system data structures */ -} slcfun, *Slcfun; - -#ifdef DIAGNOSTICS -/* - * Diagnostics capabilities - */ -#define TD_REPORT 0x01 /* Report operations to client */ -#define TD_EXERCISE 0x02 /* Exercise client's implementation */ -#define TD_NETDATA 0x04 /* Display received data stream */ -#define TD_PTYDATA 0x08 /* Display data passed to pty */ -#define TD_OPTIONS 0x10 /* Report just telnet options */ -#endif /* DIAGNOSTICS */ - -/* - * We keep track of each side of the option negotiation. - */ - -#define MY_STATE_WILL 0x01 -#define MY_WANT_STATE_WILL 0x02 -#define MY_STATE_DO 0x04 -#define MY_WANT_STATE_DO 0x08 - -/* - * Macros to check the current state of things - */ - -#define my_state_is_do(opt) (options[opt]&MY_STATE_DO) -#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL) -#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO) -#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL) - -#define my_state_is_dont(opt) (!my_state_is_do(opt)) -#define my_state_is_wont(opt) (!my_state_is_will(opt)) -#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt)) -#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt)) - -#define set_my_state_do(opt) (options[opt] |= MY_STATE_DO) -#define set_my_state_will(opt) (options[opt] |= MY_STATE_WILL) -#define set_my_want_state_do(opt) (options[opt] |= MY_WANT_STATE_DO) -#define set_my_want_state_will(opt) (options[opt] |= MY_WANT_STATE_WILL) - -#define set_my_state_dont(opt) (options[opt] &= ~MY_STATE_DO) -#define set_my_state_wont(opt) (options[opt] &= ~MY_STATE_WILL) -#define set_my_want_state_dont(opt) (options[opt] &= ~MY_WANT_STATE_DO) -#define set_my_want_state_wont(opt) (options[opt] &= ~MY_WANT_STATE_WILL) - -/* - * Tricky code here. What we want to know is if the MY_STATE_WILL - * and MY_WANT_STATE_WILL bits have the same value. Since the two - * bits are adjacent, a little arithmetic will show that by adding - * in the lower bit, the upper bit will be set if the two bits were - * different, and clear if they were the same. - */ -#define my_will_wont_is_changing(opt) \ - ((options[opt]+MY_STATE_WILL) & MY_WANT_STATE_WILL) - -#define my_do_dont_is_changing(opt) \ - ((options[opt]+MY_STATE_DO) & MY_WANT_STATE_DO) - -/* - * Make everything symmetrical - */ - -#define HIS_STATE_WILL MY_STATE_DO -#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO -#define HIS_STATE_DO MY_STATE_WILL -#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL - -#define his_state_is_do my_state_is_will -#define his_state_is_will my_state_is_do -#define his_want_state_is_do my_want_state_is_will -#define his_want_state_is_will my_want_state_is_do - -#define his_state_is_dont my_state_is_wont -#define his_state_is_wont my_state_is_dont -#define his_want_state_is_dont my_want_state_is_wont -#define his_want_state_is_wont my_want_state_is_dont - -#define set_his_state_do set_my_state_will -#define set_his_state_will set_my_state_do -#define set_his_want_state_do set_my_want_state_will -#define set_his_want_state_will set_my_want_state_do - -#define set_his_state_dont set_my_state_wont -#define set_his_state_wont set_my_state_dont -#define set_his_want_state_dont set_my_want_state_wont -#define set_his_want_state_wont set_my_want_state_dont - -#define his_will_wont_is_changing my_do_dont_is_changing -#define his_do_dont_is_changing my_will_wont_is_changing - -#endif /* __DEFS_H__ */ diff --git a/libexec/telnetd/enc-proto.h b/libexec/telnetd/enc-proto.h deleted file mode 100644 index 586e236ea78..00000000000 --- a/libexec/telnetd/enc-proto.h +++ /dev/null @@ -1,153 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)enc-proto.h 8.1 (Berkeley) 6/4/93 - * - * @(#)enc-proto.h 5.2 (Berkeley) 3/22/91 - */ - - /* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - * - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America is assumed - * to require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -/* $KTH: enc-proto.h,v 1.10.8.1 2002/02/06 03:38:05 assar Exp $ */ - -#if defined(ENCRYPTION) -Encryptions *findencryption (int); -Encryptions *finddecryption(int); -int EncryptAutoDec(int); -int EncryptAutoEnc(int); -int EncryptDebug(int); -int EncryptDisable(char*, char*); -int EncryptEnable(char*, char*); -int EncryptStart(char*); -int EncryptStartInput(void); -int EncryptStartOutput(void); -int EncryptStatus(void); -int EncryptStop(char*); -int EncryptStopInput(void); -int EncryptStopOutput(void); -int EncryptType(char*, char*); -int EncryptVerbose(int); -void decrypt_auto(int); -void encrypt_auto(int); -void encrypt_debug(int); -void encrypt_dec_keyid(unsigned char*, int); -void encrypt_display(void); -void encrypt_enc_keyid(unsigned char*, int); -void encrypt_end(void); -void encrypt_gen_printsub(unsigned char*, int, unsigned char*, int); -void encrypt_init(const char*, int); -void encrypt_is(unsigned char*, int); -void encrypt_list_types(void); -void encrypt_not(void); -void encrypt_printsub(unsigned char*, int, unsigned char*, int); -void encrypt_reply(unsigned char*, int); -void encrypt_request_end(void); -void encrypt_request_start(unsigned char*, int); -void encrypt_send_end(void); -void encrypt_send_keyid(int, unsigned char*, int, int); -void encrypt_send_request_end(void); -int encrypt_is_encrypting(void); -void encrypt_send_request_start(void); -void encrypt_send_support(void); -void encrypt_session_key(Session_Key*, int); -void encrypt_start(unsigned char*, int); -void encrypt_start_output(int); -void encrypt_support(unsigned char*, int); -void encrypt_verbose_quiet(int); -void encrypt_wait(void); -int encrypt_delay(void); - -#ifdef TELENTD -void encrypt_wait (void); -#else -void encrypt_display (void); -#endif - -void cfb64_encrypt (unsigned char *, int); -int cfb64_decrypt (int); -void cfb64_init (int); -int cfb64_start (int, int); -int cfb64_is (unsigned char *, int); -int cfb64_reply (unsigned char *, int); -void cfb64_session (Session_Key *, int); -int cfb64_keyid (int, unsigned char *, int *); -void cfb64_printsub (unsigned char *, int, unsigned char *, int); - -void ofb64_encrypt (unsigned char *, int); -int ofb64_decrypt (int); -void ofb64_init (int); -int ofb64_start (int, int); -int ofb64_is (unsigned char *, int); -int ofb64_reply (unsigned char *, int); -void ofb64_session (Session_Key *, int); -int ofb64_keyid (int, unsigned char *, int *); -void ofb64_printsub (unsigned char *, int, unsigned char *, int); - -#endif - -#ifdef KRB4 -int check_krb4_tickets(); -#else -#define check_krb4_tickets() 0 -#endif - -#ifdef KRB5 -int check_krb5_tickets(); -#else -#define check_krb5_tickets() 0 -#endif diff --git a/libexec/telnetd/enc_des.c b/libexec/telnetd/enc_des.c deleted file mode 100644 index 8919d4b91a3..00000000000 --- a/libexec/telnetd/enc_des.c +++ /dev/null @@ -1,660 +0,0 @@ -/* $OpenBSD: enc_des.c,v 1.2 2003/06/02 19:38:25 millert Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* $KTH: enc_des.c,v 1.16 1998/07/09 23:16:23 assar Exp $ */ - -#if defined(AUTHENTICATION) && defined(ENCRYPTION) && defined(DES_ENCRYPTION) -#include <arpa/telnet.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "encrypt.h" -#include "misc-proto.h" -#include <des.h> - -extern int encrypt_debug_mode; - -#define CFB 0 -#define OFB 1 - -#define NO_SEND_IV 1 -#define NO_RECV_IV 2 -#define NO_KEYID 4 -#define IN_PROGRESS (NO_SEND_IV|NO_RECV_IV|NO_KEYID) -#define SUCCESS 0 -#define FAILED -1 - - -struct stinfo { - des_cblock str_output; - des_cblock str_feed; - des_cblock str_iv; - des_cblock str_ikey; - des_key_schedule str_sched; - int str_index; - int str_flagshift; -}; - -struct fb { - des_cblock krbdes_key; - des_key_schedule krbdes_sched; - des_cblock temp_feed; - unsigned char fb_feed[64]; - int need_start; - int state[2]; - int keyid[2]; - int once; - struct stinfo streams[2]; -}; - -static struct fb fb[2]; - -struct keyidlist { - char *keyid; - int keyidlen; - char *key; - int keylen; - int flags; -} keyidlist [] = { - { "\0", 1, 0, 0, 0 }, /* default key of zero */ - { 0, 0, 0, 0, 0 } -}; - -#define KEYFLAG_MASK 03 - -#define KEYFLAG_NOINIT 00 -#define KEYFLAG_INIT 01 -#define KEYFLAG_OK 02 -#define KEYFLAG_BAD 03 - -#define KEYFLAG_SHIFT 2 - -#define SHIFT_VAL(a,b) (KEYFLAG_SHIFT*((a)+((b)*2))) - -#define FB64_IV 1 -#define FB64_IV_OK 2 -#define FB64_IV_BAD 3 - - -void fb64_stream_iv (des_cblock, struct stinfo *); -void fb64_init (struct fb *); -static int fb64_start (struct fb *, int, int); -int fb64_is (unsigned char *, int, struct fb *); -int fb64_reply (unsigned char *, int, struct fb *); -static void fb64_session (Session_Key *, int, struct fb *); -void fb64_stream_key (des_cblock, struct stinfo *); -int fb64_keyid (int, unsigned char *, int *, struct fb *); - -void cfb64_init(int server) -{ - fb64_init(&fb[CFB]); - fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; - fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); - fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); -} - - -void ofb64_init(int server) -{ - fb64_init(&fb[OFB]); - fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; - fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); - fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); -} - -void fb64_init(struct fb *fbp) -{ - memset(fbp,0, sizeof(*fbp)); - fbp->state[0] = fbp->state[1] = FAILED; - fbp->fb_feed[0] = IAC; - fbp->fb_feed[1] = SB; - fbp->fb_feed[2] = TELOPT_ENCRYPT; - fbp->fb_feed[3] = ENCRYPT_IS; -} - -/* - * Returns: - * -1: some error. Negotiation is done, encryption not ready. - * 0: Successful, initial negotiation all done. - * 1: successful, negotiation not done yet. - * 2: Not yet. Other things (like getting the key from - * Kerberos) have to happen before we can continue. - */ -int cfb64_start(int dir, int server) -{ - return(fb64_start(&fb[CFB], dir, server)); -} - -int ofb64_start(int dir, int server) -{ - return(fb64_start(&fb[OFB], dir, server)); -} - -static int fb64_start(struct fb *fbp, int dir, int server) -{ - int x; - unsigned char *p; - int state; - - switch (dir) { - case DIR_DECRYPT: - /* - * This is simply a request to have the other side - * start output (our input). He will negotiate an - * IV so we need not look for it. - */ - state = fbp->state[dir-1]; - if (state == FAILED) - state = IN_PROGRESS; - break; - - case DIR_ENCRYPT: - state = fbp->state[dir-1]; - if (state == FAILED) - state = IN_PROGRESS; - else if ((state & NO_SEND_IV) == 0) { - break; - } - - if (!VALIDKEY(fbp->krbdes_key)) { - fbp->need_start = 1; - break; - } - - state &= ~NO_SEND_IV; - state |= NO_RECV_IV; - if (encrypt_debug_mode) - printf("Creating new feed\r\n"); - /* - * Create a random feed and send it over. - */ -#ifndef OLD_DES_RANDOM_KEY - des_new_random_key(&fbp->temp_feed); -#else - /* - * From des_cryp.man "If the des_check_key flag is non-zero, - * des_set_key will check that the key passed is - * of odd parity and is not a week or semi-weak key." - */ - do { - des_random_key(fbp->temp_feed); - des_set_odd_parity(fbp->temp_feed); - } while (des_is_weak_key(fbp->temp_feed)); -#endif - des_ecb_encrypt(&fbp->temp_feed, - &fbp->temp_feed, - fbp->krbdes_sched, 1); - p = fbp->fb_feed + 3; - *p++ = ENCRYPT_IS; - p++; - *p++ = FB64_IV; - for (x = 0; x < sizeof(des_cblock); ++x) { - if ((*p++ = fbp->temp_feed[x]) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); - telnet_net_write(fbp->fb_feed, p - fbp->fb_feed); - break; - default: - return(FAILED); - } - return(fbp->state[dir-1] = state); -} - -/* - * Returns: - * -1: some error. Negotiation is done, encryption not ready. - * 0: Successful, initial negotiation all done. - * 1: successful, negotiation not done yet. - */ - -int cfb64_is(unsigned char *data, int cnt) -{ - return(fb64_is(data, cnt, &fb[CFB])); -} - -int ofb64_is(unsigned char *data, int cnt) -{ - return(fb64_is(data, cnt, &fb[OFB])); -} - - -int fb64_is(unsigned char *data, int cnt, struct fb *fbp) -{ - unsigned char *p; - int state = fbp->state[DIR_DECRYPT-1]; - - if (cnt-- < 1) - goto failure; - - switch (*data++) { - case FB64_IV: - if (cnt != sizeof(des_cblock)) { - if (encrypt_debug_mode) - printf("CFB64: initial vector failed on size\r\n"); - state = FAILED; - goto failure; - } - - if (encrypt_debug_mode) - printf("CFB64: initial vector received\r\n"); - - if (encrypt_debug_mode) - printf("Initializing Decrypt stream\r\n"); - - fb64_stream_iv(data, &fbp->streams[DIR_DECRYPT-1]); - - p = fbp->fb_feed + 3; - *p++ = ENCRYPT_REPLY; - p++; - *p++ = FB64_IV_OK; - *p++ = IAC; - *p++ = SE; - printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); - telnet_net_write(fbp->fb_feed, p - fbp->fb_feed); - - state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS; - break; - - default: - if (encrypt_debug_mode) { - printf("Unknown option type: %d\r\n", *(data-1)); - printd(data, cnt); - printf("\r\n"); - } - /* FALL THROUGH */ - failure: - /* - * We failed. Send an FB64_IV_BAD option - * to the other side so it will know that - * things failed. - */ - p = fbp->fb_feed + 3; - *p++ = ENCRYPT_REPLY; - p++; - *p++ = FB64_IV_BAD; - *p++ = IAC; - *p++ = SE; - printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]); - telnet_net_write(fbp->fb_feed, p - fbp->fb_feed); - - break; - } - return(fbp->state[DIR_DECRYPT-1] = state); -} - -/* - * Returns: - * -1: some error. Negotiation is done, encryption not ready. - * 0: Successful, initial negotiation all done. - * 1: successful, negotiation not done yet. - */ - -int cfb64_reply(unsigned char *data, int cnt) -{ - return(fb64_reply(data, cnt, &fb[CFB])); -} - -int ofb64_reply(unsigned char *data, int cnt) -{ - return(fb64_reply(data, cnt, &fb[OFB])); -} - - -int fb64_reply(unsigned char *data, int cnt, struct fb *fbp) -{ - int state = fbp->state[DIR_ENCRYPT-1]; - - if (cnt-- < 1) - goto failure; - - switch (*data++) { - case FB64_IV_OK: - fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); - if (state == FAILED) - state = IN_PROGRESS; - state &= ~NO_RECV_IV; - encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); - break; - - case FB64_IV_BAD: - memset(fbp->temp_feed, 0, sizeof(des_cblock)); - fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); - state = FAILED; - break; - - default: - if (encrypt_debug_mode) { - printf("Unknown option type: %d\r\n", data[-1]); - printd(data, cnt); - printf("\r\n"); - } - /* FALL THROUGH */ - failure: - state = FAILED; - break; - } - return(fbp->state[DIR_ENCRYPT-1] = state); -} - -void cfb64_session(Session_Key *key, int server) -{ - fb64_session(key, server, &fb[CFB]); -} - -void ofb64_session(Session_Key *key, int server) -{ - fb64_session(key, server, &fb[OFB]); -} - -static void fb64_session(Session_Key *key, int server, struct fb *fbp) -{ - - if (!key || key->type != SK_DES) { - if (encrypt_debug_mode) - printf("Can't set krbdes's session key (%d != %d)\r\n", - key ? key->type : -1, SK_DES); - return; - } - memcpy(fbp->krbdes_key, key->data, sizeof(des_cblock)); - - fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]); - fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]); - - if (fbp->once == 0) { -#ifndef OLD_DES_RANDOM_KEY - des_init_random_number_generator(&fbp->krbdes_key); -#endif - fbp->once = 1; - } - des_key_sched(&fbp->krbdes_key, fbp->krbdes_sched); - /* - * Now look to see if krbdes_start() was was waiting for - * the key to show up. If so, go ahead an call it now - * that we have the key. - */ - if (fbp->need_start) { - fbp->need_start = 0; - fb64_start(fbp, DIR_ENCRYPT, server); - } -} - -/* - * We only accept a keyid of 0. If we get a keyid of - * 0, then mark the state as SUCCESS. - */ - -int cfb64_keyid(int dir, unsigned char *kp, int *lenp) -{ - return(fb64_keyid(dir, kp, lenp, &fb[CFB])); -} - -int ofb64_keyid(int dir, unsigned char *kp, int *lenp) -{ - return(fb64_keyid(dir, kp, lenp, &fb[OFB])); -} - -int fb64_keyid(int dir, unsigned char *kp, int *lenp, struct fb *fbp) -{ - int state = fbp->state[dir-1]; - - if (*lenp != 1 || (*kp != '\0')) { - *lenp = 0; - return(state); - } - - if (state == FAILED) - state = IN_PROGRESS; - - state &= ~NO_KEYID; - - return(fbp->state[dir-1] = state); -} - -void fb64_printsub(unsigned char *data, int cnt, - unsigned char *buf, int buflen, char *type) -{ - char lbuf[32]; - int i; - char *cp; - - buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ - buflen -= 1; - - switch(data[2]) { - case FB64_IV: - snprintf(lbuf, sizeof(lbuf), "%s_IV", type); - cp = lbuf; - goto common; - - case FB64_IV_OK: - snprintf(lbuf, sizeof(lbuf), "%s_IV_OK", type); - cp = lbuf; - goto common; - - case FB64_IV_BAD: - snprintf(lbuf, sizeof(lbuf), "%s_IV_BAD", type); - cp = lbuf; - goto common; - - default: - snprintf(lbuf, sizeof(lbuf), " %d (unknown)", data[2]); - cp = lbuf; - common: - for (; (buflen > 0) && (*buf = *cp++); buf++) - buflen--; - for (i = 3; i < cnt; i++) { - snprintf(lbuf, sizeof(lbuf), " %d", data[i]); - for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++) - buflen--; - } - break; - } -} - -void cfb64_printsub(unsigned char *data, int cnt, - unsigned char *buf, int buflen) -{ - fb64_printsub(data, cnt, buf, buflen, "CFB64"); -} - -void ofb64_printsub(unsigned char *data, int cnt, - unsigned char *buf, int buflen) -{ - fb64_printsub(data, cnt, buf, buflen, "OFB64"); -} - -void fb64_stream_iv(des_cblock seed, struct stinfo *stp) -{ - - memcpy(stp->str_iv, seed,sizeof(des_cblock)); - memcpy(stp->str_output, seed, sizeof(des_cblock)); - - des_key_sched(&stp->str_ikey, stp->str_sched); - - stp->str_index = sizeof(des_cblock); -} - -void fb64_stream_key(des_cblock key, struct stinfo *stp) -{ - memcpy(stp->str_ikey, key, sizeof(des_cblock)); - des_key_sched((des_cblock*)key, stp->str_sched); - - memcpy(stp->str_output, stp->str_iv, sizeof(des_cblock)); - - stp->str_index = sizeof(des_cblock); -} - -/* - * DES 64 bit Cipher Feedback - * - * key --->+-----+ - * +->| DES |--+ - * | +-----+ | - * | v - * INPUT --(--------->(+)+---> DATA - * | | - * +-------------+ - * - * - * Given: - * iV: Initial vector, 64 bits (8 bytes) long. - * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). - * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. - * - * V0 = DES(iV, key) - * On = Dn ^ Vn - * V(n+1) = DES(On, key) - */ - -void cfb64_encrypt(unsigned char *s, int c) -{ - struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; - int index; - - index = stp->str_index; - while (c-- > 0) { - if (index == sizeof(des_cblock)) { - des_cblock b; - des_ecb_encrypt(&stp->str_output, &b,stp->str_sched, 1); - memcpy(stp->str_feed, b, sizeof(des_cblock)); - index = 0; - } - - /* On encryption, we store (feed ^ data) which is cypher */ - *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); - s++; - index++; - } - stp->str_index = index; -} - -int cfb64_decrypt(int data) -{ - struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; - int index; - - if (data == -1) { - /* - * Back up one byte. It is assumed that we will - * never back up more than one byte. If we do, this - * may or may not work. - */ - if (stp->str_index) - --stp->str_index; - return(0); - } - - index = stp->str_index++; - if (index == sizeof(des_cblock)) { - des_cblock b; - des_ecb_encrypt(&stp->str_output,&b, stp->str_sched, 1); - memcpy(stp->str_feed, b, sizeof(des_cblock)); - stp->str_index = 1; /* Next time will be 1 */ - index = 0; /* But now use 0 */ - } - - /* On decryption we store (data) which is cypher. */ - stp->str_output[index] = data; - return(data ^ stp->str_feed[index]); -} - -/* - * DES 64 bit Output Feedback - * - * key --->+-----+ - * +->| DES |--+ - * | +-----+ | - * +-----------+ - * v - * INPUT -------->(+) ----> DATA - * - * Given: - * iV: Initial vector, 64 bits (8 bytes) long. - * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). - * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. - * - * V0 = DES(iV, key) - * V(n+1) = DES(Vn, key) - * On = Dn ^ Vn - */ - -void ofb64_encrypt(unsigned char *s, int c) -{ - struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; - int index; - - index = stp->str_index; - while (c-- > 0) { - if (index == sizeof(des_cblock)) { - des_cblock b; - des_ecb_encrypt(&stp->str_feed,&b, stp->str_sched, 1); - memcpy(stp->str_feed, b, sizeof(des_cblock)); - index = 0; - } - *s++ ^= stp->str_feed[index]; - index++; - } - stp->str_index = index; -} - -int ofb64_decrypt(int data) -{ - struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; - int index; - - if (data == -1) { - /* - * Back up one byte. It is assumed that we will - * never back up more than one byte. If we do, this - * may or may not work. - */ - if (stp->str_index) - --stp->str_index; - return(0); - } - - index = stp->str_index++; - if (index == sizeof(des_cblock)) { - des_cblock b; - des_ecb_encrypt(&stp->str_feed,&b,stp->str_sched, 1); - memcpy(stp->str_feed, b, sizeof(des_cblock)); - stp->str_index = 1; /* Next time will be 1 */ - index = 0; /* But now use 0 */ - } - - return(data ^ stp->str_feed[index]); -} -#endif - diff --git a/libexec/telnetd/encrypt.c b/libexec/telnetd/encrypt.c deleted file mode 100644 index 08a56f360f9..00000000000 --- a/libexec/telnetd/encrypt.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* $OpenBSD: encrypt.c,v 1.3 2003/06/26 07:53:27 deraadt Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - /* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - * - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America is assumed - * to require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -/* -RCSID("$KTH: encrypt.c,v 1.22.8.1 2002/02/06 03:39:13 assar Exp $"); -*/ - -#if defined(ENCRYPTION) - -#define ENCRYPT_NAMES -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <arpa/telnet.h> - -#include "encrypt.h" -#include "misc.h" - - - -/* - * These functions pointers point to the current routines - * for encrypting and decrypting data. - */ -void (*encrypt_output) (unsigned char *, int); -int (*decrypt_input) (int); -char *nclearto; - -int encrypt_debug_mode = 0; -static int decrypt_mode = 0; -static int encrypt_mode = 0; -static int encrypt_verbose = 0; -static int autoencrypt = 0; -static int autodecrypt = 0; -static int havesessionkey = 0; -static int Server = 0; -static const char *Name = "Noname"; - -#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) - -static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64) - | typemask(ENCTYPE_DES_OFB64); - static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64) - | typemask(ENCTYPE_DES_OFB64); - static long i_wont_support_encrypt = 0; - static long i_wont_support_decrypt = 0; -#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) -#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) - - static long remote_supports_encrypt = 0; - static long remote_supports_decrypt = 0; - - static Encryptions encryptions[] = { -#if defined(DES_ENCRYPTION) - { "DES_CFB64", ENCTYPE_DES_CFB64, - cfb64_encrypt, - cfb64_decrypt, - cfb64_init, - cfb64_start, - cfb64_is, - cfb64_reply, - cfb64_session, - cfb64_keyid, - cfb64_printsub }, - { "DES_OFB64", ENCTYPE_DES_OFB64, - ofb64_encrypt, - ofb64_decrypt, - ofb64_init, - ofb64_start, - ofb64_is, - ofb64_reply, - ofb64_session, - ofb64_keyid, - ofb64_printsub }, -#endif - { 0, }, - }; - -static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT, - ENCRYPT_SUPPORT }; -static unsigned char str_suplen = 0; -static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT }; -static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE }; - -Encryptions * -findencryption(int type) -{ - Encryptions *ep = encryptions; - - if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type))) - return(0); - while (ep->type && ep->type != type) - ++ep; - return(ep->type ? ep : 0); -} - -Encryptions * -finddecryption(int type) -{ - Encryptions *ep = encryptions; - - if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type))) - return(0); - while (ep->type && ep->type != type) - ++ep; - return(ep->type ? ep : 0); -} - -#define MAXKEYLEN 64 - -static struct key_info { - unsigned char keyid[MAXKEYLEN]; - int keylen; - int dir; - int *modep; - Encryptions *(*getcrypt)(int); -} ki[2] = { - { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, - { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, -}; - -void -encrypt_init(const char *name, int server) -{ - Encryptions *ep = encryptions; - - Name = name; - Server = server; - i_support_encrypt = i_support_decrypt = 0; - remote_supports_encrypt = remote_supports_decrypt = 0; - encrypt_mode = 0; - decrypt_mode = 0; - encrypt_output = 0; - decrypt_input = 0; -#ifdef notdef - encrypt_verbose = !server; -#endif - - str_suplen = 4; - - while (ep->type) { - if (encrypt_debug_mode) - printf(">>>%s: I will support %s\r\n", - Name, ENCTYPE_NAME(ep->type)); - i_support_encrypt |= typemask(ep->type); - i_support_decrypt |= typemask(ep->type); - if ((i_wont_support_decrypt & typemask(ep->type)) == 0) - if ((str_send[str_suplen++] = ep->type) == IAC) - str_send[str_suplen++] = IAC; - if (ep->init) - (*ep->init)(Server); - ++ep; - } - str_send[str_suplen++] = IAC; - str_send[str_suplen++] = SE; -} - -void -encrypt_list_types(void) -{ - Encryptions *ep = encryptions; - - printf("Valid encryption types:\n"); - while (ep->type) { - printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type); - ++ep; - } -} - -int -EncryptEnable(char *type, char *mode) -{ - if (isprefix(type, "help") || isprefix(type, "?")) { - printf("Usage: encrypt enable <type> [input|output]\n"); - encrypt_list_types(); - return(0); - } - if (EncryptType(type, mode)) - return(EncryptStart(mode)); - return(0); -} - -int -EncryptDisable(char *type, char *mode) -{ - Encryptions *ep; - int ret = 0; - - if (isprefix(type, "help") || isprefix(type, "?")) { - printf("Usage: encrypt disable <type> [input|output]\n"); - encrypt_list_types(); - } else if ((ep = (Encryptions *)genget(type, (char**)encryptions, - sizeof(Encryptions))) == 0) { - printf("%s: invalid encryption type\n", type); - } else if (Ambiguous(ep)) { - printf("Ambiguous type '%s'\n", type); - } else { - if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) { - if (decrypt_mode == ep->type) - EncryptStopInput(); - i_wont_support_decrypt |= typemask(ep->type); - ret = 1; - } - if ((mode == 0) || (isprefix(mode, "output"))) { - if (encrypt_mode == ep->type) - EncryptStopOutput(); - i_wont_support_encrypt |= typemask(ep->type); - ret = 1; - } - if (ret == 0) - printf("%s: invalid encryption mode\n", mode); - } - return(ret); -} - -int -EncryptType(char *type, char *mode) -{ - Encryptions *ep; - int ret = 0; - - if (isprefix(type, "help") || isprefix(type, "?")) { - printf("Usage: encrypt type <type> [input|output]\n"); - encrypt_list_types(); - } else if ((ep = (Encryptions *)genget(type, (char**)encryptions, - sizeof(Encryptions))) == 0) { - printf("%s: invalid encryption type\n", type); - } else if (Ambiguous(ep)) { - printf("Ambiguous type '%s'\n", type); - } else { - if ((mode == 0) || isprefix(mode, "input")) { - decrypt_mode = ep->type; - i_wont_support_decrypt &= ~typemask(ep->type); - ret = 1; - } - if ((mode == 0) || isprefix(mode, "output")) { - encrypt_mode = ep->type; - i_wont_support_encrypt &= ~typemask(ep->type); - ret = 1; - } - if (ret == 0) - printf("%s: invalid encryption mode\n", mode); - } - return(ret); -} - -int -EncryptStart(char *mode) -{ - int ret = 0; - if (mode) { - if (isprefix(mode, "input")) - return(EncryptStartInput()); - if (isprefix(mode, "output")) - return(EncryptStartOutput()); - if (isprefix(mode, "help") || isprefix(mode, "?")) { - printf("Usage: encrypt start [input|output]\n"); - return(0); - } - printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode); - return(0); - } - ret += EncryptStartInput(); - ret += EncryptStartOutput(); - return(ret); -} - -int -EncryptStartInput(void) -{ - if (decrypt_mode) { - encrypt_send_request_start(); - return(1); - } - printf("No previous decryption mode, decryption not enabled\r\n"); - return(0); -} - -int -EncryptStartOutput(void) -{ - if (encrypt_mode) { - encrypt_start_output(encrypt_mode); - return(1); - } - printf("No previous encryption mode, encryption not enabled\r\n"); - return(0); -} - -int -EncryptStop(char *mode) -{ - int ret = 0; - if (mode) { - if (isprefix(mode, "input")) - return(EncryptStopInput()); - if (isprefix(mode, "output")) - return(EncryptStopOutput()); - if (isprefix(mode, "help") || isprefix(mode, "?")) { - printf("Usage: encrypt stop [input|output]\n"); - return(0); - } - printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode); - return(0); - } - ret += EncryptStopInput(); - ret += EncryptStopOutput(); - return(ret); -} - -int -EncryptStopInput(void) -{ - encrypt_send_request_end(); - return(1); -} - -int -EncryptStopOutput(void) -{ - encrypt_send_end(); - return(1); -} - -void -encrypt_display(void) -{ - printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n", - autoencrypt?"on":"off", autodecrypt?"on":"off"); - - if (encrypt_output) - printf("Currently encrypting output with %s\r\n", - ENCTYPE_NAME(encrypt_mode)); - else - printf("Currently not encrypting output\r\n"); - - if (decrypt_input) - printf("Currently decrypting input with %s\r\n", - ENCTYPE_NAME(decrypt_mode)); - else - printf("Currently not decrypting input\r\n"); -} - -int -EncryptStatus(void) -{ - printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n", - autoencrypt?"on":"off", autodecrypt?"on":"off"); - - if (encrypt_output) - printf("Currently encrypting output with %s\r\n", - ENCTYPE_NAME(encrypt_mode)); - else if (encrypt_mode) { - printf("Currently output is clear text.\r\n"); - printf("Last encryption mode was %s\r\n", - ENCTYPE_NAME(encrypt_mode)); - } else - printf("Currently not encrypting output\r\n"); - - if (decrypt_input) { - printf("Currently decrypting input with %s\r\n", - ENCTYPE_NAME(decrypt_mode)); - } else if (decrypt_mode) { - printf("Currently input is clear text.\r\n"); - printf("Last decryption mode was %s\r\n", - ENCTYPE_NAME(decrypt_mode)); - } else - printf("Currently not decrypting input\r\n"); - - return 1; -} - -void -encrypt_send_support(void) -{ - if (str_suplen) { - /* - * If the user has requested that decryption start - * immediatly, then send a "REQUEST START" before - * we negotiate the type. - */ - if (!Server && autodecrypt) - encrypt_send_request_start(); - telnet_net_write(str_send, str_suplen); - printsub('>', &str_send[2], str_suplen - 2); - str_suplen = 0; - } -} - -int -EncryptDebug(int on) -{ - if (on < 0) - encrypt_debug_mode ^= 1; - else - encrypt_debug_mode = on; - printf("Encryption debugging %s\r\n", - encrypt_debug_mode ? "enabled" : "disabled"); - return(1); -} - -/* turn on verbose encryption, but dont keep telling the whole world - */ -void encrypt_verbose_quiet(int on) -{ - if(on < 0) - encrypt_verbose ^= 1; - else - encrypt_verbose = on ? 1 : 0; -} - -int -EncryptVerbose(int on) -{ - encrypt_verbose_quiet(on); - printf("Encryption %s verbose\r\n", - encrypt_verbose ? "is" : "is not"); - return(1); -} - -int -EncryptAutoEnc(int on) -{ - encrypt_auto(on); - printf("Automatic encryption of output is %s\r\n", - autoencrypt ? "enabled" : "disabled"); - return(1); -} - -int -EncryptAutoDec(int on) -{ - decrypt_auto(on); - printf("Automatic decryption of input is %s\r\n", - autodecrypt ? "enabled" : "disabled"); - return(1); -} - -/* Called when we receive a WONT or a DONT ENCRYPT after we sent a DO - encrypt */ -void -encrypt_not(void) -{ - if (encrypt_verbose) - printf("[ Connection is NOT encrypted ]\r\n"); -} - -/* - * Called when ENCRYPT SUPPORT is received. - */ -void -encrypt_support(unsigned char *typelist, int cnt) -{ - int type, use_type = 0; - Encryptions *ep; - - /* - * Forget anything the other side has previously told us. - */ - remote_supports_decrypt = 0; - - while (cnt-- > 0) { - type = *typelist++; - if (encrypt_debug_mode) - printf(">>>%s: He is supporting %s (%d)\r\n", - Name, - ENCTYPE_NAME(type), type); - if ((type < ENCTYPE_CNT) && - (I_SUPPORT_ENCRYPT & typemask(type))) { - remote_supports_decrypt |= typemask(type); - if (use_type == 0) - use_type = type; - } - } - if (use_type) { - ep = findencryption(use_type); - if (!ep) - return; - type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0; - if (encrypt_debug_mode) - printf(">>>%s: (*ep->start)() returned %d\r\n", - Name, type); - if (type < 0) - return; - encrypt_mode = use_type; - if (type == 0) - encrypt_start_output(use_type); - } -} - -void -encrypt_is(unsigned char *data, int cnt) -{ - Encryptions *ep; - int type, ret; - - if (--cnt < 0) - return; - type = *data++; - if (type < ENCTYPE_CNT) - remote_supports_encrypt |= typemask(type); - if (!(ep = finddecryption(type))) { - if (encrypt_debug_mode) - printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", - Name, - ENCTYPE_NAME_OK(type) - ? ENCTYPE_NAME(type) : "(unknown)", - type); - return; - } - if (!ep->is) { - if (encrypt_debug_mode) - printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", - Name, - ENCTYPE_NAME_OK(type) - ? ENCTYPE_NAME(type) : "(unknown)", - type); - ret = 0; - } else { - ret = (*ep->is)(data, cnt); - if (encrypt_debug_mode) - printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt, - (ret < 0) ? "FAIL " : - (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); - } - if (ret < 0) { - autodecrypt = 0; - } else { - decrypt_mode = type; - if (ret == 0 && autodecrypt) - encrypt_send_request_start(); - } -} - -void -encrypt_reply(unsigned char *data, int cnt) -{ - Encryptions *ep; - int ret, type; - - if (--cnt < 0) - return; - type = *data++; - if (!(ep = findencryption(type))) { - if (encrypt_debug_mode) - printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", - Name, - ENCTYPE_NAME_OK(type) - ? ENCTYPE_NAME(type) : "(unknown)", - type); - return; - } - if (!ep->reply) { - if (encrypt_debug_mode) - printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", - Name, - ENCTYPE_NAME_OK(type) - ? ENCTYPE_NAME(type) : "(unknown)", - type); - ret = 0; - } else { - ret = (*ep->reply)(data, cnt); - if (encrypt_debug_mode) - printf("(*ep->reply)(%p, %d) returned %s(%d)\n", - data, cnt, - (ret < 0) ? "FAIL " : - (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); - } - if (encrypt_debug_mode) - printf(">>>%s: encrypt_reply returned %d\n", Name, ret); - if (ret < 0) { - autoencrypt = 0; - } else { - encrypt_mode = type; - if (ret == 0 && autoencrypt) - encrypt_start_output(type); - } -} - -/* - * Called when a ENCRYPT START command is received. - */ -void -encrypt_start(unsigned char *data, int cnt) -{ - Encryptions *ep; - - if (!decrypt_mode) { - /* - * Something is wrong. We should not get a START - * command without having already picked our - * decryption scheme. Send a REQUEST-END to - * attempt to clear the channel... - */ - printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name); - encrypt_send_request_end(); - return; - } - - if ((ep = finddecryption(decrypt_mode))) { - decrypt_input = ep->input; - if (encrypt_verbose) - printf("[ Input is now decrypted with type %s ]\r\n", - ENCTYPE_NAME(decrypt_mode)); - if (encrypt_debug_mode) - printf(">>>%s: Start to decrypt input with type %s\r\n", - Name, ENCTYPE_NAME(decrypt_mode)); - } else { - printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n", - Name, - ENCTYPE_NAME_OK(decrypt_mode) - ? ENCTYPE_NAME(decrypt_mode) - : "(unknown)", - decrypt_mode); - encrypt_send_request_end(); - } -} - -void -encrypt_session_key(Session_Key *key, int server) -{ - Encryptions *ep = encryptions; - - havesessionkey = 1; - - while (ep->type) { - if (ep->session) - (*ep->session)(key, server); - ++ep; - } -} - -/* - * Called when ENCRYPT END is received. - */ -void -encrypt_end(void) -{ - decrypt_input = 0; - if (encrypt_debug_mode) - printf(">>>%s: Input is back to clear text\r\n", Name); - if (encrypt_verbose) - printf("[ Input is now clear text ]\r\n"); -} - -/* - * Called when ENCRYPT REQUEST-END is received. - */ -void -encrypt_request_end(void) -{ - encrypt_send_end(); -} - -/* - * Called when ENCRYPT REQUEST-START is received. If we receive - * this before a type is picked, then that indicates that the - * other side wants us to start encrypting data as soon as we - * can. - */ -void -encrypt_request_start(unsigned char *data, int cnt) -{ - if (encrypt_mode == 0) { - if (Server) - autoencrypt = 1; - return; - } - encrypt_start_output(encrypt_mode); -} - -static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; - -static void -encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len) -{ - Encryptions *ep; - int dir = kp->dir; - int ret = 0; - - if (!(ep = (*kp->getcrypt)(*kp->modep))) { - if (len == 0) - return; - kp->keylen = 0; - } else if (len == 0) { - /* - * Empty option, indicates a failure. - */ - if (kp->keylen == 0) - return; - kp->keylen = 0; - if (ep->keyid) - (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); - - } else if ((len != kp->keylen) || (memcmp(keyid,kp->keyid,len) != 0)) { - /* - * Length or contents are different - */ - kp->keylen = len; - memcpy(kp->keyid,keyid, len); - if (ep->keyid) - (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); - } else { - if (ep->keyid) - ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen); - if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt) - encrypt_start_output(*kp->modep); - return; - } - - encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0); -} - -void encrypt_enc_keyid(unsigned char *keyid, int len) -{ - encrypt_keyid(&ki[1], keyid, len); -} - -void encrypt_dec_keyid(unsigned char *keyid, int len) -{ - encrypt_keyid(&ki[0], keyid, len); -} - - -void encrypt_send_keyid(int dir, unsigned char *keyid, int keylen, int saveit) -{ - unsigned char *strp; - - str_keyid[3] = (dir == DIR_ENCRYPT) - ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; - if (saveit) { - struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; - memcpy(kp->keyid,keyid, keylen); - kp->keylen = keylen; - } - - for (strp = &str_keyid[4]; keylen > 0; --keylen) { - if ((*strp++ = *keyid++) == IAC) - *strp++ = IAC; - } - *strp++ = IAC; - *strp++ = SE; - telnet_net_write(str_keyid, strp - str_keyid); - printsub('>', &str_keyid[2], strp - str_keyid - 2); -} - -void -encrypt_auto(int on) -{ - if (on < 0) - autoencrypt ^= 1; - else - autoencrypt = on ? 1 : 0; -} - -void -decrypt_auto(int on) -{ - if (on < 0) - autodecrypt ^= 1; - else - autodecrypt = on ? 1 : 0; -} - -void -encrypt_start_output(int type) -{ - Encryptions *ep; - unsigned char *p; - int i; - - if (!(ep = findencryption(type))) { - if (encrypt_debug_mode) { - printf(">>>%s: Can't encrypt with type %s (%d)\r\n", - Name, - ENCTYPE_NAME_OK(type) - ? ENCTYPE_NAME(type) : "(unknown)", - type); - } - return; - } - if (ep->start) { - i = (*ep->start)(DIR_ENCRYPT, Server); - if (encrypt_debug_mode) { - printf(">>>%s: Encrypt start: %s (%d) %s\r\n", - Name, - (i < 0) ? "failed" : - "initial negotiation in progress", - i, ENCTYPE_NAME(type)); - } - if (i) - return; - } - p = str_start + 3; - *p++ = ENCRYPT_START; - for (i = 0; i < ki[0].keylen; ++i) { - if ((*p++ = ki[0].keyid[i]) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - telnet_net_write(str_start, p - str_start); - net_encrypt(); - printsub('>', &str_start[2], p - &str_start[2]); - /* - * If we are already encrypting in some mode, then - * encrypt the ring (which includes our request) in - * the old mode, mark it all as "clear text" and then - * switch to the new mode. - */ - encrypt_output = ep->output; - encrypt_mode = type; - if (encrypt_debug_mode) - printf(">>>%s: Started to encrypt output with type %s\r\n", - Name, ENCTYPE_NAME(type)); - if (encrypt_verbose) - printf("[ Output is now encrypted with type %s ]\r\n", - ENCTYPE_NAME(type)); -} - -void -encrypt_send_end(void) -{ - if (!encrypt_output) - return; - - str_end[3] = ENCRYPT_END; - telnet_net_write(str_end, sizeof(str_end)); - net_encrypt(); - printsub('>', &str_end[2], sizeof(str_end) - 2); - /* - * Encrypt the output buffer now because it will not be done by - * netflush... - */ - encrypt_output = 0; - if (encrypt_debug_mode) - printf(">>>%s: Output is back to clear text\r\n", Name); - if (encrypt_verbose) - printf("[ Output is now clear text ]\r\n"); -} - -void -encrypt_send_request_start(void) -{ - unsigned char *p; - int i; - - p = &str_start[3]; - *p++ = ENCRYPT_REQSTART; - for (i = 0; i < ki[1].keylen; ++i) { - if ((*p++ = ki[1].keyid[i]) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - telnet_net_write(str_start, p - str_start); - printsub('>', &str_start[2], p - &str_start[2]); - if (encrypt_debug_mode) - printf(">>>%s: Request input to be encrypted\r\n", Name); -} - -void -encrypt_send_request_end(void) -{ - str_end[3] = ENCRYPT_REQEND; - telnet_net_write(str_end, sizeof(str_end)); - printsub('>', &str_end[2], sizeof(str_end) - 2); - - if (encrypt_debug_mode) - printf(">>>%s: Request input to be clear text\r\n", Name); -} - - -void encrypt_wait(void) -{ - if (encrypt_debug_mode) - printf(">>>%s: in encrypt_wait\r\n", Name); - if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt)) - return; - while (autoencrypt && !encrypt_output) - if (telnet_spin()) - return; -} - -int -encrypt_delay(void) -{ - if(!havesessionkey || - (I_SUPPORT_ENCRYPT & remote_supports_decrypt) == 0 || - (I_SUPPORT_DECRYPT & remote_supports_encrypt) == 0) - return 0; - if(!(encrypt_output && decrypt_input)) - return 1; - return 0; -} - -int encrypt_is_encrypting() -{ - if (encrypt_output && decrypt_input) - return 1; - return 0; -} - -void -encrypt_debug(int mode) -{ - encrypt_debug_mode = mode; -} - -void encrypt_gen_printsub(unsigned char *data, int cnt, - unsigned char *buf, int buflen) -{ - char tbuf[16], *cp; - - cnt -= 2; - data += 2; - buf[buflen-1] = '\0'; - buf[buflen-2] = '*'; - buflen -= 2;; - for (; cnt > 0; cnt--, data++) { - snprintf(tbuf, sizeof(tbuf), " %d", *data); - for (cp = tbuf; *cp && buflen > 0; --buflen) - *buf++ = *cp++; - if (buflen <= 0) - return; - } - *buf = '\0'; -} - -void -encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) -{ - Encryptions *ep; - int type = data[1]; - - for (ep = encryptions; ep->type && ep->type != type; ep++) - ; - - if (ep->printsub) - (*ep->printsub)(data, cnt, buf, buflen); - else - encrypt_gen_printsub(data, cnt, buf, buflen); -} -#endif diff --git a/libexec/telnetd/encrypt.h b/libexec/telnetd/encrypt.h deleted file mode 100644 index eeeff06e07b..00000000000 --- a/libexec/telnetd/encrypt.h +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)encrypt.h 8.1 (Berkeley) 6/4/93 - * $OpenBSD: encrypt.h,v 1.2 2003/06/02 19:38:25 millert Exp $ - * $NetBSD: encrypt.h,v 1.4 1996/02/24 01:15:20 jtk Exp $ - */ - -/* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America is assumed - * to require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -/* $KTH: encrypt.h,v 1.4 1997/01/24 23:10:56 assar Exp $ */ - -#ifndef __ENCRYPT__ -#define __ENCRYPT__ - -#define DIR_DECRYPT 1 -#define DIR_ENCRYPT 2 - -#define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \ - key[4] | key[5] | key[6] | key[7]) - -#define SAMEKEY(k1, k2) (!memcmp(k1, k2, sizeof(des_cblock))) - -typedef struct { - short type; - int length; - unsigned char *data; -} Session_Key; - -typedef struct { - char *name; - int type; - void (*output) (unsigned char *, int); - int (*input) (int); - void (*init) (int); - int (*start) (int, int); - int (*is) (unsigned char *, int); - int (*reply) (unsigned char *, int); - void (*session) (Session_Key *, int); - int (*keyid) (int, unsigned char *, int *); - void (*printsub) (unsigned char *, int, unsigned char *, int); -} Encryptions; - -#define SK_DES 1 /* Matched Kerberos v5 KEYTYPE_DES */ - -#include "enc-proto.h" - -extern int encrypt_debug_mode; -extern int (*decrypt_input) (int); -extern void (*encrypt_output) (unsigned char *, int); -#endif diff --git a/libexec/telnetd/ext.h b/libexec/telnetd/ext.h deleted file mode 100644 index a2ffa2b2d37..00000000000 --- a/libexec/telnetd/ext.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ext.h 8.2 (Berkeley) 12/15/93 - */ - -/* $KTH: ext.h,v 1.22 2001/04/24 23:12:11 assar Exp $ */ - -#ifndef __EXT_H__ -#define __EXT_H__ - -#include <arpa/telnet.h> - -/* - * Telnet server variable declarations - */ -extern char options[256]; -extern char do_dont_resp[256]; -extern char will_wont_resp[256]; -extern int flowmode; /* current flow control state */ -extern int restartany; /* restart output on any character state */ -#ifdef DIAGNOSTICS -extern int diagnostic; /* telnet diagnostic capabilities */ -#endif /* DIAGNOSTICS */ -extern int require_otp; -#ifdef AUTHENTICATION -extern int auth_level; -#endif -extern char *new_login; - -extern slcfun slctab[NSLC + 1]; /* slc mapping table */ - -extern char terminaltype[41]; - -/* - * I/O data buffers, pointers, and counters. - */ -extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; - -extern char netibuf[BUFSIZ], *netip; - -extern char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp; -extern char *neturg; /* one past last bye of urgent data */ - -extern int pcc, ncc; - -extern int ourpty, net; -extern char *line; -extern int SYNCHing; /* we are in TELNET SYNCH mode */ - -int telnet_net_write (unsigned char *str, int len); -void net_encrypt (void); -int telnet_spin (void); -char *telnet_getenv (const char *val); -char *telnet_gets (char *prompt, char *result, int length, int echo); -void get_slc_defaults (void); -void telrcv (void); -void send_do (int option, int init); -void willoption (int option); -void send_dont (int option, int init); -void wontoption (int option); -void send_will (int option, int init); -void dooption (int option); -void send_wont (int option, int init); -void dontoption (int option); -void suboption (void); -void doclientstat (void); -void send_status (void); -void init_termbuf (void); -void set_termbuf (void); -int spcset (int func, cc_t *valp, cc_t **valpp); -void set_utid (void); -int getpty (int *ptynum); -int tty_isecho (void); -int tty_flowmode (void); -int tty_restartany (void); -void tty_setecho (int on); -int tty_israw (void); -void tty_binaryin (int on); -void tty_binaryout (int on); -int tty_isbinaryin (void); -int tty_isbinaryout (void); -int tty_issofttab (void); -void tty_setsofttab (int on); -int tty_islitecho (void); -void tty_setlitecho (int on); -int tty_iscrnl (void); -void tty_tspeed (int val); -void tty_rspeed (int val); -void getptyslave (void); -int cleanopen (char *line); -void startslave (const char *host, const char *, int autologin, char *autoname); -void init_env (void); -void start_login (const char *host, int autologin, char *name); -void cleanup (int sig); -int main (int argc, char **argv); -int getterminaltype (char *name, size_t); -void _gettermname (void); -int terminaltypeok (char *s); -void my_telnet (int f, int p, const char*, const char *, int, char*); -void interrupt (void); -void sendbrk (void); -void sendsusp (void); -void recv_ayt (void); -void doeof (void); -void flowstat (void); -void clientstat (int code, int parm1, int parm2); -int ttloop (void); -int stilloob (int s); -void ptyflush (void); -char *nextitem (char *current); -void netclear (void); -void netflush (void); -void writenet (unsigned char *ptr, int len); -void fatal (int f, char *msg); -void fatalperror (int f, const char *msg); -void fatalperror_errno (int f, const char *msg, int error); -void edithost (char *pat, char *host); -void putstr (char *s); -void putchr (int cc); -void putf (char *cp, char *where); -void printoption (char *fmt, int option); -void printsub (int direction, unsigned char *pointer, int length); -void printdata (char *tag, char *ptr, int cnt); -int login_tty(int t); - -#ifdef ENCRYPTION -extern void (*encrypt_output) (unsigned char *, int); -extern int (*decrypt_input) (int); -extern char *nclearto; -#endif - - -/* - * The following are some clocks used to decide how to interpret - * the relationship between various variables. - */ - -struct clocks_t{ - int - system, /* what the current time is */ - echotoggle, /* last time user entered echo character */ - modenegotiated, /* last time operating mode negotiated */ - didnetreceive, /* last time we read data from network */ - ttypesubopt, /* ttype subopt is received */ - tspeedsubopt, /* tspeed subopt is received */ - environsubopt, /* environ subopt is received */ - oenvironsubopt, /* old environ subopt is received */ - xdisplocsubopt, /* xdisploc subopt is received */ - baseline, /* time started to do timed action */ - gotDM; /* when did we last see a data mark */ -}; -extern struct clocks_t clocks; - -extern int log_unauth; -extern int no_warn; - -#ifdef STREAMSPTY -extern int really_stream; -#endif - -#ifndef USE_IM -# ifdef CRAY -# define USE_IM "Cray UNICOS (%h) (%t)" -# endif -# ifdef _AIX -# define USE_IM "%s %v.%r (%h) (%t)" -# endif -# ifndef USE_IM -# define USE_IM "%s %r (%h) (%t)" -# endif -#endif - -#define DEFAULT_IM "\r\n\r\n" USE_IM "\r\n\r\n\r\n" - -#endif /* __EXT_H__ */ diff --git a/libexec/telnetd/genget.c b/libexec/telnetd/genget.c deleted file mode 100644 index 49503c238ea..00000000000 --- a/libexec/telnetd/genget.c +++ /dev/null @@ -1,104 +0,0 @@ -/* $OpenBSD: genget.c,v 1.2 2003/06/02 19:38:25 millert Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/* from: static char sccsid[] = "@(#)genget.c 8.2 (Berkeley) 5/30/95"; */ -/* from: static char *rcsid = "$NetBSD: genget.c,v 1.5 1996/02/24 01:15:21 jtk Exp $"; */ -static char *rcsid = "$OpenBSD: genget.c,v 1.2 2003/06/02 19:38:25 millert Exp $"; -#endif /* not lint */ - -/* $KTH: genget.c,v 1.6 1997/05/04 09:01:34 assar Exp $ */ - -#include <ctype.h> -#include "misc-proto.h" - -#define LOWER(x) (isupper((int)x) ? tolower((int)x) : (x)) -/* - * The prefix function returns 0 if *s1 is not a prefix - * of *s2. If *s1 exactly matches *s2, the negative of - * the length is returned. If *s1 is a prefix of *s2, - * the length of *s1 is returned. - */ -int -isprefix(char *s1, char *s2) -{ - char *os1; - char c1, c2; - - if (*s1 == '\0') - return(-1); - os1 = s1; - c1 = *s1; - c2 = *s2; - while (LOWER(c1) == LOWER(c2)) { - if (c1 == '\0') - break; - c1 = *++s1; - c2 = *++s2; - } - return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); -} - -static char *ambiguous; /* special return value for command routines */ - -char ** -genget(char *name, char **table, int stlen) - /* name to match */ - /* name entry in table */ - -{ - char **c, **found; - int n; - - if (name == 0) - return 0; - - found = 0; - for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { - if ((n = isprefix(name, *c)) == 0) - continue; - if (n < 0) /* exact match */ - return(c); - if (found) - return(&ambiguous); - found = c; - } - return(found); -} - -/* - * Function call version of Ambiguous() - */ -int -Ambiguous(void *s) -{ - return((char **)s == &ambiguous); -} diff --git a/libexec/telnetd/global.c b/libexec/telnetd/global.c deleted file mode 100644 index c7d008af540..00000000000 --- a/libexec/telnetd/global.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* a *lot* of ugly global definitions that really should be removed... - */ - -#include "telnetd.h" - -/* RCSID("$KTH: global.c,v 1.12 1997/05/11 06:29:59 assar Exp $"); */ - -/* - * Telnet server variable declarations - */ -char options[256]; -char do_dont_resp[256]; -char will_wont_resp[256]; -int linemode; /* linemode on/off */ -int flowmode; /* current flow control state */ -int restartany; /* restart output on any character state */ -#ifdef DIAGNOSTICS -int diagnostic; /* telnet diagnostic capabilities */ -#endif /* DIAGNOSTICS */ - -slcfun slctab[NSLC + 1]; /* slc mapping table */ - -char terminaltype[41]; - -/* - * I/O data buffers, pointers, and counters. - */ -char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; - -char netibuf[BUFSIZ], *netip; - -char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp; -char *neturg; /* one past last bye of urgent data */ - -int pcc, ncc; - -int ourpty, net; -int SYNCHing; /* we are in TELNET SYNCH mode */ - -/* - * The following are some clocks used to decide how to interpret - * the relationship between various variables. - */ - -struct clocks_t clocks; - - -/* whether to log unauthenticated login attempts */ -int log_unauth; - -/* do not print warning if connection is not encrypted */ -int no_warn; - -/* - * This function appends data to nfrontp and advances nfrontp. - */ - -int -output_data (const char *format, ...) -{ - va_list args; - size_t remaining; - int n; - - va_start(args, format); - remaining = BUFSIZ - (nfrontp - netobuf); - if (remaining == 0) { - va_end(args); - return remaining; - } - if ((n = vsnprintf(nfrontp, remaining, format, args)) >= remaining || n < 0) - n = strlen(nfrontp); - nfrontp += n; - va_end(args); - return n; -} diff --git a/libexec/telnetd/kerberos.c b/libexec/telnetd/kerberos.c deleted file mode 100644 index dde320a055f..00000000000 --- a/libexec/telnetd/kerberos.c +++ /dev/null @@ -1,751 +0,0 @@ -/* $OpenBSD: kerberos.c,v 1.2 2003/06/02 19:38:25 millert Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - /* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - * - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America is assumed - * to require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -/* $KTH: kerberos.c,v 1.50 2000/11/23 02:28:06 joda Exp $" */ - -#ifdef KRB4 -#include <sys/types.h> -#include <sys/socket.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <netinet/in.h> -#include <resolv.h> -#include <arpa/telnet.h> -#include <des.h> -#include <kerberosIV/krb.h> -#include <pwd.h> -#include <syslog.h> -#include <err.h> -#include "encrypt.h" -#include "auth.h" -#include "misc.h" - -int kerberos4_cksum (unsigned char *, int); -extern int auth_debug_mode; - -static unsigned char str_data[2048] = { IAC, SB, TELOPT_AUTHENTICATION, 0, - AUTHTYPE_KERBEROS_V4, }; - -#define KRB_AUTH 0 /* Authentication data follows */ -#define KRB_REJECT 1 /* Rejected (reason might follow) */ -#define KRB_ACCEPT 2 /* Accepted */ -#define KRB_CHALLENGE 3 /* Challenge for mutual auth. */ -#define KRB_RESPONSE 4 /* Response for mutual auth. */ - -#define KRB_FORWARD 5 /* */ -#define KRB_FORWARD_ACCEPT 6 /* */ -#define KRB_FORWARD_REJECT 7 /* */ - -#define KRB_SERVICE_NAME "rcmd" - -static KTEXT_ST auth; -static char name[ANAME_SZ]; -static AUTH_DAT adat; -static des_cblock session_key; -static des_cblock cred_session; -static des_key_schedule sched; -static des_cblock challenge; -static int auth_done; /* XXX */ - -static int pack_cred(CREDENTIALS *cred, unsigned char *buf); -static int unpack_cred(unsigned char *buf, int len, CREDENTIALS *cred); - -int -check_krb4_tickets() { - int ret; - int retval = 0; - char *file; - krb_principal princ; - - file = getenv("KRBTKFILE"); - if(file == NULL) - file = TKT_FILE; - - ret = krb_get_tf_realm(file, princ.realm); - switch(ret) { - case NO_TKT_FIL: - retval = 0; - goto done; - case 0: - retval = 1; - goto done; - default: - errx(1, "krb_get_tf_realm: %d", ret); - } - - done: - return retval; -} - -static int -Data(Authenticator *ap, int type, const void *d, int c) -{ - unsigned char *p = str_data + 4; - const unsigned char *cd = (const unsigned char *)d; - - if (c == -1) - c = strlen((const char *)cd); - - if (auth_debug_mode) { - printf("%s:%d: [%d] (%d)", - str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", - str_data[3], - type, c); - printd(d, c); - printf("\r\n"); - } - *p++ = ap->type; - *p++ = ap->way; - *p++ = type; - while (c-- > 0) { - if ((*p++ = *cd++) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - if (str_data[3] == TELQUAL_IS) - printsub('>', &str_data[2], p - (&str_data[2])); - return(telnet_net_write(str_data, p - str_data)); -} - -int -kerberos4_init(Authenticator *ap, int server) -{ - FILE *fp; - - if (server) { - str_data[3] = TELQUAL_REPLY; - if ((fp = fopen(KEYFILE, "r")) == NULL) - return(0); - fclose(fp); - } else { - str_data[3] = TELQUAL_IS; - } - return(1); -} - -char dst_realm_buf[REALM_SZ], *dest_realm = NULL; -int dst_realm_sz = REALM_SZ; - -static int -kerberos4_send(char *name, Authenticator *ap) -{ - KTEXT_ST auth; - char instance[INST_SZ]; - char *realm; - CREDENTIALS cred; - int r; - - if(check_krb4_tickets() != 1) - return 0; - - if (!UserNameRequested) { - if (auth_debug_mode) { - printf("Kerberos V4: no user name supplied\r\n"); - } - return(0); - } - - memset(instance, 0, sizeof(instance)); - - strlcpy (instance, - krb_get_phost(RemoteHostName), - INST_SZ); - - realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName); - - if (!realm) { - printf("Kerberos V4: no realm for %s\r\n", RemoteHostName); - return(0); - } - printf("[ Trying %s (%s.%s@%s) ... ]\r\n", name, - KRB_SERVICE_NAME, instance, realm); - r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0L); - if (r) { - printf("mk_req failed: %s\r\n", krb_get_err_text(r)); - return(0); - } - r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred); - if (r) { - printf("get_cred failed: %s\r\n", krb_get_err_text(r)); - return(0); - } - if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { - if (auth_debug_mode) - printf("Not enough room for user name\r\n"); - return(0); - } - if (auth_debug_mode) - printf("Sent %d bytes of authentication data\r\n", auth.length); - if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) { - if (auth_debug_mode) - printf("Not enough room for authentication data\r\n"); - return(0); - } -#ifdef ENCRYPTION - /* create challenge */ - if ((ap->way & AUTH_HOW_MASK)==AUTH_HOW_MUTUAL) { - int i; - - des_key_sched(&cred.session, sched); - memcpy (&cred_session, &cred.session, sizeof(cred_session)); - des_init_random_number_generator(&cred.session); - des_new_random_key(&session_key); - des_ecb_encrypt(&session_key, &session_key, sched, 0); - des_ecb_encrypt(&session_key, &challenge, sched, 0); - - /* - old code - Some CERT Advisory thinks this is a bad thing... - - des_init_random_number_generator(&cred.session); - des_new_random_key(&challenge); - des_ecb_encrypt(&challenge, &session_key, sched, 1); - */ - - /* - * Increment the challenge by 1, and encrypt it for - * later comparison. - */ - for (i = 7; i >= 0; --i) - if(++challenge[i] != 0) /* No carry! */ - break; - des_ecb_encrypt(&challenge, &challenge, sched, 1); - } - -#endif - - if (auth_debug_mode) { - printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); - printd(auth.dat, auth.length); - printf("\r\n"); - printf("Sent Kerberos V4 credentials to server\r\n"); - } - return(1); -} -int -kerberos4_send_mutual(Authenticator *ap) -{ - return kerberos4_send("mutual KERBEROS4", ap); -} - -int -kerberos4_send_oneway(Authenticator *ap) -{ - return kerberos4_send("KERBEROS4", ap); -} - -void -kerberos4_is(Authenticator *ap, unsigned char *data, int cnt) -{ - struct sockaddr_in addr; - char realm[REALM_SZ]; - char instance[INST_SZ]; - int r; - socklen_t addr_len; - - if (cnt-- < 1) - return; - switch (*data++) { - case KRB_AUTH: - if (krb_get_lrealm(realm, 1) != KSUCCESS) { - Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("No local realm\r\n"); - return; - } - memmove(auth.dat, data, auth.length = cnt); - if (auth_debug_mode) { - printf("Got %d bytes of authentication data\r\n", cnt); - printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length)); - printd(auth.dat, auth.length); - printf("\r\n"); - } - k_getsockinst(0, instance, sizeof(instance)); - addr_len = sizeof(addr); - if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) { - if(auth_debug_mode) - printf("getpeername failed\r\n"); - Data(ap, KRB_REJECT, "getpeername failed", -1); - auth_finished(ap, AUTH_REJECT); - return; - } - if (addr.sin_family != AF_INET) { - if (auth_debug_mode) - printf("unknown address family: %d\r\n", addr.sin_family); - Data(ap, KRB_REJECT, "bad address family", -1); - auth_finished(ap, AUTH_REJECT); - return; - } - - r = krb_rd_req(&auth, KRB_SERVICE_NAME, - instance, addr.sin_addr.s_addr, &adat, ""); - if (r) { - if (auth_debug_mode) - printf("Kerberos failed him as %s\r\n", name); - Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1); - auth_finished(ap, AUTH_REJECT); - return; - } - /* save the session key */ - memmove(session_key, adat.session, sizeof(adat.session)); - krb_kntoln(&adat, name); - - if (UserNameRequested && !kuserok(&adat, UserNameRequested)){ - char ts[MAXPATHLEN]; - struct passwd *pw = getpwnam(UserNameRequested); - - if(pw){ - snprintf(ts, sizeof(ts), - "%s%u", - TKT_ROOT, - (unsigned)pw->pw_uid); - esetenv("KRBTKFILE", ts, 1); - - if (pw->pw_uid == 0) - syslog(LOG_INFO|LOG_AUTH, - "ROOT Kerberos login from %s on %s", - krb_unparse_name_long(adat.pname, - adat.pinst, - adat.prealm), - RemoteHostName); - } - Data(ap, KRB_ACCEPT, NULL, 0); - } else { - char *msg; - - asprintf (&msg, "user `%s' is not authorized to " - "login as `%s'", - krb_unparse_name_long(adat.pname, - adat.pinst, - adat.prealm), - UserNameRequested ? UserNameRequested : "<nobody>"); - if (msg == NULL) - Data(ap, KRB_REJECT, NULL, 0); - else { - Data(ap, KRB_REJECT, (void *)msg, -1); - free(msg); - } - auth_finished(ap, AUTH_REJECT); - break; - } - auth_finished(ap, AUTH_USER); - break; - - case KRB_CHALLENGE: -#ifndef ENCRYPTION - Data(ap, KRB_RESPONSE, NULL, 0); -#else - if(!VALIDKEY(session_key)){ - Data(ap, KRB_RESPONSE, NULL, 0); - break; - } - des_key_sched(&session_key, sched); - { - des_cblock d_block; - int i; - Session_Key skey; - - memmove(d_block, data, sizeof(d_block)); - - /* make a session key for encryption */ - des_ecb_encrypt(&d_block, &session_key, sched, 1); - skey.type=SK_DES; - skey.length=8; - skey.data=session_key; - encrypt_session_key(&skey, 1); - - /* decrypt challenge, add one and encrypt it */ - des_ecb_encrypt(&d_block, &challenge, sched, 0); - for (i = 7; i >= 0; i--) - if(++challenge[i] != 0) - break; - des_ecb_encrypt(&challenge, &challenge, sched, 1); - Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge)); - } -#endif - break; - - case KRB_FORWARD: - { - des_key_schedule ks; - unsigned char netcred[sizeof(CREDENTIALS)]; - CREDENTIALS cred; - int ret; - if(cnt > sizeof(cred)) - abort(); - - memcpy (session_key, adat.session, sizeof(session_key)); - des_set_key(&session_key, ks); - des_pcbc_encrypt((void*)data, (void*)netcred, cnt, - ks, &session_key, DES_DECRYPT); - unpack_cred(netcred, cnt, &cred); - { - if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) || - strncmp(cred.instance, cred.realm, sizeof(cred.instance)) || - cred.lifetime < 0 || cred.lifetime > 255 || - cred.kvno < 0 || cred.kvno > 255 || - cred.issue_date < 0 || - cred.issue_date > time(0) + CLOCK_SKEW || - strncmp(cred.pname, adat.pname, sizeof(cred.pname)) || - strncmp(cred.pinst, adat.pinst, sizeof(cred.pinst))){ - Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1); - }else{ - if((ret = tf_setup(&cred, - cred.pname, - cred.pinst)) == KSUCCESS){ - struct passwd *pw = getpwnam(UserNameRequested); - - if (pw) - chown(tkt_string(), pw->pw_uid, pw->pw_gid); - Data(ap, KRB_FORWARD_ACCEPT, 0, 0); - } else{ - Data(ap, KRB_FORWARD_REJECT, - krb_get_err_text(ret), -1); - } - } - } - memset(data, 0, cnt); - memset(ks, 0, sizeof(ks)); - memset(&cred, 0, sizeof(cred)); - } - - break; - - default: - if (auth_debug_mode) - printf("Unknown Kerberos option %d\r\n", data[-1]); - Data(ap, KRB_REJECT, 0, 0); - break; - } -} - -void -kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt) -{ - Session_Key skey; - - if (cnt-- < 1) - return; - switch (*data++) { - case KRB_REJECT: - if(auth_done){ /* XXX Ick! */ - printf("[ Kerberos V4 received unknown opcode ]\r\n"); - }else{ - printf("[ Kerberos V4 refuses authentication "); - if (cnt > 0) - printf("because %.*s ", cnt, data); - printf("]\r\n"); - auth_send_retry(); - } - return; - case KRB_ACCEPT: - printf("[ Kerberos V4 accepts you ]\r\n"); - auth_done = 1; - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - /* - * Send over the encrypted challenge. - */ - Data(ap, KRB_CHALLENGE, session_key, - sizeof(session_key)); - des_ecb_encrypt(&session_key, &session_key, sched, 1); - skey.type = SK_DES; - skey.length = 8; - skey.data = session_key; - encrypt_session_key(&skey, 0); -#if 0 - kerberos4_forward(ap, &cred_session); -#endif - return; - } - auth_finished(ap, AUTH_USER); - return; - case KRB_RESPONSE: - /* make sure the response is correct */ - if ((cnt != sizeof(des_cblock)) || - (memcmp(data, challenge, sizeof(challenge)))){ - printf("[ Kerberos V4 challenge failed!!! ]\r\n"); - auth_send_retry(); - return; - } - printf("[ Kerberos V4 challenge successful ]\r\n"); - auth_finished(ap, AUTH_USER); - break; - case KRB_FORWARD_ACCEPT: - printf("[ Kerberos V4 accepted forwarded credentials ]\r\n"); - break; - case KRB_FORWARD_REJECT: - printf("[ Kerberos V4 rejected forwarded credentials: `%.*s']\r\n", - cnt, data); - break; - default: - if (auth_debug_mode) - printf("Unknown Kerberos option %d\r\n", data[-1]); - return; - } -} - -int -kerberos4_status(Authenticator *ap, char *name, size_t name_sz, int level) -{ - if (level < AUTH_USER) - return(level); - - if (UserNameRequested && !kuserok(&adat, UserNameRequested)) { - strlcpy(name, UserNameRequested, name_sz); - return(AUTH_VALID); - } else - return(AUTH_USER); -} - -#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} -#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} - -void -kerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) -{ - int i; - - buf[buflen-1] = '\0'; /* make sure its NULL terminated */ - buflen -= 1; - - switch(data[3]) { - case KRB_REJECT: /* Rejected (reason might follow) */ - strlcpy((char *)buf, " REJECT ", buflen); - goto common; - - case KRB_ACCEPT: /* Accepted (name might follow) */ - strlcpy((char *)buf, " ACCEPT ", buflen); - common: - BUMP(buf, buflen); - if (cnt <= 4) - break; - ADDC(buf, buflen, '"'); - for (i = 4; i < cnt; i++) - ADDC(buf, buflen, data[i]); - ADDC(buf, buflen, '"'); - ADDC(buf, buflen, '\0'); - break; - - case KRB_AUTH: /* Authentication data follows */ - strlcpy((char *)buf, " AUTH", buflen); - goto common2; - - case KRB_CHALLENGE: - strlcpy((char *)buf, " CHALLENGE", buflen); - goto common2; - - case KRB_RESPONSE: - strlcpy((char *)buf, " RESPONSE", buflen); - goto common2; - - default: - snprintf(buf, buflen, " %d (unknown)", data[3]); - common2: - BUMP(buf, buflen); - for (i = 4; i < cnt; i++) { - snprintf(buf, buflen, " %d", data[i]); - BUMP(buf, buflen); - } - break; - } -} - -int -kerberos4_cksum(unsigned char *d, int n) -{ - int ck = 0; - - /* - * A comment is probably needed here for those not - * well versed in the "C" language. Yes, this is - * supposed to be a "switch" with the body of the - * "switch" being a "while" statement. The whole - * purpose of the switch is to allow us to jump into - * the middle of the while() loop, and then not have - * to do any more switch()s. - * - * Some compilers will spit out a warning message - * about the loop not being entered at the top. - */ - switch (n&03) - while (n > 0) { - case 0: - ck ^= (int)*d++ << 24; - --n; - case 3: - ck ^= (int)*d++ << 16; - --n; - case 2: - ck ^= (int)*d++ << 8; - --n; - case 1: - ck ^= (int)*d++; - --n; - } - return(ck); -} - -static int -pack_cred(CREDENTIALS *cred, unsigned char *buf) -{ - unsigned char *p = buf; - - memcpy (p, cred->service, ANAME_SZ); - p += ANAME_SZ; - memcpy (p, cred->instance, INST_SZ); - p += INST_SZ; - memcpy (p, cred->realm, REALM_SZ); - p += REALM_SZ; - memcpy(p, cred->session, 8); - p += 8; - p += krb_put_int(cred->lifetime, p, 4, 4); - p += krb_put_int(cred->kvno, p, 4, 4); - p += krb_put_int(cred->ticket_st.length, p, 4, 4); - memcpy(p, cred->ticket_st.dat, cred->ticket_st.length); - p += cred->ticket_st.length; - p += krb_put_int(0, p, 4, 4); - p += krb_put_int(cred->issue_date, p, 4, 4); - memcpy (p, cred->pname, ANAME_SZ); - p += ANAME_SZ; - memcpy (p, cred->pinst, INST_SZ); - p += INST_SZ; - return p - buf; -} - -static int -unpack_cred(unsigned char *buf, int len, CREDENTIALS *cred) -{ - unsigned char *p = buf; - u_int32_t tmp; - - strncpy (cred->service, p, ANAME_SZ); - cred->service[ANAME_SZ - 1] = '\0'; - p += ANAME_SZ; - strncpy (cred->instance, p, INST_SZ); - cred->instance[INST_SZ - 1] = '\0'; - p += INST_SZ; - strncpy (cred->realm, p, REALM_SZ); - cred->realm[REALM_SZ - 1] = '\0'; - p += REALM_SZ; - - memcpy(cred->session, p, 8); - p += 8; - p += krb_get_int(p, &tmp, 4, 0); - cred->lifetime = tmp; - p += krb_get_int(p, &tmp, 4, 0); - cred->kvno = tmp; - - p += krb_get_int(p, &cred->ticket_st.length, 4, 0); - memcpy(cred->ticket_st.dat, p, cred->ticket_st.length); - p += cred->ticket_st.length; - p += krb_get_int(p, &tmp, 4, 0); - cred->ticket_st.mbz = 0; - p += krb_get_int(p, (u_int32_t *)&cred->issue_date, 4, 0); - - strncpy (cred->pname, p, ANAME_SZ); - cred->pname[ANAME_SZ - 1] = '\0'; - p += ANAME_SZ; - strncpy (cred->pinst, p, INST_SZ); - cred->pinst[INST_SZ - 1] = '\0'; - p += INST_SZ; - return 0; -} - - -int -kerberos4_forward(Authenticator *ap, void *v) -{ - des_cblock *key = (des_cblock *)v; - CREDENTIALS cred; - char *realm; - des_key_schedule ks; - int len; - unsigned char netcred[sizeof(CREDENTIALS)]; - int ret; - - realm = krb_realmofhost(RemoteHostName); - if(realm == NULL) - return -1; - memset(&cred, 0, sizeof(cred)); - ret = krb_get_cred(KRB_TICKET_GRANTING_TICKET, - realm, - realm, - &cred); - if(ret) - return ret; - des_set_key(key, ks); - len = pack_cred(&cred, netcred); - des_pcbc_encrypt((void*)netcred, (void*)netcred, len, - ks, key, DES_ENCRYPT); - memset(ks, 0, sizeof(ks)); - Data(ap, KRB_FORWARD, netcred, len); - memset(netcred, 0, sizeof(netcred)); - return 0; -} - -#endif /* KRB4 */ - diff --git a/libexec/telnetd/kerberos5.c b/libexec/telnetd/kerberos5.c deleted file mode 100644 index d0ff32dcf78..00000000000 --- a/libexec/telnetd/kerberos5.c +++ /dev/null @@ -1,910 +0,0 @@ -/* $OpenBSD: kerberos5.c,v 1.2 2003/06/02 19:38:25 millert Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - * - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -/* $KTH: kerberos5.c,v 1.47 2001/01/09 18:45:33 assar Exp $ */ - -#ifdef KRB5 - -#include <arpa/telnet.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <netdb.h> -#include <ctype.h> -#include <pwd.h> -#include <errno.h> -#define Authenticator k5_Authenticator -#include <kerberosV/krb5.h> -#undef Authenticator -#include <err.h> - -#include "encrypt.h" -#include "auth.h" -#include "misc.h" - -#if defined(DCE) -int dfsk5ok = 0; -int dfspag = 0; -int dfsfwd = 0; -#endif - -int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */ - -int forward(int); -int forwardable(int); - -/* These values need to be the same as those defined in telnet/main.c. */ -/* Either define them in both places, or put in some common header file. */ -#define OPTS_FORWARD_CREDS 0x00000002 -#define OPTS_FORWARDABLE_CREDS 0x00000001 - - -void kerberos5_forward (Authenticator *); - -static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, - AUTHTYPE_KERBEROS_V5, }; - -#define KRB_AUTH 0 /* Authentication data follows */ -#define KRB_REJECT 1 /* Rejected (reason might follow) */ -#define KRB_ACCEPT 2 /* Accepted */ -#define KRB_RESPONSE 3 /* Response for mutual auth. */ - -#define KRB_FORWARD 4 /* Forwarded credentials follow */ -#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */ -#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */ - -static krb5_data auth; -static krb5_ticket *ticket; - -static krb5_context context; -static krb5_auth_context auth_context; - -int -check_krb5_tickets() -{ - krb5_error_code ret; - krb5_context context; - krb5_ccache ccache; - krb5_principal principal; - int retval = 1; - - ret = krb5_init_context(&context); - if(ret) - errx(1, "krb5_init_context failt: %d", ret); - - ret = krb5_cc_default(context, &ccache); - if(ret) - errx(1, "krb5_cc_default: %d", ret); - - ret = krb5_cc_get_principal (context, ccache, &principal); - switch(ret) { - case ENOENT: - retval = 0; - goto done; - case 0: - retval = 1; - goto done; - default: - errx(1, "krb5_cc_get_principal: %d", ret); - break; - } - - done: - krb5_free_context(context); - return retval; -} - -static int -Data(Authenticator *ap, int type, void *d, int c) -{ - unsigned char *p = str_data + 4; - unsigned char *cd = (unsigned char *)d; - - if (c == -1) - c = strlen(cd); - - if (auth_debug_mode) { - printf("%s:%d: [%d] (%d)", - str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", - str_data[3], - type, c); - printd(d, c); - printf("\r\n"); - } - *p++ = ap->type; - *p++ = ap->way; - *p++ = type; - while (c-- > 0) { - if ((*p++ = *cd++) == IAC) - *p++ = IAC; - } - *p++ = IAC; - *p++ = SE; - if (str_data[3] == TELQUAL_IS) - printsub('>', &str_data[2], p - &str_data[2]); - return(telnet_net_write(str_data, p - str_data)); -} - -int -kerberos5_init(Authenticator *ap, int server) -{ - krb5_error_code ret; - - ret = krb5_init_context(&context); - if (ret) - return 0; - if (server) { - krb5_keytab kt; - krb5_kt_cursor cursor; - - ret = krb5_kt_default(context, &kt); - if (ret) - return 0; - - ret = krb5_kt_start_seq_get (context, kt, &cursor); - if (ret) { - krb5_kt_close (context, kt); - return 0; - } - krb5_kt_end_seq_get (context, kt, &cursor); - krb5_kt_close (context, kt); - - str_data[3] = TELQUAL_REPLY; - } else - str_data[3] = TELQUAL_IS; - return(1); -} - -extern int net; -static int -kerberos5_send(char *name, Authenticator *ap) -{ - krb5_error_code ret; - krb5_ccache ccache; - int ap_opts; - krb5_data cksum_data; - char foo[2]; - - if(check_krb5_tickets() != 1) - return 0; - - if (!UserNameRequested) { - if (auth_debug_mode) { - printf("Kerberos V5: no user name supplied\r\n"); - } - return(0); - } - - ret = krb5_cc_default(context, &ccache); - if (ret) { - if (auth_debug_mode) { - printf("Kerberos V5: could not get default ccache: %s\r\n", - krb5_get_err_text (context, ret)); - } - return 0; - } - - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) - ap_opts = AP_OPTS_MUTUAL_REQUIRED; - else - ap_opts = 0; - - ap_opts |= AP_OPTS_USE_SUBKEY; - - ret = krb5_auth_con_init (context, &auth_context); - if (ret) { - if (auth_debug_mode) { - printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", - krb5_get_err_text(context, ret)); - } - return(0); - } - - ret = krb5_auth_con_setaddrs_from_fd (context, - auth_context, - &net); - if (ret) { - if (auth_debug_mode) { - printf ("Kerberos V5:" - " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", - krb5_get_err_text(context, ret)); - } - return(0); - } - - krb5_auth_con_setkeytype (context, auth_context, KEYTYPE_DES); - - foo[0] = ap->type; - foo[1] = ap->way; - - cksum_data.length = sizeof(foo); - cksum_data.data = foo; - - - { - krb5_principal service; - char sname[128]; - - - ret = krb5_sname_to_principal (context, - RemoteHostName, - NULL, - KRB5_NT_SRV_HST, - &service); - if(ret) { - if (auth_debug_mode) { - printf ("Kerberos V5:" - " krb5_sname_to_principal(%s) failed (%s)\r\n", - RemoteHostName, krb5_get_err_text(context, ret)); - } - return 0; - } - ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname)); - if(ret) { - if (auth_debug_mode) { - printf ("Kerberos V5:" - " krb5_unparse_name_fixed failed (%s)\r\n", - krb5_get_err_text(context, ret)); - } - return 0; - } - printf("[ Trying %s (%s)... ]\r\n", name, sname); - ret = krb5_mk_req_exact(context, &auth_context, ap_opts, - service, - &cksum_data, ccache, &auth); - krb5_free_principal (context, service); - - } - if (ret) { - if (1 || auth_debug_mode) { - printf("Kerberos V5: mk_req failed (%s)\r\n", - krb5_get_err_text(context, ret)); - } - return(0); - } - - if (!auth_sendname((unsigned char *)UserNameRequested, - strlen(UserNameRequested))) { - if (auth_debug_mode) - printf("Not enough room for user name\r\n"); - return(0); - } - if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { - if (auth_debug_mode) - printf("Not enough room for authentication data\r\n"); - return(0); - } - if (auth_debug_mode) { - printf("Sent Kerberos V5 credentials to server\r\n"); - } - return(1); -} - -int -kerberos5_send_mutual(Authenticator *ap) -{ - return kerberos5_send("mutual KERBEROS5", ap); -} - -int -kerberos5_send_oneway(Authenticator *ap) -{ - return kerberos5_send("KERBEROS5", ap); -} - -void -kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) -{ - krb5_error_code ret; - krb5_data outbuf; - krb5_keyblock *key_block; - char *name; - krb5_principal server; - int zero = 0; - - if (cnt-- < 1) - return; - switch (*data++) { - case KRB_AUTH: - auth.data = (char *)data; - auth.length = cnt; - - auth_context = NULL; - - ret = krb5_auth_con_init (context, &auth_context); - if (ret) { - Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", - krb5_get_err_text(context, ret)); - return; - } - - ret = krb5_auth_con_setaddrs_from_fd (context, - auth_context, - &zero); - if (ret) { - Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: " - "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", - krb5_get_err_text(context, ret)); - return; - } - - ret = krb5_sock_to_principal (context, - 0, - "host", - KRB5_NT_SRV_HST, - &server); - if (ret) { - Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: " - "krb5_sock_to_principal failed (%s)\r\n", - krb5_get_err_text(context, ret)); - return; - } - - ret = krb5_rd_req(context, - &auth_context, - &auth, - server, - NULL, - NULL, - &ticket); - - krb5_free_principal (context, server); - if (ret) { - char *errbuf; - - asprintf(&errbuf, - "Read req failed: %s", - krb5_get_err_text(context, ret)); - Data(ap, KRB_REJECT, errbuf, -1); - if (auth_debug_mode) - printf("%s\r\n", errbuf); - free (errbuf); - return; - } - - { - char foo[2]; - - foo[0] = ap->type; - foo[1] = ap->way; - - ret = krb5_verify_authenticator_checksum(context, - auth_context, - foo, - sizeof(foo)); - - if (ret) { - char *errbuf; - asprintf(&errbuf, "Bad checksum: %s", - krb5_get_err_text(context, ret)); - Data(ap, KRB_REJECT, errbuf, -1); - if (auth_debug_mode) - printf ("%s\r\n", errbuf); - free(errbuf); - return; - } - } - ret = krb5_auth_con_getremotesubkey (context, - auth_context, - &key_block); - - if (ret) { - Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: " - "krb5_auth_con_getremotesubkey failed (%s)\r\n", - krb5_get_err_text(context, ret)); - return; - } - - if (key_block == NULL) { - ret = krb5_auth_con_getkey(context, - auth_context, - &key_block); - } - if (ret) { - Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: " - "krb5_auth_con_getkey failed (%s)\r\n", - krb5_get_err_text(context, ret)); - return; - } - if (key_block == NULL) { - Data(ap, KRB_REJECT, "no subkey received", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: " - "krb5_auth_con_getremotesubkey returned NULL key\r\n"); - return; - } - - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - ret = krb5_mk_rep(context, auth_context, &outbuf); - if (ret) { - Data(ap, KRB_REJECT, - "krb5_mk_rep failed", -1); - auth_finished(ap, AUTH_REJECT); - if (auth_debug_mode) - printf("Kerberos V5: " - "krb5_mk_rep failed (%s)\r\n", - krb5_get_err_text(context, ret)); - return; - } - Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); - } - if (krb5_unparse_name(context, ticket->client, &name)) - name = 0; - - if(UserNameRequested && krb5_kuserok(context, - ticket->client, - UserNameRequested)) { - Data(ap, KRB_ACCEPT, name, name ? -1 : 0); - if (auth_debug_mode) { - printf("Kerberos5 identifies him as ``%s''\r\n", - name ? name : ""); - } - - if(key_block->keytype == ETYPE_DES_CBC_MD5 || - key_block->keytype == ETYPE_DES_CBC_MD4 || - key_block->keytype == ETYPE_DES_CBC_CRC) { - Session_Key skey; - - skey.type = SK_DES; - skey.length = 8; - skey.data = key_block->keyvalue.data; - encrypt_session_key(&skey, 0); - } - - } else { - char *msg; - - asprintf (&msg, "user `%s' is not authorized to " - "login as `%s'", - name ? name : "<unknown>", - UserNameRequested ? UserNameRequested : "<nobody>"); - if (msg == NULL) - Data(ap, KRB_REJECT, NULL, 0); - else { - Data(ap, KRB_REJECT, (void *)msg, -1); - free(msg); - } - auth_finished (ap, AUTH_REJECT); - krb5_free_keyblock_contents(context, key_block); - break; - } - auth_finished(ap, AUTH_USER); - krb5_free_keyblock_contents(context, key_block); - - break; - case KRB_FORWARD: { - struct passwd *pwd; - char ccname[1024]; /* XXX */ - krb5_data inbuf; - krb5_ccache ccache; - inbuf.data = (char *)data; - inbuf.length = cnt; - - pwd = getpwnam (UserNameRequested); - if (pwd == NULL) - break; - - snprintf (ccname, sizeof(ccname), - "FILE:/tmp/krb5cc_%u", pwd->pw_uid); - - ret = krb5_cc_resolve (context, ccname, &ccache); - if (ret) { - if (auth_debug_mode) - printf ("Kerberos V5: could not get ccache: %s\r\n", - krb5_get_err_text(context, ret)); - break; - } - - ret = krb5_cc_initialize (context, - ccache, - ticket->client); - if (ret) { - if (auth_debug_mode) - printf ("Kerberos V5: could not init ccache: %s\r\n", - krb5_get_err_text(context, ret)); - break; - } - -#if defined(DCE) - esetenv("KRB5CCNAME", ccname, 1); -#endif - ret = krb5_rd_cred2 (context, - auth_context, - ccache, - &inbuf); - if(ret) { - char *errbuf; - - asprintf (&errbuf, - "Read forwarded creds failed: %s", - krb5_get_err_text (context, ret)); - if(errbuf == NULL) - Data(ap, KRB_FORWARD_REJECT, NULL, 0); - else - Data(ap, KRB_FORWARD_REJECT, errbuf, -1); - if (auth_debug_mode) - printf("Could not read forwarded credentials: %s\r\n", - errbuf); - free (errbuf); - } else { - Data(ap, KRB_FORWARD_ACCEPT, 0, 0); -#if defined(DCE) - dfsfwd = 1; -#endif - } - chown (ccname + 5, pwd->pw_uid, -1); - if (auth_debug_mode) - printf("Forwarded credentials obtained\r\n"); - break; - } - default: - if (auth_debug_mode) - printf("Unknown Kerberos option %d\r\n", data[-1]); - Data(ap, KRB_REJECT, 0, 0); - break; - } -} - -void -kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) -{ - static int mutual_complete = 0; - - if (cnt-- < 1) - return; - switch (*data++) { - case KRB_REJECT: - if (cnt > 0) { - printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", - cnt, data); - } else - printf("[ Kerberos V5 refuses authentication ]\r\n"); - auth_send_retry(); - return; - case KRB_ACCEPT: { - krb5_error_code ret; - Session_Key skey; - krb5_keyblock *keyblock; - - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && - !mutual_complete) { - printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n"); - auth_send_retry(); - return; - } - if (cnt) - printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data); - else - printf("[ Kerberos V5 accepts you ]\r\n"); - - ret = krb5_auth_con_getlocalsubkey (context, - auth_context, - &keyblock); - if (ret) - ret = krb5_auth_con_getkey (context, - auth_context, - &keyblock); - if(ret) { - printf("[ krb5_auth_con_getkey: %s ]\r\n", - krb5_get_err_text(context, ret)); - auth_send_retry(); - return; - } - - skey.type = SK_DES; - skey.length = 8; - skey.data = keyblock->keyvalue.data; - encrypt_session_key(&skey, 0); - krb5_free_keyblock_contents (context, keyblock); - auth_finished(ap, AUTH_USER); - if (forward_flags & OPTS_FORWARD_CREDS) - kerberos5_forward(ap); - break; - } - case KRB_RESPONSE: - if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { - /* the rest of the reply should contain a krb_ap_rep */ - krb5_ap_rep_enc_part *reply; - krb5_data inbuf; - krb5_error_code ret; - - inbuf.length = cnt; - inbuf.data = (char *)data; - - ret = krb5_rd_rep(context, auth_context, &inbuf, &reply); - if (ret) { - printf("[ Mutual authentication failed: %s ]\r\n", - krb5_get_err_text (context, ret)); - auth_send_retry(); - return; - } - krb5_free_ap_rep_enc_part(context, reply); - mutual_complete = 1; - } - return; - case KRB_FORWARD_ACCEPT: - printf("[ Kerberos V5 accepted forwarded credentials ]\r\n"); - return; - case KRB_FORWARD_REJECT: - printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", - cnt, data); - return; - default: - if (auth_debug_mode) - printf("Unknown Kerberos option %d\r\n", data[-1]); - return; - } -} - -int -kerberos5_status(Authenticator *ap, char *name, size_t name_sz, int level) -{ - if (level < AUTH_USER) - return(level); - - if (UserNameRequested && - krb5_kuserok(context, - ticket->client, - UserNameRequested)) - { - strlcpy(name, UserNameRequested, name_sz); -#if defined(DCE) - dfsk5ok = 1; -#endif - return(AUTH_VALID); - } else - return(AUTH_USER); -} - -#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} -#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} - -void -kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) -{ - int i; - - buf[buflen-1] = '\0'; /* make sure its NULL terminated */ - buflen -= 1; - - switch(data[3]) { - case KRB_REJECT: /* Rejected (reason might follow) */ - strlcpy((char *)buf, " REJECT ", buflen); - goto common; - - case KRB_ACCEPT: /* Accepted (name might follow) */ - strlcpy((char *)buf, " ACCEPT ", buflen); - common: - BUMP(buf, buflen); - if (cnt <= 4) - break; - ADDC(buf, buflen, '"'); - for (i = 4; i < cnt; i++) - ADDC(buf, buflen, data[i]); - ADDC(buf, buflen, '"'); - ADDC(buf, buflen, '\0'); - break; - - - case KRB_AUTH: /* Authentication data follows */ - strlcpy((char *)buf, " AUTH", buflen); - goto common2; - - case KRB_RESPONSE: - strlcpy((char *)buf, " RESPONSE", buflen); - goto common2; - - case KRB_FORWARD: /* Forwarded credentials follow */ - strlcpy((char *)buf, " FORWARD", buflen); - goto common2; - - case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ - strlcpy((char *)buf, " FORWARD_ACCEPT", buflen); - goto common2; - - case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ - /* (reason might follow) */ - strlcpy((char *)buf, " FORWARD_REJECT", buflen); - goto common2; - - default: - snprintf(buf, buflen, " %d (unknown)", data[3]); - common2: - BUMP(buf, buflen); - for (i = 4; i < cnt; i++) { - snprintf(buf, buflen, " %d", data[i]); - BUMP(buf, buflen); - } - break; - } -} - -void -kerberos5_forward(Authenticator *ap) -{ - krb5_error_code ret; - krb5_ccache ccache; - krb5_creds creds; - krb5_kdc_flags flags; - krb5_data out_data; - krb5_principal principal; - - ret = krb5_cc_default (context, &ccache); - if (ret) { - if (auth_debug_mode) - printf ("KerberosV5: could not get default ccache: %s\r\n", - krb5_get_err_text (context, ret)); - return; - } - - ret = krb5_cc_get_principal (context, ccache, &principal); - if (ret) { - if (auth_debug_mode) - printf ("KerberosV5: could not get principal: %s\r\n", - krb5_get_err_text (context, ret)); - return; - } - - memset (&creds, 0, sizeof(creds)); - - creds.client = principal; - - ret = krb5_build_principal (context, - &creds.server, - strlen(principal->realm), - principal->realm, - "krbtgt", - principal->realm, - NULL); - - if (ret) { - if (auth_debug_mode) - printf ("KerberosV5: could not get principal: %s\r\n", - krb5_get_err_text (context, ret)); - return; - } - - creds.times.endtime = 0; - - flags.i = 0; - flags.b.forwarded = 1; - if (forward_flags & OPTS_FORWARDABLE_CREDS) - flags.b.forwardable = 1; - - ret = krb5_get_forwarded_creds (context, - auth_context, - ccache, - flags.i, - RemoteHostName, - &creds, - &out_data); - if (ret) { - if (auth_debug_mode) - printf ("Kerberos V5: error getting forwarded creds: %s\r\n", - krb5_get_err_text (context, ret)); - return; - } - - if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) { - if (auth_debug_mode) - printf("Not enough room for authentication data\r\n"); - } else { - if (auth_debug_mode) - printf("Forwarded local Kerberos V5 credentials to server\r\n"); - } -} - -#if defined(DCE) -/* if this was a K5 authentication try and join a PAG for the user. */ -void -kerberos5_dfspag(void) -{ - if (dfsk5ok) { - dfspag = krb5_dfs_pag(context, dfsfwd, ticket->client, - UserNameRequested); - } -} -#endif - -int -kerberos5_set_forward(int on) -{ - if(on == 0) - forward_flags &= ~OPTS_FORWARD_CREDS; - if(on == 1) - forward_flags |= OPTS_FORWARD_CREDS; - if(on == -1) - forward_flags ^= OPTS_FORWARD_CREDS; - return 0; -} - -int -kerberos5_set_forwardable(int on) -{ - if(on == 0) - forward_flags &= ~OPTS_FORWARDABLE_CREDS; - if(on == 1) - forward_flags |= OPTS_FORWARDABLE_CREDS; - if(on == -1) - forward_flags ^= OPTS_FORWARDABLE_CREDS; - return 0; -} - -#endif /* KRB5 */ diff --git a/libexec/telnetd/mini_inetd.c b/libexec/telnetd/mini_inetd.c deleted file mode 100644 index a240e306f13..00000000000 --- a/libexec/telnetd/mini_inetd.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -RCSID("$KTH: mini_inetd.c,v 1.28 2000/10/08 13:38:47 assar Exp $"); -#endif - -#include "telnetd.h" - -#include <err.h> - -#ifndef max -#define max(a,b) (((a)>(b))?(a):(b)) -#endif - -/* - * accept a connection on `s' and pretend it's served by inetd. - */ - -static void -accept_it (int s) -{ - int s2; - - s2 = accept(s, NULL, NULL); - if(s2 < 0) - err (1, "accept"); - close(s); - dup2(s2, STDIN_FILENO); - dup2(s2, STDOUT_FILENO); - /* dup2(s2, STDERR_FILENO); */ - close(s2); -} - -/* - * Listen on `port' emulating inetd. - */ - -void -mini_inetd (int port) -{ - int error, ret; - struct addrinfo *ai, *a, hints; - char portstr[NI_MAXSERV]; - int n, nalloc, i; - int *fds; - fd_set orig_read_set, read_set; - int max_fd = -1; - - memset (&hints, 0, sizeof(hints)); - hints.ai_flags = AI_PASSIVE; - hints.ai_socktype = SOCK_STREAM; - - snprintf (portstr, sizeof(portstr), "%d", ntohs(port)); - - error = getaddrinfo (NULL, portstr, &hints, &ai); - if (error) - errx (1, "getaddrinfo: %s", gai_strerror (error)); - - for (nalloc = 0, a = ai; a != NULL; a = a->ai_next) - ++nalloc; - - fds = malloc (nalloc * sizeof(*fds)); - if (fds == NULL) - errx (1, "mini_inetd: out of memory"); - - FD_ZERO(&orig_read_set); - - for (i = 0, a = ai; a != NULL; a = a->ai_next) { - fds[i] = socket (a->ai_family, a->ai_socktype, a->ai_protocol); - if (fds[i] < 0) { - warn ("socket"); - continue; - } - socket_set_reuseaddr (fds[i], 1); - if (bind (fds[i], a->ai_addr, a->ai_addrlen) < 0) - err (1, "bind"); - if (listen (fds[i], SOMAXCONN) < 0) - err (1, "listen"); - if (fds[i] >= FD_SETSIZE) - errx (1, "fd too large"); - FD_SET(fds[i], &orig_read_set); - max_fd = max(max_fd, fds[i]); - ++i; - } - freeaddrinfo (ai); - if (i == 0) - errx (1, "no sockets"); - n = i; - - do { - read_set = orig_read_set; - - ret = select (max_fd + 1, &read_set, NULL, NULL, NULL); - if (ret < 0 && errno != EINTR) - err (1, "select"); - } while (ret <= 0); - - for (i = 0; i < n; ++i) - if (FD_ISSET (fds[i], &read_set)) { - accept_it (fds[i]); - return; - } - abort (); -} diff --git a/libexec/telnetd/misc-proto.h b/libexec/telnetd/misc-proto.h deleted file mode 100644 index 978e3b8446a..00000000000 --- a/libexec/telnetd/misc-proto.h +++ /dev/null @@ -1,90 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)misc-proto.h 8.1 (Berkeley) 6/4/93 - * $OpenBSD: misc-proto.h,v 1.2 2003/06/02 19:38:25 millert Exp $ - * $NetBSD: misc-proto.h,v 1.5 1996/02/24 01:15:23 jtk Exp $ - */ - -/* - * This source code is no longer held under any constraint of USA - * `cryptographic laws' since it was exported legally. The cryptographic - * functions were removed from the code and a "Bones" distribution was - * made. A Commodity Jurisdiction Request #012-94 was filed with the - * USA State Department, who handed it to the Commerce department. The - * code was determined to fall under General License GTDA under ECCN 5D96G, - * and hence exportable. The cryptographic interfaces were re-added by Eric - * Young, and then KTH proceeded to maintain the code in the free world. - * - */ - -/* - * Copyright (C) 1990 by the Massachusetts Institute of Technology - * - * Export of this software from the United States of America is assumed - * to require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -/* $KTH: misc-proto.h,v 1.9 2000/11/15 23:00:21 assar Exp $ */ - -#ifndef __MISC_PROTO__ -#define __MISC_PROTO__ - -void auth_encrypt_init (const char *, const char *, const char *, int); -void auth_encrypt_user(const char *name); -void auth_encrypt_connect (int); -void printd (const unsigned char *, int); - -char** genget (char *name, char **table, int stlen); -int isprefix(char *s1, char *s2); -int Ambiguous(void *s); - -/* - * These functions are imported from the application - */ -int telnet_net_write (unsigned char *, int); -void net_encrypt (void); -int telnet_spin (void); -char *telnet_getenv (const char *); -char *telnet_gets (char *, char *, int, int); -void printsub(int direction, unsigned char *pointer, int length); -void esetenv(const char *, const char *, int); -#endif diff --git a/libexec/telnetd/misc.c b/libexec/telnetd/misc.c deleted file mode 100644 index 69b049c6302..00000000000 --- a/libexec/telnetd/misc.c +++ /dev/null @@ -1,102 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -/* from: static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93"; */ -/* from: static char rcsid[] = "$NetBSD: misc.c,v 1.5 1996/02/24 01:15:25 jtk Exp $"; */ -static char rcsid[] = "$OpenBSD: misc.c,v 1.2 2003/06/02 19:38:25 millert Exp $"; -#endif /* not lint */ - -/* $KTH: misc.c,v 1.15 2000/01/25 23:24:58 assar Exp $ */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <err.h> -#include "misc.h" -#include "auth.h" -#include "encrypt.h" - - -const char *RemoteHostName; -const char *LocalHostName; -char *UserNameRequested = 0; -int ConnectedCount = 0; - -void -auth_encrypt_init(const char *local, const char *remote, const char *name, - int server) -{ - RemoteHostName = remote; - LocalHostName = local; -#ifdef AUTHENTICATION - auth_init(name, server); -#endif -#ifdef ENCRYPTION - encrypt_init(name, server); -#endif - if (UserNameRequested) { - free(UserNameRequested); - UserNameRequested = 0; - } -} - -void -auth_encrypt_user(const char *name) -{ - if (UserNameRequested) - free(UserNameRequested); - UserNameRequested = name ? strdup(name) : 0; -} - -void -auth_encrypt_connect(int cnt) -{ -} - -void -printd(const unsigned char *data, int cnt) -{ - if (cnt > 16) - cnt = 16; - while (cnt-- > 0) { - printf(" %02x", *data); - ++data; - } -} - -/* This is stolen from libroken; it's the only thing actually needed from - * libroken. - */ -void -esetenv(const char *var, const char *val, int rewrite) -{ - if (setenv ((char *)var, (char *)val, rewrite)) - errx (1, "failed setting environment variable %s", var); -} diff --git a/libexec/telnetd/misc.h b/libexec/telnetd/misc.h deleted file mode 100644 index f98e78ad23d..00000000000 --- a/libexec/telnetd/misc.h +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)misc.h 8.1 (Berkeley) 6/4/93 - * $OpenBSD: misc.h,v 1.2 2003/06/02 19:38:25 millert Exp $ - * $NetBSD: misc.h,v 1.4 1996/02/24 01:15:27 jtk Exp $ - */ - -extern char *UserNameRequested; -extern const char *LocalHostName; -extern const char *RemoteHostName; -extern int ConnectedCount; -extern int ReservedPort; - -#include "misc-proto.h" diff --git a/libexec/telnetd/slc.c b/libexec/telnetd/slc.c deleted file mode 100644 index ea82b3373ec..00000000000 --- a/libexec/telnetd/slc.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "telnetd.h" - -/* RCSID("$KTH: slc.c,v 1.10 1997/05/11 06:30:00 assar Exp $"); */ - -/* - * get_slc_defaults - * - * Initialize the slc mapping table. - */ -void -get_slc_defaults(void) -{ - int i; - - init_termbuf(); - - for (i = 1; i <= NSLC; i++) { - slctab[i].defset.flag = - spcset(i, &slctab[i].defset.val, &slctab[i].sptr); - slctab[i].current.flag = SLC_NOSUPPORT; - slctab[i].current.val = 0; - } - -} diff --git a/libexec/telnetd/socket.c b/libexec/telnetd/socket.c deleted file mode 100644 index ef0ecee692b..00000000000 --- a/libexec/telnetd/socket.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -RCSID("$KTH: socket.c,v 1.5 2000/07/27 04:41:06 assar Exp $"); -#endif - -#include <telnetd.h> -#include <err.h> -#include <netinet/in.h> - -/* - * set the reuse of addresses on `sock' to `val'. - */ - -void -socket_set_reuseaddr (int sock, int val) -{ -#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) - if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, - sizeof(val)) < 0) - err (1, "setsockopt SO_REUSEADDR"); -#endif -} diff --git a/libexec/telnetd/state.c b/libexec/telnetd/state.c deleted file mode 100644 index 2daab2c4600..00000000000 --- a/libexec/telnetd/state.c +++ /dev/null @@ -1,1400 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "telnetd.h" -#include <syslog.h> - -/* RCSID("$KTH: state.c,v 1.14 2000/10/02 05:06:02 assar Exp $"); */ - -unsigned char doopt[] = { IAC, DO, '%', 'c', 0 }; -unsigned char dont[] = { IAC, DONT, '%', 'c', 0 }; -unsigned char will[] = { IAC, WILL, '%', 'c', 0 }; -unsigned char wont[] = { IAC, WONT, '%', 'c', 0 }; -int not42 = 1; - -/* - * Buffer for sub-options, and macros - * for suboptions buffer manipulations - */ -unsigned char subbuffer[2048], *subpointer= subbuffer, *subend= subbuffer; - -#define SB_CLEAR() subpointer = subbuffer -#define SB_TERM() { subend = subpointer; SB_CLEAR(); } -#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ - *subpointer++ = (c); \ - } -#define SB_GET() ((*subpointer++)&0xff) -#define SB_EOF() (subpointer >= subend) -#define SB_LEN() (subend - subpointer) - -#ifdef ENV_HACK -unsigned char *subsave; -#define SB_SAVE() subsave = subpointer; -#define SB_RESTORE() subpointer = subsave; -#endif - - -/* - * State for recv fsm - */ -#define TS_DATA 0 /* base state */ -#define TS_IAC 1 /* look for double IAC's */ -#define TS_CR 2 /* CR-LF ->'s CR */ -#define TS_SB 3 /* throw away begin's... */ -#define TS_SE 4 /* ...end's (suboption negotiation) */ -#define TS_WILL 5 /* will option negotiation */ -#define TS_WONT 6 /* wont -''- */ -#define TS_DO 7 /* do -''- */ -#define TS_DONT 8 /* dont -''- */ - -void -telrcv(void) -{ - int c; - static int state = TS_DATA; - - while (ncc > 0) { - if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) - break; - c = *netip++ & 0377, ncc--; -#ifdef ENCRYPTION - if (decrypt_input) - c = (*decrypt_input)(c); -#endif - switch (state) { - - case TS_CR: - state = TS_DATA; - /* Strip off \n or \0 after a \r */ - if ((c == 0) || (c == '\n')) { - break; - } - /* FALL THROUGH */ - - case TS_DATA: - if (c == IAC) { - state = TS_IAC; - break; - } - /* - * We now map \r\n ==> \r for pragmatic reasons. - * Many client implementations send \r\n when - * the user hits the CarriageReturn key. - * - * We USED to map \r\n ==> \n, since \r\n says - * that we want to be in column 1 of the next - * printable line, and \n is the standard - * unix way of saying that (\r is only good - * if CRMOD is set, which it normally is). - */ - if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { -#ifdef ENCRYPTION - int nc = *netip; - - if (decrypt_input) - nc = (*decrypt_input)(nc & 0xff); -#endif - { -#ifdef ENCRYPTION - if (decrypt_input) - (void)(*decrypt_input)(-1); -#endif - state = TS_CR; - } - } - *pfrontp++ = c; - break; - - case TS_IAC: - gotiac: switch (c) { - - /* - * Send the process on the pty side an - * interrupt. Do this with a NULL or - * interrupt char; depending on the tty mode. - */ - case IP: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - interrupt(); - break; - - case BREAK: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - sendbrk(); - break; - - /* - * Are You There? - */ - case AYT: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - recv_ayt(); - break; - - /* - * Abort Output - */ - case AO: - { - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - ptyflush(); /* half-hearted */ - init_termbuf(); - - if (slctab[SLC_AO].sptr && - *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { - *pfrontp++ = - (unsigned char)*slctab[SLC_AO].sptr; - } - - netclear(); /* clear buffer back */ - output_data ("%c%c", IAC, DM); - neturg = nfrontp-1; /* off by one XXX */ - DIAG(TD_OPTIONS, - printoption("td: send IAC", DM)); - break; - } - - /* - * Erase Character and - * Erase Line - */ - case EC: - case EL: - { - cc_t ch; - - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - ptyflush(); /* half-hearted */ - init_termbuf(); - if (c == EC) - ch = *slctab[SLC_EC].sptr; - else - ch = *slctab[SLC_EL].sptr; - if (ch != (cc_t)(_POSIX_VDISABLE)) - *pfrontp++ = (unsigned char)ch; - break; - } - - /* - * Check for urgent data... - */ - case DM: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - SYNCHing = stilloob(net); - settimer(gotDM); - break; - - - /* - * Begin option subnegotiation... - */ - case SB: - state = TS_SB; - SB_CLEAR(); - continue; - - case WILL: - state = TS_WILL; - continue; - - case WONT: - state = TS_WONT; - continue; - - case DO: - state = TS_DO; - continue; - - case DONT: - state = TS_DONT; - continue; - case EOR: - if (his_state_is_will(TELOPT_EOR)) - doeof(); - break; - - /* - * Handle RFC 10xx Telnet linemode option additions - * to command stream (EOF, SUSP, ABORT). - */ - case xEOF: - doeof(); - break; - - case SUSP: - sendsusp(); - break; - - case ABORT: - sendbrk(); - break; - - case IAC: - *pfrontp++ = c; - break; - } - state = TS_DATA; - break; - - case TS_SB: - if (c == IAC) { - state = TS_SE; - } else { - SB_ACCUM(c); - } - break; - - case TS_SE: - if (c != SE) { - if (c != IAC) { - /* - * bad form of suboption negotiation. - * handle it in such a way as to avoid - * damage to local state. Parse - * suboption buffer found so far, - * then treat remaining stream as - * another command sequence. - */ - - /* for DIAGNOSTICS */ - SB_ACCUM(IAC); - SB_ACCUM(c); - subpointer -= 2; - - SB_TERM(); - suboption(); - state = TS_IAC; - goto gotiac; - } - SB_ACCUM(c); - state = TS_SB; - } else { - /* for DIAGNOSTICS */ - SB_ACCUM(IAC); - SB_ACCUM(SE); - subpointer -= 2; - - SB_TERM(); - suboption(); /* handle sub-option */ - state = TS_DATA; - } - break; - - case TS_WILL: - willoption(c); - state = TS_DATA; - continue; - - case TS_WONT: - wontoption(c); - if (c==TELOPT_ENCRYPT && his_do_dont_is_changing(TELOPT_ENCRYPT) ) - dontoption(c); - state = TS_DATA; - continue; - - case TS_DO: - dooption(c); - state = TS_DATA; - continue; - - case TS_DONT: - dontoption(c); - state = TS_DATA; - continue; - - default: - syslog(LOG_ERR, "telnetd: panic state=%d", state); - printf("telnetd: panic state=%d\n", state); - exit(1); - } - } -} /* end of telrcv */ - -/* - * The will/wont/do/dont state machines are based on Dave Borman's - * Telnet option processing state machine. - * - * These correspond to the following states: - * my_state = the last negotiated state - * want_state = what I want the state to go to - * want_resp = how many requests I have sent - * All state defaults are negative, and resp defaults to 0. - * - * When initiating a request to change state to new_state: - * - * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) { - * do nothing; - * } else { - * want_state = new_state; - * send new_state; - * want_resp++; - * } - * - * When receiving new_state: - * - * if (want_resp) { - * want_resp--; - * if (want_resp && (new_state == my_state)) - * want_resp--; - * } - * if ((want_resp == 0) && (new_state != want_state)) { - * if (ok_to_switch_to new_state) - * want_state = new_state; - * else - * want_resp++; - * send want_state; - * } - * my_state = new_state; - * - * Note that new_state is implied in these functions by the function itself. - * will and do imply positive new_state, wont and dont imply negative. - * - * Finally, there is one catch. If we send a negative response to a - * positive request, my_state will be the positive while want_state will - * remain negative. my_state will revert to negative when the negative - * acknowlegment arrives from the peer. Thus, my_state generally tells - * us not only the last negotiated state, but also tells us what the peer - * wants to be doing as well. It is important to understand this difference - * as we may wish to be processing data streams based on our desired state - * (want_state) or based on what the peer thinks the state is (my_state). - * - * This all works fine because if the peer sends a positive request, the data - * that we receive prior to negative acknowlegment will probably be affected - * by the positive state, and we can process it as such (if we can; if we - * can't then it really doesn't matter). If it is that important, then the - * peer probably should be buffering until this option state negotiation - * is complete. - * - */ -void -send_do(int option, int init) -{ - if (init) { - if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || - his_want_state_is_will(option)) - return; - /* - * Special case for TELOPT_TM: We send a DO, but pretend - * that we sent a DONT, so that we can send more DOs if - * we want to. - */ - if (option == TELOPT_TM) - set_his_want_state_wont(option); - else - set_his_want_state_will(option); - do_dont_resp[option]++; - } - output_data((const char *)doopt, option); - - DIAG(TD_OPTIONS, printoption("td: send do", option)); -} - -#ifdef AUTHENTICATION -extern void auth_request(void); -#endif -#ifdef ENCRYPTION -extern void encrypt_send_support(void); -#endif - -void -willoption(int option) -{ - int changeok = 0; - void (*func)(void) = 0; - - /* - * process input from peer. - */ - - DIAG(TD_OPTIONS, printoption("td: recv will", option)); - - if (do_dont_resp[option]) { - do_dont_resp[option]--; - if (do_dont_resp[option] && his_state_is_will(option)) - do_dont_resp[option]--; - } - if (do_dont_resp[option] == 0) { - if (his_want_state_is_wont(option)) { - switch (option) { - - case TELOPT_BINARY: - init_termbuf(); - tty_binaryin(1); - set_termbuf(); - changeok++; - break; - - case TELOPT_ECHO: - /* - * See comments below for more info. - */ - not42 = 0; /* looks like a 4.2 system */ - break; - - case TELOPT_TM: - /* - * We never respond to a WILL TM, and - * we leave the state WONT. - */ - return; - - case TELOPT_LFLOW: - /* - * If we are going to support flow control - * option, then don't worry peer that we can't - * change the flow control characters. - */ - slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XON].defset.flag |= SLC_DEFAULT; - slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; - case TELOPT_TTYPE: - case TELOPT_SGA: - case TELOPT_NAWS: - case TELOPT_TSPEED: - case TELOPT_XDISPLOC: - case TELOPT_NEW_ENVIRON: - case TELOPT_OLD_ENVIRON: - changeok++; - break; - - -#ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - func = auth_request; - changeok++; - break; -#endif - -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - func = encrypt_send_support; - changeok++; - break; -#endif - - default: - break; - } - if (changeok) { - set_his_want_state_will(option); - send_do(option, 0); - } else { - do_dont_resp[option]++; - send_dont(option, 0); - } - } else { - /* - * Option processing that should happen when - * we receive conformation of a change in - * state that we had requested. - */ - switch (option) { - case TELOPT_ECHO: - not42 = 0; /* looks like a 4.2 system */ - /* - * Egads, he responded "WILL ECHO". Turn - * it off right now! - */ - send_dont(option, 1); - /* - * "WILL ECHO". Kludge upon kludge! - * A 4.2 client is now echoing user input at - * the tty. This is probably undesireable and - * it should be stopped. The client will - * respond WONT TM to the DO TM that we send to - * check for kludge linemode. When the WONT TM - * arrives, linemode will be turned off and a - * change propogated to the pty. This change - * will cause us to process the new pty state - * in localstat(), which will notice that - * linemode is off and send a WILL ECHO - * so that we are properly in character mode and - * all is well. - */ - break; - -#ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - func = auth_request; - break; -#endif - -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - func = encrypt_send_support; - break; -#endif - - case TELOPT_LFLOW: - func = flowstat; - break; - } - } - } - set_his_state_will(option); - if (func) - (*func)(); -} /* end of willoption */ - -void -send_dont(int option, int init) -{ - if (init) { - if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || - his_want_state_is_wont(option)) - return; - set_his_want_state_wont(option); - do_dont_resp[option]++; - } - output_data((const char *)dont, option); - - DIAG(TD_OPTIONS, printoption("td: send dont", option)); -} - -void -wontoption(int option) -{ - /* - * Process client input. - */ - - DIAG(TD_OPTIONS, printoption("td: recv wont", option)); - - if (do_dont_resp[option]) { - do_dont_resp[option]--; - if (do_dont_resp[option] && his_state_is_wont(option)) - do_dont_resp[option]--; - } - if (do_dont_resp[option] == 0) { - if (his_want_state_is_will(option)) { - /* it is always ok to change to negative state */ - switch (option) { - case TELOPT_ECHO: - not42 = 1; /* doesn't seem to be a 4.2 system */ - break; - - case TELOPT_BINARY: - init_termbuf(); - tty_binaryin(0); - set_termbuf(); - break; - - case TELOPT_TM: - /* - * If we get a WONT TM, and had sent a DO TM, - * don't respond with a DONT TM, just leave it - * as is. Short circut the state machine to - * achive this. - */ - set_his_want_state_wont(TELOPT_TM); - return; - - case TELOPT_LFLOW: - /* - * If we are not going to support flow control - * option, then let peer know that we can't - * change the flow control characters. - */ - slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; - slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; - break; - -#ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - auth_finished(0, AUTH_REJECT); - break; -#endif - - /* - * For options that we might spin waiting for - * sub-negotiation, if the client turns off the - * option rather than responding to the request, - * we have to treat it here as if we got a response - * to the sub-negotiation, (by updating the timers) - * so that we'll break out of the loop. - */ - case TELOPT_TTYPE: - settimer(ttypesubopt); - break; - - case TELOPT_TSPEED: - settimer(tspeedsubopt); - break; - - case TELOPT_XDISPLOC: - settimer(xdisplocsubopt); - break; - - case TELOPT_OLD_ENVIRON: - settimer(oenvironsubopt); - break; - - case TELOPT_NEW_ENVIRON: - settimer(environsubopt); - break; - - default: - break; - } - set_his_want_state_wont(option); - if (his_state_is_will(option)) - send_dont(option, 0); - } else { - switch (option) { - case TELOPT_TM: - break; - -#ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - auth_finished(0, AUTH_REJECT); - break; -#endif - default: - break; - } - } - } - set_his_state_wont(option); - -} /* end of wontoption */ - -void -send_will(int option, int init) -{ - if (init) { - if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| - my_want_state_is_will(option)) - return; - set_my_want_state_will(option); - will_wont_resp[option]++; - } - output_data ((const char *)will, option); - - DIAG(TD_OPTIONS, printoption("td: send will", option)); -} - -/* - * When we get a DONT SGA, we will try once to turn it - * back on. If the other side responds DONT SGA, we - * leave it at that. This is so that when we talk to - * clients that understand KLUDGELINEMODE but not LINEMODE, - * we'll keep them in char-at-a-time mode. - */ -int turn_on_sga = 0; - -void -dooption(int option) -{ - int changeok = 0; - - /* - * Process client input. - */ - - DIAG(TD_OPTIONS, printoption("td: recv do", option)); - - if (will_wont_resp[option]) { - will_wont_resp[option]--; - if (will_wont_resp[option] && my_state_is_will(option)) - will_wont_resp[option]--; - } - if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { - switch (option) { - case TELOPT_ECHO: - { - init_termbuf(); - tty_setecho(1); - set_termbuf(); - } - changeok++; - break; - - case TELOPT_BINARY: - init_termbuf(); - tty_binaryout(1); - set_termbuf(); - changeok++; - break; - - case TELOPT_SGA: - turn_on_sga = 0; - changeok++; - break; - - case TELOPT_STATUS: - changeok++; - break; - - case TELOPT_TM: - /* - * Special case for TM. We send a WILL, but - * pretend we sent a WONT. - */ - send_will(option, 0); - set_my_want_state_wont(option); - set_my_state_wont(option); - return; - - case TELOPT_LOGOUT: - /* - * When we get a LOGOUT option, respond - * with a WILL LOGOUT, make sure that - * it gets written out to the network, - * and then just go away... - */ - set_my_want_state_will(TELOPT_LOGOUT); - send_will(TELOPT_LOGOUT, 0); - set_my_state_will(TELOPT_LOGOUT); - netflush(); - cleanup(0); - /* NOT REACHED */ - break; - -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - changeok++; - break; -#endif - case TELOPT_LINEMODE: - case TELOPT_TTYPE: - case TELOPT_NAWS: - case TELOPT_TSPEED: - case TELOPT_LFLOW: - case TELOPT_XDISPLOC: -#ifdef TELOPT_ENVIRON - case TELOPT_NEW_ENVIRON: -#endif - case TELOPT_OLD_ENVIRON: - default: - break; - } - if (changeok) { - set_my_want_state_will(option); - send_will(option, 0); - } else { - will_wont_resp[option]++; - send_wont(option, 0); - } - } - set_my_state_will(option); - -} /* end of dooption */ - -void -send_wont(int option, int init) -{ - if (init) { - if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || - my_want_state_is_wont(option)) - return; - set_my_want_state_wont(option); - will_wont_resp[option]++; - } - output_data ((const char *)wont, option); - - DIAG(TD_OPTIONS, printoption("td: send wont", option)); -} - -void -dontoption(int option) -{ - /* - * Process client input. - */ - - - DIAG(TD_OPTIONS, printoption("td: recv dont", option)); - - if (will_wont_resp[option]) { - will_wont_resp[option]--; - if (will_wont_resp[option] && my_state_is_wont(option)) - will_wont_resp[option]--; - } - if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { - switch (option) { - case TELOPT_BINARY: - init_termbuf(); - tty_binaryout(0); - set_termbuf(); - break; - - case TELOPT_ECHO: /* we should stop echoing */ - { - init_termbuf(); - tty_setecho(0); - set_termbuf(); - } - break; - - case TELOPT_SGA: - set_my_want_state_wont(option); - if (my_state_is_will(option)) - send_wont(option, 0); - set_my_state_wont(option); - if (turn_on_sga ^= 1) - send_will(option, 1); - return; - - default: - break; - } - - set_my_want_state_wont(option); - if (my_state_is_will(option)) - send_wont(option, 0); - } - set_my_state_wont(option); - -} /* end of dontoption */ - -#ifdef ENV_HACK -int env_ovar = -1; -int env_ovalue = -1; -#else /* ENV_HACK */ -# define env_ovar OLD_ENV_VAR -# define env_ovalue OLD_ENV_VALUE -#endif /* ENV_HACK */ - -/* - * variables not to let through. - * if name ends in =, it is complete variable name - * if it does not end in =, all variables starting with this name - * should be dropped. - */ -char *badenv_table[] = { - "IFS=", - "LD_", - "_RLD_", - "SHLIB_PATH=", - "LIBPATH=", - "KRB", - "ENV=", - "BASH_ENV=", - NULL, -}; - -static int envvarok(char *); - -/* envvarok(char*) */ -/* check that variable is safe to pass to login or shell */ -static int -envvarok(varp) - char *varp; -{ - int i; - int len; - - if (strchr(varp, '=')) - return (0); - for (i = 0; badenv_table[i]; i++) { - len = strlen(badenv_table[i]); - if (badenv_table[i][len-1] == '=' && - !strncmp(badenv_table[i], varp, len-1) && - varp[len-2] == '\0') - return (0); - if (!strncmp(badenv_table[i], varp, len-1)) - return (0); - } - return (1); -} - -/* - * suboption() - * - * Look at the sub-option buffer, and try to be helpful to the other - * side. - * - * Currently we recognize: - * - * Terminal type is - * Linemode - * Window size - * Terminal speed - */ -void -suboption(void) -{ - int subchar; - - DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); - - subchar = SB_GET(); - switch (subchar) { - case TELOPT_TSPEED: { - int xspeed, rspeed; - - if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ - break; - - settimer(tspeedsubopt); - - if (SB_EOF() || SB_GET() != TELQUAL_IS) - return; - - xspeed = atoi((char *)subpointer); - - while (SB_GET() != ',' && !SB_EOF()); - if (SB_EOF()) - return; - - rspeed = atoi((char *)subpointer); - clientstat(TELOPT_TSPEED, xspeed, rspeed); - - break; - - } /* end of case TELOPT_TSPEED */ - - case TELOPT_TTYPE: { /* Yaaaay! */ - char *tt; - - if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ - break; - settimer(ttypesubopt); - - if (SB_EOF() || SB_GET() != TELQUAL_IS) { - return; /* ??? XXX but, this is the most robust */ - } - - tt = terminaltype; - - while ((tt < (terminaltype + sizeof terminaltype-1)) && - !SB_EOF()) { - int c; - - c = SB_GET(); - if (isupper(c)) { - c = tolower(c); - } - *tt++ = c; /* accumulate name */ - } - *tt = 0; - break; - } /* end of case TELOPT_TTYPE */ - - case TELOPT_NAWS: { - int xwinsize, ywinsize; - - if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ - break; - - if (SB_EOF()) - return; - xwinsize = SB_GET() << 8; - if (SB_EOF()) - return; - xwinsize |= SB_GET(); - if (SB_EOF()) - return; - ywinsize = SB_GET() << 8; - if (SB_EOF()) - return; - ywinsize |= SB_GET(); - clientstat(TELOPT_NAWS, xwinsize, ywinsize); - - break; - - } /* end of case TELOPT_NAWS */ - - case TELOPT_STATUS: { - int mode; - - if (SB_EOF()) - break; - mode = SB_GET(); - switch (mode) { - case TELQUAL_SEND: - if (my_state_is_will(TELOPT_STATUS)) - send_status(); - break; - - case TELQUAL_IS: - break; - - default: - break; - } - break; - } /* end of case TELOPT_STATUS */ - - case TELOPT_XDISPLOC: { - if (SB_EOF() || SB_GET() != TELQUAL_IS) - return; - settimer(xdisplocsubopt); - subpointer[SB_LEN()] = '\0'; - esetenv("DISPLAY", (char *)subpointer, 1); - break; - } /* end of case TELOPT_XDISPLOC */ - -#ifdef TELOPT_NEW_ENVIRON - case TELOPT_NEW_ENVIRON: -#endif - case TELOPT_OLD_ENVIRON: { - int c; - char *cp, *varp, *valp; - - if (SB_EOF()) - return; - c = SB_GET(); - if (c == TELQUAL_IS) { - if (subchar == TELOPT_OLD_ENVIRON) - settimer(oenvironsubopt); - else - settimer(environsubopt); - } else if (c != TELQUAL_INFO) { - return; - } - -#ifdef TELOPT_NEW_ENVIRON - if (subchar == TELOPT_NEW_ENVIRON) { - while (!SB_EOF()) { - c = SB_GET(); - if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) - break; - } - } else -#endif - { -#ifdef ENV_HACK - /* - * We only want to do this if we haven't already decided - * whether or not the other side has its VALUE and VAR - * reversed. - */ - if (env_ovar < 0) { - int last = -1; /* invalid value */ - int empty = 0; - int got_var = 0, got_value = 0, got_uservar = 0; - - /* - * The other side might have its VALUE and VAR values - * reversed. To be interoperable, we need to determine - * which way it is. If the first recognized character - * is a VAR or VALUE, then that will tell us what - * type of client it is. If the fist recognized - * character is a USERVAR, then we continue scanning - * the suboption looking for two consecutive - * VAR or VALUE fields. We should not get two - * consecutive VALUE fields, so finding two - * consecutive VALUE or VAR fields will tell us - * what the client is. - */ - SB_SAVE(); - while (!SB_EOF()) { - c = SB_GET(); - switch(c) { - case OLD_ENV_VAR: - if (last < 0 || last == OLD_ENV_VAR - || (empty && (last == OLD_ENV_VALUE))) - goto env_ovar_ok; - got_var++; - last = OLD_ENV_VAR; - break; - case OLD_ENV_VALUE: - if (last < 0 || last == OLD_ENV_VALUE - || (empty && (last == OLD_ENV_VAR))) - goto env_ovar_wrong; - got_value++; - last = OLD_ENV_VALUE; - break; - case ENV_USERVAR: - /* count strings of USERVAR as one */ - if (last != ENV_USERVAR) - got_uservar++; - if (empty) { - if (last == OLD_ENV_VALUE) - goto env_ovar_ok; - if (last == OLD_ENV_VAR) - goto env_ovar_wrong; - } - last = ENV_USERVAR; - break; - case ENV_ESC: - if (!SB_EOF()) - c = SB_GET(); - /* FALL THROUGH */ - default: - empty = 0; - continue; - } - empty = 1; - } - if (empty) { - if (last == OLD_ENV_VALUE) - goto env_ovar_ok; - if (last == OLD_ENV_VAR) - goto env_ovar_wrong; - } - /* - * Ok, the first thing was a USERVAR, and there - * are not two consecutive VAR or VALUE commands, - * and none of the VAR or VALUE commands are empty. - * If the client has sent us a well-formed option, - * then the number of VALUEs received should always - * be less than or equal to the number of VARs and - * USERVARs received. - * - * If we got exactly as many VALUEs as VARs and - * USERVARs, the client has the same definitions. - * - * If we got exactly as many VARs as VALUEs and - * USERVARS, the client has reversed definitions. - */ - if (got_uservar + got_var == got_value) { - env_ovar_ok: - env_ovar = OLD_ENV_VAR; - env_ovalue = OLD_ENV_VALUE; - } else if (got_uservar + got_value == got_var) { - env_ovar_wrong: - env_ovar = OLD_ENV_VALUE; - env_ovalue = OLD_ENV_VAR; - DIAG(TD_OPTIONS, { - output_data("ENVIRON VALUE and VAR are reversed!\r\n"); - }); - - } - } - SB_RESTORE(); -#endif - - while (!SB_EOF()) { - c = SB_GET(); - if ((c == env_ovar) || (c == ENV_USERVAR)) - break; - } - } - - if (SB_EOF()) - return; - - cp = varp = (char *)subpointer; - valp = 0; - - while (!SB_EOF()) { - c = SB_GET(); - if (subchar == TELOPT_OLD_ENVIRON) { - if (c == env_ovar) - c = NEW_ENV_VAR; - else if (c == env_ovalue) - c = NEW_ENV_VALUE; - } - switch (c) { - - case NEW_ENV_VALUE: - *cp = '\0'; - cp = valp = (char *)subpointer; - break; - - case NEW_ENV_VAR: - case ENV_USERVAR: - *cp = '\0'; - if(envvarok(varp)) { - if (valp) - esetenv(varp, valp, 1); - else - unsetenv(varp); - } - cp = varp = (char *)subpointer; - valp = 0; - break; - - case ENV_ESC: - if (SB_EOF()) - break; - c = SB_GET(); - /* FALL THROUGH */ - default: - *cp++ = c; - break; - } - } - *cp = '\0'; - if(envvarok(varp)) { - if (valp) - esetenv(varp, valp, 1); - else - unsetenv(varp); - } - break; - } /* end of case TELOPT_NEW_ENVIRON */ -#ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - if (SB_EOF()) - break; - switch(SB_GET()) { - case TELQUAL_SEND: - case TELQUAL_REPLY: - /* - * These are sent by us and cannot be sent by - * the client. - */ - break; - case TELQUAL_IS: - auth_is(subpointer, SB_LEN()); - break; - case TELQUAL_NAME: - auth_name(subpointer, SB_LEN()); - break; - } - break; -#endif -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - if (SB_EOF()) - break; - switch(SB_GET()) { - case ENCRYPT_SUPPORT: - encrypt_support(subpointer, SB_LEN()); - break; - case ENCRYPT_IS: - encrypt_is(subpointer, SB_LEN()); - break; - case ENCRYPT_REPLY: - encrypt_reply(subpointer, SB_LEN()); - break; - case ENCRYPT_START: - encrypt_start(subpointer, SB_LEN()); - break; - case ENCRYPT_END: - encrypt_end(); - break; - case ENCRYPT_REQSTART: - encrypt_request_start(subpointer, SB_LEN()); - break; - case ENCRYPT_REQEND: - /* - * We can always send an REQEND so that we cannot - * get stuck encrypting. We should only get this - * if we have been able to get in the correct mode - * anyhow. - */ - encrypt_request_end(); - break; - case ENCRYPT_ENC_KEYID: - encrypt_enc_keyid(subpointer, SB_LEN()); - break; - case ENCRYPT_DEC_KEYID: - encrypt_dec_keyid(subpointer, SB_LEN()); - break; - default: - break; - } - break; -#endif - - default: - break; - } /* end of switch */ - -} /* end of suboption */ - -void -doclientstat(void) -{ - clientstat(TELOPT_LINEMODE, WILL, 0); -} - -#define ADD(c) *ncp++ = c -#define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; } - -void -send_status(void) -{ - unsigned char statusbuf[256]; - unsigned char *ncp; - unsigned char i; - - ncp = statusbuf; - - netflush(); /* get rid of anything waiting to go out */ - - ADD(IAC); - ADD(SB); - ADD(TELOPT_STATUS); - ADD(TELQUAL_IS); - - /* - * We check the want_state rather than the current state, - * because if we received a DO/WILL for an option that we - * don't support, and the other side didn't send a DONT/WONT - * in response to our WONT/DONT, then the "state" will be - * WILL/DO, and the "want_state" will be WONT/DONT. We - * need to go by the latter. - */ - for (i = 0; i < (unsigned char)NTELOPTS; i++) { - if (my_want_state_is_will(i)) { - ADD(WILL); - ADD_DATA(i); - } - if (his_want_state_is_will(i)) { - ADD(DO); - ADD_DATA(i); - } - } - - if (his_want_state_is_will(TELOPT_LFLOW)) { - ADD(SB); - ADD(TELOPT_LFLOW); - if (flowmode) { - ADD(LFLOW_ON); - } else { - ADD(LFLOW_OFF); - } - ADD(SE); - - if (restartany >= 0) { - ADD(SB); - ADD(TELOPT_LFLOW); - if (restartany) { - ADD(LFLOW_RESTART_ANY); - } else { - ADD(LFLOW_RESTART_XON); - } - ADD(SE); - } - } - - - ADD(IAC); - ADD(SE); - - writenet(statusbuf, ncp - statusbuf); - netflush(); /* Send it on its way */ - - DIAG(TD_OPTIONS, - {printsub('>', statusbuf, ncp - statusbuf); netflush();}); -} diff --git a/libexec/telnetd/sys_term.c b/libexec/telnetd/sys_term.c deleted file mode 100644 index bf5030fd87d..00000000000 --- a/libexec/telnetd/sys_term.c +++ /dev/null @@ -1,1911 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "telnetd.h" - -/* RCSID("$KTH: sys_term.c,v 1.100 2001/04/24 23:11:43 assar Exp $"); */ - -#if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H)) -# define PARENT_DOES_UTMP -#endif - -#ifdef HAVE_UTMP_H -#include <utmp.h> -#endif - -#ifdef HAVE_UTMPX_H -#include <utmpx.h> -#endif - -#ifdef HAVE_UTMPX_H -struct utmpx wtmp; -#elif defined(HAVE_UTMP_H) -struct utmp wtmp; -#endif /* HAVE_UTMPX_H */ - -#ifdef HAVE_STRUCT_UTMP_UT_HOST -int utmp_len = sizeof(wtmp.ut_host); -#else -int utmp_len = MAXHOSTNAMELEN; -#endif - -#ifndef UTMP_FILE -#ifdef _PATH_UTMP -#define UTMP_FILE _PATH_UTMP -#else -#define UTMP_FILE "/etc/utmp" -#endif -#endif - -#if !defined(WTMP_FILE) && defined(_PATH_WTMP) -#define WTMP_FILE _PATH_WTMP -#endif - -#ifndef PARENT_DOES_UTMP -#ifdef WTMP_FILE -char wtmpf[] = WTMP_FILE; -#else -char wtmpf[] = "/usr/adm/wtmp"; -#endif -char utmpf[] = UTMP_FILE; -#else /* PARENT_DOES_UTMP */ -#ifdef WTMP_FILE -char wtmpf[] = WTMP_FILE; -#else -char wtmpf[] = "/etc/wtmp"; -#endif -#endif /* PARENT_DOES_UTMP */ - -#ifdef HAVE_TMPDIR_H -#include <tmpdir.h> -#endif /* CRAY */ - -#ifdef STREAMSPTY - -#ifdef HAVE_SAC_H -#include <sac.h> -#endif - -#ifdef HAVE_SYS_STROPTS_H -#include <sys/stropts.h> -#endif - -#endif /* STREAMSPTY */ - -#ifdef HAVE_SYS_STREAM_H -#ifdef HAVE_SYS_UIO_H -#include <sys/uio.h> -#endif -#ifdef __hpux -#undef SE -#endif -#include <sys/stream.h> -#endif -#if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY) -#include <sys/tty.h> -#endif -#ifdef t_erase -#undef t_erase -#undef t_kill -#undef t_intrc -#undef t_quitc -#undef t_startc -#undef t_stopc -#undef t_eofc -#undef t_brkc -#undef t_suspc -#undef t_dsuspc -#undef t_rprntc -#undef t_flushc -#undef t_werasc -#undef t_lnextc -#endif - -#ifdef HAVE_TERMIOS_H -#include <termios.h> -#else -#ifdef HAVE_TERMIO_H -#include <termio.h> -#endif -#endif - -#ifdef HAVE_UTIL_H -#include <util.h> -#endif - -# ifndef TCSANOW -# ifdef TCSETS -# define TCSANOW TCSETS -# define TCSADRAIN TCSETSW -# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) -# else -# ifdef TCSETA -# define TCSANOW TCSETA -# define TCSADRAIN TCSETAW -# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) -# else -# define TCSANOW TIOCSETA -# define TCSADRAIN TIOCSETAW -# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) -# endif -# endif -# define tcsetattr(f, a, t) ioctl(f, a, t) -# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ -(tp)->c_cflag |= (val) -# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) -# ifdef CIBAUD -# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ - (tp)->c_cflag |= ((val)<<IBSHIFT) -# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) -# else -# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ - (tp)->c_cflag |= (val) -# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) -# endif -# endif /* TCSANOW */ - struct termios termbuf, termbuf2; /* pty control structure */ -# ifdef STREAMSPTY - static int ttyfd = -1; - int really_stream = 0; -# endif - - char *new_login = NULL; - -/* - * init_termbuf() - * copy_termbuf(cp) - * set_termbuf() - * - * These three routines are used to get and set the "termbuf" structure - * to and from the kernel. init_termbuf() gets the current settings. - * copy_termbuf() hands in a new "termbuf" to write to the kernel, and - * set_termbuf() writes the structure into the kernel. - */ - - void - init_termbuf(void) -{ -# ifdef STREAMSPTY - if (really_stream) - tcgetattr(ttyfd, &termbuf); - else -# endif - tcgetattr(ourpty, &termbuf); - termbuf2 = termbuf; -} - -void -set_termbuf(void) -{ - /* - * Only make the necessary changes. - */ - if (memcmp(&termbuf, &termbuf2, sizeof(termbuf))) -# ifdef STREAMSPTY - if (really_stream) - tcsetattr(ttyfd, TCSANOW, &termbuf); - else -# endif - tcsetattr(ourpty, TCSANOW, &termbuf); -} - - -/* - * spcset(func, valp, valpp) - * - * This function takes various special characters (func), and - * sets *valp to the current value of that character, and - * *valpp to point to where in the "termbuf" structure that - * value is kept. - * - * It returns the SLC_ level of support for this function. - */ - - -int -spcset(int func, cc_t *valp, cc_t **valpp) -{ - -#define setval(a, b) *valp = termbuf.c_cc[a]; \ - *valpp = &termbuf.c_cc[a]; \ - return(b); -#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); - - switch(func) { - case SLC_EOF: - setval(VEOF, SLC_VARIABLE); - case SLC_EC: - setval(VERASE, SLC_VARIABLE); - case SLC_EL: - setval(VKILL, SLC_VARIABLE); - case SLC_IP: - setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_ABORT: - setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_XON: -#ifdef VSTART - setval(VSTART, SLC_VARIABLE); -#else - defval(0x13); -#endif - case SLC_XOFF: -#ifdef VSTOP - setval(VSTOP, SLC_VARIABLE); -#else - defval(0x11); -#endif - case SLC_EW: -#ifdef VWERASE - setval(VWERASE, SLC_VARIABLE); -#else - defval(0); -#endif - case SLC_RP: -#ifdef VREPRINT - setval(VREPRINT, SLC_VARIABLE); -#else - defval(0); -#endif - case SLC_LNEXT: -#ifdef VLNEXT - setval(VLNEXT, SLC_VARIABLE); -#else - defval(0); -#endif - case SLC_AO: -#if !defined(VDISCARD) && defined(VFLUSHO) -# define VDISCARD VFLUSHO -#endif -#ifdef VDISCARD - setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); -#else - defval(0); -#endif - case SLC_SUSP: -#ifdef VSUSP - setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); -#else - defval(0); -#endif -#ifdef VEOL - case SLC_FORW1: - setval(VEOL, SLC_VARIABLE); -#endif -#ifdef VEOL2 - case SLC_FORW2: - setval(VEOL2, SLC_VARIABLE); -#endif - case SLC_AYT: -#ifdef VSTATUS - setval(VSTATUS, SLC_VARIABLE); -#else - defval(0); -#endif - - case SLC_BRK: - case SLC_SYNCH: - case SLC_EOR: - defval(0); - - default: - *valp = 0; - *valpp = 0; - return(SLC_NOSUPPORT); - } -} - -#ifdef _CRAY -/* - * getnpty() - * - * Return the number of pty's configured into the system. - */ -int -getnpty() -{ -#ifdef _SC_CRAY_NPTY - int numptys; - - if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) - return numptys; - else -#endif /* _SC_CRAY_NPTY */ - return 128; -} -#endif /* CRAY */ - -/* - * getpty() - * - * Allocate a pty. As a side effect, the external character - * array "line" contains the name of the slave side. - * - * Returns the file descriptor of the opened pty. - */ - -static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -char *line = Xline; - -int slavefd = -1; - -#ifdef _CRAY -char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -#endif /* CRAY */ - -#if !defined(HAVE_PTSNAME) && defined(STREAMSPTY) -static char *ptsname(int fd) -{ -#ifdef HAVE_TTYNAME - return ttyname(fd); -#else - return NULL; -#endif -} -#endif - -int getpty(int *ptynum) -{ -#if defined(__osf__) || defined(HAVE_OPENPTY) - int master; - int slave; - if(openpty(&master, &slave, line, 0, 0) == 0){ - slavefd = slave; - return master; - } - return -1; -#else -#ifdef HAVE__GETPTY - int master, slave; - char *p; - p = _getpty(&master, O_RDWR, 0600, 1); - if(p == NULL) - return -1; - strlcpy(line, p, sizeof(Xline)); - return master; -#else - - int p; - char *cp, *p1, *p2; - int i; -#if SunOS == 40 - int dummy; -#endif -#if 0 /* && defined(HAVE_OPENPTY) */ - int master; - int slave; - if(openpty(&master, &slave, line, 0, 0) == 0){ - close(slave); - return master; - } -#else -#ifdef STREAMSPTY - char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", - "/dev/ptym/clone", 0 }; - - char **q; - for(q=clone; *q; q++){ - p=open(*q, O_RDWR); - if(p >= 0){ -#ifdef HAVE_GRANTPT - grantpt(p); -#endif -#ifdef HAVE_UNLOCKPT - unlockpt(p); -#endif - strlcpy(line, ptsname(p), sizeof(Xline)); - really_stream = 1; - return p; - } - } -#endif /* STREAMSPTY */ -#ifndef _CRAY - -#ifndef __hpux - snprintf(line, sizeof(Xline), "/dev/ptyXX"); - p1 = &line[8]; - p2 = &line[9]; -#else - snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX"); - p1 = &line[13]; - p2 = &line[14]; -#endif - - - for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { - struct stat stb; - - *p1 = *cp; - *p2 = '0'; - /* - * This stat() check is just to keep us from - * looping through all 256 combinations if there - * aren't that many ptys available. - */ - if (stat(line, &stb) < 0) - break; - for (i = 0; i < 16; i++) { - *p2 = "0123456789abcdef"[i]; - p = open(line, O_RDWR); - if (p > 0) { -#ifndef __hpux - line[5] = 't'; -#else - for (p1 = &line[8]; *p1; p1++) - *p1 = *(p1+1); - line[9] = 't'; -#endif - chown(line, 0, 0); - chmod(line, 0600); -#if SunOS == 40 - if (ioctl(p, TIOCGPGRP, &dummy) == 0 - || errno != EIO) { - chmod(line, 0666); - close(p); - line[5] = 'p'; - } else -#endif /* SunOS == 40 */ - return(p); - } - } - } -#else /* CRAY */ - extern lowpty, highpty; - struct stat sb; - - for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { - snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum); - p = open(myline, 2); - if (p < 0) - continue; - snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum); - /* - * Here are some shenanigans to make sure that there - * are no listeners lurking on the line. - */ - if(stat(line, &sb) < 0) { - close(p); - continue; - } - if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { - chown(line, 0, 0); - chmod(line, 0600); - close(p); - p = open(myline, 2); - if (p < 0) - continue; - } - /* - * Now it should be safe...check for accessability. - */ - if (access(line, 6) == 0) - return(p); - else { - /* no tty side to pty so skip it */ - close(p); - } - } -#endif /* CRAY */ -#endif /* STREAMSPTY */ -#endif /* OPENPTY */ - return(-1); -#endif -} - - -int -tty_isecho(void) -{ - return (termbuf.c_lflag & ECHO); -} - -int -tty_flowmode(void) -{ - return((termbuf.c_iflag & IXON) ? 1 : 0); -} - -int -tty_restartany(void) -{ - return((termbuf.c_iflag & IXANY) ? 1 : 0); -} - -void -tty_setecho(int on) -{ - if (on) - termbuf.c_lflag |= ECHO; - else - termbuf.c_lflag &= ~ECHO; -} - -int -tty_israw(void) -{ - return(!(termbuf.c_lflag & ICANON)); -} - -void -tty_binaryin(int on) -{ - if (on) { - termbuf.c_iflag &= ~ISTRIP; - } else { - termbuf.c_iflag |= ISTRIP; - } -} - -void -tty_binaryout(int on) -{ - if (on) { - termbuf.c_cflag &= ~(CSIZE|PARENB); - termbuf.c_cflag |= CS8; - termbuf.c_oflag &= ~OPOST; - } else { - termbuf.c_cflag &= ~CSIZE; - termbuf.c_cflag |= CS7|PARENB; - termbuf.c_oflag |= OPOST; - } -} - -int -tty_isbinaryin(void) -{ - return(!(termbuf.c_iflag & ISTRIP)); -} - -int -tty_isbinaryout(void) -{ - return(!(termbuf.c_oflag&OPOST)); -} - - -int -tty_issofttab(void) -{ -# ifdef OXTABS - return (termbuf.c_oflag & OXTABS); -# endif -# ifdef TABDLY - return ((termbuf.c_oflag & TABDLY) == TAB3); -# endif -} - -void -tty_setsofttab(int on) -{ - if (on) { -# ifdef OXTABS - termbuf.c_oflag |= OXTABS; -# endif -# ifdef TABDLY - termbuf.c_oflag &= ~TABDLY; - termbuf.c_oflag |= TAB3; -# endif - } else { -# ifdef OXTABS - termbuf.c_oflag &= ~OXTABS; -# endif -# ifdef TABDLY - termbuf.c_oflag &= ~TABDLY; - termbuf.c_oflag |= TAB0; -# endif - } -} - -int -tty_islitecho(void) -{ -# ifdef ECHOCTL - return (!(termbuf.c_lflag & ECHOCTL)); -# endif -# ifdef TCTLECH - return (!(termbuf.c_lflag & TCTLECH)); -# endif -# if !defined(ECHOCTL) && !defined(TCTLECH) - return (0); /* assumes ctl chars are echoed '^x' */ -# endif -} - -void -tty_setlitecho(int on) -{ -# ifdef ECHOCTL - if (on) - termbuf.c_lflag &= ~ECHOCTL; - else - termbuf.c_lflag |= ECHOCTL; -# endif -# ifdef TCTLECH - if (on) - termbuf.c_lflag &= ~TCTLECH; - else - termbuf.c_lflag |= TCTLECH; -# endif -} - -int -tty_iscrnl(void) -{ - return (termbuf.c_iflag & ICRNL); -} - -/* - * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). - */ -#if B4800 != 4800 -#define DECODE_BAUD -#endif - -#ifdef DECODE_BAUD - -/* - * A table of available terminal speeds - */ -struct termspeeds { - int speed; - int value; -} termspeeds[] = { - { 0, B0 }, { 50, B50 }, { 75, B75 }, - { 110, B110 }, { 134, B134 }, { 150, B150 }, - { 200, B200 }, { 300, B300 }, { 600, B600 }, - { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, - { 4800, B4800 }, -#ifdef B7200 - { 7200, B7200 }, -#endif - { 9600, B9600 }, -#ifdef B14400 - { 14400, B14400 }, -#endif -#ifdef B19200 - { 19200, B19200 }, -#endif -#ifdef B28800 - { 28800, B28800 }, -#endif -#ifdef B38400 - { 38400, B38400 }, -#endif -#ifdef B57600 - { 57600, B57600 }, -#endif -#ifdef B115200 - { 115200, B115200 }, -#endif -#ifdef B230400 - { 230400, B230400 }, -#endif - { -1, 0 } -}; -#endif /* DECODE_BUAD */ - -void -tty_tspeed(int val) -{ -#ifdef DECODE_BAUD - struct termspeeds *tp; - - for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) - ; - if (tp->speed == -1) /* back up to last valid value */ - --tp; - cfsetospeed(&termbuf, tp->value); -#else /* DECODE_BUAD */ - cfsetospeed(&termbuf, val); -#endif /* DECODE_BUAD */ -} - -void -tty_rspeed(int val) -{ -#ifdef DECODE_BAUD - struct termspeeds *tp; - - for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) - ; - if (tp->speed == -1) /* back up to last valid value */ - --tp; - cfsetispeed(&termbuf, tp->value); -#else /* DECODE_BAUD */ - cfsetispeed(&termbuf, val); -#endif /* DECODE_BAUD */ -} - -#ifdef PARENT_DOES_UTMP -extern struct utmp wtmp; -extern char wtmpf[]; - -extern void utmp_sig_init (void); -extern void utmp_sig_reset (void); -extern void utmp_sig_wait (void); -extern void utmp_sig_notify (int); -# endif /* PARENT_DOES_UTMP */ - -#ifdef STREAMSPTY - -/* I_FIND seems to live a life of its own */ -static int my_find(int fd, char *module) -{ -#if defined(I_FIND) && defined(I_LIST) - static int flag; - static struct str_list sl; - int n; - int i; - - if(!flag){ - n = ioctl(fd, I_LIST, 0); - if(n < 0){ - perror("ioctl(fd, I_LIST, 0)"); - return -1; - } - sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist)); - sl.sl_nmods = n; - n = ioctl(fd, I_LIST, &sl); - if(n < 0){ - perror("ioctl(fd, I_LIST, n)"); - return -1; - } - flag = 1; - } - - for(i=0; i<sl.sl_nmods; i++) - if(!strcmp(sl.sl_modlist[i].l_name, module)) - return 1; -#endif - return 0; -} - -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"); - } -} -#endif - -/* - * 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; - extern int def_row, def_col; - extern int def_tspeed, def_rspeed; - /* - * 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. - */ - - if (slavefd != -1) { - t = slavefd; - goto gottty; - } - - /* - * 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); -gottty: - 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; - } -} - -#ifndef O_NOCTTY -#define O_NOCTTY 0 -#endif -/* - * Open the specified slave side of the pty, - * making sure that we have a clean tty. - */ - -int cleanopen(char *line) -{ - int t; - -#ifdef STREAMSPTY - if (!really_stream) -#endif - { - /* - * Make sure that other people can't open the - * slave side of the connection. - */ - chown(line, 0, 0); - chmod(line, 0600); - } - -#ifdef HAVE_REVOKE - revoke(line); -#endif - - t = open(line, O_RDWR|O_NOCTTY); - - if (t < 0) - return(-1); - - /* - * Hangup anybody else using this ttyp, then reopen it for - * ourselves. - */ -# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) - signal(SIGHUP, SIG_IGN); -#ifdef HAVE_VHANGUP - vhangup(); -#else -#endif - signal(SIGHUP, SIG_DFL); - t = open(line, O_RDWR|O_NOCTTY); - if (t < 0) - return(-1); -# endif -# if defined(_CRAY) && defined(TCVHUP) - { - int i; - signal(SIGHUP, SIG_IGN); - ioctl(t, TCVHUP, (char *)0); - signal(SIGHUP, SIG_DFL); - - i = open(line, O_RDWR); - - if (i < 0) - return(-1); - close(t); - t = i; - } -# endif /* defined(CRAY) && defined(TCVHUP) */ - return(t); -} - -#if !defined(BSD4_4) - -int login_tty(int t) -{ -# if defined(TIOCSCTTY) && !defined(__hpux) - if (ioctl(t, TIOCSCTTY, (char *)0) < 0) - 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); -} -#endif /* BSD <= 43 */ - -/* - * This comes from ../../bsd/tty.c and should not really be here. - */ - -/* - * Clean the tty name. Return a pointer to the cleaned version. - */ - -static char * -clean_ttyname (char *tty) -{ - char *res = tty; - - if (strncmp (res, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) - res += sizeof(_PATH_DEV) - 1; - if (strncmp (res, "pty/", 4) == 0) - res += 4; - if (strncmp (res, "ptym/", 5) == 0) - res += 5; - return res; -} - -/* - * Generate a name usable as an `ut_id', typically without `tty'. - */ - -#ifdef HAVE_STRUCT_UTMP_UT_ID -static char * -make_id (char *tty) -{ - char *res = tty; - - if (strncmp (res, "pts/", 4) == 0) - res += 4; - if (strncmp (res, "tty", 3) == 0) - res += 3; - return res; -} -#endif - -/* - * startslave(host) - * - * Given a hostname, do whatever - * is necessary to startup the login process on the slave side of the pty. - */ - -/* 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 - -# 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*/ - } -} - -char *envinit[3]; -extern char **environ; - -void -init_env(void) -{ - char **envp; - - envp = envinit; - if ((*envp = getenv("TZ"))) - *envp++ -= 3; -#if defined(_CRAY) || defined(__hpux) - else - *envp++ = "TZ=GMT0"; -#endif - *envp = 0; - environ = envinit; -} - -/* We won't agree with the Heimdal people about the right way to check for - * bad environment variables, so we don't use this code. - * See envvarok() in state.c instead. - */ -#if 0 -/* - * scrub_env() - * - * We only accept the environment variables listed below. - */ - -static void -scrub_env(void) -{ - static const char *reject[] = { - "TERMCAP=/", - NULL - }; - - static const char *accept[] = { - "XAUTH=", "XAUTHORITY=", "DISPLAY=", - "TERM=", - "EDITOR=", - "PAGER=", - "PRINTER=", - "LOGNAME=", - "POSIXLY_CORRECT=", - "TERMCAP=", - NULL - }; - - char **cpp, **cpp2; - const char **p; - - for (cpp2 = cpp = environ; *cpp; cpp++) { - int reject_it = 0; - - for(p = reject; *p; p++) - if(strncmp(*cpp, *p, strlen(*p)) == 0) { - reject_it = 1; - break; - } - if (reject_it) - continue; - - for(p = accept; *p; p++) - if(strncmp(*cpp, *p, strlen(*p)) == 0) - break; - if(*p != NULL) - *cpp2++ = *cpp; - } - *cpp2 = NULL; -} -#endif - -struct arg_val { - int size; - int argc; - const char **argv; -}; - -static void addarg(struct arg_val*, const char*); - -/* - * start_login(host) - * - * Assuming that we are now running as a child processes, this - * function will turn us into the login process. - */ - -void -start_login(const char *host, int autologin, char *name) -{ - struct arg_val argv; - char *user; - int save_errno; - char *buf; - extern char *gettytab[2], *gettyent; - -#ifdef HAVE_UTMPX_H - int pid = getpid(); - struct utmpx utmpx; - char *clean_tty; - - /* - * Create utmp entry for child - */ - - clean_tty = clean_ttyname(line); - memset(&utmpx, 0, sizeof(utmpx)); - strncpy(utmpx.ut_user, ".telnet", sizeof(utmpx.ut_user)); - strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); -#ifdef HAVE_STRUCT_UTMP_UT_ID - strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id)); -#endif - utmpx.ut_pid = pid; - - utmpx.ut_type = LOGIN_PROCESS; - - gettimeofday (&utmpx.ut_tv, NULL); - if (pututxline(&utmpx) == NULL) - fatal(net, "pututxline failed"); -#endif - -#if 0 - scrub_env(); -#endif - /* - * -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 - */ - - /* init argv structure */ - argv.size=0; - argv.argc=0; - argv.argv=malloc(0); /*so we can call realloc later */ - addarg(&argv, "login"); - addarg(&argv, "-h"); - addarg(&argv, host); - addarg(&argv, "-p"); - if(name[0]) - user = name; - else - user = getenv("USER"); -#ifdef AUTHENTICATION - if (auth_level < 0 || autologin != AUTH_VALID) { - if(!no_warn) { - printf("User not authenticated. " - "Using plaintext username and password\r\n"); - } - if(log_unauth) - syslog(LOG_INFO, "unauthenticated access from %s (%s)", - host, user ? user : "unknown user"); - } - if (auth_level >= 0 && autologin == AUTH_VALID) - addarg(&argv, "-f"); -#endif - if(user){ - addarg(&argv, "--"); - addarg(&argv, strdup(user)); - } - if (new_login == NULL && cgetent(&buf, gettytab, gettyent) >= 0) { - cgetstr(buf, "lo", &new_login); - cgetclose(); - } - if (new_login == NULL) - new_login = _PATH_LOGIN; - - if (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"); - } - 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(new_login, (char *const*)argv.argv); - save_errno = errno; - syslog(LOG_ERR, "%s: %m", new_login); - fatalperror_errno(net, new_login, save_errno); - /*NOTREACHED*/ -} - -static void -addarg(struct arg_val *argv, const char *val) -{ - const char **tmp; - - if (argv->size <= argv->argc+1) { - tmp = realloc(argv->argv, sizeof(char*) * (argv->size + 10)); - if (tmp == NULL) { - if (argv->argv) - free(argv->argv); - argv->argv = NULL; - argv->size = 0; - fatal (net, "realloc: out of memory"); - } - argv->argv = tmp; - argv->size+=10; - } - argv->argv[argv->argc++] = val; - argv->argv[argv->argc] = NULL; -} - - -/* - * rmut() - * - * This is the function called by cleanup() to - * remove the utmp entry for this person. - */ - -#ifdef HAVE_UTMPX_H -static void -rmut(void) -{ - struct utmpx utmpx, *non_save_utxp; - char *clean_tty = clean_ttyname(line); - - /* - * This updates the utmpx and utmp entries and make a wtmp/x entry - */ - - setutxent(); - memset(&utmpx, 0, sizeof(utmpx)); - strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); - utmpx.ut_type = LOGIN_PROCESS; - non_save_utxp = getutxline(&utmpx); - if (non_save_utxp) { - struct utmpx *utxp; - char user0; - - utxp = malloc(sizeof(struct utmpx)); - *utxp = *non_save_utxp; - user0 = utxp->ut_user[0]; - utxp->ut_user[0] = '\0'; - utxp->ut_type = DEAD_PROCESS; -#ifdef HAVE_STRUCT_UTMPX_UT_EXIT -#ifdef _STRUCT___EXIT_STATUS - utxp->ut_exit.__e_termination = 0; - utxp->ut_exit.__e_exit = 0; -#elif defined(__osf__) /* XXX */ - utxp->ut_exit.ut_termination = 0; - utxp->ut_exit.ut_exit = 0; -#else - utxp->ut_exit.e_termination = 0; - utxp->ut_exit.e_exit = 0; -#endif -#endif - gettimeofday(&utxp->ut_tv, NULL); - pututxline(utxp); -#ifdef WTMPX_FILE - utxp->ut_user[0] = user0; - updwtmpx(WTMPX_FILE, utxp); -#elif defined(WTMP_FILE) - /* This is a strange system with a utmpx and a wtmp! */ - { - int f = open(wtmpf, O_WRONLY|O_APPEND); - struct utmp wtmp; - if (f >= 0) { - strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); - strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); -#ifdef HAVE_STRUCT_UTMP_UT_HOST - strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); -#endif - wtmp.ut_time = time(NULL); - write(f, &wtmp, sizeof(wtmp)); - close(f); - } - } -#endif - free (utxp); - } - endutxent(); -} /* end of rmut */ -#endif - -#if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) -static void -rmut(void) -{ - int f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - char *clean_tty = clean_ttyname(line); - - f = open(utmpf, O_RDWR); - if (f >= 0) { - fstat(f, &statbf); - utmp = (struct utmp *)malloc((unsigned)statbf.st_size); - if (!utmp) - syslog(LOG_ERR, "utmp malloc failed"); - if (statbf.st_size && utmp) { - nutmp = read(f, utmp, (int)statbf.st_size); - nutmp /= sizeof(struct utmp); - - for (u = utmp ; u < &utmp[nutmp] ; u++) { - if (strncmp(u->ut_line, - clean_tty, - sizeof(u->ut_line)) || - u->ut_name[0]==0) - continue; - lseek(f, ((long)u)-((long)utmp), L_SET); - strncpy(u->ut_name, "", sizeof(u->ut_name)); -#ifdef HAVE_STRUCT_UTMP_UT_HOST - strncpy(u->ut_host, "", sizeof(u->ut_host)); -#endif - u->ut_time = time(NULL); - write(f, u, sizeof(wtmp)); - found++; - } - } - close(f); - } - if (found) { - f = open(wtmpf, O_WRONLY|O_APPEND); - if (f >= 0) { - strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); - strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); -#ifdef HAVE_STRUCT_UTMP_UT_HOST - strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); -#endif - wtmp.ut_time = time(NULL); - write(f, &wtmp, sizeof(wtmp)); - close(f); - } - } - chmod(line, 0666); - chown(line, 0, 0); - line[strlen("/dev/")] = 'p'; - chmod(line, 0666); - chown(line, 0, 0); -} /* end of rmut */ -#endif /* CRAY */ - -#if defined(__hpux) && !defined(HAVE_UTMPX_H) -static void -rmut (char *line) -{ - struct utmp utmp; - struct utmp *utptr; - int fd; /* for /etc/wtmp */ - - utmp.ut_type = USER_PROCESS; - strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line)); - setutent(); - utptr = getutline(&utmp); - /* write it out only if it exists */ - if (utptr) { - utptr->ut_type = DEAD_PROCESS; - utptr->ut_time = time(NULL); - pututline(utptr); - /* set wtmp entry if wtmp file exists */ - if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { - write(fd, utptr, sizeof(utmp)); - close(fd); - } - } - endutent(); - - chmod(line, 0666); - chown(line, 0, 0); - line[14] = line[13]; - line[13] = line[12]; - line[8] = 'm'; - line[9] = '/'; - line[10] = 'p'; - line[11] = 't'; - line[12] = 'y'; - chmod(line, 0666); - chown(line, 0, 0); -} -#endif - -/* - * cleanup() - * - * This is the routine to call when we are all through, to - * clean up anything that needs to be cleaned up. - */ - -#ifdef PARENT_DOES_UTMP - -void -cleanup(int sig) -{ -#ifdef _CRAY - static int incleanup = 0; - int t; - int child_status; /* status of child process as returned by waitpid */ - int flags = WNOHANG|WUNTRACED; - - /* - * 1: Pick up the zombie, if we are being called - * as the signal handler. - * 2: If we are a nested cleanup(), return. - * 3: Try to clean up TMPDIR. - * 4: Fill in utmp with shutdown of process. - * 5: Close down the network and pty connections. - * 6: Finish up the TMPDIR cleanup, if needed. - */ - if (sig == SIGCHLD) { - while (waitpid(-1, &child_status, flags) > 0) - ; /* VOID */ - /* Check if the child process was stopped - * rather than exited. We want cleanup only if - * the child has died. - */ - if (WIFSTOPPED(child_status)) { - return; - } - } - t = sigblock(sigmask(SIGCHLD)); - if (incleanup) { - sigsetmask(t); - return; - } - incleanup = 1; - sigsetmask(t); - - t = cleantmp(&wtmp); - setutent(); /* just to make sure */ -#endif /* CRAY */ - rmut(line); - close(ourpty); - shutdown(net, 2); -#ifdef _CRAY - if (t == 0) - cleantmp(&wtmp); -#endif /* CRAY */ - exit(1); -} - -#else /* PARENT_DOES_UTMP */ - -void -cleanup(int sig) -{ -#if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP) - rmut(); -#ifdef HAVE_VHANGUP -#ifndef __sgi - vhangup(); /* XXX */ -#endif -#endif -#else - char *p; - - p = line + sizeof("/dev/") - 1; - if (logout(p)) - logwtmp(p, "", ""); - chmod(line, 0666); - chown(line, 0, 0); - *p = 'p'; - chmod(line, 0666); - chown(line, 0, 0); -#endif - shutdown(net, 2); - _exit(1); -} - -#endif /* PARENT_DOES_UTMP */ - -#ifdef PARENT_DOES_UTMP -/* - * _utmp_sig_rcv - * utmp_sig_init - * utmp_sig_wait - * These three functions are used to coordinate the handling of - * the utmp file between the server and the soon-to-be-login shell. - * The server actually creates the utmp structure, the child calls - * utmp_sig_wait(), until the server calls utmp_sig_notify() and - * signals the future-login shell to proceed. - */ -static int caught=0; /* NZ when signal intercepted */ -static void (*func)(); /* address of previous handler */ - -void -_utmp_sig_rcv(sig) - int sig; -{ - caught = 1; - signal(SIGUSR1, func); -} - -void -utmp_sig_init() -{ - /* - * register signal handler for UTMP creation - */ - if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) - fatalperror(net, "telnetd/signal"); -} - -void -utmp_sig_reset() -{ - signal(SIGUSR1, func); /* reset handler to default */ -} - -# ifdef __hpux -# define sigoff() /* do nothing */ -# define sigon() /* do nothing */ -# endif - -void -utmp_sig_wait() -{ - /* - * Wait for parent to write our utmp entry. - */ - sigoff(); - while (caught == 0) { - pause(); /* wait until we get a signal (sigon) */ - sigoff(); /* turn off signals while we check caught */ - } - sigon(); /* turn on signals again */ -} - -void -utmp_sig_notify(pid) -{ - kill(pid, SIGUSR1); -} - -#ifdef _CRAY -static int gotsigjob = 0; - - /*ARGSUSED*/ -void -sigjob(sig) - int sig; -{ - int jid; - struct jobtemp *jp; - - while ((jid = waitjob(NULL)) != -1) { - if (jid == 0) { - return; - } - gotsigjob++; - jobend(jid, NULL, NULL); - } -} - -/* - * jid_getutid: - * called by jobend() before calling cleantmp() - * to find the correct $TMPDIR to cleanup. - */ - -struct utmp * -jid_getutid(jid) - int jid; -{ - struct utmp *cur = NULL; - - setutent(); /* just to make sure */ - while (cur = getutent()) { - if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { - return(cur); - } - } - - return(0); -} - -/* - * Clean up the TMPDIR that login created. - * The first time this is called we pick up the info - * from the utmp. If the job has already gone away, - * then we'll clean up and be done. If not, then - * when this is called the second time it will wait - * for the signal that the job is done. - */ -int -cleantmp(wtp) - struct utmp *wtp; -{ - struct utmp *utp; - static int first = 1; - int mask, omask, ret; - extern struct utmp *getutid (const struct utmp *_Id); - - - mask = sigmask(WJSIGNAL); - - if (first == 0) { - omask = sigblock(mask); - while (gotsigjob == 0) - sigpause(omask); - return(1); - } - first = 0; - setutent(); /* just to make sure */ - - utp = getutid(wtp); - if (utp == 0) { - syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); - return(-1); - } - /* - * Nothing to clean up if the user shell was never started. - */ - if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) - return(1); - - /* - * Block the WJSIGNAL while we are in jobend(). - */ - omask = sigblock(mask); - ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); - sigsetmask(omask); - return(ret); -} - -/* - * jobend - * Assumes that if path is not NULL, then user is also - * not NULL. - */ -int -jobend(jid, path, user) - int jid; - char *path; - char *user; -{ - static int saved_jid = 0; - static int pty_saved_jid = 0; - static char saved_path[sizeof(wtmp.ut_tpath)+1]; - static char saved_user[sizeof(wtmp.ut_user)+1]; - - /* - * this little piece of code comes into play - * only when ptyreconnect is used to reconnect - * to an previous session. - * - * this is the only time when the - * "saved_jid != jid" code is executed. - */ - - if ( saved_jid && saved_jid != jid ) { - if (!path) { /* called from signal handler */ - pty_saved_jid = jid; - } else { - pty_saved_jid = saved_jid; - } - } - - if (path) { - strncpy(saved_path, path, sizeof(saved_path) - 1); - strncpy(saved_user, path, sizeof(saved_user) - 1); - saved_path[sizeof(saved_path) - 1] = '\0'; - saved_user[sizeof(saved_user) - 1] = '\0'; - } - if (saved_jid == 0) { - saved_jid = jid; - return(0); - } - - /* if the jid has changed, get the correct entry from the utmp file */ - - if ( saved_jid != jid ) { - struct utmp *utp = NULL; - struct utmp *jid_getutid(); - - utp = jid_getutid(pty_saved_jid); - - if (utp == 0) { - syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); - return(-1); - } - - cleantmpdir(jid, utp->ut_tpath, utp->ut_user); - return(1); - } - - cleantmpdir(jid, saved_path, saved_user); - return(1); -} - -/* - * Fork a child process to clean up the TMPDIR - */ -cleantmpdir(jid, tpath, user) - int jid; - char *tpath; - char *user; -{ - switch(fork()) { - case -1: - syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m", - tpath); - break; - case 0: - execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, (char *)NULL); - syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m", - tpath, CLEANTMPCMD); - exit(1); - default: - /* - * Forget about child. We will exit, and - * /etc/init will pick it up. - */ - break; - } -} -#endif /* CRAY */ -#endif /* defined(PARENT_DOES_UTMP) */ diff --git a/libexec/telnetd/telnetd.8 b/libexec/telnetd/telnetd.8 deleted file mode 100644 index cdba3a0ed28..00000000000 --- a/libexec/telnetd/telnetd.8 +++ /dev/null @@ -1,537 +0,0 @@ -.\" $OpenBSD: telnetd.8,v 1.33 2003/08/08 09:26:03 jmc Exp $ -.\" -.\" Copyright (c) 1983, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)telnetd.8 8.4 (Berkeley) 6/1/94 -.\" -.Dd June 1, 1994 -.Dt TELNETD 8 -.Os -.Sh NAME -.Nm telnetd -.Nd DARPA -.Tn TELNET -protocol server -.Sh SYNOPSIS -.Nm telnetd -.Bk -words -.Op Fl BUhkln -.Op Fl D Ar debugmode -.Op Fl S Ar tos -.Op Fl X Ar authtype -.Op Fl a Ar authmode -.Op Fl g Ar gettyent -.Op Fl r Ar lowpty-highpty -.Op Fl u Ar len -.Op Fl debug -.Op Fl L Ar /bin/login -.Op Fl y -.Op Ar port -.Ek -.Sh DESCRIPTION -The -.Nm telnetd -command is a server which supports the -.Tn DARPA -standard -.Tn TELNET -virtual terminal protocol. -.Nm Telnetd -is normally invoked by the internet server (see -.Xr inetd 8 ) -for requests to connect to the -.Tn TELNET -port as indicated by the -.Pa /etc/services -file (see -.Xr services 5 ) . -The -.Fl debug -option may be used to start up -.Nm telnetd -manually, instead of through -.Xr inetd 8 . -If started up this way, -.Ar port -may be specified to run -.Nm telnetd -on an alternate -.Tn TCP -port number. -.Pp -The -.Nm telnetd -command accepts the following options: -.Bl -tag -width "-a authmode" -.It Fl a Ar authmode -This option may be used for specifying what mode should -be used for Kerberos authentication. -Note that this option is only useful if -.Nm telnetd -has been compiled with support for the -.Dv AUTHENTICATION -option. -There are several valid values for -.Ar authmode : -.Bl -tag -width debug -.It debug -Turns on authentication debugging code. -.It user -Only allow connections when the remote user -can provide valid Kerberos authentication information -to identify the remote user, -and is allowed access to the specified account -without providing a password. -.It valid -Only allow connections when the remote user -can provide valid Kerberos authentication information -to identify the remote user. -The -.Xr login 1 -command will provide any additional user verification -needed if the remote user is not allowed automatic -access to the specified account. -.It other -Only allow connections that supply some authentication information. -This option is currently not supported -by any of the existing authentication mechanisms, -and is thus the same as specifying -.Fl a -.Cm valid . -.\" .It otp -.\" Only allow Kerberos authenticated connections (as with -.\" .Fl a -.\" .Cm user ) -.\" and also logins with one-time passwords (OTPs). -.\" This option will call login with an option so that only OTPs are accepted. -.\" The user can of course still type secret information at the prompt. -.It none -This is the default state. -Kerberos authentication information is not required. -If no or insufficient authentication information -is provided, then traditional cleartext passwords will be used. -.It off -This disables the authentication code, and cleartext password will be used. -.El -.It Fl B -Ignored. -.It Fl D Ar debugmode -This option may be used for debugging purposes. -This allows -.Nm telnetd -to print out debugging information -to the connection, allowing the user to see what -.Nm telnetd -is doing. -There are several possible values for -.Ar debugmode : -.Bl -tag -width exercise -.It Cm options -Prints information about the negotiation of -.Tn TELNET -options. -.It Cm report -Prints the -.Cm options -information, plus some additional information -about what processing is going on. -.It Cm netdata -Displays the data stream received by -.Nm telnetd . -.It Cm ptydata -Displays data written to the pty. -.It Cm exercise -Has not been implemented yet. -.El -.It Fl h -Disables the printing of host-specific information before -login has been completed. -.It Fl l -Ignored. -.It Fl n -Disable -.Dv TCP -keep-alives. -Normally -.Nm telnetd -enables the -.Tn TCP -keep-alive mechanism to probe connections that -have been idle for some period of time to determine -if the client is still there, so that idle connections -from machines that have crashed or can no longer -be reached may be cleaned up. -.It Fl g Ar gettyent -Specifies which entry from -.Pa /etc/gettytab -should be used to get banner strings, login program and other information. -The default entry is -.Dq default. -.It Fl r Ar lowpty-highpty -This option is only enabled when -.Nm telnetd -is compiled for -.Dv UNICOS . -It specifies an inclusive range of pseudo-terminal devices to -use. -If the system has sysconf variable -.Dv _SC_CRAY_NPTY -configured, the default pty search range is 0 to -.Dv _SC_CRAY_NPTY ; -otherwise, the default range is 0 to 128. -Either -.Ar lowpty -or -.Ar highpty -may be omitted to allow changing -either end of the search range. -If -.Ar lowpty -is omitted, the - character is still required so that -.Nm telnetd -can differentiate -.Ar highpty -from -.Ar lowpty . -.It Fl S Ar tos -.It Fl u Ar len -This option is used to specify the size of the field -in the -.Dv utmp -structure that holds the remote host name. -If the resolved host name is longer than -.Ar len , -the dotted decimal value will be used instead. -This allows hosts with very long host names that -overflow this field to still be uniquely identified. -Specifying -.Fl u0 -indicates that only dotted decimal addresses -should be put into the -.Pa utmp -file. -.It Fl U -This option causes -.Nm telnetd -to refuse connections from addresses that -cannot be mapped back into a symbolic name -via the -.Xr gethostbyaddr 3 -routine. -.It Fl X Ar authtype -This option is only valid if -.Nm telnetd -has been built with support for the authentication option. -It disables the use of -.Ar authtype -authentication, and -can be used to temporarily disable -a specific authentication type without having to recompile -.Nm telnetd . -.It Fl L Ar pathname -Specify pathname to an alternative login program. -.It Fl y -Makes -.Nm telnetd -not warn when a user is trying to login with cleartext -passwords. -.El -.Pp -.Nm Telnetd -operates by allocating a pseudo-terminal device (see -.Xr pty 4 ) -for a client, then creating a login process which has -the slave side of the pseudo-terminal as -.Dv stdin , -.Dv stdout -and -.Dv stderr . -.Nm Telnetd -manipulates the master side of the pseudo-terminal, -implementing the -.Tn TELNET -protocol and passing characters -between the remote client and the login process. -.Pp -When a -.Tn TELNET -session is started up, -.Nm telnetd -sends -.Tn TELNET -options to the client side indicating -a willingness to do the -following -.Tn TELNET -options, which are described in more detail below: -.Bd -literal -offset indent -DO AUTHENTICATION -WILL ENCRYPT -DO TERMINAL TYPE -DO TSPEED -DO XDISPLOC -DO NEW-ENVIRON -DO ENVIRON -WILL SUPPRESS GO AHEAD -DO ECHO -DO LINEMODE -DO NAWS -WILL STATUS -DO LFLOW -DO TIMING-MARK -.Ed -.Pp -The pseudo-terminal allocated to the client is configured -to operate in -.Dq cooked -mode, and with -.Dv XTABS and -.Dv CRMOD -enabled (see -.Xr tty 4 ) . -.Pp -.Nm Telnetd -has support for enabling locally the following -.Tn TELNET -options: -.Bl -tag -width "DO AUTHENTICATION" -.It "WILL ECHO" -When the -.Dv LINEMODE -option is enabled, a -.Dv WILL ECHO -or -.Dv WONT ECHO -will be sent to the client to indicate the -current state of terminal echoing. -When terminal echo is not desired, a -.Dv WILL ECHO -is sent to indicate that -.Nm telnetd -will take care of echoing any data that needs to be -echoed to the terminal, and then nothing is echoed. -When terminal echo is desired, a -.Dv WONT ECHO -is sent to indicate that -.Nm telnetd -will not be doing any terminal echoing, so the -client should do any terminal echoing that is needed. -.It "WILL BINARY" -Indicates that the client is willing to send -8 bits of data, rather than the normal 7 bits -of the Network Virtual Terminal. -.It "WILL SGA" -Indicates that it will not be sending -.Dv IAC GA , -go ahead, commands. -.It "WILL STATUS" -Indicates a willingness to send the client, upon -request, the current status of all -.Tn TELNET -options. -.It "WILL TIMING-MARK" -Whenever a -.Dv DO TIMING-MARK -command is received, it is always responded -to with a -.Dv WILL TIMING-MARK -.It "WILL LOGOUT" -When a -.Dv DO LOGOUT -is received, a -.Dv WILL LOGOUT -is sent in response, and the -.Tn TELNET -session is shut down. -.It "WILL ENCRYPT" -Only sent if -.Nm telnetd -Kerberos is enabled, and -indicates a willingness to decrypt -the data stream. -.El -.Pp -.Nm Telnetd -has support for enabling remotely the following -.Tn TELNET -options: -.Bl -tag -width "DO AUTHENTICATION" -.It "DO BINARY" -Sent to indicate that -.Nm telnetd -is willing to receive an 8 bit data stream. -.It "DO LFLOW" -Requests that the client handle flow control -characters remotely. -.It "DO ECHO" -This is not really supported, but is sent to identify a 4.2BSD -.Xr telnet 1 -client, which will improperly respond with -.Dv WILL ECHO . -If a -.Dv WILL ECHO -is received, a -.Dv DONT ECHO -will be sent in response. -.It "DO TERMINAL-TYPE" -Indicates a desire to be able to request the -name of the type of terminal that is attached -to the client side of the connection. -.It "DO SGA" -Indicates that it does not need to receive -.Dv IAC GA , -the go ahead command. -.It "DO NAWS" -Requests that the client inform the server when -the window (display) size changes. -.It "DO TERMINAL-SPEED" -Indicates a desire to be able to request information -about the speed of the serial line to which -the client is attached. -.It "DO XDISPLOC" -Indicates a desire to be able to request the name -of the X11 display that is associated with -the telnet client. -.It "DO NEW-ENVIRON" -Indicates a desire to be able to request environment -variable information, as described in RFC 1572. -.It "DO ENVIRON" -Indicates a desire to be able to request environment -variable information, as described in RFC 1408. -.It "DO LINEMODE" -Only sent if -.Nm telnetd -is compiled with support for linemode, and -requests that the client do line by line processing. -.It "DO TIMING-MARK" -Only sent if -.Nm telnetd -is compiled with support for both linemode and -kludge linemode, and the client responded with -.Dv WONT LINEMODE . -If the client responds with -.Dv WILL TM , -the it is assumed that the client supports -kludge linemode. -Note that the -.Op Fl k -option can be used to disable this. -.It "DO AUTHENTICATION" -Only sent if -.Nm telnetd -Kerberos authentication is enabled, and -indicates a willingness to receive authentication -information for automatic login. -.It "DO ENCRYPT" -Only sent if -.Nm telnetd -Kerberos is enabled, and -indicates a willingness to decrypt -the data stream. -.El -.Sh FILES -.Bl -tag -width /etc/services -compact -.It Pa /etc/services -.It Pa /etc/inittab -(UNICOS systems only) -.It Pa /etc/iptos -(if supported) -.El -.Sh SEE ALSO -.Xr login 1 , -.Xr telnet 1 -.Sh STANDARDS -.Bl -tag -compact -width "RFC 1572 " -.It RFC 854 -.Tn TELNET -PROTOCOL SPECIFICATION -.It RFC 855 -TELNET OPTION SPECIFICATIONS -.It RFC 856 -TELNET BINARY TRANSMISSION -.It RFC 857 -TELNET ECHO OPTION -.It RFC 858 -TELNET SUPPRESS GO AHEAD OPTION -.It RFC 859 -TELNET STATUS OPTION -.It RFC 860 -TELNET TIMING MARK OPTION -.It RFC 861 -TELNET EXTENDED OPTIONS - LIST OPTION -.It RFC 885 -TELNET END OF RECORD OPTION -.It RFC 1073 -Telnet Window Size Option -.It RFC 1079 -Telnet Terminal Speed Option -.It RFC 1091 -Telnet Terminal-Type Option -.It RFC 1096 -Telnet X Display Location Option -.It RFC 1123 -Requirements for Internet Hosts -- Application and Support -.It RFC 1184 -Telnet Linemode Option -.It RFC 1372 -Telnet Remote Flow Control Option -.It RFC 1416 -Telnet Authentication Option -.It RFC 1411 -Telnet Authentication: Kerberos Version 4 -.It RFC 1412 -Telnet Authentication: SPX -.It RFC 1571 -Telnet Environment Option Interoperability Issues -.It RFC 1572 -Telnet Environment Option -.El -.Sh BUGS -Some -.Tn TELNET -commands are only partially implemented. -.Pp -Because of bugs in the original 4.2 BSD -.Xr telnet 1 , -.Nm telnetd -performs some dubious protocol exchanges to try to discover if the remote -client is, in fact, a 4.2 BSD -.Xr telnet 1 . -.Pp -Binary mode -has no common interpretation except between similar operating systems -(Unix in this case). -.Pp -The terminal type name received from the remote client is converted to -lower case. -.Pp -.Nm Telnetd -never sends -.Tn TELNET -.Dv IAC GA -(go ahead) commands. diff --git a/libexec/telnetd/telnetd.c b/libexec/telnetd/telnetd.c deleted file mode 100644 index e31286bcb50..00000000000 --- a/libexec/telnetd/telnetd.c +++ /dev/null @@ -1,1398 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "telnetd.h" -#include <sys/socket.h> -#include <netdb.h> -#include <fcntl.h> -#include <syslog.h> -#include <unistd.h> -#include <sys/ioctl.h> - -/* RCSID("$KTH: telnetd.c,v 1.64 2001/02/08 16:06:27 assar Exp $"); */ - -#ifdef _SC_CRAY_SECURE_SYS -#include <sys/sysv.h> -#include <sys/secdev.h> -#include <sys/secparm.h> -#include <sys/usrv.h> -int secflag; -char tty_dev[16]; -struct secdev dv; -struct sysv sysv; -struct socksec ss; -#endif /* _SC_CRAY_SECURE_SYS */ - -#ifndef ENCRYPTION -#define encrypt_delay() 0 -#endif - -#ifdef AUTHENTICATION -int auth_level = 0; -#endif - -extern int utmp_len; -int registerd_host_only = 0; - -#ifdef STREAMSPTY -# include <stropts.h> -# include <termios.h> -#ifdef HAVE_SYS_UIO_H -#include <sys/uio.h> -#endif /* HAVE_SYS_UIO_H */ -#ifdef HAVE_SYS_STREAM_H -#include <sys/stream.h> -#endif -#ifdef _AIX -#include <sys/termio.h> -#endif -# ifdef HAVE_SYS_STRTTY_H -# include <sys/strtty.h> -# endif -# ifdef HAVE_SYS_STR_TTY_H -# include <sys/str_tty.h> -# endif -/* make sure we don't get the bsd version */ -/* what is this here for? solaris? /joda */ -# ifdef HAVE_SYS_TTY_H -# include "/usr/include/sys/tty.h" -# endif -# ifdef HAVE_SYS_PTYVAR_H -# include <sys/ptyvar.h> -# endif - -/* - * Because of the way ptyibuf is used with streams messages, we need - * ptyibuf+1 to be on a full-word boundary. The following weirdness - * is simply to make that happen. - */ -long ptyibufbuf[BUFSIZ/sizeof(long)+1]; -char *ptyibuf = ((char *)&ptyibufbuf[1])-1; -char *ptyip = ((char *)&ptyibufbuf[1])-1; -char ptyibuf2[BUFSIZ]; -unsigned char ctlbuf[BUFSIZ]; -struct strbuf strbufc, strbufd; - -int readstream(int, char*, int); - -#else /* ! STREAMPTY */ - -/* - * I/O data buffers, - * pointers, and counters. - */ -char ptyibuf[BUFSIZ], *ptyip = ptyibuf; -char ptyibuf2[BUFSIZ]; - -#endif /* ! STREAMPTY */ - -int hostinfo = 1; /* do we print login banner? */ - -#ifdef _CRAY -extern int newmap; /* nonzero if \n maps to ^M^J */ -int lowpty = 0, highpty; /* low, high pty numbers */ -#endif /* CRAY */ - -int debug = 0; -int keepalive = 1; -char *progname; -char *gettyent = "default"; -char *gettytab[2] = { "/etc/gettytab", NULL }; - -static void usage (void); - -/* - * The string to pass to getopt(). We do it this way so - * that only the actual options that we support will be - * passed off to getopt(). - */ -char valid_opts[] = "Bd:g:hklnS:u:UL:y" -#ifdef AUTHENTICATION - "a:X:z" -#endif -#ifdef DIAGNOSTICS - "D:" -#endif -#ifdef _CRAY - "r:" -#endif - ; - -static void doit(struct sockaddr*, int); - -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 = -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, "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; - 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 */ - - - case 'g': - gettyent = optarg; - break; - - case 'h': - hostinfo = 0; - 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 (debug) { - int port = 0; - struct servent *sp; - - if (argc > 1) { - usage (); - } else if (argc == 1) { - sp = getservbyname (*argv, "tcp"); - if (sp) - port = sp->s_port; - else - port = htons(atoi(*argv)); - } else { - sp = getservbyname ("telnet", "tcp"); - port = sp ? sp->s_port : htons(23); - } - mini_inetd (port); - } else 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("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); - 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 */ - -static void -usage(void) -{ - fprintf(stderr, "Usage: telnetd"); -#ifdef AUTHENTICATION - fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t"); -#endif - fprintf(stderr, " [-debug]"); -#ifdef DIAGNOSTICS - fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); -#endif -#ifdef AUTHENTICATION - fprintf(stderr, " [-edebug]"); -#endif - fprintf(stderr, " [-h]"); - fprintf(stderr, " [-L login]"); - fprintf(stderr, " [-n]"); -#ifdef _CRAY - fprintf(stderr, " [-r[lowpty]-[highpty]]"); -#endif - fprintf(stderr, "\n\t"); -#ifdef HAVE_GETTOSBYNAME - fprintf(stderr, " [-S tos]"); -#endif -#ifdef AUTHENTICATION - fprintf(stderr, " [-X auth-type] [-y] [-z]"); -#endif - fprintf(stderr, " [-u utmp_hostname_length] [-U]"); - fprintf(stderr, " [port]\n"); - exit(1); -} - -/* - * getterminaltype - * - * Ask the other end to send along its terminal type and speed. - * Output is the variable terminaltype filled in. - */ -static unsigned char ttytype_sbbuf[] = { - IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE -}; - -int -getterminaltype(char *name, size_t name_sz) -{ - int retval = -1; - - settimer(baseline); -#ifdef AUTHENTICATION - /* - * Handle the Authentication option before we do anything else. - */ - send_do(TELOPT_AUTHENTICATION, 1); - while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) - ttloop(); - if (his_state_is_will(TELOPT_AUTHENTICATION)) { - retval = auth_wait(name, name_sz); - } -#endif - -#ifdef ENCRYPTION - send_will(TELOPT_ENCRYPT, 1); - send_do(TELOPT_ENCRYPT, 1); /* esc@magic.fi */ -#endif - send_do(TELOPT_TTYPE, 1); - send_do(TELOPT_TSPEED, 1); - send_do(TELOPT_XDISPLOC, 1); - send_do(TELOPT_NEW_ENVIRON, 1); - send_do(TELOPT_OLD_ENVIRON, 1); - while ( -#ifdef ENCRYPTION - his_do_dont_is_changing(TELOPT_ENCRYPT) || -#endif - his_will_wont_is_changing(TELOPT_TTYPE) || - his_will_wont_is_changing(TELOPT_TSPEED) || - his_will_wont_is_changing(TELOPT_XDISPLOC) || - his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || - his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { - ttloop(); - } -#ifdef ENCRYPTION - /* - * Wait for the negotiation of what type of encryption we can - * send with. If autoencrypt is not set, this will just return. - */ - if (his_state_is_will(TELOPT_ENCRYPT)) { - encrypt_wait(); - } -#endif - if (his_state_is_will(TELOPT_TSPEED)) { - static unsigned char sb[] = - { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; - - telnet_net_write (sb, sizeof sb); - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); - } - if (his_state_is_will(TELOPT_XDISPLOC)) { - static unsigned char sb[] = - { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; - - telnet_net_write (sb, sizeof sb); - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); - } - if (his_state_is_will(TELOPT_NEW_ENVIRON)) { - static unsigned char sb[] = - { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; - - telnet_net_write (sb, sizeof sb); - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); - } - else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { - static unsigned char sb[] = - { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; - - telnet_net_write (sb, sizeof sb); - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); - } - if (his_state_is_will(TELOPT_TTYPE)) { - - telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf); - DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, - sizeof ttytype_sbbuf - 2);); - } - if (his_state_is_will(TELOPT_TSPEED)) { - while (sequenceIs(tspeedsubopt, baseline)) - ttloop(); - } - if (his_state_is_will(TELOPT_XDISPLOC)) { - while (sequenceIs(xdisplocsubopt, baseline)) - ttloop(); - } - if (his_state_is_will(TELOPT_NEW_ENVIRON)) { - while (sequenceIs(environsubopt, baseline)) - ttloop(); - } - if (his_state_is_will(TELOPT_OLD_ENVIRON)) { - while (sequenceIs(oenvironsubopt, baseline)) - ttloop(); - } - if (his_state_is_will(TELOPT_TTYPE)) { - char first[256], last[256]; - - while (sequenceIs(ttypesubopt, baseline)) - ttloop(); - - /* - * If the other side has already disabled the option, then - * we have to just go with what we (might) have already gotten. - */ - if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { - strlcpy(first, terminaltype, sizeof(first)); - for(;;) { - /* - * Save the unknown name, and request the next name. - */ - strlcpy(last, terminaltype, sizeof(last)); - _gettermname(); - if (terminaltypeok(terminaltype)) - break; - if ((strncmp(last, terminaltype, sizeof(last)) == 0) || - his_state_is_wont(TELOPT_TTYPE)) { - /* - * We've hit the end. If this is the same as - * the first name, just go with it. - */ - if (strncmp(first, terminaltype, sizeof(first)) == 0) - break; - /* - * Get the terminal name one more time, so that - * RFC1091 compliant telnets will cycle back to - * the start of the list. - */ - _gettermname(); - if (strncmp(first, terminaltype, sizeof(first)) != 0) - strlcpy(terminaltype, first, sizeof(terminaltype)); - break; - } - } - } - } - return(retval); -} /* end of getterminaltype */ - -void -_gettermname(void) -{ - /* - * If the client turned off the option, - * we can't send another request, so we - * just return. - */ - if (his_state_is_wont(TELOPT_TTYPE)) - return; - settimer(baseline); - telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf); - DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, - sizeof ttytype_sbbuf - 2);); - while (sequenceIs(ttypesubopt, baseline)) - ttloop(); -} - -int -terminaltypeok(char *s) -{ - return 1; -} - - -char host_name[MAXHOSTNAMELEN]; -char remote_host_name[MAXHOSTNAMELEN]; -char remote_utmp_name[MAXHOSTNAMELEN]; - -/* - * Get a pty, scan input lines. - */ -static void -doit(struct sockaddr *who, int who_len) -{ - int level; - int ptynum; - char user_name[256]; - int error; - - /* - * Find an available pty to use. - */ - ourpty = getpty(&ptynum); - if (ourpty < 0) - fatal(net, "All network ports in use"); - -#ifdef _SC_CRAY_SECURE_SYS - /* - * set ttyp line security label - */ - if (secflag) { - char slave_dev[16]; - - snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum); - if (setdevs(tty_dev, &dv) < 0) - fatal(net, "cannot set pty security"); - snprintf(slave_dev, sizeof(slave_dev), "/dev/ttyp%03d", ptynum); - if (setdevs(slave_dev, &dv) < 0) - fatal(net, "cannot set tty security"); - } -#endif /* _SC_CRAY_SECURE_SYS */ - - error = getnameinfo (who, who_len, - remote_host_name, - sizeof(remote_host_name), - NULL, 0, - registerd_host_only ? NI_NAMEREQD : 0); - if (error) - fatal(net, "Couldn't resolve your address into a host name.\r\n\ -Please contact your net administrator"); - - gethostname(host_name, sizeof (host_name)); - - strlcpy (remote_utmp_name, remote_host_name, sizeof(remote_utmp_name)); - - /* Only trim if too long (and possible) */ - if (strlen(remote_utmp_name) > utmp_len) { - char *domain = strchr(host_name, '.'); - char *p = strchr(remote_utmp_name, '.'); - if (domain != NULL && p != NULL && (strcmp(p, domain) == 0)) - *p = '\0'; /* remove domain part */ - } - - /* - * If hostname still doesn't fit utmp, use ipaddr. - */ - if (strlen(remote_utmp_name) > utmp_len) { - error = getnameinfo (who, who_len, - remote_utmp_name, - sizeof(remote_utmp_name), - NULL, 0, - NI_NUMERICHOST); - if (error) - fatal(net, "Couldn't get numeric address\r\n"); - } - -#ifdef AUTHENTICATION - auth_encrypt_init(host_name, remote_host_name, "TELNETD", 1); -#endif - - init_env(); - /* - * get terminal type. - */ - *user_name = 0; - level = getterminaltype(user_name, sizeof(user_name)); - esetenv("TERM", terminaltype ? terminaltype : "network", 1); - -#ifdef _SC_CRAY_SECURE_SYS - if (secflag) { - if (setulvl(dv.dv_actlvl) < 0) - fatal(net,"cannot setulvl()"); - if (setucmp(dv.dv_actcmp) < 0) - fatal(net, "cannot setucmp()"); - } -#endif /* _SC_CRAY_SECURE_SYS */ - - /* begin server processing */ - my_telnet(net, ourpty, remote_host_name, remote_utmp_name, - level, user_name); - /*NOTREACHED*/ -} /* end of doit */ - -/* output contents of /etc/issue.net, or /etc/issue */ -static void -show_issue(void) -{ - FILE *f; - char buf[128]; - f = fopen("/etc/issue.net", "r"); - if(f == NULL) - f = fopen("/etc/issue", "r"); - if(f){ - while(fgets(buf, sizeof(buf)-2, f)){ - size_t off = strcspn(buf, "\r\n"); - strlcpy(buf + off, "\r\n", sizeof(buf) - off); - writenet((unsigned char*)buf, strlen(buf)); - } - fclose(f); - } -} - -/* - * Main loop. Select from pty and network, and - * hand data to telnet receiver finite state machine. - */ -void -my_telnet(int f, int p, const char *host, const char *utmp_host, - int level, char *autoname) -{ - int on = 1; - char *he; - char *IM; - char *buf; - int nfd; - int startslave_called = 0; - time_t timeout; - fd_set *ibits = NULL; - fd_set *obits = NULL; - fd_set *xbits = NULL; - int setsize; - - /* - * Initialize the slc mapping table. - */ - get_slc_defaults(); - - /* - * Do some tests where it is desireable to wait for a response. - * Rather than doing them slowly, one at a time, do them all - * at once. - */ - if (my_state_is_wont(TELOPT_SGA)) - send_will(TELOPT_SGA, 1); - /* - * Is the client side a 4.2 (NOT 4.3) system? We need to know this - * because 4.2 clients are unable to deal with TCP urgent data. - * - * To find out, we send out a "DO ECHO". If the remote system - * answers "WILL ECHO" it is probably a 4.2 client, and we note - * that fact ("WILL ECHO" ==> that the client will echo what - * WE, the server, sends it; it does NOT mean that the client will - * echo the terminal input). - */ - send_do(TELOPT_ECHO, 1); - - /* - * Send along a couple of other options that we wish to negotiate. - */ - send_do(TELOPT_NAWS, 1); - send_will(TELOPT_STATUS, 1); - flowmode = 1; /* default flow control state */ - restartany = -1; /* uninitialized... */ - send_do(TELOPT_LFLOW, 1); - - /* - * Spin, waiting for a response from the DO ECHO. However, - * some REALLY DUMB telnets out there might not respond - * to the DO ECHO. So, we spin looking for NAWS, (most dumb - * telnets so far seem to respond with WONT for a DO that - * they don't understand...) because by the time we get the - * response, it will already have processed the DO ECHO. - * Kludge upon kludge. - */ - while (his_will_wont_is_changing(TELOPT_NAWS)) - ttloop(); - - /* - * But... - * The client might have sent a WILL NAWS as part of its - * startup code; if so, we'll be here before we get the - * response to the DO ECHO. We'll make the assumption - * that any implementation that understands about NAWS - * is a modern enough implementation that it will respond - * to our DO ECHO request; hence we'll do another spin - * waiting for the ECHO option to settle down, which is - * what we wanted to do in the first place... - */ - if (his_want_state_is_will(TELOPT_ECHO) && - his_state_is_will(TELOPT_NAWS)) { - while (his_will_wont_is_changing(TELOPT_ECHO)) - ttloop(); - } - /* - * On the off chance that the telnet client is broken and does not - * respond to the DO ECHO we sent, (after all, we did send the - * DO NAWS negotiation after the DO ECHO, and we won't get here - * until a response to the DO NAWS comes back) simulate the - * receipt of a will echo. This will also send a WONT ECHO - * to the client, since we assume that the client failed to - * respond because it believes that it is already in DO ECHO - * mode, which we do not want. - */ - if (his_want_state_is_will(TELOPT_ECHO)) { - DIAG(TD_OPTIONS, - {output_data("td: simulating recv\r\n"); - }); - willoption(TELOPT_ECHO); - } - - /* - * Finally, to clean things up, we turn on our echo. This - * will break stupid 4.2 telnets out of local terminal echo. - */ - - if (my_state_is_wont(TELOPT_ECHO)) - send_will(TELOPT_ECHO, 1); - -#ifdef TIOCPKT -#ifdef STREAMSPTY - if (!really_stream) -#endif - /* - * Turn on packet mode - */ - ioctl(p, TIOCPKT, (char *)&on); -#endif - - - /* - * Call telrcv() once to pick up anything received during - * terminal type negotiation, 4.2/4.3 determination, and - * linemode negotiation. - */ - telrcv(); - - ioctl(f, FIONBIO, (char *)&on); - ioctl(p, FIONBIO, (char *)&on); - -#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) - setsockopt(net, SOL_SOCKET, SO_OOBINLINE, - (void *)&on, sizeof on); -#endif /* defined(SO_OOBINLINE) */ - -#ifdef SIGTSTP - signal(SIGTSTP, SIG_IGN); -#endif -#ifdef SIGTTOU - /* - * Ignoring SIGTTOU keeps the kernel from blocking us - * in ttioct() in /sys/tty.c. - */ - signal(SIGTTOU, SIG_IGN); -#endif - - signal(SIGCHLD, cleanup); - -#ifdef TIOCNOTTY - { - int t; - t = open(_PATH_TTY, O_RDWR); - if (t >= 0) { - ioctl(t, TIOCNOTTY, (char *)0); - close(t); - } - } -#endif - - show_issue(); - /* - * Show banner that getty never gave. - * - * We put the banner in the pty input buffer. This way, it - * gets carriage return null processing, etc., just like all - * other pty --> client data. - */ - - if (getenv("USER")) - hostinfo = 0; - - if (cgetent(&buf, gettytab, gettyent) >= 0) { - char *HN; - - if (cgetstr(buf, "he", &he) <= 0) - he = NULL; - if (cgetstr(buf, "im", &IM) <= 0) - IM = ""; - if (cgetstr(buf, "hn", &HN) > 0) { - strlcpy(host_name, HN, sizeof host_name); - free(HN); - } - cgetclose(); - } else { - IM = DEFAULT_IM; - he = NULL; - } - edithost(he, host_name); - if (he) - free(he); - if (hostinfo && *IM) - putf(IM, ptyibuf2); - if (IM != DEFAULT_IM && *IM) - free(IM); - - if (pcc) - strncat(ptyibuf2, ptyip, pcc+1); - ptyip = ptyibuf2; - pcc = strlen(ptyip); - - DIAG(TD_REPORT, { - output_data("td: Entering processing loop\r\n"); - }); - - - nfd = ((f > p) ? f : p) + 1; - setsize = howmany(nfd, NFDBITS) * sizeof(fd_mask); - ibits = malloc(setsize); - obits = malloc(setsize); - xbits = malloc(setsize); - if (ibits == NULL || obits == NULL || xbits == NULL) { - syslog(LOG_ERR, "Out of memory"); - exit(1); - } - timeout = time(NULL) + 5; - for (;;) { - int c; - - /* wait for encryption to be turned on, but don't wait - indefinitely */ - if(!startslave_called && (!encrypt_delay() || timeout > time(NULL))){ - startslave_called = 1; - startslave(host, utmp_host, level, autoname); - } - - if (ncc < 0 && pcc < 0) - break; - - memset(obits, 0, setsize); - memset(ibits, 0, setsize); - memset(xbits, 0, setsize); - - /* - * Never look for input if there's still - * stuff in the corresponding output buffer - */ - if (nfrontp - nbackp || pcc > 0) { - FD_SET(f, obits); - } else { - FD_SET(p, ibits); - } - if (pfrontp - pbackp || ncc > 0) { - FD_SET(p, obits); - } else { - FD_SET(f, ibits); - } - if (!SYNCHing) { - FD_SET(f, xbits); - } - if ((c = select(nfd, ibits, obits, xbits, - (struct timeval *)0)) < 1) { - if (c == -1) { - if (errno == EINTR) { - continue; - } - } - sleep(5); - continue; - } - - /* - * Any urgent data? - */ - if (FD_ISSET(f, xbits)) { - SYNCHing = 1; - } - - /* - * Something to read from the network... - */ - if (FD_ISSET(f, ibits)) { -#ifndef SO_OOBINLINE - /* - * In 4.2 (and 4.3 beta) systems, the - * OOB indication and data handling in the kernel - * is such that if two separate TCP Urgent requests - * come in, one byte of TCP data will be overlaid. - * This is fatal for Telnet, but we try to live - * with it. - * - * In addition, in 4.2 (and...), a special protocol - * is needed to pick up the TCP Urgent data in - * the correct sequence. - * - * What we do is: if we think we are in urgent - * mode, we look to see if we are "at the mark". - * If we are, we do an OOB receive. If we run - * this twice, we will do the OOB receive twice, - * but the second will fail, since the second - * time we were "at the mark", but there wasn't - * any data there (the kernel doesn't reset - * "at the mark" until we do a normal read). - * Once we've read the OOB data, we go ahead - * and do normal reads. - * - * There is also another problem, which is that - * since the OOB byte we read doesn't put us - * out of OOB state, and since that byte is most - * likely the TELNET DM (data mark), we would - * stay in the TELNET SYNCH (SYNCHing) state. - * So, clocks to the rescue. If we've "just" - * received a DM, then we test for the - * presence of OOB data when the receive OOB - * fails (and AFTER we did the normal mode read - * to clear "at the mark"). - */ - if (SYNCHing) { - int atmark; - - ioctl(f, SIOCATMARK, (char *)&atmark); - if (atmark) { - ncc = recv(f, netibuf, sizeof (netibuf), MSG_OOB); - if ((ncc == -1) && (errno == EINVAL)) { - ncc = read(f, netibuf, sizeof (netibuf)); - if (sequenceIs(didnetreceive, gotDM)) { - SYNCHing = stilloob(f); - } - } - } else { - ncc = read(f, netibuf, sizeof (netibuf)); - } - } else { - ncc = read(f, netibuf, sizeof (netibuf)); - } - settimer(didnetreceive); -#else /* !defined(SO_OOBINLINE)) */ - ncc = read(net, netibuf, sizeof (netibuf)); -#endif /* !defined(SO_OOBINLINE)) */ - if (ncc < 0 && errno == EWOULDBLOCK) - ncc = 0; - else { - if (ncc <= 0) { - break; - } - netip = netibuf; - } - DIAG((TD_REPORT | TD_NETDATA), { - output_data("td: netread %d chars\r\n", ncc); - }); - DIAG(TD_NETDATA, printdata("nd", netip, ncc)); - } - - /* - * Something to read from the pty... - */ - if (FD_ISSET(p, ibits)) { -#ifdef STREAMSPTY - if (really_stream) - pcc = readstream(p, ptyibuf, BUFSIZ); - else -#endif - pcc = read(p, ptyibuf, BUFSIZ); - - /* - * On some systems, if we try to read something - * off the master side before the slave side is - * opened, we get EIO. - */ - if (pcc < 0 && (errno == EWOULDBLOCK || -#ifdef EAGAIN - errno == EAGAIN || -#endif - errno == EIO)) { - pcc = 0; - } else { - if (pcc <= 0) - break; - if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { - netclear(); /* clear buffer back */ -#ifndef NO_URGENT - /* - * There are client telnets on some - * operating systems get screwed up - * royally if we send them urgent - * mode data. - */ - output_data ("%c%c", IAC, DM); - - neturg = nfrontp-1; /* off by one XXX */ - DIAG(TD_OPTIONS, - printoption("td: send IAC", DM)); - -#endif - } - if (his_state_is_will(TELOPT_LFLOW) && - (ptyibuf[0] & - (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { - int newflow = - ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; - if (newflow != flowmode) { - flowmode = newflow; - output_data("%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - flowmode ? LFLOW_ON - : LFLOW_OFF, - IAC, SE); - DIAG(TD_OPTIONS, printsub('>', - (unsigned char *)nfrontp-4, - 4);); - } - } - pcc--; - ptyip = ptyibuf+1; - } - } - - while (pcc > 0) { - if ((&netobuf[BUFSIZ] - nfrontp) < 3) - break; - c = *ptyip++ & 0377, pcc--; - if (c == IAC) - *nfrontp++ = c; - *nfrontp++ = c; - if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { - if (pcc > 0 && ((*ptyip & 0377) == '\n')) { - *nfrontp++ = *ptyip++ & 0377; - pcc--; - } else - *nfrontp++ = '\0'; - } - } - - if (FD_ISSET(f, obits) && (nfrontp - nbackp) > 0) - netflush(); - if (ncc > 0) - telrcv(); - if (FD_ISSET(p, obits) && (pfrontp - pbackp) > 0) - ptyflush(); - } - cleanup(0); -} - -#ifndef TCSIG -# ifdef TIOCSIG -# define TCSIG TIOCSIG -# endif -#endif - -#ifdef STREAMSPTY - - int flowison = -1; /* current state of flow: -1 is unknown */ - -int -readstream(int p, char *ibuf, int bufsize) -{ - int flags = 0; - int ret = 0; - struct termios *tsp; -#if 0 - struct termio *tp; -#endif - struct iocblk *ip; - char vstop, vstart; - int ixon; - int newflow; - - strbufc.maxlen = BUFSIZ; - strbufc.buf = (char *)ctlbuf; - strbufd.maxlen = bufsize-1; - strbufd.len = 0; - strbufd.buf = ibuf+1; - ibuf[0] = 0; - - ret = getmsg(p, &strbufc, &strbufd, &flags); - if (ret < 0) /* error of some sort -- probably EAGAIN */ - return(-1); - - if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { - /* data message */ - if (strbufd.len > 0) { /* real data */ - return(strbufd.len + 1); /* count header char */ - } else { - /* nothing there */ - errno = EAGAIN; - return(-1); - } - } - - /* - * It's a control message. Return 1, to look at the flag we set - */ - - switch (ctlbuf[0]) { - case M_FLUSH: - if (ibuf[1] & FLUSHW) - ibuf[0] = TIOCPKT_FLUSHWRITE; - return(1); - - case M_IOCTL: - ip = (struct iocblk *) (ibuf+1); - - switch (ip->ioc_cmd) { -#ifdef TCSETS - case TCSETS: - case TCSETSW: - case TCSETSF: - tsp = (struct termios *) - (ibuf+1 + sizeof(struct iocblk)); - vstop = tsp->c_cc[VSTOP]; - vstart = tsp->c_cc[VSTART]; - ixon = tsp->c_iflag & IXON; - break; -#endif -#if 0 - case TCSETA: - case TCSETAW: - case TCSETAF: - tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); - vstop = tp->c_cc[VSTOP]; - vstart = tp->c_cc[VSTART]; - ixon = tp->c_iflag & IXON; - break; -#endif - default: - errno = EAGAIN; - return(-1); - } - - newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; - if (newflow != flowison) { /* it's a change */ - flowison = newflow; - ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; - return(1); - } - } - - /* nothing worth doing anything about */ - errno = EAGAIN; - return(-1); -} -#endif /* STREAMSPTY */ - -/* - * Send interrupt to process on other side of pty. - * If it is in raw mode, just write NULL; - * otherwise, write intr char. - */ -void -interrupt() -{ - ptyflush(); /* half-hearted */ - -#if defined(STREAMSPTY) && defined(TIOCSIGNAL) - /* Streams PTY style ioctl to post a signal */ - if (really_stream) - { - int sig = SIGINT; - ioctl(ourpty, TIOCSIGNAL, &sig); - ioctl(ourpty, I_FLUSH, FLUSHR); - } -#else -#ifdef TCSIG - ioctl(ourpty, TCSIG, (char *)SIGINT); -#else /* TCSIG */ - init_termbuf(); - *pfrontp++ = slctab[SLC_IP].sptr ? - (unsigned char)*slctab[SLC_IP].sptr : '\177'; -#endif /* TCSIG */ -#endif -} - -/* - * Send quit to process on other side of pty. - * If it is in raw mode, just write NULL; - * otherwise, write quit char. - */ -void -sendbrk() -{ - ptyflush(); /* half-hearted */ -#ifdef TCSIG - ioctl(ourpty, TCSIG, (char *)SIGQUIT); -#else /* TCSIG */ - init_termbuf(); - *pfrontp++ = slctab[SLC_ABORT].sptr ? - (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; -#endif /* TCSIG */ -} - -void -sendsusp() -{ -#ifdef SIGTSTP - ptyflush(); /* half-hearted */ -# ifdef TCSIG - ioctl(ourpty, TCSIG, (char *)SIGTSTP); -# else /* TCSIG */ - *pfrontp++ = slctab[SLC_SUSP].sptr ? - (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; -# endif /* TCSIG */ -#endif /* SIGTSTP */ -} - -/* - * When we get an AYT, if ^T is enabled, use that. Otherwise, - * just send back "[Yes]". - */ -void -recv_ayt() -{ -#if defined(SIGINFO) && defined(TCSIG) - if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { - ioctl(ourpty, TCSIG, (char *)SIGINFO); - return; - } -#endif - output_data("\r\n[Yes]\r\n"); -} - -void -doeof() -{ - init_termbuf(); - - *pfrontp++ = slctab[SLC_EOF].sptr ? - (unsigned char)*slctab[SLC_EOF].sptr : '\004'; -} - diff --git a/libexec/telnetd/telnetd.h b/libexec/telnetd/telnetd.h deleted file mode 100644 index e0c40f22f26..00000000000 --- a/libexec/telnetd/telnetd.h +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)telnetd.h 8.1 (Berkeley) 6/4/93 - */ - - -#include <err.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#define HAVE_STDARG_H -#define HAVE_NETDB_H -#define HAVE_SYS_STAT_H -#define HAVE_SYSLOG_H -#define HAVE_UTMP_H -#define HAVE_SYS_TYPES_H -#define HAVE_SYS_SOCKET_H -#define HAVE_FCNTL_H -#define HAVE_SYS_IOCTL_H -#define HAVE_UNISTD_H -#define HAVE_SYS_UTSNAME_H -#define HAVE_UNAME -#define HAVE_UTIL_H -#define HAVE_OPENPTY - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef TIME_WITH_SYS_TIME -#include <sys/time.h> -#include <time.h> -#elif defined(HAVE_SYS_TIME_H) -#include <sys/time.h> -#else -#include <time.h> -#endif - -#ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> -#endif /* HAVE_SYS_RESOURCE_H */ - -#ifdef HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_SYS_FILE_H -#include <sys/file.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -/* including both <sys/ioctl.h> and <termios.h> in SunOS 4 generates a - lot of warnings */ - -#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 -#include <sys/ioctl.h> -#endif -#ifdef HAVE_SYS_FILIO_H -#include <sys/filio.h> -#endif - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_NETINET_IN6_H -#include <netinet/in6.h> -#endif -#ifdef HAVE_NETINET6_IN6_H -#include <netinet6/in6.h> -#endif - -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif - -#include <signal.h> -#include <errno.h> -#ifdef HAVE_NETDB_H -#include <netdb.h> -#endif -#ifdef HAVE_SYSLOG_H -#include <syslog.h> -#endif -#include <ctype.h> - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <termios.h> - -#ifdef HAVE_PTY_H -#include <pty.h> -#endif - -#include "defs.h" - -#ifndef _POSIX_VDISABLE -# ifdef VDISABLE -# define _POSIX_VDISABLE VDISABLE -# else -# define _POSIX_VDISABLE ((unsigned char)'\377') -# endif -#endif - - -#ifdef HAVE_SYS_PTY_H -#include <sys/pty.h> -#endif -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -#ifdef HAVE_SYS_PTYIO_H -#include <sys/ptyio.h> -#endif - -#ifdef HAVE_SYS_UTSNAME_H -#include <sys/utsname.h> -#endif - -#ifdef HAVE_PATHS_H -#include <paths.h> -#endif - -#ifdef HAVE_ARPA_TELNET_H -#include <arpa/telnet.h> -#endif - -#ifdef HAVE_STDARG_H -#include <stdarg.h> -#endif - -#include "ext.h" - -#ifdef SOCKS -#include <socks.h> -/* This doesn't belong here. */ -struct tm *localtime(const time_t *); -struct hostent *gethostbyname(const char *); -#endif - -#ifdef KRB4 -#include <kerberosIV/krb.h> -#endif - -#ifdef AUTHENTICATION -#include <auth.h> -#include <misc.h> -#ifdef ENCRYPTION -#include <encrypt.h> -#endif -#endif - -#ifdef HAVE_LIBUTIL_H -#include <libutil.h> -#endif - - -/* Don't use the system login, use our version instead */ - -/* BINDIR should be defined somewhere else... */ - -#ifndef BINDIR -#define BINDIR "/usr/bin" -#endif - -#undef _PATH_LOGIN -#define _PATH_LOGIN BINDIR "/login" - -/* fallbacks */ - -#ifndef _PATH_DEV -#define _PATH_DEV "/dev/" -#endif - -#ifndef _PATH_TTY -#define _PATH_TTY "/dev/tty" -#endif /* _PATH_TTY */ - -#ifdef DIAGNOSTICS -#define DIAG(a,b) if (diagnostic & (a)) b -#else -#define DIAG(a,b) -#endif - -/* other external variables */ -extern char **environ; - -/* prototypes */ - -/* appends data to nfrontp and advances */ -int output_data (const char *format, ...) -#ifdef __GNUC__ -__attribute__ ((format (printf, 1, 2))) -#endif -; - -void esetenv(const char *, const char *, int); -void mini_inetd(int); -void socket_set_reuseaddr (int, int); - diff --git a/libexec/telnetd/termstat.c b/libexec/telnetd/termstat.c deleted file mode 100644 index e2e3edaff38..00000000000 --- a/libexec/telnetd/termstat.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "telnetd.h" - -/* RCSID("$KTH: termstat.c,v 1.11 1997/05/11 06:30:04 assar Exp $") */ - -/* - * local variables - */ -int def_tspeed = -1, def_rspeed = -1; -#ifdef TIOCSWINSZ -int def_row = 0, def_col = 0; -#endif - -/* - * flowstat - * - * Check for changes to flow control - */ -void -flowstat() -{ - if (his_state_is_will(TELOPT_LFLOW)) { - if (tty_flowmode() != flowmode) { - flowmode = tty_flowmode(); - output_data("%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - flowmode ? LFLOW_ON : LFLOW_OFF, - IAC, SE); - } - if (tty_restartany() != restartany) { - restartany = tty_restartany(); - output_data("%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - restartany ? LFLOW_RESTART_ANY - : LFLOW_RESTART_XON, - IAC, SE); - } - } -} - -/* - * clientstat - * - * Process linemode related requests from the client. - * Client can request a change to only one of linemode, editmode or slc's - * at a time, and if using kludge linemode, then only linemode may be - * affected. - */ -void -clientstat(int code, int parm1, int parm2) -{ - void netflush(void); - - /* - * Get a copy of terminal characteristics. - */ - init_termbuf(); - - /* - * Process request from client. code tells what it is. - */ - switch (code) { - case TELOPT_NAWS: -#ifdef TIOCSWINSZ - { - struct winsize ws; - - def_col = parm1; - def_row = parm2; - - /* - * Change window size as requested by client. - */ - - ws.ws_col = parm1; - ws.ws_row = parm2; - ioctl(ourpty, TIOCSWINSZ, (char *)&ws); - } -#endif /* TIOCSWINSZ */ - - break; - - case TELOPT_TSPEED: - { - def_tspeed = parm1; - def_rspeed = parm2; - /* - * Change terminal speed as requested by client. - * We set the receive speed first, so that if we can't - * store separate receive and transmit speeds, the transmit - * speed will take precedence. - */ - tty_rspeed(parm2); - tty_tspeed(parm1); - set_termbuf(); - - break; - - } /* end of case TELOPT_TSPEED */ - - default: - /* What? */ - break; - } /* end of switch */ - - netflush(); - -} diff --git a/libexec/telnetd/utility.c b/libexec/telnetd/utility.c deleted file mode 100644 index f0a7202c590..00000000000 --- a/libexec/telnetd/utility.c +++ /dev/null @@ -1,1169 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#define PRINTOPTIONS -#include "telnetd.h" - -/* RCSID("$KTH: utility.c,v 1.25 2001/05/17 00:34:42 assar Exp $"); */ - -/* - * utility functions performing io related tasks - */ - -/* - * ttloop - * - * A small subroutine to flush the network output buffer, get some - * data from the network, and pass it through the telnet state - * machine. We also flush the pty input buffer (by dropping its data) - * if it becomes too full. - * - * return 0 if OK or 1 if interrupted by a signal. - */ - -int -ttloop(void) -{ - void netflush(void); - - DIAG(TD_REPORT, { - output_data("td: ttloop\r\n"); - }); - if (nfrontp-nbackp) - netflush(); - ncc = read(net, netibuf, sizeof netibuf); - if (ncc < 0) { - if (errno == EINTR) - return 1; - syslog(LOG_INFO, "ttloop: read: %m"); - exit(1); - } else if (ncc == 0) { - syslog(LOG_INFO, "ttloop: peer died"); - exit(1); - } - DIAG(TD_REPORT, { - output_data("td: ttloop read %d chars\r\n", ncc); - }); - netip = netibuf; - telrcv(); /* state machine */ - if (ncc > 0) { - pfrontp = pbackp = ptyobuf; - telrcv(); - } - return 0; -} /* end of ttloop */ - -/* - * Check a descriptor to see if out of band data exists on it. - */ -int -stilloob(int s) -{ - static struct timeval timeout = { 0 }; - fd_set excepts; - int value; - - if (s >= FD_SETSIZE) - fatal(ourpty, "fd too large"); - - do { - FD_ZERO(&excepts); - FD_SET(s, &excepts); - value = select(s+1, 0, 0, &excepts, &timeout); - } while ((value == -1) && (errno == EINTR)); - - if (value < 0) { - fatalperror(ourpty, "select"); - } - if (FD_ISSET(s, &excepts)) { - return 1; - } else { - return 0; - } -} - -void -ptyflush(void) -{ - int n; - - if ((n = pfrontp - pbackp) > 0) { - DIAG((TD_REPORT | TD_PTYDATA), { - output_data("td: ptyflush %d chars\r\n", n); - }); - DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); - n = write(ourpty, pbackp, n); - } - if (n < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) - return; - cleanup(0); - } - pbackp += n; - if (pbackp == pfrontp) - pbackp = pfrontp = ptyobuf; -} - -/* - * nextitem() - * - * Return the address of the next "item" in the TELNET data - * stream. This will be the address of the next character if - * the current address is a user data character, or it will - * be the address of the character following the TELNET command - * if the current address is a TELNET IAC ("I Am a Command") - * character. - */ -char * -nextitem(char *current) -{ - if ((*current&0xff) != IAC) { - return current+1; - } - switch (*(current+1)&0xff) { - case DO: - case DONT: - case WILL: - case WONT: - return current+3; - case SB:{ - /* loop forever looking for the SE */ - char *look = current+2; - - for (;;) { - if ((*look++&0xff) == IAC) { - if ((*look++&0xff) == SE) { - return look; - } - } - } - } - default: - return current+2; - } -} - - -/* - * netclear() - * - * We are about to do a TELNET SYNCH operation. Clear - * the path to the network. - * - * Things are a bit tricky since we may have sent the first - * byte or so of a previous TELNET command into the network. - * So, we have to scan the network buffer from the beginning - * until we are up to where we want to be. - * - * A side effect of what we do, just to keep things - * simple, is to clear the urgent data pointer. The principal - * caller should be setting the urgent data pointer AFTER calling - * us in any case. - */ -void -netclear(void) -{ - char *thisitem, *next; - char *good; -#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ - ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) - -#ifdef ENCRYPTION - thisitem = nclearto > netobuf ? nclearto : netobuf; -#else - thisitem = netobuf; -#endif - - while ((next = nextitem(thisitem)) <= nbackp) { - thisitem = next; - } - - /* Now, thisitem is first before/at boundary. */ - -#ifdef ENCRYPTION - good = nclearto > netobuf ? nclearto : netobuf; -#else - good = netobuf; /* where the good bytes go */ -#endif - - while (nfrontp > thisitem) { - if (wewant(thisitem)) { - int length; - - next = thisitem; - do { - next = nextitem(next); - } while (wewant(next) && (nfrontp > next)); - length = next-thisitem; - memmove(good, thisitem, length); - good += length; - thisitem = next; - } else { - thisitem = nextitem(thisitem); - } - } - - nbackp = netobuf; - nfrontp = good; /* next byte to be sent */ - neturg = 0; -} /* end of netclear */ - -/* - * netflush - * Send as much data as possible to the network, - * handling requests for urgent data. - */ -void -netflush(void) -{ - int n; - extern int not42; - - if ((n = nfrontp - nbackp) > 0) { - DIAG(TD_REPORT, - { n += output_data("td: netflush %d chars\r\n", n); - }); -#ifdef ENCRYPTION - if (encrypt_output) { - char *s = nclearto ? nclearto : nbackp; - if (nfrontp - s > 0) { - (*encrypt_output)((unsigned char *)s, nfrontp-s); - nclearto = nfrontp; - } - } -#endif - /* - * if no urgent data, or if the other side appears to be an - * old 4.2 client (and thus unable to survive TCP urgent data), - * write the entire buffer in non-OOB mode. - */ -#if 1 /* remove this to make it work between solaris 2.6 and linux */ - if ((neturg == 0) || (not42 == 0)) { -#endif - n = write(net, nbackp, n); /* normal write */ -#if 1 /* remove this to make it work between solaris 2.6 and linux */ - } else { - n = neturg - nbackp; - /* - * In 4.2 (and 4.3) systems, there is some question about - * what byte in a sendOOB operation is the "OOB" data. - * To make ourselves compatible, we only send ONE byte - * out of band, the one WE THINK should be OOB (though - * we really have more the TCP philosophy of urgent data - * rather than the Unix philosophy of OOB data). - */ - if (n > 1) { - n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ - } else { - n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ - } - } -#endif - } - if (n < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) - return; - cleanup(0); - } - nbackp += n; -#ifdef ENCRYPTION - if (nbackp > nclearto) - nclearto = 0; -#endif - if (nbackp >= neturg) { - neturg = 0; - } - if (nbackp == nfrontp) { - nbackp = nfrontp = netobuf; -#ifdef ENCRYPTION - nclearto = 0; -#endif - } - return; -} - - -/* - * writenet - * - * Just a handy little function to write a bit of raw data to the net. - * It will force a transmit of the buffer if necessary - * - * arguments - * ptr - A pointer to a character string to write - * len - How many bytes to write - */ -void -writenet(unsigned char *ptr, int len) -{ - /* flush buffer if no room for new data) */ - while ((&netobuf[BUFSIZ] - nfrontp) < len) { - /* if this fails, don't worry, buffer is a little big */ - netflush(); - } - - memmove(nfrontp, ptr, len); - nfrontp += len; -} - - -/* - * miscellaneous functions doing a variety of little jobs follow ... - */ - - -void fatal(int f, char *msg) -{ - char buf[BUFSIZ]; - - snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg); -#ifdef ENCRYPTION - if (encrypt_output) { - /* - * Better turn off encryption first.... - * Hope it flushes... - */ - encrypt_send_end(); - netflush(); - } -#endif - write(f, buf, (int)strlen(buf)); - sleep(1); /*XXX*/ - exit(1); -} - -void -fatalperror_errno(int f, const char *msg, int error) -{ - char buf[BUFSIZ]; - - snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(error)); - fatal(f, buf); -} - -void -fatalperror(int f, const char *msg) -{ - fatalperror_errno(f, msg, errno); -} - -char editedhost[32]; - -void edithost(char *pat, char *host) -{ - char *res = editedhost; - - if (!pat) - pat = ""; - while (*pat) { - switch (*pat) { - - case '#': - if (*host) - host++; - break; - - case '@': - if (*host) - *res++ = *host++; - break; - - default: - *res++ = *pat; - break; - } - if (res == &editedhost[sizeof editedhost - 1]) { - *res = '\0'; - return; - } - pat++; - } - if (*host) - strlcpy (res, host, - sizeof editedhost - (res - editedhost)); - else - *res = '\0'; - editedhost[sizeof editedhost - 1] = '\0'; -} - -static char *putlocation; - -void -putstr(char *s) -{ - - while (*s) - putchr(*s++); -} - -void -putchr(int cc) -{ - *putlocation++ = cc; -} - -/* - * This is split on two lines so that SCCS will not see the M - * between two % signs and expand it... - */ -static char fmtstr[] = { "%l:%M" "%P on %A, %d %B %Y" }; - -void putf(char *cp, char *where) -{ -#ifdef HAVE_UNAME - struct utsname name; -#endif - char *slash; - time_t t; - char db[100]; - - /* if we don't have uname, set these to sensible values */ - char *sysname = "Unix", - *machine = "", - *release = "", - *version = ""; - -#ifdef HAVE_UNAME - uname(&name); - sysname=name.sysname; - machine=name.machine; - release=name.release; - version=name.version; -#endif - - putlocation = where; - - while (*cp) { - if (*cp != '%') { - putchr(*cp++); - continue; - } - switch (*++cp) { - - case 't': -#ifdef STREAMSPTY - /* names are like /dev/pts/2 -- we want pts/2 */ - slash = strchr(line+1, '/'); -#else - slash = strrchr(line, '/'); -#endif - if (slash == (char *) 0) - putstr(line); - else - putstr(&slash[1]); - break; - - case 'h': - putstr(editedhost); - break; - - case 's': - putstr(sysname); - break; - - case 'm': - putstr(machine); - break; - - case 'r': - putstr(release); - break; - - case 'v': - putstr(version); - break; - - case 'd': - time(&t); - strftime(db, sizeof(db), fmtstr, localtime(&t)); - putstr(db); - break; - - case '%': - putchr('%'); - break; - } - cp++; - } -} - -#ifdef DIAGNOSTICS -/* - * Print telnet options and commands in plain text, if possible. - */ -void -printoption(char *fmt, int option) -{ - if (TELOPT_OK(option)) - output_data("%s %s\r\n", - fmt, - TELOPT(option)); - else if (TELCMD_OK(option)) - output_data("%s %s\r\n", - fmt, - TELCMD(option)); - else - output_data("%s %d\r\n", - fmt, - option); - return; -} - -void -printsub(int direction, unsigned char *pointer, int length) - /* '<' or '>' */ - /* where suboption data sits */ - /* length of suboption data */ -{ - int i = 0; -#ifdef AUTHENTICATION - unsigned char buf[512]; -#endif - - if (!(diagnostic & TD_OPTIONS)) - return; - - if (direction) { - output_data("td: %s suboption ", - direction == '<' ? "recv" : "send"); - if (length >= 3) { - int j; - - i = pointer[length-2]; - j = pointer[length-1]; - - if (i != IAC || j != SE) { - output_data("(terminated by "); - if (TELOPT_OK(i)) - output_data("%s ", - TELOPT(i)); - else if (TELCMD_OK(i)) - output_data("%s ", - TELCMD(i)); - else - output_data("%d ", - i); - if (TELOPT_OK(j)) - output_data("%s", - TELOPT(j)); - else if (TELCMD_OK(j)) - output_data("%s", - TELCMD(j)); - else - output_data("%d", - j); - output_data(", not IAC SE!) "); - } - } - length -= 2; - } - if (length < 1) { - output_data("(Empty suboption??\?)"); - return; - } - switch (pointer[0]) { - case TELOPT_TTYPE: - output_data("TERMINAL-TYPE "); - switch (pointer[1]) { - case TELQUAL_IS: - output_data("IS \"%.*s\"", - length-2, - (char *)pointer+2); - break; - case TELQUAL_SEND: - output_data("SEND"); - break; - default: - output_data("- unknown qualifier %d (0x%x).", - pointer[1], pointer[1]); - } - break; - case TELOPT_TSPEED: - output_data("TERMINAL-SPEED"); - if (length < 2) { - output_data(" (empty suboption??\?)"); - break; - } - switch (pointer[1]) { - case TELQUAL_IS: - output_data(" IS %.*s", length-2, (char *)pointer+2); - break; - default: - if (pointer[1] == 1) - output_data(" SEND"); - else - output_data(" %d (unknown)", pointer[1]); - for (i = 2; i < length; i++) { - output_data(" ?%d?", pointer[i]); - } - break; - } - break; - - case TELOPT_LFLOW: - output_data("TOGGLE-FLOW-CONTROL"); - if (length < 2) { - output_data(" (empty suboption??\?)"); - break; - } - switch (pointer[1]) { - case LFLOW_OFF: - output_data(" OFF"); - break; - case LFLOW_ON: - output_data(" ON"); - break; - case LFLOW_RESTART_ANY: - output_data(" RESTART-ANY"); - break; - case LFLOW_RESTART_XON: - output_data(" RESTART-XON"); - break; - default: - output_data(" %d (unknown)", - pointer[1]); - } - for (i = 2; i < length; i++) { - output_data(" ?%d?", - pointer[i]); - } - break; - - case TELOPT_NAWS: - output_data("NAWS"); - if (length < 2) { - output_data(" (empty suboption??\?)"); - break; - } - if (length == 2) { - output_data(" ?%d?", - pointer[1]); - break; - } - output_data(" %u %u(%u)", - pointer[1], - pointer[2], - (((unsigned int)pointer[1])<<8) + pointer[2]); - if (length == 4) { - output_data(" ?%d?", - pointer[3]); - break; - } - output_data(" %u %u(%u)", - pointer[3], - pointer[4], - (((unsigned int)pointer[3])<<8) + pointer[4]); - for (i = 5; i < length; i++) { - output_data(" ?%d?", - pointer[i]); - } - break; - - case TELOPT_LINEMODE: - output_data("LINEMODE "); - if (length < 2) { - output_data(" (empty suboption??\?)"); - break; - } - switch (pointer[1]) { - case WILL: - output_data("WILL "); - goto common; - case WONT: - output_data("WONT "); - goto common; - case DO: - output_data("DO "); - goto common; - case DONT: - output_data("DONT "); - common: - if (length < 3) { - output_data("(no option??\?)"); - break; - } - switch (pointer[2]) { - case LM_FORWARDMASK: - output_data("Forward Mask"); - for (i = 3; i < length; i++) { - output_data(" %x", pointer[i]); - } - break; - default: - output_data("%d (unknown)", - pointer[2]); - for (i = 3; i < length; i++) { - output_data(" %d", - pointer[i]); - } - break; - } - break; - - case LM_SLC: - output_data("SLC"); - for (i = 2; i < length - 2; i += 3) { - if (SLC_NAME_OK(pointer[i+SLC_FUNC])) - output_data(" %s", - SLC_NAME(pointer[i+SLC_FUNC])); - else - output_data(" %d", - pointer[i+SLC_FUNC]); - switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { - case SLC_NOSUPPORT: - output_data(" NOSUPPORT"); - break; - case SLC_CANTCHANGE: - output_data(" CANTCHANGE"); - break; - case SLC_VARIABLE: - output_data(" VARIABLE"); - break; - case SLC_DEFAULT: - output_data(" DEFAULT"); - break; - } - output_data("%s%s%s", - pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", - pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", - pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); - if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| - SLC_FLUSHOUT| SLC_LEVELBITS)) { - output_data("(0x%x)", - pointer[i+SLC_FLAGS]); - } - output_data(" %d;", - pointer[i+SLC_VALUE]); - if ((pointer[i+SLC_VALUE] == IAC) && - (pointer[i+SLC_VALUE+1] == IAC)) - i++; - } - for (; i < length; i++) { - output_data(" ?%d?", - pointer[i]); - } - break; - - case LM_MODE: - output_data("MODE "); - if (length < 3) { - output_data("(no mode??\?)"); - break; - } - { - char tbuf[32]; - snprintf(tbuf, - sizeof(tbuf), - "%s%s%s%s%s", - pointer[2]&MODE_EDIT ? "|EDIT" : "", - pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", - pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", - pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", - pointer[2]&MODE_ACK ? "|ACK" : ""); - output_data("%s", - tbuf[1] ? &tbuf[1] : "0"); - } - if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { - output_data(" (0x%x)", - pointer[2]); - } - for (i = 3; i < length; i++) { - output_data(" ?0x%x?", - pointer[i]); - } - break; - default: - output_data("%d (unknown)", - pointer[1]); - for (i = 2; i < length; i++) { - output_data(" %d", pointer[i]); - } - } - break; - - case TELOPT_STATUS: { - char *cp; - int j, k; - - output_data("STATUS"); - - switch (pointer[1]) { - default: - if (pointer[1] == TELQUAL_SEND) - output_data(" SEND"); - else - output_data(" %d (unknown)", - pointer[1]); - for (i = 2; i < length; i++) { - output_data(" ?%d?", - pointer[i]); - } - break; - case TELQUAL_IS: - output_data(" IS\r\n"); - - for (i = 2; i < length; i++) { - switch(pointer[i]) { - case DO: cp = "DO"; goto common2; - case DONT: cp = "DONT"; goto common2; - case WILL: cp = "WILL"; goto common2; - case WONT: cp = "WONT"; goto common2; - common2: - i++; - if (TELOPT_OK(pointer[i])) - output_data(" %s %s", - cp, - TELOPT(pointer[i])); - else - output_data(" %s %d", - cp, - pointer[i]); - - output_data("\r\n"); - break; - - case SB: - output_data(" SB "); - i++; - j = k = i; - while (j < length) { - if (pointer[j] == SE) { - if (j+1 == length) - break; - if (pointer[j+1] == SE) - j++; - else - break; - } - pointer[k++] = pointer[j++]; - } - printsub(0, &pointer[i], k - i); - if (i < length) { - output_data(" SE"); - i = j; - } else - i = j - 1; - - output_data("\r\n"); - - break; - - default: - output_data(" %d", - pointer[i]); - break; - } - } - break; - } - break; - } - - case TELOPT_XDISPLOC: - output_data("X-DISPLAY-LOCATION "); - switch (pointer[1]) { - case TELQUAL_IS: - output_data("IS \"%.*s\"", - length-2, - (char *)pointer+2); - break; - case TELQUAL_SEND: - output_data("SEND"); - break; - default: - output_data("- unknown qualifier %d (0x%x).", - pointer[1], pointer[1]); - } - break; - - case TELOPT_NEW_ENVIRON: - output_data("NEW-ENVIRON "); - goto env_common1; - case TELOPT_OLD_ENVIRON: - output_data("OLD-ENVIRON"); - env_common1: - switch (pointer[1]) { - case TELQUAL_IS: - output_data("IS "); - goto env_common; - case TELQUAL_SEND: - output_data("SEND "); - goto env_common; - case TELQUAL_INFO: - output_data("INFO "); - env_common: - { - int noquote = 2; - for (i = 2; i < length; i++ ) { - switch (pointer[i]) { - case NEW_ENV_VAR: - output_data("\" VAR " + noquote); - noquote = 2; - break; - - case NEW_ENV_VALUE: - output_data("\" VALUE " + noquote); - noquote = 2; - break; - - case ENV_ESC: - output_data("\" ESC " + noquote); - noquote = 2; - break; - - case ENV_USERVAR: - output_data("\" USERVAR " + noquote); - noquote = 2; - break; - - default: - if (isprint(pointer[i]) && pointer[i] != '"') { - if (noquote) { - output_data ("\""); - noquote = 0; - } - output_data ("%c", pointer[i]); - } else { - output_data("\" %03o " + noquote, - pointer[i]); - noquote = 2; - } - break; - } - } - if (!noquote) - output_data ("\""); - break; - } - } - break; - -#ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - output_data("AUTHENTICATION"); - - if (length < 2) { - output_data(" (empty suboption??\?)"); - break; - } - switch (pointer[1]) { - case TELQUAL_REPLY: - case TELQUAL_IS: - output_data(" %s ", - (pointer[1] == TELQUAL_IS) ? - "IS" : "REPLY"); - if (AUTHTYPE_NAME_OK(pointer[2])) - output_data("%s ", - AUTHTYPE_NAME(pointer[2])); - else - output_data("%d ", - pointer[2]); - if (length < 3) { - output_data("(partial suboption??\?)"); - break; - } - output_data("%s|%s", - ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? - "CLIENT" : "SERVER", - ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? - "MUTUAL" : "ONE-WAY"); - - auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); - output_data("%s", - buf); - break; - - case TELQUAL_SEND: - i = 2; - output_data(" SEND "); - while (i < length) { - if (AUTHTYPE_NAME_OK(pointer[i])) - output_data("%s ", - AUTHTYPE_NAME(pointer[i])); - else - output_data("%d ", - pointer[i]); - if (++i >= length) { - output_data("(partial suboption??\?)"); - break; - } - output_data("%s|%s ", - ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? - "CLIENT" : "SERVER", - ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? - "MUTUAL" : "ONE-WAY"); - ++i; - } - break; - - case TELQUAL_NAME: - i = 2; - output_data(" NAME \"%.*s\"", - length - 2, - pointer); - break; - - default: - for (i = 2; i < length; i++) { - output_data(" ?%d?", - pointer[i]); - } - break; - } - break; -#endif - -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - output_data("ENCRYPT"); - if (length < 2) { - output_data(" (empty suboption?)"); - break; - } - switch (pointer[1]) { - case ENCRYPT_START: - output_data(" START"); - break; - - case ENCRYPT_END: - output_data(" END"); - break; - - case ENCRYPT_REQSTART: - output_data(" REQUEST-START"); - break; - - case ENCRYPT_REQEND: - output_data(" REQUEST-END"); - break; - - case ENCRYPT_IS: - case ENCRYPT_REPLY: - output_data(" %s ", - (pointer[1] == ENCRYPT_IS) ? - "IS" : "REPLY"); - if (length < 3) { - output_data(" (partial suboption?)"); - break; - } - if (ENCTYPE_NAME_OK(pointer[2])) - output_data("%s ", - ENCTYPE_NAME(pointer[2])); - else - output_data(" %d (unknown)", - pointer[2]); - - encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); - output_data("%s", - buf); - break; - - case ENCRYPT_SUPPORT: - i = 2; - output_data(" SUPPORT "); - while (i < length) { - if (ENCTYPE_NAME_OK(pointer[i])) - output_data("%s ", - ENCTYPE_NAME(pointer[i])); - else - output_data("%d ", - pointer[i]); - i++; - } - break; - - case ENCRYPT_ENC_KEYID: - output_data(" ENC_KEYID %d", pointer[1]); - goto encommon; - - case ENCRYPT_DEC_KEYID: - output_data(" DEC_KEYID %d", pointer[1]); - goto encommon; - - default: - output_data(" %d (unknown)", pointer[1]); - encommon: - for (i = 2; i < length; i++) { - output_data(" %d", pointer[i]); - } - break; - } - break; -#endif - - default: - if (TELOPT_OK(pointer[0])) - output_data("%s (unknown)", - TELOPT(pointer[0])); - else - output_data("%d (unknown)", - pointer[i]); - for (i = 1; i < length; i++) { - output_data(" %d", pointer[i]); - } - break; - } - output_data("\r\n"); -} - -/* - * Dump a data buffer in hex and ascii to the output data stream. - */ -void -printdata(char *tag, char *ptr, int cnt) -{ - int i; - char xbuf[30]; - - while (cnt) { - /* flush net output buffer if no room for new data) */ - if ((&netobuf[BUFSIZ] - nfrontp) < 80) { - netflush(); - } - - /* add a line of output */ - output_data("%s: ", tag); - for (i = 0; i < 20 && cnt; i++) { - output_data("%02x", *ptr); - if (isprint(*ptr)) { - xbuf[i] = *ptr; - } else { - xbuf[i] = '.'; - } - if (i % 2) { - output_data(" "); - } - cnt--; - ptr++; - } - xbuf[i] = '\0'; - output_data(" %s\r\n", xbuf); - } -} -#endif /* DIAGNOSTICS */ |