aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-10 14:55:53 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-10 14:55:53 -0400
commitd7dbd335bfc76ace0a0d3a13a5ba83b7c6734bfc (patch)
tree1414bdf4d635656a51463888061af11d8ca9890c
parentd88d199f23088ac1c3d7696374b0a1c1c1c18358 (diff)
downloadapple_cmds-d7dbd335bfc76ace0a0d3a13a5ba83b7c6734bfc.tar.gz
apple_cmds-d7dbd335bfc76ace0a0d3a13a5ba83b7c6734bfc.tar.zst
apple_cmds-d7dbd335bfc76ace0a0d3a13a5ba83b7c6734bfc.zip
libtelnet-13
-rw-r--r--lib/libtelnet/LICENSE79
-rw-r--r--lib/libtelnet/auth-proto.h110
-rw-r--r--lib/libtelnet/auth.c631
-rw-r--r--lib/libtelnet/auth.h83
-rw-r--r--lib/libtelnet/enc-proto.h126
-rw-r--r--lib/libtelnet/enc_des.c675
-rw-r--r--lib/libtelnet/encrypt.c961
-rw-r--r--lib/libtelnet/encrypt.h106
-rw-r--r--lib/libtelnet/forward.c70
-rw-r--r--lib/libtelnet/genget.c109
-rw-r--r--lib/libtelnet/getent.c82
-rw-r--r--lib/libtelnet/kerberos.c519
-rw-r--r--lib/libtelnet/kerberos5.c888
-rw-r--r--lib/libtelnet/key-proto.h65
-rw-r--r--lib/libtelnet/krb4encpwd.c430
-rw-r--r--lib/libtelnet/libtelnet.plist22
-rw-r--r--lib/libtelnet/libtelnet.xcodeproj/project.pbxproj313
-rw-r--r--lib/libtelnet/misc-proto.h80
-rw-r--r--lib/libtelnet/misc.c114
-rw-r--r--lib/libtelnet/misc.h42
-rw-r--r--lib/libtelnet/pk.c269
-rw-r--r--lib/libtelnet/pk.h59
-rw-r--r--lib/libtelnet/read_password.c153
-rw-r--r--lib/libtelnet/rsaencpwd.c475
-rw-r--r--lib/libtelnet/sra.c604
25 files changed, 7065 insertions, 0 deletions
diff --git a/lib/libtelnet/LICENSE b/lib/libtelnet/LICENSE
new file mode 100644
index 0000000..f35662f
--- /dev/null
+++ b/lib/libtelnet/LICENSE
@@ -0,0 +1,79 @@
+Copyright (c) 1991, 1992, 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. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+This product includes software developed by the University of
+California, Berkeley and its contributors.
+4. 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.
+
+=====
+
+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.
+
+=====
+
+Copyright (c) 1991, 1993
+ Dave Safford. 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.
diff --git a/lib/libtelnet/auth-proto.h b/lib/libtelnet/auth-proto.h
new file mode 100644
index 0000000..6f0346a
--- /dev/null
+++ b/lib/libtelnet/auth-proto.h
@@ -0,0 +1,110 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * @(#)auth-proto.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD: src/crypto/telnet/libtelnet/auth-proto.h,v 1.3.2.2 2002/04/13 10:59:07 markm Exp $
+ */
+
+/*
+ * 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.
+ */
+
+#ifdef AUTHENTICATION
+
+Authenticator *findauthenticator(int, int);
+
+void auth_init(const char *, int);
+int auth_cmd(int, char **);
+void auth_request(void);
+void auth_send(unsigned char *, int);
+void auth_send_retry(void);
+void auth_is(unsigned char *, int);
+void auth_reply(unsigned char *, int);
+void auth_finished(Authenticator *, int);
+int auth_wait(char *);
+void auth_disable_name(char *);
+void auth_gen_printsub(unsigned char *, int, unsigned char *, int);
+void auth_name(unsigned char *, int);
+void auth_printsub(unsigned char *, int, unsigned char *, int);
+int auth_sendname(unsigned char *, int);
+void auth_encrypt_user(char *);
+int auth_disable(char *);
+int auth_enable(char *);
+int auth_togdebug(int);
+int auth_status(void);
+
+int getauthmask(char *, int *);
+
+#ifdef KRB4
+int kerberos4_init(Authenticator *, int);
+int kerberos4_send(Authenticator *);
+void kerberos4_is(Authenticator *, unsigned char *, int);
+void kerberos4_reply(Authenticator *, unsigned char *, int);
+int kerberos4_status(Authenticator *, char *, int);
+void kerberos4_printsub(unsigned char *, int, unsigned char *, int);
+#endif
+
+#ifdef KRB5
+int kerberos5_init(Authenticator *, int);
+int kerberos5_send(Authenticator *);
+void kerberos5_is(Authenticator *, unsigned char *, int);
+void kerberos5_reply(Authenticator *, unsigned char *, int);
+int kerberos5_status(Authenticator *, char *, int level);
+void kerberos5_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
+
+#endif
diff --git a/lib/libtelnet/auth.c b/lib/libtelnet/auth.c
new file mode 100644
index 0000000..f10e6ec
--- /dev/null
+++ b/lib/libtelnet/auth.c
@@ -0,0 +1,631 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * $FreeBSD: src/crypto/telnet/libtelnet/auth.c,v 1.3.2.5 2002/04/13 10:59:07 markm Exp $
+ */
+
+#include <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/auth.c,v 1.3.2.5 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifndef lint
+static const char sccsid[] = "@(#)auth.c 8.3 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+/*
+ * 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.
+ */
+
+
+#ifdef AUTHENTICATION
+#define AUTH_NAMES
+#include <sys/types.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/telnet.h>
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc-proto.h"
+#include "auth-proto.h"
+
+#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0)
+
+#ifdef KRB4_ENCPWD
+extern int krb4encpwd_init();
+extern int krb4encpwd_send();
+extern int krb4encpwd_is();
+extern int krb4encpwd_reply();
+extern int krb4encpwd_status();
+extern int 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;
+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;
+
+int auth_onoff(char *type, int on);
+void auth_encrypt_user(char *name);
+
+/*
+ * Authentication types supported. Plese note that these are stored
+ * in priority order, i.e. try the first one first.
+ */
+Authenticator authenticators[] = {
+#ifdef KRB5
+# ifdef ENCRYPTION
+ { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
+ kerberos5_init,
+ kerberos5_send,
+ kerberos5_is,
+ kerberos5_reply,
+ kerberos5_status,
+ kerberos5_printsub },
+# endif /* ENCRYPTION */
+ { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
+ kerberos5_init,
+ kerberos5_send,
+ kerberos5_is,
+ kerberos5_reply,
+ kerberos5_status,
+ kerberos5_printsub },
+#endif
+#ifdef KRB4
+# ifdef ENCRYPTION
+ { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
+ kerberos4_init,
+ kerberos4_send,
+ kerberos4_is,
+ kerberos4_reply,
+ kerberos4_status,
+ kerberos4_printsub },
+# endif /* ENCRYPTION */
+ { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
+ kerberos4_init,
+ kerberos4_send,
+ 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
+#ifdef SRA
+ { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
+ sra_init,
+ sra_send,
+ sra_is,
+ sra_reply,
+ sra_status,
+ sra_printsub },
+
+#endif
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static Authenticator NoAuth = { 0, 0, 0, 0, 0, 0, 0, 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 (AUTHTYPE_NAME(x) && !strcasecmp(name, AUTHTYPE_NAME(x))) {
+ i_wont_support |= typemask(x);
+ break;
+ }
+ }
+}
+
+int
+getauthmask(char *type, int *maskp)
+{
+ int x;
+
+ if (AUTHTYPE_NAME(0) && !strcasecmp(type, AUTHTYPE_NAME(0))) {
+ *maskp = -1;
+ return(1);
+ }
+
+ for (x = 1; x < AUTHTYPE_CNT; ++x) {
+ if (AUTHTYPE_NAME(x) && !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;
+ 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 = (size_t)cnt > sizeof(_auth_send_data)
+ ? sizeof(_auth_send_data)
+ : cnt;
+ memmove((void *)_auth_send_data, (void *)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;
+ }
+ 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);
+}
+
+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)
+{
+ unsigned char savename[256];
+
+ if (cnt < 1) {
+ if (auth_debug_mode)
+ printf(">>>%s: Empty name in NAME\r\n", Name);
+ return;
+ }
+ if ((size_t)cnt > sizeof(savename) - 1) {
+ if (auth_debug_mode)
+ printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n",
+ Name, cnt, (u_int)sizeof(savename)-1);
+ return;
+ }
+ memmove((void *)savename, (void *)data, cnt);
+ savename[cnt] = '\0'; /* Null terminate */
+ if (auth_debug_mode)
+ printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
+#ifdef ENCRYPTION
+ auth_encrypt_user(savename);
+#endif
+}
+
+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;
+ 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 __unused)
+{
+ auth_finished(0, AUTH_REJECT);
+}
+
+int
+auth_wait(char *name)
+{
+ if (auth_debug_mode)
+ printf(">>>%s: in auth_wait.\r\n", Name);
+
+ if (Server && !authenticating)
+ return(0);
+
+ (void) signal(SIGALRM, auth_intr);
+ alarm(30);
+ while (!authenticated)
+ if (telnet_spin())
+ break;
+ alarm(0);
+ (void) 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, validuser);
+ return(validuser);
+}
+
+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++) {
+ sprintf((char *)tbuf, " %d", *data);
+ for (cp = tbuf; *cp && buflen > 0; --buflen)
+ *buf++ = *cp++;
+ if (buflen <= 0)
+ return;
+ }
+ *buf = '\0';
+}
+#endif
diff --git a/lib/libtelnet/auth.h b/lib/libtelnet/auth.h
new file mode 100644
index 0000000..557b037
--- /dev/null
+++ b/lib/libtelnet/auth.h
@@ -0,0 +1,83 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * @(#)auth.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD: src/crypto/telnet/libtelnet/auth.h,v 1.1.1.1.8.1 2002/04/13 10:59:07 markm Exp $
+ */
+
+/*
+ * 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.
+ */
+
+#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 *, int);
+ void (*printsub)(unsigned char *, int, unsigned char *, int);
+} Authenticator;
+
+#include "auth-proto.h"
+
+#define OPTS_FORWARD_CREDS 0x00000002
+#define OPTS_FORWARDABLE_CREDS 0x00000001
+
+extern int auth_debug_mode;
+#endif
diff --git a/lib/libtelnet/enc-proto.h b/lib/libtelnet/enc-proto.h
new file mode 100644
index 0000000..3c9ef88
--- /dev/null
+++ b/lib/libtelnet/enc-proto.h
@@ -0,0 +1,126 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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
+ * $FreeBSD: src/crypto/telnet/libtelnet/enc-proto.h,v 1.3.2.2 2002/04/13 10:59:07 markm Exp $
+ */
+
+/*
+ * 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.
+ */
+
+#ifdef ENCRYPTION
+void encrypt_init(const char *, int);
+Encryptions *findencryption(int);
+void encrypt_send_supprt(void);
+void encrypt_auto(int);
+void decrypt_auto(int);
+void encrypt_is(unsigned char *, int);
+void encrypt_reply(unsigned char *, int);
+void encrypt_start_input(int);
+void encrypt_session_key(Session_Key *, int);
+void encrypt_end_input(void);
+void encrypt_start_output(int);
+void encrypt_end_output(void);
+void encrypt_send_request_start(void);
+void encrypt_send_request_end(void);
+void encrypt_send_end(void);
+void encrypt_wait(void);
+void encrypt_send_support(void);
+void encrypt_send_keyid(int, const char *, int, int);
+void encrypt_start(unsigned char *, int);
+void encrypt_end(void);
+void encrypt_support(unsigned char *, int);
+void encrypt_request_start(unsigned char *, int);
+void encrypt_request_end(void);
+void encrypt_enc_keyid(unsigned char *, int);
+void encrypt_dec_keyid(unsigned char *, int);
+void encrypt_printsub(unsigned char *, int, unsigned char *, int);
+void encrypt_gen_printsub(unsigned char *, int, unsigned char *, int);
+void encrypt_display(void);
+
+void fb64_printsub(unsigned char *, int, unsigned char *, int, const char *);
+
+int EncryptEnable(char *, char *);
+int EncryptDisable(char *, char *);
+int EncryptStatus(void);
+int EncryptDebug(int);
+int EncryptVerbose(int);
+int EncryptAutoEnc(int);
+int EncryptAutoDec(int);
+
+void krbdes_encrypt(unsigned char *, int);
+int krbdes_decrypt(int);
+int krbdes_is(unsigned char *, int);
+int krbdes_reply(unsigned char *, int);
+void krbdes_init(int);
+int krbdes_start(int, int);
+void krbdes_session(Session_Key *, int);
+void krbdes_printsub(unsigned char *, int, unsigned char *, int);
+
+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 /* ENCRYPTION */
diff --git a/lib/libtelnet/enc_des.c b/lib/libtelnet/enc_des.c
new file mode 100644
index 0000000..c6d6ea6
--- /dev/null
+++ b/lib/libtelnet/enc_des.c
@@ -0,0 +1,675 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * $FreeBSD: src/crypto/telnet/libtelnet/enc_des.c,v 1.3.2.1 2002/04/13 10:59:07 markm Exp $
+ */
+
+#include <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/enc_des.c,v 1.3.2.1 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifndef lint
+static const char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+#ifdef ENCRYPTION
+# ifdef AUTHENTICATION
+#include <arpa/telnet.h>
+#include <des.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "encrypt.h"
+#include "key-proto.h"
+#include "misc-proto.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 fb {
+ Block krbdes_key;
+ Schedule krbdes_sched;
+ Block temp_feed;
+ unsigned char fb_feed[64];
+ int need_start;
+ int state[2];
+ int keyid[2];
+ int once;
+ struct stinfo {
+ Block str_output;
+ Block str_feed;
+ Block str_iv;
+ Block str_ikey;
+ Schedule str_sched;
+ int str_index;
+ int str_flagshift;
+ } streams[2];
+};
+
+static struct fb fb[2];
+
+struct keyidlist {
+ const 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(Block, 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(Block, struct stinfo *);
+int fb64_keyid(int, unsigned char *, int *, struct fb *);
+
+void
+cfb64_init(int server __unused)
+{
+ 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 __unused)
+{
+ 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((void *)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 __unused)
+{
+ size_t 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.
+ */
+ des_new_random_key(fbp->temp_feed);
+ des_ecb_encrypt((Block *)fbp->temp_feed, (Block *)fbp->temp_feed,
+ fbp->krbdes_sched, 1);
+ p = fbp->fb_feed + 3;
+ *p++ = ENCRYPT_IS;
+ p++;
+ *p++ = FB64_IV;
+ for (x = 0; x < sizeof(Block); ++x) {
+ if ((*p++ = fbp->temp_feed[x]) == IAC)
+ *p++ = IAC;
+ }
+ *p++ = IAC;
+ *p++ = SE;
+ printsub('>', &fbp->fb_feed[2], p - &fbp->fb_feed[2]);
+ 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(Block)) {
+ 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((void *)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]);
+ 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]);
+ 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, "\0", 1, 1);
+ break;
+
+ case FB64_IV_BAD:
+ memset(fbp->temp_feed, 0, sizeof(Block));
+ 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;
+ }
+ memmove((void *)fbp->krbdes_key, (void *)key->data, sizeof(Block));
+
+ 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) {
+ des_set_random_generator_seed(fbp->krbdes_key);
+ 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, const 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:
+ sprintf(lbuf, "%s_IV", type);
+ cp = lbuf;
+ goto common;
+
+ case FB64_IV_OK:
+ sprintf(lbuf, "%s_IV_OK", type);
+ cp = lbuf;
+ goto common;
+
+ case FB64_IV_BAD:
+ sprintf(lbuf, "%s_IV_BAD", type);
+ cp = lbuf;
+ goto common;
+
+ default:
+ sprintf(lbuf, " %d (unknown)", data[2]);
+ cp = lbuf;
+ common:
+ for (; (buflen > 0) && (*buf = *cp++); buf++)
+ buflen--;
+ for (i = 3; i < cnt; i++) {
+ sprintf(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(Block seed, struct stinfo *stp)
+{
+
+ memmove((void *)stp->str_iv, (void *)seed, sizeof(Block));
+ memmove((void *)stp->str_output, (void *)seed, sizeof(Block));
+
+ des_key_sched(stp->str_ikey, stp->str_sched);
+
+ stp->str_index = sizeof(Block);
+}
+
+void
+fb64_stream_key(Block key, struct stinfo *stp)
+{
+ memmove((void *)stp->str_ikey, (void *)key, sizeof(Block));
+ des_key_sched(key, stp->str_sched);
+
+ memmove((void *)stp->str_output, (void *)stp->str_iv, sizeof(Block));
+
+ stp->str_index = sizeof(Block);
+}
+
+/*
+ * 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 idx;
+
+ idx = stp->str_index;
+ while (c-- > 0) {
+ if (idx == sizeof(Block)) {
+ Block b;
+ des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1);
+ memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
+ idx = 0;
+ }
+
+ /* On encryption, we store (feed ^ data) which is cypher */
+ *s = stp->str_output[idx] = (stp->str_feed[idx] ^ *s);
+ s++;
+ idx++;
+ }
+ stp->str_index = idx;
+}
+
+int
+cfb64_decrypt(int data)
+{
+ struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1];
+ int idx;
+
+ 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);
+ }
+
+ idx = stp->str_index++;
+ if (idx == sizeof(Block)) {
+ Block b;
+ des_ecb_encrypt((Block *)stp->str_output, (Block *)b, stp->str_sched, 1);
+ memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
+ stp->str_index = 1; /* Next time will be 1 */
+ idx = 0; /* But now use 0 */
+ }
+
+ /* On decryption we store (data) which is cypher. */
+ stp->str_output[idx] = data;
+ return(data ^ stp->str_feed[idx]);
+}
+
+/*
+ * 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 idx;
+
+ idx = stp->str_index;
+ while (c-- > 0) {
+ if (idx == sizeof(Block)) {
+ Block b;
+ des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1);
+ memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
+ idx = 0;
+ }
+ *s++ ^= stp->str_feed[idx];
+ idx++;
+ }
+ stp->str_index = idx;
+}
+
+int
+ofb64_decrypt(int data)
+{
+ struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1];
+ int idx;
+
+ 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);
+ }
+
+ idx = stp->str_index++;
+ if (idx == sizeof(Block)) {
+ Block b;
+ des_ecb_encrypt((Block *)stp->str_feed, (Block *)b, stp->str_sched, 1);
+ memmove((void *)stp->str_feed, (void *)b, sizeof(Block));
+ stp->str_index = 1; /* Next time will be 1 */
+ idx = 0; /* But now use 0 */
+ }
+
+ return(data ^ stp->str_feed[idx]);
+}
+# endif /* AUTHENTICATION */
+#endif /* ENCRYPTION */
diff --git a/lib/libtelnet/encrypt.c b/lib/libtelnet/encrypt.c
new file mode 100644
index 0000000..4295fad
--- /dev/null
+++ b/lib/libtelnet/encrypt.c
@@ -0,0 +1,961 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/encrypt.c,v 1.3.2.2 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef lint
+#if 0
+static const char sccsid[] = "@(#)encrypt.c 8.2 (Berkeley) 5/30/95";
+#endif
+#endif /* not lint */
+
+/*
+ * 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.
+ */
+
+#ifdef ENCRYPTION
+
+#define ENCRYPT_NAMES
+#include <arpa/telnet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "encrypt.h"
+#include "misc.h"
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+/*
+ * These functions pointers point to the current routines
+ * for encrypting and decrypting data.
+ */
+void (*encrypt_output)(unsigned char *, int);
+int (*decrypt_input)(int);
+
+int EncryptType(char *type, char *mode);
+int EncryptStart(char *mode);
+int EncryptStop(char *mode);
+int EncryptStartInput(void);
+int EncryptStartOutput(void);
+int EncryptStopInput(void);
+int EncryptStopOutput(void);
+
+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 = 0
+ | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
+ |0;
+static long i_support_decrypt = 0
+ | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
+ |0;
+
+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[] = {
+ { "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 },
+ { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 & (unsigned)typemask(type)))
+ return(0);
+ while (ep->type && ep->type != type)
+ ++ep;
+ return(ep->type ? ep : 0);
+}
+
+static Encryptions *
+finddecryption(int type)
+{
+ Encryptions *ep = encryptions;
+
+ if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & (unsigned)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 },
+};
+
+static void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len);
+
+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;
+
+ 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;
+}
+
+static 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((char **)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((char **)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)
+{
+ if (encrypt_output)
+ printf("Currently encrypting output with %s\r\n",
+ ENCTYPE_NAME(encrypt_mode));
+ if (decrypt_input)
+ printf("Currently decrypting input with %s\r\n",
+ ENCTYPE_NAME(decrypt_mode));
+}
+
+int
+EncryptStatus(void)
+{
+ 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));
+ }
+ 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));
+ }
+ 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();
+ 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);
+}
+
+int
+EncryptVerbose(int on)
+{
+ if (on < 0)
+ encrypt_verbose ^= 1;
+ else
+ encrypt_verbose = 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 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 __unused, int cnt __unused)
+{
+ 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 __unused, int cnt __unused)
+{
+ 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 };
+
+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_keyid(struct key_info *kp, unsigned char *keyid, int len)
+{
+ Encryptions *ep;
+ int dir = kp->dir;
+ int ret = 0;
+
+ if (len > MAXKEYLEN)
+ len = MAXKEYLEN;
+
+ 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;
+ memmove(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_send_keyid(int dir, const 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];
+ memmove(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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+}
+
+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++) {
+ sprintf(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 /* ENCRYPTION */
diff --git a/lib/libtelnet/encrypt.h b/lib/libtelnet/encrypt.h
new file mode 100644
index 0000000..3e262b5
--- /dev/null
+++ b/lib/libtelnet/encrypt.h
@@ -0,0 +1,106 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * @(#)encrypt.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD: src/crypto/telnet/libtelnet/encrypt.h,v 1.4.2.1 2002/04/13 10:59:07 markm Exp $
+ */
+
+/*
+ * 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.
+ */
+
+#ifdef ENCRYPTION
+# ifndef __ENCRYPTION__
+# define __ENCRYPTION__
+
+#define DIR_DECRYPT 1
+#define DIR_ENCRYPT 2
+
+#include <des.h>
+typedef unsigned char Block[8];
+typedef unsigned char *BlockT;
+#if 0
+typedef struct { Block __; } Schedule[16];
+#else
+#define Schedule des_key_schedule
+#endif
+
+#define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \
+ key[4] | key[5] | key[6] | key[7])
+
+#define SAMEKEY(k1, k2) (!bcmp((void *)k1, (void *)k2, sizeof(Block)))
+
+typedef struct {
+ short type;
+ int length;
+ unsigned char *data;
+} Session_Key;
+
+typedef struct {
+ const 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 /* __ENCRYPTION__ */
+#endif /* ENCRYPTION */
diff --git a/lib/libtelnet/forward.c b/lib/libtelnet/forward.c
new file mode 100644
index 0000000..1a3d365
--- /dev/null
+++ b/lib/libtelnet/forward.c
@@ -0,0 +1,70 @@
+/*
+ * appl/telnet/libtelnet/forward.c
+ */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/* General-purpose forwarding routines. These routines may be put into */
+/* libkrb5.a to allow widespread use */
+
+#if defined(KERBEROS) || defined(KRB5)
+#include <stdio.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <krb5.h>
+
+extern char *line; /* see sys_term.c */
+
+/* Decode, decrypt and store the forwarded creds in the local ccache. */
+krb5_error_code
+rd_and_store_for_creds(context, auth_context, inbuf, ticket)
+ krb5_context context;
+ krb5_auth_context auth_context;
+ krb5_data *inbuf;
+ krb5_ticket *ticket;
+{
+ krb5_creds **creds;
+ krb5_error_code retval;
+ char ccname[35];
+ krb5_ccache ccache = NULL;
+#if 0
+ char *tty;
+#endif
+
+ if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
+ return(retval);
+
+ sprintf(ccname, "FILE:/tmp/krb5cc_p%d", getpid());
+ setenv("KRB5CCNAME", ccname, 1);
+
+ if ((retval = krb5_cc_resolve(context, ccname, &ccache)))
+ goto cleanup;
+
+ if ((retval = krb5_cc_initialize(context, ccache, ticket->enc_part2->client)))
+ goto cleanup;
+
+ if ((retval = krb5_cc_store_cred(context, ccache, *creds)))
+ goto cleanup;
+
+cleanup:
+ krb5_free_creds(context, *creds);
+ return retval;
+}
+
+#endif /* defined(KRB5) && defined(FORWARD) */
diff --git a/lib/libtelnet/genget.c b/lib/libtelnet/genget.c
new file mode 100644
index 0000000..9d4e164
--- /dev/null
+++ b/lib/libtelnet/genget.c
@@ -0,0 +1,109 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/genget.c,v 1.2.8.2 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef lint
+#if 0
+static const char sccsid[] = "@(#)genget.c 8.2 (Berkeley) 5/30/95";
+#endif
+#endif /* not lint */
+
+
+#include <ctype.h>
+
+#include "misc-proto.h"
+
+#define LOWER(x) (isupper(x) ? tolower(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, const 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)
+{
+ 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(char **s)
+{
+ return(s == &ambiguous);
+}
diff --git a/lib/libtelnet/getent.c b/lib/libtelnet/getent.c
new file mode 100644
index 0000000..99bebbc
--- /dev/null
+++ b/lib/libtelnet/getent.c
@@ -0,0 +1,82 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/getent.c,v 1.2.6.2 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)getent.c 8.2 (Berkeley) 12/15/93";
+#endif
+#endif /* not lint */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "misc-proto.h"
+
+static char *area;
+static char gettytab[] = "/etc/gettytab";
+
+/*ARGSUSED*/
+int
+getent(char *cp __unused, const char *name)
+{
+ int retval;
+ char *tempnam, *dba[2] = { gettytab, NULL };
+
+ tempnam = strdup(name);
+ retval = cgetent(&area, dba, tempnam) == 0 ? 1 : 0;
+ free(tempnam);
+ return(retval);
+}
+
+/*ARGSUSED*/
+char *
+Getstr(const char *id, char **cpp __unused)
+{
+ int retval;
+ char *answer, *tempid;
+
+ tempid = strdup(id);
+ retval = cgetstr(area, tempid, &answer);
+ free(tempid);
+ return((retval > 0) ? answer : NULL);
+}
diff --git a/lib/libtelnet/kerberos.c b/lib/libtelnet/kerberos.c
new file mode 100644
index 0000000..0cd9648
--- /dev/null
+++ b/lib/libtelnet/kerberos.c
@@ -0,0 +1,519 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/kerberos.c,v 1.3.2.1 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifndef lint
+static const char sccsid[] = "@(#)kerberos.c 8.3 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+/*
+ * 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.
+ */
+
+#ifdef KRB4
+#include <sys/types.h>
+#include <arpa/telnet.h>
+#include <des.h> /* BSD wont include this in krb.h, so we do it here */
+#include <krb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+int kerberos4_cksum(unsigned char *, int);
+int kuserok(AUTH_DAT *, char *);
+
+extern int auth_debug_mode;
+
+static unsigned char str_data[1024] = { 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. */
+
+static KTEXT_ST auth;
+static char name[ANAME_SZ];
+static AUTH_DAT adat = { 0, "", "", "", 0, {}, 0, 0, 0, { 0, "", 0 } };
+#ifdef ENCRYPTION
+static Block session_key = { 0 };
+static des_key_schedule sched;
+static Block challenge = { 0 };
+#endif /* ENCRYPTION */
+
+static char krb_service_name[] = "rcmd";
+static char empty[] = "";
+
+static int
+Data(Authenticator *ap, int type, const unsigned char *d, int c)
+{
+ unsigned char *p = str_data + 4;
+ const unsigned char *cd = 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(net_write(str_data, p - str_data));
+}
+
+int
+kerberos4_init(Authenticator *ap __unused, 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;
+
+int
+kerberos4_send(Authenticator *ap)
+{
+ KTEXT_ST lauth;
+ char instance[INST_SZ];
+ char *realm;
+ CREDENTIALS cred;
+ int r;
+
+ printf("[ Trying KERBEROS4 ... ]\n");
+ if (!UserNameRequested) {
+ if (auth_debug_mode) {
+ printf("Kerberos V4: no user name supplied\r\n");
+ }
+ return(0);
+ }
+
+ memset(instance, 0, sizeof(instance));
+
+ if ((realm = krb_get_phost(RemoteHostName)))
+ strncpy(instance, realm, sizeof(instance));
+
+ instance[sizeof(instance)-1] = '\0';
+
+ realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
+
+ if (!realm) {
+ printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
+ return(0);
+ }
+ if ((r = krb_mk_req(&lauth, krb_service_name, instance, realm, 0L))) {
+ printf("mk_req failed: %s\r\n", krb_err_txt[r]);
+ return(0);
+ }
+ if ((r = krb_get_cred(krb_service_name, instance, realm, &cred))) {
+ printf("get_cred failed: %s\r\n", krb_err_txt[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", lauth.length);
+ if (!Data(ap, KRB_AUTH, (void *)lauth.dat, lauth.length)) {
+ if (auth_debug_mode)
+ printf("Not enough room for authentication data\r\n");
+ return(0);
+ }
+#ifdef ENCRYPTION
+ /*
+ * If we are doing mutual authentication, get set up to send
+ * the challenge, and verify it when the response comes back.
+ */
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ register int i;
+
+ des_key_sched(cred.session, sched);
+ 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);
+ /*
+ * Increment the challenge by 1, and encrypt it for
+ * later comparison.
+ */
+ for (i = 7; i >= 0; --i) {
+ register int x;
+ x = (unsigned int)challenge[i] + 1;
+ challenge[i] = x; /* ignore overflow */
+ if (x < 256) /* if no overflow, all done */
+ break;
+ }
+ des_ecb_encrypt(&challenge, &challenge, sched, 1);
+ }
+#endif /* ENCRYPTION */
+
+ if (auth_debug_mode) {
+ printf("CK: %d:", kerberos4_cksum(lauth.dat, lauth.length));
+ printd(lauth.dat, lauth.length);
+ printf("\r\n");
+ printf("Sent Kerberos V4 credentials to server\r\n");
+ }
+ return(1);
+}
+
+void
+kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
+{
+#ifdef ENCRYPTION
+ Session_Key skey;
+ Block datablock;
+#endif /* ENCRYPTION */
+ char realm[REALM_SZ];
+ char instance[INST_SZ];
+ int r;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB_AUTH:
+ if (krb_get_lrealm(realm, 1) != KSUCCESS) {
+ Data(ap, KRB_REJECT, "No local V4 Realm.", -1);
+ auth_finished(ap, AUTH_REJECT);
+ if (auth_debug_mode)
+ printf("No local realm\r\n");
+ return;
+ }
+ memmove((void *)auth.dat, (void *)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");
+ }
+ instance[0] = '*'; instance[1] = 0;
+ if ((r = krb_rd_req(&auth, krb_service_name,
+ instance, 0, &adat, empty))) {
+ if (auth_debug_mode)
+ printf("Kerberos failed him as %s\r\n", name);
+ Data(ap, KRB_REJECT, krb_err_txt[r], -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+#ifdef ENCRYPTION
+ memmove((void *)session_key, (void *)adat.session, sizeof(Block));
+#endif /* ENCRYPTION */
+ strncpy (name, adat.pname, ANAME_SZ-1);
+ name[ANAME_SZ-1] = '\0';
+
+ if (UserNameRequested && !kuserok(&adat, UserNameRequested))
+ Data(ap, KRB_ACCEPT, NULL, 0);
+ else
+ Data(ap, KRB_REJECT, "user is not authorized", -1);
+ auth_finished(ap, AUTH_USER);
+ break;
+
+ case KRB_CHALLENGE:
+#ifndef ENCRYPTION
+ Data(ap, KRB_RESPONSE, NULL, 0);
+#else /* ENCRYPTION */
+ if (!VALIDKEY(session_key)) {
+ /*
+ * We don't have a valid session key, so just
+ * send back a response with an empty session
+ * key.
+ */
+ Data(ap, KRB_RESPONSE, NULL, 0);
+ break;
+ }
+
+ /*
+ * Initialize the random number generator since it's
+ * used later on by the encryption routine.
+ */
+ des_init_random_number_generator(session_key);
+ des_key_sched(session_key, sched);
+ memmove((void *)datablock, (void *)data, sizeof(Block));
+ /*
+ * Take the received encrypted challenge, and encrypt
+ * it again to get a unique session_key for the
+ * ENCRYPT option.
+ */
+ des_ecb_encrypt(&datablock, &session_key, sched, 1);
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = session_key;
+ encrypt_session_key(&skey, 1);
+ /*
+ * Now decrypt the received encrypted challenge,
+ * increment by one, re-encrypt it and send it back.
+ */
+ des_ecb_encrypt(&datablock, &challenge, sched, 0);
+ for (r = 7; r >= 0; r--) {
+ register int t;
+ t = (unsigned int)challenge[r] + 1;
+ challenge[r] = t; /* ignore overflow */
+ if (t < 256) /* if no overflow, all done */
+ break;
+ }
+ des_ecb_encrypt(&challenge, &challenge, sched, 1);
+ Data(ap, KRB_RESPONSE, challenge, sizeof(challenge));
+#endif /* ENCRYPTION */
+ break;
+
+ default:
+ if (auth_debug_mode)
+ printf("Unknown Kerberos option %d\r\n", data[-1]);
+ Data(ap, KRB_REJECT, NULL, 0);
+ break;
+ }
+}
+
+void
+kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt)
+{
+#ifdef ENCRYPTION
+ Session_Key skey;
+#endif /* ENCRYPTION */
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB_REJECT:
+ if (cnt > 0) {
+ printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n",
+ cnt, data);
+ } else
+ printf("[ Kerberos V4 refuses authentication ]\r\n");
+ auth_send_retry();
+ return;
+ case KRB_ACCEPT:
+ printf("[ Kerberos V4 accepts you ]\n");
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ /*
+ * Send over the encrypted challenge.
+ */
+#ifndef ENCRYPTION
+ Data(ap, KRB_CHALLENGE, NULL, 0);
+#else /* ENCRYPTION */
+ 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);
+#endif /* ENCRYPTION */
+ return;
+ }
+ auth_finished(ap, AUTH_USER);
+ return;
+ case KRB_RESPONSE:
+#ifdef ENCRYPTION
+ /*
+ * Verify that the response to the challenge is correct.
+ */
+ if ((cnt != sizeof(Block)) ||
+ (0 != memcmp((void *)data, (void *)challenge,
+ sizeof(challenge))))
+ {
+#endif /* ENCRYPTION */
+ printf("[ Kerberos V4 challenge failed!!! ]\r\n");
+ auth_send_retry();
+ return;
+#ifdef ENCRYPTION
+ }
+ printf("[ Kerberos V4 challenge successful ]\r\n");
+ auth_finished(ap, AUTH_USER);
+#endif /* ENCRYPTION */
+ break;
+ default:
+ if (auth_debug_mode)
+ printf("Unknown Kerberos option %d\r\n", data[-1]);
+ return;
+ }
+}
+
+int
+kerberos4_status(Authenticator *ap __unused, char *nam, int level)
+{
+ if (level < AUTH_USER)
+ return(level);
+
+ if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
+ strcpy(nam, UserNameRequested);
+ 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)
+{
+ char lbuf[32];
+ register int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case KRB_REJECT: /* Rejected (reason might follow) */
+ strncpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB_ACCEPT: /* Accepted (name might follow) */
+ strncpy((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 */
+ strncpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB_CHALLENGE:
+ strncpy((char *)buf, " CHALLENGE", buflen);
+ goto common2;
+
+ case KRB_RESPONSE:
+ strncpy((char *)buf, " RESPONSE", buflen);
+ goto common2;
+
+ default:
+ sprintf(lbuf, " %d (unknown)", data[3]);
+ strncpy((char *)buf, lbuf, buflen);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ sprintf(lbuf, " %d", data[i]);
+ strncpy((char *)buf, lbuf, buflen);
+ 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)
+ do {
+ 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;
+ } while (n > 0);
+ return(ck);
+}
+#endif
diff --git a/lib/libtelnet/kerberos5.c b/lib/libtelnet/kerberos5.c
new file mode 100644
index 0000000..55c68ca
--- /dev/null
+++ b/lib/libtelnet/kerberos5.c
@@ -0,0 +1,888 @@
+/*
+ * appl/telnet/libtelnet/kerberos5.c
+ */
+
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/* based on @(#)kerberos5.c 8.1 (Berkeley) 6/4/93 */
+
+/*
+ * 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. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * 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.
+ */
+
+
+#ifdef KRB5
+#include <arpa/telnet.h>
+#include <stdio.h>
+#define KRB5_DEPRECATED 1 /* krb5_auth_con_getremotesubkey */
+#include <krb5.h>
+#include "com_err.h"
+#include <netdb.h>
+#include <ctype.h>
+#include <syslog.h>
+#include <sys/errno.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char *malloc();
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+extern int auth_debug_mode;
+extern int net;
+
+#ifdef FORWARD
+int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */
+
+void kerberos5_forward();
+krb5_error_code
+rd_and_store_for_creds(krb5_context context, krb5_auth_context auth_context, krb5_data *inbuf, krb5_ticket *ticket);
+
+#endif /* FORWARD */
+
+static unsigned char str_data[8192] = {IAC, SB, TELOPT_AUTHENTICATION, 0,
+ AUTHTYPE_KERBEROS_V5, };
+/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
+ TELQUAL_NAME, };*/
+
+#define AUTH_ENCRYPT_OFF 0
+#define AUTH_ENCRYPT_ON 4
+#define AUTH_ENCRYPT_MASK 4
+
+#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. */
+
+#ifdef FORWARD
+#define KRB_FORWARD 4 /* Forwarded credentials follow */
+#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */
+#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */
+#endif /* FORWARD */
+
+krb5_auth_context auth_context = 0;
+
+static krb5_data auth;
+ /* telnetd gets session key from here */
+static krb5_ticket * ticket = NULL;
+/* telnet matches the AP_REQ and AP_REP with this */
+
+/* some compilers can't hack void *, so we use the Kerberos krb5_pointer,
+ which is either void * or char *, depending on the compiler. */
+
+#define Voidptr krb5_pointer
+
+krb5_keyblock *session_key = 0;
+char * telnet_srvtab = NULL;
+char * telnet_krb5_realm = NULL;
+
+ static int
+Data(ap, type, d, c)
+ Authenticator *ap;
+ int type;
+ Voidptr d;
+ int c;
+{
+ unsigned char *p = str_data + 4;
+ unsigned char *cd = (unsigned char *)d;
+ size_t spaceleft = sizeof(str_data) - 4;
+
+ if (c == -1)
+ c = strlen((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;
+ spaceleft -= 3;
+ while (c-- > 0) {
+ if ((*p++ = *cd++) == IAC) {
+ *p++ = IAC;
+ spaceleft--;
+ }
+ if ((--spaceleft < 4) && c) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ *p++ = IAC;
+ *p++ = SE;
+ if (str_data[3] == TELQUAL_IS)
+ printsub('>', &str_data[2], p - &str_data[2]);
+ return(net_write(str_data, p - str_data));
+}
+
+krb5_context telnet_context = 0;
+int
+kerberos5_init(ap, server)
+ Authenticator *ap;
+ int server;
+{
+ krb5_error_code retval;
+
+ if (server)
+ str_data[3] = TELQUAL_REPLY;
+ else
+ str_data[3] = TELQUAL_IS;
+ if (telnet_context == 0) {
+ retval = krb5_init_context(&telnet_context);
+ if (retval)
+ return 0;
+ }
+ return(1);
+}
+
+void
+kerberos5_cleanup()
+{
+ krb5_error_code retval;
+ krb5_ccache ccache;
+ char *ccname;
+
+ if (telnet_context == 0)
+ return;
+
+ ccname = getenv("KRB5CCNAME");
+ if (ccname) {
+ retval = krb5_cc_resolve(telnet_context, ccname, &ccache);
+ if (!retval)
+ retval = krb5_cc_destroy(telnet_context, ccache);
+ }
+
+ krb5_free_context(telnet_context);
+ telnet_context = 0;
+}
+
+
+ int
+kerberos5_send(ap)
+ Authenticator *ap;
+{
+ krb5_error_code r;
+ krb5_ccache ccache;
+ krb5_creds creds; /* telnet gets session key from here */
+ krb5_creds * new_creds = 0;
+ int ap_opts;
+ char type_check[2];
+ krb5_data check_data;
+
+#ifdef ENCRYPTION
+ krb5_keyblock *newkey = 0;
+#endif /* ENCRYPTION */
+
+ if (!UserNameRequested) {
+ if (auth_debug_mode) {
+ printf(
+ "telnet: Kerberos V5: no user name supplied\r\n");
+ }
+ return(0);
+ }
+
+ if ((r = krb5_cc_default(telnet_context, &ccache))) {
+ if (auth_debug_mode) {
+ printf(
+ "telnet: Kerberos V5: could not get default ccache\r\n");
+ }
+ return(0);
+ }
+
+ memset((char *)&creds, 0, sizeof(creds));
+ if ((r = krb5_sname_to_principal(telnet_context, RemoteHostName,
+ "host", KRB5_NT_SRV_HST,
+ &creds.server))) {
+ if (auth_debug_mode)
+ printf("telnet: Kerberos V5: error while constructing service name: %s\r\n", error_message(r));
+ return(0);
+ }
+
+ if (telnet_krb5_realm != NULL) {
+ krb5_data rdata;
+
+ rdata.length = strlen(telnet_krb5_realm);
+ rdata.data = (char *) malloc(rdata.length + 1);
+ if (rdata.data == NULL) {
+ fprintf(stderr, "malloc failed\n");
+ return(0);
+ }
+ strcpy(rdata.data, telnet_krb5_realm);
+ krb5_princ_set_realm(telnet_context, creds.server, &rdata);
+ }
+
+ if ((r = krb5_cc_get_principal(telnet_context, ccache,
+ &creds.client))) {
+ if (auth_debug_mode) {
+ printf(
+ "telnet: Kerberos V5: failure on principal (%s)\r\n",
+ error_message(r));
+ }
+ krb5_free_cred_contents(telnet_context, &creds);
+ return(0);
+ }
+
+ creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
+ if ((r = krb5_get_credentials(telnet_context, 0,
+ ccache, &creds, &new_creds))) {
+ if (auth_debug_mode) {
+ printf(
+ "telnet: Kerberos V5: failure on credentials(%s)\r\n",
+ error_message(r));
+ }
+ krb5_free_cred_contents(telnet_context, &creds);
+ return(0);
+ }
+
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+ ap_opts = AP_OPTS_MUTUAL_REQUIRED;
+ else
+ ap_opts = 0;
+
+#ifdef ENCRYPTION
+ ap_opts |= AP_OPTS_USE_SUBKEY;
+#endif /* ENCRYPTION */
+
+ if (auth_context) {
+ krb5_auth_con_free(telnet_context, auth_context);
+ auth_context = 0;
+ }
+ if ((r = krb5_auth_con_init(telnet_context, &auth_context))) {
+ if (auth_debug_mode) {
+ printf("Kerberos V5: failed to init auth_context (%s)\r\n",
+ error_message(r));
+ }
+ return(0);
+ }
+
+ krb5_auth_con_setflags(telnet_context, auth_context,
+ KRB5_AUTH_CONTEXT_RET_TIME);
+
+ type_check[0] = ap->type;
+ type_check[1] = ap->way;
+ check_data.magic = KV5M_DATA;
+ check_data.length = 2;
+ check_data.data = (char *) &type_check;
+
+ r = krb5_mk_req_extended(telnet_context, &auth_context, ap_opts,
+ &check_data, new_creds, &auth);
+
+#ifdef ENCRYPTION
+ krb5_auth_con_getlocalsubkey(telnet_context, auth_context, &newkey);
+ if (session_key) {
+ krb5_free_keyblock(telnet_context, session_key);
+ session_key = 0;
+ }
+
+ if (newkey) {
+ /* keep the key in our private storage, but don't use it
+ yet---see kerberos5_reply() below */
+ if ((newkey->enctype != ENCTYPE_DES_CBC_CRC) &&
+ (newkey-> enctype != ENCTYPE_DES_CBC_MD5)) {
+ if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
+ (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
+ /* use the session key in credentials instead */
+ krb5_copy_keyblock(telnet_context,&new_creds->keyblock,
+ &session_key);
+ else
+ /* XXX ? */;
+ } else {
+ krb5_copy_keyblock(telnet_context, newkey, &session_key);
+ }
+ krb5_free_keyblock(telnet_context, newkey);
+ }
+#endif /* ENCRYPTION */
+ krb5_free_cred_contents(telnet_context, &creds);
+ krb5_free_creds(telnet_context, new_creds);
+ if (r) {
+ if (auth_debug_mode) {
+ printf("telnet: Kerberos V5: mk_req failed (%s)\r\n",
+ error_message(r));
+ }
+ return(0);
+ }
+
+ if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
+ if (auth_debug_mode)
+ printf("telnet: Not enough room for user name\r\n");
+ return(0);
+ }
+ if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
+ if (auth_debug_mode)
+ printf(
+ "telnet: Not enough room for authentication data\r\n");
+ return(0);
+ }
+ if (auth_debug_mode) {
+ printf("telnet: Sent Kerberos V5 credentials to server\r\n");
+ }
+ return(1);
+}
+
+ void
+kerberos5_is(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+ int r = 0;
+ krb5_principal server;
+ krb5_keyblock *newkey = NULL;
+ krb5_keytab keytabid = 0;
+ krb5_data outbuf;
+#ifdef ENCRYPTION
+ Session_Key skey;
+#endif
+ char errbuf[320];
+ char *name;
+ char *getenv();
+ krb5_data inbuf;
+ krb5_authenticator *authenticator;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB_AUTH:
+ auth.data = (char *)data;
+ auth.length = cnt;
+
+ if (!r && !auth_context)
+ r = krb5_auth_con_init(telnet_context, &auth_context);
+ if (!r) {
+ krb5_rcache rcache;
+
+ r = krb5_auth_con_getrcache(telnet_context, auth_context,
+ &rcache);
+ if (!r && !rcache) {
+ r = krb5_sname_to_principal(telnet_context, 0, 0,
+ KRB5_NT_SRV_HST, &server);
+ if (!r) {
+ r = krb5_get_server_rcache(telnet_context,
+ krb5_princ_component(telnet_context,
+ server, 0),
+ &rcache);
+ krb5_free_principal(telnet_context, server);
+ }
+ }
+ if (!r)
+ r = krb5_auth_con_setrcache(telnet_context,
+ auth_context, rcache);
+ }
+ if (!r && telnet_srvtab)
+ r = krb5_kt_resolve(telnet_context,
+ telnet_srvtab, &keytabid);
+ if (!r)
+ r = krb5_rd_req(telnet_context, &auth_context, &auth,
+ NULL, keytabid, NULL, &ticket);
+ if (r) {
+ (void) strcpy(errbuf, "krb5_rd_req failed: ");
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+ goto errout;
+ }
+
+ /*
+ * 256 bytes should be much larger than any reasonable
+ * first component of a service name especially since
+ * the default is of length 4.
+ */
+ if (krb5_princ_component(telnet_context,ticket->server,0)->length < 256) {
+ char princ[256];
+ strncpy(princ,
+ krb5_princ_component(telnet_context, ticket->server,0)->data,
+ krb5_princ_component(telnet_context, ticket->server,0)->length);
+ princ[krb5_princ_component(telnet_context,
+ ticket->server,0)->length] = '\0';
+ if (strcmp("host", princ)) {
+ if(strlen(princ) < sizeof(errbuf) - 39) {
+ (void) sprintf(errbuf, "incorrect service name: \"%s\" != \"host\"",
+ princ);
+ } else {
+ (void) sprintf(errbuf, "incorrect service name: principal != \"host\"");
+ }
+ goto errout;
+ }
+ } else {
+ (void) strcpy(errbuf, "service name too long");
+ goto errout;
+ }
+
+ r = krb5_auth_con_getauthenticator(telnet_context,
+ auth_context,
+ &authenticator);
+ if (r) {
+ (void) strcpy(errbuf,
+ "krb5_auth_con_getauthenticator failed: ");
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+ goto errout;
+ }
+ if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
+ !authenticator->checksum) {
+ (void) strcpy(errbuf,
+ "authenticator is missing required checksum");
+ goto errout;
+ }
+ if (authenticator->checksum) {
+ char type_check[2];
+ krb5_checksum *cksum = authenticator->checksum;
+ krb5_keyblock *key;
+
+ type_check[0] = ap->type;
+ type_check[1] = ap->way;
+
+ r = krb5_auth_con_getkey(telnet_context, auth_context,
+ &key);
+ if (r) {
+ (void) strcpy(errbuf, "krb5_auth_con_getkey failed: ");
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+ goto errout;
+ }
+ r = krb5_verify_checksum(telnet_context,
+ cksum->checksum_type, cksum,
+ &type_check, 2, key->contents,
+ key->length);
+ /*
+ * Note that krb5_verify_checksum() will fail if a pre-
+ * MIT Kerberos Beta 5 client is attempting to connect
+ * to this server (Beta 6 or later). There is not way to
+ * fix this without compromising encryption. It would be
+ * reasonable to add a -i option to telnetd to ignore
+ * checksums (like in klogind). Such an option is not
+ * present at this time.
+ */
+ if (r) {
+ (void) strcpy(errbuf,
+ "checksum verification failed: ");
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+ goto errout;
+ }
+ krb5_free_keyblock(telnet_context, key);
+ }
+ krb5_free_authenticator(telnet_context, authenticator);
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ /* do ap_rep stuff here */
+ if ((r = krb5_mk_rep(telnet_context, auth_context,
+ &outbuf))) {
+ (void) strcpy(errbuf, "Make reply failed: ");
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+ goto errout;
+ }
+
+ Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
+ }
+ if (krb5_unparse_name(telnet_context,
+ ticket->enc_part2 ->client,
+ &name))
+ name = 0;
+ Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
+ if (auth_debug_mode) {
+ printf(
+ "telnetd: Kerberos5 identifies him as ``%s''\r\n",
+ name ? name : "");
+ }
+ auth_finished(ap, AUTH_USER);
+
+ if (name)
+ free(name);
+ krb5_auth_con_getremotesubkey(telnet_context, auth_context,
+ &newkey);
+ if (session_key) {
+ krb5_free_keyblock(telnet_context, session_key);
+ session_key = 0;
+ }
+ if (newkey) {
+ krb5_copy_keyblock(telnet_context, newkey, &session_key);
+ krb5_free_keyblock(telnet_context, newkey);
+ } else {
+ krb5_copy_keyblock(telnet_context,
+ ticket->enc_part2->session,
+ &session_key);
+ }
+
+#ifdef ENCRYPTION
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = session_key->contents;
+ encrypt_session_key(&skey, 1);
+#endif
+ break;
+#ifdef FORWARD
+ case KRB_FORWARD:
+ inbuf.length = cnt;
+ inbuf.data = (char *)data;
+ if ((r = krb5_auth_con_genaddrs(telnet_context, auth_context,
+ net, KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) ||
+ (r = rd_and_store_for_creds(telnet_context, auth_context,
+ &inbuf, ticket))) {
+
+ char errbuf[128];
+
+ (void) strcpy(errbuf, "Read forwarded creds failed: ");
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
+ Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
+ if (auth_debug_mode)
+ printf(
+ "telnetd: Could not read forwarded credentials\r\n");
+ }
+ else
+ Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
+ if (auth_debug_mode)
+ printf("telnetd: Forwarded credentials obtained\r\n");
+ break;
+#endif /* FORWARD */
+ default:
+ if (auth_debug_mode)
+ printf("telnetd: Unknown Kerberos option %d\r\n",
+ data[-1]);
+ Data(ap, KRB_REJECT, 0, 0);
+ break;
+ }
+ return;
+
+ errout:
+ {
+ char eerrbuf[329];
+
+ strcpy(eerrbuf, "telnetd: ");
+ eerrbuf[sizeof(eerrbuf) - 1] = '\0';
+ strncat(eerrbuf, errbuf, sizeof(eerrbuf) - 1 - strlen(eerrbuf));
+ Data(ap, KRB_REJECT, eerrbuf, -1);
+ }
+ if (auth_debug_mode)
+ printf("telnetd: %s\r\n", errbuf);
+ syslog(LOG_ERR, "%s", errbuf);
+ if (auth_context) {
+ krb5_auth_con_free(telnet_context, auth_context);
+ auth_context = 0;
+ }
+ return;
+}
+
+ void
+kerberos5_reply(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+#ifdef ENCRYPTION
+ Session_Key skey;
+#endif
+ 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:
+ if (!mutual_complete) {
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
+ auth_send_retry();
+ return;
+ }
+#ifdef ENCRYPTION
+ if (session_key) {
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = session_key->contents;
+ encrypt_session_key(&skey, 0);
+ }
+#endif /* ENCRYPTION */
+ }
+ if (cnt)
+ printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data);
+ else
+ printf("[ Kerberos V5 accepts you ]\r\n");
+ auth_finished(ap, AUTH_USER);
+#ifdef FORWARD
+ if (forward_flags & OPTS_FORWARD_CREDS)
+ kerberos5_forward(ap);
+#endif /* FORWARD */
+ 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 r;
+
+ inbuf.length = cnt;
+ inbuf.data = (char *)data;
+
+ if ((r = krb5_rd_rep(telnet_context, auth_context, &inbuf,
+ &reply))) {
+ printf("[ Mutual authentication failed: %s ]\r\n",
+ error_message(r));
+ auth_send_retry();
+ return;
+ }
+ krb5_free_ap_rep_enc_part(telnet_context, reply);
+#ifdef ENCRYPTION
+ if (session_key) {
+ skey.type = SK_DES;
+ skey.length = 8;
+ skey.data = session_key->contents;
+ encrypt_session_key(&skey, 0);
+ }
+#endif /* ENCRYPTION */
+ mutual_complete = 1;
+ }
+ return;
+#ifdef FORWARD
+ 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;
+#endif /* FORWARD */
+ default:
+ if (auth_debug_mode)
+ printf("Unknown Kerberos option %d\r\n", data[-1]);
+ return;
+ }
+ return;
+}
+
+ int
+kerberos5_status(ap, name, level)
+ Authenticator *ap;
+ char *name;
+ int level;
+{
+ if (level < AUTH_USER)
+ return(level);
+
+ if (UserNameRequested &&
+ krb5_kuserok(telnet_context, ticket->enc_part2->client,
+ UserNameRequested))
+ {
+ /* the name buffer comes from telnetd/telnetd{-ktd}.c */
+ strncpy(name, UserNameRequested, 255);
+ name[255] = '\0';
+ 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(data, cnt, buf, buflen)
+ unsigned char *data, *buf;
+ int cnt, buflen;
+{
+ char lbuf[32];
+ register int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case KRB_REJECT: /* Rejected (reason might follow) */
+ strncpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB_ACCEPT: /* Accepted (name might follow) */
+ strncpy((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 */
+ strncpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB_RESPONSE:
+ strncpy((char *)buf, " RESPONSE", buflen);
+ goto common2;
+
+#ifdef FORWARD
+ case KRB_FORWARD: /* Forwarded credentials follow */
+ strncpy((char *)buf, " FORWARD", buflen);
+ goto common2;
+
+ case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */
+ strncpy((char *)buf, " FORWARD_ACCEPT", buflen);
+ goto common2;
+
+ case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */
+ /* (reason might follow) */
+ strncpy((char *)buf, " FORWARD_REJECT", buflen);
+ goto common2;
+#endif /* FORWARD */
+
+ default:
+ sprintf(lbuf, " %d (unknown)", data[3]);
+ strncpy((char *)buf, lbuf, buflen);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ sprintf(lbuf, " %d", data[i]);
+ strncpy((char *)buf, lbuf, buflen);
+ BUMP(buf, buflen);
+ }
+ break;
+ }
+}
+
+#ifdef FORWARD
+
+void
+kerberos5_forward(ap)
+ Authenticator *ap;
+{
+ krb5_error_code r;
+ krb5_ccache ccache;
+ krb5_principal client = 0;
+ krb5_principal server = 0;
+ krb5_data forw_creds;
+
+ forw_creds.data = 0;
+
+ if ((r = krb5_cc_default(telnet_context, &ccache))) {
+ if (auth_debug_mode)
+ printf("Kerberos V5: could not get default ccache - %s\r\n",
+ error_message(r));
+ return;
+ }
+
+ if ((r = krb5_cc_get_principal(telnet_context, ccache, &client))) {
+ if (auth_debug_mode)
+ printf("Kerberos V5: could not get default principal - %s\r\n",
+ error_message(r));
+ goto cleanup;
+ }
+
+ if ((r = krb5_sname_to_principal(telnet_context, RemoteHostName, "host",
+ KRB5_NT_SRV_HST, &server))) {
+ if (auth_debug_mode)
+ printf("Kerberos V5: could not make server principal - %s\r\n",
+ error_message(r));
+ goto cleanup;
+ }
+
+ if ((r = krb5_auth_con_genaddrs(telnet_context, auth_context, net,
+ KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR))) {
+ if (auth_debug_mode)
+ printf("Kerberos V5: could not gen local full address - %s\r\n",
+ error_message(r));
+ goto cleanup;
+ }
+
+ if ((r = krb5_fwd_tgt_creds(telnet_context, auth_context, 0, client,
+ server, ccache,
+ forward_flags & OPTS_FORWARDABLE_CREDS,
+ &forw_creds))) {
+ if (auth_debug_mode)
+ printf("Kerberos V5: error getting forwarded creds - %s\r\n",
+ error_message(r));
+ goto cleanup;
+ }
+
+ /* Send forwarded credentials */
+ if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.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");
+ }
+
+cleanup:
+ if (client)
+ krb5_free_principal(telnet_context, client);
+ if (server)
+ krb5_free_principal(telnet_context, server);
+ if (forw_creds.data)
+ free(forw_creds.data);
+ krb5_cc_close(telnet_context, ccache);
+}
+#endif /* FORWARD */
+
+#endif /* KRB5 */
diff --git a/lib/libtelnet/key-proto.h b/lib/libtelnet/key-proto.h
new file mode 100644
index 0000000..1e4d772
--- /dev/null
+++ b/lib/libtelnet/key-proto.h
@@ -0,0 +1,65 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * @(#)key-proto.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * 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.
+ *
+ * $FreeBSD: src/crypto/telnet/libtelnet/key-proto.h,v 1.1.1.1.8.1 2002/04/13 10:59:07 markm Exp $
+ */
+
+#ifndef __KEY_PROTO__
+#define __KEY_PROTO__
+
+int key_file_exists(void);
+void key_lookup(unsigned char *, Block);
+void key_stream_init(Block, Block, int);
+unsigned char key_stream(int, int);
+#endif
diff --git a/lib/libtelnet/krb4encpwd.c b/lib/libtelnet/krb4encpwd.c
new file mode 100644
index 0000000..6af7bf6
--- /dev/null
+++ b/lib/libtelnet/krb4encpwd.c
@@ -0,0 +1,430 @@
+/*-
+ * Copyright (c) 1992, 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/krb4encpwd.c,v 1.3.2.1 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef lint
+static const char sccsid[] = "@(#)krb4encpwd.c 8.3 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+
+#ifdef KRB4_ENCPWD
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <sys/types.h>
+#include <openssl/des.h>
+#include <arpa/telnet.h>
+#include <krb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+
+int krb_mk_encpwd_req(KTEXT, char *, char *, char *, char *, char *, char *);
+int krb_rd_encpwd_req(KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *);
+
+extern auth_debug_mode;
+
+static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+ AUTHTYPE_KRB4_ENCPWD, };
+static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
+ TELQUAL_NAME, };
+
+#define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */
+#define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
+#define KRB4_ENCPWD_ACCEPT 2 /* Accepted */
+#define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */
+#define KRB4_ENCPWD_ACK 4 /* Acknowledge */
+
+#define KRB_SERVICE_NAME "rcmd"
+
+static KTEXT_ST auth;
+static char name[ANAME_SZ];
+static char user_passwd[ANAME_SZ];
+static AUTH_DAT adat = { 0 };
+#ifdef ENCRYPTION
+static Block session_key = { 0 };
+#endif /* ENCRYPTION */
+static char challenge[REALM_SZ];
+
+ static int
+Data(ap, type, d, c)
+ 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((char *)cd);
+
+ if (0) {
+ 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(net_write(str_data, p - str_data));
+}
+
+ int
+krb4encpwd_init(ap, server)
+ Authenticator *ap;
+ int server;
+{
+ char hostname[80], *cp, *realm;
+ C_Block skey;
+
+ if (server) {
+ str_data[3] = TELQUAL_REPLY;
+ } else {
+ str_data[3] = TELQUAL_IS;
+ gethostname(hostname, sizeof(hostname));
+ realm = krb_realmofhost(hostname);
+ cp = strchr(hostname, '.');
+ if (*cp != NULL) *cp = NULL;
+ if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0,
+ KEYFILE, (char *)skey)) {
+ return(0);
+ }
+ }
+ return(1);
+}
+
+ int
+krb4encpwd_send(ap)
+ Authenticator *ap;
+{
+
+ printf("[ Trying KRB4ENCPWD ... ]\n");
+ if (!UserNameRequested) {
+ return(0);
+ }
+ if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
+ return(0);
+ }
+
+ if (!Data(ap, KRB4_ENCPWD_ACK, (void *)NULL, 0)) {
+ return(0);
+ }
+
+ return(1);
+}
+
+ void
+krb4encpwd_is(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+ Session_Key skey;
+ Block datablock;
+ char r_passwd[ANAME_SZ], r_user[ANAME_SZ];
+ char lhostname[ANAME_SZ], *cp;
+ int r;
+ time_t now;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB4_ENCPWD_AUTH:
+ memmove((void *)auth.dat, (void *)data, auth.length = cnt);
+
+ gethostname(lhostname, sizeof(lhostname));
+ if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';
+
+ if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) {
+ Data(ap, KRB4_ENCPWD_REJECT, (void *)"Auth failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+ auth_encrypt_userpwd(r_passwd);
+ if (passwdok(UserNameRequested, UserPassword) == 0) {
+ /*
+ * illegal username and password
+ */
+ Data(ap, KRB4_ENCPWD_REJECT, (void *)"Illegal password", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+
+ memmove((void *)session_key, (void *)adat.session, sizeof(Block));
+ Data(ap, KRB4_ENCPWD_ACCEPT, (void *)0, 0);
+ auth_finished(ap, AUTH_USER);
+ break;
+
+ case KRB4_ENCPWD_CHALLENGE:
+ /*
+ * Take the received random challenge text and save
+ * for future authentication.
+ */
+ memmove((void *)challenge, (void *)data, sizeof(Block));
+ break;
+
+
+ case KRB4_ENCPWD_ACK:
+ /*
+ * Receive ack, if mutual then send random challenge
+ */
+
+ /*
+ * If we are doing mutual authentication, get set up to send
+ * the challenge, and verify it when the response comes back.
+ */
+
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
+ register int i;
+
+ time(&now);
+ sprintf(challenge, "%x", now);
+ Data(ap, KRB4_ENCPWD_CHALLENGE, (void *)challenge, strlen(challenge));
+ }
+ break;
+
+ default:
+ Data(ap, KRB4_ENCPWD_REJECT, 0, 0);
+ break;
+ }
+}
+
+
+ void
+krb4encpwd_reply(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+ Session_Key skey;
+ KTEXT_ST krb_token;
+ Block enckey;
+ CREDENTIALS cred;
+ int r;
+ char randchal[REALM_SZ], instance[ANAME_SZ], *cp;
+ char hostname[80], *realm;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case KRB4_ENCPWD_REJECT:
+ if (cnt > 0) {
+ printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n",
+ cnt, data);
+ } else
+ printf("[ KRB4_ENCPWD refuses authentication ]\r\n");
+ auth_send_retry();
+ return;
+ case KRB4_ENCPWD_ACCEPT:
+ printf("[ KRB4_ENCPWD accepts you ]\n");
+ auth_finished(ap, AUTH_USER);
+ return;
+ case KRB4_ENCPWD_CHALLENGE:
+ /*
+ * Verify that the response to the challenge is correct.
+ */
+
+ gethostname(hostname, sizeof(hostname));
+ realm = krb_realmofhost(hostname);
+ memmove((void *)challenge, (void *)data, cnt);
+ memset(user_passwd, 0, sizeof(user_passwd));
+ local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
+ UserPassword = user_passwd;
+ Challenge = challenge;
+ strcpy(instance, RemoteHostName);
+ if ((cp = strchr(instance, '.')) != 0) *cp = '\0';
+
+ if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) {
+ krb_token.length = 0;
+ }
+
+ if (!Data(ap, KRB4_ENCPWD_AUTH, (void *)krb_token.dat, krb_token.length)) {
+ return;
+ }
+
+ break;
+
+ default:
+ return;
+ }
+}
+
+ int
+krb4encpwd_status(ap, name, level)
+ Authenticator *ap;
+ char *name;
+ int level;
+{
+
+ if (level < AUTH_USER)
+ return(level);
+
+ if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) {
+ strcpy(name, UserNameRequested);
+ 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
+krb4encpwd_printsub(data, cnt, buf, buflen)
+ unsigned char *data, *buf;
+ int cnt, buflen;
+{
+ char lbuf[32];
+ register int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */
+ strncpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */
+ strncpy((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 KRB4_ENCPWD_AUTH: /* Authentication data follows */
+ strncpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case KRB4_ENCPWD_CHALLENGE:
+ strncpy((char *)buf, " CHALLENGE", buflen);
+ goto common2;
+
+ case KRB4_ENCPWD_ACK:
+ strncpy((char *)buf, " ACK", buflen);
+ goto common2;
+
+ default:
+ sprintf(lbuf, " %d (unknown)", data[3]);
+ strncpy((char *)buf, lbuf, buflen);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ sprintf(lbuf, " %d", data[i]);
+ strncpy((char *)buf, lbuf, buflen);
+ BUMP(buf, buflen);
+ }
+ break;
+ }
+}
+
+int passwdok(name, passwd)
+char *name, *passwd;
+{
+ char *crypt();
+ char *salt, *p;
+ struct passwd *pwd;
+ int passwdok_status = 0;
+
+ if (pwd = getpwnam(name))
+ salt = pwd->pw_passwd;
+ else salt = "xx";
+
+ p = crypt(passwd, salt);
+
+ if (pwd && !strcmp(p, pwd->pw_passwd)) {
+ passwdok_status = 1;
+ } else passwdok_status = 0;
+ return(passwdok_status);
+}
+
+#endif
diff --git a/lib/libtelnet/libtelnet.plist b/lib/libtelnet/libtelnet.plist
new file mode 100644
index 0000000..2a9597a
--- /dev/null
+++ b/lib/libtelnet/libtelnet.plist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+ <dict>
+ <key>OpenSourceImportDate</key>
+ <string>2002-05-20</string>
+ <key>OpenSourceLicense</key>
+ <string>BSD</string>
+ <key>OpenSourceLicenseFile</key>
+ <string>libtelnet.txt</string>
+ <key>OpenSourceProject</key>
+ <string>libtelnet</string>
+ <key>OpenSourceVersion</key>
+ <string>2002-05-20</string>
+ <key>OpenSourceCVS</key>
+ <string>cvs -d freebsdanoncvs@anoncvs.FreeBSD.org:/home/ncvs co lib/libtelnet</string>
+ <key>OpenSourceWebsiteURL</key>
+ <string>http://www.freebsd.org/</string>
+ </dict>
+</array>
+</plist>
diff --git a/lib/libtelnet/libtelnet.xcodeproj/project.pbxproj b/lib/libtelnet/libtelnet.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..d409c11
--- /dev/null
+++ b/lib/libtelnet/libtelnet.xcodeproj/project.pbxproj
@@ -0,0 +1,313 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ FD32B4470FF01C38000846C1 /* libtelnet.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD99230C0FEB057C00E57170 /* libtelnet.plist */; };
+ FD32B44C0FF01C49000846C1 /* LICENSE in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD99230D0FEB057C00E57170 /* LICENSE */; };
+ FD9923170FEB057C00E57170 /* auth-proto.h in Headers */ = {isa = PBXBuildFile; fileRef = FD9922FC0FEB057C00E57170 /* auth-proto.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ FD9923180FEB057C00E57170 /* auth.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9922FD0FEB057C00E57170 /* auth.c */; };
+ FD9923190FEB057C00E57170 /* auth.h in Headers */ = {isa = PBXBuildFile; fileRef = FD9922FE0FEB057C00E57170 /* auth.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ FD99231A0FEB057C00E57170 /* enc_des.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923010FEB057C00E57170 /* enc_des.c */; };
+ FD99231B0FEB057C00E57170 /* enc-proto.h in Headers */ = {isa = PBXBuildFile; fileRef = FD9923020FEB057C00E57170 /* enc-proto.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ FD99231C0FEB057C00E57170 /* encrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923030FEB057C00E57170 /* encrypt.c */; };
+ FD99231D0FEB057C00E57170 /* encrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = FD9923040FEB057C00E57170 /* encrypt.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ FD99231E0FEB057C00E57170 /* forward.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923050FEB057C00E57170 /* forward.c */; };
+ FD99231F0FEB057C00E57170 /* genget.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923060FEB057C00E57170 /* genget.c */; };
+ FD9923200FEB057C00E57170 /* getent.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923070FEB057C00E57170 /* getent.c */; };
+ FD9923210FEB057C00E57170 /* kerberos.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923080FEB057C00E57170 /* kerberos.c */; };
+ FD9923220FEB057C00E57170 /* kerberos5.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923090FEB057C00E57170 /* kerberos5.c */; };
+ FD9923240FEB057C00E57170 /* krb4encpwd.c in Sources */ = {isa = PBXBuildFile; fileRef = FD99230B0FEB057C00E57170 /* krb4encpwd.c */; };
+ FD9923260FEB057C00E57170 /* misc-proto.h in Headers */ = {isa = PBXBuildFile; fileRef = FD99230F0FEB057C00E57170 /* misc-proto.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ FD9923270FEB057C00E57170 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923100FEB057C00E57170 /* misc.c */; };
+ FD9923280FEB057C00E57170 /* misc.h in Headers */ = {isa = PBXBuildFile; fileRef = FD9923110FEB057C00E57170 /* misc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ FD99232B0FEB057C00E57170 /* read_password.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923140FEB057C00E57170 /* read_password.c */; };
+ FD99232C0FEB057C00E57170 /* rsaencpwd.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923150FEB057C00E57170 /* rsaencpwd.c */; };
+ FD99232D0FEB057C00E57170 /* sra.c in Sources */ = {isa = PBXBuildFile; fileRef = FD9923160FEB057C00E57170 /* sra.c */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ FD32B4460FF01C2D000846C1 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/local/OpenSourceVersions;
+ dstSubfolderSpec = 0;
+ files = (
+ FD32B4470FF01C38000846C1 /* libtelnet.plist in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ FD32B44B0FF01C41000846C1 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/local/OpenSourceLicenses;
+ dstSubfolderSpec = 0;
+ files = (
+ FD32B44C0FF01C49000846C1 /* LICENSE in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ D2AAC046055464E500DB518D /* libtelnet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtelnet.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ FD9922FC0FEB057C00E57170 /* auth-proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "auth-proto.h"; sourceTree = "<group>"; };
+ FD9922FD0FEB057C00E57170 /* auth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = auth.c; sourceTree = "<group>"; };
+ FD9922FE0FEB057C00E57170 /* auth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auth.h; sourceTree = "<group>"; };
+ FD9923010FEB057C00E57170 /* enc_des.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = enc_des.c; sourceTree = "<group>"; };
+ FD9923020FEB057C00E57170 /* enc-proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "enc-proto.h"; sourceTree = "<group>"; };
+ FD9923030FEB057C00E57170 /* encrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = encrypt.c; sourceTree = "<group>"; };
+ FD9923040FEB057C00E57170 /* encrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = encrypt.h; sourceTree = "<group>"; };
+ FD9923050FEB057C00E57170 /* forward.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = forward.c; sourceTree = "<group>"; };
+ FD9923060FEB057C00E57170 /* genget.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = genget.c; sourceTree = "<group>"; };
+ FD9923070FEB057C00E57170 /* getent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = getent.c; sourceTree = "<group>"; };
+ FD9923080FEB057C00E57170 /* kerberos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kerberos.c; sourceTree = "<group>"; };
+ FD9923090FEB057C00E57170 /* kerberos5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kerberos5.c; sourceTree = "<group>"; };
+ FD99230A0FEB057C00E57170 /* key-proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "key-proto.h"; sourceTree = "<group>"; };
+ FD99230B0FEB057C00E57170 /* krb4encpwd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = krb4encpwd.c; sourceTree = "<group>"; };
+ FD99230C0FEB057C00E57170 /* libtelnet.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = libtelnet.plist; sourceTree = "<group>"; };
+ FD99230D0FEB057C00E57170 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
+ FD99230F0FEB057C00E57170 /* misc-proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "misc-proto.h"; sourceTree = "<group>"; };
+ FD9923100FEB057C00E57170 /* misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = misc.c; sourceTree = "<group>"; };
+ FD9923110FEB057C00E57170 /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = "<group>"; };
+ FD9923120FEB057C00E57170 /* pk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pk.c; sourceTree = "<group>"; };
+ FD9923130FEB057C00E57170 /* pk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pk.h; sourceTree = "<group>"; };
+ FD9923140FEB057C00E57170 /* read_password.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read_password.c; sourceTree = "<group>"; };
+ FD9923150FEB057C00E57170 /* rsaencpwd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rsaencpwd.c; sourceTree = "<group>"; };
+ FD9923160FEB057C00E57170 /* sra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sra.c; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D289987405E68DCB004EDB86 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* libtelnet */ = {
+ isa = PBXGroup;
+ children = (
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ C6A0FF2B0290797F04C91782 /* Documentation */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = libtelnet;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ FD9922FC0FEB057C00E57170 /* auth-proto.h */,
+ FD9922FE0FEB057C00E57170 /* auth.h */,
+ FD9923020FEB057C00E57170 /* enc-proto.h */,
+ FD9923040FEB057C00E57170 /* encrypt.h */,
+ FD99230A0FEB057C00E57170 /* key-proto.h */,
+ FD99230F0FEB057C00E57170 /* misc-proto.h */,
+ FD9923110FEB057C00E57170 /* misc.h */,
+ FD9923130FEB057C00E57170 /* pk.h */,
+ FD9922FD0FEB057C00E57170 /* auth.c */,
+ FD9923010FEB057C00E57170 /* enc_des.c */,
+ FD9923030FEB057C00E57170 /* encrypt.c */,
+ FD9923050FEB057C00E57170 /* forward.c */,
+ FD9923060FEB057C00E57170 /* genget.c */,
+ FD9923070FEB057C00E57170 /* getent.c */,
+ FD9923080FEB057C00E57170 /* kerberos.c */,
+ FD9923090FEB057C00E57170 /* kerberos5.c */,
+ FD99230B0FEB057C00E57170 /* krb4encpwd.c */,
+ FD9923100FEB057C00E57170 /* misc.c */,
+ FD9923120FEB057C00E57170 /* pk.c */,
+ FD9923140FEB057C00E57170 /* read_password.c */,
+ FD9923150FEB057C00E57170 /* rsaencpwd.c */,
+ FD9923160FEB057C00E57170 /* sra.c */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D2AAC046055464E500DB518D /* libtelnet.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C6A0FF2B0290797F04C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ FD99230C0FEB057C00E57170 /* libtelnet.plist */,
+ FD99230D0FEB057C00E57170 /* LICENSE */,
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC043055464E500DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FD9923190FEB057C00E57170 /* auth.h in Headers */,
+ FD9923170FEB057C00E57170 /* auth-proto.h in Headers */,
+ FD99231D0FEB057C00E57170 /* encrypt.h in Headers */,
+ FD99231B0FEB057C00E57170 /* enc-proto.h in Headers */,
+ FD9923280FEB057C00E57170 /* misc.h in Headers */,
+ FD9923260FEB057C00E57170 /* misc-proto.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ D2AAC045055464E500DB518D /* libtelnet */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libtelnet" */;
+ buildPhases = (
+ D2AAC043055464E500DB518D /* Headers */,
+ D2AAC044055464E500DB518D /* Sources */,
+ D289987405E68DCB004EDB86 /* Frameworks */,
+ FD32B4460FF01C2D000846C1 /* CopyFiles */,
+ FD32B44B0FF01C41000846C1 /* CopyFiles */,
+ FD32B4530FF01CD9000846C1 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = libtelnet;
+ productName = libtelnet;
+ productReference = D2AAC046055464E500DB518D /* libtelnet.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libtelnet" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* libtelnet */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D2AAC045055464E500DB518D /* libtelnet */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ FD32B4530FF01CD9000846C1 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "set -ex\nmv ${DSTROOT}/usr/local/OpenSourceLicenses/LICENSE ${DSTROOT}/usr/local/OpenSourceLicenses/libtelnet.txt";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D2AAC044055464E500DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FD9923180FEB057C00E57170 /* auth.c in Sources */,
+ FD99231A0FEB057C00E57170 /* enc_des.c in Sources */,
+ FD99231C0FEB057C00E57170 /* encrypt.c in Sources */,
+ FD99231E0FEB057C00E57170 /* forward.c in Sources */,
+ FD99231F0FEB057C00E57170 /* genget.c in Sources */,
+ FD9923200FEB057C00E57170 /* getent.c in Sources */,
+ FD9923210FEB057C00E57170 /* kerberos.c in Sources */,
+ FD9923220FEB057C00E57170 /* kerberos5.c in Sources */,
+ FD9923240FEB057C00E57170 /* krb4encpwd.c in Sources */,
+ FD9923270FEB057C00E57170 /* misc.c in Sources */,
+ FD99232B0FEB057C00E57170 /* read_password.c in Sources */,
+ FD99232C0FEB057C00E57170 /* rsaencpwd.c in Sources */,
+ FD99232D0FEB057C00E57170 /* sra.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91ED08733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/lib;
+ PRODUCT_NAME = telnet;
+ PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/libtelnet;
+ };
+ name = Release;
+ };
+ 1DEB91F108733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ DEAD_CODE_STRIPPING = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__FBSDID=__RCSID",
+ HAS_CGETENT,
+ AUTHENTICATION,
+ RSA,
+ KRB5,
+ FORWARD,
+ HAVE_STDLIB_H,
+ );
+ "GCC_PREPROCESSOR_DEFINITIONS[sdk=iphone*]" = (
+ "__FBSDID=__RCSID",
+ HAS_CGETENT,
+ AUTHENTICATION,
+ RSA,
+ FORWARD,
+ HAVE_STDLIB_H,
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ USE_HEADERMAP = NO;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libtelnet" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91ED08733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libtelnet" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91F108733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/lib/libtelnet/misc-proto.h b/lib/libtelnet/misc-proto.h
new file mode 100644
index 0000000..511a1bf
--- /dev/null
+++ b/lib/libtelnet/misc-proto.h
@@ -0,0 +1,80 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * @(#)misc-proto.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD: src/crypto/telnet/libtelnet/misc-proto.h,v 1.1.1.1.8.1 2002/04/13 10:59:07 markm Exp $
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef __MISC_PROTO__
+#define __MISC_PROTO__
+
+void auth_encrypt_init(char *, char *, const char *, int);
+void auth_encrypt_connect(int);
+void printd(const unsigned char *, int);
+
+int isprefix(char *, const char *);
+char **genget(char *, char **, int);
+int Ambiguous(char **);
+
+int getent(char *, const char *);
+char *Getstr(const char *, char **);
+
+/*
+ * These functions are imported from the application
+ */
+int net_write(unsigned char *, int);
+void net_encrypt(void);
+int telnet_spin(void);
+char *telnet_getenv(char *);
+char *telnet_gets(const char *, char *, int, int);
+void printsub(char, unsigned char *, int);
+#endif
diff --git a/lib/libtelnet/misc.c b/lib/libtelnet/misc.c
new file mode 100644
index 0000000..6eac32e
--- /dev/null
+++ b/lib/libtelnet/misc.c
@@ -0,0 +1,114 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/misc.c,v 1.2.8.2 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifndef lint
+#if 0
+static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93";
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "misc.h"
+#ifdef AUTHENTICATION
+#include "auth.h"
+#endif
+#ifdef ENCRYPTION
+#include "encrypt.h"
+#endif /* ENCRYPTION */
+
+char *RemoteHostName;
+char *LocalHostName;
+char *UserNameRequested = 0;
+int ConnectedCount = 0;
+
+#ifndef AUTHENTICATION
+#define undef1 __unused
+#else
+#define undef1
+#endif
+
+void
+auth_encrypt_init(char *local, char *remote, const char *name undef1, int server undef1)
+{
+ RemoteHostName = remote;
+ LocalHostName = local;
+#ifdef AUTHENTICATION
+ auth_init(name, server);
+#endif
+#ifdef ENCRYPTION
+ encrypt_init(name, server);
+#endif /* ENCRYPTION */
+ if (UserNameRequested) {
+ free(UserNameRequested);
+ UserNameRequested = 0;
+ }
+}
+
+#ifdef ENCRYPTION
+void
+auth_encrypt_user(char *name)
+{
+ if (UserNameRequested)
+ free(UserNameRequested);
+ UserNameRequested = name ? strdup(name) : 0;
+}
+
+void
+auth_encrypt_connect(int cnt __unused)
+{
+}
+#endif /* ENCRYPTION */
+
+void
+printd(const unsigned char *data, int cnt)
+{
+ if (cnt > 16)
+ cnt = 16;
+ while (cnt-- > 0) {
+ printf(" %02x", *data);
+ ++data;
+ }
+}
diff --git a/lib/libtelnet/misc.h b/lib/libtelnet/misc.h
new file mode 100644
index 0000000..41ffa7f
--- /dev/null
+++ b/lib/libtelnet/misc.h
@@ -0,0 +1,42 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * @(#)misc.h 8.1 (Berkeley) 6/4/93
+ */
+
+extern char *UserNameRequested;
+extern char *LocalHostName;
+extern char *RemoteHostName;
+extern int ConnectedCount;
+extern int ReservedPort;
+
+#include "misc-proto.h"
diff --git a/lib/libtelnet/pk.c b/lib/libtelnet/pk.c
new file mode 100644
index 0000000..56444ed
--- /dev/null
+++ b/lib/libtelnet/pk.c
@@ -0,0 +1,269 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * Dave Safford. 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 <sys/cdefs.h>
+
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/pk.c,v 1.2.2.3 2002/04/13 10:59:07 markm Exp $");
+
+/* public key routines */
+/* functions:
+ genkeys(char *public, char *secret)
+ common_key(char *secret, char *public, desData *deskey)
+ pk_encode(char *in, *out, DesData *deskey);
+ pk_decode(char *in, *out, DesData *deskey);
+ where
+ char public[HEXKEYBYTES + 1];
+ char secret[HEXKEYBYTES + 1];
+ */
+
+#include <sys/time.h>
+#include <openssl/des.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mp.h"
+#include "pk.h"
+
+static void adjust(char keyout[HEXKEYBYTES+1], char *keyin);
+
+/*
+ * Choose top 128 bits of the common key to use as our idea key.
+ */
+static void
+extractideakey(MINT *ck, IdeaData *ideakey)
+{
+ MINT *a;
+ MINT *z;
+ short r;
+ int i;
+ short base = (1 << 8);
+ char *k;
+
+ z = itom(0);
+ a = itom(0);
+ madd(ck, z, a);
+ for (i = 0; i < ((KEYSIZE - 128) / 8); i++) {
+ sdiv(a, base, a, &r);
+ }
+ k = (char *)ideakey;
+ for (i = 0; i < 16; i++) {
+ sdiv(a, base, a, &r);
+ *k++ = r;
+ }
+ mfree(z);
+ mfree(a);
+}
+
+/*
+ * Choose middle 64 bits of the common key to use as our des key, possibly
+ * overwriting the lower order bits by setting parity.
+ */
+static void
+extractdeskey(MINT *ck, DesData *deskey)
+{
+ MINT *a;
+ MINT *z;
+ short r;
+ int i;
+ short base = (1 << 8);
+ char *k;
+
+ z = itom(0);
+ a = itom(0);
+ madd(ck, z, a);
+ for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
+ sdiv(a, base, a, &r);
+ }
+ k = (char *)deskey;
+ for (i = 0; i < 8; i++) {
+ sdiv(a, base, a, &r);
+ *k++ = r;
+ }
+ mfree(z);
+ mfree(a);
+}
+
+/*
+ * get common key from my secret key and his public key
+ */
+void
+common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
+{
+ MINT *public;
+ MINT *secret;
+ MINT *common;
+ MINT *modulus = xtom(HEXMODULUS);
+
+ public = xtom(xpublic);
+ secret = xtom(xsecret);
+ common = itom(0);
+ pow(public, secret, modulus, common);
+ extractdeskey(common, deskey);
+ extractideakey(common, ideakey);
+ des_set_odd_parity(deskey);
+ mfree(common);
+ mfree(secret);
+ mfree(public);
+ mfree(modulus);
+}
+
+/*
+ * Generate a seed
+ */
+static void
+getseed(char *seed, int seedsize)
+{
+ int i;
+
+ srandomdev();
+ for (i = 0; i < seedsize; i++) {
+ seed[i] = random() & 0xff;
+ }
+}
+
+/*
+ * Generate a random public/secret key pair
+ */
+void
+genkeys(char *public, char *secret)
+{
+ size_t i;
+
+# define BASEBITS (8*sizeof(short) - 1)
+# define BASE (1 << BASEBITS)
+
+ MINT *pk = itom(0);
+ MINT *sk = itom(0);
+ MINT *tmp;
+ MINT *base = itom(BASE);
+ MINT *root = itom(PROOT);
+ MINT *modulus = xtom(HEXMODULUS);
+ short r;
+ unsigned short seed[KEYSIZE/BASEBITS + 1];
+ char *xkey;
+
+ getseed((char *)seed, sizeof(seed));
+ for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
+ r = seed[i] % BASE;
+ tmp = itom(r);
+ mult(sk, base, sk);
+ madd(sk, tmp, sk);
+ mfree(tmp);
+ }
+ tmp = itom(0);
+ mdiv(sk, modulus, tmp, sk);
+ mfree(tmp);
+ pow(root, sk, modulus, pk);
+ xkey = mtox(sk);
+ adjust(secret, xkey);
+ xkey = mtox(pk);
+ adjust(public, xkey);
+ mfree(sk);
+ mfree(base);
+ mfree(pk);
+ mfree(root);
+ mfree(modulus);
+}
+
+/*
+ * Adjust the input key so that it is 0-filled on the left
+ */
+static void
+adjust(char keyout[HEXKEYBYTES+1], char *keyin)
+{
+ char *p;
+ char *s;
+
+ for (p = keyin; *p; p++)
+ ;
+ for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
+ *s = *p;
+ }
+ while (s >= keyout) {
+ *s-- = '0';
+ }
+}
+
+static char hextab[17] = "0123456789ABCDEF";
+
+/* given a DES key, cbc encrypt and translate input to terminated hex */
+void
+pk_encode(char *in, char *out, DesData *key)
+{
+ char buf[256];
+ DesData i;
+ des_key_schedule k;
+ int l,op,deslen;
+
+ memset(&i,0,sizeof(i));
+ memset(buf,0,sizeof(buf));
+ deslen = ((strlen(in) + 7)/8)*8;
+ des_key_sched(key, k);
+ des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT);
+ for (l=0,op=0;l<deslen;l++) {
+ out[op++] = hextab[(buf[l] & 0xf0) >> 4];
+ out[op++] = hextab[(buf[l] & 0x0f)];
+ }
+ out[op] = '\0';
+}
+
+/* given a DES key, translate input from hex and decrypt */
+void
+pk_decode(char *in, char *out, DesData *key)
+{
+ char buf[256];
+ DesData i;
+ des_key_schedule k;
+ int n1,n2,op;
+ size_t l;
+
+ memset(&i,0,sizeof(i));
+ memset(buf,0,sizeof(buf));
+ for (l=0,op=0;l<strlen(in)/2;l++,op+=2) {
+ if(in[op] == '0' && in[op+1] == '0') {
+ buf[l] = '\0';
+ break;
+ }
+ if (in[op] > '9')
+ n1 = in[op] - 'A' + 10;
+ else
+ n1 = in[op] - '0';
+ if (in[op+1] > '9')
+ n2 = in[op+1] - 'A' + 10;
+ else
+ n2 = in[op+1] - '0';
+ buf[l] = n1*16 +n2;
+ }
+ des_key_sched(key, k);
+ des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT);
+ out[strlen(in)/2] = '\0';
+}
diff --git a/lib/libtelnet/pk.h b/lib/libtelnet/pk.h
new file mode 100644
index 0000000..401728a
--- /dev/null
+++ b/lib/libtelnet/pk.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * Dave Safford. 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.
+ *
+ * $FreeBSD: src/crypto/telnet/libtelnet/pk.h,v 1.1.2.3 2002/04/13 10:59:07 markm Exp $
+ */
+
+/* header for the des routines that we will use */
+
+typedef unsigned char byte, DesData[ 8], IdeaData[16];
+#define DesKeys des_key_schedule
+
+#define DES_DECRYPT 0
+#define DES_ENCRYPT 1
+
+/* public key routines */
+/* functions:
+ genkeys(char *public, char *secret)
+ common_key(char *secret, char *public, desData *deskey)
+ where
+ char public[HEXKEYBYTES + 1];
+ char secret[HEXKEYBYTES + 1];
+ */
+
+#define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"
+#define HEXKEYBYTES 48
+#define KEYSIZE 192
+#define KEYBYTES 24
+#define PROOT 3
+
+extern void genkeys(char *public, char *secret);
+extern void common_key(char *secret, char *public, IdeaData *common,
+ DesData *deskey);
+extern void pk_encode(char *in, char *out, DesData *deskey);
+extern void pk_decode(char *in, char *out, DesData *deskey);
diff --git a/lib/libtelnet/read_password.c b/lib/libtelnet/read_password.c
new file mode 100644
index 0000000..b8ab104
--- /dev/null
+++ b/lib/libtelnet/read_password.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 1992, 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/read_password.c,v 1.1.1.1.8.2 2002/04/13 10:59:07 markm Exp $");
+#endif
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)read_password.c 8.3 (Berkeley) 5/30/95";
+#endif
+#endif /* not lint */
+
+/*
+ * $Source: /Users/Shared/libtelnet/libtelnet/read_password.c,v $
+ * $Author: nicolai $
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This routine prints the supplied string to standard
+ * output as a prompt, and reads a password string without
+ * echoing.
+ */
+
+#if defined(RSA_ENCPWD) || defined(KRB4_ENCPWD)
+
+#include <stdio.h>
+#include <strings.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <setjmp.h>
+
+static jmp_buf env;
+
+/*** Routines ****************************************************** */
+/*
+ * This version just returns the string, doesn't map to key.
+ *
+ * Returns 0 on success, non-zero on failure.
+ */
+
+int
+local_des_read_pw_string(s,max,prompt,verify)
+ char *s;
+ int max;
+ char *prompt;
+ int verify;
+{
+ int ok = 0;
+ char *ptr;
+
+ jmp_buf old_env;
+ struct sgttyb tty_state;
+ char key_string[BUFSIZ];
+
+ if (max > BUFSIZ) {
+ return -1;
+ }
+
+ /* XXX assume jmp_buf is typedef'ed to an array */
+ memmove((char *)env, (char *)old_env, sizeof(env));
+ if (setjmp(env))
+ goto lose;
+
+ /* save terminal state*/
+ if (ioctl(0,TIOCGETP,(char *)&tty_state) == -1)
+ return -1;
+/*
+ push_signals();
+*/
+ /* Turn off echo */
+ tty_state.sg_flags &= ~ECHO;
+ if (ioctl(0,TIOCSETP,(char *)&tty_state) == -1)
+ return -1;
+ while (!ok) {
+ (void) printf("%s", prompt);
+ (void) fflush(stdout);
+ while (!fgets(s, max, stdin));
+
+ if ((ptr = strchr(s, '\n')))
+ *ptr = '\0';
+ if (verify) {
+ printf("\nVerifying, please re-enter %s",prompt);
+ (void) fflush(stdout);
+ if (!fgets(key_string, sizeof(key_string), stdin)) {
+ clearerr(stdin);
+ continue;
+ }
+ if ((ptr = strchr(key_string, '\n')))
+ *ptr = '\0';
+ if (strcmp(s,key_string)) {
+ printf("\n\07\07Mismatch - try again\n");
+ (void) fflush(stdout);
+ continue;
+ }
+ }
+ ok = 1;
+ }
+
+lose:
+ if (!ok)
+ memset(s, 0, max);
+ printf("\n");
+ /* turn echo back on */
+ tty_state.sg_flags |= ECHO;
+ if (ioctl(0,TIOCSETP,(char *)&tty_state))
+ ok = 0;
+/*
+ pop_signals();
+*/
+ memmove((char *)old_env, (char *)env, sizeof(env));
+ if (verify)
+ memset(key_string, 0, sizeof (key_string));
+ s[max-1] = 0; /* force termination */
+ return !ok; /* return nonzero if not okay */
+}
+#endif /* defined(RSA_ENCPWD) || defined(KRB4_ENCPWD) */
diff --git a/lib/libtelnet/rsaencpwd.c b/lib/libtelnet/rsaencpwd.c
new file mode 100644
index 0000000..60242a2
--- /dev/null
+++ b/lib/libtelnet/rsaencpwd.c
@@ -0,0 +1,475 @@
+/*-
+ * Copyright (c) 1992, 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <sys/cdefs.h>
+
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/rsaencpwd.c,v 1.1.1.1.8.1 2002/04/13 10:59:07 markm Exp $");
+
+#ifndef lint
+static char sccsid[] = "@(#)rsaencpwd.c 8.3 (Berkeley) 5/30/95";
+#endif /* not lint */
+
+
+#ifdef RSA_ENCPWD
+/*
+ * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
+ * ALL RIGHTS RESERVED
+ *
+ * "Digital Equipment Corporation authorizes the reproduction,
+ * distribution and modification of this software subject to the following
+ * restrictions:
+ *
+ * 1. Any partial or whole copy of this software, or any modification
+ * thereof, must include this copyright notice in its entirety.
+ *
+ * 2. This software is supplied "as is" with no warranty of any kind,
+ * expressed or implied, for any purpose, including any warranty of fitness
+ * or merchantibility. DIGITAL assumes no responsibility for the use or
+ * reliability of this software, nor promises to provide any form of
+ * support for it on any basis.
+ *
+ * 3. Distribution of this software is authorized only if no profit or
+ * remuneration of any kind is received in exchange for such distribution.
+ *
+ * 4. This software produces public key authentication certificates
+ * bearing an expiration date established by DIGITAL and RSA Data
+ * Security, Inc. It may cease to generate certificates after the expiration
+ * date. Any modification of this software that changes or defeats
+ * the expiration date or its effect is unauthorized.
+ *
+ * 5. Software that will renew or extend the expiration date of
+ * authentication certificates produced by this software may be obtained
+ * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
+ * 94065, (415)595-8782, or from DIGITAL"
+ *
+ */
+
+#include <sys/types.h>
+#include <arpa/telnet.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "encrypt.h"
+#include "auth.h"
+#include "misc.h"
+#include "cdc.h"
+
+extern auth_debug_mode;
+
+static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+ AUTHTYPE_RSA_ENCPWD, };
+static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
+ TELQUAL_NAME, };
+
+#define RSA_ENCPWD_AUTH 0 /* Authentication data follows */
+#define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
+#define RSA_ENCPWD_ACCEPT 2 /* Accepted */
+#define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */
+
+#define NAME_SZ 40
+#define CHAL_SZ 20
+#define PWD_SZ 40
+
+static KTEXT_ST auth;
+static char name[NAME_SZ];
+static char user_passwd[PWD_SZ];
+static char key_file[2*NAME_SZ];
+static char lhostname[NAME_SZ];
+static char challenge[CHAL_SZ];
+static int challenge_len;
+
+ static int
+Data(ap, type, d, c)
+ 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((char *)cd);
+
+ if (0) {
+ 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;
+ if (type != NULL) *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(net_write(str_data, p - str_data));
+}
+
+ int
+rsaencpwd_init(ap, server)
+ Authenticator *ap;
+ int server;
+{
+ char *cp;
+ FILE *fp;
+
+ if (server) {
+ str_data[3] = TELQUAL_REPLY;
+ memset(key_file, 0, sizeof(key_file));
+ gethostname(lhostname, sizeof(lhostname));
+ if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';
+ strcpy(key_file, "/etc/.");
+ strcat(key_file, lhostname);
+ strcat(key_file, "_privkey");
+ if ((fp=fopen(key_file, "r"))==NULL) return(0);
+ fclose(fp);
+ } else {
+ str_data[3] = TELQUAL_IS;
+ }
+ return(1);
+}
+
+ int
+rsaencpwd_send(ap)
+ Authenticator *ap;
+{
+
+ printf("[ Trying RSAENCPWD ... ]\n");
+ if (!UserNameRequested) {
+ return(0);
+ }
+ if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
+ return(0);
+ }
+ if (!Data(ap, NULL, (void *)NULL, 0)) {
+ return(0);
+ }
+
+
+ return(1);
+}
+
+ void
+rsaencpwd_is(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+ Session_Key skey;
+ Block datablock;
+ char r_passwd[PWD_SZ], r_user[NAME_SZ];
+ char *cp, key[160];
+ char chalkey[160], *ptr;
+ FILE *fp;
+ int r, i, j, chalkey_len, len;
+ time_t now;
+
+ cnt--;
+ switch (*data++) {
+ case RSA_ENCPWD_AUTH:
+ memmove((void *)auth.dat, (void *)data, auth.length = cnt);
+
+ if ((fp=fopen(key_file, "r"))==NULL) {
+ Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+ /*
+ * get privkey
+ */
+ fscanf(fp, "%x;", &len);
+ for (i=0;i<len;i++) {
+ j = getc(fp); key[i]=j;
+ }
+ fclose(fp);
+
+ r = accept_rsa_encpwd(&auth, key, challenge,
+ challenge_len, r_passwd);
+ if (r < 0) {
+ Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+ auth_encrypt_userpwd(r_passwd);
+ if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) {
+ /*
+ * illegal username and password
+ */
+ Data(ap, RSA_ENCPWD_REJECT, (void *)"Illegal password", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+
+ Data(ap, RSA_ENCPWD_ACCEPT, (void *)0, 0);
+ auth_finished(ap, AUTH_USER);
+ break;
+
+
+ case IAC:
+
+ /*
+ * If we are doing mutual authentication, get set up to send
+ * the challenge, and verify it when the response comes back.
+ */
+ if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
+ register int i;
+
+
+ time(&now);
+ if ((now % 2) == 0) {
+ sprintf(challenge, "%x", now);
+ challenge_len = strlen(challenge);
+ } else {
+ strcpy(challenge, "randchal");
+ challenge_len = 8;
+ }
+
+ if ((fp=fopen(key_file, "r"))==NULL) {
+ Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
+ auth_finished(ap, AUTH_REJECT);
+ return;
+ }
+ /*
+ * skip privkey
+ */
+ fscanf(fp, "%x;", &len);
+ for (i=0;i<len;i++) {
+ j = getc(fp);
+ }
+ /*
+ * get pubkey
+ */
+ fscanf(fp, "%x;", &len);
+ for (i=0;i<len;i++) {
+ j = getc(fp); key[i]=j;
+ }
+ fclose(fp);
+ chalkey[0] = 0x30;
+ ptr = (char *) &chalkey[1];
+ chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len;
+ EncodeLength(ptr, chalkey_len);
+ ptr +=NumEncodeLengthOctets(chalkey_len);
+ *ptr++ = 0x04; /* OCTET STRING */
+ *ptr++ = challenge_len;
+ memmove(ptr, challenge, challenge_len);
+ ptr += challenge_len;
+ *ptr++ = 0x04; /* OCTET STRING */
+ EncodeLength(ptr, i);
+ ptr += NumEncodeLengthOctets(i);
+ memmove(ptr, key, i);
+ chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len;
+ Data(ap, RSA_ENCPWD_CHALLENGEKEY, (void *)chalkey, chalkey_len);
+ }
+ break;
+
+ default:
+ Data(ap, RSA_ENCPWD_REJECT, 0, 0);
+ break;
+ }
+}
+
+
+ void
+rsaencpwd_reply(ap, data, cnt)
+ Authenticator *ap;
+ unsigned char *data;
+ int cnt;
+{
+ Session_Key skey;
+ KTEXT_ST token;
+ Block enckey;
+ int r, pubkey_len;
+ char randchal[CHAL_SZ], *cp;
+ char chalkey[160], pubkey[128], *ptr;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+ case RSA_ENCPWD_REJECT:
+ if (cnt > 0) {
+ printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n",
+ cnt, data);
+ } else
+ printf("[ RSA_ENCPWD refuses authentication ]\r\n");
+ auth_send_retry();
+ return;
+ case RSA_ENCPWD_ACCEPT:
+ printf("[ RSA_ENCPWD accepts you ]\n");
+ auth_finished(ap, AUTH_USER);
+ return;
+ case RSA_ENCPWD_CHALLENGEKEY:
+ /*
+ * Verify that the response to the challenge is correct.
+ */
+
+ memmove((void *)chalkey, (void *)data, cnt);
+ ptr = (char *) &chalkey[0];
+ ptr += DecodeHeaderLength(chalkey);
+ if (*ptr != 0x04) {
+ return;
+ }
+ *ptr++;
+ challenge_len = DecodeValueLength(ptr);
+ ptr += NumEncodeLengthOctets(challenge_len);
+ memmove(challenge, ptr, challenge_len);
+ ptr += challenge_len;
+ if (*ptr != 0x04) {
+ return;
+ }
+ *ptr++;
+ pubkey_len = DecodeValueLength(ptr);
+ ptr += NumEncodeLengthOctets(pubkey_len);
+ memmove(pubkey, ptr, pubkey_len);
+ memset(user_passwd, 0, sizeof(user_passwd));
+ local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
+ UserPassword = user_passwd;
+ Challenge = challenge;
+ r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey);
+ if (r < 0) {
+ token.length = 1;
+ }
+
+ if (!Data(ap, RSA_ENCPWD_AUTH, (void *)token.dat, token.length)) {
+ return;
+ }
+
+ break;
+
+ default:
+ return;
+ }
+}
+
+ int
+rsaencpwd_status(ap, name, level)
+ Authenticator *ap;
+ char *name;
+ int level;
+{
+
+ if (level < AUTH_USER)
+ return(level);
+
+ if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) {
+ strcpy(name, UserNameRequested);
+ 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
+rsaencpwd_printsub(data, cnt, buf, buflen)
+ unsigned char *data, *buf;
+ int cnt, buflen;
+{
+ char lbuf[32];
+ register int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+ case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */
+ strncpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */
+ strncpy((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 RSA_ENCPWD_AUTH: /* Authentication data follows */
+ strncpy((char *)buf, " AUTH", buflen);
+ goto common2;
+
+ case RSA_ENCPWD_CHALLENGEKEY:
+ strncpy((char *)buf, " CHALLENGEKEY", buflen);
+ goto common2;
+
+ default:
+ sprintf(lbuf, " %d (unknown)", data[3]);
+ strncpy((char *)buf, lbuf, buflen);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ sprintf(lbuf, " %d", data[i]);
+ strncpy((char *)buf, lbuf, buflen);
+ BUMP(buf, buflen);
+ }
+ break;
+ }
+}
+
+int rsaencpwd_passwdok(name, passwd)
+char *name, *passwd;
+{
+ char *crypt();
+ char *salt, *p;
+ struct passwd *pwd;
+ int passwdok_status = 0;
+
+ if (pwd = getpwnam(name))
+ salt = pwd->pw_passwd;
+ else salt = "xx";
+
+ p = crypt(passwd, salt);
+
+ if (pwd && !strcmp(p, pwd->pw_passwd)) {
+ passwdok_status = 1;
+ } else passwdok_status = 0;
+ return(passwdok_status);
+}
+
+#endif
diff --git a/lib/libtelnet/sra.c b/lib/libtelnet/sra.c
new file mode 100644
index 0000000..c85abbf
--- /dev/null
+++ b/lib/libtelnet/sra.c
@@ -0,0 +1,604 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * Dave Safford. 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 <sys/cdefs.h>
+
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: src/crypto/telnet/libtelnet/sra.c,v 1.1.2.7 2002/05/16 08:46:49 markm Exp $");
+#endif
+
+#ifdef SRA
+#ifdef ENCRYPTION
+#include <sys/types.h>
+#include <arpa/telnet.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <ttyent.h>
+
+#ifndef NOPAM
+#include <security/pam_appl.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "auth.h"
+#include "misc.h"
+#include "encrypt.h"
+#include "pk.h"
+
+char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
+char *user, *pass, *xuser, *xpass;
+DesData ck;
+IdeaData ik;
+
+extern int auth_debug_mode;
+extern char line[];
+
+static int sra_valid = 0;
+static int passwd_sent = 0;
+
+static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+ AUTHTYPE_SRA, };
+
+#define SRA_KEY 0
+#define SRA_USER 1
+#define SRA_CONTINUE 2
+#define SRA_PASS 3
+#define SRA_ACCEPT 4
+#define SRA_REJECT 5
+
+static int check_user(char *, char *);
+
+/* support routine to send out authentication message */
+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((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(net_write(str_data, p - str_data));
+}
+
+int
+sra_init(Authenticator *ap __unused, int server)
+{
+ if (server)
+ str_data[3] = TELQUAL_REPLY;
+ else
+ str_data[3] = TELQUAL_IS;
+
+ user = (char *)malloc(256);
+ xuser = (char *)malloc(513);
+ pass = (char *)malloc(256);
+ xpass = (char *)malloc(513);
+
+ if (user == NULL || xuser == NULL || pass == NULL || xpass ==
+ NULL)
+ return 0; /* malloc failed */
+
+ passwd_sent = 0;
+
+ genkeys(pka,ska);
+ return(1);
+}
+
+/* client received a go-ahead for sra */
+int
+sra_send(Authenticator *ap)
+{
+ /* send PKA */
+
+ if (auth_debug_mode)
+ printf("Sent PKA to server.\r\n" );
+ printf("Trying SRA secure login:\r\n");
+ if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
+ if (auth_debug_mode)
+ printf("Not enough room for authentication data\r\n");
+ return(0);
+ }
+
+ return(1);
+}
+
+/* server received an IS -- could be SRA KEY, USER, or PASS */
+void
+sra_is(Authenticator *ap, unsigned char *data, int cnt)
+{
+ int valid;
+ Session_Key skey;
+
+ if (cnt-- < 1)
+ goto bad;
+ switch (*data++) {
+
+ case SRA_KEY:
+ if (cnt < HEXKEYBYTES) {
+ Data(ap, SRA_REJECT, (void *)0, 0);
+ auth_finished(ap, AUTH_USER);
+ if (auth_debug_mode) {
+ printf("SRA user rejected for bad PKB\r\n");
+ }
+ return;
+ }
+ if (auth_debug_mode)
+ printf("Sent pka\r\n");
+ if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
+ if (auth_debug_mode)
+ printf("Not enough room\r\n");
+ return;
+ }
+ memcpy(pkb,data,HEXKEYBYTES);
+ pkb[HEXKEYBYTES] = '\0';
+ common_key(ska,pkb,&ik,&ck);
+ return;
+
+ case SRA_USER:
+ /* decode KAB(u) */
+ if (cnt > 512) /* Attempted buffer overflow */
+ break;
+ memcpy(xuser,data,cnt);
+ xuser[cnt] = '\0';
+ pk_decode(xuser,user,&ck);
+ auth_encrypt_user(user);
+ Data(ap, SRA_CONTINUE, (void *)0, 0);
+
+ return;
+
+ case SRA_PASS:
+ if (cnt > 512) /* Attempted buffer overflow */
+ break;
+ /* decode KAB(P) */
+ memcpy(xpass,data,cnt);
+ xpass[cnt] = '\0';
+ pk_decode(xpass,pass,&ck);
+
+ /* check user's password */
+ valid = check_user(user,pass);
+
+ if(valid) {
+ Data(ap, SRA_ACCEPT, (void *)0, 0);
+ skey.data = ck;
+ skey.type = SK_DES;
+ skey.length = 8;
+ encrypt_session_key(&skey, 1);
+
+ sra_valid = 1;
+ auth_finished(ap, AUTH_VALID);
+ if (auth_debug_mode) {
+ printf("SRA user accepted\r\n");
+ }
+ }
+ else {
+ Data(ap, SRA_CONTINUE, (void *)0, 0);
+/*
+ Data(ap, SRA_REJECT, (void *)0, 0);
+ sra_valid = 0;
+ auth_finished(ap, AUTH_REJECT);
+*/
+ if (auth_debug_mode) {
+ printf("SRA user failed\r\n");
+ }
+ }
+ return;
+
+ default:
+ if (auth_debug_mode)
+ printf("Unknown SRA option %d\r\n", data[-1]);
+ }
+bad:
+ Data(ap, SRA_REJECT, 0, 0);
+ sra_valid = 0;
+ auth_finished(ap, AUTH_REJECT);
+}
+
+/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
+void
+sra_reply(Authenticator *ap, unsigned char *data, int cnt)
+{
+ char uprompt[256],tuser[256];
+ Session_Key skey;
+ size_t i;
+
+ if (cnt-- < 1)
+ return;
+ switch (*data++) {
+
+ case SRA_KEY:
+ /* calculate common key */
+ if (cnt < HEXKEYBYTES) {
+ if (auth_debug_mode) {
+ printf("SRA user rejected for bad PKB\r\n");
+ }
+ return;
+ }
+ memcpy(pkb,data,HEXKEYBYTES);
+ pkb[HEXKEYBYTES] = '\0';
+
+ common_key(ska,pkb,&ik,&ck);
+
+ enc_user:
+
+ /* encode user */
+ memset(tuser,0,sizeof(tuser));
+ sprintf(uprompt,"User (%s): ",UserNameRequested);
+ telnet_gets(uprompt,tuser,255,1);
+ if (tuser[0] == '\n' || tuser[0] == '\r' )
+ strcpy(user,UserNameRequested);
+ else {
+ /* telnet_gets leaves the newline on */
+ for(i=0;i<sizeof(tuser);i++) {
+ if (tuser[i] == '\n') {
+ tuser[i] = '\0';
+ break;
+ }
+ }
+ strcpy(user,tuser);
+ }
+ pk_encode(user,xuser,&ck);
+
+ /* send it off */
+ if (auth_debug_mode)
+ printf("Sent KAB(U)\r\n");
+ if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
+ if (auth_debug_mode)
+ printf("Not enough room\r\n");
+ return;
+ }
+ break;
+
+ case SRA_CONTINUE:
+ if (passwd_sent) {
+ passwd_sent = 0;
+ printf("[ SRA login failed ]\r\n");
+ goto enc_user;
+ }
+ /* encode password */
+ memset(pass,0,sizeof(pass));
+ telnet_gets("Password: ",pass,255,0);
+ pk_encode(pass,xpass,&ck);
+ /* send it off */
+ if (auth_debug_mode)
+ printf("Sent KAB(P)\r\n");
+ if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
+ if (auth_debug_mode)
+ printf("Not enough room\r\n");
+ return;
+ }
+ passwd_sent = 1;
+ break;
+
+ case SRA_REJECT:
+ printf("[ SRA refuses authentication ]\r\n");
+ printf("Trying plaintext login:\r\n");
+ auth_finished(0,AUTH_REJECT);
+ return;
+
+ case SRA_ACCEPT:
+ printf("[ SRA accepts you ]\r\n");
+ skey.data = ck;
+ skey.type = SK_DES;
+ skey.length = 8;
+ encrypt_session_key(&skey, 0);
+
+ auth_finished(ap, AUTH_VALID);
+ return;
+ default:
+ if (auth_debug_mode)
+ printf("Unknown SRA option %d\r\n", data[-1]);
+ return;
+ }
+}
+
+int
+sra_status(Authenticator *ap __unused, char *name, int level)
+{
+ if (level < AUTH_USER)
+ return(level);
+ if (UserNameRequested && sra_valid) {
+ strcpy(name, UserNameRequested);
+ 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
+sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
+{
+ char lbuf[32];
+ int i;
+
+ buf[buflen-1] = '\0'; /* make sure its NULL terminated */
+ buflen -= 1;
+
+ switch(data[3]) {
+
+ case SRA_CONTINUE:
+ strncpy((char *)buf, " CONTINUE ", buflen);
+ goto common;
+
+ case SRA_REJECT: /* Rejected (reason might follow) */
+ strncpy((char *)buf, " REJECT ", buflen);
+ goto common;
+
+ case SRA_ACCEPT: /* Accepted (name might follow) */
+ strncpy((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 SRA_KEY: /* Authentication data follows */
+ strncpy((char *)buf, " KEY ", buflen);
+ goto common2;
+
+ case SRA_USER:
+ strncpy((char *)buf, " USER ", buflen);
+ goto common2;
+
+ case SRA_PASS:
+ strncpy((char *)buf, " PASS ", buflen);
+ goto common2;
+
+ default:
+ sprintf(lbuf, " %d (unknown)", data[3]);
+ strncpy((char *)buf, lbuf, buflen);
+ common2:
+ BUMP(buf, buflen);
+ for (i = 4; i < cnt; i++) {
+ sprintf(lbuf, " %d", data[i]);
+ strncpy((char *)buf, lbuf, buflen);
+ BUMP(buf, buflen);
+ }
+ break;
+ }
+}
+
+static int
+isroot(const char *usr)
+{
+ struct passwd *pwd;
+
+ if ((pwd=getpwnam(usr))==NULL)
+ return 0;
+ return (!pwd->pw_uid);
+}
+
+static int
+rootterm(char *ttyn)
+{
+ struct ttyent *t;
+
+ return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
+}
+
+#ifdef NOPAM
+static int
+check_user(char *name, char *cred)
+{
+ char *cp;
+ char *xpasswd, *salt;
+
+ if (isroot(name) && !rootterm(line))
+ {
+ crypt("AA","*"); /* Waste some time to simulate success */
+ return(0);
+ }
+
+ if (pw = sgetpwnam(name)) {
+ if (pw->pw_shell == NULL) {
+ pw = (struct passwd *) NULL;
+ return(0);
+ }
+
+ salt = pw->pw_passwd;
+ xpasswd = crypt(cred, salt);
+ /* The strcmp does not catch null passwords! */
+ if (pw == NULL || *pw->pw_passwd == '\0' ||
+ strcmp(xpasswd, pw->pw_passwd)) {
+ pw = (struct passwd *) NULL;
+ return(0);
+ }
+ return(1);
+ }
+ return(0);
+}
+#else
+
+/*
+ * The following is stolen from ftpd, which stole it from the imap-uw
+ * PAM module and login.c. It is needed because we can't really
+ * "converse" with the user, having already gone to the trouble of
+ * getting their username and password through an encrypted channel.
+ */
+
+#define COPY_STRING(s) (s ? strdup(s):NULL)
+
+struct cred_t {
+ const char *uname;
+ const char *pass;
+};
+typedef struct cred_t cred_t;
+
+static int
+auth_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata)
+{
+ int i;
+ cred_t *cred = (cred_t *) appdata;
+ struct pam_response *reply =
+ malloc(sizeof(struct pam_response) * num_msg);
+
+ if (reply == NULL)
+ return PAM_BUF_ERR;
+
+ for (i = 0; i < num_msg; i++) {
+ switch (msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_ON: /* assume want user name */
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = COPY_STRING(cred->uname);
+ /* PAM frees resp. */
+ break;
+ case PAM_PROMPT_ECHO_OFF: /* assume want password */
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = COPY_STRING(cred->pass);
+ /* PAM frees resp. */
+ break;
+ case PAM_TEXT_INFO:
+ case PAM_ERROR_MSG:
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = NULL;
+ break;
+ default: /* unknown message style */
+ free(reply);
+ return PAM_CONV_ERR;
+ }
+ }
+
+ *resp = reply;
+ return PAM_SUCCESS;
+}
+
+/*
+ * The PAM version as a side effect may put a new username in *name.
+ */
+static int
+check_user(char *name, char *cred)
+{
+ pam_handle_t *pamh = NULL;
+ const void *item;
+ int rval;
+ int e;
+ cred_t auth_cred = { name, cred };
+ struct pam_conv conv = { &auth_conv, &auth_cred };
+
+ e = pam_start("telnetd", name, &conv, &pamh);
+ if (e != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
+ return 0;
+ }
+
+#if 0 /* Where can we find this value? */
+ e = pam_set_item(pamh, PAM_RHOST, remotehost);
+ if (e != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
+ pam_strerror(pamh, e));
+ return 0;
+ }
+#endif
+
+ e = pam_authenticate(pamh, 0);
+ switch (e) {
+ case PAM_SUCCESS:
+ /*
+ * With PAM we support the concept of a "template"
+ * user. The user enters a login name which is
+ * authenticated by PAM, usually via a remote service
+ * such as RADIUS or TACACS+. If authentication
+ * succeeds, a different but related "template" name
+ * is used for setting the credentials, shell, and
+ * home directory. The name the user enters need only
+ * exist on the remote authentication server, but the
+ * template name must be present in the local password
+ * database.
+ *
+ * This is supported by two various mechanisms in the
+ * individual modules. However, from the application's
+ * point of view, the template user is always passed
+ * back as a changed value of the PAM_USER item.
+ */
+ if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
+ PAM_SUCCESS) {
+ strcpy(name, item);
+ } else
+ syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
+ pam_strerror(pamh, e));
+ if (isroot(name) && !rootterm(line))
+ rval = 0;
+ else
+ rval = 1;
+ break;
+
+ case PAM_AUTH_ERR:
+ case PAM_USER_UNKNOWN:
+ case PAM_MAXTRIES:
+ rval = 0;
+ break;
+
+ default:
+ syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
+ rval = 0;
+ break;
+ }
+
+ if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
+ rval = 0;
+ }
+ return rval;
+}
+
+#endif
+
+#endif /* ENCRYPTION */
+#endif /* SRA */