diff options
author | markm <markm@FreeBSD.org> | 1997-09-04 06:11:16 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 1997-09-04 06:11:16 +0000 |
commit | a9e6ba3f81bf9daf246d3fa948bc174190bd15dc (patch) | |
tree | 081b7e52d5745c9a970536ccf536dfc1dc9f2402 /contrib/telnet/libtelnet | |
download | FreeBSD-src-a9e6ba3f81bf9daf246d3fa948bc174190bd15dc.zip FreeBSD-src-a9e6ba3f81bf9daf246d3fa948bc174190bd15dc.tar.gz |
Initial import of BSD telnet. This will be used to build the kerberised
telnet, and after userland diffs have been merged in, will be used to
build the non-kerberised sources as well. (See unifdef(1) for details)
Diffstat (limited to 'contrib/telnet/libtelnet')
-rw-r--r-- | contrib/telnet/libtelnet/auth-proto.h | 96 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/auth.c | 671 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/auth.h | 87 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/enc-proto.h | 125 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/enc_des.c | 724 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/encrypt.c | 1000 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/encrypt.h | 108 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/genget.c | 105 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/getent.c | 68 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/kerberos.c | 560 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/kerberos5.c | 764 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/key-proto.h | 71 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/krb4encpwd.c | 446 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/misc-proto.h | 79 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/misc.c | 94 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/misc.h | 42 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/read_password.c | 145 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/rsaencpwd.c | 492 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/spx.c | 588 |
19 files changed, 6265 insertions, 0 deletions
diff --git a/contrib/telnet/libtelnet/auth-proto.h b/contrib/telnet/libtelnet/auth-proto.h new file mode 100644 index 0000000..06bba2b --- /dev/null +++ b/contrib/telnet/libtelnet/auth-proto.h @@ -0,0 +1,96 @@ +/*- + * 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 + */ + +/* + * 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. + */ + +#if !defined(P) +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif +#endif + +#if defined(AUTHENTICATION) +Authenticator *findauthenticator P((int, int)); + +void auth_init P((char *, int)); +int auth_cmd P((int, char **)); +void auth_request P((void)); +void auth_send P((unsigned char *, int)); +void auth_send_retry P((void)); +void auth_is P((unsigned char *, int)); +void auth_reply P((unsigned char *, int)); +void auth_finished P((Authenticator *, int)); +int auth_wait P((char *)); +void auth_disable_name P((char *)); +void auth_gen_printsub P((unsigned char *, int, unsigned char *, int)); + +#ifdef KRB4 +int kerberos4_init P((Authenticator *, int)); +int kerberos4_send P((Authenticator *)); +void kerberos4_is P((Authenticator *, unsigned char *, int)); +void kerberos4_reply P((Authenticator *, unsigned char *, int)); +int kerberos4_status P((Authenticator *, char *, int)); +void kerberos4_printsub P((unsigned char *, int, unsigned char *, int)); +#endif + +#ifdef KRB5 +int kerberos5_init P((Authenticator *, int)); +int kerberos5_send P((Authenticator *)); +void kerberos5_is P((Authenticator *, unsigned char *, int)); +void kerberos5_reply P((Authenticator *, unsigned char *, int)); +int kerberos5_status P((Authenticator *, char *, int)); +void kerberos5_printsub P((unsigned char *, int, unsigned char *, int)); +#endif +#endif diff --git a/contrib/telnet/libtelnet/auth.c b/contrib/telnet/libtelnet/auth.c new file mode 100644 index 0000000..a8b287c --- /dev/null +++ b/contrib/telnet/libtelnet/auth.c @@ -0,0 +1,671 @@ +/*- + * 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. + */ + +#ifndef lint +static 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. + */ + + +#if defined(AUTHENTICATION) +#include <stdio.h> +#include <sys/types.h> +#include <signal.h> +#define AUTH_NAMES +#include <arpa/telnet.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif +#ifdef NO_STRING_H +#include <strings.h> +#else +#include <string.h> +#endif + +#include "encrypt.h" +#include "auth.h" +#include "misc-proto.h" +#include "auth-proto.h" + +#define typemask(x) (1<<((x)-1)) + +#ifdef KRB4_ENCPWD +extern krb4encpwd_init(); +extern krb4encpwd_send(); +extern krb4encpwd_is(); +extern krb4encpwd_reply(); +extern krb4encpwd_status(); +extern krb4encpwd_printsub(); +#endif + +#ifdef RSA_ENCPWD +extern rsaencpwd_init(); +extern rsaencpwd_send(); +extern rsaencpwd_is(); +extern rsaencpwd_reply(); +extern rsaencpwd_status(); +extern rsaencpwd_printsub(); +#endif + +int auth_debug_mode = 0; +static char *Name = "Noname"; +static int Server = 0; +static Authenticator *authenticated = 0; +static int authenticating = 0; +static int validuser = 0; +static unsigned char _auth_send_data[256]; +static unsigned char *auth_send_data; +static int auth_send_cnt = 0; + +/* + * Authentication types supported. Plese note that these are stored + * in priority order, i.e. try the first one first. + */ +Authenticator authenticators[] = { +#ifdef SPX + { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL, + spx_init, + spx_send, + spx_is, + spx_reply, + spx_status, + spx_printsub }, + { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + spx_init, + spx_send, + spx_is, + spx_reply, + spx_status, + spx_printsub }, +#endif +#ifdef KRB5 +# 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 + { 0, }, +}; + +static Authenticator NoAuth = { 0 }; + +static int i_support = 0; +static int i_wont_support = 0; + + Authenticator * +findauthenticator(type, way) + 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(name, server) + 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(name) + char *name; +{ + int x; + for (x = 0; x < AUTHTYPE_CNT; ++x) { + if (!strcasecmp(name, AUTHTYPE_NAME(x))) { + i_wont_support |= typemask(x); + break; + } + } +} + + int +getauthmask(type, maskp) + char *type; + int *maskp; +{ + register int x; + + if (!strcasecmp(type, AUTHTYPE_NAME(0))) { + *maskp = -1; + return(1); + } + + for (x = 1; x < AUTHTYPE_CNT; ++x) { + if (!strcasecmp(type, AUTHTYPE_NAME(x))) { + *maskp = typemask(x); + return(1); + } + } + return(0); +} + + int +auth_enable(type) + char *type; +{ + return(auth_onoff(type, 1)); +} + + int +auth_disable(type) + char *type; +{ + return(auth_onoff(type, 0)); +} + + int +auth_onoff(type, on) + 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(on) + 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() +{ + 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() +{ + 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(data, cnt) + unsigned char *data; + int cnt; +{ + Authenticator *ap; + static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_IS, AUTHTYPE_NULL, 0, + IAC, SE }; + if (Server) { + if (auth_debug_mode) { + printf(">>>%s: auth_send called!\r\n", Name); + } + return; + } + + if (auth_debug_mode) { + printf(">>>%s: auth_send got:", Name); + printd(data, cnt); printf("\r\n"); + } + + /* + * Save the data, if it is new, so that we can continue looking + * at it if the authorization we try doesn't work + */ + if (data < _auth_send_data || + data > _auth_send_data + sizeof(_auth_send_data)) { + auth_send_cnt = cnt > sizeof(_auth_send_data) + ? sizeof(_auth_send_data) + : cnt; + memmove((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); +#ifdef KANNAN + /* + * We requested strong authentication, however no mechanisms worked. + * Therefore, exit on client end. + */ + printf("Unable to securely authenticate user ... exit\n"); + exit(0); +#endif /* KANNAN */ +} + + void +auth_send_retry() +{ + /* + * 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(data, cnt) + 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(data, cnt) + 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(data, cnt) + unsigned char *data; + int cnt; +{ + Authenticator *ap; + unsigned char savename[256]; + + if (cnt < 1) { + if (auth_debug_mode) + printf(">>>%s: Empty name in NAME\r\n", Name); + return; + } + if (cnt > sizeof(savename) - 1) { + if (auth_debug_mode) + printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n", + Name, cnt, 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); + auth_encrypt_user(savename); +} + + int +auth_sendname(cp, len) + unsigned char *cp; + int len; +{ + static unsigned char str_request[256+6] + = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, }; + register unsigned char *e = str_request + 4; + register 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(ap, result) + Authenticator *ap; + int result; +{ + if (!(authenticated = ap)) + authenticated = &NoAuth; + validuser = result; +} + + /* ARGSUSED */ + static void +auth_intr(sig) + int sig; +{ + auth_finished(0, AUTH_REJECT); +} + + int +auth_wait(name) + 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_debug(mode) + int mode; +{ + auth_debug_mode = mode; +} + + void +auth_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, 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(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + register 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/contrib/telnet/libtelnet/auth.h b/contrib/telnet/libtelnet/auth.h new file mode 100644 index 0000000..615e8a0 --- /dev/null +++ b/contrib/telnet/libtelnet/auth.h @@ -0,0 +1,87 @@ +/*- + * 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 + */ + +/* + * 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 */ + +#if !defined(P) +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif +#endif + +typedef struct XauthP { + int type; + int way; + int (*init) P((struct XauthP *, int)); + int (*send) P((struct XauthP *)); + void (*is) P((struct XauthP *, unsigned char *, int)); + void (*reply) P((struct XauthP *, unsigned char *, int)); + int (*status) P((struct XauthP *, char *, int)); + void (*printsub) P((unsigned char *, int, unsigned char *, int)); +} Authenticator; + +#include "auth-proto.h" + +extern auth_debug_mode; +#endif diff --git a/contrib/telnet/libtelnet/enc-proto.h b/contrib/telnet/libtelnet/enc-proto.h new file mode 100644 index 0000000..2e30908 --- /dev/null +++ b/contrib/telnet/libtelnet/enc-proto.h @@ -0,0 +1,125 @@ +/*- + * 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 + */ + +/* + * 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. + */ +#if !defined(P) +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif +#endif + +#ifdef ENCRYPTION +void encrypt_init P((char *, int)); +Encryptions *findencryption P((int)); +void encrypt_send_supprt P((void)); +void encrypt_auto P((int)); +void decrypt_auto P((int)); +void encrypt_is P((unsigned char *, int)); +void encrypt_reply P((unsigned char *, int)); +void encrypt_start_input P((int)); +void encrypt_session_key P((Session_Key *, int)); +void encrypt_end_input P((void)); +void encrypt_start_output P((int)); +void encrypt_end_output P((void)); +void encrypt_send_request_start P((void)); +void encrypt_send_request_end P((void)); +void encrypt_send_end P((void)); +void encrypt_wait P((void)); +void encrypt_send_support P((void)); +void encrypt_send_keyid P((int, unsigned char *, int, int)); +int net_write P((unsigned char *, int)); + +#ifdef TELENTD +void encrypt_wait P((void)); +#else +int encrypt_cmd P((int, char **)); +void encrypt_display P((void)); +#endif + +void krbdes_encrypt P((unsigned char *, int)); +int krbdes_decrypt P((int)); +int krbdes_is P((unsigned char *, int)); +int krbdes_reply P((unsigned char *, int)); +void krbdes_init P((int)); +int krbdes_start P((int, int)); +void krbdes_session P((Session_Key *, int)); +void krbdes_printsub P((unsigned char *, int, unsigned char *, int)); + +void cfb64_encrypt P((unsigned char *, int)); +int cfb64_decrypt P((int)); +void cfb64_init P((int)); +int cfb64_start P((int, int)); +int cfb64_is P((unsigned char *, int)); +int cfb64_reply P((unsigned char *, int)); +void cfb64_session P((Session_Key *, int)); +int cfb64_keyid P((int, unsigned char *, int *)); +void cfb64_printsub P((unsigned char *, int, unsigned char *, int)); + +void ofb64_encrypt P((unsigned char *, int)); +int ofb64_decrypt P((int)); +void ofb64_init P((int)); +int ofb64_start P((int, int)); +int ofb64_is P((unsigned char *, int)); +int ofb64_reply P((unsigned char *, int)); +void ofb64_session P((Session_Key *, int)); +int ofb64_keyid P((int, unsigned char *, int *)); +void ofb64_printsub P((unsigned char *, int, unsigned char *, int)); + +int des_new_random_key P((Block)); +void des_set_random_generator_seed P((Block)); +void des_key_sched P((Block, Schedule)); +void des_ecb_encrypt P((Block, Block, Schedule, int)); +int des_string_to_key P((char *, Block)); +#endif /* ENCRYPTION */ diff --git a/contrib/telnet/libtelnet/enc_des.c b/contrib/telnet/libtelnet/enc_des.c new file mode 100644 index 0000000..d6886fd --- /dev/null +++ b/contrib/telnet/libtelnet/enc_des.c @@ -0,0 +1,724 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)enc_des.c 8.3 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#ifdef ENCRYPTION +# ifdef AUTHENTICATION +# ifdef DES_ENCRYPTION +#include <arpa/telnet.h> +#include <stdio.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif + +#include "encrypt.h" +#include "key-proto.h" +#include "misc-proto.h" + +extern 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 { + 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 P((Block, struct stinfo *)); +void fb64_init P((struct fb *)); +static int fb64_start P((struct fb *, int, int)); +int fb64_is P((unsigned char *, int, struct fb *)); +int fb64_reply P((unsigned char *, int, struct fb *)); +static void fb64_session P((Session_Key *, int, struct fb *)); +void fb64_stream_key P((Block, struct stinfo *)); +int fb64_keyid P((int, unsigned char *, int *, struct fb *)); + + void +cfb64_init(server) + int server; +{ + fb64_init(&fb[CFB]); + fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64; + fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB); + fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB); +} + + void +ofb64_init(server) + int server; +{ + fb64_init(&fb[OFB]); + fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64; + fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB); + fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB); +} + + void +fb64_init(fbp) + register 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(dir, server) + int dir; + int server; +{ + return(fb64_start(&fb[CFB], dir, server)); +} + int +ofb64_start(dir, server) + int dir; + int server; +{ + return(fb64_start(&fb[OFB], dir, server)); +} + + static int +fb64_start(fbp, dir, server) + struct fb *fbp; + int dir; + int server; +{ + Block b; + int x; + unsigned char *p; + register 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(fbp->temp_feed, fbp->temp_feed, + fbp->krbdes_sched, 1); + p = fbp->fb_feed + 3; + *p++ = ENCRYPT_IS; + p++; + *p++ = FB64_IV; + for (x = 0; x < sizeof(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(data, cnt) + unsigned char *data; + int cnt; +{ + return(fb64_is(data, cnt, &fb[CFB])); +} + int +ofb64_is(data, cnt) + unsigned char *data; + int cnt; +{ + return(fb64_is(data, cnt, &fb[OFB])); +} + + int +fb64_is(data, cnt, fbp) + unsigned char *data; + int cnt; + struct fb *fbp; +{ + int x; + unsigned char *p; + Block b; + register 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(data, cnt) + unsigned char *data; + int cnt; +{ + return(fb64_reply(data, cnt, &fb[CFB])); +} + int +ofb64_reply(data, cnt) + unsigned char *data; + int cnt; +{ + return(fb64_reply(data, cnt, &fb[OFB])); +} + + + int +fb64_reply(data, cnt, fbp) + unsigned char *data; + int cnt; + struct fb *fbp; +{ + int x; + unsigned char *p; + Block b; + register int state = fbp->state[DIR_ENCRYPT-1]; + + if (cnt-- < 1) + goto failure; + + switch (*data++) { + case FB64_IV_OK: + fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]); + if (state == FAILED) + state = IN_PROGRESS; + state &= ~NO_RECV_IV; + encrypt_send_keyid(DIR_ENCRYPT, (unsigned char *)"\0", 1, 1); + break; + + case FB64_IV_BAD: + memset(fbp->temp_feed, 0, sizeof(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(key, server) + Session_Key *key; + int server; +{ + fb64_session(key, server, &fb[CFB]); +} + + void +ofb64_session(key, server) + Session_Key *key; + int server; +{ + fb64_session(key, server, &fb[OFB]); +} + + static void +fb64_session(key, server, fbp) + 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(dir, kp, lenp) + int dir, *lenp; + unsigned char *kp; +{ + return(fb64_keyid(dir, kp, lenp, &fb[CFB])); +} + + int +ofb64_keyid(dir, kp, lenp) + int dir, *lenp; + unsigned char *kp; +{ + return(fb64_keyid(dir, kp, lenp, &fb[OFB])); +} + + int +fb64_keyid(dir, kp, lenp, fbp) + int dir, *lenp; + unsigned char *kp; + struct fb *fbp; +{ + register 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(data, cnt, buf, buflen, type) + unsigned char *data, *buf, *type; + int cnt, buflen; +{ + char lbuf[32]; + register 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(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + fb64_printsub(data, cnt, buf, buflen, "CFB64"); +} + + void +ofb64_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + fb64_printsub(data, cnt, buf, buflen, "OFB64"); +} + + void +fb64_stream_iv(seed, stp) + Block seed; + register 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(key, stp) + Block key; + register 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(s, c) + register unsigned char *s; + int c; +{ + register struct stinfo *stp = &fb[CFB].streams[DIR_ENCRYPT-1]; + register int index; + + index = stp->str_index; + while (c-- > 0) { + if (index == sizeof(Block)) { + Block b; + des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1); + memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); + index = 0; + } + + /* On encryption, we store (feed ^ data) which is cypher */ + *s = stp->str_output[index] = (stp->str_feed[index] ^ *s); + s++; + index++; + } + stp->str_index = index; +} + + int +cfb64_decrypt(data) + int data; +{ + register struct stinfo *stp = &fb[CFB].streams[DIR_DECRYPT-1]; + int index; + + if (data == -1) { + /* + * Back up one byte. It is assumed that we will + * never back up more than one byte. If we do, this + * may or may not work. + */ + if (stp->str_index) + --stp->str_index; + return(0); + } + + index = stp->str_index++; + if (index == sizeof(Block)) { + Block b; + des_ecb_encrypt(stp->str_output, b, stp->str_sched, 1); + memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); + stp->str_index = 1; /* Next time will be 1 */ + index = 0; /* But now use 0 */ + } + + /* On decryption we store (data) which is cypher. */ + stp->str_output[index] = data; + return(data ^ stp->str_feed[index]); +} + +/* + * DES 64 bit Output Feedback + * + * key --->+-----+ + * +->| DES |--+ + * | +-----+ | + * +-----------+ + * v + * INPUT -------->(+) ----> DATA + * + * Given: + * iV: Initial vector, 64 bits (8 bytes) long. + * Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt). + * On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output. + * + * V0 = DES(iV, key) + * V(n+1) = DES(Vn, key) + * On = Dn ^ Vn + */ + void +ofb64_encrypt(s, c) + register unsigned char *s; + int c; +{ + register struct stinfo *stp = &fb[OFB].streams[DIR_ENCRYPT-1]; + register int index; + + index = stp->str_index; + while (c-- > 0) { + if (index == sizeof(Block)) { + Block b; + des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1); + memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); + index = 0; + } + *s++ ^= stp->str_feed[index]; + index++; + } + stp->str_index = index; +} + + int +ofb64_decrypt(data) + int data; +{ + register struct stinfo *stp = &fb[OFB].streams[DIR_DECRYPT-1]; + int index; + + if (data == -1) { + /* + * Back up one byte. It is assumed that we will + * never back up more than one byte. If we do, this + * may or may not work. + */ + if (stp->str_index) + --stp->str_index; + return(0); + } + + index = stp->str_index++; + if (index == sizeof(Block)) { + Block b; + des_ecb_encrypt(stp->str_feed, b, stp->str_sched, 1); + memmove((void *)stp->str_feed, (void *)b, sizeof(Block)); + stp->str_index = 1; /* Next time will be 1 */ + index = 0; /* But now use 0 */ + } + + return(data ^ stp->str_feed[index]); +} +# endif /* DES_ENCRYPTION */ +# endif /* AUTHENTICATION */ +#endif /* ENCRYPTION */ diff --git a/contrib/telnet/libtelnet/encrypt.c b/contrib/telnet/libtelnet/encrypt.c new file mode 100644 index 0000000..432df0c --- /dev/null +++ b/contrib/telnet/libtelnet/encrypt.c @@ -0,0 +1,1000 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)encrypt.c 8.2 (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 ENCRYPTION + +#define ENCRYPT_NAMES +#include <arpa/telnet.h> + +#include "encrypt.h" +#include "misc.h" + +#ifdef __STDC__ +#include <stdlib.h> +#endif +#ifdef NO_STRING_H +#include <strings.h> +#else +#include <string.h> +#endif + +/* + * These functions pointers point to the current routines + * for encrypting and decrypting data. + */ +void (*encrypt_output) P((unsigned char *, int)); +int (*decrypt_input) P((int)); + +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 char *Name = "Noname"; + +#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) + +static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64) + | typemask(ENCTYPE_DES_OFB64); +static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64) + | typemask(ENCTYPE_DES_OFB64); +static long i_wont_support_encrypt = 0; +static long i_wont_support_decrypt = 0; +#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) +#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) + +static long remote_supports_encrypt = 0; +static long remote_supports_decrypt = 0; + +static Encryptions encryptions[] = { +#ifdef DES_ENCRYPTION + { "DES_CFB64", ENCTYPE_DES_CFB64, + cfb64_encrypt, + cfb64_decrypt, + cfb64_init, + cfb64_start, + cfb64_is, + cfb64_reply, + cfb64_session, + cfb64_keyid, + cfb64_printsub }, + { "DES_OFB64", ENCTYPE_DES_OFB64, + ofb64_encrypt, + ofb64_decrypt, + ofb64_init, + ofb64_start, + ofb64_is, + ofb64_reply, + ofb64_session, + ofb64_keyid, + ofb64_printsub }, +#endif /* DES_ENCRYPTION */ + { 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(type) + int type; +{ + Encryptions *ep = encryptions; + + if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type))) + return(0); + while (ep->type && ep->type != type) + ++ep; + return(ep->type ? ep : 0); +} + + Encryptions * +finddecryption(type) + int type; +{ + Encryptions *ep = encryptions; + + if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type))) + return(0); + while (ep->type && ep->type != type) + ++ep; + return(ep->type ? ep : 0); +} + +#define MAXKEYLEN 64 + +static struct key_info { + unsigned char keyid[MAXKEYLEN]; + int keylen; + int dir; + int *modep; + Encryptions *(*getcrypt)(); +} ki[2] = { + { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, + { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, +}; + + void +encrypt_init(name, server) + char *name; + int server; +{ + Encryptions *ep = encryptions; + + Name = name; + Server = server; + i_support_encrypt = i_support_decrypt = 0; + remote_supports_encrypt = remote_supports_decrypt = 0; + encrypt_mode = 0; + decrypt_mode = 0; + encrypt_output = 0; + decrypt_input = 0; +#ifdef notdef + encrypt_verbose = !server; +#endif + + str_suplen = 4; + + while (ep->type) { + if (encrypt_debug_mode) + printf(">>>%s: I will support %s\r\n", + Name, ENCTYPE_NAME(ep->type)); + i_support_encrypt |= typemask(ep->type); + i_support_decrypt |= typemask(ep->type); + if ((i_wont_support_decrypt & typemask(ep->type)) == 0) + if ((str_send[str_suplen++] = ep->type) == IAC) + str_send[str_suplen++] = IAC; + if (ep->init) + (*ep->init)(Server); + ++ep; + } + str_send[str_suplen++] = IAC; + str_send[str_suplen++] = SE; +} + + void +encrypt_list_types() +{ + 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(type, mode) + char *type, *mode; +{ + if (isprefix(type, "help") || isprefix(type, "?")) { + printf("Usage: encrypt enable <type> [input|output]\n"); + encrypt_list_types(); + return(0); + } + if (EncryptType(type, mode)) + return(EncryptStart(mode)); + return(0); +} + + int +EncryptDisable(type, mode) + char *type, *mode; +{ + register Encryptions *ep; + int ret = 0; + + if (isprefix(type, "help") || isprefix(type, "?")) { + printf("Usage: encrypt disable <type> [input|output]\n"); + encrypt_list_types(); + } else if ((ep = (Encryptions *)genget(type, encryptions, + sizeof(Encryptions))) == 0) { + printf("%s: invalid encryption type\n", type); + } else if (Ambiguous(ep)) { + printf("Ambiguous type '%s'\n", type); + } else { + if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) { + if (decrypt_mode == ep->type) + EncryptStopInput(); + i_wont_support_decrypt |= typemask(ep->type); + ret = 1; + } + if ((mode == 0) || (isprefix(mode, "output"))) { + if (encrypt_mode == ep->type) + EncryptStopOutput(); + i_wont_support_encrypt |= typemask(ep->type); + ret = 1; + } + if (ret == 0) + printf("%s: invalid encryption mode\n", mode); + } + return(ret); +} + + int +EncryptType(type, mode) + char *type; + char *mode; +{ + register Encryptions *ep; + int ret = 0; + + if (isprefix(type, "help") || isprefix(type, "?")) { + printf("Usage: encrypt type <type> [input|output]\n"); + encrypt_list_types(); + } else if ((ep = (Encryptions *)genget(type, encryptions, + sizeof(Encryptions))) == 0) { + printf("%s: invalid encryption type\n", type); + } else if (Ambiguous(ep)) { + printf("Ambiguous type '%s'\n", type); + } else { + if ((mode == 0) || isprefix(mode, "input")) { + decrypt_mode = ep->type; + i_wont_support_decrypt &= ~typemask(ep->type); + ret = 1; + } + if ((mode == 0) || isprefix(mode, "output")) { + encrypt_mode = ep->type; + i_wont_support_encrypt &= ~typemask(ep->type); + ret = 1; + } + if (ret == 0) + printf("%s: invalid encryption mode\n", mode); + } + return(ret); +} + + int +EncryptStart(mode) + char *mode; +{ + register 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() +{ + if (decrypt_mode) { + encrypt_send_request_start(); + return(1); + } + printf("No previous decryption mode, decryption not enabled\r\n"); + return(0); +} + + int +EncryptStartOutput() +{ + if (encrypt_mode) { + encrypt_start_output(encrypt_mode); + return(1); + } + printf("No previous encryption mode, encryption not enabled\r\n"); + return(0); +} + + int +EncryptStop(mode) + 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() +{ + encrypt_send_request_end(); + return(1); +} + + int +EncryptStopOutput() +{ + encrypt_send_end(); + return(1); +} + + void +encrypt_display() +{ + 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() +{ + 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() +{ + 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(on) + 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(on) + 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(on) + int on; +{ + encrypt_auto(on); + printf("Automatic encryption of output is %s\r\n", + autoencrypt ? "enabled" : "disabled"); + return(1); +} + + int +EncryptAutoDec(on) + 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(typelist, cnt) + unsigned char *typelist; + int cnt; +{ + register 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(data, cnt) + unsigned char *data; + int cnt; +{ + Encryptions *ep; + register 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)(%x, %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(data, cnt) + unsigned char *data; + int cnt; +{ + Encryptions *ep; + register 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)(%x, %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(data, cnt) + unsigned char *data; + int cnt; +{ + Encryptions *ep; + + if (!decrypt_mode) { + /* + * Something is wrong. We should not get a START + * command without having already picked our + * decryption scheme. Send a REQUEST-END to + * attempt to clear the channel... + */ + printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name); + encrypt_send_request_end(); + return; + } + + if (ep = finddecryption(decrypt_mode)) { + decrypt_input = ep->input; + if (encrypt_verbose) + printf("[ Input is now decrypted with type %s ]\r\n", + ENCTYPE_NAME(decrypt_mode)); + if (encrypt_debug_mode) + printf(">>>%s: Start to decrypt input with type %s\r\n", + Name, ENCTYPE_NAME(decrypt_mode)); + } else { + printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n", + Name, + ENCTYPE_NAME_OK(decrypt_mode) + ? ENCTYPE_NAME(decrypt_mode) + : "(unknown)", + decrypt_mode); + encrypt_send_request_end(); + } +} + + void +encrypt_session_key(key, server) + Session_Key *key; + int server; +{ + Encryptions *ep = encryptions; + + havesessionkey = 1; + + while (ep->type) { + if (ep->session) + (*ep->session)(key, server); +#ifdef notdef + if (!encrypt_output && autoencrypt && !server) + encrypt_start_output(ep->type); + if (!decrypt_input && autodecrypt && !server) + encrypt_send_request_start(); +#endif + ++ep; + } +} + +/* + * Called when ENCRYPT END is received. + */ + void +encrypt_end() +{ + 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() +{ + 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(data, cnt) + unsigned char *data; + int cnt; +{ + if (encrypt_mode == 0) { + if (Server) + autoencrypt = 1; + return; + } + encrypt_start_output(encrypt_mode); +} + +static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; + +encrypt_enc_keyid(keyid, len) + unsigned char *keyid; + int len; +{ + encrypt_keyid(&ki[1], keyid, len); +} + +encrypt_dec_keyid(keyid, len) + unsigned char *keyid; + int len; +{ + encrypt_keyid(&ki[0], keyid, len); +} + +encrypt_keyid(kp, keyid, len) + struct key_info *kp; + unsigned char *keyid; + int len; +{ + Encryptions *ep; + unsigned char *strp, *cp; + int dir = kp->dir; + register int ret = 0; + + if (!(ep = (*kp->getcrypt)(*kp->modep))) { + if (len == 0) + return; + kp->keylen = 0; + } else if (len == 0) { + /* + * Empty option, indicates a failure. + */ + if (kp->keylen == 0) + return; + kp->keylen = 0; + if (ep->keyid) + (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); + + } else if ((len != kp->keylen) || + (memcmp(keyid, kp->keyid, len) != 0)) { + /* + * Length or contents are different + */ + kp->keylen = len; + 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(dir, keyid, keylen, saveit) + int dir; + unsigned char *keyid; + int keylen; + int saveit; +{ + unsigned char *strp; + + str_keyid[3] = (dir == DIR_ENCRYPT) + ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; + if (saveit) { + struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; + 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(on) + int on; +{ + if (on < 0) + autoencrypt ^= 1; + else + autoencrypt = on ? 1 : 0; +} + + void +decrypt_auto(on) + int on; +{ + if (on < 0) + autodecrypt ^= 1; + else + autodecrypt = on ? 1 : 0; +} + + void +encrypt_start_output(type) + int type; +{ + Encryptions *ep; + register unsigned char *p; + register 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() +{ + 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() +{ + register unsigned char *p; + register 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() +{ + 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() +{ + register int encrypt, decrypt; + 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_debug(mode) + int mode; +{ + encrypt_debug_mode = mode; +} + + void +encrypt_gen_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, 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(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + Encryptions *ep; + register 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/contrib/telnet/libtelnet/encrypt.h b/contrib/telnet/libtelnet/encrypt.h new file mode 100644 index 0000000..e0ae385 --- /dev/null +++ b/contrib/telnet/libtelnet/encrypt.h @@ -0,0 +1,108 @@ +/*- + * 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 + */ + +/* + * 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 + +typedef unsigned char Block[8]; +typedef unsigned char *BlockT; +typedef struct { Block _; } Schedule[16]; + +#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; + +# if !defined(P) +# ifdef __STDC__ +# define P(x) x +# else +# define P(x) () +# endif +# endif + +typedef struct { + char *name; + int type; + void (*output) P((unsigned char *, int)); + int (*input) P((int)); + void (*init) P((int)); + int (*start) P((int, int)); + int (*is) P((unsigned char *, int)); + int (*reply) P((unsigned char *, int)); + void (*session) P((Session_Key *, int)); + int (*keyid) P((int, unsigned char *, int *)); + void (*printsub) P((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) P((int)); +extern void (*encrypt_output) P((unsigned char *, int)); +# endif /* __ENCRYPTION__ */ +#endif /* ENCRYPTION */ diff --git a/contrib/telnet/libtelnet/genget.c b/contrib/telnet/libtelnet/genget.c new file mode 100644 index 0000000..7be3846 --- /dev/null +++ b/contrib/telnet/libtelnet/genget.c @@ -0,0 +1,105 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)genget.c 8.2 (Berkeley) 5/30/95"; +#endif /* not lint */ + + +#include <ctype.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(s1, s2) + register char *s1, *s2; +{ + register int n = 0; + char *os1; + register 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(name, table, stlen) + char *name; /* name to match */ + char **table; /* name entry in table */ + int stlen; +{ + register char **c, **found; + register 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(s) + char *s; +{ + return((char **)s == &ambiguous); +} diff --git a/contrib/telnet/libtelnet/getent.c b/contrib/telnet/libtelnet/getent.c new file mode 100644 index 0000000..05626f1 --- /dev/null +++ b/contrib/telnet/libtelnet/getent.c @@ -0,0 +1,68 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)getent.c 8.2 (Berkeley) 12/15/93"; +#endif /* not lint */ + +static char *area; + +/*ARGSUSED*/ +getent(cp, name) +char *cp, *name; +{ +#ifdef HAS_CGETENT + char *dba[2]; + + dba[0] = "/etc/gettytab"; + dba[1] = 0; + return((cgetent(&area, dba, name) == 0) ? 1 : 0); +#else + return(0); +#endif +} + +#ifndef SOLARIS +/*ARGSUSED*/ +char * +getstr(id, cpp) +char *id, **cpp; +{ +# ifdef HAS_CGETENT + char *answer; + return((cgetstr(area, id, &answer) > 0) ? answer : 0); +# else + return(0); +# endif +} +#endif diff --git a/contrib/telnet/libtelnet/kerberos.c b/contrib/telnet/libtelnet/kerberos.c new file mode 100644 index 0000000..dbf4956 --- /dev/null +++ b/contrib/telnet/libtelnet/kerberos.c @@ -0,0 +1,560 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)kerberos.c 8.3 (Berkeley) 5/30/95"; +#endif /* not lint */ + +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifdef KRB4 +#include <sys/types.h> +#include <arpa/telnet.h> +#include <stdio.h> +#include <des.h> /* BSD wont include this in krb.h, so we do it here */ +#include <krb.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif +#ifdef NO_STRING_H +#include <strings.h> +#else +#include <string.h> +#endif + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" + +int kerberos4_cksum P((unsigned char *, int)); +int krb_mk_req P((KTEXT, char *, char *, char *, u_long)); +int krb_rd_req P((KTEXT, char *, char *, u_long, AUTH_DAT *, char *)); +int krb_kntoln P((AUTH_DAT *, char *)); +int krb_get_cred P((char *, char *, char *, CREDENTIALS *)); +int krb_get_lrealm P((char *, int)); +int kuserok P((AUTH_DAT *, char *)); + +extern auth_debug_mode; + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_KERBEROS_V4, }; +static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_NAME, }; + +#define KRB_AUTH 0 /* Authentication data follows */ +#define KRB_REJECT 1 /* Rejected (reason might follow) */ +#define KRB_ACCEPT 2 /* Accepted */ +#define KRB_CHALLENGE 3 /* Challenge for mutual auth. */ +#define KRB_RESPONSE 4 /* Response for mutual auth. */ + +#define KRB_SERVICE_NAME "rcmd" + +static KTEXT_ST auth; +static char name[ANAME_SZ]; +static AUTH_DAT adat = { 0 }; +#ifdef ENCRYPTION +static Block session_key = { 0 }; +static Schedule sched; +static Block challenge = { 0 }; +#endif /* ENCRYPTION */ + + 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 (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(ap, server) + Authenticator *ap; + int server; +{ + FILE *fp; + + if (server) { + str_data[3] = TELQUAL_REPLY; + if ((fp = fopen(KEYFILE, "r")) == NULL) + return(0); + fclose(fp); + } else { + str_data[3] = TELQUAL_IS; + } + return(1); +} + +char dst_realm_buf[REALM_SZ], *dest_realm = NULL; +int dst_realm_sz = REALM_SZ; + + int +kerberos4_send(ap) + Authenticator *ap; +{ + KTEXT_ST auth; +#ifdef ENCRYPTION + Block enckey; +#endif /* ENCRYPTION */ + char instance[INST_SZ]; + char *realm; + char *krb_realmofhost(); + char *krb_get_phost(); + 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(&auth, 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", auth.length); + if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) { + if (auth_debug_mode) + printf("Not enough room for authentication data\r\n"); + return(0); + } +#ifdef ENCRYPTION + /* + * 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(auth.dat, auth.length)); + printd(auth.dat, auth.length); + printf("\r\n"); + printf("Sent Kerberos V4 credentials to server\r\n"); + } + return(1); +} + + void +kerberos4_is(ap, data, cnt) + 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, (void *)"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, "")) { + if (auth_debug_mode) + printf("Kerberos failed him as %s\r\n", name); + Data(ap, KRB_REJECT, (void *)krb_err_txt[r], -1); + auth_finished(ap, AUTH_REJECT); + return; + } +#ifdef ENCRYPTION + memmove((void *)session_key, (void *)adat.session, sizeof(Block)); +#endif /* ENCRYPTION */ + krb_kntoln(&adat, name); + + if (UserNameRequested && !kuserok(&adat, UserNameRequested)) + Data(ap, KRB_ACCEPT, (void *)0, 0); + else + Data(ap, KRB_REJECT, + (void *)"user is not authorized", -1); + auth_finished(ap, AUTH_USER); + break; + + case KRB_CHALLENGE: +#ifndef ENCRYPTION + Data(ap, KRB_RESPONSE, (void *)0, 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, (void *)0, 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, (void *)challenge, sizeof(challenge)); +#endif /* ENCRYPTION */ + break; + + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + Data(ap, KRB_REJECT, 0, 0); + break; + } +} + + void +kerberos4_reply(ap, data, cnt) + 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, (void *)0, 0); +#else /* ENCRYPTION */ + Data(ap, KRB_CHALLENGE, (void *)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(ap, name, level) + Authenticator *ap; + char *name; + int level; +{ + if (level < AUTH_USER) + return(level); + + if (UserNameRequested && !kuserok(&adat, UserNameRequested)) { + 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 +kerberos4_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_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(d, n) + unsigned char *d; + int n; +{ + int ck = 0; + + /* + * A comment is probably needed here for those not + * well versed in the "C" language. Yes, this is + * supposed to be a "switch" with the body of the + * "switch" being a "while" statement. The whole + * purpose of the switch is to allow us to jump into + * the middle of the while() loop, and then not have + * to do any more switch()s. + * + * Some compilers will spit out a warning message + * about the loop not being entered at the top. + */ + switch (n&03) + while (n > 0) { + case 0: + ck ^= (int)*d++ << 24; + --n; + case 3: + ck ^= (int)*d++ << 16; + --n; + case 2: + ck ^= (int)*d++ << 8; + --n; + case 1: + ck ^= (int)*d++; + --n; + } + return(ck); +} +#endif + +#ifdef notdef + +prkey(msg, key) + char *msg; + unsigned char *key; +{ + register int i; + printf("%s:", msg); + for (i = 0; i < 8; i++) + printf(" %3d", key[i]); + printf("\r\n"); +} +#endif diff --git a/contrib/telnet/libtelnet/kerberos5.c b/contrib/telnet/libtelnet/kerberos5.c new file mode 100644 index 0000000..bcf1a9f --- /dev/null +++ b/contrib/telnet/libtelnet/kerberos5.c @@ -0,0 +1,764 @@ +/* + * $Source: /mit/krb5/.cvsroot/src/appl/telnet/libtelnet/kerberos5.c,v $ + * $Author: tytso $ + * $Id: kerberos5.c,v 1.1 1997/09/04 06:11:15 markm Exp $ + */ + +#if !defined(lint) && !defined(SABER) +static +#ifdef __STDC__ +const +#endif +char rcsid_kerberos5_c[] = "$Id: kerberos5.c,v 1.1 1997/09/04 06:11:15 markm Exp $"; +#endif /* lint */ + +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)kerberos5.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 may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + + +#ifdef KRB5 +#include <arpa/telnet.h> +#include <stdio.h> +#include <krb5/krb5.h> +#include <krb5/asn1.h> +#include <krb5/crc-32.h> +#include <krb5/los-proto.h> +#include <krb5/ext-proto.h> +#include <com_err.h> +#include <netdb.h> +#include <ctype.h> + +/* kerberos 5 include files (ext-proto.h) will get an appropriate stdlib.h + and string.h/strings.h */ + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" + +extern auth_debug_mode; + +#ifdef FORWARD +int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */ + +/* These values need to be the same as those defined in telnet/main.c. */ +/* Either define them in both places, or put in some common header file. */ +#define OPTS_FORWARD_CREDS 0x00000002 +#define OPTS_FORWARDABLE_CREDS 0x00000001 + +void kerberos5_forward(); + +#endif /* FORWARD */ + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_KERBEROS_V5, }; +/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_NAME, };*/ + +#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 */ + +static krb5_data auth; + /* telnetd gets session key from here */ +static krb5_tkt_authent *authdat = NULL; +/* telnet matches the AP_REQ and AP_REP with this */ +static krb5_authenticator authenticator; + +/* 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 + +Block session_key; + + 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; + + 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 +kerberos5_init(ap, server) + Authenticator *ap; + int server; +{ + if (server) + str_data[3] = TELQUAL_REPLY; + else + str_data[3] = TELQUAL_IS; + krb5_init_ets(); + return(1); +} + + int +kerberos5_send(ap) + Authenticator *ap; +{ + char **realms; + char *name; + char *p1, *p2; + krb5_checksum ksum; + krb5_octet sum[CRC32_CKSUM_LENGTH]; + krb5_principal server; + krb5_error_code r; + krb5_ccache ccache; + krb5_creds creds; /* telnet gets session key from here */ + extern krb5_flags krb5_kdc_default_options; + int ap_opts; + +#ifdef ENCRYPTION + krb5_keyblock *newkey = 0; +#endif /* ENCRYPTION */ + + ksum.checksum_type = CKSUMTYPE_CRC32; + ksum.contents = sum; + ksum.length = sizeof(sum); + memset((Voidptr )sum, 0, sizeof(sum)); + + if (!UserNameRequested) { + if (auth_debug_mode) { + printf("Kerberos V5: no user name supplied\r\n"); + } + return(0); + } + + if (r = krb5_cc_default(&ccache)) { + if (auth_debug_mode) { + printf("Kerberos V5: could not get default ccache\r\n"); + } + return(0); + } + + if ((name = malloc(strlen(RemoteHostName)+1)) == NULL) { + if (auth_debug_mode) + printf("Out of memory for hostname in Kerberos V5\r\n"); + return(0); + } + + if (r = krb5_get_host_realm(RemoteHostName, &realms)) { + if (auth_debug_mode) + printf("Kerberos V5: no realm for %s\r\n", RemoteHostName); + free(name); + return(0); + } + + p1 = RemoteHostName; + p2 = name; + + while (*p2 = *p1++) { + if (isupper(*p2)) + *p2 |= 040; + ++p2; + } + + if (r = krb5_build_principal_ext(&server, + strlen(realms[0]), realms[0], + 4, "host", + p2 - name, name, + 0)) { + if (auth_debug_mode) { + printf("Kerberos V5: failure setting up principal (%s)\r\n", + error_message(r)); + } + free(name); + krb5_free_host_realm(realms); + return(0); + } + + + memset((char *)&creds, 0, sizeof(creds)); + creds.server = server; + + if (r = krb5_cc_get_principal(ccache, &creds.client)) { + if (auth_debug_mode) { + printf("Kerberos V5: failure on principal (%s)\r\n", + error_message(r)); + } + free(name); + krb5_free_principal(server); + krb5_free_host_realm(realms); + return(0); + } + + if (r = krb5_get_credentials(krb5_kdc_default_options, ccache, &creds)) { + if (auth_debug_mode) { + printf("Kerberos V5: failure on credentials(%d)\r\n",r); + } + free(name); + krb5_free_host_realm(realms); + krb5_free_principal(server); + return(0); + } + + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) + ap_opts = AP_OPTS_MUTUAL_REQUIRED; + else + ap_opts = 0; + + r = krb5_mk_req_extended(ap_opts, &ksum, krb5_kdc_default_options, 0, +#ifdef ENCRYPTION + &newkey, +#else /* ENCRYPTION */ + 0, +#endif /* ENCRYPTION */ + ccache, &creds, &authenticator, &auth); + /* don't let the key get freed if we clean up the authenticator */ + authenticator.subkey = 0; + + free(name); + krb5_free_host_realm(realms); + krb5_free_principal(server); +#ifdef ENCRYPTION + if (newkey) { + /* keep the key in our private storage, but don't use it + yet---see kerberos5_reply() below */ + if (newkey->keytype != KEYTYPE_DES) { + if (creds.keyblock.keytype == KEYTYPE_DES) + /* use the session key in credentials instead */ + memmove((char *)session_key, + (char *)creds.keyblock.contents, sizeof(Block)); + else + /* XXX ? */; + } else { + memmove((char *)session_key, (char *)newkey->contents, + sizeof(Block)); + } + krb5_free_keyblock(newkey); + } +#endif /* ENCRYPTION */ + if (r) { + if (auth_debug_mode) { + printf("Kerberos V5: mk_req failed (%s)\r\n", + error_message(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 (!Data(ap, KRB_AUTH, auth.data, auth.length)) { + if (auth_debug_mode) + printf("Not enough room for authentication data\r\n"); + return(0); + } + if (auth_debug_mode) { + printf("Sent Kerberos V5 credentials to server\r\n"); + } + return(1); +} + + void +kerberos5_is(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + int r; + struct hostent *hp; + char *p1, *p2; + static char *realm = NULL; + krb5_principal server; + krb5_ap_rep_enc_part reply; + krb5_data outbuf; +#ifdef ENCRYPTION + Session_Key skey; +#endif /* ENCRYPTION */ + char *name; + char *getenv(); + krb5_data inbuf; + + if (cnt-- < 1) + return; + switch (*data++) { + case KRB_AUTH: + auth.data = (char *)data; + auth.length = cnt; + + if (!(hp = gethostbyname(LocalHostName))) { + if (auth_debug_mode) + printf("Cannot resolve local host name\r\n"); + Data(ap, KRB_REJECT, "Unknown local hostname.", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + if (!realm && (krb5_get_default_realm(&realm))) { + if (auth_debug_mode) + printf("Could not get default realm\r\n"); + Data(ap, KRB_REJECT, "Could not get default realm.", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + if ((name = malloc(strlen(hp->h_name)+1)) == NULL) { + if (auth_debug_mode) + printf("Out of memory for hostname in Kerberos V5\r\n"); + Data(ap, KRB_REJECT, "Out of memory.", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + p1 = hp->h_name; + p2 = name; + + while (*p2 = *p1++) { + if (isupper(*p2)) + *p2 |= 040; + ++p2; + } + + if (authdat) + krb5_free_tkt_authent(authdat); + + r = krb5_build_principal_ext(&server, + strlen(realm), realm, + 4, "host", + p2 - name, name, + 0); + if (!r) { + r = krb5_rd_req_simple(&auth, server, 0, &authdat); + krb5_free_principal(server); + } + if (r) { + char errbuf[128]; + + errout: + authdat = 0; + (void) strcpy(errbuf, "Read req failed: "); + (void) strcat(errbuf, error_message(r)); + Data(ap, KRB_REJECT, errbuf, -1); + if (auth_debug_mode) + printf("%s\r\n", errbuf); + return; + } + free(name); + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* do ap_rep stuff here */ + reply.ctime = authdat->authenticator->ctime; + reply.cusec = authdat->authenticator->cusec; + reply.subkey = 0; /* use the one he gave us, so don't + need to return one here */ + reply.seq_number = 0; /* we don't do seq #'s. */ + + if (r = krb5_mk_rep(&reply, + authdat->authenticator->subkey ? + authdat->authenticator->subkey : + authdat->ticket->enc_part2->session, + &outbuf)) { + goto errout; + } + Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); + } + if (krb5_unparse_name(authdat->ticket->enc_part2 ->client, + &name)) + name = 0; + Data(ap, KRB_ACCEPT, name, name ? -1 : 0); + if (auth_debug_mode) { + printf("Kerberos5 identifies him as ``%s''\r\n", + name ? name : ""); + } + auth_finished(ap, AUTH_USER); + + free(name); + if (authdat->authenticator->subkey && + authdat->authenticator->subkey->keytype == KEYTYPE_DES) { + memmove((Voidptr )session_key, + (Voidptr )authdat->authenticator->subkey->contents, + sizeof(Block)); + } else if (authdat->ticket->enc_part2->session->keytype == + KEYTYPE_DES) { + memmove((Voidptr )session_key, + (Voidptr )authdat->ticket->enc_part2->session->contents, + sizeof(Block)); + } else + break; + +#ifdef ENCRYPTION + skey.type = SK_DES; + skey.length = 8; + skey.data = session_key; + encrypt_session_key(&skey, 1); +#endif /* ENCRYPTION */ + break; +#ifdef FORWARD + case KRB_FORWARD: + inbuf.data = (char *)data; + inbuf.length = cnt; + if (r = rd_and_store_for_creds(&inbuf, authdat->ticket, + UserNameRequested)) { + char errbuf[128]; + + (void) strcpy(errbuf, "Read forwarded creds failed: "); + (void) strcat(errbuf, error_message(r)); + Data(ap, KRB_FORWARD_REJECT, errbuf, -1); + if (auth_debug_mode) + printf("Could not read forwarded credentials\r\n"); + } + else + Data(ap, KRB_FORWARD_ACCEPT, 0, 0); + if (auth_debug_mode) + printf("Forwarded credentials obtained\r\n"); + break; +#endif /* FORWARD */ + default: + if (auth_debug_mode) + printf("Unknown Kerberos option %d\r\n", data[-1]); + Data(ap, KRB_REJECT, 0, 0); + break; + } +} + + void +kerberos5_reply(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + 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 ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && + !mutual_complete) { + printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\n"); + auth_send_retry(); + return; + } + if (cnt) + printf("[ Kerberos V5 accepts you as ``%.*s'' ]\n", cnt, data); + else + printf("[ Kerberos V5 accepts you ]\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; + krb5_keyblock tmpkey; + + inbuf.length = cnt; + inbuf.data = (char *)data; + + tmpkey.keytype = KEYTYPE_DES; + tmpkey.contents = session_key; + tmpkey.length = sizeof(Block); + + if (r = krb5_rd_rep(&inbuf, &tmpkey, &reply)) { + printf("[ Mutual authentication failed: %s ]\n", + error_message(r)); + auth_send_retry(); + return; + } + if (reply->ctime != authenticator.ctime || + reply->cusec != authenticator.cusec) { + printf("[ Mutual authentication failed (mismatched KRB_AP_REP) ]\n"); + auth_send_retry(); + return; + } + krb5_free_ap_rep_enc_part(reply); +#ifdef ENCRYPTION + skey.type = SK_DES; + skey.length = 8; + skey.data = session_key; + encrypt_session_key(&skey, 0); +#endif /* ENCRYPTION */ + mutual_complete = 1; + } + return; +#ifdef FORWARD + case KRB_FORWARD_ACCEPT: + printf("[ Kerberos V5 accepted forwarded credentials ]\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; + } +} + + int +kerberos5_status(ap, name, level) + Authenticator *ap; + char *name; + int level; +{ + if (level < AUTH_USER) + return(level); + + if (UserNameRequested && + krb5_kuserok(authdat->ticket->enc_part2->client, UserNameRequested)) + { + 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 +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; +{ + struct hostent *hp; + krb5_creds *local_creds; + krb5_error_code r; + krb5_data forw_creds; + extern krb5_cksumtype krb5_kdc_req_sumtype; + krb5_ccache ccache; + int i; + + if (!(local_creds = (krb5_creds *) + calloc(1, sizeof(*local_creds)))) { + if (auth_debug_mode) + printf("Kerberos V5: could not allocate memory for credentials\r\n"); + return; + } + + if (r = krb5_sname_to_principal(RemoteHostName, "host", 1, + &local_creds->server)) { + if (auth_debug_mode) + printf("Kerberos V5: could not build server name - %s\r\n", + error_message(r)); + krb5_free_creds(local_creds); + return; + } + + if (r = krb5_cc_default(&ccache)) { + if (auth_debug_mode) + printf("Kerberos V5: could not get default ccache - %s\r\n", + error_message(r)); + krb5_free_creds(local_creds); + return; + } + + if (r = krb5_cc_get_principal(ccache, &local_creds->client)) { + if (auth_debug_mode) + printf("Kerberos V5: could not get default principal - %s\r\n", + error_message(r)); + krb5_free_creds(local_creds); + return; + } + + /* Get ticket from credentials cache */ + if (r = krb5_get_credentials(KRB5_GC_CACHED, ccache, local_creds)) { + if (auth_debug_mode) + printf("Kerberos V5: could not obtain credentials - %s\r\n", + error_message(r)); + krb5_free_creds(local_creds); + return; + } + + if (r = get_for_creds(ETYPE_DES_CBC_CRC, + krb5_kdc_req_sumtype, + RemoteHostName, + local_creds->client, + &local_creds->keyblock, + forward_flags & OPTS_FORWARDABLE_CREDS, + &forw_creds)) { + if (auth_debug_mode) + printf("Kerberos V5: error getting forwarded creds - %s\r\n", + error_message(r)); + krb5_free_creds(local_creds); + return; + } + + /* 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"); + } + + krb5_free_creds(local_creds); +} +#endif /* FORWARD */ + +#endif /* KRB5 */ diff --git a/contrib/telnet/libtelnet/key-proto.h b/contrib/telnet/libtelnet/key-proto.h new file mode 100644 index 0000000..9668a77 --- /dev/null +++ b/contrib/telnet/libtelnet/key-proto.h @@ -0,0 +1,71 @@ +/*- + * 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. + */ + +#ifndef __KEY_PROTO__ +#define __KEY_PROTO__ + +#if !defined(P) +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif +#endif + +int key_file_exists P((void)); +void key_lookup P((unsigned char *, Block)); +void key_stream_init P((Block, Block, int)); +unsigned char key_stream P((int, int)); +#endif diff --git a/contrib/telnet/libtelnet/krb4encpwd.c b/contrib/telnet/libtelnet/krb4encpwd.c new file mode 100644 index 0000000..6148190 --- /dev/null +++ b/contrib/telnet/libtelnet/krb4encpwd.c @@ -0,0 +1,446 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)krb4encpwd.c 8.3 (Berkeley) 5/30/95"; +#endif /* not lint */ + + +#ifdef KRB4_ENCPWD +/* + * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION + * ALL RIGHTS RESERVED + * + * "Digital Equipment Corporation authorizes the reproduction, + * distribution and modification of this software subject to the following + * restrictions: + * + * 1. Any partial or whole copy of this software, or any modification + * thereof, must include this copyright notice in its entirety. + * + * 2. This software is supplied "as is" with no warranty of any kind, + * expressed or implied, for any purpose, including any warranty of fitness + * or merchantibility. DIGITAL assumes no responsibility for the use or + * reliability of this software, nor promises to provide any form of + * support for it on any basis. + * + * 3. Distribution of this software is authorized only if no profit or + * remuneration of any kind is received in exchange for such distribution. + * + * 4. This software produces public key authentication certificates + * bearing an expiration date established by DIGITAL and RSA Data + * Security, Inc. It may cease to generate certificates after the expiration + * date. Any modification of this software that changes or defeats + * the expiration date or its effect is unauthorized. + * + * 5. Software that will renew or extend the expiration date of + * authentication certificates produced by this software may be obtained + * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA + * 94065, (415)595-8782, or from DIGITAL" + * + */ + +#include <sys/types.h> +#include <arpa/telnet.h> +#include <pwd.h> +#include <stdio.h> + +#include <des.h> +#include <krb.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif +#ifdef NO_STRING_H +#include <strings.h> +#else +#include <string.h> +#endif + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" + +int krb_mk_encpwd_req P((KTEXT, char *, char *, char *, char *, char *, char *)); +int krb_rd_encpwd_req P((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 Schedule sched; +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 + +#ifdef notdef + +prkey(msg, key) + char *msg; + unsigned char *key; +{ + register int i; + printf("%s:", msg); + for (i = 0; i < 8; i++) + printf(" %3d", key[i]); + printf("\r\n"); +} +#endif diff --git a/contrib/telnet/libtelnet/misc-proto.h b/contrib/telnet/libtelnet/misc-proto.h new file mode 100644 index 0000000..e5f334a --- /dev/null +++ b/contrib/telnet/libtelnet/misc-proto.h @@ -0,0 +1,79 @@ +/*- + * 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 + */ + +/* + * 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__ + +#if !defined(P) +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif +#endif + +void auth_encrypt_init P((char *, char *, char *, int)); +void auth_encrypt_connect P((int)); +void printd P((unsigned char *, int)); + +/* + * These functions are imported from the application + */ +int net_write P((unsigned char *, int)); +void net_encrypt P((void)); +int telnet_spin P((void)); +char *telnet_getenv P((char *)); +char *telnet_gets P((char *, char *, int, int)); +#endif diff --git a/contrib/telnet/libtelnet/misc.c b/contrib/telnet/libtelnet/misc.c new file mode 100644 index 0000000..9565900 --- /dev/null +++ b/contrib/telnet/libtelnet/misc.c @@ -0,0 +1,94 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include "misc.h" + +char *RemoteHostName; +char *LocalHostName; +char *UserNameRequested = 0; +int ConnectedCount = 0; + + void +auth_encrypt_init(local, remote, name, server) + char *local; + char *remote; + char *name; + int server; +{ + RemoteHostName = remote; + LocalHostName = local; +#if defined(AUTHENTICATION) + auth_init(name, server); +#endif +#ifdef ENCRYPTION + encrypt_init(name, server); +#endif /* ENCRYPTION */ + if (UserNameRequested) { + free(UserNameRequested); + UserNameRequested = 0; + } +} + + void +auth_encrypt_user(name) + char *name; +{ + extern char *strdup(); + + if (UserNameRequested) + free(UserNameRequested); + UserNameRequested = name ? strdup(name) : 0; +} + + void +auth_encrypt_connect(cnt) + int cnt; +{ +} + + void +printd(data, cnt) + unsigned char *data; + int cnt; +{ + if (cnt > 16) + cnt = 16; + while (cnt-- > 0) { + printf(" %02x", *data); + ++data; + } +} diff --git a/contrib/telnet/libtelnet/misc.h b/contrib/telnet/libtelnet/misc.h new file mode 100644 index 0000000..41ffa7f --- /dev/null +++ b/contrib/telnet/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/contrib/telnet/libtelnet/read_password.c b/contrib/telnet/libtelnet/read_password.c new file mode 100644 index 0000000..4676ed3 --- /dev/null +++ b/contrib/telnet/libtelnet/read_password.c @@ -0,0 +1,145 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)read_password.c 8.3 (Berkeley) 5/30/95"; +#endif /* not lint */ + +/* + * $Source: /mit/kerberos/src/lib/des/RCS/read_password.c,v $ + * $Author: jon $ + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * This routine prints the supplied string to standard + * output as a prompt, and reads a password string without + * echoing. + */ + +#if defined(RSA_ENCPWD) || defined(KRB4_ENCPWD) + +#include <stdio.h> +#include <strings.h> +#include <sys/ioctl.h> +#include <signal.h> +#include <setjmp.h> + +static jmp_buf env; + +/*** Routines ****************************************************** */ +/* + * This version just returns the string, doesn't map to key. + * + * Returns 0 on success, non-zero on failure. + */ + +int +local_des_read_pw_string(s,max,prompt,verify) + char *s; + int max; + char *prompt; + int verify; +{ + int ok = 0; + char *ptr; + + jmp_buf old_env; + struct sgttyb tty_state; + char key_string[BUFSIZ]; + + if (max > BUFSIZ) { + return -1; + } + + /* XXX assume jmp_buf is typedef'ed to an array */ + memmove((char *)env, (char *)old_env, sizeof(env)); + if (setjmp(env)) + goto lose; + + /* save terminal state*/ + if (ioctl(0,TIOCGETP,(char *)&tty_state) == -1) + return -1; +/* + push_signals(); +*/ + /* Turn off echo */ + tty_state.sg_flags &= ~ECHO; + if (ioctl(0,TIOCSETP,(char *)&tty_state) == -1) + return -1; + while (!ok) { + (void) printf(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/contrib/telnet/libtelnet/rsaencpwd.c b/contrib/telnet/libtelnet/rsaencpwd.c new file mode 100644 index 0000000..5906d99 --- /dev/null +++ b/contrib/telnet/libtelnet/rsaencpwd.c @@ -0,0 +1,492 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)rsaencpwd.c 8.3 (Berkeley) 5/30/95"; +#endif /* not lint */ + + +#ifdef RSA_ENCPWD +/* + * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION + * ALL RIGHTS RESERVED + * + * "Digital Equipment Corporation authorizes the reproduction, + * distribution and modification of this software subject to the following + * restrictions: + * + * 1. Any partial or whole copy of this software, or any modification + * thereof, must include this copyright notice in its entirety. + * + * 2. This software is supplied "as is" with no warranty of any kind, + * expressed or implied, for any purpose, including any warranty of fitness + * or merchantibility. DIGITAL assumes no responsibility for the use or + * reliability of this software, nor promises to provide any form of + * support for it on any basis. + * + * 3. Distribution of this software is authorized only if no profit or + * remuneration of any kind is received in exchange for such distribution. + * + * 4. This software produces public key authentication certificates + * bearing an expiration date established by DIGITAL and RSA Data + * Security, Inc. It may cease to generate certificates after the expiration + * date. Any modification of this software that changes or defeats + * the expiration date or its effect is unauthorized. + * + * 5. Software that will renew or extend the expiration date of + * authentication certificates produced by this software may be obtained + * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA + * 94065, (415)595-8782, or from DIGITAL" + * + */ + +#include <sys/types.h> +#include <arpa/telnet.h> +#include <pwd.h> +#include <stdio.h> + +#ifdef __STDC__ +#include <stdlib.h> +#endif +#ifdef NO_STRING_H +#include <strings.h> +#else +#include <string.h> +#endif + +#include "encrypt.h" +#include "auth.h" +#include "misc.h" +#include "cdc.h" + +extern auth_debug_mode; + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_RSA_ENCPWD, }; +static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_NAME, }; + +#define RSA_ENCPWD_AUTH 0 /* Authentication data follows */ +#define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ +#define RSA_ENCPWD_ACCEPT 2 /* Accepted */ +#define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */ + +#define NAME_SZ 40 +#define CHAL_SZ 20 +#define PWD_SZ 40 + +static KTEXT_ST auth; +static char name[NAME_SZ]; +static char user_passwd[PWD_SZ]; +static char key_file[2*NAME_SZ]; +static char lhostname[NAME_SZ]; +static char challenge[CHAL_SZ]; +static int challenge_len; + + static int +Data(ap, type, d, c) + Authenticator *ap; + int type; + void *d; + int c; +{ + unsigned char *p = str_data + 4; + unsigned char *cd = (unsigned char *)d; + + if (c == -1) + c = strlen((char *)cd); + + if (0) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + if (type != NULL) *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - (&str_data[2])); + return(net_write(str_data, p - str_data)); +} + + int +rsaencpwd_init(ap, server) + Authenticator *ap; + int server; +{ + char *cp; + FILE *fp; + + if (server) { + str_data[3] = TELQUAL_REPLY; + memset(key_file, 0, sizeof(key_file)); + gethostname(lhostname, sizeof(lhostname)); + if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; + strcpy(key_file, "/etc/."); + strcat(key_file, lhostname); + strcat(key_file, "_privkey"); + if ((fp=fopen(key_file, "r"))==NULL) return(0); + fclose(fp); + } else { + str_data[3] = TELQUAL_IS; + } + return(1); +} + + int +rsaencpwd_send(ap) + Authenticator *ap; +{ + + printf("[ Trying RSAENCPWD ... ]\n"); + if (!UserNameRequested) { + return(0); + } + if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { + return(0); + } + if (!Data(ap, NULL, (void *)NULL, 0)) { + return(0); + } + + + return(1); +} + + void +rsaencpwd_is(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + Block datablock; + char r_passwd[PWD_SZ], r_user[NAME_SZ]; + char *cp, key[160]; + char chalkey[160], *ptr; + FILE *fp; + int r, i, j, chalkey_len, len; + time_t now; + + cnt--; + switch (*data++) { + case RSA_ENCPWD_AUTH: + memmove((void *)auth.dat, (void *)data, auth.length = cnt); + + if ((fp=fopen(key_file, "r"))==NULL) { + Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + /* + * get privkey + */ + fscanf(fp, "%x;", &len); + for (i=0;i<len;i++) { + j = getc(fp); key[i]=j; + } + fclose(fp); + + r = accept_rsa_encpwd(&auth, key, challenge, + challenge_len, r_passwd); + if (r < 0) { + Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + auth_encrypt_userpwd(r_passwd); + if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) { + /* + * illegal username and password + */ + Data(ap, RSA_ENCPWD_REJECT, (void *)"Illegal password", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + Data(ap, RSA_ENCPWD_ACCEPT, (void *)0, 0); + auth_finished(ap, AUTH_USER); + break; + + + case IAC: + + /* + * If we are doing mutual authentication, get set up to send + * the challenge, and verify it when the response comes back. + */ + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) { + register int i; + + + time(&now); + if ((now % 2) == 0) { + sprintf(challenge, "%x", now); + challenge_len = strlen(challenge); + } else { + strcpy(challenge, "randchal"); + challenge_len = 8; + } + + if ((fp=fopen(key_file, "r"))==NULL) { + Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + /* + * skip privkey + */ + fscanf(fp, "%x;", &len); + for (i=0;i<len;i++) { + j = getc(fp); + } + /* + * get pubkey + */ + fscanf(fp, "%x;", &len); + for (i=0;i<len;i++) { + j = getc(fp); key[i]=j; + } + fclose(fp); + chalkey[0] = 0x30; + ptr = (char *) &chalkey[1]; + chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len; + EncodeLength(ptr, chalkey_len); + ptr +=NumEncodeLengthOctets(chalkey_len); + *ptr++ = 0x04; /* OCTET STRING */ + *ptr++ = challenge_len; + memmove(ptr, challenge, challenge_len); + ptr += challenge_len; + *ptr++ = 0x04; /* OCTET STRING */ + EncodeLength(ptr, i); + ptr += NumEncodeLengthOctets(i); + memmove(ptr, key, i); + chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len; + Data(ap, RSA_ENCPWD_CHALLENGEKEY, (void *)chalkey, chalkey_len); + } + break; + + default: + Data(ap, RSA_ENCPWD_REJECT, 0, 0); + break; + } +} + + + void +rsaencpwd_reply(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + KTEXT_ST token; + Block enckey; + int r, pubkey_len; + char randchal[CHAL_SZ], *cp; + char chalkey[160], pubkey[128], *ptr; + + if (cnt-- < 1) + return; + switch (*data++) { + case RSA_ENCPWD_REJECT: + if (cnt > 0) { + printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n", + cnt, data); + } else + printf("[ RSA_ENCPWD refuses authentication ]\r\n"); + auth_send_retry(); + return; + case RSA_ENCPWD_ACCEPT: + printf("[ RSA_ENCPWD accepts you ]\n"); + auth_finished(ap, AUTH_USER); + return; + case RSA_ENCPWD_CHALLENGEKEY: + /* + * Verify that the response to the challenge is correct. + */ + + memmove((void *)chalkey, (void *)data, cnt); + ptr = (char *) &chalkey[0]; + ptr += DecodeHeaderLength(chalkey); + if (*ptr != 0x04) { + return; + } + *ptr++; + challenge_len = DecodeValueLength(ptr); + ptr += NumEncodeLengthOctets(challenge_len); + memmove(challenge, ptr, challenge_len); + ptr += challenge_len; + if (*ptr != 0x04) { + return; + } + *ptr++; + pubkey_len = DecodeValueLength(ptr); + ptr += NumEncodeLengthOctets(pubkey_len); + memmove(pubkey, ptr, pubkey_len); + memset(user_passwd, 0, sizeof(user_passwd)); + local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); + UserPassword = user_passwd; + Challenge = challenge; + r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey); + if (r < 0) { + token.length = 1; + } + + if (!Data(ap, RSA_ENCPWD_AUTH, (void *)token.dat, token.length)) { + return; + } + + break; + + default: + return; + } +} + + int +rsaencpwd_status(ap, name, level) + Authenticator *ap; + char *name; + int level; +{ + + if (level < AUTH_USER) + return(level); + + if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) { + strcpy(name, UserNameRequested); + return(AUTH_VALID); + } else { + return(AUTH_USER); + } +} + +#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} +#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} + + void +rsaencpwd_printsub(data, cnt, buf, buflen) + unsigned char *data, *buf; + int cnt, buflen; +{ + char lbuf[32]; + register int i; + + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; + + switch(data[3]) { + case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */ + strncpy((char *)buf, " REJECT ", buflen); + goto common; + + case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */ + strncpy((char *)buf, " ACCEPT ", buflen); + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; + + case RSA_ENCPWD_AUTH: /* Authentication data follows */ + strncpy((char *)buf, " AUTH", buflen); + goto common2; + + case RSA_ENCPWD_CHALLENGEKEY: + strncpy((char *)buf, " CHALLENGEKEY", buflen); + goto common2; + + default: + sprintf(lbuf, " %d (unknown)", data[3]); + strncpy((char *)buf, lbuf, buflen); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + sprintf(lbuf, " %d", data[i]); + strncpy((char *)buf, lbuf, buflen); + BUMP(buf, buflen); + } + break; + } +} + +int rsaencpwd_passwdok(name, passwd) +char *name, *passwd; +{ + char *crypt(); + char *salt, *p; + struct passwd *pwd; + int passwdok_status = 0; + + if (pwd = getpwnam(name)) + salt = pwd->pw_passwd; + else salt = "xx"; + + p = crypt(passwd, salt); + + if (pwd && !strcmp(p, pwd->pw_passwd)) { + passwdok_status = 1; + } else passwdok_status = 0; + return(passwdok_status); +} + +#endif + +#ifdef notdef + +prkey(msg, key) + char *msg; + unsigned char *key; +{ + register int i; + printf("%s:", msg); + for (i = 0; i < 8; i++) + printf(" %3d", key[i]); + printf("\r\n"); +} +#endif diff --git a/contrib/telnet/libtelnet/spx.c b/contrib/telnet/libtelnet/spx.c new file mode 100644 index 0000000..86c6197 --- /dev/null +++ b/contrib/telnet/libtelnet/spx.c @@ -0,0 +1,588 @@ +/*- + * 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)spx.c 8.2 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#ifdef SPX +/* + * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION + * ALL RIGHTS RESERVED + * + * "Digital Equipment Corporation authorizes the reproduction, + * distribution and modification of this software subject to the following + * restrictions: + * + * 1. Any partial or whole copy of this software, or any modification + * thereof, must include this copyright notice in its entirety. + * + * 2. This software is supplied "as is" with no warranty of any kind, + * expressed or implied, for any purpose, including any warranty of fitness + * or merchantibility. DIGITAL assumes no responsibility for the use or + * reliability of this software, nor promises to provide any form of + * support for it on any basis. + * + * 3. Distribution of this software is authorized only if no profit or + * remuneration of any kind is received in exchange for such distribution. + * + * 4. This software produces public key authentication certificates + * bearing an expiration date established by DIGITAL and RSA Data + * Security, Inc. It may cease to generate certificates after the expiration + * date. Any modification of this software that changes or defeats + * the expiration date or its effect is unauthorized. + * + * 5. Software that will renew or extend the expiration date of + * authentication certificates produced by this software may be obtained + * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA + * 94065, (415)595-8782, or from DIGITAL" + * + */ + +#include <sys/types.h> +#include <arpa/telnet.h> +#include <stdio.h> +#include "gssapi_defs.h" +#ifdef __STDC__ +#include <stdlib.h> +#endif +#ifdef NO_STRING_H +#include <strings.h> +#else +#include <string.h> +#endif + +#include <pwd.h> +#include "encrypt.h" +#include "auth.h" +#include "misc.h" + +extern auth_debug_mode; + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_SPX, }; +static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, + TELQUAL_NAME, }; + +#define SPX_AUTH 0 /* Authentication data follows */ +#define SPX_REJECT 1 /* Rejected (reason might follow) */ +#define SPX_ACCEPT 2 /* Accepted */ + +#ifdef ENCRYPTION +static Block session_key = { 0 }; +#endif /* ENCRYPTION */ +static Schedule sched; +static Block challenge = { 0 }; + + +/*******************************************************************/ + +gss_OID_set actual_mechs; +gss_OID actual_mech_type, output_name_type; +int major_status, status, msg_ctx = 0, new_status; +int req_flags = 0, ret_flags, lifetime_rec; +gss_cred_id_t gss_cred_handle; +gss_ctx_id_t actual_ctxhandle, context_handle; +gss_buffer_desc output_token, input_token, input_name_buffer; +gss_buffer_desc status_string; +gss_name_t desired_targname, src_name; +gss_channel_bindings input_chan_bindings; +char lhostname[GSS_C_MAX_PRINTABLE_NAME]; +char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; +int to_addr=0, from_addr=0; +char *address; +gss_buffer_desc fullname_buffer; +gss_OID fullname_type; +gss_cred_id_t gss_delegated_cred_handle; + +/*******************************************************************/ + + + + 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 +spx_init(ap, server) + Authenticator *ap; + int server; +{ + gss_cred_id_t tmp_cred_handle; + + if (server) { + str_data[3] = TELQUAL_REPLY; + gethostname(lhostname, sizeof(lhostname)); + strcpy(targ_printable, "SERVICE:rcmd@"); + strcat(targ_printable, lhostname); + input_name_buffer.length = strlen(targ_printable); + input_name_buffer.value = targ_printable; + major_status = gss_import_name(&status, + &input_name_buffer, + GSS_C_NULL_OID, + &desired_targname); + major_status = gss_acquire_cred(&status, + desired_targname, + 0, + GSS_C_NULL_OID_SET, + GSS_C_ACCEPT, + &tmp_cred_handle, + &actual_mechs, + &lifetime_rec); + if (major_status != GSS_S_COMPLETE) return(0); + } else { + str_data[3] = TELQUAL_IS; + } + return(1); +} + + int +spx_send(ap) + Authenticator *ap; +{ + Block enckey; + int r; + + gss_OID actual_mech_type, output_name_type; + int msg_ctx = 0, new_status, status; + int req_flags = 0, ret_flags, lifetime_rec, major_status; + gss_buffer_desc output_token, input_token, input_name_buffer; + gss_buffer_desc output_name_buffer, status_string; + gss_name_t desired_targname; + gss_channel_bindings input_chan_bindings; + char targ_printable[GSS_C_MAX_PRINTABLE_NAME]; + int from_addr=0, to_addr=0, myhostlen, j; + int deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0; + char *address; + + printf("[ Trying SPX ... ]\n"); + strcpy(targ_printable, "SERVICE:rcmd@"); + strcat(targ_printable, RemoteHostName); + + input_name_buffer.length = strlen(targ_printable); + input_name_buffer.value = targ_printable; + + if (!UserNameRequested) { + return(0); + } + + major_status = gss_import_name(&status, + &input_name_buffer, + GSS_C_NULL_OID, + &desired_targname); + + + major_status = gss_display_name(&status, + desired_targname, + &output_name_buffer, + &output_name_type); + + printf("target is '%s'\n", output_name_buffer.value); fflush(stdout); + + major_status = gss_release_buffer(&status, &output_name_buffer); + + input_chan_bindings = (gss_channel_bindings) + malloc(sizeof(gss_channel_bindings_desc)); + + input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; + input_chan_bindings->initiator_address.length = 4; + address = (char *) malloc(4); + input_chan_bindings->initiator_address.value = (char *) address; + address[0] = ((from_addr & 0xff000000) >> 24); + address[1] = ((from_addr & 0xff0000) >> 16); + address[2] = ((from_addr & 0xff00) >> 8); + address[3] = (from_addr & 0xff); + input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; + input_chan_bindings->acceptor_address.length = 4; + address = (char *) malloc(4); + input_chan_bindings->acceptor_address.value = (char *) address; + address[0] = ((to_addr & 0xff000000) >> 24); + address[1] = ((to_addr & 0xff0000) >> 16); + address[2] = ((to_addr & 0xff00) >> 8); + address[3] = (to_addr & 0xff); + input_chan_bindings->application_data.length = 0; + + req_flags = 0; + if (deleg_flag) req_flags = req_flags | 1; + if (mutual_flag) req_flags = req_flags | 2; + if (replay_flag) req_flags = req_flags | 4; + if (seq_flag) req_flags = req_flags | 8; + + major_status = gss_init_sec_context(&status, /* minor status */ + GSS_C_NO_CREDENTIAL, /* cred handle */ + &actual_ctxhandle, /* ctx handle */ + desired_targname, /* target name */ + GSS_C_NULL_OID, /* mech type */ + req_flags, /* req flags */ + 0, /* time req */ + input_chan_bindings, /* chan binding */ + GSS_C_NO_BUFFER, /* input token */ + &actual_mech_type, /* actual mech */ + &output_token, /* output token */ + &ret_flags, /* ret flags */ + &lifetime_rec); /* time rec */ + + if ((major_status != GSS_S_COMPLETE) && + (major_status != GSS_S_CONTINUE_NEEDED)) { + gss_display_status(&new_status, + status, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status_string); + printf("%s\n", status_string.value); + return(0); + } + + if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { + return(0); + } + + if (!Data(ap, SPX_AUTH, (void *)output_token.value, output_token.length)) { + return(0); + } + + return(1); +} + + void +spx_is(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + Block datablock; + int r; + + if (cnt-- < 1) + return; + switch (*data++) { + case SPX_AUTH: + input_token.length = cnt; + input_token.value = (char *) data; + + gethostname(lhostname, sizeof(lhostname)); + + strcpy(targ_printable, "SERVICE:rcmd@"); + strcat(targ_printable, lhostname); + + input_name_buffer.length = strlen(targ_printable); + input_name_buffer.value = targ_printable; + + major_status = gss_import_name(&status, + &input_name_buffer, + GSS_C_NULL_OID, + &desired_targname); + + major_status = gss_acquire_cred(&status, + desired_targname, + 0, + GSS_C_NULL_OID_SET, + GSS_C_ACCEPT, + &gss_cred_handle, + &actual_mechs, + &lifetime_rec); + + major_status = gss_release_name(&status, desired_targname); + + input_chan_bindings = (gss_channel_bindings) + malloc(sizeof(gss_channel_bindings_desc)); + + input_chan_bindings->initiator_addrtype = GSS_C_AF_INET; + input_chan_bindings->initiator_address.length = 4; + address = (char *) malloc(4); + input_chan_bindings->initiator_address.value = (char *) address; + address[0] = ((from_addr & 0xff000000) >> 24); + address[1] = ((from_addr & 0xff0000) >> 16); + address[2] = ((from_addr & 0xff00) >> 8); + address[3] = (from_addr & 0xff); + input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET; + input_chan_bindings->acceptor_address.length = 4; + address = (char *) malloc(4); + input_chan_bindings->acceptor_address.value = (char *) address; + address[0] = ((to_addr & 0xff000000) >> 24); + address[1] = ((to_addr & 0xff0000) >> 16); + address[2] = ((to_addr & 0xff00) >> 8); + address[3] = (to_addr & 0xff); + input_chan_bindings->application_data.length = 0; + + major_status = gss_accept_sec_context(&status, + &context_handle, + gss_cred_handle, + &input_token, + input_chan_bindings, + &src_name, + &actual_mech_type, + &output_token, + &ret_flags, + &lifetime_rec, + &gss_delegated_cred_handle); + + + if (major_status != GSS_S_COMPLETE) { + + major_status = gss_display_name(&status, + src_name, + &fullname_buffer, + &fullname_type); + Data(ap, SPX_REJECT, (void *)"auth failed", -1); + auth_finished(ap, AUTH_REJECT); + return; + } + + major_status = gss_display_name(&status, + src_name, + &fullname_buffer, + &fullname_type); + + + Data(ap, SPX_ACCEPT, (void *)output_token.value, output_token.length); + auth_finished(ap, AUTH_USER); + break; + + default: + Data(ap, SPX_REJECT, 0, 0); + break; + } +} + + + void +spx_reply(ap, data, cnt) + Authenticator *ap; + unsigned char *data; + int cnt; +{ + Session_Key skey; + + if (cnt-- < 1) + return; + switch (*data++) { + case SPX_REJECT: + if (cnt > 0) { + printf("[ SPX refuses authentication because %.*s ]\r\n", + cnt, data); + } else + printf("[ SPX refuses authentication ]\r\n"); + auth_send_retry(); + return; + case SPX_ACCEPT: + printf("[ SPX accepts you ]\n"); + if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { + /* + * Send over the encrypted challenge. + */ + input_token.value = (char *) data; + input_token.length = cnt; + + major_status = gss_init_sec_context(&status, /* minor stat */ + GSS_C_NO_CREDENTIAL, /* cred handle */ + &actual_ctxhandle, /* ctx handle */ + desired_targname, /* target name */ + GSS_C_NULL_OID, /* mech type */ + req_flags, /* req flags */ + 0, /* time req */ + input_chan_bindings, /* chan binding */ + &input_token, /* input token */ + &actual_mech_type, /* actual mech */ + &output_token, /* output token */ + &ret_flags, /* ret flags */ + &lifetime_rec); /* time rec */ + + if (major_status != GSS_S_COMPLETE) { + gss_display_status(&new_status, + status, + GSS_C_MECH_CODE, + GSS_C_NULL_OID, + &msg_ctx, + &status_string); + printf("[ SPX mutual response fails ... '%s' ]\r\n", + status_string.value); + auth_send_retry(); + return; + } + } + auth_finished(ap, AUTH_USER); + return; + + default: + return; + } +} + + int +spx_status(ap, name, level) + Authenticator *ap; + char *name; + int level; +{ + + gss_buffer_desc fullname_buffer, acl_file_buffer; + gss_OID fullname_type; + char acl_file[160], fullname[160]; + int major_status, status = 0; + struct passwd *pwd; + + /* + * hard code fullname to + * "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan" + * and acl_file to "~kannan/.sphinx" + */ + + pwd = getpwnam(UserNameRequested); + if (pwd == NULL) { + return(AUTH_USER); /* not authenticated */ + } + + strcpy(acl_file, pwd->pw_dir); + strcat(acl_file, "/.sphinx"); + acl_file_buffer.value = acl_file; + acl_file_buffer.length = strlen(acl_file); + + major_status = gss_display_name(&status, + src_name, + &fullname_buffer, + &fullname_type); + + if (level < AUTH_USER) + return(level); + + major_status = gss__check_acl(&status, &fullname_buffer, + &acl_file_buffer); + + if (major_status == GSS_S_COMPLETE) { + 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 +spx_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 SPX_REJECT: /* Rejected (reason might follow) */ + strncpy((char *)buf, " REJECT ", buflen); + goto common; + + case SPX_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 SPX_AUTH: /* Authentication data follows */ + strncpy((char *)buf, " AUTH", 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; + } +} + +#endif + +#ifdef notdef + +prkey(msg, key) + char *msg; + unsigned char *key; +{ + register int i; + printf("%s:", msg); + for (i = 0; i < 8; i++) + printf(" %3d", key[i]); + printf("\r\n"); +} +#endif |