From d7dbd335bfc76ace0a0d3a13a5ba83b7c6734bfc Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Mon, 10 May 2021 14:55:53 -0400 Subject: libtelnet-13 --- lib/libtelnet/LICENSE | 79 ++ lib/libtelnet/auth-proto.h | 110 +++ lib/libtelnet/auth.c | 631 ++++++++++++++ lib/libtelnet/auth.h | 83 ++ lib/libtelnet/enc-proto.h | 126 +++ lib/libtelnet/enc_des.c | 675 +++++++++++++++ lib/libtelnet/encrypt.c | 961 ++++++++++++++++++++++ lib/libtelnet/encrypt.h | 106 +++ lib/libtelnet/forward.c | 70 ++ lib/libtelnet/genget.c | 109 +++ lib/libtelnet/getent.c | 82 ++ lib/libtelnet/kerberos.c | 519 ++++++++++++ lib/libtelnet/kerberos5.c | 888 ++++++++++++++++++++ lib/libtelnet/key-proto.h | 65 ++ lib/libtelnet/krb4encpwd.c | 430 ++++++++++ lib/libtelnet/libtelnet.plist | 22 + lib/libtelnet/libtelnet.xcodeproj/project.pbxproj | 313 +++++++ lib/libtelnet/misc-proto.h | 80 ++ lib/libtelnet/misc.c | 114 +++ lib/libtelnet/misc.h | 42 + lib/libtelnet/pk.c | 269 ++++++ lib/libtelnet/pk.h | 59 ++ lib/libtelnet/read_password.c | 153 ++++ lib/libtelnet/rsaencpwd.c | 475 +++++++++++ lib/libtelnet/sra.c | 604 ++++++++++++++ 25 files changed, 7065 insertions(+) create mode 100644 lib/libtelnet/LICENSE create mode 100644 lib/libtelnet/auth-proto.h create mode 100644 lib/libtelnet/auth.c create mode 100644 lib/libtelnet/auth.h create mode 100644 lib/libtelnet/enc-proto.h create mode 100644 lib/libtelnet/enc_des.c create mode 100644 lib/libtelnet/encrypt.c create mode 100644 lib/libtelnet/encrypt.h create mode 100644 lib/libtelnet/forward.c create mode 100644 lib/libtelnet/genget.c create mode 100644 lib/libtelnet/getent.c create mode 100644 lib/libtelnet/kerberos.c create mode 100644 lib/libtelnet/kerberos5.c create mode 100644 lib/libtelnet/key-proto.h create mode 100644 lib/libtelnet/krb4encpwd.c create mode 100644 lib/libtelnet/libtelnet.plist create mode 100644 lib/libtelnet/libtelnet.xcodeproj/project.pbxproj create mode 100644 lib/libtelnet/misc-proto.h create mode 100644 lib/libtelnet/misc.c create mode 100644 lib/libtelnet/misc.h create mode 100644 lib/libtelnet/pk.c create mode 100644 lib/libtelnet/pk.h create mode 100644 lib/libtelnet/read_password.c create mode 100644 lib/libtelnet/rsaencpwd.c create mode 100644 lib/libtelnet/sra.c 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 + +#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 +#include +#include +#include +#include +#include +#include + +#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 + +#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 +#include +#include +#include +#include + +#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 + +#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 +#include +#include +#include + +#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 [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 [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 [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 +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 +#include +#include +#include + +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 + +#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 + +#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 + +#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 +#include + +#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 + +#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 +#include +#include /* BSD wont include this in krb.h, so we do it here */ +#include +#include +#include +#include + +#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 +#include +#define KRB5_DEPRECATED 1 /* krb5_auth_con_getremotesubkey */ +#include +#include "com_err.h" +#include +#include +#include +#include + +#ifdef HAVE_STDLIB_H +#include +#else +extern char *malloc(); +#endif +#ifdef HAVE_STRING_H +#include +#else +#include +#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 + +#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 +#include +#include +#include +#include +#include +#include +#include + +#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 @@ + + + + + + OpenSourceImportDate + 2002-05-20 + OpenSourceLicense + BSD + OpenSourceLicenseFile + libtelnet.txt + OpenSourceProject + libtelnet + OpenSourceVersion + 2002-05-20 + OpenSourceCVS + cvs -d freebsdanoncvs@anoncvs.FreeBSD.org:/home/ncvs co lib/libtelnet + OpenSourceWebsiteURL + http://www.freebsd.org/ + + + 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 = ""; }; + FD9922FD0FEB057C00E57170 /* auth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = auth.c; sourceTree = ""; }; + FD9922FE0FEB057C00E57170 /* auth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = auth.h; sourceTree = ""; }; + FD9923010FEB057C00E57170 /* enc_des.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = enc_des.c; sourceTree = ""; }; + FD9923020FEB057C00E57170 /* enc-proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "enc-proto.h"; sourceTree = ""; }; + FD9923030FEB057C00E57170 /* encrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = encrypt.c; sourceTree = ""; }; + FD9923040FEB057C00E57170 /* encrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = encrypt.h; sourceTree = ""; }; + FD9923050FEB057C00E57170 /* forward.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = forward.c; sourceTree = ""; }; + FD9923060FEB057C00E57170 /* genget.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = genget.c; sourceTree = ""; }; + FD9923070FEB057C00E57170 /* getent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = getent.c; sourceTree = ""; }; + FD9923080FEB057C00E57170 /* kerberos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kerberos.c; sourceTree = ""; }; + FD9923090FEB057C00E57170 /* kerberos5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kerberos5.c; sourceTree = ""; }; + FD99230A0FEB057C00E57170 /* key-proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "key-proto.h"; sourceTree = ""; }; + FD99230B0FEB057C00E57170 /* krb4encpwd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = krb4encpwd.c; sourceTree = ""; }; + FD99230C0FEB057C00E57170 /* libtelnet.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = libtelnet.plist; sourceTree = ""; }; + FD99230D0FEB057C00E57170 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + FD99230F0FEB057C00E57170 /* misc-proto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "misc-proto.h"; sourceTree = ""; }; + FD9923100FEB057C00E57170 /* misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = misc.c; sourceTree = ""; }; + FD9923110FEB057C00E57170 /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = ""; }; + FD9923120FEB057C00E57170 /* pk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pk.c; sourceTree = ""; }; + FD9923130FEB057C00E57170 /* pk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pk.h; sourceTree = ""; }; + FD9923140FEB057C00E57170 /* read_password.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = read_password.c; sourceTree = ""; }; + FD9923150FEB057C00E57170 /* rsaencpwd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rsaencpwd.c; sourceTree = ""; }; + FD9923160FEB057C00E57170 /* sra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sra.c; sourceTree = ""; }; +/* 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 = ""; + }; + 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 = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + D2AAC046055464E500DB518D /* libtelnet.a */, + ); + name = Products; + sourceTree = ""; + }; + C6A0FF2B0290797F04C91782 /* Documentation */ = { + isa = PBXGroup; + children = ( + FD99230C0FEB057C00E57170 /* libtelnet.plist */, + FD99230D0FEB057C00E57170 /* LICENSE */, + ); + name = Documentation; + sourceTree = ""; + }; +/* 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 + +#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 +#include +#include + +#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 + +__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 +#include +#include +#include +#include +#include + +#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> 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 '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 + +#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 + * . + * + * 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 +#include +#include +#include +#include + +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 + +__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 +#include +#include +#include +#include +#include + +#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;iway & 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 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 + +#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 +#include +#include +#include +#include +#include +#include +#include + +#ifndef NOPAM +#include +#else +#include +#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 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 */ -- cgit v1.2.3-56-ge451