📄 kerberos5.c
字号:
/* Copyright (C) 2002 Free Software Foundation, Inc. This file is part of GNU Inetutils. GNU Inetutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Inetutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Inetutils; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#ifdef KRB5#include <stdlib.h>#include <stdio.h>#include <arpa/telnet.h>#include <krb5.h>#include <assert.h>#include <com_err.h>#include <netdb.h>#include <ctype.h>#include <syslog.h>#ifdef HAVE_STRING_H# include <string.h>#else# include <strings.h>#endif#include "auth.h"#include "misc.h"#ifndef KRB5_ENV_CCNAME# define KRB5_ENV_CCNAME "KRB5CCNAME"#endif#ifdef ENCRYPTION#include "encrypt.h"#endif#ifdef FORWARD/* FIXME: This is set directly from telnet/main.c */int forward_flags = 0; extern int net; /*FIXME*/void kerberos5_forward ();#endif /* FORWARD */static unsigned char str_data[2048] = { IAC, SB, TELOPT_AUTHENTICATION, 0, AUTHTYPE_KERBEROS_V5, };#define KRB_AUTH 0 /* Authentication data follows */#define KRB_REJECT 1 /* Rejected (reason might follow) */#define KRB_ACCEPT 2 /* Accepted */#define KRB_RESPONSE 3 /* Response for mutual auth. */#define KRB_FORWARD 4 /* Forwarded credentials follow */#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */krb5_auth_context auth_context = 0;krb5_context telnet_context = 0;static krb5_data auth; /* session key for telnet */static krb5_ticket *ticket = NULL; /* telnet matches the AP_REQ and AP_REP with this */krb5_keyblock *session_key = 0;char *telnet_srvtab = NULL;char *telnet_krb5_realm = NULL;#define DEBUG(c) if (auth_debug_mode) printf cstatic intData (TN_Authenticator *ap, int type, krb5_pointer d, int c){ unsigned char *p = str_data + 4; unsigned char *cd = (unsigned char *) d; if (c == -1) c = strlen (cd); if (auth_debug_mode) { printf ("%s:%d: [%d] (%d)", str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", str_data[3], type, c); printd (d, c); printf ("\r\n"); } *p++ = ap->type; *p++ = ap->way; *p++ = type; while (c-- > 0) { if ((*p++ = *cd++) == IAC) *p++ = IAC; } *p++ = IAC; *p++ = SE; if (str_data[3] == TELQUAL_IS) printsub ('>', &str_data[2], p - &str_data[2]); return (net_write (str_data, p - str_data));}/* FIXME: Reverse return code! */intkerberos5_init (TN_Authenticator *ap, int server){ str_data[3] = server ? TELQUAL_REPLY : TELQUAL_IS; if (telnet_context == 0 && krb5_init_context(&telnet_context)) return 0; return 1;}voidkerberos5_cleanup (){ krb5_ccache ccache; char *ccname; if (telnet_context == 0) return; ccname = getenv (KRB5_ENV_CCNAME); if (ccname) { if (!krb5_cc_resolve (telnet_context, ccname, &ccache)) krb5_cc_destroy (telnet_context, ccache); } krb5_free_context (telnet_context); telnet_context = 0;}#ifdef ENCRYPTIONvoidencryption_init (krb5_creds *creds){ krb5_keyblock *newkey = 0; krb5_auth_con_getlocalsubkey (telnet_context, auth_context, &newkey); if (session_key) { krb5_free_keyblock (telnet_context, session_key); session_key = 0; } if (newkey) { switch (newkey->enctype) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD5: krb5_copy_keyblock (telnet_context, newkey, &session_key); break; default: switch (creds->keyblock.enctype) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD5: krb5_copy_keyblock (telnet_context, &creds->keyblock, &session_key); break; default: DEBUG(("can't determine which keyblock to use")); /*FIXME: abort?*/ } } krb5_free_keyblock(telnet_context, newkey); }}#else# define encryption_init(c)#endifintkerberos5_send (TN_Authenticator *ap){ krb5_error_code r; krb5_ccache ccache; krb5_creds creds; krb5_creds *new_creds = 0; int ap_opts; char type_check[2]; krb5_data check_data; if (!UserNameRequested) { DEBUG(("telnet: Kerberos V5: no user name supplied\r\n")); return 0; } if ((r = krb5_cc_default (telnet_context, &ccache))) { DEBUG(("telnet: Kerberos V5: could not get default ccache\r\n")); return 0; } memset (&creds, 0, sizeof (creds)); if ((r = krb5_sname_to_principal (telnet_context, RemoteHostName, "host", KRB5_NT_SRV_HST, &creds.server))) { DEBUG(("telnet: Kerberos V5: error while constructing service name: %s\r\n", error_message(r))); return 0; } if (telnet_krb5_realm) { krb5_data rdata; rdata.length = strlen (telnet_krb5_realm); rdata.data = malloc (rdata.length + 1); assert (rdata.data); strcpy (rdata.data, telnet_krb5_realm); krb5_princ_set_realm (telnet_context, creds.server, &rdata); } if ((r = krb5_cc_get_principal (telnet_context, ccache, &creds.client))) { DEBUG(("telnet: Kerberos V5: failure on principal (%s)\r\n", error_message(r))); krb5_free_cred_contents (telnet_context, &creds); return 0; } creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; if ((r = krb5_get_credentials (telnet_context, 0, ccache, &creds, &new_creds))) { DEBUG(("telnet: Kerberos V5: failure on credentials(%s)\r\n", error_message(r))); krb5_free_cred_contents (telnet_context, &creds); return 0; } if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ap_opts = AP_OPTS_MUTUAL_REQUIRED; else ap_opts = 0;#ifdef ENCRYPTION ap_opts |= AP_OPTS_USE_SUBKEY;#endif if (auth_context) { krb5_auth_con_free (telnet_context, auth_context); auth_context = 0; } if ((r = krb5_auth_con_init (telnet_context, &auth_context))) { DEBUG(("Kerberos V5: failed to init auth_context (%s)\r\n", error_message(r))); return 0; } krb5_auth_con_setflags (telnet_context, auth_context, KRB5_AUTH_CONTEXT_RET_TIME); type_check[0] = ap->type; type_check[1] = ap->way; check_data.magic = KV5M_DATA; check_data.length = 2; check_data.data = (char *) &type_check; r = krb5_mk_req_extended (telnet_context, &auth_context, ap_opts, &check_data, new_creds, &auth); encryption_init (new_creds); krb5_free_cred_contents (telnet_context, &creds); krb5_free_creds (telnet_context, new_creds); if (r) { DEBUG(("telnet: Kerberos V5: mk_req failed (%s)\r\n", error_message(r))); return 0; } if (!auth_sendname (UserNameRequested, strlen (UserNameRequested))) { DEBUG(("telnet: Not enough room for user name\r\n")); return 0; } if (!Data (ap, KRB_AUTH, auth.data, auth.length)) { DEBUG(("telnet: Not enough room for authentication data\r\n")); return 0; } DEBUG(("telnet: Sent Kerberos V5 credentials to server\r\n")); return 1;}#ifdef ENCRYPTIONvoidtelnet_encrypt_key (Session_Key *skey){ if (session_key) { skey->type = SK_DES; skey->length = 8; skey->data = session_key->contents; encrypt_session_key (skey, 0); }}#else# define telnet_encrypt_key(s)#endifvoidkerberos5_reply (TN_Authenticator *ap, unsigned char *data, int cnt){#ifdef ENCRYPTION Session_Key skey;#endif static int mutual_complete = 0; if (cnt-- < 1) return; switch (*data++) { case KRB_REJECT: if (cnt > 0) printf ("[ Kerberos V5 refuses authentication because %.*s ]\r\n", cnt, data); else printf ("[ Kerberos V5 refuses authentication ]\r\n"); auth_send_retry(); return; case KRB_ACCEPT: if (!mutual_complete) { if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { printf ("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n"); auth_send_retry (); break; } telnet_encrypt_key (&skey); } if (cnt) printf ("[ Kerberos V5 accepts you as ``%.*s''%s ]\r\n", cnt, data, mutual_complete ? " (server authenticated)" : " (server NOT authenticated)"); else printf ("[ Kerberos V5 accepts you ]\r\n"); auth_finished(ap, AUTH_USER);#ifdef FORWARD if (forward_flags & OPTS_FORWARD_CREDS) kerberos5_forward (ap);#endif break; case KRB_RESPONSE: if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { krb5_ap_rep_enc_part *reply; krb5_data inbuf; krb5_error_code r; inbuf.length = cnt; inbuf.data = (char *)data; if ((r = krb5_rd_rep (telnet_context, auth_context, &inbuf, &reply))) { printf ("[ Mutual authentication failed: %s ]\r\n", error_message (r)); auth_send_retry (); break; } krb5_free_ap_rep_enc_part (telnet_context, reply); telnet_encrypt_key (&skey); mutual_complete = 1; } break;#ifdef FORWARD case KRB_FORWARD_ACCEPT: printf ("[ Kerberos V5 accepted forwarded credentials ]\r\n"); break; case KRB_FORWARD_REJECT: printf ("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", cnt, data); break;#endif /* FORWARD */ default: DEBUG(("Unknown Kerberos option %d\r\n", data[-1])); }}intkerberos5_status (TN_Authenticator *ap, char *name, int level){ if (level < AUTH_USER) return level;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -