aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/os/k5auth.c
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/programs/Xserver/os/k5auth.c
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/programs/Xserver/os/k5auth.c')
-rw-r--r--nx-X11/programs/Xserver/os/k5auth.c801
1 files changed, 801 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/os/k5auth.c b/nx-X11/programs/Xserver/os/k5auth.c
new file mode 100644
index 000000000..78301ad10
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/k5auth.c
@@ -0,0 +1,801 @@
+/* $Xorg: k5auth.c,v 1.4 2001/02/09 02:05:23 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/programs/Xserver/os/k5auth.c,v 3.4 2001/01/17 22:37:10 dawes Exp $ */
+
+/*
+ * Kerberos V5 authentication scheme
+ * Author: Tom Yu <tlyu@MIT.EDU>
+ *
+ * Mostly snarfed wholesale from the user_user demo in the
+ * krb5 distribution. (At least the checking part)
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef TCPCONN
+#include <netinet/in.h>
+#endif
+#ifdef DNETCONN
+#include <netdnet/dn.h>
+#endif
+#include <arpa/inet.h>
+#include <krb5/krb5.h>
+/* 9/93: krb5.h leaks some symbols */
+#undef BITS32
+#undef xfree
+#include <krb5/los-proto.h>
+#include <X11/X.h>
+#include "os.h"
+#include "osdep.h"
+#include <X11/Xproto.h>
+#include <X11/Xfuncs.h>
+#include "dixstruct.h"
+#include <com_err.h>
+#include "Xauth.h"
+
+extern int (*k5_Vector[256])();
+extern int SendConnSetup();
+extern char *display; /* need this to generate rcache name */
+
+static XID krb5_id = ~0L;
+static krb5_principal srvname = NULL; /* service name */
+static char *ccname = NULL;
+static char *ktname = NULL; /* key table name */
+static char kerror[256];
+
+/*
+ * tgt_keyproc:
+ *
+ * extract session key from a credentials struct
+ */
+krb5_error_code tgt_keyproc(keyprocarg, principal, vno, key)
+ krb5_pointer keyprocarg;
+ krb5_principal principal;
+ krb5_kvno vno;
+ krb5_keyblock **key;
+{
+ krb5_creds *creds = (krb5_creds *)keyprocarg;
+
+ return krb5_copy_keyblock(&creds->keyblock, key);
+}
+
+/*
+ * k5_cmpenc:
+ *
+ * compare "encoded" principals
+ */
+Bool k5_cmpenc(pname, plen, buf)
+ unsigned char *pname;
+ short plen;
+ krb5_data *buf;
+{
+ return (plen == buf->length &&
+ memcmp(pname, buf->data, plen) == 0);
+}
+
+/*
+ * K5Check:
+ *
+ * This is stage 0 of the krb5 authentication protocol. It
+ * goes through the current credentials cache and extracts the
+ * primary principal and tgt to send to the client, or as
+ * appropriate, extracts from a keytab.
+ *
+ * The packet sent to the client has the following format:
+ *
+ * CARD8 reqType = 2
+ * CARD8 data = 0
+ * CARD16 length = total length of packet (in 32 bit units)
+ * CARD16 plen = length of encoded principal following
+ * STRING8 princ = encoded principal
+ * STRING8 ticket = server tgt
+ *
+ * For client-server authentication, the packet is as follows:
+ *
+ * CARD8 reqType = 3
+ * CARD8 data = 0
+ * CARD16 length = total length
+ * STRING8 princ = encoded principal of server
+ */
+XID K5Check(data_length, data, client, reason)
+ unsigned short data_length;
+ char *data;
+ ClientPtr client;
+ char **reason;
+{
+ krb5_error_code retval;
+ CARD16 tlen;
+ krb5_principal sprinc, cprinc;
+ krb5_ccache cc;
+ krb5_creds *creds;
+ char *outbuf, *cp;
+ krb5_data princ;
+ register char n;
+ xReq prefix;
+
+ if (krb5_id == ~0L)
+ return ~0L;
+ if (!ccname && !srvname)
+ return ~0L;
+ if (ccname)
+ {
+ if ((creds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL)
+ return ~0L;
+ if (retval = krb5_cc_resolve(ccname, &cc))
+ return ~0L;
+ bzero((char*)creds, sizeof (krb5_creds));
+ if (retval = krb5_cc_get_principal(cc, &cprinc))
+ {
+ krb5_free_creds(creds);
+ krb5_cc_close(cc);
+ return ~0L;
+ }
+ creds->client = cprinc;
+ if (retval =
+ krb5_build_principal_ext(&sprinc,
+ krb5_princ_realm(creds->client)->length,
+ krb5_princ_realm(creds->client)->data,
+ 6, "krbtgt",
+ krb5_princ_realm(creds->client)->length,
+ krb5_princ_realm(creds->client)->data,
+ 0))
+ {
+ krb5_free_creds(creds);
+ krb5_cc_close(cc);
+ return ~0L;
+ }
+ creds->server = sprinc;
+ retval = krb5_get_credentials(KRB5_GC_CACHED, cc, creds);
+ krb5_cc_close(cc);
+ if (retval)
+ {
+ krb5_free_creds(creds);
+ return ~0L;
+ }
+ if (retval = XauKrb5Encode(cprinc, &princ))
+ {
+ krb5_free_creds(creds);
+ return ~0L;
+ }
+ tlen = sz_xReq + 2 + princ.length + creds->ticket.length;
+ prefix.reqType = 2; /* opcode = authenticate user-to-user */
+ }
+ else if (srvname)
+ {
+ if (retval = XauKrb5Encode(srvname, &princ))
+ {
+ return ~0L;
+ }
+ tlen = sz_xReq + princ.length;
+ prefix.reqType = 3; /* opcode = authenticate client-server */
+ }
+ prefix.data = 0; /* stage = 0 */
+ prefix.length = (tlen + 3) >> 2; /* round up to nearest multiple
+ of 4 bytes */
+ if (client->swapped)
+ {
+ swaps(&prefix.length, n);
+ }
+ if ((cp = outbuf = (char *)malloc(tlen)) == NULL)
+ {
+ if (ccname)
+ {
+ krb5_free_creds(creds);
+ }
+ free(princ.data);
+ return ~0L;
+ }
+ memcpy(cp, &prefix, sz_xReq);
+ cp += sz_xReq;
+ if (ccname)
+ {
+ memcpy(cp, &princ.length, 2);
+ if (client->swapped)
+ {
+ swaps((CARD16 *)cp, n);
+ }
+ cp += 2;
+ }
+ memcpy(cp, princ.data, princ.length);
+ cp += princ.length;
+ free(princ.data); /* we don't need that anymore */
+ if (ccname)
+ memcpy(cp, creds->ticket.data, creds->ticket.length);
+ WriteToClient(client, tlen, outbuf);
+ free(outbuf);
+ client->requestVector = k5_Vector; /* hack in our dispatch vector */
+ client->clientState = ClientStateAuthenticating;
+ if (ccname)
+ {
+ ((OsCommPtr)client->osPrivate)->authstate.srvcreds = (pointer)creds; /* save tgt creds */
+ ((OsCommPtr)client->osPrivate)->authstate.ktname = NULL;
+ ((OsCommPtr)client->osPrivate)->authstate.srvname = NULL;
+ }
+ if (srvname)
+ {
+ ((OsCommPtr)client->osPrivate)->authstate.srvcreds = NULL;
+ ((OsCommPtr)client->osPrivate)->authstate.ktname = (pointer)ktname;
+ ((OsCommPtr)client->osPrivate)->authstate.srvname = (pointer)srvname;
+ }
+ ((OsCommPtr)client->osPrivate)->authstate.stageno = 1; /* next stage is 1 */
+ return krb5_id;
+}
+
+/*
+ * k5_stage1:
+ *
+ * This gets called out of the dispatcher after K5Check frobs with the
+ * client->requestVector. It accepts the ap_req from the client and verifies
+ * it. In addition, if the client has set AP_OPTS_MUTUAL_REQUIRED, it then
+ * sends an ap_rep to the client to achieve mutual authentication.
+ *
+ * client stage1 packet format is as follows:
+ *
+ * CARD8 reqType = 1
+ * CARD8 data = ignored
+ * CARD16 length = total length
+ * STRING8 data = the actual ap_req
+ *
+ * stage2 packet sent back to client for mutual authentication:
+ *
+ * CARD8 reqType = 2
+ * CARD8 data = 2
+ * CARD16 length = total length
+ * STRING8 data = the ap_rep
+ */
+int k5_stage1(client)
+ register ClientPtr client;
+{
+ long addrlen;
+ krb5_error_code retval, retval2;
+ register char n;
+ struct sockaddr cli_net_addr;
+ xReq prefix;
+ krb5_principal cprinc;
+ krb5_data buf;
+ krb5_creds *creds = (krb5_creds *)((OsCommPtr)client->osPrivate)->authstate.srvcreds;
+ krb5_keyblock *skey;
+ krb5_address cli_addr, **localaddrs = NULL;
+ krb5_tkt_authent *authdat;
+ krb5_ap_rep_enc_part rep;
+ krb5_int32 ctime, cusec;
+ krb5_rcache rcache = NULL;
+ char *cachename = NULL, *rc_type = NULL, *rc_base = "rcX", *kt = NULL;
+ REQUEST(xReq);
+
+ if (((OsCommPtr)client->osPrivate)->authstate.stageno != 1)
+ {
+ if (creds)
+ krb5_free_creds(creds);
+ return(SendConnSetup(client, "expected Krb5 stage1 packet"));
+ }
+ addrlen = sizeof (cli_net_addr);
+ if (getpeername(((OsCommPtr)client->osPrivate)->fd,
+ &cli_net_addr, &addrlen) == -1)
+ {
+ if (creds)
+ krb5_free_creds(creds);
+ return(SendConnSetup(client, "Krb5 stage1: getpeername failed"));
+ }
+ if (cli_net_addr.sa_family == AF_UNSPEC
+#if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+ || cli_net_addr.sa_family == AF_UNIX
+#endif
+ ) /* assume local host */
+ {
+ krb5_os_localaddr(&localaddrs);
+ if (!localaddrs || !localaddrs[0])
+ {
+ if (creds)
+ krb5_free_creds(creds);
+ return(SendConnSetup(client, "Krb5 failed to get localaddrs"));
+ }
+ cli_addr.addrtype = localaddrs[0]->addrtype;
+ cli_addr.length = localaddrs[0]->length;
+ cli_addr.contents = localaddrs[0]->contents;
+ }
+ else
+ {
+ cli_addr.addrtype = cli_net_addr.sa_family; /* the values
+ are compatible */
+ switch (cli_net_addr.sa_family)
+ {
+#ifdef TCPCONN
+ case AF_INET:
+ cli_addr.length = sizeof (struct in_addr);
+ cli_addr.contents =
+ (krb5_octet *)&((struct sockaddr_in *)&cli_net_addr)->sin_addr;
+ break;
+#endif
+#ifdef DNETCONN
+ case AF_DECnet:
+ cli_addr.length = sizeof (struct dn_naddr);
+ cli_addr.contents =
+ (krb5_octet *)&((struct sockaddr_dn *)&cli_net_addr)->sdn_add;
+ break;
+#endif
+ default:
+ if (localaddrs)
+ krb5_free_addresses(localaddrs);
+ if (creds)
+ krb5_free_creds(creds);
+ sprintf(kerror, "Krb5 stage1: unknown address family %d from getpeername",
+ cli_net_addr.sa_family);
+ return(SendConnSetup(client, kerror));
+ }
+ }
+ if ((rcache = (krb5_rcache)malloc(sizeof(*rcache))) == NULL)
+ {
+ if (localaddrs)
+ krb5_free_addresses(localaddrs);
+ if (creds)
+ krb5_free_creds(creds);
+ return(SendConnSetup(client, "malloc bombed for krb5_rcache"));
+ }
+ if ((rc_type = krb5_rc_default_type()) == NULL)
+ rc_type = "dfl";
+ if (retval = krb5_rc_resolve_type(&rcache, rc_type))
+ {
+ if (localaddrs)
+ krb5_free_addresses(localaddrs);
+ if (creds)
+ krb5_free_creds(creds);
+ free(rcache);
+ strcpy(kerror, "krb5_rc_resolve_type failed: ");
+ strncat(kerror, error_message(retval), 231);
+ return(SendConnSetup(client, kerror));
+ }
+ if ((cachename = (char *)malloc(strlen(rc_base) + strlen(display) + 1))
+ == NULL)
+ {
+ if (localaddrs)
+ krb5_free_addresses(localaddrs);
+ if (creds)
+ krb5_free_creds(creds);
+ free(rcache);
+ return(SendConnSetup(client, "Krb5: malloc bombed for cachename"));
+ }
+ strcpy(cachename, rc_base);
+ strcat(cachename, display);
+ if (retval = krb5_rc_resolve(rcache, cachename))
+ {
+ if (localaddrs)
+ krb5_free_addresses(localaddrs);
+ if (creds)
+ krb5_free_creds(creds);
+ free(rcache);
+ free(cachename);
+ strcpy(kerror, "krb5_rc_resolve failed: ");
+ strncat(kerror, error_message(retval), 236);
+ return(SendConnSetup(client, kerror));
+ }
+ free(cachename);
+ if (krb5_rc_recover(rcache))
+ {
+ extern krb5_deltat krb5_clockskew;
+ if (retval = krb5_rc_initialize(rcache, krb5_clockskew))
+ {
+ if (localaddrs)
+ krb5_free_addresses(localaddrs);
+ if (creds)
+ krb5_free_creds(creds);
+ if (retval2 = krb5_rc_close(rcache))
+ {
+ strcpy(kerror, "krb5_rc_close failed: ");
+ strncat(kerror, error_message(retval2), 238);
+ return(SendConnSetup(client, kerror));
+ }
+ free(rcache);
+ strcpy(kerror, "krb5_rc_initialize failed: ");
+ strncat(kerror, error_message(retval), 233);
+ return(SendConnSetup(client, kerror));
+ }
+ }
+ buf.length = (stuff->length << 2) - sz_xReq;
+ buf.data = (char *)stuff + sz_xReq;
+ if (creds)
+ {
+ retval = krb5_rd_req(&buf,
+ NULL, /* don't bother with server name */
+ &cli_addr,
+ NULL, /* no fetchfrom */
+ tgt_keyproc,
+ creds, /* credentials as arg to
+ keyproc */
+ rcache,
+ &authdat);
+ krb5_free_creds(creds);
+ }
+ else if (kt = (char *)((OsCommPtr)client->osPrivate)->authstate.ktname)
+ {
+ retval = krb5_rd_req(&buf, srvname, &cli_addr, kt, NULL, NULL,
+ rcache, &authdat);
+ ((OsCommPtr)client->osPrivate)->authstate.ktname = NULL;
+ }
+ else
+ {
+ if (localaddrs)
+ krb5_free_addresses(localaddrs);
+ return(SendConnSetup(client, "Krb5: neither srvcreds nor ktname set"));
+ }
+ if (localaddrs)
+ krb5_free_addresses(localaddrs);
+ if (rcache)
+ {
+ if (retval2 = krb5_rc_close(rcache))
+ {
+ strcpy(kerror, "krb5_rc_close failed (2): ");
+ strncat(kerror, error_message(retval2), 230);
+ return(SendConnSetup(client, kerror));
+ }
+ free(rcache);
+ }
+ if (retval)
+ {
+ strcpy(kerror, "Krb5: Bad application request: ");
+ strncat(kerror, error_message(retval), 224);
+ return(SendConnSetup(client, kerror));
+ }
+ cprinc = authdat->ticket->enc_part2->client;
+ skey = authdat->ticket->enc_part2->session;
+ if (XauKrb5Encode(cprinc, &buf))
+ {
+ krb5_free_tkt_authent(authdat);
+ return(SendConnSetup(client, "XauKrb5Encode bombed"));
+ }
+ /*
+ * Now check to see if the principal we got is one that we want to let in
+ */
+ if (ForEachHostInFamily(FamilyKrb5Principal, k5_cmpenc, (pointer)&buf))
+ {
+ free(buf.data);
+ /*
+ * The following deals with sending an ap_rep to the client to
+ * achieve mutual authentication. The client sends back a stage 3
+ * packet if all is ok.
+ */
+ if (authdat->ap_options | AP_OPTS_MUTUAL_REQUIRED)
+ {
+ /*
+ * stage 2: send ap_rep to client
+ */
+ if (retval = krb5_us_timeofday(&ctime, &cusec))
+ {
+ krb5_free_tkt_authent(authdat);
+ strcpy(kerror, "error in krb5_us_timeofday: ");
+ strncat(kerror, error_message(retval), 234);
+ return(SendConnSetup(client, kerror));
+ }
+ rep.ctime = ctime;
+ rep.cusec = cusec;
+ rep.subkey = NULL;
+ rep.seq_number = 0;
+ if (retval = krb5_mk_rep(&rep, skey, &buf))
+ {
+ krb5_free_tkt_authent(authdat);
+ strcpy(kerror, "error in krb5_mk_rep: ");
+ strncat(kerror, error_message(retval), 238);
+ return(SendConnSetup(client, kerror));
+ }
+ prefix.reqType = 2; /* opcode = authenticate */
+ prefix.data = 2; /* stage = 2 */
+ prefix.length = (buf.length + sz_xReq + 3) >> 2;
+ if (client->swapped)
+ {
+ swaps(&prefix.length, n);
+ }
+ WriteToClient(client, sz_xReq, (char *)&prefix);
+ WriteToClient(client, buf.length, buf.data);
+ free(buf.data);
+ krb5_free_tkt_authent(authdat);
+ ((OsCommPtr)client->osPrivate)->authstate.stageno = 3; /* expect stage3 packet */
+ return(Success);
+ }
+ else
+ {
+ free(buf.data);
+ krb5_free_tkt_authent(authdat);
+ return(SendConnSetup(client, NULL)); /* success! */
+ }
+ }
+ else
+ {
+ char *kname;
+
+ krb5_free_tkt_authent(authdat);
+ free(buf.data);
+ retval = krb5_unparse_name(cprinc, &kname);
+ if (retval == 0)
+ {
+ sprintf(kerror, "Principal \"%s\" is not authorized to connect",
+ kname);
+ if (kname)
+ free(kname);
+ return(SendConnSetup(client, kerror));
+ }
+ else
+ return(SendConnSetup(client,"Principal is not authorized to connect to Server"));
+ }
+}
+
+/*
+ * k5_stage3:
+ *
+ * Get the short ack packet from the client. This packet can conceivably
+ * be expanded to allow for switching on end-to-end encryption.
+ *
+ * stage3 packet format:
+ *
+ * CARD8 reqType = 3
+ * CARD8 data = ignored (for now)
+ * CARD16 length = should be zero
+ */
+int k5_stage3(client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+
+ if (((OsCommPtr)client->osPrivate)->authstate.stageno != 3)
+ {
+ return(SendConnSetup(client, "expected Krb5 stage3 packet"));
+ }
+ else
+ return(SendConnSetup(client, NULL)); /* success! */
+}
+
+k5_bad(client)
+ register ClientPtr client;
+{
+ if (((OsCommPtr)client->osPrivate)->authstate.srvcreds)
+ krb5_free_creds((krb5_creds *)((OsCommPtr)client->osPrivate)->authstate.srvcreds);
+ sprintf(kerror, "unrecognized Krb5 auth packet %d, expecting %d",
+ ((xReq *)client->requestBuffer)->reqType,
+ ((OsCommPtr)client->osPrivate)->authstate.stageno);
+ return(SendConnSetup(client, kerror));
+}
+
+/*
+ * K5Add:
+ *
+ * Takes the name of a credentials cache and resolves it. Also adds the
+ * primary principal of the ccache to the acl.
+ *
+ * Now will also take a service name.
+ */
+int K5Add(data_length, data, id)
+ unsigned short data_length;
+ char *data;
+ XID id;
+{
+ krb5_principal princ;
+ krb5_error_code retval;
+ krb5_keytab_entry tmp_entry;
+ krb5_keytab keytab;
+ krb5_kvno kvno = 0;
+ krb5_ccache cc;
+ char *nbuf, *cp;
+ krb5_data kbuf;
+ int i, ktlen;
+
+ krb5_init_ets(); /* can't think of a better place to put it */
+ krb5_id = ~0L;
+ if (data_length < 3)
+ return 0;
+ if ((nbuf = (char *)malloc(data_length - 2)) == NULL)
+ return 0;
+ memcpy(nbuf, data + 3, data_length - 3);
+ nbuf[data_length - 3] = '\0';
+ if (ccname)
+ {
+ free(ccname);
+ ccname = NULL;
+ }
+ if (srvname)
+ {
+ krb5_free_principal(srvname);
+ srvname = NULL;
+ }
+ if (ktname)
+ {
+ free(ktname);
+ ktname = NULL;
+ }
+ if (!strncmp(data, "UU:", 3))
+ {
+ if (retval = krb5_cc_resolve(nbuf, &cc))
+ {
+ ErrorF("K5Add: krb5_cc_resolve of \"%s\" failed: %s\n",
+ nbuf, error_message(retval));
+ free(nbuf);
+ return 0;
+ }
+ if (cc && !(retval = krb5_cc_get_principal(cc, &princ)))
+ {
+ if (XauKrb5Encode(princ, &kbuf))
+ {
+ free(nbuf);
+ krb5_free_principal(princ);
+ krb5_cc_close(cc);
+ return 0;
+ }
+ if (krb5_cc_close(cc))
+ return 0;
+ AddHost(NULL, FamilyKrb5Principal, kbuf.length, kbuf.data);
+ krb5_free_principal(princ);
+ free(kbuf.data);
+ ccname = nbuf;
+ krb5_id = id;
+ return 1;
+ }
+ else
+ {
+ ErrorF("K5Add: getting principal from cache \"%s\" failed: %s\n",
+ nbuf, error_message(retval));
+ }
+ }
+ else if (!strncmp(data, "CS:", 3))
+ {
+ if ((cp = strchr(nbuf, ',')) == NULL)
+ {
+ free(nbuf);
+ return 0;
+ }
+ *cp = '\0'; /* gross but it works :-) */
+ ktlen = strlen(cp + 1);
+ if ((ktname = (char *)malloc(ktlen + 1)) == NULL)
+ {
+ free(nbuf);
+ return 0;
+ }
+ strcpy(ktname, cp + 1);
+ retval = krb5_sname_to_principal(NULL, /* NULL for hostname uses
+ local host name*/
+ nbuf, KRB5_NT_SRV_HST,
+ &srvname);
+ free(nbuf);
+ if (retval)
+ {
+ free(ktname);
+ ktname = NULL;
+ return 0;
+ }
+ if (retval = krb5_kt_resolve(ktname, &keytab))
+ {
+ free(ktname);
+ ktname = NULL;
+ krb5_free_principal(srvname);
+ srvname = NULL;
+ return 0;
+ }
+ retval = krb5_kt_get_entry(keytab, srvname, kvno, &tmp_entry);
+ krb5_kt_free_entry(&tmp_entry);
+ if (retval)
+ {
+ free(ktname);
+ ktname = NULL;
+ krb5_free_principal(srvname);
+ srvname = NULL;
+ return 0;
+ }
+ if (XauKrb5Encode(srvname, &kbuf))
+ {
+ free(ktname);
+ ktname = NULL;
+ krb5_free_principal(srvname);
+ srvname = NULL;
+ return 0;
+ }
+ AddHost(NULL, FamilyKrb5Principal, kbuf.length, kbuf.data);
+ krb5_id = id;
+ return 1;
+ }
+ else
+ {
+ ErrorF("K5Add: credentials cache name \"%.*s\" in auth file: unknown type\n",
+ data_length, data);
+ }
+ return 0;
+}
+
+/*
+ * K5Reset:
+ *
+ * Reset krb5_id, also nuke the current principal from the acl.
+ */
+int K5Reset()
+{
+ krb5_principal princ;
+ krb5_error_code retval;
+ krb5_ccache cc;
+ krb5_data kbuf;
+ int i;
+
+ if (ccname)
+ {
+ if (retval = krb5_cc_resolve(ccname, &cc))
+ {
+ free(ccname);
+ ccname = NULL;
+ }
+ if (cc && !(retval = krb5_cc_get_principal(cc, &princ)))
+ {
+ if (XauKrb5Encode(princ, &kbuf))
+ return 1;
+ RemoveHost(NULL, FamilyKrb5Principal, kbuf.length, kbuf.data);
+ krb5_free_principal(princ);
+ free(kbuf.data);
+ if (krb5_cc_close(cc))
+ return 1;
+ free(ccname);
+ ccname = NULL;
+ }
+ }
+ if (srvname)
+ {
+ if (XauKrb5Encode(srvname, &kbuf))
+ return 1;
+ RemoveHost(NULL, FamilyKrb5Principal, kbuf.length, kbuf.data);
+ krb5_free_principal(srvname);
+ free(kbuf.data);
+ srvname = NULL;
+ }
+ if (ktname)
+ {
+ free(ktname);
+ ktname = NULL;
+ }
+ krb5_id = ~0L;
+ return 0;
+}
+
+XID K5ToID(data_length, data)
+ unsigned short data_length;
+ char *data;
+{
+ return krb5_id;
+}
+
+int K5FromID(id, data_lenp, datap)
+ XID id;
+ unsigned short *data_lenp;
+ char **datap;
+{
+ return 0;
+}
+
+int K5Remove(data_length, data)
+ unsigned short data_length;
+ char *data;
+{
+ return 0;
+}