mirror of
https://git.savannah.gnu.org/git/inetutils.git
synced 2026-01-12 00:19:39 +08:00
731 lines
16 KiB
C
731 lines
16 KiB
C
/*
|
|
Copyright (C) 2003-2025 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 3 of the License, 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 A 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 this program. If not, see `http://www.gnu.org/licenses/'. */
|
|
|
|
/* Written by Simon Josefsson and Nicolas Pouvesle, based on
|
|
kerberos5.c from GNU Inetutils. */
|
|
|
|
#include <config.h>
|
|
|
|
#ifdef SHISHI
|
|
# include <stdlib.h>
|
|
# include <stdio.h>
|
|
# include <arpa/telnet.h>
|
|
# include <shishi.h>
|
|
|
|
# include <netdb.h>
|
|
# include <ctype.h>
|
|
# include <syslog.h>
|
|
# include <string.h>
|
|
# include <attribute.h>
|
|
|
|
# include "auth.h"
|
|
# include "misc.h"
|
|
|
|
# ifdef ENCRYPTION
|
|
# include "encrypt.h"
|
|
# endif
|
|
|
|
char *dest_realm = NULL;
|
|
|
|
Shishi_key *enckey = NULL;
|
|
|
|
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. */
|
|
|
|
Shishi *shishi_handle = NULL;
|
|
Shishi_ap *auth_handle;
|
|
|
|
# define DEBUG(c) if (auth_debug_mode) printf c
|
|
|
|
/* Callback from consumer. */
|
|
extern void printsub (char, unsigned char *, int);
|
|
|
|
static int
|
|
Data (TN_Authenticator *ap, int type, void *d, int c)
|
|
{
|
|
unsigned char *p = str_data + 4;
|
|
unsigned char *cd = (unsigned char *) d;
|
|
|
|
/* Submitted as test data. */
|
|
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));
|
|
}
|
|
|
|
Shishi *shishi_telnet = NULL;
|
|
|
|
/* FIXME: Reverse return code! */
|
|
int
|
|
krb5shishi_init (TN_Authenticator *ap MAYBE_UNUSED, int server)
|
|
{
|
|
if (server)
|
|
str_data[3] = TELQUAL_REPLY;
|
|
else
|
|
str_data[3] = TELQUAL_IS;
|
|
|
|
if (!shishi_check_version (SHISHI_VERSION))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
delayed_shishi_init (void)
|
|
{
|
|
if (shishi_handle)
|
|
return 1;
|
|
|
|
if (str_data[3] == TELQUAL_REPLY)
|
|
{
|
|
if (!shishi_handle && shishi_init_server (&shishi_handle) != SHISHI_OK)
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
if (!shishi_handle && shishi_init (&shishi_handle) != SHISHI_OK)
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
krb5shishi_cleanup (TN_Authenticator *ap MAYBE_UNUSED)
|
|
{
|
|
if (shishi_handle == NULL)
|
|
return;
|
|
|
|
shishi_done (shishi_handle);
|
|
shishi_handle = NULL;
|
|
}
|
|
|
|
int
|
|
krb5shishi_send (TN_Authenticator *ap)
|
|
{
|
|
int ap_opts;
|
|
char type_check[2];
|
|
Shishi_tkt *tkt;
|
|
Shishi_tkts_hint hint;
|
|
int rc;
|
|
char *tmp;
|
|
char *apreq;
|
|
size_t apreq_len;
|
|
|
|
if (!UserNameRequested)
|
|
{
|
|
DEBUG (("telnet: Kerberos V5: no user name supplied\r\n"));
|
|
return 0;
|
|
}
|
|
|
|
if (!delayed_shishi_init ())
|
|
{
|
|
DEBUG (("telnet: Kerberos V5: shishi initialization failed\r\n"));
|
|
return 0;
|
|
}
|
|
|
|
tmp = malloc (strlen ("host/") + strlen (RemoteHostName) + 1);
|
|
if (tmp == NULL)
|
|
{
|
|
DEBUG (("telnet: Kerberos V5: shishi memory allocation failed\r\n"));
|
|
return 0;
|
|
}
|
|
|
|
/* Check for Kerberos prefix in principal name. */
|
|
if (strchr (RemoteHostName, '/'))
|
|
strcpy (tmp, RemoteHostName);
|
|
else
|
|
sprintf (tmp, "host/%s", RemoteHostName);
|
|
|
|
memset (&hint, 0, sizeof (hint));
|
|
hint.server = tmp;
|
|
hint.client = UserNameRequested;
|
|
|
|
if (dest_realm && *dest_realm)
|
|
shishi_realm_default_set (shishi_handle, dest_realm);
|
|
else
|
|
{
|
|
/* Retrieve realm assigned to this server as per configuration. */
|
|
char *p = strchr (RemoteHostName, '/');
|
|
|
|
if (p)
|
|
++p;
|
|
else
|
|
p = RemoteHostName;
|
|
|
|
shishi_realm_default_set (shishi_handle,
|
|
shishi_realm_for_server (shishi_handle, p));
|
|
}
|
|
|
|
tkt = shishi_tkts_get (shishi_tkts_default (shishi_handle), &hint);
|
|
free (tmp);
|
|
if (!tkt)
|
|
{
|
|
DEBUG (("telnet: Kerberos V5: no shishi ticket for server\r\n"));
|
|
return 0;
|
|
}
|
|
|
|
if (auth_debug_mode)
|
|
shishi_tkt_pretty_print (tkt, stdout);
|
|
|
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
|
|
ap_opts = SHISHI_APOPTIONS_MUTUAL_REQUIRED;
|
|
else
|
|
ap_opts = 0;
|
|
|
|
type_check[0] = ap->type;
|
|
type_check[1] = ap->way;
|
|
|
|
# ifndef DONT_ALWAYS_USE_DES
|
|
/* Even if we are not using a DES key, we can still try a DES
|
|
session-key. Then we can support DES_?FB64 encryption with 3DES
|
|
or AES keys against non-RFC 2952 implementations. Of course, it
|
|
would be better to follow RFC 2952, but enc_des.c does not
|
|
support this (see comment in that file). */
|
|
if (shishi_tkt_keytype_fast (tkt) != SHISHI_DES_CBC_CRC &&
|
|
shishi_tkt_keytype_fast (tkt) != SHISHI_DES_CBC_MD4 &&
|
|
shishi_tkt_keytype_fast (tkt) != SHISHI_DES_CBC_MD5)
|
|
rc = shishi_ap_etype_tktoptionsdata (shishi_handle, &auth_handle,
|
|
SHISHI_DES_CBC_MD5,
|
|
tkt, ap_opts,
|
|
(char *) &type_check, 2);
|
|
else
|
|
# endif
|
|
rc = shishi_ap_tktoptionsdata (shishi_handle, &auth_handle,
|
|
tkt, ap_opts, (char *) &type_check, 2);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
DEBUG (("telnet: Kerberos V5: Could not make AP-REQ (%s)\r\n",
|
|
shishi_strerror (rc)));
|
|
return 0;
|
|
}
|
|
|
|
# ifdef ENCRYPTION
|
|
if (enckey)
|
|
{
|
|
shishi_key_done (enckey);
|
|
enckey = NULL;
|
|
}
|
|
|
|
rc = shishi_authenticator_get_subkey
|
|
(shishi_handle, shishi_ap_authenticator (auth_handle), &enckey);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
DEBUG (("telnet: Kerberos V5: could not get encryption key (%s)\r\n",
|
|
shishi_strerror (rc)));
|
|
return 0;
|
|
}
|
|
# endif
|
|
|
|
rc = shishi_ap_req_der (auth_handle, &apreq, &apreq_len);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
DEBUG (("telnet: Kerberos V5: could not DER encode (%s)\r\n",
|
|
shishi_strerror (rc)));
|
|
return 0;
|
|
}
|
|
|
|
if (auth_debug_mode)
|
|
{
|
|
shishi_authenticator_print (shishi_handle, stdout,
|
|
shishi_ap_authenticator (auth_handle));
|
|
shishi_apreq_print (shishi_handle, stdout, shishi_ap_req (auth_handle));
|
|
}
|
|
|
|
if (!auth_sendname (UserNameRequested, strlen (UserNameRequested)))
|
|
{
|
|
DEBUG (("telnet: Not enough room for user name\r\n"));
|
|
return 0;
|
|
}
|
|
|
|
if (!Data (ap, KRB_AUTH, apreq, apreq_len))
|
|
{
|
|
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 ENCRYPTION
|
|
static void
|
|
shishi_init_key (Session_Key *skey, int type)
|
|
{
|
|
int32_t etype = shishi_key_type (enckey);
|
|
|
|
if (etype == SHISHI_DES_CBC_CRC || etype == SHISHI_DES_CBC_MD4
|
|
|| etype == SHISHI_DES_CBC_MD5)
|
|
skey->type = SK_DES;
|
|
else
|
|
skey->type = SK_OTHER;
|
|
skey->length = shishi_key_length (enckey);
|
|
skey->data = (unsigned char *) shishi_key_value (enckey);
|
|
|
|
encrypt_session_key (skey, type);
|
|
}
|
|
# endif
|
|
|
|
void
|
|
krb5shishi_reply (TN_Authenticator *ap, unsigned char *data, int cnt)
|
|
{
|
|
static int mutual_complete = 0;
|
|
# ifdef ENCRYPTION
|
|
Session_Key skey;
|
|
# endif
|
|
|
|
if (cnt-- < 1)
|
|
return;
|
|
|
|
switch (*data++)
|
|
{
|
|
case KRB_REJECT:
|
|
if (cnt > 0)
|
|
printf ("[ Kerberos V5 rejects authentication: %.*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;
|
|
}
|
|
# ifdef ENCRYPTION
|
|
shishi_init_key (&skey, 0);
|
|
# endif
|
|
}
|
|
|
|
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);
|
|
/* This was last access to handle on behalf of the client. */
|
|
shishi_done (shishi_handle);
|
|
shishi_handle = NULL;
|
|
break;
|
|
|
|
case KRB_RESPONSE:
|
|
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
|
|
{
|
|
if (shishi_ap_rep_verify_der (auth_handle, (char *) data, cnt)
|
|
!= SHISHI_OK)
|
|
{
|
|
printf ("[ Mutual authentication failed ]\r\n");
|
|
auth_send_retry ();
|
|
break;
|
|
}
|
|
|
|
if (auth_debug_mode)
|
|
{
|
|
shishi_aprep_print (shishi_handle, stdout,
|
|
shishi_ap_rep (auth_handle));
|
|
shishi_encapreppart_print (shishi_handle, stdout,
|
|
shishi_ap_encapreppart
|
|
(auth_handle));
|
|
}
|
|
|
|
# ifdef ENCRYPTION
|
|
shishi_init_key (&skey, 0);
|
|
# endif
|
|
mutual_complete = 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DEBUG (("Unknown Kerberos option %d\r\n", data[-1]));
|
|
}
|
|
}
|
|
|
|
int
|
|
krb5shishi_status (TN_Authenticator *ap MAYBE_UNUSED,
|
|
char *name, size_t len, int level)
|
|
{
|
|
int status;
|
|
|
|
if (level < AUTH_USER)
|
|
return level;
|
|
|
|
if (UserNameRequested
|
|
&& shishi_authorized_p (shishi_handle,
|
|
shishi_ap_tkt (auth_handle), UserNameRequested))
|
|
{
|
|
/* FIXME: Check buffer length */
|
|
strncpy (name, UserNameRequested, len);
|
|
status = AUTH_VALID;
|
|
}
|
|
else
|
|
status = AUTH_USER;
|
|
|
|
return status;
|
|
}
|
|
|
|
static int
|
|
krb5shishi_is_auth (TN_Authenticator *a, unsigned char *data, int cnt,
|
|
char *errbuf, int errbuflen)
|
|
{
|
|
Shishi_key *key;
|
|
int rc;
|
|
char *cnamerealm, *server = NULL, *realm = NULL;
|
|
size_t cnamerealmlen;
|
|
# ifdef ENCRYPTION
|
|
Session_Key skey;
|
|
# endif
|
|
|
|
if (!delayed_shishi_init ())
|
|
{
|
|
DEBUG (("telnet: Kerberos V5: shishi initialization failed\r\n"));
|
|
return 0;
|
|
}
|
|
|
|
/* Enable use of `~/.k5login'. */
|
|
if (shishi_check_version ("1.0.2")) /* Faulty in version 1.0.1. */
|
|
{
|
|
rc = shishi_cfg_authorizationtype_set (shishi_handle, "k5login basic");
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
snprintf (errbuf, errbuflen,
|
|
"Cannot initiate authorization types: %s",
|
|
shishi_error (shishi_handle));
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
if (ServerPrincipal && *ServerPrincipal)
|
|
{
|
|
rc = shishi_parse_name (shishi_handle, ServerPrincipal,
|
|
&server, &realm);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
snprintf (errbuf, errbuflen,
|
|
"Cannot parse server principal name: %s",
|
|
shishi_strerror (rc));
|
|
return 1;
|
|
}
|
|
if (realm)
|
|
shishi_realm_default_set (shishi_handle, realm);
|
|
|
|
/* Reclaim an empty server part. */
|
|
if (server && !*server)
|
|
{
|
|
free (server);
|
|
server = NULL;
|
|
}
|
|
}
|
|
|
|
if (!server)
|
|
{
|
|
server = malloc (strlen ("host/") + strlen (LocalHostName) + 1);
|
|
if (server)
|
|
sprintf (server, "host/%s", LocalHostName);
|
|
}
|
|
|
|
if (server)
|
|
{
|
|
/* Two possible action on `server':
|
|
* "srv.local" : rewrite as "host/srv.local"
|
|
* "tn/srv.local" : accept as is
|
|
*/
|
|
char *p = strchr (server, '/');
|
|
|
|
if (!p)
|
|
{
|
|
p = server;
|
|
server = malloc (strlen ("host/") + strlen (p) + 1);
|
|
if (!server)
|
|
{
|
|
free (p); /* This old `server'. */
|
|
snprintf (errbuf, errbuflen,
|
|
"Cannot allocate memory for server name");
|
|
return 1;
|
|
}
|
|
sprintf (server, "host/%s", p);
|
|
}
|
|
|
|
if (realm)
|
|
key = shishi_hostkeys_for_serverrealm (shishi_handle, server, realm);
|
|
else
|
|
/* Enforce a search with the known default realm. */
|
|
key = shishi_hostkeys_for_serverrealm (shishi_handle,
|
|
server,
|
|
shishi_realm_default
|
|
(shishi_handle));
|
|
|
|
free (server);
|
|
}
|
|
else
|
|
key = shishi_hostkeys_for_localservicerealm (shishi_handle,
|
|
"host", realm);
|
|
|
|
free (realm);
|
|
|
|
if (key == NULL)
|
|
{
|
|
snprintf (errbuf, errbuflen, "Could not find key: %s",
|
|
shishi_error (shishi_handle));
|
|
return 1;
|
|
}
|
|
|
|
rc = shishi_ap (shishi_handle, &auth_handle);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
snprintf (errbuf, errbuflen,
|
|
"Cannot allocate authentication structures: %s",
|
|
shishi_strerror (rc));
|
|
return 1;
|
|
}
|
|
|
|
rc = shishi_ap_req_der_set (auth_handle, (char *) data, cnt);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
snprintf (errbuf, errbuflen,
|
|
"Cannot parse authentication information: %s",
|
|
shishi_strerror (rc));
|
|
return 1;
|
|
}
|
|
|
|
rc = shishi_ap_req_process (auth_handle, key);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
snprintf (errbuf, errbuflen, "Could not process AP-REQ: %s",
|
|
shishi_strerror (rc));
|
|
return 1;
|
|
}
|
|
|
|
if (shishi_apreq_mutual_required_p (shishi_handle,
|
|
shishi_ap_req (auth_handle)))
|
|
{
|
|
char *der;
|
|
size_t derlen;
|
|
|
|
rc = shishi_ap_rep_der (auth_handle, &der, &derlen);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
snprintf (errbuf, errbuflen, "Error DER encoding aprep: %s",
|
|
shishi_strerror (rc));
|
|
return 1;
|
|
}
|
|
|
|
Data (a, KRB_RESPONSE, der, derlen);
|
|
free (der);
|
|
}
|
|
|
|
rc = shishi_encticketpart_clientrealm (shishi_handle,
|
|
shishi_tkt_encticketpart
|
|
(shishi_ap_tkt (auth_handle)),
|
|
&cnamerealm, &cnamerealmlen);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
snprintf (errbuf, errbuflen, "Error getting authenticator name: %s",
|
|
shishi_strerror (rc));
|
|
return 1;
|
|
}
|
|
Data (a, KRB_ACCEPT, cnamerealm, cnamerealm ? -1 : 0);
|
|
DEBUG (("telnetd: Kerberos5 identifies him as ``%s''\r\n",
|
|
cnamerealm ? cnamerealm : ""));
|
|
free (cnamerealm);
|
|
auth_finished (a, AUTH_USER);
|
|
|
|
/* Make sure that shishi_handle is still valid,
|
|
* it must not be released in auth_finish()!
|
|
* The server side will make reference to it
|
|
* later on. */
|
|
|
|
# ifdef ENCRYPTION
|
|
if (enckey)
|
|
{
|
|
shishi_key_done (enckey);
|
|
enckey = NULL;
|
|
}
|
|
|
|
rc = shishi_authenticator_get_subkey (shishi_handle,
|
|
shishi_ap_authenticator (auth_handle),
|
|
&enckey);
|
|
if (rc != SHISHI_OK)
|
|
{
|
|
Shishi_tkt *tkt;
|
|
|
|
tkt = shishi_ap_tkt (auth_handle);
|
|
if (tkt)
|
|
{
|
|
rc = shishi_encticketpart_get_key (shishi_handle,
|
|
shishi_tkt_encticketpart (tkt),
|
|
&enckey);
|
|
if (rc != SHISHI_OK)
|
|
enckey = NULL;
|
|
|
|
shishi_tkt_done (tkt);
|
|
}
|
|
}
|
|
|
|
if (enckey == NULL)
|
|
{
|
|
snprintf (errbuf, errbuflen,
|
|
"telnet: Kerberos V5: could not get encryption key (%s)\r\n",
|
|
shishi_strerror (rc));
|
|
return 1;
|
|
}
|
|
|
|
shishi_init_key (&skey, 1);
|
|
# endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
krb5shishi_is (TN_Authenticator *ap, unsigned char *data, int cnt)
|
|
{
|
|
int r = 0;
|
|
char errbuf[512];
|
|
|
|
if (cnt-- < 1)
|
|
return;
|
|
errbuf[0] = 0;
|
|
switch (*data++)
|
|
{
|
|
case KRB_AUTH:
|
|
r = krb5shishi_is_auth (ap, data, cnt, errbuf, sizeof errbuf);
|
|
break;
|
|
|
|
default:
|
|
DEBUG (("Unknown Kerberos option %d\r\n", data[-1]));
|
|
Data (ap, KRB_REJECT, 0, 0);
|
|
break;
|
|
}
|
|
|
|
if (r)
|
|
{
|
|
if (!errbuf[0])
|
|
snprintf (errbuf, sizeof errbuf, "kerberos_is: error");
|
|
Data (ap, KRB_REJECT, errbuf, -1);
|
|
DEBUG (("%s\r\n", errbuf));
|
|
syslog (LOG_ERR, "%s", errbuf);
|
|
}
|
|
}
|
|
|
|
static char *
|
|
req_type_str (int type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case KRB_REJECT:
|
|
return "REJECT";
|
|
|
|
case KRB_ACCEPT:
|
|
return "ACCEPT";
|
|
|
|
case KRB_AUTH:
|
|
return "AUTH";
|
|
|
|
case KRB_RESPONSE:
|
|
return "RESPONSE";
|
|
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
# define ADDC(p,l,c) if ((l) > 0) {*(p)++ = (c); --(l);}
|
|
|
|
void
|
|
krb5shishi_printsub (unsigned char *data, int cnt, char *buf, int buflen)
|
|
{
|
|
char *p;
|
|
int i;
|
|
|
|
buf[buflen - 1] = '\0'; /* make sure its NULL terminated */
|
|
buflen -= 1;
|
|
|
|
p = req_type_str (data[3]);
|
|
if (!p)
|
|
{
|
|
int l = snprintf (buf, buflen, " %d (unknown)", data[3]);
|
|
buf += l;
|
|
buflen -= l;
|
|
}
|
|
else
|
|
{
|
|
while (buflen > 0 && (*buf++ = *p++) != 0)
|
|
buflen--;
|
|
}
|
|
|
|
switch (data[3])
|
|
{
|
|
case KRB_REJECT: /* Rejected (reason might follow) */
|
|
case KRB_ACCEPT: /* Accepted (username might follow) */
|
|
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:
|
|
case KRB_RESPONSE:
|
|
for (i = 4; buflen > 0 && i < cnt; i++)
|
|
{
|
|
int l = snprintf (buf, buflen, " %d", data[i]);
|
|
buf += l;
|
|
buflen -= l;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* SHISHI */
|