Added leashdll/wshelper related files from KFW
authorSam Hartman <hartmans@mit.edu>
Wed, 28 Sep 2011 20:54:16 +0000 (20:54 +0000)
committerSam Hartman <hartmans@mit.edu>
Wed, 28 Sep 2011 20:54:16 +0000 (20:54 +0000)
From: Alexey Melnikov <alexey.melnikov@isode.com>

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25243 dc483132-0cff-0310-8789-dd5450dbe970

59 files changed:
src/include/arpa/nameser.h [new file with mode: 0644]
src/include/hesiod.h [new file with mode: 0644]
src/include/mitwhich.h [new file with mode: 0644]
src/include/resolv.h [new file with mode: 0644]
src/include/wshelper.h [new file with mode: 0644]
src/windows/leashdll/AFSroutines.c [new file with mode: 0644]
src/windows/leashdll/include/krb4/conf-pc.h [new file with mode: 0644]
src/windows/leashdll/include/krb4/conf.h [new file with mode: 0644]
src/windows/leashdll/include/krb4/osconf.h [new file with mode: 0644]
src/windows/leashdll/include/leasherr.h [new file with mode: 0644]
src/windows/leashdll/include/leashinfo.h [new file with mode: 0644]
src/windows/leashdll/include/leashwin.h [new file with mode: 0644]
src/windows/leashdll/include/loadfuncs-com_err.h [new file with mode: 0644]
src/windows/leashdll/include/loadfuncs-krb5.h [new file with mode: 0644]
src/windows/leashdll/include/loadfuncs-lsa.h [new file with mode: 0644]
src/windows/leashdll/include/loadfuncs-profile.h [new file with mode: 0644]
src/windows/leashdll/include/loadfuncs.h [new file with mode: 0644]
src/windows/leashdll/krb5routines.c [new file with mode: 0644]
src/windows/leashdll/leash-int.h [new file with mode: 0644]
src/windows/leashdll/leashdll.c [new file with mode: 0644]
src/windows/leashdll/leashdll.h [new file with mode: 0644]
src/windows/leashdll/leasherr.c [new file with mode: 0644]
src/windows/leashdll/leasherr.et [new file with mode: 0644]
src/windows/leashdll/leashids.h [new file with mode: 0644]
src/windows/leashdll/leashw32.def [new file with mode: 0644]
src/windows/leashdll/loadfuncs.c [new file with mode: 0644]
src/windows/leashdll/lsh_pwd.c [new file with mode: 0644]
src/windows/leashdll/lsh_pwd.rc [new file with mode: 0644]
src/windows/leashdll/lshcallb.c [new file with mode: 0644]
src/windows/leashdll/lshfunc.c [new file with mode: 0644]
src/windows/leashdll/registry.c [new file with mode: 0644]
src/windows/leashdll/reminder.h [new file with mode: 0644]
src/windows/leashdll/res/islogo.bmp [new file with mode: 0644]
src/windows/leashdll/res/leash.ico [new file with mode: 0644]
src/windows/leashdll/resource.h [new file with mode: 0644]
src/windows/leashdll/timesync.c [new file with mode: 0644]
src/windows/leashdll/ver.rc [new file with mode: 0644]
src/windows/leashdll/winerr.c [new file with mode: 0644]
src/windows/leashdll/winutil.c [new file with mode: 0644]
src/windows/wshelper/dllmain.c [new file with mode: 0644]
src/windows/wshelper/gethna.c [new file with mode: 0644]
src/windows/wshelper/hesiod.c [new file with mode: 0644]
src/windows/wshelper/hesmailh.c [new file with mode: 0644]
src/windows/wshelper/hespwnam.c [new file with mode: 0644]
src/windows/wshelper/hesservb.c [new file with mode: 0644]
src/windows/wshelper/inetaton.c [new file with mode: 0644]
src/windows/wshelper/pwd.h [new file with mode: 0644]
src/windows/wshelper/res_comp.c [new file with mode: 0644]
src/windows/wshelper/res_init.c [new file with mode: 0644]
src/windows/wshelper/res_quer.c [new file with mode: 0644]
src/windows/wshelper/resource.h [new file with mode: 0644]
src/windows/wshelper/resource.rc [new file with mode: 0644]
src/windows/wshelper/string.rc [new file with mode: 0644]
src/windows/wshelper/ver.rc.inc [new file with mode: 0644]
src/windows/wshelper/version.rc [new file with mode: 0644]
src/windows/wshelper/wsh-int.h [new file with mode: 0644]
src/windows/wshelper/wshelp32.def [new file with mode: 0644]
src/windows/wshelper/wshelp64.def [new file with mode: 0644]
src/windows/wshelper/wshelper.def [new file with mode: 0644]

diff --git a/src/include/arpa/nameser.h b/src/include/arpa/nameser.h
new file mode 100644 (file)
index 0000000..f9ddafc
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * @doc
+ * @module nameser.h |
+ * Copyright (c) 1983, 1989 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.
+ *
+ *     @(#)nameser.h   5.25 (Berkeley) 4/3/91
+ */
+
+#ifndef _NAMESER_H_
+#define        _NAMESER_H_
+
+/*
+ * Define constants based on rfc883
+ */
+#define PACKETSZ       512             /* maximum packet size */
+#define MAXDNAME       256             /* maximum domain name */
+#define MAXCDNAME      255             /* maximum compressed domain name */
+#define MAXLABEL       63              /* maximum length of domain label */
+       /* Number of bytes of fixed size data in query structure */
+#define QFIXEDSZ       4
+       /* number of bytes of fixed size data in resource record */
+#define RRFIXEDSZ      10
+
+#if !defined(MAXHOSTNAME)
+#define MAXHOSTNAME MAXCDNAME
+#endif
+
+/*
+ * Internet nameserver port number
+ */
+#define NAMESERVER_PORT        53
+
+/*
+ * Currently defined opcodes
+ */
+#define QUERY          0x0             /* standard query */
+#define IQUERY         0x1             /* inverse query */
+#define STATUS         0x2             /* nameserver status query */
+/*#define xxx          0x3             /* 0x3 reserved */
+       /* non standard */
+#define UPDATEA                0x9             /* add resource record */
+#define UPDATED                0xa             /* delete a specific resource record */
+#define UPDATEDA       0xb             /* delete all nemed resource record */
+#define UPDATEM                0xc             /* modify a specific resource record */
+#define UPDATEMA       0xd             /* modify all named resource record */
+
+#define ZONEINIT       0xe             /* initial zone transfer */
+#define ZONEREF                0xf             /* incremental zone referesh */
+
+/*
+ * Currently defined response codes
+ */
+#define NOERROR                0               /* no error */
+#define FORMERR                1               /* format error */
+#define SERVFAIL       2               /* server failure */
+#define NXDOMAIN       3               /* non existent domain */
+#define NOTIMP         4               /* not implemented */
+#define REFUSED                5               /* query refused */
+       /* non standard */
+#define NOCHANGE       0xf             /* update failed to change db */
+
+/*
+ * Type values for resources and queries
+ */
+#define T_A            1               /* host address */
+#define T_NS           2               /* authoritative server */
+#define T_MD           3               /* mail destination */
+#define T_MF           4               /* mail forwarder */
+#define T_CNAME                5               /* connonical name */
+#define T_SOA          6               /* start of authority zone */
+#define T_MB           7               /* mailbox domain name */
+#define T_MG           8               /* mail group member */
+#define T_MR           9               /* mail rename name */
+#define T_NULL         10              /* null resource record */
+#define T_WKS          11              /* well known service */
+#define T_PTR          12              /* domain name pointer */
+#define T_HINFO                13              /* host information */
+#define T_MINFO                14              /* mailbox information */
+#define T_MX           15              /* mail routing information */
+#define T_TXT          16              /* text strings */
+       /* non standard */
+#define T_UINFO                100             /* user (finger) information */
+#define T_UID          101             /* user ID */
+#define T_GID          102             /* group ID */
+#define T_UNSPEC       103             /* Unspecified format (binary data) */
+       /* Query type values which do not appear in resource records */
+#define T_AXFR         252             /* transfer zone of authority */
+#define T_MAILB                253             /* transfer mailbox records */
+#define T_MAILA                254             /* transfer mail agent records */
+#define T_ANY          255             /* wildcard match */
+
+/*
+ * Values for class field
+ */
+
+#define C_IN           1               /* the arpa internet */
+#define C_CHAOS                3               /* for chaos net at MIT */
+#define C_HS           4               /* for Hesiod name server at MIT */
+       /* Query class values which do not appear in resource records */
+#define C_ANY          255             /* wildcard match */
+
+/*
+ * Status return codes for T_UNSPEC conversion routines
+ */
+#define CONV_SUCCESS 0
+#define CONV_OVERFLOW -1
+#define CONV_BADFMT -2
+#define CONV_BADCKSUM -3
+#define CONV_BADBUFLEN -4
+
+#ifndef BYTE_ORDER
+#define        LITTLE_ENDIAN   1234    /* least-significant byte first (vax) */
+#define        BIG_ENDIAN      4321    /* most-significant byte first (IBM, net) */
+#define        PDP_ENDIAN      3412    /* LSB first in word, MSW first in long (pdp) */
+
+#if defined(vax) || defined(ns32000) || defined(sun386) || defined(MIPSEL) || \
+    defined(BIT_ZERO_ON_RIGHT)
+#define BYTE_ORDER     LITTLE_ENDIAN
+
+#endif
+#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
+    defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
+    defined(MIPSEB) || defined (BIT_ZERO_ON_LEFT)
+#define BYTE_ORDER     BIG_ENDIAN
+#endif
+#endif /* BYTE_ORDER */
+
+#ifndef BYTE_ORDER
+       /* you must determine what the correct bit order is for your compiler */
+       #define BYTE_ORDER LITTLE_ENDIAN        /* for Intel x86 series */
+#endif
+/*
+ * Structure for query header, the order of the fields is machine and
+ * compiler dependent, in our case, the bits within a byte are assignd
+ * least significant first, while the order of transmition is most
+ * significant first.  This requires a somewhat confusing rearrangement.
+ */
+
+#if defined (_WINDLL) || (_WIN32)
+/* define UNIX types */
+#include <winsock.h>
+#endif
+
+typedef struct {
+       u_short id;             /* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+                       /* fields in third byte */
+       u_char  qr:1;           /* response flag */
+       u_char  opcode:4;       /* purpose of message */
+       u_char  aa:1;           /* authoritive answer */
+       u_char  tc:1;           /* truncated message */
+       u_char  rd:1;           /* recursion desired */
+                       /* fields in fourth byte */
+       u_char  ra:1;           /* recursion available */
+       u_char  pr:1;           /* primary server required (non standard) */
+       u_char  unused:2;       /* unused bits */
+       u_char  rcode:4;        /* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+                       /* fields in third byte */
+       u_char  rd:1;           /* recursion desired */
+       u_char  tc:1;           /* truncated message */
+       u_char  aa:1;           /* authoritive answer */
+       u_char  opcode:4;       /* purpose of message */
+       u_char  qr:1;           /* response flag */
+                       /* fields in fourth byte */
+       u_char  rcode:4;        /* response code */
+       u_char  unused:2;       /* unused bits */
+       u_char  pr:1;           /* primary server required (non standard) */
+       u_char  ra:1;           /* recursion available */
+#endif
+                       /* remaining bytes */
+       u_short qdcount;        /* number of question entries */
+       u_short ancount;        /* number of answer entries */
+       u_short nscount;        /* number of authority entries */
+       u_short arcount;        /* number of resource entries */
+} HEADER;
+
+/*
+ * Defines for handling compressed domain names
+ */
+#define INDIR_MASK     0xc0
+
+/*
+ * Structure for passing resource records around.
+ */
+struct rrec {
+       short   r_zone;                 /* zone number */
+       short   r_class;                /* class number */
+       short   r_type;                 /* type number */
+       u_long  r_ttl;                  /* time to live */
+       int     r_size;                 /* size of data area */
+       char    *r_data;                /* pointer to data */
+};
+
+extern u_short _getshort();
+extern u_long  _getlong();
+
+/*
+ * Inline versions of get/put short/long.
+ * Pointer is advanced; we assume that both arguments
+ * are lvalues and will already be in registers.
+ * cp MUST be u_char *.
+ */
+#define GETSHORT(s, cp) { \
+       (s) = *(cp)++ << 8; \
+       (s) |= *(cp)++; \
+}
+
+#define GETLONG(l, cp) { \
+       (l) = *(cp)++ << 8; \
+       (l) |= *(cp)++; (l) <<= 8; \
+       (l) |= *(cp)++; (l) <<= 8; \
+       (l) |= *(cp)++; \
+}
+
+
+#define PUTSHORT(s, cp) { \
+       *(cp)++ = (s) >> 8; \
+       *(cp)++ = (s); \
+}
+
+/*
+ * Warning: PUTLONG destroys its first argument.
+ */
+#define PUTLONG(l, cp) { \
+       (cp)[3] = l; \
+       (cp)[2] = (l >>= 8); \
+       (cp)[1] = (l >>= 8); \
+       (cp)[0] = l >> 8; \
+       (cp) += sizeof(u_long); \
+}
+
+#endif /* !_NAMESER_H_ */
diff --git a/src/include/hesiod.h b/src/include/hesiod.h
new file mode 100644 (file)
index 0000000..3005929
--- /dev/null
@@ -0,0 +1,217 @@
+/*!    \file hesiod.h
+ *     WSHelper DNS/Hesiod Library
+ *
+ *     This file contains the function declaration for: \n
+ *     hes_to_bind()   \n
+ *     hes_resolve()   \n
+ *     hes_error()             \n
+ *     hes_free()              \n
+ *     hes_getmailhost()       \n
+ *     hes_getservbyname()     \n
+ *     hes_getpwnam()  \n
+ *     hes_getpwuid()  \n
+*/
+
+#ifndef _HESIOD_
+#define _HESIOD_
+
+
+#include <windows.h>
+
+/*! \def HESIOD_CONF
+ *     name of the hesiod configuration file. We will look at the file to determine the RHS AND LHS value before using the default.
+ *  Here is a sample hesiod.cfg file: \n
+ *     lhs .ns \n
+ *     rhs .ATHENA.MIT.EDU \n
+ */
+#define HESIOD_CONF     "c:\\net\\tcp\\hesiod.cfg"
+
+/*! \def DEF_RHS
+ *     default RHS value is the hesiod configuration file is not present
+ */
+#define DEF_RHS         ".Athena.MIT.EDU"
+
+/*! \def DEF_LHS
+ *     default LHS value is the hesiod configuration file is not present
+ */
+#define DEF_LHS         ".ns"
+
+/*! \def HES_ER_UNINIT
+ *     HES error code: uninitialized
+ */
+#define HES_ER_UNINIT   -1
+
+/*! \def HES_ER_OK
+ *     HES error code: no error
+ */
+#define HES_ER_OK       0
+
+/*! \def HES_ER_NOTFOUND
+ *     HES error code: Hesiod name not found by server
+ */
+#define HES_ER_NOTFOUND 1
+
+/*! \def HES_ER_CONFIG
+ *     HES error code: local problem (no config file?)
+ */
+#define HES_ER_CONFIG   2
+
+/*! \def HES_ER_NET
+ *     HES error code: network problem
+ */
+#define HES_ER_NET      3
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!    \fn LPSTR WINAPI hes_to_bind(LPSTR HesiodName, LPSTR HesiodNameType)
+ *     hes_to_bind function use the LHS and RHS values and
+ *     binds them with the parameters so that a well formed DNS query may
+ *     be performed.
+ *
+ *     defined in hesiod.c
+ *
+ *     \param[in]      HesiodName              The Hesiod name such as a username or service name
+ *     \param[in]      HesiodNameType  The Hesiod name type such as pobox, passwd, or sloc
+ *     \retval         Returns NULL if there was an error. Otherwise the pointer to a string containing a valid query is returned.
+ *
+ */
+LPSTR WINAPI
+hes_to_bind(
+    LPSTR HesiodName,
+    LPSTR HesiodNameType
+    );
+
+
+/*!    \fn LPSTR * WINAPI hes_resolve(LPSTR HesiodName, LPSTR HesiodNameType)
+ *     This function calls hes_to_bind to form a valid hesiod query, then queries the dns database.
+ *
+ *     defined in hesiod.c
+ *
+ *     \param[in]      HesiodName              The Hesiod name such as a username or service name
+ *     \param[in]      HesiodNameType  The Hesiod name type such as pobox, passwd, or sloc
+ *     \retval         returns a NULL terminated vector of strings (a la argv),
+ *                             one for each resource record containing Hesiod data, or NULL if
+ *                             there is any error. If there is an error call hes_error() to get
+ *                             further information. You will need to call hes_free to free the result
+ *
+ */
+
+LPSTR * WINAPI
+hes_resolve(
+    LPSTR HesiodName,
+    LPSTR HesiodNameType
+    );
+
+/*! \fn  int WINAPI hes_error(void)
+ *     The  function  hes_error may be called to determine the
+ *     source of the error.  It does not take an argument.
+ *
+ *     defined in hesiod.c
+ *
+ *     \retval         return one of the HES_ER_* codes defined in hesiod.h.
+ */
+
+int WINAPI
+hes_error(
+    void
+    );
+
+
+/*! \fn void WINAPI hes_free(LPSTR* hesinfo)
+ * The function hes_free should be called to free up memeory returned by hes_resolve
+ *
+ * defined in hesiod.c
+ *
+ * \param[in]  hesinfo         a NULL terminiated array of strings returned by hes_resolve
+ */
+void WINAPI
+hes_free(
+    LPSTR* hesinfo
+    );
+
+
+/*! \struct hes_postoffice
+ * For use in getting post-office information.
+ */
+struct hes_postoffice {
+       /*! The post office type, e.g. POP, IMAP */
+    LPSTR   po_type;
+       /*! The post office host, e.g. PO10.MIT.EDU */
+    LPSTR   po_host;
+       /*! The account name on the post office, e.g. tom */
+    LPSTR   po_name;
+};
+
+/*! \fn struct hes_postoffice  * WINAPI hes_getmailhost(LPSTR user)
+ * This call is used to obtain a user's type of mail account and the location of that
+ *     account. E.g. POP PO10.MIT.EDU or IMAP IMAP-TEST.MIT.EDU
+ *
+ *     defined in hesmailh.c
+ *
+ *     \param[in]      user    The username to be used when querying for the Hesiod Name Type POBOX.
+ *     \retval                         NULL if there was an error or if there was no entry for the
+ *                                             username. Otherwise a pointer to a hes_postoffice structure is
+ *                                             returned. The caller must never attempt to modify this structure or to free
+ *                                             any of its components. Furthermore, only one copy of this structure is allocated per call per thread, so the application should copy any information it needs before
+ *                                             issuing another getmailhost call
+ */
+struct hes_postoffice  * WINAPI hes_getmailhost(LPSTR user);
+
+/*!    \fn struct servent  * WINAPI hes_getservbyname(LPSTR name, LPSTR proto)
+ *     This function will query a Hesiod server for a servent structure given
+ *     a service name and protocol. This is a replacement for the Winsock
+ *     getservbyname function which normally just uses a local services
+ *     file. This allows a site to use a centralized database for adding new
+ *     services.
+ *
+ *     defined in hesservb.c
+ *
+ *     \param[in]      name    pointer to the official name of the service, eg "POP3".
+ *     \param[in]      proto   pointer to the protocol to use when contacting the service, e.g. "TCP"
+ *     \retval                         NULL if there was an error or a pointer to a servent structure. The caller must
+ *                                             never attempt to modify this structure or to free any of its components.
+ *                                             Furthermore, only one copy of this structure is allocated per call per thread, so the application should copy any information it needs before
+ *                                             issuing another hes_getservbyname call
+ *
+ */
+struct servent  * WINAPI hes_getservbyname(LPSTR name,
+                                              LPSTR proto);
+
+/*! \fn struct passwd  * WINAPI hes_getpwnam(LPSTR nam)
+ *     Given a username this function will return the pwd information, eg
+ *     username, uid, gid, fullname, office location, phone number, home
+ *     directory, and default shell
+ *
+ *     defined in hespwnam.c
+ *
+ *     \param  nam                     a pointer to the username
+ *     \retval                         NULL if there was an error or a pointer to the passwd structure. The caller must
+ *                                             never attempt to modify this structure or to free any of its components.
+ *                                             Furthermore, only one copy of this structure is allocated per call per thread, so the application should copy any information it needs before
+ *                                             issuing another hes_getpwnam call
+ *
+ */
+struct passwd  * WINAPI hes_getpwnam(LPSTR nam);
+
+/*!  struct passwd  * WINAPI hes_getpwuid(int uid)
+ *     Given a UID this function will return the pwd information, eg username, uid,
+ *     gid, fullname, office location, phone number, home directory, and default shell
+ *
+ *     defined in hespwnam.c
+ *
+ *     \param  uid                     The user ID
+ *     \retval                         NULL if there was an error or a pointer to the passwd structure. The caller must
+ *                                             never attempt to modify this structure or to free any of its components.
+ *                                             Furthermore, only one copy of this structure is allocated per call per thread, so the application should copy any information it needs before
+ *                                             issuing another hes_getpwuid call
+ */
+struct passwd  * WINAPI hes_getpwuid(int uid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HESIOD_ */
diff --git a/src/include/mitwhich.h b/src/include/mitwhich.h
new file mode 100644 (file)
index 0000000..47ee5da
--- /dev/null
@@ -0,0 +1,84 @@
+/*! \file mitwhich.h
+ *     some defines so that we can figure out which MS OS and subsystem an
+ *     application is running under. Also support for finding out which
+ *     TCP/IP stack is being used. This is useful when you need to find out
+ *     about the domain or the nameservers.
+ */
+
+#if !defined( __MIT_WHICH_H )
+#define __MIT_WHICH_H
+
+// these should become resources and loaded at run time
+#define NT_32 "Winsock 2.0"
+#define NT_16 "Windows NT 16-bit Windows Sockets"
+#define W95_32 "Microsoft Windows Sockets Version 1.1."
+#define W95_16 "Microsoft Windows Sockets Version 1.1."
+#define LWP_16 "Novell Winsock version 1.1"
+// Note that these are currently in wshelper.h and should be somewhere else
+#define MS_NT_32 1
+#define MS_NT_16 2
+#define MS_95_32 3
+#define MS_95_16 4
+#define NOVELL_LWP_16 5
+
+#define MS_OS_WIN 1
+#define MS_OS_95 2
+#define MS_OS_NT 4
+#define MS_OS_2000 12
+#define MS_OS_XP 28
+#define MS_OS_2003 60
+#define MS_OS_NT_UNKNOWN 124
+#define MS_OS_UNKNOWN 0
+
+#define STACK_UNKNOWN 0
+#define UNKNOWN_16_UNDER_32 -2
+#define UNKNOWN_16_UNDER_16 -3
+#define UNKNOWN_32_UNDER_32 -4
+#define UNKNOWN_32_UNDER_16 -5
+
+
+/*
+   @comm these are the current MIT DNS servers, the wshelper and
+   wshelp32 DLLs will do their best to find the correct DNS servers
+   for the local machine however, if all else fails these will be used
+   as a last resort. Site administrators outside of the MIT domain
+   should change these defaults to their own defaults either by
+   editing this file and recompiling or by editing the string tables
+   of the binaries. Don't use App Studio to edit the .RC files.
+\n
+       #define DNS1    "18.70.0.160" \n
+       #define DNS2    "18.71.0.151" \n
+       #define DNS3    "18.72.0.3"   \n
+\n
+       #define DEFAULT_DOMAIN "mit.edu" \n
+*/
+
+#define DNS1   "18.70.0.160"
+#define DNS2   "18.71.0.151"
+#define DNS3   "18.72.0.3"
+
+#define DEFAULT_DOMAIN "mit.edu"
+
+
+#ifndef _PATH_RESCONF
+#if !defined(WINDOWS) && !defined(_WINDOWS) && !defined(_WIN32)
+#define _PATH_RESCONF  "/etc/resolv.conf"
+#else
+#define _PATH_RESCONF  "c:/net/tcp/resolv.cfg"
+#endif
+#endif
+
+
+/* Microsoft TCP/IP registry values that we care about */
+#define NT_TCP_PATH    "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
+#define NT_TCP_PATH_TRANS "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Transient"
+#define W95_TCP_PATH   "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP"
+
+#define NT_DOMAIN_KEY  "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Domain"
+#define NT_NS_KEY      "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\NameServer"
+
+#define W95_DOMAIN_KEY "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP\\Domain"
+#define W95_NS_KEY     "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP\\NameServer"
+
+
+#endif // __MIT_WHICH_H
diff --git a/src/include/resolv.h b/src/include/resolv.h
new file mode 100644 (file)
index 0000000..9297959
--- /dev/null
@@ -0,0 +1,284 @@
+/*! \file resolv.h
+ *  WSHelper DNS/Hesiod Library header
+ *     This file contains the function declaration for:\n
+ *     res_init()              \n
+ *     res_search()    \n
+ *  dn_comp()          \n
+ *     rdn_expand()    \n \n
+ *     and unsupported functions: \n
+ *     res_setopts()           \n
+ *     res_getopts()           \n
+ *     res_querydomain()       \n
+ *     res_mkquery()           \n
+ *     res_send()                      \n
+*/
+
+#ifndef _RESOLV_H_
+#define _RESOLV_H_
+
+#include <windows.h>
+#ifndef MAXDNAME
+#include <arpa/nameser.h>
+#endif
+
+/*! \def MAXNS
+ *     max # name servers we'll track
+ */
+#define MAXNS                   3
+
+/*! \def MAXDFLSRCH
+ *     # default domain levels to try
+ */
+#define MAXDFLSRCH              3
+
+/*!    \def MAXDNSRCH
+ *     max # domains in search path
+ */
+#define MAXDNSRCH               6
+
+/*! \def LOCALDOMAINPARTS
+ *     min levels in name that is "local"
+ */
+#define LOCALDOMAINPARTS        2
+
+/*! \def RES_TIMEOUT
+ *     min. seconds between retries
+ */
+#define RES_TIMEOUT             5
+
+/*! \def MAXMXRECS
+ *     number of records in the preference array in the MX record
+ */
+#define MAXMXRECS               8
+
+/*! \struct mxent
+ *     structure to hold the MX record
+ */
+struct mxent {
+       /*! number of records in the preference field */
+    int numrecs;
+       /*! holds a 16 bit integer which specifies the preference given to this RR */
+    u_short pref[MAXMXRECS];
+       /*! a host willing to act as a mail exchange */
+    char ** hostname;
+};
+
+
+/*! \struct state
+ * This structure holds the state for the resolver query
+ */
+struct state {
+       /*! retransmition time interval */
+    int     retrans;
+       /*! number of times to retransmit */
+    int     retry;
+       /*! field option flags - see below. */
+    long    options;
+        /*! field number of name servers */
+    int     nscount;
+       /*! address of name server */
+    struct  sockaddr_in nsaddr_list[MAXNS];
+#define nsaddr  nsaddr_list[0]
+       /*! current packet id */
+    u_short id;
+       /*! field default domain */
+    char    defdname[MAXDNAME];
+       /*! field components of domain to search */
+    char    *dnsrch[MAXDNSRCH+1];
+};
+
+/*! \def RES_INIT
+ *     resolver option: address initialized
+ */
+#define RES_INIT        0x0001
+
+/*! \def RES_DEBUG
+ *     resolver option: print debug messages
+ */
+#define RES_DEBUG       0x0002
+
+/*! \def RES_AAONLY
+ *     resolver option: authoritative answers only
+ */
+#define RES_AAONLY      0x0004
+
+/*! \def RES_USEVC
+ *     resolver option: use virtual circuit
+ */
+#define RES_USEVC       0x0008
+
+/*! \def RES_PRIMARY
+ *     resolver option: query primary server only
+ */
+#define RES_PRIMARY     0x0010
+
+/*! \def RES_IGNTC
+ *     resolver option: ignore trucation errors
+ */
+#define RES_IGNTC       0x0020
+
+/*! \def RES_RECURSE
+ *     resolver option: recursion desired
+ */
+#define RES_RECURSE     0x0040
+
+/*! \def RES_DEFNAMES
+ *     resolver option: use default domain name
+ */
+#define RES_DEFNAMES    0x0080
+
+/*! \def RES_STAYOPEN
+ *     resolver option: Keep TCP socket ope
+ */
+#define RES_STAYOPEN    0x0100
+
+/*! \def RES_DNSRCH
+ *     resolver option: search up local domain tree
+ */
+#define RES_DNSRCH      0x0200
+
+/*! \def RES_DEFAULT
+ *     resolver option: Default RES options (RES_RECURSE + RES_DEFNAMES + RES_DNSRCH)
+ */
+#define RES_DEFAULT     (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
+
+extern struct state _res;
+
+#include <stdio.h>
+
+/* Private routines shared between libc/net, named, nslookup and others. */
+#define fp_query        __fp_query
+#define hostalias       __hostalias
+#define putlong         __putlong
+#define putshort        __putshort
+#define p_class         __p_class
+#define p_time          __p_time
+#define p_type          __p_type
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \fn int WINAPI res_init()
+ *     \brief retrieves the default domain name and search order. It will look to see if an environment variable LOCALDOMAIN is defined. Otherwise,
+ *     the domain associated with the local host is used. Otherwise, it will try to find the domain name from the registry
+ *
+ *  defined in res_init.c
+ *
+ *     \retval         The return value is 0 if the operation was successful.  Otherwise the value -1 is returned.
+ */
+int  WINAPI res_init();
+
+
+/*! \fn        int WINAPI res_search(const char* name, int qclass, int type, u_char* answer, int anslen)
+ *     \brief a generic query interface to the DNS name space. The query is performed with the dnsapi and
+ *     the answer buffer is populated based on the returned RR set.
+ *
+ *     defined in res_quer.c
+
+ *     \param[in]      name    domain name
+ *     \param[in]      qclass  class of query(such as DNS_CLASS_INTERNET, DNS_CLASS_CSNET, DNS_CLASS_CHAOS,
+ *                                             DNS_CLASS_HESIOD. Defined in windns.h)
+ *     \param[in]      type    type of query(such as DNS_TYPE_A, DNS_TYPE_NS, DNS_TYPE_MX, DNS_TYPE_SRV. Defined in
+ *                                             windns.h)
+ *     \param[in]      answer  buffer to put answer in
+ *     \param[in]      anslen  size of the answer buffer. compare the anslen with the return value, if the return
+ *                                             value is bigger than anslen, it means the answer buffer doesn't contain the complete
+ *                                             response. You will need to call this function again with a bigger answer buffer if
+ *                                             you care about the complete response
+ *
+ *     \retval         return the size of the response on success, -1 on error
+ *
+ */
+int  WINAPI res_search(const char  *name,
+                                       int qclass, int type,
+                                       u_char  *answer, int anslen);
+
+/*! \fn        int WINAPI dn_comp(const u_char* exp_dn, u_char* comp_dn, int length, u_char** dnptrs, u_char** lastdnptr)
+ *     \brief Compress domain name 'exp_dn' into 'comp_dn'
+ *
+ *     defined in res_comp.c
+ *
+ *     \param[in]      exp_dn  name to compress
+ *     \param[in, out] comp_dn         result of the compression
+ *     \param[in]      length                  the size of the array pointed to by 'comp_dn'.
+ *     \param[in, out] dnptrs          a list of pointers to previous compressed names. dnptrs[0]
+ *                                                             is a pointer to the beginning of the message. The list ends with NULL.
+ *     \param[in]      lastdnptr               a pointer to the end of the arrary pointed to by 'dnptrs'. Side effect
+ *                                                             is to update the list of pointers for labels inserted into the
+ *                                                             message as we compress the name. If 'dnptr' is NULL, we don't try to
+ *                                                             compress names. If 'lastdnptr' is NULL, we don't update the list.
+ *     \retval                                         Return the size of the compressed name or -1
+ */
+int  WINAPI dn_comp(const u_char *exp_dn,
+                                    u_char  *comp_dn,
+                                    int length, u_char  **dnptrs,
+                                    u_char  * *lastdnptr);
+
+/*! \fn int WINAPI rdn_expand(const u_char  *msg, const u_char  *eomorig, const u_char  *comp_dn, u_char  *exp_dn,
+                              int length);
+ *     \brief  replacement for dn_expand called rdn_expand. Older versions of the DLL used to this as dn_expand
+ *                     but this has caused some conflict with more recent versions of the MSDEV libraries. rdn_expand()
+ *                     expands the compressed domain name comp_dn to a full domain name.  Expanded names are converted to upper case.
+ *
+ *     defined in res_comp.c
+ *
+ *     \param[in]              msg                     msg is a pointer to the  beginning  of  the  message
+ *     \param[in]              eomorig
+ *     \param[in]              comp_dn         the compressed domain name.
+ *     \param[in, out] exp_dn          a pointer to the result buffer
+ *     \param[in]              length          size of the result in expn_dn
+ *     \retval                                         the size of compressed name is returned or -1 if there was an error.
+*/
+int  WINAPI rdn_expand(const u_char  *msg,
+                                      const u_char  *eomorig,
+                                      const u_char  *comp_dn,
+                                      u_char  *exp_dn,
+                                      int length);
+/* Microsoft includes an implementation of dn_expand() in winsock */
+/* Make sure we do not use it.  jaltman@columbia.edu              */
+#define dn_expand(a,b,c,d,e) rdn_expand(a,b,c,d,e)
+
+
+/*! \fn void WINAPI res_setopts(long opts)
+ *             unsupported
+*/
+void WINAPI res_setopts(long opts);
+
+/*! \fn long WINAPI res_getopts(void)
+ *             unsupported
+*/
+long WINAPI res_getopts(void);
+
+/*! \fn int  WINAPI res_mkquery(int op, const char *dname, int qclass, int type, const char  *data, int datalen,
+ *                                     const struct rrec  *newrr, char  *buf, int buflen)
+ *             unsupported
+ */
+int  WINAPI res_mkquery(int op, const char *dname,
+                                        int qclass, int type,
+                                        const char  *data, int datalen,
+                                        const struct rrec  *newrr,
+                                        char  *buf, int buflen);
+
+/*! \fn int  WINAPI res_send(const char  *msg, int msglen, char  *answer, int anslen)
+ *             unsupported
+*/
+int  WINAPI res_send(const char  *msg, int msglen,
+                                     char  *answer, int anslen);
+
+/*! \fn int  WINAPI res_querydomain(const char  *name, const char  *domain, int qclass, int type,
+                                                                       u_char  *answer, int anslen);
+*              unsupported
+*/
+int  WINAPI res_querydomain(const char  *name,
+                                            const char  *domain,
+                                            int qclass, int type,
+                                                                                       u_char  *answer, int anslen);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_RESOLV_H_ */
diff --git a/src/include/wshelper.h b/src/include/wshelper.h
new file mode 100644 (file)
index 0000000..1bd31f0
--- /dev/null
@@ -0,0 +1,148 @@
+/*! \file wshelper.h
+ * WSHelper DNS/Hesiod Library
+ *
+ * This file contains the function declaration for:    \n
+ *     rgethostbyname()        \n
+ *     rgethostbyaddr()        \n
+ *  rgetservbyname()   \n
+ *  inet_aton()                        \n
+ *     wsh_gethostname()       \n
+ *     wsh_getdomainname()     \n \n
+ *  and unsupported functions: \n
+ *     gethinfobyname()        \n
+ *     getmxbyname()           \n
+ *     getrecordbyname()       \n
+ *     rrhost()                        \n
+ */
+
+#ifndef _WSHELPER_
+#define _WSHELPER_
+
+#include <winsock.h>
+#include <mitwhich.h>
+#include <resolv.h>
+#include <hesiod.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*!  \fn struct hostent * WINAPI rgethostbyname(char  *name)
+ *     retrieves host information corresponding to a host name in the DNS database
+ *
+ *     defined in gethna.c
+ *
+ *     \param[in]      name    Pointer to the null-terminated name of the host to resolve. It can be a fully qualified host name such as x.mit.edu
+ *                                             or it can be a simple host name such as x. If it is a simple host name, the default domain name is
+ *                                             appended to do the search.
+ *     \retval         a pointer to the structure hostent. a structure allocated by the library. The hostent structure contains
+ *                             the results of a successful search for the host specified in the name parameter. The caller must never
+ *                             attempt to modify this structure or to free any of its components. Furthermore, only one copy of this
+ *                             structure is allocated per call per thread, so the application should copy any information it needs before
+ *                             issuing another rgethostbyname.
+ *                             NULL if the search has failed
+ *
+*/
+struct hostent * WINAPI rgethostbyname(char  *name);
+
+/*! \fn struct hostent * WINAPI rgethostbyaddr(char  *addr, int len, int type)
+ *     retrieves the host information corresponding to a network address in the DNS database
+ *
+ *     defined in gethna.c
+ *
+ *     \param[in]      addr    Pointer to an address in network byte order
+ *     \param[in]      len             Length of the address, in bytes
+ *     \param[in]  type        Type of the address, such as the AF_INET address family type (defined as TCP,
+ *                                             UDP, and other associated Internet protocols). Address family types and their corresponding
+ *                                             values are defined in the Winsock2.h header file.
+ *     \retval         returns a pointer to the hostent structure that contains the name and address corresponding
+ *                             to the given network address. The structure is allocated by the library.  The caller must never
+ *                             attempt to modify this structure or to free any of its components. Furthermore, only one copy of this
+ *                             structure is allocated per call per thread, so the application should copy any information it needs before
+ *                             issuing another rgethostbyaddr.
+ *                             NULL if the search has failed
+ *
+*/
+struct hostent * WINAPI rgethostbyaddr(char  *addr, int len, int type);
+
+/*! \fn        struct servent * WINAPI rgetservbyname(LPSTR name, LPSTR proto)
+ *     retrieves service information corresponding to a service name and protocol.
+ *
+ *     defined in gethna.c
+ *
+ *     \param[in]      name    Pointer to a null-terminated service name.
+ *     \param[in]  proto       pointer to a null-terminated protocol name. getservbyname should match both
+ *                                             the name and the proto.
+ *     \retval         a pointer to the servent structure containing the name(s) and service number that match the name and proto
+ *                             parameters. The structure is allocated by the library.  The caller must never
+ *                             attempt to modify this structure or to free any of its components. Furthermore, only one copy of this
+ *                             structure is allocated per call per thread, so the application should copy any information it needs before
+ *                             issuing another rgetservbyname.
+ *                             NULL if the search has failed
+ *
+ */
+struct servent * WINAPI rgetservbyname(LPSTR name, LPSTR proto);
+
+/*! \fn LPSTR WINAPI gethinfobyname(LPSTR name)
+ *     unsupported
+ */
+LPSTR WINAPI gethinfobyname(LPSTR name);
+
+/*! \fn LPSTR WINAPI getmxbyname(LPSTR name)
+ *     unsupported
+ */
+LPSTR WINAPI getmxbyname(LPSTR name);
+
+/*! \fn LPSTR WINAPI getrecordbyname(LPSTR name, int rectype)
+ *     unsupported
+ */
+LPSTR WINAPI getrecordbyname(LPSTR name, int rectype);
+
+/*! \fn  DWORD WINAPI rrhost( LPSTR lpHost )
+ *     unsupported
+ */
+DWORD WINAPI rrhost( LPSTR lpHost );
+
+/*! \fn  unsigned long WINAPI inet_aton(register const char *cp, struct in_addr *addr)
+ *     converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the in_addr structure
+ *
+ *     defined in inetaton.c
+ *
+ *     \param[in]              cp              Null-terminated character string representing a number expressed in the
+ *                                                     Internet standard ".'' (dotted) notation.
+ *     \param[in, out] addr    pointer to the in_addr structure. The s_addr memeber will be populated
+ *     \retval Returns 1 if the address is valid, 0 if not.
+ */
+unsigned long WINAPI inet_aton(register const char *cp, struct in_addr *addr);
+
+
+/*! \fn int WINAPI wsh_gethostname(char* name, int size)
+ *     Gets the base part of the hostname
+ *
+ *     defined in res_init.c
+ *
+ *     \param[in, out] name    pointer to a buffer that receives a null-terminated string containing the computer name
+ *     \param[in]              size    specifies the size of the buffer, in chars (must be large
+ *                                                     enough to hold NULL-terminated host name)
+ *     \retval                 return 0 ifsuccess,  -1 on error.
+*/
+int WINAPI wsh_gethostname(char* name, int size);
+
+/*!    \fn int WINAPI wsh_getdomainname(char* name, int size)
+ *     Gets the machine's domain name
+ *
+ *     defined in res_init.c
+ *
+ *     \param[in, out] name    pointer to a buffer that receives a null-terminated string containing the domain name
+ *     \param[in]              size    specifies the size of the buffer, in chars (must be large
+ *                                                     enough to hold NULL-terminated domain name)
+ *
+ *     \retval                 return 0 ifsuccess,  -1 on error.
+ */
+int WINAPI wsh_getdomainname(char* name, int size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _WSHELPER_ */
diff --git a/src/windows/leashdll/AFSroutines.c b/src/windows/leashdll/AFSroutines.c
new file mode 100644 (file)
index 0000000..a67b164
--- /dev/null
@@ -0,0 +1,852 @@
+//* Module name: AFSroutines.c
+
+#include <windows.h>
+#include <stdio.h>
+#include <time.h>
+
+/* Private Include files */
+#include <conf.h>
+#include <leasherr.h>
+#include <krb.h>
+#include "leashdll.h"
+#include <leashwin.h>
+
+#ifndef NO_AFS
+#include "afscompat.h"
+#endif
+#include "leash-int.h"
+
+#define MAXCELLCHARS   64
+#define MAXHOSTCHARS   64
+#define MAXHOSTSPERCELL 8
+#define TRANSARCAFSDAEMON "TransarcAFSDaemon"
+typedef struct {
+    char name[MAXCELLCHARS];
+    short numServers;
+    short flags;
+    struct sockaddr_in hostAddr[MAXHOSTSPERCELL];
+    char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS];
+    char *linkedCell;
+} afsconf_cell;
+
+DWORD   AfsOnLine = 1;
+extern  DWORD AfsAvailable;
+
+int not_an_API_LeashAFSGetToken(TICKETINFO * ticketinfo, TicketList** ticketList, char * kprinc);
+DWORD GetServiceStatus(LPSTR lpszMachineName, LPSTR lpszServiceName, DWORD *lpdwCurrentState);
+BOOL SetAfsStatus(DWORD AfsStatus);
+BOOL GetAfsStatus(DWORD *AfsStatus);
+void Leash_afs_error(LONG rc, LPCSTR FailedFunctionName);
+
+static char *afs_realm_of_cell(afsconf_cell *);
+static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
+static int get_cellconfig(char *, afsconf_cell *, char *);
+
+/**************************************/
+/* LeashAFSdestroyToken():            */
+/**************************************/
+int
+Leash_afs_unlog(
+    void
+    )
+{
+#ifdef NO_AFS
+    return(0);
+#else
+    long       rc;
+    char    HostName[64];
+    DWORD   CurrentState;
+
+    if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine)
+        return(0);
+
+    CurrentState = 0;
+    memset(HostName, '\0', sizeof(HostName));
+    gethostname(HostName, sizeof(HostName));
+    if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
+        return(0);
+    if (CurrentState != SERVICE_RUNNING)
+        return(0);
+
+    rc = ktc_ForgetAllTokens();
+
+    return(0);
+#endif
+}
+
+
+int
+not_an_API_LeashAFSGetToken(
+    TICKETINFO * ticketinfo,
+    TicketList** ticketList,
+    char * kerberosPrincipal
+    )
+{
+#ifdef NO_AFS
+    return(0);
+#else
+    struct ktc_principal    aserver;
+    struct ktc_principal    aclient;
+    struct ktc_token        atoken;
+    int                     EndMonth;
+    int                     EndDay;
+    int                     cellNum;
+    int                     BreakAtEnd;
+    char                    UserName[64];
+    char                    CellName[64];
+    char                    ServiceName[64];
+    char                    InstanceName[64];
+    char                    EndTime[16];
+    char                    Buffer[256];
+    char                    Months[12][4] = {"Jan\0", "Feb\0", "Mar\0", "Apr\0", "May\0", "Jun\0", "Jul\0", "Aug\0", "Sep\0", "Oct\0", "Nov\0", "Dec\0"};
+    char                    TokenStatus[16];
+    time_t                  CurrentTime;
+    struct tm               *newtime;
+    DWORD                   CurrentState;
+    DWORD                   rc;
+    char                    HostName[64];
+
+
+    TicketList* list = NULL;
+    if ( ticketinfo ) {
+        ticketinfo->btickets = NO_TICKETS;
+        ticketinfo->principal[0] = '\0';
+    }
+    if ( !kerberosPrincipal )
+        kerberosPrincipal = "";
+
+    if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine)
+        return(0);
+
+    CurrentState = 0;
+    memset(HostName, '\0', sizeof(HostName));
+    gethostname(HostName, sizeof(HostName));
+    if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
+        return(0);
+    if (CurrentState != SERVICE_RUNNING)
+        return(0);
+
+    BreakAtEnd = 0;
+    cellNum = 0;
+    while (1)
+    {
+        if (rc = ktc_ListTokens(cellNum, &cellNum, &aserver))
+        {
+            if (rc != KTC_NOENT)
+                return(0);
+
+            if (BreakAtEnd == 1)
+                break;
+        }
+        BreakAtEnd = 1;
+        memset(&atoken, '\0', sizeof(atoken));
+        if (rc = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient))
+        {
+            if (rc == KTC_ERROR)
+                return(0);
+
+            continue;
+        }
+
+        if (!list)
+        {
+            list = (TicketList*) calloc(1, sizeof(TicketList));
+            (*ticketList) = list;
+        }
+        else
+        {
+            list->next = (struct TicketList*) calloc(1, sizeof(TicketList));
+            list = (TicketList*) list->next;
+        }
+
+        CurrentTime = time(NULL);
+
+        newtime = localtime(&atoken.endTime);
+
+        memset(UserName, '\0', sizeof(UserName));
+        strcpy(UserName, aclient.name);
+
+        memset(CellName, '\0', sizeof(CellName));
+        strcpy(CellName, aclient.cell);
+
+        memset(InstanceName, '\0', sizeof(InstanceName));
+        strcpy(InstanceName, aclient.instance);
+
+        memset(ServiceName, '\0', sizeof(ServiceName));
+        strcpy(ServiceName, aserver.name);
+
+        memset(TokenStatus, '\0', sizeof(TokenStatus));
+
+        EndDay = newtime->tm_mday;
+
+        EndMonth = newtime->tm_mon + 1;;
+
+        sprintf(EndTime, "%02d:%02d:%02d", newtime->tm_hour, newtime->tm_min, newtime->tm_sec);
+
+        sprintf(Buffer,"                          %s %02d %s      %s%s%s@%s  %s",
+                Months[EndMonth - 1], EndDay, EndTime,
+                UserName,
+                InstanceName[0] ? "." : "",
+                InstanceName,
+                CellName,
+                TokenStatus);
+
+        list->theTicket = (char*) calloc(1, sizeof(Buffer));
+        if (!list->theTicket)
+        {
+            MessageBox(NULL, "Memory Error", "Error", MB_OK);
+            return ENOMEM;
+        }
+
+        strcpy(list->theTicket, Buffer);
+        list->name = strdup(aclient.name);
+        list->inst = aclient.instance[0] ? strdup(aclient.instance) : NULL;
+        list->realm = strdup(aclient.cell);
+        list->tktEncType = NULL;
+        list->keyEncType = NULL;
+        list->addrCount = 0;
+        list->addrList = NULL;
+
+        if ( ticketinfo ) {
+            sprintf(Buffer,"%s@%s",UserName,CellName);
+            if (!ticketinfo->principal[0] || !stricmp(Buffer,kerberosPrincipal)) {
+                strcpy(ticketinfo->principal, Buffer);
+                ticketinfo->issue_date = 0;
+                ticketinfo->lifetime = atoken.endTime;
+                ticketinfo->renew_till = 0;
+
+                _tzset();
+                if ( ticketinfo->lifetime - time(0) <= 0L )
+                    ticketinfo->btickets = EXPD_TICKETS;
+                else
+                    ticketinfo->btickets = GOOD_TICKETS;
+            }
+        }
+    }
+    return(0);
+#endif
+}
+
+static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
+
+static int
+use_krb524(void)
+{
+    HKEY parmKey;
+    DWORD code, len;
+    DWORD use524 = 0;
+
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+                         0, KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        len = sizeof(use524);
+        code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+                                (BYTE *) &use524, &len);
+        RegCloseKey(parmKey);
+    }
+    if (code != ERROR_SUCCESS) {
+        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+                             0, KEY_QUERY_VALUE, &parmKey);
+        if (code == ERROR_SUCCESS) {
+            len = sizeof(use524);
+            code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+                                    (BYTE *) &use524, &len);
+            RegCloseKey (parmKey);
+        }
+    }
+    return use524;
+}
+
+
+
+int
+Leash_afs_klog(
+    char *service,
+    char *cell,
+    char *realm,
+    int LifeTime
+    )
+{
+#ifdef NO_AFS
+    return(0);
+#else
+    long       rc;
+    CREDENTIALS        creds;
+    KTEXT_ST   ticket;
+    struct ktc_principal       aserver;
+    struct ktc_principal       aclient;
+    char       realm_of_user[REALM_SZ]; /* Kerberos realm of user */
+    char       realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
+    char       local_cell[MAXCELLCHARS+1];
+    char       Dmycell[MAXCELLCHARS+1];
+    struct ktc_token   atoken;
+    struct ktc_token   btoken;
+    afsconf_cell       ak_cellconfig; /* General information about the cell */
+    char       RealmName[128];
+    char       CellName[128];
+    char       ServiceName[128];
+    DWORD       CurrentState;
+    char        HostName[64];
+    BOOL        try_krb5 = 0;
+    int         retry = 0;
+    int         len;
+#ifndef NO_KRB5
+    krb5_context  context = 0;
+    krb5_ccache  _krb425_ccache = 0;
+    krb5_creds increds;
+    krb5_creds * k5creds = 0;
+    krb5_error_code r;
+    krb5_principal client_principal = 0;
+    krb5_flags         flags = 0;
+#endif /* NO_KRB5 */
+
+    if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine)
+        return(0);
+
+    if ( !realm ) realm = "";
+    if ( !cell )  cell = "";
+    if ( !service ) service = "";
+
+    CurrentState = 0;
+    memset(HostName, '\0', sizeof(HostName));
+    gethostname(HostName, sizeof(HostName));
+    if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
+        return(0);
+    if (CurrentState != SERVICE_RUNNING)
+        return(0);
+
+    memset(RealmName, '\0', sizeof(RealmName));
+    memset(CellName, '\0', sizeof(CellName));
+    memset(ServiceName, '\0', sizeof(ServiceName));
+    memset(realm_of_user, '\0', sizeof(realm_of_user));
+    memset(realm_of_cell, '\0', sizeof(realm_of_cell));
+    memset(Dmycell, '\0', sizeof(Dmycell));
+
+    // NULL or empty cell returns information on local cell
+    if (cell && cell[0])
+        strcpy(Dmycell, cell);
+    rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell);
+    if (rc && cell && cell[0]) {
+        memset(Dmycell, '\0', sizeof(Dmycell));
+        rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell);
+    }
+    if (rc)
+        return(rc);
+
+#ifndef NO_KRB5
+    if (!(r = Leash_krb5_initialize(&context, &_krb425_ccache))) {
+        int i;
+
+        memset((char *)&increds, 0, sizeof(increds));
+
+        (*pkrb5_cc_get_principal)(context, _krb425_ccache, &client_principal);
+        i = krb5_princ_realm(context, client_principal)->length;
+        if (i > REALM_SZ-1)
+            i = REALM_SZ-1;
+        strncpy(realm_of_user,krb5_princ_realm(context, client_principal)->data,i);
+        realm_of_user[i] = 0;
+        try_krb5 = 1;
+    }
+#endif /* NO_KRB5 */
+    if ( !try_krb5 || !realm_of_user[0] ) {
+        if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
+        {
+            return(rc);
+        }
+    }
+    strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));
+
+    if (strlen(service) == 0)
+        strcpy(ServiceName, "afs");
+    else
+        strcpy(ServiceName, service);
+
+    if (strlen(cell) == 0)
+        strcpy(CellName, local_cell);
+    else
+        strcpy(CellName, cell);
+
+    if (strlen(realm) == 0)
+        strcpy(RealmName, realm_of_cell);
+    else
+        strcpy(RealmName, realm);
+
+    memset(&creds, '\0', sizeof(creds));
+
+#ifndef NO_KRB5
+    if ( try_krb5 ) {
+        /* First try Service/Cell@REALM */
+        if (r = (*pkrb5_build_principal)(context, &increds.server,
+                                      strlen(RealmName),
+                                      RealmName,
+                                      ServiceName,
+                                      CellName,
+                                      0))
+        {
+            try_krb5 = 0;
+            goto use_krb4;
+        }
+
+        increds.client = client_principal;
+        increds.times.endtime = 0;
+        /* Ask for DES since that is what V4 understands */
+        increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+
+#ifdef KRB5_TC_NOTICKET
+        flags = 0;
+        r = pkrb5_cc_set_flags(context, _krb425_ccache, flags);
+#endif
+        if (r == 0)
+            r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds);
+        if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+                       r == KRB5KRB_ERR_GENERIC /* Heimdal */) {
+            /* Next try Service@REALM */
+            pkrb5_free_principal(context, increds.server);
+            r = pkrb5_build_principal(context, &increds.server,
+                                      strlen(RealmName),
+                                      RealmName,
+                                      ServiceName,
+                                      0);
+            if (r == 0)
+                r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds);
+        }
+
+        pkrb5_free_principal(context, increds.server);
+        pkrb5_free_principal(context, client_principal);
+#ifdef KRB5_TC_NOTICKET
+        flags = KRB5_TC_NOTICKET;
+        pkrb5_cc_set_flags(context, _krb425_ccache, flags);
+#endif
+        (void) pkrb5_cc_close(context, _krb425_ccache);
+        _krb425_ccache = 0;
+
+        if (r || k5creds == 0) {
+            pkrb5_free_context(context);
+            try_krb5 = 0;
+            goto use_krb4;
+        }
+
+        /* This code inserts the entire K5 ticket into the token
+         * No need to perform a krb524 translation which is
+         * commented out in the code below
+         */
+        if ( use_krb524() || k5creds->ticket.length > MAXKTCTICKETLEN )
+            goto try_krb524d;
+
+        memset(&aserver, '\0', sizeof(aserver));
+        strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
+        strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
+
+        memset(&atoken, '\0', sizeof(atoken));
+        atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
+        atoken.startTime = k5creds->times.starttime;
+        atoken.endTime = k5creds->times.endtime;
+        memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
+        atoken.ticketLen = k5creds->ticket.length;
+        memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
+
+      retry_gettoken5:
+        rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
+        if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
+            if ( rc == KTC_NOCM && retry < 20 ) {
+                Sleep(500);
+                retry++;
+                goto retry_gettoken5;
+            }
+            goto try_krb524d;
+        }
+
+        if (atoken.kvno == btoken.kvno &&
+             atoken.ticketLen == btoken.ticketLen &&
+             !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
+             !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
+        {
+            /* Success */
+            pkrb5_free_creds(context, k5creds);
+            pkrb5_free_context(context);
+            return(0);
+        }
+
+        // * Reset the "aclient" structure before we call ktc_SetToken.
+        // * This structure was first set by the ktc_GetToken call when
+        // * we were comparing whether identical tokens already existed.
+
+        len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
+        strncpy(aclient.name, k5creds->client->data[0].data, len);
+        aclient.name[len] = '\0';
+
+        if ( k5creds->client->length > 1 ) {
+            char * p;
+            strcat(aclient.name, ".");
+            p = aclient.name + strlen(aclient.name);
+            len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
+            strncpy(p, k5creds->client->data[1].data, len);
+            p[len] = '\0';
+        }
+        aclient.instance[0] = '\0';
+
+        strcpy(aclient.cell, realm_of_cell);
+
+        len = min(k5creds->client->realm.length,strlen(realm_of_cell));
+        if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
+            char * p;
+            strcat(aclient.name, "@");
+            p = aclient.name + strlen(aclient.name);
+            len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
+            strncpy(p, k5creds->client->realm.data, len);
+            p[len] = '\0';
+        }
+
+        rc = ktc_SetToken(&aserver, &atoken, &aclient, 0);
+        if (!rc) {
+            /* Success */
+            pkrb5_free_creds(context, k5creds);
+            pkrb5_free_context(context);
+            return(0);
+        }
+
+      try_krb524d:
+        /* This requires krb524d to be running with the KDC */
+        r = pkrb524_convert_creds_kdc(context, k5creds, &creds);
+        pkrb5_free_creds(context, k5creds);
+               pkrb5_free_context(context);
+        if (r) {
+            try_krb5 = 0;
+            goto use_krb4;
+        }
+        rc = KSUCCESS;
+    } else
+#endif /* NO_KRB5 */
+    {
+      use_krb4:
+        rc = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
+               if (rc == NO_TKT_FIL) {
+                       // if the problem is that we have no krb4 tickets
+                       // do not attempt to continue
+            return(rc);
+               }
+        if (rc != KSUCCESS)
+            rc = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
+    }
+    if (rc != KSUCCESS)
+    {
+        if ((rc = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
+        {
+            if ((rc = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
+            {
+                return(rc);
+            }
+        }
+        else if ((rc = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
+        {
+            if ((rc = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
+            {
+                return(rc);
+            }
+        }
+        else
+        {
+            return(rc);
+        }
+    }
+
+       memset(&aserver, '\0', sizeof(aserver));
+    strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
+    strncpy(aserver.cell, CellName, MAXKTCNAMELEN - 1);
+
+    memset(&atoken, '\0', sizeof(atoken));
+    atoken.kvno = creds.kvno;
+    atoken.startTime = creds.issue_date;
+    atoken.endTime = (*pkrb_life_to_time)(creds.issue_date,creds.lifetime);
+    memcpy(&atoken.sessionKey, creds.session, 8);
+    atoken.ticketLen = creds.ticket_st.length;
+    memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
+
+    if (!(rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient)) &&
+        atoken.kvno == btoken.kvno &&
+        atoken.ticketLen == btoken.ticketLen &&
+        !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
+        !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
+    {
+        return(0);
+    }
+
+    // * Reset the "aclient" structure before we call ktc_SetToken.
+    // * This structure was first set by the ktc_GetToken call when
+    // * we were comparing whether identical tokens already existed.
+
+    strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
+    aclient.name[MAXKTCNAMELEN - 1] = '\0';
+    if (creds.pinst[0])
+    {
+        strncat(aclient.name, ".", MAXKTCNAMELEN - 1 - strlen(aclient.name));
+        aclient.name[MAXKTCNAMELEN - 1] = '\0';
+        strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1 - strlen(aclient.name));
+        aclient.name[MAXKTCNAMELEN - 1] = '\0';
+    }
+    strcpy(aclient.instance, "");
+
+    if ( strcmp(realm_of_cell, creds.realm) )
+    {
+        strncat(aclient.name, "@", MAXKTCNAMELEN - 1 - strlen(aclient.name));
+        aclient.name[MAXKTCNAMELEN - 1] = '\0';
+        strncat(aclient.name, creds.realm, MAXKTCNAMELEN - 1 - strlen(aclient.name));
+        aclient.name[MAXKTCNAMELEN - 1] = '\0';
+    }
+    aclient.name[MAXKTCNAMELEN-1] = '\0';
+
+    strcpy(aclient.cell, CellName);
+
+    // * NOTE: On WIN32, the order of SetToken params changed...
+    // * to   ktc_SetToken(&aserver, &aclient, &atoken, 0)
+    // * from ktc_SetToken(&aserver, &atoken, &aclient, 0) on Unix...
+    // * The afscompat ktc_SetToken provides the Unix order
+
+    if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0))
+    {
+        Leash_afs_error(rc, "ktc_SetToken()");
+        return(rc);
+    }
+
+    return(0);
+#endif
+}
+
+/**************************************/
+/* afs_realm_of_cell():               */
+/**************************************/
+static char *afs_realm_of_cell(afsconf_cell *cellconfig)
+{
+#ifdef NO_AFS
+    return(0);
+#else
+    char krbhst[MAX_HSTNM]="";
+    static char krbrlm[REALM_SZ+1]="";
+#ifndef NO_KRB5
+    krb5_context  ctx = 0;
+    char ** realmlist=NULL;
+    krb5_error_code r;
+#endif /* NO_KRB5 */
+
+    if (!cellconfig)
+        return 0;
+
+#ifndef NO_KRB5
+    if ( pkrb5_init_context ) {
+        r = pkrb5_init_context(&ctx);
+        if ( !r )
+            r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
+        if ( !r && realmlist && realmlist[0] ) {
+            strcpy(krbrlm, realmlist[0]);
+            pkrb5_free_host_realm(ctx, realmlist);
+        }
+        if (ctx)
+            pkrb5_free_context(ctx);
+    }
+#endif /* NO_KRB5 */
+
+    if ( !krbrlm[0] ) {
+        strcpy(krbrlm, (char *)(*pkrb_realmofhost)(cellconfig->hostName[0]));
+        if ((*pkrb_get_krbhst)(krbhst, krbrlm, 1) != KSUCCESS)
+            krbrlm[0] = '\0';
+    }
+
+    if ( !krbrlm[0] )
+    {
+        char *s = krbrlm;
+        char *t = cellconfig->name;
+        int c;
+
+        while (c = *t++)
+        {
+            if (islower(c)) c=toupper(c);
+            *s++ = c;
+        }
+        *s++ = 0;
+    }
+    return(krbrlm);
+#endif
+}
+
+/**************************************/
+/* get_cellconfig():                  */
+/**************************************/
+static int get_cellconfig(char *cell, afsconf_cell *cellconfig, char *local_cell)
+{
+#ifdef NO_AFS
+    return(0);
+#else
+    int        rc;
+
+    local_cell[0] = (char)0;
+    memset(cellconfig, 0, sizeof(*cellconfig));
+
+    /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
+    if (rc = cm_GetRootCellName(local_cell))
+    {
+        return(rc);
+    }
+
+    if (strlen(cell) == 0)
+        strcpy(cell, local_cell);
+
+    /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
+    strcpy(cellconfig->name, cell);
+
+    return cm_SearchCell(cell, get_cellconfig_callback, NULL, (void*)cellconfig);
+#endif
+}
+
+/**************************************/
+/* get_cellconfig_callback():          */
+/**************************************/
+static long get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
+{
+#ifdef NO_AFS
+    return(0);
+#else
+    afsconf_cell *cc = (afsconf_cell *)cellconfig;
+
+    cc->hostAddr[cc->numServers] = *addrp;
+    strcpy(cc->hostName[cc->numServers], namep);
+    cc->numServers++;
+    return(0);
+#endif
+}
+
+
+/**************************************/
+/* Leash_afs_error():           */
+/**************************************/
+void
+Leash_afs_error(LONG rc, LPCSTR FailedFunctionName)
+{
+#ifdef NO_AFS
+    return;
+#else
+    char message[256];
+    const char *errText;
+
+    // Using AFS defines as error messages for now, until Transarc
+    // gets back to me with "string" translations of each of these
+    // const. defines.
+    if (rc == KTC_ERROR)
+      errText = "KTC_ERROR";
+    else if (rc == KTC_TOOBIG)
+      errText = "KTC_TOOBIG";
+    else if (rc == KTC_INVAL)
+      errText = "KTC_INVAL";
+    else if (rc == KTC_NOENT)
+      errText = "KTC_NOENT";
+    else if (rc == KTC_PIOCTLFAIL)
+      errText = "KTC_PIOCTLFAIL";
+    else if (rc == KTC_NOPIOCTL)
+      errText = "KTC_NOPIOCTL";
+    else if (rc == KTC_NOCELL)
+      errText = "KTC_NOCELL";
+    else if (rc == KTC_NOCM)
+      errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
+    else
+      errText = "Unknown error!";
+
+    sprintf(message, "%s\n(%s failed)", errText, FailedFunctionName);
+    MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
+    return;
+
+#endif
+}
+
+DWORD GetServiceStatus(
+    LPSTR lpszMachineName,
+    LPSTR lpszServiceName,
+    DWORD *lpdwCurrentState)
+{
+#ifdef NO_AFS
+    return(NOERROR);
+#else
+    DWORD           hr               = NOERROR;
+    SC_HANDLE       schSCManager     = NULL;
+    SC_HANDLE       schService       = NULL;
+    DWORD           fdwDesiredAccess = 0;
+    SERVICE_STATUS  ssServiceStatus  = {0};
+    BOOL            fRet             = FALSE;
+
+    if ((pOpenSCManagerA == NULL) ||
+        (pOpenServiceA == NULL) ||
+        (pQueryServiceStatus == NULL) ||
+        (pCloseServiceHandle == NULL))
+        {
+        *lpdwCurrentState = SERVICE_RUNNING;
+        return(NOERROR);
+        }
+
+    *lpdwCurrentState = 0;
+
+    fdwDesiredAccess = GENERIC_READ;
+
+    schSCManager = (*pOpenSCManagerA)(lpszMachineName,
+                                 NULL,
+                                 fdwDesiredAccess);
+
+    if(schSCManager == NULL)
+    {
+        hr = GetLastError();
+        goto cleanup;
+    }
+
+    schService = (*pOpenServiceA)(schSCManager,
+                             lpszServiceName,
+                             fdwDesiredAccess);
+
+    if(schService == NULL)
+    {
+        hr = GetLastError();
+        goto cleanup;
+    }
+
+    fRet = (*pQueryServiceStatus)(schService,
+                              &ssServiceStatus);
+
+    if(fRet == FALSE)
+    {
+        hr = GetLastError();
+        goto cleanup;
+    }
+
+    *lpdwCurrentState = ssServiceStatus.dwCurrentState;
+
+cleanup:
+
+    (*pCloseServiceHandle)(schService);
+    (*pCloseServiceHandle)(schSCManager);
+
+    return(hr);
+#endif
+}
+
+BOOL
+SetAfsStatus(
+    DWORD AfsStatus
+    )
+{
+#ifdef NO_AFS
+    return(TRUE);
+#else
+    return write_registry_setting(LEASH_SETTINGS_REGISTRY_VALUE_AFS_STATUS,
+                                  REG_DWORD, &AfsStatus,
+                                  sizeof(AfsStatus)) ? FALSE : TRUE;
+#endif
+}
+
+BOOL
+GetAfsStatus(
+    DWORD *AfsStatus
+    )
+{
+#ifdef NO_AFS
+    return(TRUE);
+#else
+    return read_registry_setting(LEASH_SETTINGS_REGISTRY_VALUE_AFS_STATUS,
+                                 AfsStatus, sizeof(DWORD)) ? FALSE : TRUE;
+#endif
+}
diff --git a/src/windows/leashdll/include/krb4/conf-pc.h b/src/windows/leashdll/include/krb4/conf-pc.h
new file mode 100644 (file)
index 0000000..65a8779
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: IBM PC 8086
+ */
+
+#if defined(_WIN32) && !defined(WIN32)
+#define WIN32
+#endif
+
+#if ( defined(WIN16) || defined(WIN32) || defined(_WINDOWS)) && !defined(WINDOWS)
+#define WINDOWS
+#endif
+
+#if defined(__OS2__) && !defined(OS2)
+#define OS2
+#endif
+
+#ifdef WIN16
+#define BITS16
+#else
+#ifdef MSDOS
+#define BITS16
+#else
+#define BITS32
+#endif
+#endif
+#define LSBFIRST
+
+#define index(s,c) strchr(s,c)          /* PC version of index */
+#define rindex(s,c) strrchr(s,c)
+#if !defined(OS2) && !defined(LWP) /* utils.h under OS/2 */
+#define bcmp(s1,s2,n) memcmp((s1),(s2),(n))
+#define bcopy(a,b,c) memcpy( (b), (a), (c) )
+#define bzero(a,b) memset( (a), 0, (b) )
+#endif
+
+typedef unsigned char u_char;
+typedef unsigned long u_long;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+#define NO_UIDGID_T
+
+#if !defined(WINDOWS) && !defined(DWORD)
+typedef long DWORD;
+#endif
+
+#if defined(PC)&&!defined(WINDOWS)
+#ifndef LPSTR
+typedef char *LPSTR;
+typedef char *LPBYTE;
+typedef char *CHARPTR;
+typedef char *LPINT;
+typedef unsigned int WORD;
+#endif
+#define LONG long
+#define FAR
+#define PASCAL
+#define EXPORT
+#endif
+
+#ifdef OS2
+#include <utils.h>
+#define lstrcpy strcpy
+#define lstrlen strlen
+#define lstrcmp strcmp
+#define lstrcpyn strncpy
+#endif
+
+#ifdef WIN32
+#define _export
+#endif
+
+#if defined(BITS32)
+#define far
+#define near
+#endif
+
+#ifdef WINDOWS
+#include <windows.h>
+#endif
+
+#ifdef WIN32
+#include <windowsx.h>
+#endif
+
+#ifdef WIN16
+#pragma message ( "WIN16 in " __FILE__ )
+#include <time.h>
+#include <process.h>
+#ifndef KRB_INT32
+#define KRB_INT32 long
+#endif
+#ifndef KRB_UINT32
+#define KRB_UINT32 unsigned KRB_INT32
+#endif
+#endif
+
+
+#define RANDOM_KRB_INT32_1 ((KRB_INT32) time(NULL))
+#define RANDOM_KRB_INT32_2 ((KRB_INT32) getpid())
+#define TIME_GMT_UNIXSEC unix_time_gmt_unixsec((unsigned KRB_INT32 *)0);
+#ifndef MAXPATHLEN
+#define MAXPATHLEN _MAX_PATH
+#endif
diff --git a/src/windows/leashdll/include/krb4/conf.h b/src/windows/leashdll/include/krb4/conf.h
new file mode 100644 (file)
index 0000000..2e2a84c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Configuration info for operating system, hardware description,
+ * language implementation, C library, etc.
+ *
+ * This file should be included in (almost) every file in the Kerberos
+ * sources, and probably should *not* be needed outside of those
+ * sources.  (How do we deal with /usr/include/des.h and
+ * /usr/include/krb.h?)
+ */
+
+#ifndef _CONF_H_
+#define _CONF_H_
+
+#include "osconf.h"
+
+#ifdef SHORTNAMES
+#include "names.h"
+#endif
+
+/*
+ * Language implementation-specific definitions
+ */
+
+/* special cases */
+#ifdef __HIGHC__
+/* broken implementation of ANSI C */
+#undef __STDC__
+#endif
+
+#if !defined(__STDC__) && !defined(PC)
+#define const
+#define volatile
+#define signed
+typedef char *pointer;          /* pointer to generic data */
+#ifndef PROTOTYPE
+#define PROTOTYPE(p) ()
+#endif
+#else
+typedef void *pointer;
+#ifndef PROTOTYPE
+#define PROTOTYPE(p) p
+#endif
+#endif
+
+/* Does your compiler understand "void"? */
+#ifdef notdef
+#define void int
+#endif
+
+/*
+ * A few checks to see that necessary definitions are included.
+ */
+
+#ifndef MSBFIRST
+#ifndef LSBFIRST
+#error byte order not defined
+#endif
+#endif
+
+/* machine size */
+#ifndef BITS16
+#ifndef BITS32
+#error number of bits?
+#endif
+#endif
+
+/* end of checks */
+
+#endif /* _CONF_H_ */
diff --git a/src/windows/leashdll/include/krb4/osconf.h b/src/windows/leashdll/include/krb4/osconf.h
new file mode 100644 (file)
index 0000000..340421e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Athena configuration.
+ */
+
+#ifndef _OSCONF_H_
+#define _OSCONF_H_
+
+#ifndef PC
+#if defined(IBMPC) || defined(__MSDOS__) || defined(OS2) || defined(_MSDOS) || defined(_WIN32)
+#define PC
+#endif
+#endif
+
+#ifdef tahoe
+#include "conf-bsdtahoe.h"
+#else /* !tahoe */
+#ifdef vax
+#include "conf-bsdvax.h"
+#else /* !vax */
+#if defined(mips) && defined(ultrix)
+#include "conf-ultmips2.h"
+#else /* !Ultrix MIPS-2 */
+#ifdef ibm032
+#include "conf-bsdibm032.h"
+#else /* !ibm032 */
+#ifdef apollo
+#include "conf-bsdapollo.h"
+#else /* !apollo */
+#ifdef sun
+#ifdef sparc
+#include "conf-bsdsparc.h"
+#else /* sun but not sparc */
+#ifdef i386
+#include "conf-bsd386i.h"
+#else /* sun but not (sparc or 386i) */
+#include "conf-bsdm68k.h"
+#endif /* i386 */
+#endif /* sparc */
+#else /* !sun */
+#ifdef pyr
+#include "conf-pyr.h"
+#else
+#if defined(PC) || defined(__MSDOS__) || defined(OS2) || defined(_MSDOS) || defined(_WIN32)
+#include "conf-pc.h"
+#endif /* PC */
+#endif /* pyr */
+#endif /* sun */
+#endif /* apollo */
+#endif /* ibm032 */
+#endif /* mips */
+#endif /* vax */
+#endif /* tahoe */
+
+#endif /* _OSCONF_H_ */
diff --git a/src/windows/leashdll/include/leasherr.h b/src/windows/leashdll/include/leasherr.h
new file mode 100644 (file)
index 0000000..834765f
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * leasherr.h
+ * This file is the #include file for leasherr.et.
+ * Please do not edit it as it is automatically generated.
+ */
+
+#define LSH_ONLYONEME                            (40591872L)
+#define LSH_INVPRINCIPAL                         (40591873L)
+#define LSH_FAILEDREALM                          (40591874L)
+#define LSH_INVINSTANCE                          (40591875L)
+#define LSH_INVREALM                             (40591876L)
+#define LSH_EOF                                  (40591877L)
+#define LSH_EXPIRESOON                           (40591878L)
+#define LSH_NOMATCH                              (40591879L)
+#define LSH_BADCHARS                             (40591880L)
+#define LSH_FATAL_ERROR                          (40591881L)
+#define LSH_BADWINSOCK                           (40591882L)
+#define LSH_BADTIMESERV                          (40591883L)
+#define LSH_NOSOCKET                             (40591884L)
+#define LSH_NOCONNECT                            (40591885L)
+#define LSH_TIMEFAILED                           (40591886L)
+#define LSH_GETTIMEOFDAY                         (40591887L)
+#define LSH_SETTIMEOFDAY                         (40591888L)
+#define LSH_RECVTIME                             (40591889L)
+#define LSH_RECVBYTES                            (40591890L)
+#define LSH_ALREADY_SETTIME                      (40591891L)
+extern void initialize_lsh_error_table(struct et_list **);
+#define ERROR_TABLE_BASE_lsh (40591872L)
+
+/* for compatibility with older versions... */
+#define init_lsh_err_tbl() initialize_lsh_error_table(&_et_list)
+#define lsh_err_base ERROR_TABLE_BASE_lsh
diff --git a/src/windows/leashdll/include/leashinfo.h b/src/windows/leashdll/include/leashinfo.h
new file mode 100644 (file)
index 0000000..7365aa1
--- /dev/null
@@ -0,0 +1,2 @@
+#define LSH_TIME_HOST 1970
+#define LSH_DEFAULT_TICKET_LIFE 1971
diff --git a/src/windows/leashdll/include/leashwin.h b/src/windows/leashdll/include/leashwin.h
new file mode 100644 (file)
index 0000000..477c6c3
--- /dev/null
@@ -0,0 +1,188 @@
+#ifndef __LEASHWIN__
+#define __LEASHWIN__
+
+#include <krb.h>
+
+#define DLGTYPE_PASSWD   0
+#define DLGTYPE_CHPASSWD 1
+typedef struct {
+    int dlgtype;
+    // Tells whether dialog box is in change pwd more or init ticket mode???
+    // (verify this):
+    int dlgstatemax; // What is this???
+    // The title on the Dialog box - for Renewing or Initializing:
+    LPSTR title;
+    LPSTR principal;
+} LSH_DLGINFO, FAR *LPLSH_DLGINFO;
+
+#define LEASH_USERNAME_SZ        64
+#define LEASH_REALM_SZ          192
+#define LEASH_TITLE_SZ          128
+#define LEASH_CCACHE_NAME_SZ   264
+
+typedef struct {
+    DWORD size;
+    int dlgtype;
+    // Tells whether dialog box is in change pwd mode or init ticket mode
+    LPSTR title;               // in v3, set to in.title
+    LPSTR username;            // in v3, set to in.username
+    LPSTR realm;               // in v3, set to in.realm
+    int   use_defaults;
+    int   forwardable;
+    int   noaddresses;
+    int   lifetime;
+    int   renew_till;
+    int   proxiable;
+    int   publicip;
+    // Version 1 of this structure ends here
+    struct {
+        char username[LEASH_USERNAME_SZ];
+        char realm[LEASH_REALM_SZ];
+       // Version 2 of this structure ends here
+       char ccache[LEASH_CCACHE_NAME_SZ];
+    } out;
+    struct {
+       char title[LEASH_TITLE_SZ];
+       char username[LEASH_USERNAME_SZ];
+       char realm[LEASH_REALM_SZ];
+       char ccache[LEASH_CCACHE_NAME_SZ];
+    } in;
+} LSH_DLGINFO_EX, *LPLSH_DLGINFO_EX;
+
+#define LSH_DLGINFO_EX_V1_SZ (sizeof(DWORD) + 3 * sizeof(LPSTR) + 8 * sizeof(int))
+#define LSH_DLGINFO_EX_V2_SZ (LSH_DLGINFO_EX_V1_SZ + LEASH_USERNAME_SZ + LEASH_REALM_SZ)
+#define LSH_DLGINFO_EX_V3_SZ (LSH_DLGINFO_EX_V2_SZ + LEASH_TITLE_SZ + LEASH_USERNAME_SZ + LEASH_REALM_SZ + 2 * LEASH_CCACHE_NAME_SZ)
+
+#ifndef NETIDMGR
+#define NETID_USERNAME_SZ       128
+#define NETID_REALM_SZ          192
+#define NETID_TITLE_SZ          256
+#define NETID_CCACHE_NAME_SZ   264
+
+#define NETID_DLGTYPE_TGT      0
+#define NETID_DLGTYPE_CHPASSWD 1
+typedef struct {
+    DWORD size;
+    DWORD dlgtype;
+    // Tells whether dialog box is in change pwd mode or init ticket mode
+    struct {
+       WCHAR title[NETID_TITLE_SZ];
+       WCHAR username[NETID_USERNAME_SZ];
+       WCHAR realm[NETID_REALM_SZ];
+       WCHAR ccache[NETID_CCACHE_NAME_SZ];
+       DWORD use_defaults;
+       DWORD forwardable;
+       DWORD noaddresses;
+       DWORD lifetime;
+       DWORD renew_till;
+       DWORD proxiable;
+       DWORD publicip;
+       DWORD must_use_specified_principal;
+    } in;
+    struct {
+        WCHAR username[NETID_USERNAME_SZ];
+        WCHAR realm[NETID_REALM_SZ];
+       WCHAR ccache[NETID_CCACHE_NAME_SZ];
+    } out;
+    // Version 1 of this structure ends here
+} NETID_DLGINFO, *LPNETID_DLGINFO;
+
+#define NETID_DLGINFO_V1_SZ (10 * sizeof(DWORD) \
+        + sizeof(WCHAR) * (NETID_TITLE_SZ + \
+        2 * NETID_USERNAME_SZ + 2 * NETID_REALM_SZ + \
+        2 * NETID_CCACHE_NAME_SZ))
+#endif /* NETIDMGR */
+
+typedef struct {
+    char    principal[MAX_K_NAME_SZ]; /* Principal name/instance/realm */
+    int     btickets;                 /* Do we have tickets? */
+    long    lifetime;                 /* Lifetime -- needs to have
+                                         room for 255 5-minute
+                                         periods * 5 * 60 */
+    long    issue_date;               /* The issue time */
+    long    renew_till;               /* The Renew time (k5 only) */
+} TICKETINFO;
+
+int FAR Leash_kinit_dlg(HWND hParent, LPLSH_DLGINFO lpdlginfo);
+int FAR Leash_kinit_dlg_ex(HWND hParent, LPLSH_DLGINFO_EX lpdlginfoex);
+int FAR Leash_changepwd_dlg(HWND hParent, LPLSH_DLGINFO lpdlginfo);
+int FAR Leash_changepwd_dlg_ex(HWND hParent, LPLSH_DLGINFO_EX lpdlginfo);
+
+long FAR Leash_checkpwd(char *principal, char *password);
+long FAR Leash_changepwd(char *principal, char *password, char *newpassword, char** result_string);
+long FAR Leash_kinit(char *principal, char *password, int lifetime);
+long FAR Leash_kinit_ex(char * principal, char * password, int lifetime,
+                                               int forwardable, int proxiable, int renew_life,
+                                               int addressless, unsigned long publicIP);
+
+long FAR Leash_klist(HWND hlist, TICKETINFO FAR *ticketinfo);
+long FAR Leash_kdestroy(void);
+long FAR Leash_get_lsh_errno( LONG FAR *err_val);
+
+long FAR Leash_renew(void);
+long FAR Leash_importable(void);
+long FAR Leash_import(void);
+
+BOOL Leash_set_help_file( char FAR *szHelpFile );
+LPSTR Leash_get_help_file(void);
+
+void Leash_reset_defaults(void);
+
+#define NO_TICKETS 0
+#define EXPD_TICKETS 2
+#define GOOD_TICKETS 1
+
+/* Leash Configuration functions - alters Current User Registry */
+DWORD Leash_get_default_lifetime();
+DWORD Leash_set_default_lifetime(DWORD minutes);
+DWORD Leash_reset_default_lifetime();
+DWORD Leash_get_default_renew_till();
+DWORD Leash_set_default_renew_till(DWORD minutes);
+DWORD Leash_reset_default_renew_till();
+DWORD Leash_get_default_renewable();
+DWORD Leash_set_default_renewable(DWORD onoff);
+DWORD Leash_reset_default_renewable();
+DWORD Leash_get_default_forwardable();
+DWORD Leash_set_default_forwardable(DWORD onoff);
+DWORD Leash_reset_default_forwardable();
+DWORD Leash_get_default_noaddresses();
+DWORD Leash_set_default_noaddresses(DWORD onoff);
+DWORD Leash_reset_default_noaddresses();
+DWORD Leash_get_default_proxiable();
+DWORD Leash_set_default_proxiable(DWORD onoff);
+DWORD Leash_reset_default_proxiable();
+DWORD Leash_get_default_publicip();
+DWORD Leash_set_default_publicip(DWORD ipv4addr);
+DWORD Leash_reset_default_publicip();
+DWORD Leash_get_default_use_krb4();
+DWORD Leash_set_default_use_krb4(DWORD onoff);
+DWORD Leash_reset_default_use_krb4();
+DWORD Leash_get_hide_kinit_options();
+DWORD Leash_set_hide_kinit_options(DWORD onoff);
+DWORD Leash_reset_hide_kinit_options();
+DWORD Leash_get_default_life_min();
+DWORD Leash_set_default_life_min(DWORD minutes);
+DWORD Leash_reset_default_life_min();
+DWORD Leash_get_default_life_max();
+DWORD Leash_set_default_life_max(DWORD minutes);
+DWORD Leash_reset_default_life_max();
+DWORD Leash_get_default_renew_min();
+DWORD Leash_set_default_renew_min(DWORD minutes);
+DWORD Leash_reset_default_renew_min();
+DWORD Leash_get_default_renew_max();
+DWORD Leash_set_default_renew_max(DWORD minutes);
+DWORD Leash_reset_default_renew_max();
+DWORD Leash_get_lock_file_locations();
+DWORD Leash_set_lock_file_locations(DWORD onoff);
+DWORD Leash_reset_lock_file_locations();
+DWORD Leash_get_default_uppercaserealm();
+DWORD Leash_set_default_uppercaserealm(DWORD onoff);
+DWORD Leash_reset_default_uppercaserealm();
+DWORD Leash_get_default_mslsa_import();
+DWORD Leash_set_default_mslsa_import(DWORD onoffmatch);
+DWORD Leash_reset_default_mslsa_import();
+DWORD Leash_get_default_preserve_kinit_settings();
+DWORD Leash_set_default_preserve_kinit_settings(DWORD onoff);
+DWORD Leash_reset_default_preserve_kinit_settings();
+
+#endif /* LEASHWIN */
diff --git a/src/windows/leashdll/include/loadfuncs-com_err.h b/src/windows/leashdll/include/loadfuncs-com_err.h
new file mode 100644 (file)
index 0000000..a579749
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __LOADFUNCS_COM_ERR_H__
+#define __LOADFUNCS_COM_ERR_H__
+
+#include "loadfuncs.h"
+#include <com_err.h>
+
+#if defined(_WIN64)
+#define COMERR_DLL      "comerr64.dll"
+#else
+#define COMERR_DLL      "comerr32.dll"
+#endif
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV_C,
+    com_err,
+    (const char FAR *, errcode_t, const char FAR *, ...)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    com_err_va,
+    (const char FAR *whoami, errcode_t code, const char FAR *fmt, va_list ap)
+    );
+TYPEDEF_FUNC(
+    const char FAR *,
+    KRB5_CALLCONV,
+    error_message,
+    (errcode_t)
+    );
+TYPEDEF_FUNC(
+    errcode_t,
+    KRB5_CALLCONV,
+    add_error_table,
+    (const struct error_table FAR *)
+    );
+TYPEDEF_FUNC(
+    errcode_t,
+    KRB5_CALLCONV,
+    remove_error_table,
+    (const struct error_table FAR *)
+    );
+
+#endif /* __LOADFUNCS_COM_ERR_H__ */
diff --git a/src/windows/leashdll/include/loadfuncs-krb5.h b/src/windows/leashdll/include/loadfuncs-krb5.h
new file mode 100644 (file)
index 0000000..1fab675
--- /dev/null
@@ -0,0 +1,1757 @@
+#ifndef __LOADFUNCS_KRB5_H__
+#define __LOADFUNCS_KRB5_H__
+
+#include "loadfuncs.h"
+#include <krb5.h>
+
+#if defined(_WIN64)
+#define KRB5_DLL      "krb5_64.dll"
+#else
+#define KRB5_DLL      "krb5_32.dll"
+#endif
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_principal,
+    (krb5_context, krb5_principal)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_authenticator,
+    (krb5_context, krb5_authenticator * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_authenticator_contents,
+    (krb5_context, krb5_authenticator * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_addresses,
+    (krb5_context, krb5_address * * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_address,
+    (krb5_context, krb5_address * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_authdata,
+    (krb5_context, krb5_authdata * * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_enc_tkt_part,
+    (krb5_context, krb5_enc_tkt_part * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_ticket,
+    (krb5_context, krb5_ticket * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_tickets,
+    (krb5_context, krb5_ticket * * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_kdc_req,
+    (krb5_context, krb5_kdc_req * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_kdc_rep,
+    (krb5_context, krb5_kdc_rep * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_last_req,
+    (krb5_context, krb5_last_req_entry * * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_enc_kdc_rep_part,
+    (krb5_context, krb5_enc_kdc_rep_part * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_error,
+    (krb5_context, krb5_error * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_ap_req,
+    (krb5_context, krb5_ap_req * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_ap_rep,
+    (krb5_context, krb5_ap_rep * )
+    );
+
+/* Removed around the time of krb5_rc_* change... */
+#if 0
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_safe,
+    (krb5_context, krb5_safe * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_priv,
+    (krb5_context, krb5_priv * )
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_priv_enc_part,
+    (krb5_context, krb5_priv_enc_part * )
+    );
+#endif
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_cred,
+    (krb5_context, krb5_cred *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_creds,
+    (krb5_context, krb5_creds *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_cred_contents,
+    (krb5_context, krb5_creds *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_cred_enc_part,
+    (krb5_context, krb5_cred_enc_part *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_checksum,
+    (krb5_context, krb5_checksum *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_checksum_contents,
+    (krb5_context, krb5_checksum *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_keyblock,
+    (krb5_context, krb5_keyblock *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_keyblock_contents,
+    (krb5_context, krb5_keyblock *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_pa_data,
+    (krb5_context, krb5_pa_data * *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_ap_rep_enc_part,
+    (krb5_context, krb5_ap_rep_enc_part *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_tkt_authent,
+    (krb5_context, krb5_tkt_authent *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_pwd_data,
+    (krb5_context, krb5_pwd_data *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_pwd_sequences,
+    (krb5_context, passwd_phrase_element * *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_data,
+    (krb5_context, krb5_data *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_data_contents,
+    (krb5_context, krb5_data *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_unparsed_name,
+    (krb5_context, char *)
+    );
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_cksumtypes,
+    (krb5_context, krb5_cksumtype *)
+    );
+
+/* ------------------------------------------------------------------------- */
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_encrypt,
+    (krb5_context context, const krb5_keyblock *key,
+     krb5_keyusage usage, const krb5_data *ivec,
+     const krb5_data *input, krb5_enc_data *output)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_decrypt,
+    (krb5_context context, const krb5_keyblock *key,
+     krb5_keyusage usage, const krb5_data *ivec,
+     const krb5_enc_data *input, krb5_data *output)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_encrypt_length,
+    (krb5_context context, krb5_enctype enctype,
+     size_t inputlen, size_t *length)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_block_size,
+    (krb5_context context, krb5_enctype enctype,
+     size_t *blocksize)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_make_random_key,
+    (krb5_context context, krb5_enctype enctype,
+     krb5_keyblock *random_key)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_random_make_octets,
+    (krb5_context context, krb5_data *data)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_random_seed,
+    (krb5_context context, krb5_data *data)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_string_to_key,
+    (krb5_context context, krb5_enctype enctype,
+     const krb5_data *string, const krb5_data *salt,
+     krb5_keyblock *key)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_enctype_compare,
+    (krb5_context context, krb5_enctype e1, krb5_enctype e2,
+     krb5_boolean *similar)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_make_checksum,
+    (krb5_context context, krb5_cksumtype cksumtype,
+     const krb5_keyblock *key, krb5_keyusage usage,
+     const krb5_data *input, krb5_checksum *cksum)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_verify_checksum,
+    (krb5_context context,
+     const krb5_keyblock *key, krb5_keyusage usage,
+     const krb5_data *data,
+     const krb5_checksum *cksum,
+     krb5_boolean *valid)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_checksum_length,
+    (krb5_context context, krb5_cksumtype cksumtype,
+     size_t *length)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_c_keyed_checksum_types,
+    (krb5_context context, krb5_enctype enctype,
+     unsigned int *count, krb5_cksumtype **cksumtypes)
+    );
+
+/* ------------------------------------------------------------------------- */
+
+TYPEDEF_FUNC(
+    krb5_boolean,
+    KRB5_CALLCONV,
+    valid_enctype,
+    (const krb5_enctype ktype)
+    );
+
+TYPEDEF_FUNC(
+    krb5_boolean,
+    KRB5_CALLCONV,
+    valid_cksumtype,
+    (const krb5_cksumtype ctype)
+    );
+
+TYPEDEF_FUNC(
+    krb5_boolean,
+    KRB5_CALLCONV,
+    is_coll_proof_cksum,
+    (const krb5_cksumtype ctype)
+    );
+
+TYPEDEF_FUNC(
+    krb5_boolean,
+    KRB5_CALLCONV,
+    is_keyed_cksum,
+    (const krb5_cksumtype ctype)
+    );
+
+/* ------------------------------------------------------------------------- */
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_init_context,
+    (krb5_context *)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_context,
+    (krb5_context)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_decrypt_tkt_part,
+    (krb5_context,
+     const krb5_keyblock *,
+     krb5_ticket * )
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_tgt_creds,
+    (krb5_context,
+     krb5_creds ** )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_credentials,
+    (krb5_context,
+     const krb5_flags,
+     krb5_ccache,
+     krb5_creds *,
+     krb5_creds * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_credentials_validate,
+    (krb5_context,
+     const krb5_flags,
+     krb5_ccache,
+     krb5_creds *,
+     krb5_creds * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_credentials_renew,
+    (krb5_context,
+     const krb5_flags,
+     krb5_ccache,
+     krb5_creds *,
+     krb5_creds * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_req,
+    (krb5_context,
+     krb5_auth_context *,
+     const krb5_flags,
+     char *,
+     char *,
+     krb5_data *,
+     krb5_ccache,
+     krb5_data * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_req_extended,
+    (krb5_context,
+     krb5_auth_context *,
+     const krb5_flags,
+     krb5_data *,
+     krb5_creds *,
+     krb5_data * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_rep,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_rd_rep,
+    (krb5_context,
+     krb5_auth_context,
+     const krb5_data *,
+     krb5_ap_rep_enc_part * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_error,
+    (krb5_context,
+     const krb5_error *,
+     krb5_data * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_rd_error,
+    (krb5_context,
+     const krb5_data *,
+     krb5_error * * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_rd_safe,
+    (krb5_context,
+     krb5_auth_context,
+     const krb5_data *,
+     krb5_data *,
+     krb5_replay_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_rd_priv,
+    (krb5_context,
+     krb5_auth_context,
+     const krb5_data *,
+     krb5_data *,
+     krb5_replay_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_parse_name,
+    (krb5_context,
+     const char *,
+     krb5_principal * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_unparse_name,
+    (krb5_context,
+     krb5_const_principal,
+     char * * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_unparse_name_ext,
+    (krb5_context,
+     krb5_const_principal,
+     char * *,
+     int *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_set_principal_realm,
+    (krb5_context, krb5_principal, const char *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_boolean,
+    KRB5_CALLCONV,
+    krb5_principal_compare,
+    (krb5_context,
+     krb5_const_principal,
+     krb5_const_principal)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_keyblock,
+    (krb5_context,
+     const krb5_keyblock *,
+     krb5_keyblock * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_keyblock_contents,
+    (krb5_context,
+     const krb5_keyblock *,
+     krb5_keyblock *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_creds,
+    (krb5_context,
+     const krb5_creds *,
+     krb5_creds * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_data,
+    (krb5_context,
+     const krb5_data *,
+     krb5_data * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_principal,
+    (krb5_context,
+     krb5_const_principal,
+     krb5_principal *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_addr,
+    (krb5_context,
+     const krb5_address *,
+     krb5_address * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_addresses,
+    (krb5_context,
+     krb5_address * const *,
+     krb5_address * * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_ticket,
+    (krb5_context,
+     const krb5_ticket *,
+     krb5_ticket * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_authdata,
+    (krb5_context,
+     krb5_authdata * const *,
+     krb5_authdata * * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_authenticator,
+    (krb5_context,
+     const krb5_authenticator *,
+     krb5_authenticator * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_copy_checksum,
+    (krb5_context,
+     const krb5_checksum *,
+     krb5_checksum * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_server_rcache,
+    (krb5_context,
+     const krb5_data *, krb5_rcache *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV_C,
+    krb5_build_principal_ext,
+    (krb5_context, krb5_principal *, int, const char *, ...)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV_C,
+    krb5_build_principal,
+    (krb5_context, krb5_principal *, int, const char *, ...)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_425_conv_principal,
+    (krb5_context,
+     const char *name,
+     const char *instance, const char *realm,
+     krb5_principal *princ)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_524_conv_principal,
+    (krb5_context context, const krb5_principal princ,
+     char *name, char *inst, char *realm)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_chpw_req,
+    (krb5_context context, krb5_auth_context auth_context,
+     krb5_data *ap_req, char *passwd, krb5_data *packet)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_rd_chpw_rep,
+    (krb5_context context, krb5_auth_context auth_context,
+     krb5_data *packet, int *result_code,
+     krb5_data *result_data)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_chpw_result_code_string,
+    (krb5_context context, int result_code,
+     char **result_codestr)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_register,
+    (krb5_context,
+     struct _krb5_kt_ops * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_resolve,
+    (krb5_context,
+     const char *,
+     krb5_keytab * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_default_name,
+    (krb5_context,
+     char *,
+     int )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_default,
+    (krb5_context,
+     krb5_keytab * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_free_entry,
+    (krb5_context,
+     krb5_keytab_entry * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_remove_entry,
+    (krb5_context,
+     krb5_keytab,
+     krb5_keytab_entry * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_add_entry,
+    (krb5_context,
+     krb5_keytab,
+     krb5_keytab_entry * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_resolve,
+    (krb5_context,
+     const char *,
+     krb5_ccache * )
+    );
+
+TYPEDEF_FUNC(
+    const char*,
+    KRB5_CALLCONV,
+    krb5_cc_default_name,
+    (krb5_context)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_set_default_name,
+    (krb5_context, const char *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_default,
+    (krb5_context,
+     krb5_ccache *)
+    );
+
+TYPEDEF_FUNC(
+    unsigned int,
+    KRB5_CALLCONV,
+    krb5_get_notification_message,
+    (void)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_copy_creds,
+    (krb5_context context,
+     krb5_ccache incc,
+     krb5_ccache outcc)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_us_timeofday,
+    (krb5_context,
+     krb5_int32 *,
+     krb5_int32 * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_timeofday,
+    (krb5_context,
+     krb5_int32 * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_os_localaddr,
+    (krb5_context,
+     krb5_address * * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_default_realm,
+    (krb5_context,
+     char * * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_set_default_realm,
+    (krb5_context,
+     const char * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_free_default_realm,
+    (krb5_context,
+     const char * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_sname_to_principal,
+    (krb5_context,
+     const char *,
+     const char *,
+     krb5_int32,
+     krb5_principal *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_change_password,
+    (krb5_context context, krb5_creds *creds, char *newpw,
+     int *result_code, krb5_data *result_code_string,
+     krb5_data *result_string)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_default_config_files,
+    (char ***filenames)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_config_files,
+    (char **filenames)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_in_tkt,
+    (krb5_context,
+     const krb5_flags,
+     krb5_address * const *,
+     krb5_enctype *,
+     krb5_preauthtype *,
+     krb5_error_code ( * )(krb5_context,
+                           const krb5_enctype,
+                           krb5_data *,
+                           krb5_const_pointer,
+                           krb5_keyblock * *),
+     krb5_const_pointer,
+     krb5_error_code ( * )(krb5_context,
+                           const krb5_keyblock *,
+                           krb5_const_pointer,
+                           krb5_kdc_rep * ),
+     krb5_const_pointer,
+     krb5_creds *,
+     krb5_ccache,
+     krb5_kdc_rep * * )
+    );
+
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_in_tkt_with_password,
+    (krb5_context,
+     const krb5_flags,
+     krb5_address * const *,
+     krb5_enctype *,
+     krb5_preauthtype *,
+     const char *,
+     krb5_ccache,
+     krb5_creds *,
+     krb5_kdc_rep * * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_in_tkt_with_skey,
+    (krb5_context,
+     const krb5_flags,
+     krb5_address * const *,
+     krb5_enctype *,
+     krb5_preauthtype *,
+     const krb5_keyblock *,
+     krb5_ccache,
+     krb5_creds *,
+     krb5_kdc_rep * * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_in_tkt_with_keytab,
+    (krb5_context,
+     const krb5_flags,
+     krb5_address * const *,
+     krb5_enctype *,
+     krb5_preauthtype *,
+     const krb5_keytab,
+     krb5_ccache,
+     krb5_creds *,
+     krb5_kdc_rep * * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_rd_req,
+    (krb5_context,
+     krb5_auth_context *,
+     const krb5_data *,
+     krb5_const_principal,
+     krb5_keytab,
+     krb5_flags *,
+     krb5_ticket * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_read_service_key,
+    (krb5_context,
+     krb5_pointer,
+     krb5_principal,
+     krb5_kvno,
+     krb5_enctype,
+     krb5_keyblock * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_safe,
+    (krb5_context,
+     krb5_auth_context,
+     const krb5_data *,
+     krb5_data *,
+     krb5_replay_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_priv,
+    (krb5_context,
+     krb5_auth_context,
+     const krb5_data *,
+     krb5_data *,
+     krb5_replay_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_register,
+    (krb5_context,
+     krb5_cc_ops *,
+     krb5_boolean )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_sendauth,
+    (krb5_context,
+     krb5_auth_context *,
+     krb5_pointer,
+     char *,
+     krb5_principal,
+     krb5_principal,
+     krb5_flags,
+     krb5_data *,
+     krb5_creds *,
+     krb5_ccache,
+     krb5_error * *,
+     krb5_ap_rep_enc_part * *,
+     krb5_creds * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_recvauth,
+    (krb5_context,
+     krb5_auth_context *,
+     krb5_pointer,
+     char *,
+     krb5_principal,
+     krb5_int32,
+     krb5_keytab,
+     krb5_ticket * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_ncred,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_creds * *,
+     krb5_data * *,
+     krb5_replay_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_mk_1cred,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_creds *,
+     krb5_data * *,
+     krb5_replay_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_rd_cred,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_data *,
+     krb5_creds * * *,
+     krb5_replay_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_fwd_tgt_creds,
+    (krb5_context,
+     krb5_auth_context,
+     char *,
+     krb5_principal,
+     krb5_principal,
+     krb5_ccache,
+     int forwardable,
+     krb5_data *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_init,
+    (krb5_context,
+     krb5_auth_context *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_free,
+    (krb5_context,
+     krb5_auth_context)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_setflags,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_int32)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_getflags,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_int32 *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_setuseruserkey,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_keyblock *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_getkey,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_keyblock **)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_getlocalsubkey,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_keyblock * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_set_req_cksumtype,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_cksumtype)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_getlocalseqnumber,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_int32 *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_getremoteseqnumber,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_int32 *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_setrcache,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_rcache)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_getauthenticator,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_authenticator * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_getremotesubkey,
+    (krb5_context,
+     krb5_auth_context,
+     krb5_keyblock * *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_read_password,
+    (krb5_context,
+     const char *,
+     const char *,
+     char *,
+     int * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_host_realm,
+    (krb5_context,
+     const char *,
+     char * * * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_free_host_realm,
+    (krb5_context,
+     char * const * )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_realm_domain,
+    (krb5_context,
+     const char *,
+     char ** )
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_auth_con_genaddrs,
+    (krb5_context,
+     krb5_auth_context,
+     int, int)
+    );
+
+/* ------------------------------------------------------------------------- */
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_string_to_enctype,
+    (char *, krb5_enctype *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_string_to_salttype,
+    (char *, krb5_int32 *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_string_to_cksumtype,
+    (char *, krb5_cksumtype *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_string_to_timestamp,
+    (char *, krb5_timestamp *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_string_to_deltat,
+    (char *, krb5_deltat *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_enctype_to_string,
+    (krb5_enctype, char *, size_t)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_salttype_to_string,
+    (krb5_int32, char *, size_t)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cksumtype_to_string,
+    (krb5_cksumtype, char *, size_t)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_timestamp_to_string,
+    (krb5_timestamp, char *, size_t)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_timestamp_to_sfstring,
+    (krb5_timestamp, char *, size_t, char *)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_deltat_to_string,
+    (krb5_deltat, char *, size_t)
+    );
+
+/* ------------------------------------------------------------------------- */
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_prompter_posix,
+    (krb5_context context,
+     void *data,
+     const char *name,
+     const char *banner,
+     int num_prompts,
+     krb5_prompt prompts[])
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_init,
+    (krb5_get_init_creds_opt *opt)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_tkt_life,
+    (krb5_get_init_creds_opt *opt,
+     krb5_deltat tkt_life)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_renew_life,
+    (krb5_get_init_creds_opt *opt,
+     krb5_deltat renew_life)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_forwardable,
+    (krb5_get_init_creds_opt *opt,
+     int forwardable)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_proxiable,
+    (krb5_get_init_creds_opt *opt,
+     int proxiable)
+    );
+
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_etype_list,
+    (krb5_get_init_creds_opt *opt,
+     krb5_enctype *etype_list,
+     int etype_list_length)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_address_list,
+    (krb5_get_init_creds_opt *opt,
+     krb5_address **addresses)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_preauth_list,
+    (krb5_get_init_creds_opt *opt,
+     krb5_preauthtype *preauth_list,
+     int preauth_list_length)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_salt,
+    (krb5_get_init_creds_opt *opt,
+     krb5_data *salt)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_opt_set_change_password_prompt,
+    (krb5_get_init_creds_opt *opt,
+     int prompt)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_password,
+    (krb5_context context,
+     krb5_creds *creds,
+     krb5_principal client,
+     char *password,
+     krb5_prompter_fct prompter,
+     void *data,
+     krb5_deltat start_time,
+     char *in_tkt_service,
+     krb5_get_init_creds_opt *options)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_init_creds_keytab,
+    (krb5_context context,
+     krb5_creds *creds,
+     krb5_principal client,
+     krb5_keytab arg_keytab,
+     krb5_deltat start_time,
+     char *in_tkt_service,
+     krb5_get_init_creds_opt *options)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_verify_init_creds_opt_init,
+    (krb5_verify_init_creds_opt *options)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_verify_init_creds_opt_set_ap_req_nofail,
+    (krb5_verify_init_creds_opt *options,
+     int ap_req_nofail)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_verify_init_creds,
+    (krb5_context context,
+     krb5_creds *creds,
+     krb5_principal ap_req_server,
+     krb5_keytab ap_req_keytab,
+     krb5_ccache *ccache,
+     krb5_verify_init_creds_opt *options)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_validated_creds,
+    (krb5_context context,
+     krb5_creds *creds,
+     krb5_principal client,
+     krb5_ccache ccache,
+     char *in_tkt_service)
+    );
+
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_get_renewed_creds,
+    (krb5_context context,
+     krb5_creds *creds,
+     krb5_principal client,
+     krb5_ccache ccache,
+     char *in_tkt_service)
+    );
+
+/* ------------------------------------------------------------------------- */
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_realm_iterator_create,
+    (krb5_context context, void **iter_p)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_realm_iterator,
+    (krb5_context context, void **iter_p, char **ret_realm)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_realm_iterator_free,
+    (krb5_context context, void **iter_p)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    krb5_free_realm_string,
+    (krb5_context context, char *str)
+    );
+
+TYPEDEF_FUNC(
+    krb5_prompt_type*,
+    KRB5_CALLCONV,
+    krb5_get_prompt_types,
+    (krb5_context context)
+    );
+
+/* NOT IN krb5.h HEADER: */
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_decode_ticket,
+    (const krb5_data *code, krb5_ticket **rep)
+    );
+
+/* --- more --- */
+
+TYPEDEF_FUNC(
+    char *,
+    KRB5_CALLCONV,
+    krb5_cc_get_name,
+    (krb5_context context, krb5_ccache cache)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_gen_new,
+    (krb5_context context, krb5_ccache *cache)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_initialize,
+    (krb5_context context, krb5_ccache cache, krb5_principal principal)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_destroy,
+    (krb5_context context, krb5_ccache cache)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_close,
+    (krb5_context context, krb5_ccache cache)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_store_cred,
+    (krb5_context context, krb5_ccache cache, krb5_creds *creds)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_retrieve_cred,
+    (krb5_context context, krb5_ccache cache,
+     krb5_flags flags, krb5_creds *mcreds,
+     krb5_creds *creds)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_get_principal,
+    (krb5_context context, krb5_ccache cache, krb5_principal *principal)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_start_seq_get,
+    (krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_next_cred,
+    (krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor,
+     krb5_creds *creds)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_end_seq_get,
+    (krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_remove_cred,
+    (krb5_context context, krb5_ccache cache, krb5_flags flags,
+     krb5_creds *creds)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_cc_set_flags,
+    (krb5_context context, krb5_ccache cache, krb5_flags flags)
+    );
+
+TYPEDEF_FUNC(
+    const char *,
+    KRB5_CALLCONV,
+    krb5_cc_get_type,
+    (krb5_context context, krb5_ccache cache)
+    );
+
+TYPEDEF_FUNC(
+    char *,
+    KRB5_CALLCONV,
+    krb5_kt_get_type,
+    (krb5_context, krb5_keytab keytab)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_get_name,
+    (krb5_context context, krb5_keytab keytab, char *name,
+     unsigned int namelen)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_close,
+    (krb5_context context, krb5_keytab keytab)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_get_entry,
+    (krb5_context context, krb5_keytab keytab,
+     krb5_const_principal principal, krb5_kvno vno,
+     krb5_enctype enctype, krb5_keytab_entry *entry)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_start_seq_get,
+    (krb5_context context, krb5_keytab keytab, krb5_kt_cursor *cursor)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_next_entry,
+    (krb5_context context, krb5_keytab keytab,
+     krb5_keytab_entry *entry, krb5_kt_cursor *cursor)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_kt_end_seq_get,
+    (krb5_context context, krb5_keytab keytab, krb5_kt_cursor *cursor)
+    );
+
+TYPEDEF_FUNC(
+    krb5_error_code,
+    KRB5_CALLCONV,
+    krb5_locate_kdc,
+    (krb5_context context, const krb5_data *realm,
+      struct addrlist *addrlist,
+      int get_masters, int socktype, int family)
+    );
+#endif /* __LOADFUNCS_KRB5_H__ */
diff --git a/src/windows/leashdll/include/loadfuncs-lsa.h b/src/windows/leashdll/include/loadfuncs-lsa.h
new file mode 100644 (file)
index 0000000..40138f5
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __LOADFUNCS_LSA_H__
+#define __LOADFUNCS_LSA_H__
+
+#include "loadfuncs.h"
+
+#define SECUR32_DLL "secur32.dll"
+#define ADVAPI32_DLL "advapi32.dll"
+
+TYPEDEF_FUNC(
+    NTSTATUS,
+    NTAPI,
+    LsaConnectUntrusted,
+    (PHANDLE)
+    );
+TYPEDEF_FUNC(
+    NTSTATUS,
+    NTAPI,
+    LsaLookupAuthenticationPackage,
+    (HANDLE, PLSA_STRING, PULONG)
+    );
+TYPEDEF_FUNC(
+    NTSTATUS,
+    NTAPI,
+    LsaCallAuthenticationPackage,
+    (HANDLE, ULONG, PVOID, ULONG, PVOID *, PULONG, PNTSTATUS)
+    );
+TYPEDEF_FUNC(
+    NTSTATUS,
+    NTAPI,
+    LsaFreeReturnBuffer,
+    (PVOID)
+    );
+TYPEDEF_FUNC(
+    ULONG,
+    NTAPI,
+    LsaNtStatusToWinError,
+    (NTSTATUS)
+    );
+TYPEDEF_FUNC(
+    NTSTATUS,
+    NTAPI,
+    LsaGetLogonSessionData,
+    (PLUID, PSECURITY_LOGON_SESSION_DATA*)
+    );
+#endif /* __LOADFUNCS_LSA_H__ */
diff --git a/src/windows/leashdll/include/loadfuncs-profile.h b/src/windows/leashdll/include/loadfuncs-profile.h
new file mode 100644 (file)
index 0000000..ef7f6b7
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef __LOADFUNCS_PROFILE_H__
+#define __LOADFUNCS_PROFILE_H__
+
+#include "loadfuncs.h"
+#include <profile.h>
+
+#if defined(_WIN64)
+#define PROFILE_DLL      "xpprof64.dll"
+#else
+#define PROFILE_DLL      "xpprof32.dll"
+#endif
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_init,
+    (const_profile_filespec_t *files, profile_t *ret_profile)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_init_path,
+    (const_profile_filespec_list_t filelist, profile_t *ret_profile)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_flush,
+    (profile_t profile)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    profile_abandon,
+    (profile_t profile)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    profile_release,
+    (profile_t profile)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_get_values,
+    (profile_t profile, const char **names, char ***ret_values)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    profile_free_list,
+    (char **list)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_get_string,
+    (profile_t profile, const char *name, const char *subname,
+                       const char *subsubname, const char *def_val,
+                       char **ret_string)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_get_integer,
+    (profile_t profile, const char *name, const char *subname,
+                       const char *subsubname, int def_val,
+                       int *ret_default)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_get_relation_names,
+    (profile_t profile, const char **names, char ***ret_names)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_get_subsection_names,
+    (profile_t profile, const char **names, char ***ret_names)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_iterator_create,
+    (profile_t profile, const char **names, int flags, void **ret_iter)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    profile_iterator_free,
+    (void **iter_p)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_iterator,
+    (void **iter_p, char **ret_name, char **ret_value)
+    );
+
+TYPEDEF_FUNC(
+    void,
+    KRB5_CALLCONV,
+    profile_release_string,
+    (char *str)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_update_relation,
+    (profile_t profile, const char **names, const char *old_value, const char *new_value)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_clear_relation,
+    (profile_t profile, const char **names)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_rename_section,
+    (profile_t profile, const char **names, const char *new_name)
+    );
+
+TYPEDEF_FUNC(
+    long,
+    KRB5_CALLCONV,
+    profile_add_relation,
+    (profile_t profile, const char **names, const char *new_value)
+    );
+
+
+#endif /* __LOADFUNCS_PROFILE_H__ */
diff --git a/src/windows/leashdll/include/loadfuncs.h b/src/windows/leashdll/include/loadfuncs.h
new file mode 100644 (file)
index 0000000..7aef62d
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __LOADFUNCS_H__
+#define __LOADFUNCS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+
+typedef struct _FUNC_INFO {
+    void** func_ptr_var;
+    char* func_name;
+} FUNC_INFO;
+
+#define DECL_FUNC_PTR(x) FP_##x p##x
+#define MAKE_FUNC_INFO(x) { (void**) &p##x, #x }
+#define END_FUNC_INFO { 0, 0 }
+#define TYPEDEF_FUNC(ret, call, name, args) typedef ret (call *FP_##name) args
+
+void
+UnloadFuncs(
+    FUNC_INFO fi[],
+    HINSTANCE h
+    );
+
+int
+LoadFuncs(
+    const char* dll_name,
+    FUNC_INFO fi[],
+    HINSTANCE* ph,  // [out, optional] - DLL handle
+    int* pindex,    // [out, optional] - index of last func loaded (-1 if none)
+    int cleanup,    // cleanup function pointers and unload on error
+    int go_on,      // continue loading even if some functions cannot be loaded
+    int silent      // do not pop-up a system dialog if DLL cannot be loaded
+    );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LOADFUNCS_H__ */
diff --git a/src/windows/leashdll/krb5routines.c b/src/windows/leashdll/krb5routines.c
new file mode 100644 (file)
index 0000000..7f2d283
--- /dev/null
@@ -0,0 +1,1530 @@
+// Module name: krb5routines.c
+
+#include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+
+/* _WIN32_WINNT must be 0x0501 or greater to pull in definition of
+ * all required LSA data types when the Vista SDK NtSecAPI.h is used.
+ */
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#else
+#if _WIN32_WINNT < 0x0501
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+#endif
+#include <ntsecapi.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+
+/* Private Include files */
+#include "leashdll.h"
+#include <leashwin.h>
+#include "leash-int.h"
+
+#define KRB5_DEFAULT_LIFE            60*60*10 /* 10 hours */
+
+char *GetTicketFlag(krb5_creds *cred)
+{
+   static char buf[32];
+   int i = 0;
+
+   buf[i++] = ' ';
+   buf[i++] = '(';
+
+   if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
+     buf[i++] = 'F';
+
+   if (cred->ticket_flags & TKT_FLG_FORWARDED)
+     buf[i++] = 'f';
+
+   if (cred->ticket_flags & TKT_FLG_PROXIABLE)
+     buf[i++] = 'P';
+
+   if (cred->ticket_flags & TKT_FLG_PROXY)
+     buf[i++] = 'p';
+
+   if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
+     buf[i++] = 'D';
+
+   if (cred->ticket_flags & TKT_FLG_POSTDATED)
+     buf[i++] = 'd';
+
+   if (cred->ticket_flags & TKT_FLG_INVALID)
+     buf[i++] = 'i';
+
+   if (cred->ticket_flags & TKT_FLG_RENEWABLE)
+     buf[i++] = 'R';
+
+   if (cred->ticket_flags & TKT_FLG_INITIAL)
+     buf[i++] = 'I';
+
+   if (cred->ticket_flags & TKT_FLG_HW_AUTH)
+     buf[i++] = 'H';
+
+   if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
+     buf[i++] = 'A';
+
+   buf[i++] = ')';
+   buf[i] = '\0';
+
+   if (i <= 3)
+     buf[0] = '\0';
+
+   return buf;
+}
+
+long
+Leash_convert524(
+     krb5_context alt_ctx
+     )
+{
+#if defined(NO_KRB5) || defined(NO_KRB4)
+    return(0);
+#else
+    krb5_context ctx = 0;
+    krb5_error_code code = 0;
+    int icode = 0;
+    krb5_principal me = 0;
+    krb5_principal server = 0;
+    krb5_creds *v5creds = 0;
+    krb5_creds increds;
+    krb5_ccache cc = 0;
+    CREDENTIALS * v4creds = NULL;
+    static int init_ets = 1;
+
+    if (!pkrb5_init_context ||
+        !pkrb_in_tkt ||
+       !pkrb524_init_ets ||
+       !pkrb524_convert_creds_kdc)
+        return 0;
+
+       v4creds = (CREDENTIALS *) malloc(sizeof(CREDENTIALS));
+       memset((char *) v4creds, 0, sizeof(CREDENTIALS));
+
+    memset((char *) &increds, 0, sizeof(increds));
+    /*
+      From this point on, we can goto cleanup because increds is
+      initialized.
+    */
+
+    if (alt_ctx)
+    {
+        ctx = alt_ctx;
+    }
+    else
+    {
+        code = pkrb5_init_context(&ctx);
+        if (code) goto cleanup;
+    }
+
+    code = pkrb5_cc_default(ctx, &cc);
+    if (code) goto cleanup;
+
+    if ( init_ets ) {
+        pkrb524_init_ets(ctx);
+        init_ets = 0;
+    }
+
+    if (code = pkrb5_cc_get_principal(ctx, cc, &me))
+        goto cleanup;
+
+    if ((code = pkrb5_build_principal(ctx,
+                                     &server,
+                                     krb5_princ_realm(ctx, me)->length,
+                                     krb5_princ_realm(ctx, me)->data,
+                                     "krbtgt",
+                                     krb5_princ_realm(ctx, me)->data,
+                                     NULL))) {
+        goto cleanup;
+    }
+
+    increds.client = me;
+    increds.server = server;
+    increds.times.endtime = 0;
+    increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+    if ((code = pkrb5_get_credentials(ctx, 0,
+                                     cc,
+                                     &increds,
+                                     &v5creds))) {
+        goto cleanup;
+    }
+
+    if ((icode = pkrb524_convert_creds_kdc(ctx,
+                                          v5creds,
+                                          v4creds))) {
+        goto cleanup;
+    }
+
+    /* initialize ticket cache */
+    if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm)
+         != KSUCCESS)) {
+        goto cleanup;
+    }
+    /* stash ticket, session key, etc. for future use */
+    if ((icode = pkrb_save_credentials(v4creds->service,
+                                      v4creds->instance,
+                                      v4creds->realm,
+                                      v4creds->session,
+                                      v4creds->lifetime,
+                                      v4creds->kvno,
+                                      &(v4creds->ticket_st),
+                                      v4creds->issue_date))) {
+        goto cleanup;
+    }
+
+ cleanup:
+    memset(v4creds, 0, sizeof(v4creds));
+    free(v4creds);
+
+    if (v5creds) {
+        pkrb5_free_creds(ctx, v5creds);
+    }
+    if (increds.client == me)
+        me = 0;
+    if (increds.server == server)
+        server = 0;
+    pkrb5_free_cred_contents(ctx, &increds);
+    if (server) {
+        pkrb5_free_principal(ctx, server);
+    }
+    if (me) {
+        pkrb5_free_principal(ctx, me);
+    }
+    pkrb5_cc_close(ctx, cc);
+
+    if (ctx && (ctx != alt_ctx)) {
+        pkrb5_free_context(ctx);
+    }
+    return !(code || icode);
+#endif /* NO_KRB5 */
+}
+
+#ifndef ENCTYPE_LOCAL_RC4_MD4
+#define ENCTYPE_LOCAL_RC4_MD4    0xFFFFFF80
+#endif
+
+static char *
+etype_string(krb5_enctype enctype)
+{
+    static char buf[12];
+
+    switch (enctype) {
+    case ENCTYPE_NULL:
+        return "NULL";
+    case ENCTYPE_DES_CBC_CRC:
+        return "DES-CBC-CRC";
+    case ENCTYPE_DES_CBC_MD4:
+        return "DES-CBC-MD4";
+    case ENCTYPE_DES_CBC_MD5:
+        return "DES-CBC-MD5";
+    case ENCTYPE_DES_CBC_RAW:
+        return "DES-CBC-RAW";
+    case ENCTYPE_DES3_CBC_SHA:
+        return "DES3-CBC-SHA";
+    case ENCTYPE_DES3_CBC_RAW:
+        return "DES3-CBC-RAW";
+    case ENCTYPE_DES_HMAC_SHA1:
+        return "DES-HMAC-SHA1";
+    case ENCTYPE_DES3_CBC_SHA1:
+        return "DES3-CBC-SHA1";
+    case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+        return "AES128_CTS-HMAC-SHA1_96";
+    case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+        return "AES256_CTS-HMAC-SHA1_96";
+    case ENCTYPE_ARCFOUR_HMAC:
+        return "RC4-HMAC-NT";
+    case ENCTYPE_ARCFOUR_HMAC_EXP:
+        return "RC4-HMAC-NT-EXP";
+    case ENCTYPE_UNKNOWN:
+        return "UNKNOWN";
+#ifdef ENCTYPE_LOCAL_DES3_HMAC_SHA1
+    case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
+        return "LOCAL-DES3-HMAC-SHA1";
+#endif
+#ifdef ENCTYPE_LOCAL_RC4_MD4
+    case ENCTYPE_LOCAL_RC4_MD4:
+        return "LOCAL-RC4-MD4";
+#endif
+    default:
+        wsprintf(buf, "#%d", enctype);
+        return buf;
+    }
+}
+
+char *
+one_addr(krb5_address *a)
+{
+    static char retstr[256];
+    struct hostent *h;
+    int no_resolve = 1;
+
+    retstr[0] = '\0';
+
+    if ((a->addrtype == ADDRTYPE_INET && a->length == 4)
+#ifdef AF_INET6
+        || (a->addrtype == ADDRTYPE_INET6 && a->length == 16)
+#endif
+        ) {
+        int af = AF_INET;
+#ifdef AF_INET6
+        if (a->addrtype == ADDRTYPE_INET6)
+            af = AF_INET6;
+#endif
+        if (!no_resolve) {
+#ifdef HAVE_GETIPNODEBYADDR
+            int err;
+            h = getipnodebyaddr(a->contents, a->length, af, &err);
+            if (h) {
+                wsprintf(retstr, "%s", h->h_name);
+                freehostent(h);
+            }
+#else
+            h = gethostbyaddr(a->contents, a->length, af);
+            if (h) {
+                wsprintf(retstr,"%s", h->h_name);
+            }
+#endif
+            if (h)
+                return(retstr);
+        }
+        if (no_resolve || !h) {
+#ifdef HAVE_INET_NTOP
+            char buf[46];
+            const char *name = inet_ntop(a->addrtype, a->contents, buf, sizeof(buf));
+            if (name) {
+                wsprintf(retstr,"%s", name);
+                return;
+            }
+#else
+            if (a->addrtype == ADDRTYPE_INET) {
+                wsprintf(retstr,"%d.%d.%d.%d", a->contents[0], a->contents[1],
+                       a->contents[2], a->contents[3]);
+                return(retstr);
+            }
+#endif
+        }
+    }
+    wsprintf(retstr,"unknown addr type %d", a->addrtype);
+    return(retstr);
+}
+
+long
+not_an_API_LeashKRB5GetTickets(
+    TICKETINFO * ticketinfo,
+    TicketList** ticketList,
+    krb5_context *krbv5Context
+    )
+{
+#ifdef NO_KRB5
+    return(0);
+#else
+    krb5_context       ctx;
+    krb5_ccache                cache;
+    krb5_error_code    code;
+    krb5_principal     KRBv5Principal;
+    krb5_flags         flags = 0;
+    krb5_cc_cursor     KRBv5Cursor;
+    krb5_creds         KRBv5Credentials;
+    krb5_ticket    *tkt=NULL;
+    int                                StartMonth;
+    int                                EndMonth;
+    int             RenewMonth;
+    int                                StartDay;
+    int                                EndDay;
+    int             RenewDay;
+    int             freeContextFlag;
+    char                       StartTimeString[256];
+    char                       EndTimeString[256];
+    char            RenewTimeString[256];
+    char                       fill;
+    char                       *ClientName;
+    char                       *PrincipalName;
+    char                       *sServerName;
+    char                       Buffer[256];
+    char                       Months[12][4] = {"Jan\0", "Feb\0", "Mar\0", "Apr\0", "May\0", "Jun\0", "Jul\0", "Aug\0", "Sep\0", "Oct\0", "Nov\0", "Dec\0"};
+    char                       StartTime[16];
+    char                       EndTime[16];
+    char            RenewTime[16];
+    char                       temp[128];
+    char                       *sPtr;
+    char            *ticketFlag;
+    LPCSTR          functionName;
+
+    TicketList* list = NULL;
+
+    ctx = NULL;
+    cache = NULL;
+    if ( ticketinfo ) {
+        ticketinfo->btickets = NO_TICKETS;
+        ticketinfo->principal[0] = '\0';
+    }
+
+    if ((code = Leash_krb5_initialize(&(*krbv5Context), &cache)))
+        return(code);
+
+    ctx = (*krbv5Context);
+
+#ifdef KRB5_TC_NOTICKET
+    flags = KRB5_TC_NOTICKET;
+#endif
+    if ((code = pkrb5_cc_set_flags(ctx, cache, flags)))
+    {
+        if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
+            Leash_krb5_error(code, "krb5_cc_set_flags()", 0, &ctx,
+                                  &cache);
+        else if ((code == KRB5_FCC_NOFILE || code == KRB5_CC_NOTFOUND) && ctx != NULL)
+        {
+            if (cache != NULL)
+                pkrb5_cc_close(ctx, cache);
+        }
+        return code;
+    }
+
+    if ((code = pkrb5_cc_get_principal(ctx, cache, &KRBv5Principal)))
+    {
+        if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND)
+            Leash_krb5_error(code, "krb5_cc_get_principal()", 0, &ctx, &cache);
+        else if ((code == KRB5_FCC_NOFILE || code == KRB5_CC_NOTFOUND) && ctx != NULL)
+        {
+            if (cache != NULL)
+                pkrb5_cc_close(ctx, cache);
+        }
+        return code;
+    }
+
+    PrincipalName = NULL;
+    ClientName = NULL;
+    sServerName = NULL;
+    if ((code = (*pkrb5_unparse_name)(ctx, KRBv5Principal,
+                                      (char **)&PrincipalName)))
+    {
+        if (PrincipalName != NULL)
+            (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+        (*pkrb5_free_principal)(ctx, KRBv5Principal);
+        if (ctx != NULL)
+        {
+            if (cache != NULL)
+                pkrb5_cc_close(ctx, cache);
+        }
+
+        return(code);
+    }
+
+    if (!strcspn(PrincipalName, "@" ))
+    {
+        if (PrincipalName != NULL)
+            (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+        (*pkrb5_free_principal)(ctx, KRBv5Principal);
+        if (ctx != NULL)
+        {
+            if (cache != NULL)
+                pkrb5_cc_close(ctx, cache);
+        }
+
+        return(code);
+    }
+
+    if ( strcmp(ticketinfo->principal, PrincipalName) )
+        wsprintf(ticketinfo->principal, "%s", PrincipalName);
+
+    (*pkrb5_free_principal)(ctx, KRBv5Principal);
+    if ((code = pkrb5_cc_start_seq_get(ctx, cache, &KRBv5Cursor)))
+    {
+        functionName = "krb5_cc_start_seq_get()";
+        freeContextFlag = 1;
+        goto on_error;
+    }
+
+    memset(&KRBv5Credentials, '\0', sizeof(KRBv5Credentials));
+
+    while (!(code = pkrb5_cc_next_cred(ctx, cache, &KRBv5Cursor, &KRBv5Credentials)))
+    {
+        if (!list)
+        {
+            list = (TicketList*) calloc(1, sizeof(TicketList));
+            (*ticketList) = list;
+        }
+        else
+        {
+            list->next = (struct TicketList*) calloc(1, sizeof(TicketList));
+            list = (TicketList*) list->next;
+        }
+
+        if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.client, &ClientName))
+        {
+            (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+            Leash_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache);
+
+            if (ClientName != NULL)
+                (*pkrb5_free_unparsed_name)(ctx, ClientName);
+
+            ClientName = NULL;
+            sServerName = NULL;
+            continue;
+        }
+
+        if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName))
+        {
+            (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+            Leash_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache);
+
+            if (ClientName != NULL)
+                (*pkrb5_free_unparsed_name)(ctx, ClientName);
+
+            ClientName = NULL;
+            sServerName = NULL;
+            continue;
+        }
+
+        if (!KRBv5Credentials.times.starttime)
+            KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime;
+
+        fill = ' ';
+        memset(StartTimeString, '\0', sizeof(StartTimeString));
+        memset(EndTimeString, '\0', sizeof(EndTimeString));
+        memset(RenewTimeString, '\0', sizeof(RenewTimeString));
+        (*pkrb5_timestamp_to_sfstring)((krb5_timestamp)KRBv5Credentials.times.starttime, StartTimeString, 17, &fill);
+        (*pkrb5_timestamp_to_sfstring)((krb5_timestamp)KRBv5Credentials.times.endtime, EndTimeString, 17, &fill);
+               if (KRBv5Credentials.times.renew_till >= 0)
+                       (*pkrb5_timestamp_to_sfstring)((krb5_timestamp)KRBv5Credentials.times.renew_till, RenewTimeString, 17, &fill);
+        memset(temp, '\0', sizeof(temp));
+        memcpy(temp, StartTimeString, 2);
+        StartDay = atoi(temp);
+        memset(temp, (int)'\0', (size_t)sizeof(temp));
+        memcpy(temp, EndTimeString, 2);
+        EndDay = atoi(temp);
+        memset(temp, (int)'\0', (size_t)sizeof(temp));
+        memcpy(temp, RenewTimeString, 2);
+        RenewDay = atoi(temp);
+
+        memset(temp, '\0', sizeof(temp));
+        memcpy(temp, &StartTimeString[3], 2);
+        StartMonth = atoi(temp);
+        memset(temp, '\0', sizeof(temp));
+        memcpy(temp, &EndTimeString[3], 2);
+        EndMonth = atoi(temp);
+        memset(temp, '\0', sizeof(temp));
+        memcpy(temp, &RenewTimeString[3], 2);
+        RenewMonth = atoi(temp);
+
+        while (1)
+        {
+            if ((sPtr = strrchr(StartTimeString, ' ')) == NULL)
+                break;
+
+            if (strlen(sPtr) != 1)
+                break;
+
+            (*sPtr) = 0;
+        }
+
+        while (1)
+        {
+            if ((sPtr = strrchr(EndTimeString, ' ')) == NULL)
+                break;
+
+            if (strlen(sPtr) != 1)
+                break;
+
+            (*sPtr) = 0;
+        }
+
+        while (1)
+        {
+            if ((sPtr = strrchr(RenewTimeString, ' ')) == NULL)
+                break;
+
+            if (strlen(sPtr) != 1)
+                break;
+
+            (*sPtr) = 0;
+        }
+
+        memset(StartTime, '\0', sizeof(StartTime));
+        memcpy(StartTime, &StartTimeString[strlen(StartTimeString) - 5], 5);
+        memset(EndTime, '\0', sizeof(EndTime));
+        memcpy(EndTime, &EndTimeString[strlen(EndTimeString) - 5], 5);
+        memset(RenewTime, '\0', sizeof(RenewTime));
+        memcpy(RenewTime, &RenewTimeString[strlen(RenewTimeString) - 5], 5);
+
+        memset(temp, '\0', sizeof(temp));
+        strcpy(temp, ClientName);
+
+        if (!strcmp(ClientName, PrincipalName))
+            memset(temp, '\0', sizeof(temp));
+
+        memset(Buffer, '\0', sizeof(Buffer));
+
+        ticketFlag = GetTicketFlag(&KRBv5Credentials);
+
+        if (KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE) {
+            wsprintf(Buffer,"%s %02d %s     %s %02d %s     [%s %02d %s]     %s %s       %s",
+                      Months[StartMonth - 1], StartDay, StartTime,
+                      Months[EndMonth - 1], EndDay, EndTime,
+                      Months[RenewMonth - 1], RenewDay, RenewTime,
+                      sServerName,
+                      temp, ticketFlag);
+        } else {
+            wsprintf(Buffer,"%s %02d %s     %s %02d %s     %s %s       %s",
+                 Months[StartMonth - 1], StartDay, StartTime,
+                 Months[EndMonth - 1], EndDay, EndTime,
+                 sServerName,
+                 temp, ticketFlag);
+        }
+        list->theTicket = (char*) calloc(1, strlen(Buffer)+1);
+        if (!list->theTicket)
+        {
+            MessageBox(NULL, "Memory Error", "Error", MB_OK);
+            return ENOMEM;
+        }
+        strcpy(list->theTicket, Buffer);
+        list->name = NULL;
+        list->inst = NULL;
+        list->realm = NULL;
+
+        if ( !pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) {
+            wsprintf(Buffer, "Ticket Encryption Type: %s", etype_string(tkt->enc_part.enctype));
+            list->tktEncType = (char*) calloc(1, strlen(Buffer)+1);
+            if (!list->tktEncType)
+            {
+                MessageBox(NULL, "Memory Error", "Error", MB_OK);
+                return ENOMEM;
+            }
+            strcpy(list->tktEncType, Buffer);
+
+            pkrb5_free_ticket(ctx, tkt);
+            tkt = NULL;
+        } else {
+            list->tktEncType = NULL;
+        }
+
+        wsprintf(Buffer, "Session Key Type: %s", etype_string(KRBv5Credentials.keyblock.enctype));
+        list->keyEncType = (char*) calloc(1, strlen(Buffer)+1);
+        if (!list->keyEncType)
+        {
+            MessageBox(NULL, "Memory Error", "Error", MB_OK);
+            return ENOMEM;
+        }
+        strcpy(list->keyEncType, Buffer);
+
+        if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) {
+            int n = 0;
+            while ( KRBv5Credentials.addresses[n] )
+                               n++;
+            list->addrList = calloc(1, n * sizeof(char *));
+            if (!list->addrList) {
+                MessageBox(NULL, "Memory Error", "Error", MB_OK);
+                return ENOMEM;
+            }
+            list->addrCount = n;
+            for ( n=0; n<list->addrCount; n++ ) {
+                wsprintf(Buffer, "Address: %s", one_addr(KRBv5Credentials.addresses[n]));
+                list->addrList[n] = (char*) calloc(1, strlen(Buffer)+1);
+                if (!list->addrList[n])
+                {
+                    MessageBox(NULL, "Memory Error", "Error", MB_OK);
+                    return ENOMEM;
+                }
+                strcpy(list->addrList[n], Buffer);
+            }
+        }
+
+        ticketinfo->issue_date = KRBv5Credentials.times.starttime;
+        ticketinfo->lifetime = KRBv5Credentials.times.endtime - KRBv5Credentials.times.starttime;
+        ticketinfo->renew_till = KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE ?
+            KRBv5Credentials.times.renew_till : 0;
+        _tzset();
+        if ( ticketinfo->issue_date + ticketinfo->lifetime - time(0) <= 0L )
+            ticketinfo->btickets = EXPD_TICKETS;
+        else
+            ticketinfo->btickets = GOOD_TICKETS;
+
+       if (ClientName != NULL)
+            (*pkrb5_free_unparsed_name)(ctx, ClientName);
+
+        if (sServerName != NULL)
+            (*pkrb5_free_unparsed_name)(ctx, sServerName);
+
+        ClientName = NULL;
+        sServerName = NULL;
+        (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials);
+    }
+
+    if (PrincipalName != NULL)
+        (*pkrb5_free_unparsed_name)(ctx, PrincipalName);
+
+    if (ClientName != NULL)
+        (*pkrb5_free_unparsed_name)(ctx, ClientName);
+
+    if (sServerName != NULL)
+        (*pkrb5_free_unparsed_name)(ctx, sServerName);
+
+    if ((code == KRB5_CC_END) || (code == KRB5_CC_NOTFOUND))
+    {
+        if ((code = pkrb5_cc_end_seq_get(ctx, cache, &KRBv5Cursor)))
+        {
+            functionName = "krb5_cc_end_seq_get()";
+            freeContextFlag = 1;
+            goto on_error;
+        }
+
+        flags = KRB5_TC_OPENCLOSE;
+#ifdef KRB5_TC_NOTICKET
+        flags |= KRB5_TC_NOTICKET;
+#endif
+        if ((code = pkrb5_cc_set_flags(ctx, cache, flags)))
+        {
+            functionName = "krb5_cc_set_flags()";
+            freeContextFlag = 1;
+            goto on_error;
+        }
+    }
+    else
+    {
+        functionName = "krb5_cc_next_cred()";
+        freeContextFlag = 1;
+        goto on_error;
+    }
+
+    if (ctx != NULL)
+    {
+        if (cache != NULL)
+            pkrb5_cc_close(ctx, cache);
+    }
+
+    return(code);
+
+ on_error:
+
+    Leash_krb5_error(code, functionName, freeContextFlag, &(*krbv5Context), &cache);
+    return(code);
+#endif //!NO_KER5
+}
+
+
+int
+LeashKRB5_renew(void)
+{
+#ifdef NO_KRB5
+    return(0);
+#else
+    krb5_error_code                    code = 0;
+    krb5_context                       ctx = 0;
+    krb5_ccache                                cc = 0;
+    krb5_principal                     me = 0;
+    krb5_principal              server = 0;
+    krb5_creds                         my_creds;
+    krb5_data                   *realm = 0;
+
+    if ( !pkrb5_init_context )
+        goto cleanup;
+
+       memset(&my_creds, 0, sizeof(krb5_creds));
+
+    code = pkrb5_init_context(&ctx);
+    if (code) goto cleanup;
+
+    code = pkrb5_cc_default(ctx, &cc);
+    if (code) goto cleanup;
+
+    code = pkrb5_cc_get_principal(ctx, cc, &me);
+    if (code) goto cleanup;
+
+    realm = krb5_princ_realm(ctx, me);
+
+    code = pkrb5_build_principal_ext(ctx, &server,
+                                    realm->length,realm->data,
+                                    KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
+                                    realm->length,realm->data,
+                                    0);
+    if ( code ) goto cleanup;
+
+    my_creds.client = me;
+    my_creds.server = server;
+
+#ifdef KRB5_TC_NOTICKET
+    pkrb5_cc_set_flags(ctx, cc, 0);
+#endif
+    code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
+#ifdef KRB5_TC_NOTICKET
+    pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
+#endif
+    if (code) {
+        if ( code != KRB5KDC_ERR_ETYPE_NOSUPP ||
+             code != KRB5_KDC_UNREACH)
+            Leash_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
+        goto cleanup;
+    }
+
+    code = pkrb5_cc_initialize(ctx, cc, me);
+    if (code) goto cleanup;
+
+    code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+    if (code) goto cleanup;
+
+  cleanup:
+    if (my_creds.client == me)
+        my_creds.client = 0;
+    if (my_creds.server == server)
+        my_creds.server = 0;
+    pkrb5_free_cred_contents(ctx, &my_creds);
+    if (me)
+        pkrb5_free_principal(ctx, me);
+    if (server)
+        pkrb5_free_principal(ctx, server);
+    if (cc)
+        pkrb5_cc_close(ctx, cc);
+    if (ctx)
+        pkrb5_free_context(ctx);
+    return(code);
+#endif /* NO_KRB5 */
+}
+
+#ifndef NO_KRB5
+static krb5_error_code KRB5_CALLCONV
+leash_krb5_prompter( krb5_context context,
+                                        void *data,
+                                        const char *name,
+                                        const char *banner,
+                                        int num_prompts,
+                                        krb5_prompt prompts[]);
+#endif /* NO_KRB5 */
+
+int
+Leash_krb5_kinit(
+krb5_context alt_ctx,
+HWND hParent,
+char *principal_name,
+char *password,
+krb5_deltat lifetime,
+DWORD                       forwardable,
+DWORD                       proxiable,
+krb5_deltat                 renew_life,
+DWORD                       addressless,
+DWORD                       publicIP
+)
+{
+#ifdef NO_KRB5
+    return(0);
+#else
+    krb5_error_code                    code = 0;
+    krb5_context                       ctx = 0;
+    krb5_ccache                                cc = 0;
+    krb5_principal                     me = 0;
+    char*                       name = 0;
+    krb5_creds                         my_creds;
+    krb5_get_init_creds_opt     options;
+    krb5_address **             addrs = NULL;
+    int                         i = 0, addr_count = 0;
+
+    if (!pkrb5_init_context)
+        return 0;
+
+    pkrb5_get_init_creds_opt_init(&options);
+    memset(&my_creds, 0, sizeof(my_creds));
+
+    if (alt_ctx)
+    {
+        ctx = alt_ctx;
+    }
+    else
+    {
+        code = pkrb5_init_context(&ctx);
+        if (code) goto cleanup;
+    }
+
+    code = pkrb5_cc_default(ctx, &cc);
+    if (code) goto cleanup;
+
+    code = pkrb5_parse_name(ctx, principal_name, &me);
+    if (code) goto cleanup;
+
+    code = pkrb5_unparse_name(ctx, me, &name);
+    if (code) goto cleanup;
+
+    if (lifetime == 0)
+        lifetime = Leash_get_default_lifetime();
+    else
+        lifetime *= 5*60;
+
+       if (renew_life > 0)
+               renew_life *= 5*60;
+
+    if (lifetime)
+        pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
+       pkrb5_get_init_creds_opt_set_forwardable(&options,
+                                                 forwardable ? 1 : 0);
+       pkrb5_get_init_creds_opt_set_proxiable(&options,
+                                               proxiable ? 1 : 0);
+       pkrb5_get_init_creds_opt_set_renew_life(&options,
+                                               renew_life);
+    if (addressless)
+        pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
+    else {
+               if (publicIP)
+        {
+            // we are going to add the public IP address specified by the user
+            // to the list provided by the operating system
+            krb5_address ** local_addrs=NULL;
+            DWORD           netIPAddr;
+
+            pkrb5_os_localaddr(ctx, &local_addrs);
+            while ( local_addrs[i++] );
+            addr_count = i + 1;
+
+            addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
+            if ( !addrs ) {
+                pkrb5_free_addresses(ctx, local_addrs);
+                assert(0);
+            }
+            memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
+            i = 0;
+            while ( local_addrs[i] ) {
+                addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+                if (addrs[i] == NULL) {
+                    pkrb5_free_addresses(ctx, local_addrs);
+                    assert(0);
+                }
+
+                addrs[i]->magic = local_addrs[i]->magic;
+                addrs[i]->addrtype = local_addrs[i]->addrtype;
+                addrs[i]->length = local_addrs[i]->length;
+                addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+                if (!addrs[i]->contents) {
+                    pkrb5_free_addresses(ctx, local_addrs);
+                    assert(0);
+                }
+
+                memcpy(addrs[i]->contents,local_addrs[i]->contents,
+                        local_addrs[i]->length);        /* safe */
+                i++;
+            }
+            pkrb5_free_addresses(ctx, local_addrs);
+
+            addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
+            if (addrs[i] == NULL)
+                assert(0);
+
+            addrs[i]->magic = KV5M_ADDRESS;
+            addrs[i]->addrtype = AF_INET;
+            addrs[i]->length = 4;
+            addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+            if (!addrs[i]->contents)
+                assert(0);
+
+            netIPAddr = htonl(publicIP);
+            memcpy(addrs[i]->contents,&netIPAddr,4);
+
+            pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
+
+        }
+    }
+
+    code = pkrb5_get_init_creds_password(ctx,
+                                       &my_creds,
+                                       me,
+                                       password, // password
+                                       leash_krb5_prompter, // prompter
+                                       hParent, // prompter data
+                                       0, // start time
+                                       0, // service name
+                                       &options);
+    if (code) goto cleanup;
+
+    code = pkrb5_cc_initialize(ctx, cc, me);
+    if (code) goto cleanup;
+
+    code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
+    if (code) goto cleanup;
+
+ cleanup:
+    if ( addrs ) {
+        for ( i=0;i<addr_count;i++ ) {
+            if ( addrs[i] ) {
+                if ( addrs[i]->contents )
+                    free(addrs[i]->contents);
+                free(addrs[i]);
+            }
+        }
+    }
+    if (my_creds.client == me)
+       my_creds.client = 0;
+    pkrb5_free_cred_contents(ctx, &my_creds);
+    if (name)
+       pkrb5_free_unparsed_name(ctx, name);
+    if (me)
+       pkrb5_free_principal(ctx, me);
+    if (cc)
+       pkrb5_cc_close(ctx, cc);
+    if (ctx && (ctx != alt_ctx))
+       pkrb5_free_context(ctx);
+    return(code);
+#endif //!NO_KRB5
+}
+
+
+/**************************************/
+/* LeashKRB5destroyTicket():          */
+/**************************************/
+int
+Leash_krb5_kdestroy(
+    void
+    )
+{
+#ifdef NO_KRB5
+    return(0);
+#else
+    krb5_context               ctx;
+    krb5_ccache                        cache;
+    krb5_error_code            rc;
+
+    ctx = NULL;
+    cache = NULL;
+    if (rc = Leash_krb5_initialize(&ctx, &cache))
+        return(rc);
+
+    rc = pkrb5_cc_destroy(ctx, cache);
+
+    if (ctx != NULL)
+        pkrb5_free_context(ctx);
+
+    return(rc);
+
+#endif //!NO_KRB5
+}
+
+/**************************************/
+/* Leash_krb5_initialize():             */
+/**************************************/
+int Leash_krb5_initialize(krb5_context *ctx, krb5_ccache *cache)
+{
+#ifdef NO_KRB5
+    return(0);
+#else
+
+    LPCSTR          functionName;
+    int             freeContextFlag;
+    krb5_error_code    rc;
+    krb5_flags          flags;
+
+    if (pkrb5_init_context == NULL)
+        return 1;
+
+    if (*ctx == 0 && (rc = (*pkrb5_init_context)(ctx)))
+    {
+        functionName = "krb5_init_context()";
+        freeContextFlag = 0;
+        goto on_error;
+    }
+
+    if (*cache == 0 && (rc = pkrb5_cc_default(*ctx, cache)))
+    {
+        functionName = "krb5_cc_default()";
+        freeContextFlag = 1;
+        goto on_error;
+    }
+#ifdef KRB5_TC_NOTICKET
+    flags = KRB5_TC_NOTICKET;
+#endif
+    if ((rc = pkrb5_cc_set_flags(*ctx, *cache, flags)))
+    {
+        if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND)
+            Leash_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx,
+                                  cache);
+        else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL)
+        {
+            if (*cache != NULL)
+                pkrb5_cc_close(*ctx, *cache);
+        }
+        return rc;
+    }
+       return 0;
+
+  on_error:
+    return Leash_krb5_error(rc, functionName, freeContextFlag, ctx, cache);
+#endif //!NO_KRB5
+}
+
+
+/**************************************/
+/* Leash_krb5_error():           */
+/**************************************/
+int
+Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
+                 int FreeContextFlag, krb5_context * ctx,
+                 krb5_ccache * cache)
+{
+#ifdef NO_KRB5
+    return 0;
+#else
+    char message[256];
+    const char *errText;
+    int krb5Error = ((int)(rc & 255));
+
+    /*
+    switch (krb5Error)
+    {
+        // Wrong password
+        case 31:
+        case 8:
+            return;
+    }
+    */
+
+    errText = perror_message(rc);
+    _snprintf(message, sizeof(message),
+              "%s\n(Kerberos error %ld)\n\n%s failed",
+              errText,
+              krb5Error,
+              FailedFunctionName);
+
+    MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
+               MB_TASKMODAL |
+               MB_SETFOREGROUND);
+    if (FreeContextFlag == 1)
+    {
+        if (*ctx != NULL)
+        {
+            if (*cache != NULL) {
+                pkrb5_cc_close(*ctx, *cache);
+                *cache = NULL;
+            }
+
+            pkrb5_free_context(*ctx);
+            *ctx = NULL;
+        }
+    }
+
+    return rc;
+
+#endif //!NO_KRB5
+}
+
+
+BOOL
+Leash_ms2mit(BOOL save_creds)
+{
+#ifdef NO_KRB5
+    return(FALSE);
+#else /* NO_KRB5 */
+    krb5_context kcontext = 0;
+    krb5_error_code code;
+    krb5_ccache ccache=0;
+    krb5_ccache mslsa_ccache=0;
+    krb5_creds creds;
+    krb5_cc_cursor cursor=0;
+    krb5_principal princ = 0;
+    char *cache_name=NULL;
+    BOOL rc = FALSE;
+
+    if ( !pkrb5_init_context )
+        goto cleanup;
+
+    if (code = pkrb5_init_context(&kcontext))
+        goto cleanup;
+
+    if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache))
+        goto cleanup;
+
+    if ( save_creds ) {
+        if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))
+            goto cleanup;
+
+        if (code = pkrb5_cc_default(kcontext, &ccache))
+            goto cleanup;
+
+        if (code = pkrb5_cc_initialize(kcontext, ccache, princ))
+            goto cleanup;
+
+        if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))
+            goto cleanup;
+
+        rc = TRUE;
+    } else {
+        /* Enumerate tickets from cache looking for an initial ticket */
+        if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor)))
+            goto cleanup;
+
+        while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds)))
+        {
+            if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
+                rc = TRUE;
+                pkrb5_free_cred_contents(kcontext, &creds);
+                break;
+            }
+            pkrb5_free_cred_contents(kcontext, &creds);
+        }
+        pkrb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);
+    }
+
+  cleanup:
+    if (princ)
+        pkrb5_free_principal(kcontext, princ);
+    if (ccache)
+        pkrb5_cc_close(kcontext, ccache);
+    if (mslsa_ccache)
+        pkrb5_cc_close(kcontext, mslsa_ccache);
+    if (kcontext)
+        pkrb5_free_context(kcontext);
+    return(rc);
+#endif /* NO_KRB5 */
+}
+
+
+#ifndef NO_KRB5
+/* User Query data structures and functions */
+
+struct textField {
+    char * buf;                       /* Destination buffer address */
+    int    len;                       /* Destination buffer length */
+    char * label;                     /* Label for this field */
+    char * def;                       /* Default response for this field */
+    int    echo;                      /* 0 = no, 1 = yes, 2 = asterisks */
+};
+
+static int                mid_cnt = 0;
+static struct textField * mid_tb = NULL;
+
+#define ID_TEXT       150
+#define ID_MID_TEXT 300
+
+static BOOL CALLBACK
+MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    int i;
+
+    switch ( message ) {
+    case WM_INITDIALOG:
+        if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
+        {
+            SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
+            return FALSE;
+        }
+               for ( i=0; i < mid_cnt ; i++ ) {
+                       if (mid_tb[i].echo == 0)
+                               SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
+                   else if (mid_tb[i].echo == 2)
+                               SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
+               }
+        return TRUE;
+
+    case WM_COMMAND:
+        switch ( LOWORD(wParam) ) {
+        case IDOK:
+            for ( i=0; i < mid_cnt ; i++ ) {
+                if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
+                    *mid_tb[i].buf = '\0';
+            }
+            /* fallthrough */
+        case IDCANCEL:
+            EndDialog(hDialog, LOWORD(wParam));
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static LPWORD
+lpwAlign( LPWORD lpIn )
+{
+    ULONG ul;
+
+    ul = (ULONG) lpIn;
+    ul += 3;
+    ul >>=2;
+    ul <<=2;
+    return (LPWORD) ul;;
+}
+
+/*
+ * dialog widths are measured in 1/4 character widths
+ * dialog height are measured in 1/8 character heights
+ */
+
+static LRESULT
+MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
+                  char * ptext[], int numlines, int width,
+                  int tb_cnt, struct textField * tb)
+{
+    HGLOBAL hgbl;
+    LPDLGTEMPLATE lpdt;
+    LPDLGITEMTEMPLATE lpdit;
+    LPWORD lpw;
+    LPWSTR lpwsz;
+    LRESULT ret;
+    int nchar, i, pwid;
+
+    hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
+    if (!hgbl)
+        return -1;
+
+    mid_cnt = tb_cnt;
+    mid_tb = tb;
+
+    lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
+
+    // Define a dialog box.
+
+    lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
+                   | DS_MODALFRAME | WS_CAPTION | DS_CENTER
+                   | DS_SETFOREGROUND | DS_3DLOOK
+                   | DS_SHELLFONT | DS_NOFAILCREATE;
+    lpdt->cdit = numlines + (2 * tb_cnt) + 2;  // number of controls
+    lpdt->x  = 10;
+    lpdt->y  = 10;
+    lpdt->cx = 20 + width * 4;
+    lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
+
+    lpw = (LPWORD) (lpdt + 1);
+    *lpw++ = 0;   // no menu
+    *lpw++ = 0;   // predefined dialog box class (by default)
+
+    lpwsz = (LPWSTR) lpw;
+    nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
+    lpw   += nchar;
+    *lpw++ = 8;                        // font size (points)
+    lpwsz = (LPWSTR) lpw;
+    nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
+                                    -1, lpwsz, 128);
+    lpw   += nchar;
+
+    //-----------------------
+    // Define an OK button.
+    //-----------------------
+    lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
+    lpdit = (LPDLGITEMTEMPLATE) lpw;
+    lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
+    lpdit->dwExtendedStyle = 0;
+    lpdit->x  = (lpdt->cx - 14)/4 - 20;
+    lpdit->y  = 10 + (numlines + tb_cnt + 2) * 14;
+    lpdit->cx = 40;
+    lpdit->cy = 14;
+    lpdit->id = IDOK;  // OK button identifier
+
+    lpw = (LPWORD) (lpdit + 1);
+    *lpw++ = 0xFFFF;
+    *lpw++ = 0x0080;    // button class
+
+    lpwsz = (LPWSTR) lpw;
+    nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
+    lpw   += nchar;
+    *lpw++ = 0;           // no creation data
+
+    //-----------------------
+    // Define an Cancel button.
+    //-----------------------
+    lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
+    lpdit = (LPDLGITEMTEMPLATE) lpw;
+    lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
+    lpdit->dwExtendedStyle = 0;
+    lpdit->x  = (lpdt->cx - 14)*3/4 - 20;
+    lpdit->y  = 10 + (numlines + tb_cnt + 2) * 14;
+    lpdit->cx = 40;
+    lpdit->cy = 14;
+    lpdit->id = IDCANCEL;  // CANCEL button identifier
+
+    lpw = (LPWORD) (lpdit + 1);
+    *lpw++ = 0xFFFF;
+    *lpw++ = 0x0080;    // button class
+
+    lpwsz = (LPWSTR) lpw;
+    nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
+    lpw   += nchar;
+    *lpw++ = 0;           // no creation data
+
+    /* Add controls for preface data */
+    for ( i=0; i<numlines; i++) {
+        /*-----------------------
+         * Define a static text control.
+         *-----------------------*/
+        lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
+        lpdit = (LPDLGITEMTEMPLATE) lpw;
+        lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
+        lpdit->dwExtendedStyle = 0;
+        lpdit->x  = 10;
+        lpdit->y  = 10 + i * 14;
+        lpdit->cx = strlen(ptext[i]) * 4 + 10;
+        lpdit->cy = 14;
+        lpdit->id = ID_TEXT + i;  // text identifier
+
+        lpw = (LPWORD) (lpdit + 1);
+        *lpw++ = 0xFFFF;
+        *lpw++ = 0x0082;                         // static class
+
+        lpwsz = (LPWSTR) lpw;
+        nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
+                                         -1, lpwsz, 2*width);
+        lpw   += nchar;
+        *lpw++ = 0;           // no creation data
+    }
+
+    for ( i=0, pwid = 0; i<tb_cnt; i++) {
+        if ( pwid < strlen(tb[i].label) )
+            pwid = strlen(tb[i].label);
+    }
+
+    for ( i=0; i<tb_cnt; i++) {
+        /* Prompt */
+        /*-----------------------
+         * Define a static text control.
+         *-----------------------*/
+        lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
+        lpdit = (LPDLGITEMTEMPLATE) lpw;
+        lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
+        lpdit->dwExtendedStyle = 0;
+        lpdit->x  = 10;
+        lpdit->y  = 10 + (numlines + i + 1) * 14;
+        lpdit->cx = pwid * 4;
+        lpdit->cy = 14;
+        lpdit->id = ID_TEXT + numlines + i;  // text identifier
+
+        lpw = (LPWORD) (lpdit + 1);
+        *lpw++ = 0xFFFF;
+        *lpw++ = 0x0082;                         // static class
+
+        lpwsz = (LPWSTR) lpw;
+        nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
+                                     -1, lpwsz, 128);
+        lpw   += nchar;
+        *lpw++ = 0;           // no creation data
+
+        /*-----------------------
+         * Define an edit control.
+         *-----------------------*/
+        lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
+        lpdit = (LPDLGITEMTEMPLATE) lpw;
+        lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
+        lpdit->dwExtendedStyle = 0;
+        lpdit->x  = 10 + (pwid + 1) * 4;
+        lpdit->y  = 10 + (numlines + i + 1) * 14;
+        lpdit->cx = (width - (pwid + 1)) * 4;
+        lpdit->cy = 14;
+        lpdit->id = ID_MID_TEXT + i;             // identifier
+
+        lpw = (LPWORD) (lpdit + 1);
+        *lpw++ = 0xFFFF;
+        *lpw++ = 0x0081;                         // edit class
+
+        lpwsz = (LPWSTR) lpw;
+        nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
+                                     -1, lpwsz, 128);
+        lpw   += nchar;
+        *lpw++ = 0;           // no creation data
+    }
+
+    GlobalUnlock(hgbl);
+    ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
+                                                       hwndOwner, (DLGPROC) MultiInputDialogProc);
+    GlobalFree(hgbl);
+
+    switch ( ret ) {
+    case 0:     /* Timeout */
+        return -1;
+    case IDOK:
+        return 1;
+    case IDCANCEL:
+        return 0;
+    default: {
+        char buf[256];
+        sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
+        MessageBox(hwndOwner,
+                    buf,
+                    "GetLastError()",
+                    MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+        return -1;
+    }
+    }
+}
+
+static int
+multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
+{
+       extern HINSTANCE hLeashInst;
+    int maxwidth = 0;
+    int numlines = 0;
+    int len;
+    char * plines[16], *p = preface ? preface : "";
+    int i;
+
+    for ( i=0; i<16; i++ )
+        plines[i] = NULL;
+
+    while (*p && numlines < 16) {
+        plines[numlines++] = p;
+        for ( ;*p && *p != '\r' && *p != '\n'; p++ );
+        if ( *p == '\r' && *(p+1) == '\n' ) {
+            *p++ = '\0';
+            p++;
+        } else if ( *p == '\n' ) {
+            *p++ = '\0';
+        }
+        if ( strlen(plines[numlines-1]) > maxwidth )
+            maxwidth = strlen(plines[numlines-1]);
+    }
+
+    for ( i=0;i<n;i++ ) {
+        len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
+        if ( maxwidth < len )
+            maxwidth = len;
+    }
+
+    return(MultiInputDialog(hLeashInst, hParent, plines, numlines, maxwidth, n, tb));
+}
+
+static krb5_error_code KRB5_CALLCONV
+leash_krb5_prompter( krb5_context context,
+                                        void *data,
+                                        const char *name,
+                                        const char *banner,
+                                        int num_prompts,
+                                        krb5_prompt prompts[])
+{
+    krb5_error_code     errcode = 0;
+    int                 i;
+    struct textField * tb = NULL;
+    int    len = 0, blen=0, nlen=0;
+       HWND hParent = (HWND)data;
+
+    if (name)
+        nlen = strlen(name)+2;
+
+    if (banner)
+        blen = strlen(banner)+2;
+
+    tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
+    if ( tb != NULL ) {
+        int ok;
+        memset(tb,0,sizeof(struct textField) * num_prompts);
+        for ( i=0; i < num_prompts; i++ ) {
+            tb[i].buf = prompts[i].reply->data;
+            tb[i].len = prompts[i].reply->length;
+            tb[i].label = prompts[i].prompt;
+            tb[i].def = NULL;
+            tb[i].echo = (prompts[i].hidden ? 2 : 1);
+        }
+
+        ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
+        if ( ok ) {
+            for ( i=0; i < num_prompts; i++ )
+                prompts[i].reply->length = strlen(prompts[i].reply->data);
+        } else
+            errcode = -2;
+    }
+
+    if ( tb )
+        free(tb);
+    if (errcode) {
+        for (i = 0; i < num_prompts; i++) {
+            memset(prompts[i].reply->data, 0, prompts[i].reply->length);
+        }
+    }
+    return errcode;
+}
+#endif /* NO_KRB5 */
\ No newline at end of file
diff --git a/src/windows/leashdll/leash-int.h b/src/windows/leashdll/leash-int.h
new file mode 100644 (file)
index 0000000..fb7617e
--- /dev/null
@@ -0,0 +1,357 @@
+#ifndef __LEASH_INT_H__
+#define __LEASH_INT_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "leashdll.h"
+#include <leashwin.h>
+
+#include "tlhelp32.h"
+
+#define MIT_PWD_DLL_CLASS "MITPasswordWndDLL"
+
+BOOL
+Register_MITPasswordEditControl(
+    HINSTANCE hInst
+    );
+
+BOOL
+Unregister_MITPasswordEditControl(
+    HINSTANCE hInst
+    );
+
+// Some defines swiped from leash.h
+//  These are necessary but they must be kept sync'ed with leash.h
+#define HELPFILE "leash32.hlp"
+extern char KRB_HelpFile[_MAX_PATH];
+
+// Function Prototypes.
+int lsh_com_err_proc (LPSTR whoami, long code, LPSTR fmt, va_list args);
+int DoNiftyErrorReport(long errnum, LPSTR what);
+LONG Leash_timesync(int);
+BOOL Leash_ms2mit(BOOL);
+
+#ifndef NO_AFS
+int      not_an_API_LeashAFSGetToken(TICKETINFO * ticketinfo, TicketList** ticketList, char * kprinc);
+long FAR not_an_API_LeashFreeTicketList(TicketList** ticketList) ;
+#endif
+
+// Crap...
+#include <krb5.h>
+
+long
+Leash_int_kinit_ex(
+    krb5_context ctx,
+    HWND hParent,
+    char * principal,
+    char * password,
+    int lifetime,
+    int forwardable,
+    int proxiable,
+    int renew_life,
+    int addressless,
+    unsigned long publicIP,
+    int displayErrors
+    );
+
+long
+Leash_int_checkpwd(
+    char * principal,
+    char * password,
+    int    displayErrors
+    );
+
+long
+Leash_int_changepwd(
+    char * principal,
+    char * password,
+    char * newpassword,
+    char** result_string,
+    int    displayErrors
+    );
+
+int
+Leash_krb5_kdestroy(
+    void
+    );
+
+int
+Leash_krb5_kinit(
+    krb5_context,
+    HWND hParent,
+    char * principal_name,
+    char * password,
+    krb5_deltat lifetime,
+    DWORD       forwardable,
+    DWORD       proxiable,
+    krb5_deltat renew_life,
+    DWORD       addressless,
+    DWORD       publicIP
+    );
+
+long
+Leash_convert524(
+    krb5_context ctx
+    );
+
+int
+Leash_afs_unlog(
+    void
+    );
+
+int
+Leash_afs_klog(
+    char *,
+    char *,
+    char *,
+    int
+    );
+
+int
+LeashKRB5_renew(void);
+
+LONG
+write_registry_setting(
+    char* setting,
+    DWORD type,
+    void* buffer,
+    size_t size
+    );
+
+LONG
+read_registry_setting_user(
+    char* setting,
+    void* buffer,
+    size_t size
+    );
+
+LONG
+read_registry_setting(
+    char* setting,
+    void* buffer,
+    size_t size
+    );
+
+BOOL
+get_STRING_from_registry(
+    HKEY hBaseKey,
+    char * key,
+    char * value,
+    char * outbuf,
+    DWORD  outlen
+    );
+
+BOOL
+get_DWORD_from_registry(
+    HKEY hBaseKey,
+    char * key,
+    char * value,
+    DWORD * result
+    );
+
+int
+config_boolean_to_int(
+    const char *s
+    );
+
+BOOL GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData);
+BOOL IsKerberosLogon(VOID);
+
+#ifndef NO_KRB5
+int Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
+                     int FreeContextFlag, krb5_context *ctx,
+                     krb5_ccache *cache);
+int Leash_krb5_initialize(krb5_context *, krb5_ccache *);
+#endif /* NO_KRB5 */
+
+LPSTR err_describe(LPSTR buf, long code);
+
+// toolhelp functions
+TYPEDEF_FUNC(
+    HANDLE,
+    WINAPI,
+    CreateToolhelp32Snapshot,
+    (DWORD, DWORD)
+    );
+TYPEDEF_FUNC(
+    BOOL,
+    WINAPI,
+    Module32First,
+    (HANDLE, LPMODULEENTRY32)
+    );
+TYPEDEF_FUNC(
+    BOOL,
+    WINAPI,
+    Module32Next,
+    (HANDLE, LPMODULEENTRY32)
+    );
+
+// psapi functions
+TYPEDEF_FUNC(
+    DWORD,
+    WINAPI,
+    GetModuleFileNameExA,
+    (HANDLE, HMODULE, LPSTR, DWORD)
+    );
+TYPEDEF_FUNC(
+    BOOL,
+    WINAPI,
+    EnumProcessModules,
+    (HANDLE, HMODULE*, DWORD, LPDWORD)
+    );
+
+#define pGetModuleFileNameEx pGetModuleFileNameExA
+#define TOOLHELPDLL "kernel32.dll"
+#define PSAPIDLL "psapi.dll"
+
+// psapi functions
+extern DECL_FUNC_PTR(GetModuleFileNameExA);
+extern DECL_FUNC_PTR(EnumProcessModules);
+
+// toolhelp functions
+extern DECL_FUNC_PTR(CreateToolhelp32Snapshot);
+extern DECL_FUNC_PTR(Module32First);
+extern DECL_FUNC_PTR(Module32Next);
+
+/* In order to avoid including the private CCAPI headers */
+typedef int cc_int32;
+
+#define CC_API_VER_1 1
+#define CC_API_VER_2 2
+
+#define CCACHE_API cc_int32
+
+/*
+** The Official Error Codes
+*/
+#define CC_NOERROR           0
+#define CC_BADNAME           1
+#define CC_NOTFOUND          2
+#define CC_END               3
+#define CC_IO                4
+#define CC_WRITE             5
+#define CC_NOMEM             6
+#define CC_FORMAT            7
+#define CC_LOCKED            8
+#define CC_BAD_API_VERSION   9
+#define CC_NO_EXIST          10
+#define CC_NOT_SUPP          11
+#define CC_BAD_PARM          12
+#define CC_ERR_CACHE_ATTACH  13
+#define CC_ERR_CACHE_RELEASE 14
+#define CC_ERR_CACHE_FULL    15
+#define CC_ERR_CRED_VERSION  16
+
+enum {
+    CC_CRED_VUNKNOWN = 0,       // For validation
+    CC_CRED_V4 = 1,
+    CC_CRED_V5 = 2,
+    CC_CRED_VMAX = 3            // For validation
+};
+
+typedef struct opaque_dll_control_block_type* apiCB;
+typedef struct _infoNC {
+    char*     name;
+    char*     principal;
+    cc_int32  vers;
+} infoNC;
+
+TYPEDEF_FUNC(
+CCACHE_API,
+__cdecl,
+cc_initialize,
+    (
+    apiCB** cc_ctx,           // <  DLL's primary control structure.
+                              //    returned here, passed everywhere else
+    cc_int32 api_version,     // >  ver supported by caller (use CC_API_VER_1)
+    cc_int32*  api_supported, // <  if ~NULL, max ver supported by DLL
+    const char** vendor       // <  if ~NULL, vendor name in read only C string
+    )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+__cdecl,
+cc_shutdown,
+    (
+    apiCB** cc_ctx            // <> DLL's primary control structure. NULL after
+    )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+__cdecl,
+cc_get_NC_info,
+    (
+    apiCB* cc_ctx,          // >  DLL's primary control structure
+    struct _infoNC*** ppNCi // <  (NULL before call) null terminated,
+                            //    list of a structs (free via cc_free_infoNC())
+    )
+);
+
+TYPEDEF_FUNC(
+CCACHE_API,
+__cdecl,
+cc_free_NC_info,
+    (
+    apiCB* cc_ctx,
+    struct _infoNC*** ppNCi // <  free list of structs returned by
+                            //    cc_get_cache_names().  set to NULL on return
+    )
+);
+#define CCAPI_DLL   "krbcc32.dll"
+
+/* The following definitions are summarized from KRB4, KRB5, Leash32, and
+ * Leashw32 modules.  They are current as of KfW 2.6.2.  There is no
+ * guarrantee that changes to other modules will be updated in this list.
+ */
+
+/* Must match the values used in Leash32.exe */
+#define LEASH_SETTINGS_REGISTRY_KEY_NAME "Software\\MIT\\Leash32\\Settings"
+#define LEASH_SETTINGS_REGISTRY_VALUE_AFS_STATUS       "AfsStatus"
+#define LEASH_SETTINGS_REGISTRY_VALUE_DEBUG_WINDOW     "DebugWindow"
+#define LEASH_SETTINGS_REGISTRY_VALUE_LARGE_ICONS      "LargeIcons"
+#define LEASH_SETTINGS_REGISTRY_VALUE_DESTROY_TKTS     "DestroyTickets"
+#define LEASH_SETTINGS_REGISTRY_VALUE_LOW_TKT_ALARM    "LowTicketAlarm"
+#define LEASH_SETTINGS_REGISTRY_VALUE_AUTO_RENEW_TKTS  "AutoRenewTickets"
+#define LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM   "UpperCaseRealm"
+#define LEASH_SETTINGS_REGISTRY_VALUE_TIMEHOST         "TIMEHOST"
+#define LEASH_SETTINGS_REGISTRY_VALUE_CREATE_MISSING_CFG "CreateMissingConfig"
+#define LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT     "MsLsaImport"
+
+/* These values are defined and used within Leashw32.dll */
+#define LEASH_REGISTRY_KEY_NAME "Software\\MIT\\Leash"
+#define LEASH_REGISTRY_VALUE_LIFETIME "lifetime"
+#define LEASH_REGISTRY_VALUE_RENEW_TILL "renew_till"
+#define LEASH_REGISTRY_VALUE_RENEWABLE "renewable"
+#define LEASH_REGISTRY_VALUE_FORWARDABLE "forwardable"
+#define LEASH_REGISTRY_VALUE_NOADDRESSES "noaddresses"
+#define LEASH_REGISTRY_VALUE_PROXIABLE "proxiable"
+#define LEASH_REGISTRY_VALUE_PUBLICIP "publicip"
+#define LEASH_REGISTRY_VALUE_USEKRB4 "usekrb4"
+#define LEASH_REGISTRY_VALUE_KINIT_OPT "hide_kinit_options"
+#define LEASH_REGISTRY_VALUE_LIFE_MIN "life_min"
+#define LEASH_REGISTRY_VALUE_LIFE_MAX "life_max"
+#define LEASH_REGISTRY_VALUE_RENEW_MIN "renew_min"
+#define LEASH_REGISTRY_VALUE_RENEW_MAX "renew_max"
+#define LEASH_REGISTRY_VALUE_LOCK_LOCATION "lock_file_locations"
+#define LEASH_REGISTRY_VALUE_PRESERVE_KINIT "preserve_kinit_options"
+
+/* must match values used within krbv4w32.dll */
+#define KRB4_REGISTRY_KEY_NAME "Software\\MIT\\Kerberos4"
+#define KRB4_REGISTRY_VALUE_CONFIGFILE  "config"
+#define KRB4_REGISTRY_VALUE_KRB_CONF    "krb.conf"
+#define KRB4_REGISTRY_VALUE_KRB_REALMS  "krb.realms"
+#define KRB4_REGISTRY_VALUE_TICKETFILE  "ticketfile"
+
+/* must match values used within krb5_32.dll */
+#define KRB5_REGISTRY_KEY_NAME "Software\\MIT\\Kerberos5"
+#define KRB5_REGISTRY_VALUE_CCNAME      "ccname"
+#define KRB5_REGISTRY_VALUE_CONFIGFILE  "config"
+
+/* must match values used within wshelper.dll */
+#define WSHELP_REGISTRY_KEY_NAME  "Software\\MIT\\WsHelper"
+#define WSHELP_REGISTRY_VALUE_DEBUG   "DebugOn"
+
+#endif /* __LEASH_INT_H__ */
diff --git a/src/windows/leashdll/leashdll.c b/src/windows/leashdll/leashdll.c
new file mode 100644 (file)
index 0000000..f5e2653
--- /dev/null
@@ -0,0 +1,444 @@
+#include <windows.h>
+#include "leashdll.h"
+#include <krb.h>
+#include <leashwin.h>
+#include "leash-int.h"
+
+HINSTANCE hLeashInst;
+
+#ifndef NO_KRB4
+HINSTANCE hKrb4 = 0;
+#endif
+HINSTANCE hKrb5 = 0;
+HINSTANCE hKrb524 = 0;
+HINSTANCE hSecur32 = 0;
+HINSTANCE hComErr = 0;
+HINSTANCE hService = 0;
+HINSTANCE hProfile = 0;
+HINSTANCE hPsapi = 0;
+HINSTANCE hToolHelp32 = 0;
+HINSTANCE hCcapi = 0;
+
+DWORD     AfsAvailable = 0;
+
+#ifndef NO_KRB4
+// krb4 functions
+DECL_FUNC_PTR(get_krb_err_txt_entry);
+DECL_FUNC_PTR(k_isinst);
+DECL_FUNC_PTR(k_isname);
+DECL_FUNC_PTR(k_isrealm);
+DECL_FUNC_PTR(kadm_change_your_password);
+DECL_FUNC_PTR(kname_parse);
+DECL_FUNC_PTR(krb_get_cred);
+DECL_FUNC_PTR(krb_get_krbhst);
+DECL_FUNC_PTR(krb_get_lrealm);
+DECL_FUNC_PTR(krb_get_pw_in_tkt);
+DECL_FUNC_PTR(krb_get_tf_realm);
+DECL_FUNC_PTR(krb_mk_req);
+DECL_FUNC_PTR(krb_realmofhost);
+DECL_FUNC_PTR(tf_init);
+DECL_FUNC_PTR(tf_close);
+DECL_FUNC_PTR(tf_get_cred);
+DECL_FUNC_PTR(tf_get_pname);
+DECL_FUNC_PTR(tf_get_pinst);
+DECL_FUNC_PTR(LocalHostAddr);
+DECL_FUNC_PTR(tkt_string);
+DECL_FUNC_PTR(krb_set_tkt_string);
+DECL_FUNC_PTR(initialize_krb_error_func);
+DECL_FUNC_PTR(initialize_kadm_error_table);
+DECL_FUNC_PTR(dest_tkt);
+DECL_FUNC_PTR(lsh_LoadKrb4LeashErrorTables); // XXX
+DECL_FUNC_PTR(krb_in_tkt);
+DECL_FUNC_PTR(krb_save_credentials);
+DECL_FUNC_PTR(krb_get_krbconf2);
+DECL_FUNC_PTR(krb_get_krbrealm2);
+DECL_FUNC_PTR(krb_life_to_time);
+#endif
+
+// krb5 functions
+DECL_FUNC_PTR(krb5_change_password);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
+DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
+DECL_FUNC_PTR(krb5_get_init_creds_password);
+DECL_FUNC_PTR(krb5_build_principal_ext);
+DECL_FUNC_PTR(krb5_cc_resolve);
+DECL_FUNC_PTR(krb5_cc_default);
+DECL_FUNC_PTR(krb5_cc_default_name);
+DECL_FUNC_PTR(krb5_cc_set_default_name);
+DECL_FUNC_PTR(krb5_cc_initialize);
+DECL_FUNC_PTR(krb5_cc_destroy);
+DECL_FUNC_PTR(krb5_cc_close);
+DECL_FUNC_PTR(krb5_cc_store_cred);
+DECL_FUNC_PTR(krb5_cc_copy_creds);
+// DECL_FUNC_PTR(krb5_cc_retrieve_cred);
+DECL_FUNC_PTR(krb5_cc_get_principal);
+DECL_FUNC_PTR(krb5_cc_start_seq_get);
+DECL_FUNC_PTR(krb5_cc_next_cred);
+DECL_FUNC_PTR(krb5_cc_end_seq_get);
+// DECL_FUNC_PTR(krb5_cc_remove_cred);
+DECL_FUNC_PTR(krb5_cc_set_flags);
+// DECL_FUNC_PTR(krb5_cc_get_type);
+DECL_FUNC_PTR(krb5_free_context);
+DECL_FUNC_PTR(krb5_free_cred_contents);
+DECL_FUNC_PTR(krb5_free_principal);
+DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
+DECL_FUNC_PTR(krb5_init_context);
+DECL_FUNC_PTR(krb5_parse_name);
+DECL_FUNC_PTR(krb5_timeofday);
+DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
+DECL_FUNC_PTR(krb5_unparse_name);
+DECL_FUNC_PTR(krb5_get_credentials);
+DECL_FUNC_PTR(krb5_mk_req);
+DECL_FUNC_PTR(krb5_sname_to_principal);
+DECL_FUNC_PTR(krb5_get_credentials_renew);
+DECL_FUNC_PTR(krb5_free_data);
+DECL_FUNC_PTR(krb5_free_data_contents);
+// DECL_FUNC_PTR(krb5_get_realm_domain);
+DECL_FUNC_PTR(krb5_free_unparsed_name);
+DECL_FUNC_PTR(krb5_os_localaddr);
+DECL_FUNC_PTR(krb5_copy_keyblock_contents);
+DECL_FUNC_PTR(krb5_copy_data);
+DECL_FUNC_PTR(krb5_free_creds);
+DECL_FUNC_PTR(krb5_build_principal);
+DECL_FUNC_PTR(krb5_get_renewed_creds);
+DECL_FUNC_PTR(krb5_get_default_config_files);
+DECL_FUNC_PTR(krb5_free_config_files);
+DECL_FUNC_PTR(krb5_get_default_realm);
+DECL_FUNC_PTR(krb5_free_ticket);
+DECL_FUNC_PTR(krb5_decode_ticket);
+DECL_FUNC_PTR(krb5_get_host_realm);
+DECL_FUNC_PTR(krb5_free_host_realm);
+DECL_FUNC_PTR(krb5_c_random_make_octets);
+DECL_FUNC_PTR(krb5_free_addresses);
+DECL_FUNC_PTR(krb5_free_default_realm);
+DECL_FUNC_PTR(krb5_principal_compare);
+DECL_FUNC_PTR(krb5_string_to_deltat);
+
+#ifndef NO_KRB4
+// Krb524 functions
+DECL_FUNC_PTR(krb524_init_ets);
+DECL_FUNC_PTR(krb524_convert_creds_kdc);
+#endif
+
+// ComErr functions
+DECL_FUNC_PTR(com_err);
+DECL_FUNC_PTR(error_message);
+
+// Profile functions
+DECL_FUNC_PTR(profile_init);
+DECL_FUNC_PTR(profile_release);
+DECL_FUNC_PTR(profile_get_subsection_names);
+DECL_FUNC_PTR(profile_free_list);
+DECL_FUNC_PTR(profile_get_string);
+DECL_FUNC_PTR(profile_release_string);
+DECL_FUNC_PTR(profile_get_integer);
+
+// Service functions
+DECL_FUNC_PTR(OpenSCManagerA);
+DECL_FUNC_PTR(OpenServiceA);
+DECL_FUNC_PTR(QueryServiceStatus);
+DECL_FUNC_PTR(CloseServiceHandle);
+DECL_FUNC_PTR(LsaNtStatusToWinError);
+
+// LSA Functions
+DECL_FUNC_PTR(LsaConnectUntrusted);
+DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
+DECL_FUNC_PTR(LsaCallAuthenticationPackage);
+DECL_FUNC_PTR(LsaFreeReturnBuffer);
+DECL_FUNC_PTR(LsaGetLogonSessionData);
+
+// CCAPI Functions
+DECL_FUNC_PTR(cc_initialize);
+DECL_FUNC_PTR(cc_shutdown);
+DECL_FUNC_PTR(cc_get_NC_info);
+DECL_FUNC_PTR(cc_free_NC_info);
+
+#ifndef NO_KRB4
+FUNC_INFO k4_fi[] = {
+    MAKE_FUNC_INFO(get_krb_err_txt_entry),
+    MAKE_FUNC_INFO(k_isinst),
+    MAKE_FUNC_INFO(k_isname),
+    MAKE_FUNC_INFO(k_isrealm),
+    MAKE_FUNC_INFO(kadm_change_your_password),
+    MAKE_FUNC_INFO(kname_parse),
+    MAKE_FUNC_INFO(krb_get_cred),
+    MAKE_FUNC_INFO(krb_get_krbhst),
+    MAKE_FUNC_INFO(krb_get_lrealm),
+    MAKE_FUNC_INFO(krb_get_pw_in_tkt),
+    MAKE_FUNC_INFO(krb_get_tf_realm),
+    MAKE_FUNC_INFO(krb_mk_req),
+    MAKE_FUNC_INFO(krb_realmofhost),
+    MAKE_FUNC_INFO(tf_init),
+    MAKE_FUNC_INFO(tf_close),
+    MAKE_FUNC_INFO(tf_get_cred),
+    MAKE_FUNC_INFO(tf_get_pname),
+    MAKE_FUNC_INFO(tf_get_pinst),
+    MAKE_FUNC_INFO(LocalHostAddr),
+    MAKE_FUNC_INFO(tkt_string),
+    MAKE_FUNC_INFO(krb_set_tkt_string),
+    MAKE_FUNC_INFO(initialize_krb_error_func),
+    MAKE_FUNC_INFO(initialize_kadm_error_table),
+    MAKE_FUNC_INFO(dest_tkt),
+    MAKE_FUNC_INFO(lsh_LoadKrb4LeashErrorTables), // XXX
+    MAKE_FUNC_INFO(krb_in_tkt),
+    MAKE_FUNC_INFO(krb_save_credentials),
+    MAKE_FUNC_INFO(krb_get_krbconf2),
+    MAKE_FUNC_INFO(krb_get_krbrealm2),
+    MAKE_FUNC_INFO(krb_life_to_time),
+    END_FUNC_INFO
+};
+#endif
+
+FUNC_INFO k5_fi[] = {
+    MAKE_FUNC_INFO(krb5_change_password),
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
+    MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
+    MAKE_FUNC_INFO(krb5_get_init_creds_password),
+    MAKE_FUNC_INFO(krb5_build_principal_ext),
+    MAKE_FUNC_INFO(krb5_cc_resolve),
+    MAKE_FUNC_INFO(krb5_cc_default),
+    MAKE_FUNC_INFO(krb5_cc_default_name),
+    MAKE_FUNC_INFO(krb5_cc_set_default_name),
+    MAKE_FUNC_INFO(krb5_cc_initialize),
+    MAKE_FUNC_INFO(krb5_cc_destroy),
+    MAKE_FUNC_INFO(krb5_cc_close),
+    MAKE_FUNC_INFO(krb5_cc_copy_creds),
+    MAKE_FUNC_INFO(krb5_cc_store_cred),
+// MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
+    MAKE_FUNC_INFO(krb5_cc_get_principal),
+    MAKE_FUNC_INFO(krb5_cc_start_seq_get),
+    MAKE_FUNC_INFO(krb5_cc_next_cred),
+    MAKE_FUNC_INFO(krb5_cc_end_seq_get),
+// MAKE_FUNC_INFO(krb5_cc_remove_cred),
+    MAKE_FUNC_INFO(krb5_cc_set_flags),
+// MAKE_FUNC_INFO(krb5_cc_get_type),
+    MAKE_FUNC_INFO(krb5_free_context),
+    MAKE_FUNC_INFO(krb5_free_cred_contents),
+    MAKE_FUNC_INFO(krb5_free_principal),
+    MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
+    MAKE_FUNC_INFO(krb5_init_context),
+    MAKE_FUNC_INFO(krb5_parse_name),
+    MAKE_FUNC_INFO(krb5_timeofday),
+    MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
+    MAKE_FUNC_INFO(krb5_unparse_name),
+    MAKE_FUNC_INFO(krb5_get_credentials),
+    MAKE_FUNC_INFO(krb5_mk_req),
+    MAKE_FUNC_INFO(krb5_sname_to_principal),
+    MAKE_FUNC_INFO(krb5_get_credentials_renew),
+    MAKE_FUNC_INFO(krb5_free_data),
+    MAKE_FUNC_INFO(krb5_free_data_contents),
+//  MAKE_FUNC_INFO(krb5_get_realm_domain),
+    MAKE_FUNC_INFO(krb5_free_unparsed_name),
+    MAKE_FUNC_INFO(krb5_os_localaddr),
+    MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
+    MAKE_FUNC_INFO(krb5_copy_data),
+    MAKE_FUNC_INFO(krb5_free_creds),
+    MAKE_FUNC_INFO(krb5_build_principal),
+    MAKE_FUNC_INFO(krb5_get_renewed_creds),
+    MAKE_FUNC_INFO(krb5_free_addresses),
+    MAKE_FUNC_INFO(krb5_get_default_config_files),
+    MAKE_FUNC_INFO(krb5_free_config_files),
+    MAKE_FUNC_INFO(krb5_get_default_realm),
+    MAKE_FUNC_INFO(krb5_free_ticket),
+    MAKE_FUNC_INFO(krb5_decode_ticket),
+    MAKE_FUNC_INFO(krb5_get_host_realm),
+    MAKE_FUNC_INFO(krb5_free_host_realm),
+    MAKE_FUNC_INFO(krb5_c_random_make_octets),
+    MAKE_FUNC_INFO(krb5_free_default_realm),
+    MAKE_FUNC_INFO(krb5_principal_compare),
+    MAKE_FUNC_INFO(krb5_string_to_deltat),
+    END_FUNC_INFO
+};
+
+#ifndef NO_KRB4
+FUNC_INFO k524_fi[] = {
+    MAKE_FUNC_INFO(krb524_init_ets),
+    MAKE_FUNC_INFO(krb524_convert_creds_kdc),
+    END_FUNC_INFO
+};
+#endif
+
+FUNC_INFO profile_fi[] = {
+    MAKE_FUNC_INFO(profile_init),
+    MAKE_FUNC_INFO(profile_release),
+    MAKE_FUNC_INFO(profile_get_subsection_names),
+    MAKE_FUNC_INFO(profile_free_list),
+    MAKE_FUNC_INFO(profile_get_string),
+    MAKE_FUNC_INFO(profile_release_string),
+    MAKE_FUNC_INFO(profile_get_integer),
+    END_FUNC_INFO
+};
+
+FUNC_INFO ce_fi[] = {
+    MAKE_FUNC_INFO(com_err),
+    MAKE_FUNC_INFO(error_message),
+    END_FUNC_INFO
+};
+
+FUNC_INFO service_fi[] = {
+    MAKE_FUNC_INFO(OpenSCManagerA),
+    MAKE_FUNC_INFO(OpenServiceA),
+    MAKE_FUNC_INFO(QueryServiceStatus),
+    MAKE_FUNC_INFO(CloseServiceHandle),
+    MAKE_FUNC_INFO(LsaNtStatusToWinError),
+    END_FUNC_INFO
+};
+
+FUNC_INFO lsa_fi[] = {
+    MAKE_FUNC_INFO(LsaConnectUntrusted),
+    MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
+    MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
+    MAKE_FUNC_INFO(LsaFreeReturnBuffer),
+    MAKE_FUNC_INFO(LsaGetLogonSessionData),
+    END_FUNC_INFO
+};
+
+// CCAPI v2
+FUNC_INFO ccapi_fi[] = {
+    MAKE_FUNC_INFO(cc_initialize),
+    MAKE_FUNC_INFO(cc_shutdown),
+    MAKE_FUNC_INFO(cc_get_NC_info),
+    MAKE_FUNC_INFO(cc_free_NC_info),
+    END_FUNC_INFO
+};
+
+// psapi functions
+DECL_FUNC_PTR(GetModuleFileNameExA);
+DECL_FUNC_PTR(EnumProcessModules);
+
+FUNC_INFO psapi_fi[] = {
+    MAKE_FUNC_INFO(GetModuleFileNameExA),
+    MAKE_FUNC_INFO(EnumProcessModules),
+    END_FUNC_INFO
+};
+
+// toolhelp functions
+DECL_FUNC_PTR(CreateToolhelp32Snapshot);
+DECL_FUNC_PTR(Module32First);
+DECL_FUNC_PTR(Module32Next);
+
+FUNC_INFO toolhelp_fi[] = {
+    MAKE_FUNC_INFO(CreateToolhelp32Snapshot),
+    MAKE_FUNC_INFO(Module32First),
+    MAKE_FUNC_INFO(Module32Next),
+    END_FUNC_INFO
+};
+
+BOOL WINAPI
+DllMain(
+    HANDLE hinstDLL,
+    DWORD fdwReason,
+    LPVOID lpReserved
+    )
+{
+    hLeashInst = hinstDLL;
+
+    switch (fdwReason)
+    {
+    case DLL_PROCESS_ATTACH:
+    {
+        OSVERSIONINFO osvi;
+#ifndef NO_KRB4
+        LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
+#endif
+        LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
+        LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+        LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
+        LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
+#ifndef NO_KRB4
+        LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
+#endif
+       LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+       LoadFuncs(CCAPI_DLL, ccapi_fi, &hCcapi, 0, 1, 0, 0);
+
+        memset(&osvi, 0, sizeof(OSVERSIONINFO));
+        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+        GetVersionEx(&osvi);
+
+        // XXX: We should really use feature testing, first
+        // checking for CreateToolhelp32Snapshot.  If that's
+        // not around, we try the psapi stuff.
+        //
+        // Only load LSA functions if on NT/2000/XP
+        if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+        {
+            // Windows 9x
+            LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0);
+            hPsapi = 0;
+        }
+        else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
+        {
+            // Windows NT
+            LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0);
+            hToolHelp32 = 0;
+        }
+
+
+        /*
+         * Register window class for the MITPasswordControl that
+         * replaces normal edit controls for password input.
+         * zero any fields we don't explicitly set
+         */
+        hLeashInst = hinstDLL;
+#ifndef NO_KRB4
+        if (plsh_LoadKrb4LeashErrorTables)
+            plsh_LoadKrb4LeashErrorTables(hLeashInst, 0);
+#endif
+
+        Register_MITPasswordEditControl(hLeashInst);
+
+#ifndef NO_AFS
+        {
+            DWORD AfsStatus = 0;
+            GetAfsStatus(&AfsStatus);
+
+            AfsAvailable = afscompat_init();
+
+            if ( AfsStatus && !AfsAvailable )
+                SetAfsStatus(0);
+        }
+#endif
+        return TRUE;
+    }
+    case DLL_PROCESS_DETACH:
+#ifndef NO_AFS
+        afscompat_close();
+#endif
+#ifndef NO_KRB4
+        if (hKrb4)
+            FreeLibrary(hKrb4);
+#endif
+        if (hKrb5)
+            FreeLibrary(hKrb5);
+       if (hCcapi)
+           FreeLibrary(hCcapi);
+       if (hProfile)
+           FreeLibrary(hProfile);
+        if (hComErr)
+            FreeLibrary(hComErr);
+        if (hService)
+            FreeLibrary(hService);
+        if (hSecur32)
+            FreeLibrary(hSecur32);
+#ifndef NO_KRB4
+        if (hKrb524)
+            FreeLibrary(hKrb524);
+#endif
+        if (hPsapi)
+            FreeLibrary(hPsapi);
+        if (hToolHelp32)
+            FreeLibrary(hToolHelp32);
+
+        return TRUE;
+    default:
+        return TRUE;
+    }
+}
diff --git a/src/windows/leashdll/leashdll.h b/src/windows/leashdll/leashdll.h
new file mode 100644 (file)
index 0000000..162fb4f
--- /dev/null
@@ -0,0 +1,259 @@
+#ifndef _LEASHDLL_H_
+#define _LEASHDLL_H_
+
+#include <com_err.h>
+#ifndef NO_KRB4
+/*
+ * This is a hack needed because the real com_err.h does
+ * not define err_func.  We need it in the case where
+ * we pull in the real com_err instead of the krb4
+ * impostor.
+ */
+#ifndef _DCNS_MIT_COM_ERR_H
+typedef LPSTR (*err_func)(int, long);
+#endif
+
+#include <krberr.h>
+extern void Leash_initialize_krb_error_func(err_func func,struct et_list **);
+#undef init_krb_err_func
+#define init_krb_err_func(erf) Leash_initialize_krb_error_func(erf,&_et_list)
+
+#include <kadm_err.h>
+
+extern void Leash_initialize_kadm_error_table(struct et_list **);
+#undef init_kadm_err_tbl
+#define init_kadm_err_tbl() Leash_initialize_kadm_error_table(&_et_list)
+#define kadm_err_base ERROR_TABLE_BASE_kadm
+#endif
+
+#define krb_err_func Leash_krb_err_func
+
+#include <stdarg.h>
+int lsh_com_err_proc (LPSTR whoami, long code,
+                     LPSTR fmt, va_list args);
+void FAR Leash_load_com_err_callback(FARPROC,FARPROC,FARPROC);
+
+
+#ifndef KRBERR
+#define KRBERR(code) (code + krb_err_base)
+#endif
+
+
+/* Internal Stuff */
+
+#include <windows.h>
+#define SECURITY_WIN32
+#include <security.h>
+
+/* _WIN32_WINNT must be 0x0501 or greater to pull in definition of
+ * all required LSA data types when the Vista SDK NtSecAPI.h is used.
+ */
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#else
+#if _WIN32_WINNT < 0x0501
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+#endif
+#include <ntsecapi.h>
+
+#ifndef NO_KRB4
+extern HINSTANCE hKrb4;
+#endif
+extern HINSTANCE hKrb5;
+extern HINSTANCE hProfile;
+
+#define TIMEHOST "TIMEHOST"
+
+#define LEASH_DEBUG_CLASS_GENERIC   0
+#define LEASH_DEBUG_CLASS_KRB4      1
+#define LEASH_DEBUG_CLASS_KRB4_APP  2
+
+#define LEASH_PRIORITY_LOW  0
+#define LEASH_PRIORITY_HIGH 1
+
+typedef struct TicketList
+{
+    char* theTicket;
+    struct TicketList* next;
+    char* tktEncType;
+    char* keyEncType;
+    int   addrCount;
+    char ** addrList;
+    char * name;
+    char * inst;
+    char * realm;
+} TicketList;
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef _WIN64
+#define LEASH_DLL     "leashw64.dll"
+#define KRBCC32_DLL   "krbcc64.dll"
+#else
+#define LEASH_DLL     "leashw32.dll"
+#define KRBCC32_DLL   "krbcc32.dll"
+#endif
+#define SERVICE_DLL   "advapi32.dll"
+#define SECUR32_DLL   "secur32.dll"
+
+//////////////////////////////////////////////////////////////////////////////
+
+#include <loadfuncs-com_err.h>
+#include <loadfuncs-krb5.h>
+#include <loadfuncs-profile.h>
+#ifndef NO_KRB4
+#include <loadfuncs-krb.h>
+#include <loadfuncs-krb524.h>
+#endif
+#include <loadfuncs-lsa.h>
+
+#include <errno.h>
+
+#ifndef NO_AFS
+#include "afscompat.h"
+#endif
+
+// service definitions
+typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD);
+typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD);
+typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS);
+typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE);
+
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef NO_KRB4
+// krb4 functions
+extern DECL_FUNC_PTR(get_krb_err_txt_entry);
+extern DECL_FUNC_PTR(k_isinst);
+extern DECL_FUNC_PTR(k_isname);
+extern DECL_FUNC_PTR(k_isrealm);
+extern DECL_FUNC_PTR(kadm_change_your_password);
+extern DECL_FUNC_PTR(kname_parse);
+extern DECL_FUNC_PTR(krb_get_cred);
+extern DECL_FUNC_PTR(krb_get_krbhst);
+extern DECL_FUNC_PTR(krb_get_lrealm);
+extern DECL_FUNC_PTR(krb_get_pw_in_tkt);
+extern DECL_FUNC_PTR(krb_get_tf_realm);
+extern DECL_FUNC_PTR(krb_mk_req);
+extern DECL_FUNC_PTR(krb_realmofhost);
+extern DECL_FUNC_PTR(tf_init);
+extern DECL_FUNC_PTR(tf_close);
+extern DECL_FUNC_PTR(tf_get_cred);
+extern DECL_FUNC_PTR(tf_get_pname);
+extern DECL_FUNC_PTR(tf_get_pinst);
+extern DECL_FUNC_PTR(LocalHostAddr);
+extern DECL_FUNC_PTR(tkt_string);
+extern DECL_FUNC_PTR(krb_set_tkt_string);
+extern DECL_FUNC_PTR(initialize_krb_error_func);
+extern DECL_FUNC_PTR(initialize_kadm_error_table);
+extern DECL_FUNC_PTR(dest_tkt);
+extern DECL_FUNC_PTR(lsh_LoadKrb4LeashErrorTables); // XXX
+extern DECL_FUNC_PTR(krb_in_tkt);
+extern DECL_FUNC_PTR(krb_save_credentials);
+extern DECL_FUNC_PTR(krb_get_krbconf2);
+extern DECL_FUNC_PTR(krb_get_krbrealm2);
+extern DECL_FUNC_PTR(krb_life_to_time);
+#endif
+
+// krb5 functions
+extern DECL_FUNC_PTR(krb5_change_password);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
+extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
+extern DECL_FUNC_PTR(krb5_get_init_creds_password);
+extern DECL_FUNC_PTR(krb5_build_principal_ext);
+extern DECL_FUNC_PTR(krb5_cc_resolve);
+extern DECL_FUNC_PTR(krb5_cc_default);
+extern DECL_FUNC_PTR(krb5_cc_default_name);
+extern DECL_FUNC_PTR(krb5_cc_set_default_name);
+extern DECL_FUNC_PTR(krb5_cc_initialize);
+extern DECL_FUNC_PTR(krb5_cc_destroy);
+extern DECL_FUNC_PTR(krb5_cc_close);
+extern DECL_FUNC_PTR(krb5_cc_copy_creds);
+extern DECL_FUNC_PTR(krb5_cc_store_cred);
+// extern DECL_FUNC_PTR(krb5_cc_retrieve_cred);
+extern DECL_FUNC_PTR(krb5_cc_get_principal);
+extern DECL_FUNC_PTR(krb5_cc_start_seq_get);
+extern DECL_FUNC_PTR(krb5_cc_next_cred);
+extern DECL_FUNC_PTR(krb5_cc_end_seq_get);
+// extern DECL_FUNC_PTR(krb5_cc_remove_cred);
+extern DECL_FUNC_PTR(krb5_cc_set_flags);
+// extern DECL_FUNC_PTR(krb5_cc_get_type);
+extern DECL_FUNC_PTR(krb5_free_context);
+extern DECL_FUNC_PTR(krb5_free_cred_contents);
+extern DECL_FUNC_PTR(krb5_free_principal);
+extern DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
+extern DECL_FUNC_PTR(krb5_init_context);
+extern DECL_FUNC_PTR(krb5_parse_name);
+extern DECL_FUNC_PTR(krb5_timeofday);
+extern DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
+extern DECL_FUNC_PTR(krb5_unparse_name);
+extern DECL_FUNC_PTR(krb5_get_credentials);
+extern DECL_FUNC_PTR(krb5_mk_req);
+extern DECL_FUNC_PTR(krb5_sname_to_principal);
+extern DECL_FUNC_PTR(krb5_get_credentials_renew);
+extern DECL_FUNC_PTR(krb5_free_data);
+extern DECL_FUNC_PTR(krb5_free_data_contents);
+// extern DECL_FUNC_PTR(krb5_get_realm_domain);
+extern DECL_FUNC_PTR(krb5_free_unparsed_name);
+extern DECL_FUNC_PTR(krb5_os_localaddr);
+extern DECL_FUNC_PTR(krb5_copy_keyblock_contents);
+extern DECL_FUNC_PTR(krb5_copy_data);
+extern DECL_FUNC_PTR(krb5_free_creds);
+extern DECL_FUNC_PTR(krb5_build_principal);
+extern DECL_FUNC_PTR(krb5_get_renewed_creds);
+extern DECL_FUNC_PTR(krb5_free_addresses);
+extern DECL_FUNC_PTR(krb5_get_default_config_files);
+extern DECL_FUNC_PTR(krb5_free_config_files);
+extern DECL_FUNC_PTR(krb5_get_default_realm);
+extern DECL_FUNC_PTR(krb5_free_ticket);
+extern DECL_FUNC_PTR(krb5_decode_ticket);
+extern DECL_FUNC_PTR(krb5_get_host_realm);
+extern DECL_FUNC_PTR(krb5_free_host_realm);
+extern DECL_FUNC_PTR(krb5_c_random_make_octets);
+extern DECL_FUNC_PTR(krb5_free_default_realm);
+extern DECL_FUNC_PTR(krb5_principal_compare);
+extern DECL_FUNC_PTR(krb5_string_to_deltat);
+
+#ifndef NO_KRB4
+// Krb524 functions
+extern DECL_FUNC_PTR(krb524_init_ets);
+extern DECL_FUNC_PTR(krb524_convert_creds_kdc);
+#endif
+
+// ComErr functions
+extern DECL_FUNC_PTR(com_err);
+extern DECL_FUNC_PTR(error_message);
+
+// Profile functions
+extern DECL_FUNC_PTR(profile_init);
+extern DECL_FUNC_PTR(profile_release);
+extern DECL_FUNC_PTR(profile_get_subsection_names);
+extern DECL_FUNC_PTR(profile_free_list);
+extern DECL_FUNC_PTR(profile_get_string);
+extern DECL_FUNC_PTR(profile_release_string);
+extern DECL_FUNC_PTR(profile_get_integer);
+
+// Service functions
+
+extern DECL_FUNC_PTR(OpenSCManagerA);
+extern DECL_FUNC_PTR(OpenServiceA);
+extern DECL_FUNC_PTR(QueryServiceStatus);
+extern DECL_FUNC_PTR(CloseServiceHandle);
+extern DECL_FUNC_PTR(LsaNtStatusToWinError);
+
+// LSA Functions
+
+extern DECL_FUNC_PTR(LsaConnectUntrusted);
+extern DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
+extern DECL_FUNC_PTR(LsaCallAuthenticationPackage);
+extern DECL_FUNC_PTR(LsaFreeReturnBuffer);
+extern DECL_FUNC_PTR(LsaGetLogonSessionData);
+
+#endif /* _LEASHDLL_H_ */
diff --git a/src/windows/leashdll/leasherr.c b/src/windows/leashdll/leasherr.c
new file mode 100644 (file)
index 0000000..ec2616b
--- /dev/null
@@ -0,0 +1,119 @@
+// ATTENTION: someone in the past edited this file manually
+// I am continuing this tradition just to get the release out. 3/6/97
+// This needs to be revisited and repaired!!!XXXX
+// pbh
+
+
+ /*
+ * leasherr.c
+ * This file is the C file for leasherr.et.
+ * Please do not edit it as it is automatically generated.
+ */
+
+#ifndef NO_KRB4
+extern void (__cdecl *pinitialize_krb_error_func)();
+extern void (__cdecl *pinitialize_kadm_error_table)();
+#endif
+
+#include <stdlib.h>
+#include <windows.h>
+
+static const char* const text[] = {
+       "Only one instance of Leash can be run at a time.",
+       "Principal invalid.",
+       "Realm failed.",
+       "Instance invalid.",
+       "Realm invalid.",
+       "Unexpected end of Kerberos memory storage.",
+       "Warning! Your Kerberos tickets expire soon.",
+       "You did not type the same new password.",
+       "You can only use printable characters in a password.",
+       "Fatal error; cannot run this program.",
+       "Couldn't initialize WinSock.",
+       "Couldn't find the timeserver host entry.",
+       "Couldn't open a socket.",
+       "Couldn't connect to timeserver.",
+       "Couldn't get time from server.",
+       "Couldn't get local time of day.",
+       "Couldn't set local time of day.",
+       "Error while receiving time from server.",
+       "Protocol problem with timeserver.",
+       "The time was already reset. Try using a different program to synchronize the time.",
+    0
+};
+
+typedef LPSTR (*err_func)(int, long);
+struct error_table {
+    char const * const * msgs;
+    err_func func;
+    long base;
+    int n_msgs;
+};
+struct et_list {
+#ifdef WINDOWS
+       HANDLE next;
+#else
+       struct et_list *next;
+#endif
+       const struct error_table * table;
+};
+
+static const struct error_table et = { text, (err_func)0, 40591872L, 20 };
+
+#ifdef WINDOWS
+void initialize_lsh_error_table(HANDLE *__et_list) {
+//    struct et_list *_link,*_et_list;
+    struct et_list *_link;
+    HANDLE ghlink;
+
+    ghlink=GlobalAlloc(GHND,sizeof(struct et_list));
+    _link=GlobalLock(ghlink);
+    _link->next=*__et_list;
+    _link->table=&et;
+    GlobalUnlock(ghlink);
+    *__et_list=ghlink;
+}
+#else
+void initialize_lsh_error_table(struct et_list **__et_list) {
+    struct et_list *_link;
+
+    _link=malloc(sizeof(struct et_list));
+    _link->next=*__et_list;
+    _link->table=&et;
+    *__et_list=_link;
+}
+#endif
+
+#ifdef WINDOWS
+#include <krberr.h>
+
+void Leash_initialize_krb_error_func(err_func func, HANDLE *__et_list)
+{
+#ifndef NO_KRB4
+    (*pinitialize_krb_error_func)(func,__et_list);
+#endif
+}
+
+#include <kadm_err.h>
+
+void Leash_initialize_kadm_error_table(HANDLE *__et_list)
+{
+#ifndef NO_KRB4
+    (*pinitialize_kadm_error_table)(__et_list);
+#endif
+}
+#else
+#include <krberr.h>
+
+void Leash_initialize_krb_error_func(err_func func, struct et_list **__et_list)
+{
+    (*pinitialize_krb_error_func)(func,__et_list);
+}
+
+#include <kadm_err.h>
+
+void Leash_initialize_kadm_error_table(struct et_list **__et_list)
+{
+    initialize_kadm_error_table(__et_list);
+}
+#endif
diff --git a/src/windows/leashdll/leasherr.et b/src/windows/leashdll/leasherr.et
new file mode 100644 (file)
index 0000000..d1d027b
--- /dev/null
@@ -0,0 +1,22 @@
+ERROR_TABLE lsh
+  ERROR_CODE LSH_ONLYONEME,        "Only one instance of Leash can be run at a time."
+  ERROR_CODE LSH_INVPRINCIPAL, "Principal invalid."
+  ERROR_CODE LSH_FAILEDREALM,  "Realm failed."
+  ERROR_CODE LSH_INVINSTANCE,  "Instance invalid."
+  ERROR_CODE LSH_INVREALM,     "Realm invalid."
+  ERROR_CODE LSH_EOF,          "Unexpected end of Kerberos memory storage."
+  ERROR_CODE LSH_EXPIRESOON,   "Warning! Your Kerberos tickets expire soon."
+  ERROR_CODE LSH_NOMATCH,      "You did not type the same new password."
+  ERROR_CODE LSH_BADCHARS,     "You can only use printable characters in a password."
+  ERROR_CODE LSH_FATAL_ERROR,  "Fatal error; cannot run this program."
+  ERROR_CODE LSH_BADWINSOCK,   "Couldn't initialize WinSock."
+  ERROR_CODE LSH_BADTIMESERV,  "Couldn't find the timeserver host entry."
+  ERROR_CODE LSH_NOSOCKET,     "Couldn't open a socket."
+  ERROR_CODE LSH_NOCONNECT,    "Couldn't connect to timeserver."
+  ERROR_CODE LSH_TIMEFAILED,   "Couldn't get time from server."
+  ERROR_CODE LSH_GETTIMEOFDAY, "Couldn't get local time of day."
+  ERROR_CODE LSH_SETTIMEOFDAY, "Couldn't set local time of day."
+  ERROR_CODE LSH_RECVTIME,     "Error while receiving time from server."
+  ERROR_CODE LSH_RECVBYTES,    "Protocol problem with timeserver."
+  ERROR_CODE LSH_ALREADY_SETTIME, "The time was already reset. Try using a different program to synchronize the time."
+end
diff --git a/src/windows/leashdll/leashids.h b/src/windows/leashdll/leashids.h
new file mode 100644 (file)
index 0000000..64c8641
--- /dev/null
@@ -0,0 +1,115 @@
+// *** Child Windows
+#define ID_MAINLIST                    100
+#define ID_COUNTDOWN           101
+
+#define ID_DESTROY                             111
+#define ID_CHANGEPASSWORD              112
+#define ID_INITTICKETS                 113
+#define ID_SYNCTIME                            114
+
+#define ID_UPDATESTATE                 120
+#define ID_UPDATEDISPLAY               121
+#define ID_KRBDLL_DEBUG                122
+
+
+// *** Menus
+
+#define ID_EXIT                                        200
+
+#define ID_HELP_LEASH                  210
+#define ID_HELP_KERBEROS               211
+#define ID_ABOUT                               212
+
+#define ID_CHECKV                              299
+
+// *** Password Dialog
+#define ID_PRINCIPAL                   301
+#define ID_OLDPASSWORD                 302
+#define ID_CONFIRMPASSWORD1            303
+#define ID_CONFIRMPASSWORD2            304
+#define ID_PICFRAME                            305
+
+#define ID_PRINCCAPTION                        311
+#define ID_OLDPCAPTION                 312
+#define ID_CONFIRMCAPTION1             313
+#define ID_CONFIRMCAPTION2             314
+#define CAPTION_OFFSET                  10
+
+#define ID_DURATION                    320
+
+#define ID_RESTART                     351
+
+#define ID_CLOSEME                     380
+
+// *** About dialog stuff
+#define ID_LEASH_CPYRT         400
+#define ID_LEASH_AUTHOR                401
+#define ID_KERB_CPYRT          402
+#define ID_KERB_AUTHOR         403
+#define ID_LEGALESE                    404
+#define ID_ASSISTANCE          405
+
+// *** Keyboard accelerator crud
+#define ID_HELP                                        1000
+#define ID_CONTEXTSENSITIVEHELP        1001
+#define ID_ENDCSHELP                   1002
+#define ID_HELPFIRST                   1000
+#define ID_HELPLAST                            1002
+
+// *** window messages
+#define WM_STARTUP                     (WM_USER + 1)
+#define WM_F1DOWN                      (WM_USER + 2)
+#define WM_DOHELP                      (WM_USER + 3)
+#define WM_PAINTICON           0x0026
+
+// *** command messages
+#define ID_NEXTSTATE                 10000
+
+#define LSH_TIME_HOST                    1970
+#define LSH_DEFAULT_TICKET_LIFE          1971
+#define LSH_DEFAULT_TICKET_RENEW_TILL    1972
+#define LSH_DEFAULT_TICKET_FORWARD       1973
+#define LSH_DEFAULT_TICKET_NOADDRESS     1974
+#define LSH_DEFAULT_TICKET_PROXIABLE     1975
+#define LSH_DEFAULT_TICKET_PUBLICIP      1976
+#define LSH_DEFAULT_TICKET_USEKRB4       1977
+#define LSH_DEFAULT_DIALOG_KINIT_OPT     1978
+#define LSH_DEFAULT_DIALOG_LIFE_MIN      1979
+#define LSH_DEFAULT_DIALOG_LIFE_MAX      1980
+#define LSH_DEFAULT_DIALOG_RENEW_MIN     1981
+#define LSH_DEFAULT_DIALOG_RENEW_MAX     1982
+#define LSH_DEFAULT_TICKET_RENEW         1983
+#define LSH_DEFAULT_DIALOG_LOCK_LOCATION 1984
+#define LSH_DEFAULT_UPPERCASEREALM       1985
+#define LSH_DEFAULT_MSLSA_IMPORT         1986
+#define LSH_DEFAULT_PRESERVE_KINIT       1987
+
+// Authenticate Dialog
+#define IDD_AUTHENTICATE                1162
+#define IDC_STATIC_IPADDR               1163
+#define IDC_STATIC_NAME                 1164
+#define IDC_STATIC_PWD                  1165
+#define IDC_EDIT_PRINCIPAL              1166
+#define IDC_COMBO_REALM                 1167
+#define IDC_EDIT_PASSWORD               1168
+#define IDC_STATIC_LIFETIME             1169
+#define IDC_SLIDER_LIFETIME             1170
+#define IDC_STATIC_KRB5                 1171
+#define IDC_CHECK_FORWARDABLE           1172
+#define IDC_CHECK_NOADDRESS             1173
+#define IDC_CHECK_RENEWABLE             1174
+#define IDC_SLIDER_RENEWLIFE            1175
+#define IDC_STATIC_LIFETIME_VALUE       1176
+#define IDC_STATIC_RENEW_TILL_VALUE     1177
+#define IDC_PICTURE_LEASH               1179
+#define IDC_BUTTON_OPTIONS              1086
+#define IDC_STATIC_REALM                1087
+#define IDC_STATIC_COPYRIGHT            1088
+#define IDC_STATIC_NOTICE               1089
+#define IDC_STATIC_RENEW                1090
+#define IDD_PASSWORD                    1091
+#define IDC_EDIT_PASSWORD2              1192
+#define IDC_STATIC_PWD2                 1193
+#define IDC_EDIT_PASSWORD3              1194
+#define IDC_STATIC_PWD3                 1195
+#define IDC_STATIC_VERSION              1196
diff --git a/src/windows/leashdll/leashw32.def b/src/windows/leashdll/leashw32.def
new file mode 100644 (file)
index 0000000..25af0e2
--- /dev/null
@@ -0,0 +1,108 @@
+LIBRARY   LEASHW32
+
+DESCRIPTION 'DLL for Kerberos ticket initialization'
+
+HEAPSIZE  8092
+STACKSIZE 36864
+
+EXPORTS
+;              DllMain @1
+       ;       Leash_kinit_dlg                 @3
+       ;       Leash_changepwd_dlg             @4
+       ;       Leash_kinit                     @48
+       ;       Leash_kdestroy                  @49
+       ;       Leash_klist                     @50
+       ;       Leash_checkpwd                  @51
+       ;       Leash_changepwd                 @52
+       ;       Leash_get_lsh_errno             @61
+       ;       initialize_lsh_error_table      @80
+       ;       lsh_com_err_proc                @81
+       ;       Leash_initialize_krb_error_func      @82
+       ;       Leash_initialize_kadm_error_table    @83
+       ;       Leash_krb_err_func                   @84
+       ;       Leash_load_com_err_callback     @85
+       ;       Leash_set_help_file             @86
+       ;       Leash_get_help_file             @87
+       ;       Leash_timesync                  @88
+;              Leash_WhichOS                   @89
+
+       Leash_kinit_dlg
+    Leash_kinit_dlg_ex
+       Leash_changepwd_dlg
+       Leash_changepwd_dlg_ex
+       Leash_kinit
+    Leash_kinit_ex
+       Leash_kdestroy
+       Leash_klist
+       Leash_checkpwd
+       Leash_changepwd
+       Leash_get_lsh_errno
+       initialize_lsh_error_table
+       lsh_com_err_proc
+       Leash_initialize_krb_error_func
+       Leash_initialize_kadm_error_table
+       Leash_krb_err_func
+       Leash_load_com_err_callback
+       Leash_set_help_file
+       Leash_get_help_file
+       Leash_timesync
+       Leash_get_default_lifetime
+       Leash_set_default_lifetime
+    Leash_reset_default_lifetime
+       Leash_get_default_renew_till
+       Leash_set_default_renew_till
+    Leash_reset_default_renew_till
+       Leash_get_default_forwardable
+       Leash_set_default_forwardable
+    Leash_reset_default_forwardable
+       Leash_get_default_renewable
+       Leash_set_default_renewable
+    Leash_reset_default_renewable
+       Leash_get_default_noaddresses
+       Leash_set_default_noaddresses
+    Leash_reset_default_noaddresses
+       Leash_get_default_proxiable
+       Leash_set_default_proxiable
+    Leash_reset_default_proxiable
+       Leash_get_default_publicip
+       Leash_set_default_publicip
+    Leash_reset_default_publicip
+       Leash_get_default_use_krb4
+       Leash_set_default_use_krb4
+    Leash_reset_default_use_krb4
+       Leash_get_default_life_min
+       Leash_set_default_life_min
+    Leash_reset_default_life_min
+       Leash_get_default_life_max
+       Leash_set_default_life_max
+    Leash_reset_default_life_max
+       Leash_get_default_renew_min
+       Leash_set_default_renew_min
+    Leash_reset_default_renew_min
+       Leash_get_default_renew_max
+       Leash_set_default_renew_max
+    Leash_reset_default_renew_max
+       Leash_get_lock_file_locations
+       Leash_set_lock_file_locations
+    Leash_reset_lock_file_locations
+       Leash_get_default_uppercaserealm
+       Leash_set_default_uppercaserealm
+    Leash_reset_default_uppercaserealm
+       Leash_get_default_mslsa_import
+       Leash_set_default_mslsa_import
+    Leash_reset_default_mslsa_import
+       Leash_get_default_preserve_kinit_settings
+       Leash_set_default_preserve_kinit_settings
+    Leash_reset_default_preserve_kinit_settings
+    Leash_import
+    Leash_importable
+    Leash_renew
+    Leash_reset_defaults
+
+       ; XXX - These have to go...
+       not_an_API_LeashAFSGetToken
+       not_an_API_LeashKRB5GetTickets
+       not_an_API_LeashFreeTicketList
+       not_an_API_LeashKRB4GetTickets
+       not_an_API_LeashGetTimeServerName
+    not_an_API_Leash_AcquireInitialTicketsIfNeeded
diff --git a/src/windows/leashdll/loadfuncs.c b/src/windows/leashdll/loadfuncs.c
new file mode 100644 (file)
index 0000000..44ec54d
--- /dev/null
@@ -0,0 +1,88 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include "loadfuncs.h"
+
+//
+// UnloadFuncs:
+//
+// This function will reset all the function pointers of a function loaded
+// by LaodFuncs and will free the DLL instance provided.
+//
+
+void
+UnloadFuncs(
+    FUNC_INFO fi[],
+    HINSTANCE h
+    )
+{
+    int n;
+    if (fi)
+        for (n = 0; fi[n].func_ptr_var; n++)
+            *(fi[n].func_ptr_var) = NULL;
+    if (h) FreeLibrary(h);
+}
+
+
+//
+// LoadFuncs:
+//
+// This function try to load the functions for a DLL.  It returns 0 on failure
+// and non-zero on success.  The parameters are descibed below.
+//
+
+int
+LoadFuncs(
+    const char* dll_name,
+    FUNC_INFO fi[],
+    HINSTANCE* ph,  // [out, optional] - DLL handle
+    int* pindex,    // [out, optional] - index of last func loaded (-1 if none)
+    int cleanup,    // cleanup function pointers and unload on error
+    int go_on,      // continue loading even if some functions cannot be loaded
+    int silent      // do not pop-up a system dialog if DLL cannot be loaded
+
+    )
+{
+    HINSTANCE h;
+    int i, n, last_i;
+    int error = 0;
+    UINT em;
+
+    if (ph) *ph = 0;
+    if (pindex) *pindex = -1;
+
+    for (n = 0; fi[n].func_ptr_var; n++)
+       *(fi[n].func_ptr_var) = NULL;
+
+    if (silent)
+       em = SetErrorMode(SEM_FAILCRITICALERRORS);
+    h = LoadLibrary(dll_name);
+    if (silent)
+        SetErrorMode(em);
+
+    if (!h)
+        return 0;
+
+    last_i = -1;
+    for (i = 0; (go_on || !error) && (i < n); i++)
+    {
+       void* p = (void*)GetProcAddress(h, fi[i].func_name);
+       if (!p)
+           error = 1;
+        else
+        {
+            last_i = i;
+           *(fi[i].func_ptr_var) = p;
+        }
+    }
+    if (pindex) *pindex = last_i;
+    if (error && cleanup && !go_on) {
+       for (i = 0; i < n; i++) {
+           *(fi[i].func_ptr_var) = NULL;
+       }
+       FreeLibrary(h);
+       return 0;
+    }
+    if (ph) *ph = h;
+    if (error) return 0;
+    return 1;
+}
diff --git a/src/windows/leashdll/lsh_pwd.c b/src/windows/leashdll/lsh_pwd.c
new file mode 100644 (file)
index 0000000..6be1ea3
--- /dev/null
@@ -0,0 +1,2430 @@
+#define SCALE_FACTOR 31/20
+
+/* LSH_PWD.C
+
+   Jason Hunter
+   8/2/94
+   DCNS/IS MIT
+
+   Re-written for KFW 2.6 by Jeffrey Altman <jaltman@mit.edu>
+
+   Contains the callback functions for the EnterPassword an
+   ChangePassword dialog boxes and well as the API function
+   calls:
+
+   Lsh_Enter_Password_Dialog
+   Lsh_Change_Password_Dialog
+
+   for calling the dialogs.
+
+   Also contains the callback for the MITPasswordControl.
+
+*/
+
+/* Standard Include files */
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Private Inlclude files */
+#include "leashdll.h"
+#include <conf.h>
+#include <leashwin.h>
+#include "leash-int.h"
+#include "leashids.h"
+#include <leasherr.h>
+#include <krb.h>
+#ifndef NO_KRB5
+#include <krb5.h>
+#endif /* NO_KRB5 */
+#include <commctrl.h>
+
+/* Global Variables. */
+static long lsh_errno;
+static char *err_context;       /* error context */
+extern HINSTANCE hLeashInst;
+extern HINSTANCE hKrb4;
+extern HINSTANCE hKrb5;
+
+
+INT_PTR
+CALLBACK
+PasswordProc(
+    HWND hwndDlg,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+    );
+
+INT_PTR
+CALLBACK
+AuthenticateProc(
+    HWND hwndDlg,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+    );
+
+INT_PTR
+CALLBACK
+NewPasswordProc(
+    HWND hwndDlg,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+    );
+
+
+long Leash_get_lsh_errno(LONG *err_val)
+{
+    return lsh_errno;
+}
+
+/*/////// ******** API Calls follow here.   ******** /////////*/
+
+static int
+NetId_dialog(LPLSH_DLGINFO lpdlginfo)
+{
+    LRESULT             lrc;
+    HWND               hNetIdMgr;
+    HWND               hForeground;
+
+    hNetIdMgr = FindWindow("IDMgrRequestDaemonCls", "IDMgrRequestDaemon");
+    if (hNetIdMgr != NULL) {
+       char desiredPrincipal[512];
+       NETID_DLGINFO *dlginfo;
+       char            *desiredName = 0;
+       char            *desiredRealm = 0;
+       HANDLE hMap;
+       DWORD  tid = GetCurrentThreadId();
+       char mapname[256];
+
+       strcpy(desiredPrincipal, lpdlginfo->principal);
+
+       /* do we want a specific client principal? */
+       if (desiredPrincipal[0]) {
+           char * p;
+           desiredName = desiredPrincipal;
+           for (p = desiredName; *p && *p != '@'; p++);
+           if ( *p == '@' ) {
+               *p = '\0';
+               desiredRealm = ++p;
+           }
+       }
+
+       sprintf(mapname,"Local\\NetIDMgr_DlgInfo_%lu",tid);
+
+       hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+                                0, 4096, mapname);
+       if (hMap == NULL) {
+           return -1;
+       } else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS) {
+           CloseHandle(hMap);
+           return -1;
+       }
+
+       dlginfo = (NETID_DLGINFO *)MapViewOfFileEx(hMap, FILE_MAP_READ|FILE_MAP_WRITE,
+                                                0, 0, 4096, NULL);
+       if (dlginfo == NULL) {
+           CloseHandle(hMap);
+           return -1;
+       }
+
+       hForeground = GetForegroundWindow();
+
+       memset(dlginfo, 0, sizeof(NETID_DLGINFO));
+
+       dlginfo->size = sizeof(NETID_DLGINFO);
+       if (lpdlginfo->dlgtype == DLGTYPE_PASSWD)
+           dlginfo->dlgtype = NETID_DLGTYPE_TGT;
+       else
+           dlginfo->dlgtype = NETID_DLGTYPE_CHPASSWD;
+       dlginfo->in.use_defaults = 1;
+
+       if (lpdlginfo->title) {
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               lpdlginfo->title, -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       } else if (desiredName && (strlen(desiredName) + strlen(desiredRealm) + 32 < NETID_TITLE_SZ)) {
+           char mytitle[NETID_TITLE_SZ];
+           sprintf(mytitle, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm);
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               mytitle, -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       } else {
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               "Obtain Kerberos TGT", -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       }
+       if (desiredName)
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               desiredName, -1,
+                               dlginfo->in.username, NETID_USERNAME_SZ);
+       if (desiredRealm)
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               desiredRealm, -1,
+                               dlginfo->in.realm, NETID_REALM_SZ);
+       lrc = SendMessage(hNetIdMgr, 32810, 0, (LPARAM) tid);
+
+       UnmapViewOfFile(dlginfo);
+       CloseHandle(hMap);
+
+       SetForegroundWindow(hForeground);
+       return lrc;
+    }
+    return -1;
+}
+
+static int
+NetId_dialog_ex(LPLSH_DLGINFO_EX lpdlginfo)
+{
+    HWND               hNetIdMgr;
+    HWND               hForeground;
+
+    hNetIdMgr = FindWindow("IDMgrRequestDaemonCls", "IDMgrRequestDaemon");
+    if (hNetIdMgr != NULL) {
+       NETID_DLGINFO   *dlginfo;
+       char            *desiredName = lpdlginfo->username;
+       char            *desiredRealm = lpdlginfo->realm;
+       LPSTR            title;
+       char            *ccache;
+       LRESULT         lrc;
+       HANDLE hMap;
+       DWORD  tid = GetCurrentThreadId();
+       char mapname[256];
+
+       sprintf(mapname,"Local\\NetIDMgr_DlgInfo_%lu",tid);
+
+       hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+                                0, 4096, mapname);
+       if (hMap == NULL) {
+           return -1;
+       } else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS) {
+           CloseHandle(hMap);
+           return -1;
+       }
+
+       dlginfo = (NETID_DLGINFO *)MapViewOfFileEx(hMap, FILE_MAP_READ|FILE_MAP_WRITE,
+                                                0, 0, 4096, NULL);
+       if (dlginfo == NULL) {
+           CloseHandle(hMap);
+           return -1;
+       }
+
+       hForeground = GetForegroundWindow();
+
+       if (lpdlginfo->size == LSH_DLGINFO_EX_V1_SZ ||
+           lpdlginfo->size == LSH_DLGINFO_EX_V2_SZ)
+       {
+           title = lpdlginfo->title;
+           desiredName = lpdlginfo->username;
+           desiredRealm = lpdlginfo->realm;
+           ccache = NULL;
+       } else {
+           title = lpdlginfo->in.title;
+           desiredName = lpdlginfo->in.username;
+           desiredRealm = lpdlginfo->in.realm;
+           ccache = lpdlginfo->in.ccache;
+       }
+
+       memset(dlginfo, 0, sizeof(NETID_DLGINFO));
+
+       dlginfo->size = sizeof(NETID_DLGINFO);
+       if (lpdlginfo->dlgtype == DLGTYPE_PASSWD)
+           dlginfo->dlgtype = NETID_DLGTYPE_TGT;
+       else
+           dlginfo->dlgtype = NETID_DLGTYPE_CHPASSWD;
+
+       dlginfo->in.use_defaults = lpdlginfo->use_defaults;
+       dlginfo->in.forwardable  = lpdlginfo->forwardable;
+       dlginfo->in.noaddresses  = lpdlginfo->noaddresses;
+       dlginfo->in.lifetime     = lpdlginfo->lifetime;
+       dlginfo->in.renew_till   = lpdlginfo->renew_till;
+       dlginfo->in.proxiable    = lpdlginfo->proxiable;
+       dlginfo->in.publicip     = lpdlginfo->publicip;
+
+       if (title) {
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               title, -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       } else if (desiredName && (strlen(desiredName) + strlen(desiredRealm) + 32 < NETID_TITLE_SZ)) {
+           char mytitle[NETID_TITLE_SZ];
+           sprintf(mytitle, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm);
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               mytitle, -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       } else {
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               "Obtain Kerberos TGT", -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       }
+       if (desiredName)
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               desiredName, -1,
+                               dlginfo->in.username, NETID_USERNAME_SZ);
+       if (desiredRealm)
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               desiredRealm, -1,
+                               dlginfo->in.realm, NETID_REALM_SZ);
+       if (ccache)
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               ccache, -1,
+                               dlginfo->in.ccache, NETID_CCACHE_NAME_SZ);
+       lrc = SendMessage(hNetIdMgr, 32810, 0, (LPARAM) tid);
+
+       if (lrc > 0) {
+           if (lpdlginfo->size == LSH_DLGINFO_EX_V2_SZ)
+           {
+               WideCharToMultiByte(CP_ACP, 0, dlginfo->out.username, -1,
+                                    lpdlginfo->out.username, LEASH_USERNAME_SZ,
+                                    NULL, NULL);
+               WideCharToMultiByte(CP_ACP, 0, dlginfo->out.realm, -1,
+                                    lpdlginfo->out.realm, LEASH_REALM_SZ,
+                                    NULL, NULL);
+           }
+           if (lpdlginfo->size == LSH_DLGINFO_EX_V3_SZ)
+           {
+               WideCharToMultiByte(CP_ACP, 0, dlginfo->out.ccache, -1,
+                                    lpdlginfo->out.ccache, LEASH_CCACHE_NAME_SZ,
+                                    NULL, NULL);
+           }
+       }
+
+       UnmapViewOfFile(dlginfo);
+       CloseHandle(hMap);
+
+       SetForegroundWindow(hForeground);
+       return lrc;
+    }
+    return -1;
+}
+
+
+#define LEASH_DLG_MUTEX_NAME  TEXT("Leash_Dialog_Mutex")
+int Leash_kinit_dlg(HWND hParent, LPLSH_DLGINFO lpdlginfo)
+{
+    int rc;
+    HANDLE hMutex;
+
+    rc = NetId_dialog(lpdlginfo);
+    if (rc > -1)
+       return rc;
+
+    hMutex = CreateMutex(NULL, TRUE, LEASH_DLG_MUTEX_NAME);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+        if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
+            return -1;
+        }
+        ReleaseMutex(hMutex);
+        CloseHandle(hMutex);
+        return 1;   /* pretend the dialog was displayed and succeeded */
+    }
+
+    lpdlginfo->dlgtype = DLGTYPE_PASSWD;
+
+    /* set the help file */
+    Leash_set_help_file(NULL);
+
+    /* Call the Dialog box with the DLL's Password Callback and the
+       DLL's instance handle. */
+    rc =  DialogBoxParam(hLeashInst, "EnterPasswordDlg", hParent,
+                          PasswordProc, (LPARAM)lpdlginfo);
+
+    ReleaseMutex(hMutex);
+    CloseHandle(hMutex);
+    return rc;
+}
+
+
+int Leash_kinit_dlg_ex(HWND hParent, LPLSH_DLGINFO_EX lpdlginfo)
+{
+    int rc;
+    HANDLE hMutex;
+
+    rc = NetId_dialog_ex(lpdlginfo);
+    if (rc > -1)
+       return rc;
+
+    hMutex = CreateMutex(NULL, TRUE, LEASH_DLG_MUTEX_NAME);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+        if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
+            return -1;
+        }
+        ReleaseMutex(hMutex);
+        CloseHandle(hMutex);
+        return 1;   /* pretend the dialog was displayed and succeeded */
+    }
+
+    lpdlginfo->dlgtype = DLGTYPE_PASSWD;
+
+    /* set the help file */
+    Leash_set_help_file(NULL);
+
+    /* Call the Dialog box with the DLL's Password Callback and the
+       DLL's instance handle. */
+    rc = DialogBoxParam(hLeashInst, MAKEINTRESOURCE(IDD_AUTHENTICATE), hParent,
+                          AuthenticateProc, (LPARAM)lpdlginfo);
+    ReleaseMutex(hMutex);
+    CloseHandle(hMutex);
+    return rc;
+}
+
+
+int Leash_changepwd_dlg(HWND hParent, LPLSH_DLGINFO lpdlginfo)
+{
+    int rc;
+    HANDLE hMutex;
+
+    rc = NetId_dialog(lpdlginfo);
+    if (rc > -1)
+       return rc;
+
+    hMutex = CreateMutex(NULL, TRUE, LEASH_DLG_MUTEX_NAME);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+        if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
+            return -1;
+        }
+        ReleaseMutex(hMutex);
+        CloseHandle(hMutex);
+        return 1;   /* pretend the dialog was displayed and succeeded */
+    }
+
+    lpdlginfo->dlgtype = DLGTYPE_CHPASSWD;
+
+    /* Call the Dialog box with the DLL's Password Callback and the
+       DLL's instance handle. */
+    rc = DialogBoxParam(hLeashInst, "CHANGEPASSWORDDLG", hParent,
+                          PasswordProc, (LPARAM)lpdlginfo);
+    ReleaseMutex(hMutex);
+    CloseHandle(hMutex);
+    return rc;
+}
+
+int Leash_changepwd_dlg_ex(HWND hParent, LPLSH_DLGINFO_EX lpdlginfo)
+{
+    int rc;
+    HANDLE hMutex;
+
+    rc = NetId_dialog_ex(lpdlginfo);
+    if (rc > -1)
+       return rc;
+
+    hMutex = CreateMutex(NULL, TRUE, LEASH_DLG_MUTEX_NAME);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+        if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
+            return -1;
+        }
+        ReleaseMutex(hMutex);
+        CloseHandle(hMutex);
+        return 1;   /* pretend the dialog was displayed and succeeded */
+    }
+
+    lpdlginfo->dlgtype = DLGTYPE_CHPASSWD;
+
+    /* Call the Dialog box with the DLL's Password Callback and the
+       DLL's instance handle. */
+    rc = DialogBoxParam(hLeashInst, MAKEINTRESOURCE(IDD_PASSWORD), hParent,
+                          NewPasswordProc, (LPARAM)lpdlginfo);
+    ReleaseMutex(hMutex);
+    CloseHandle(hMutex);
+    return rc;
+}
+
+
+/*  These little utils are taken from lshutil.c
+    they are added here for the Call back funtion.
+****** beginning of added utils from lshutil.c  ******/
+
+BOOL IsDlgItem(HWND hWnd, WORD id)
+{
+    HWND hChild;
+
+    hChild = GetDlgItem(hWnd, id);
+    return hChild ? IsWindow(hChild) : 0;
+}
+
+int lsh_getkeystate(WORD keyid)
+{
+    static BYTE keys[256];
+
+    GetKeyboardState((LPBYTE) &keys);
+    return (int) keys[keyid];
+}
+
+LPSTR krb_err_func(int offset, long code)
+{
+#ifdef NO_KRB4
+    return(NULL);
+#else
+    return pget_krb_err_txt_entry(offset);
+#endif
+}
+
+/****** End of Added utils from leash.c  ******/
+
+
+int PaintLogoBitmap( HANDLE hPicFrame )
+{
+    HBITMAP hBitmap;
+    HBITMAP hOldBitmap;
+    BITMAP Bitmap;
+    HDC hdc, hdcMem;
+    RECT rect;
+
+    /* Invalidate the drawing space of the picframe. */
+    InvalidateRect( hPicFrame, NULL, TRUE);
+    UpdateWindow( hPicFrame );
+
+    hdc = GetDC(hPicFrame);
+    hdcMem = CreateCompatibleDC(hdc);
+    GetClientRect(hPicFrame, &rect);
+    hBitmap = LoadBitmap(hLeashInst, "LOGOBITMAP");
+    hOldBitmap = SelectObject(hdcMem, hBitmap);
+    GetObject(hBitmap, sizeof(Bitmap), (LPSTR) &Bitmap);
+    StretchBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0,
+               Bitmap.bmWidth, Bitmap.bmHeight, SRCCOPY);
+
+    SelectObject(hdcMem, hOldBitmap); /* pbh 8-15-94 */
+    ReleaseDC(hPicFrame, hdc);
+    DeleteObject( hBitmap );  /* pbh 8-15-94 */
+    DeleteDC( hdcMem );       /* pbh 8-15-94 */
+
+    return 0;
+}
+
+
+/* Callback function for the Password Dialog box that initilializes and
+   renews tickets. */
+
+INT_PTR
+CALLBACK
+PasswordProc(
+    HWND hDialog,
+    UINT message,
+    WPARAM wParam,
+    LPARAM lParam
+    )
+{
+    static POINT Position = { -1, -1 };
+    static short state;
+    int lifetime;
+#define ISCHPASSWD (lpdi->dlgtype == DLGTYPE_CHPASSWD)
+#define STATE_INIT     0
+#define STATE_PRINCIPAL 1
+#define STATE_OLDPWD   2
+#define STATE_NEWPWD1  3
+#define STATE_NEWPWD2  4
+#define STATE_CLOSED   5
+#define NEXTSTATE(newstate) SendMessage(hDialog, WM_COMMAND, ID_NEXTSTATE, newstate)
+    static int ids[STATE_NEWPWD2 + 1] = {
+        0,
+        ID_PRINCIPAL, ID_OLDPASSWORD, ID_CONFIRMPASSWORD1,
+        ID_CONFIRMPASSWORD2};
+    static char principal[255], oldpassword[255], newpassword[255],
+        newpassword2[255];
+    static char *strings[STATE_NEWPWD2 + 1] = {
+        NULL, principal, oldpassword, newpassword, newpassword2};
+    static LPLSH_DLGINFO lpdi;
+    char gbuf[200];                 /* global buffer for random stuff. */
+
+
+#define checkfirst(id, stuff) IsDlgItem(hDialog, id) ? stuff : 0
+#define CGetDlgItemText(hDlg, id, cp, len) checkfirst(id, GetDlgItemText(hDlg, id, cp, len))
+#define CSetDlgItemText(hDlg, id, cp) checkfirst(id, SetDlgItemText(hDlg, id, cp))
+#define CSetDlgItemInt(hDlg, id, i, b) checkfirst(id, SetDlgItemInt(hDlg, id, i, b))
+#define CSendDlgItemMessage(hDlg, id, m, w, l) checkfirst(id, SendDlgItemMessage(hDlg, id, m, w, l))
+#define CSendMessage(hwnd, m, w, l) IsWindow(hwnd) ? SendMessage(hwnd, m, w, l) : 0
+#define CShowWindow(hwnd, state) IsWindow(hwnd) ? ShowWindow(hwnd, state) : 0
+
+#define GETITEMTEXT(id, cp, maxlen) \
+  GetDlgItemText(hDialog, id, (LPSTR)(cp), maxlen)
+#define CloseMe(x) SendMessage(hDialog, WM_COMMAND, ID_CLOSEME, x)
+
+
+#define EDITFRAMEIDOFFSET               500
+
+    switch (message) {
+
+    case WM_INITDIALOG:
+
+        *( (LPLSH_DLGINFO far *)(&lpdi) ) = (LPLSH_DLGINFO)(LPSTR)lParam;
+        lpdi->dlgstatemax = ISCHPASSWD ? STATE_NEWPWD2
+            : STATE_OLDPWD;
+        SetWindowText(hDialog, lpdi->title);
+        /* stop at old password for normal password dlg */
+
+        SetProp(hDialog, "HANDLES_HELP", (HANDLE)1);
+
+        if (lpdi->principal)
+            lstrcpy(principal, lpdi->principal);
+        else
+       {
+            principal[0] = '\0';
+            /* is there a principal already being used? if so, use it. */
+           }
+
+        CSetDlgItemText(hDialog, ID_PRINCIPAL, principal);
+
+        lifetime = Leash_get_default_lifetime();
+        if (lifetime <= 0)
+            lifetime = 600; /* 10 hours */
+
+        CSetDlgItemInt(hDialog, ID_DURATION, lifetime, FALSE);
+
+        /* setup text of stuff. */
+
+        if (Position.x > 0 && Position.y > 0 &&
+            Position.x < GetSystemMetrics(SM_CXSCREEN) &&
+            Position.y < GetSystemMetrics(SM_CYSCREEN))
+            SetWindowPos(hDialog, 0, Position.x, Position.y, 0, 0,
+                         SWP_NOSIZE | SWP_NOZORDER);
+
+        /* set window pos to last saved window pos */
+
+
+        /* replace standard edit control with our own password edit
+           control for password entry. */
+        {
+            RECT r;
+            POINT pxy, psz;
+            HWND hwnd;
+            int i;
+
+            for (i = ID_OLDPASSWORD; i <= ids[lpdi->dlgstatemax]; i++)
+            {
+                hwnd = GetDlgItem(hDialog, i);
+                GetWindowRect(hwnd, &r);
+                psz.x = r.right - r.left;
+                psz.y = r.bottom - r.top;
+
+                pxy.x = r.left; pxy.y = r.top;
+                ScreenToClient(hDialog, &pxy);
+
+                /* create a substitute window: */
+
+                DestroyWindow(hwnd);
+                /* kill off old edit window. */
+
+                CreateWindow(MIT_PWD_DLL_CLASS,        /* our password window :o] */
+                             "",               /* no text */
+                             WS_CHILD | WS_VISIBLE | WS_TABSTOP, /* child window, visible,tabstop */
+                             pxy.x, pxy.y,     /* x, y coords */
+                             psz.x, psz.y,     /* width, height */
+                             hDialog,          /* the parent */
+                             (HMENU)i,         /* same id *//* id offset for the frames */
+                             (HANDLE)hLeashInst,/* instance handles */
+                             NULL);            /* createstruct */
+            }
+        }
+
+        state = STATE_INIT;
+        NEXTSTATE(STATE_PRINCIPAL);
+        break;
+
+    case WM_PAINT:
+        PaintLogoBitmap( GetDlgItem(hDialog, ID_PICFRAME) );
+        break;
+
+    case WM_COMMAND:
+        switch (wParam) {
+        case ID_HELP:
+       {
+            WinHelp(GetWindow(hDialog,GW_OWNER), KRB_HelpFile, HELP_CONTEXT,
+                    ISCHPASSWD ? ID_CHANGEPASSWORD : ID_INITTICKETS);
+       }
+       break;
+        case ID_CLOSEME:
+       {
+            int i;
+
+            for (i = STATE_PRINCIPAL; i <= lpdi->dlgstatemax; i++)
+           {
+                memset(strings[i], '\0', 255);
+                SetDlgItemText(hDialog, ids[i], "");
+           }
+            /* I claim these passwords in the name
+               of planet '\0'... */
+
+            RemoveProp(hDialog, "HANDLES_HELP");
+            state = STATE_CLOSED;
+            EndDialog(hDialog, (int)lParam);
+        return TRUE;
+       }
+       break;
+        case ID_DURATION:
+            break;
+        case ID_PRINCIPAL:
+        case ID_OLDPASSWORD:
+        case ID_CONFIRMPASSWORD1:
+        case ID_CONFIRMPASSWORD2:
+            if (HIWORD(lParam) == EN_SETFOCUS)
+            {
+                /* nothing, for now. */
+            }
+            break;
+        case ID_NEXTSTATE:
+       {
+            RECT rbtn, redit;
+            POINT p;
+            int idfocus, i, s;
+            HWND hfocus, hbtn;
+            int oldstate = state;
+
+            state = (int)lParam;
+            idfocus = ids[state];
+
+#ifdef ONE_NEWPWDBOX
+            if (state == STATE_NEWPWD2)
+                SendDlgItemMessage(hDialog, ID_CONFIRMPASSWORD1, WM_SETTEXT,
+                                   0, (LONG)(LPSTR)"");
+#endif
+
+            for (s = STATE_PRINCIPAL; s <= lpdi->dlgstatemax; s++)
+           {
+                i = ids[s];
+
+                if (s > state)
+                    SendDlgItemMessage(hDialog, i, WM_SETTEXT, 0,
+                                       (LONG)(LPSTR)"");
+                EnableWindow(GetDlgItem(hDialog, i), i == idfocus);
+                ShowWindow(GetDlgItem(hDialog, i),
+                           (i <= idfocus ? SW_SHOW : SW_HIDE));
+                /* ShowWindow(GetDlgItem(hDialog, i + CAPTION_OFFSET),
+                   (i <= idfocus ? SW_SHOW : SW_HIDE));*/
+                /* show caption? */
+           }
+#ifdef ONE_NEWPWDBOX
+            CSetDlgItemText(hDialog, ID_CONFIRMCAPTION1,
+                            state < STATE_NEWPWD2 ?
+                            "Enter new password:" :
+                            "Enter new password again:");
+            if (state == STATE_NEWPWD2)
+           {
+                HWND htext;
+                htext = GetDlgItem(hDialog, ID_CONFIRMCAPTION1);
+                FlashAnyWindow(htext);
+                WinSleep(50);
+                FlashAnyWindow(htext);
+           }
+#endif
+
+            hfocus = GetDlgItem(hDialog, idfocus);
+            if ( hfocus != (HWND)NULL ){
+                SetFocus(hfocus); /* switch focus */
+                if (idfocus >= ID_OLDPASSWORD)
+                    SendMessage(hfocus, WM_SETTEXT, 0, (LPARAM) (LPSTR) "");
+                else
+                {
+                    SendMessage(hfocus, EM_SETSEL, 0, MAKELONG(0, -1));
+                }
+                GetWindowRect(hfocus, &redit);
+            }
+
+            hbtn   = GetDlgItem(hDialog, IDOK);
+            if( IsWindow(hbtn) ){
+                GetWindowRect(hbtn, &rbtn);
+                p.x = rbtn.left; p.y = redit.top;
+                ScreenToClient(hDialog, &p);
+
+                SetWindowPos(hbtn, 0, p.x, p.y, 0, 0,
+                             SWP_NOSIZE | SWP_NOZORDER);
+            }
+       }
+       break;
+        case IDOK:
+       {
+           char* p_Principal;
+            DWORD value = 0;
+
+           GETITEMTEXT(ids[state], (LPSTR)strings[state], 255);
+
+            switch(state)
+            {
+            case STATE_PRINCIPAL:
+            {
+                if (!principal[0])
+                {
+                    MessageBox(hDialog,
+                                "You are not allowed to enter a blank principal.",
+                               "Invalid Principal",
+                               MB_OK | MB_ICONSTOP);
+                    NEXTSTATE(STATE_PRINCIPAL);
+                    return TRUE;
+                }
+
+               // Change 'principal' to upper case after checking
+               // "UpperCase" value in the Registry
+                p_Principal = strchr(principal, '@');
+
+                if (p_Principal && Leash_get_default_uppercaserealm())
+                    strupr(p_Principal);
+                break;
+            }
+           case STATE_OLDPWD:
+            {
+               int duration;
+
+               if (!ISCHPASSWD)
+                    duration = GetDlgItemInt(hDialog, ID_DURATION, 0, FALSE);
+                if (!oldpassword[0])
+                {
+                    MessageBox(hDialog, "You are not allowed to enter a "
+                               "blank password.",
+                               "Invalid Password",
+                               MB_OK | MB_ICONSTOP);
+                    NEXTSTATE(STATE_OLDPWD);
+                    return TRUE;
+                }
+                if (lpdi->dlgtype == DLGTYPE_CHPASSWD)
+                    lsh_errno = Leash_int_checkpwd(principal, oldpassword, 1);
+                else
+                {
+                    lsh_errno = Leash_int_kinit_ex( 0,
+                                                    hDialog,
+                                                    principal,
+                                                    oldpassword,
+                                                    duration,
+                                                    Leash_get_default_forwardable(),
+                                                    Leash_get_default_proxiable(),
+                                                    Leash_get_default_renew_till(),
+                                                    Leash_get_default_noaddresses(),
+                                                    Leash_get_default_publicip(),
+                                                    1
+                                                    );
+                }
+               if (lsh_errno != 0)
+                {
+                   int next_state = state;
+                   int capslock;
+                   LONG check_time;
+                   char *cp;
+
+                   err_context = "";
+
+                   switch(lsh_errno)
+                    {
+                    case LSH_INVPRINCIPAL:
+                    case LSH_INVINSTANCE:
+                    case LSH_INVREALM:
+#ifndef NO_KRB4
+                    case KRBERR(KDC_PR_UNKNOWN):
+#endif
+                       next_state = STATE_PRINCIPAL;
+                       break;
+#ifndef NO_KRB4
+                    case KRBERR(RD_AP_TIME):
+                    case KRBERR(KDC_SERVICE_EXP):
+                        check_time = Leash_timesync(1);
+                        if( check_time == 0 ){
+                            next_state = STATE_PRINCIPAL;
+                            SendMessage(hDialog, WM_COMMAND, IDOK, state);
+                            return(TRUE);
+                        } else {
+                            next_state = STATE_PRINCIPAL;
+                            lsh_errno = check_time;
+                            return(TRUE);
+                        }
+                        break;
+#endif
+                    }
+                   capslock = lsh_getkeystate(VK_CAPITAL);
+                    /* low-order bit means caps lock is
+                       toggled; if so, warn user since there's
+                       been an error. */
+                   if (capslock & 1)
+                    {
+                       lstrcpy((LPSTR)gbuf, (LPSTR)err_context);
+                       cp = gbuf + lstrlen((LPSTR)gbuf);
+                       if (cp != gbuf)
+                            *cp++ = ' ';
+                       lstrcpy(cp, "(This may be because your CAPS LOCK key is down.)");
+                       err_context = gbuf;
+                    }
+
+// XXX             DoNiftyErrorReport(lsh_errno, ISCHPASSWD ? ""
+// XXX                                : "Ticket initialization failed.");
+                   NEXTSTATE(next_state);
+                   return TRUE;
+                }
+               if (ISCHPASSWD)
+                    break;
+               CloseMe(TRUE); /* success */
+            }
+            break;
+           case STATE_NEWPWD1:
+            {
+                int i = 0;
+                int bit8 = 0;
+
+                for( i = 0; i < 255; i++ ){
+                    if( newpassword[i] == '\0' ){
+                        if ( bit8 ) {
+                            MessageBox(hDialog,
+                                        "Passwords should not contain non-ASCII characters.",
+                                        "Internationalization Warning",
+                                        MB_OK | MB_ICONINFORMATION);
+                        }
+                        i = 255;
+                        break;
+                    } else if( !isprint(newpassword[i]) ){
+                        memset(newpassword, '\0', 255);
+                        /* I claim these passwords in the name of planet '\0'... */
+                        MessageBox(hDialog,
+                                   "Passwords may not contain non-printable characters.",
+                                    "Invalid Password",
+                                    MB_OK | MB_ICONSTOP);
+                        NEXTSTATE(STATE_NEWPWD1);
+                        return TRUE;
+                    } else if ( newpassword[i] > 127 )
+                        bit8 = 1;
+                }
+            }
+            break;
+           case STATE_NEWPWD2:
+                if (lstrcmp(newpassword, newpassword2))
+                {
+                    NEXTSTATE(STATE_NEWPWD1);
+                    MessageBox(hDialog,
+                                "The new password was not entered the same way twice.",
+                                "Password validation error",
+                                MB_OK | MB_ICONSTOP);
+                    return TRUE;
+                }
+                else
+                {
+                    /* make them type both pwds again if error */
+                    int next_state = STATE_NEWPWD1;
+                    int capslock;
+                    char *cp;
+
+                    capslock = lsh_getkeystate(VK_CAPITAL);
+                    /* low-order bit means caps lock is
+                       toggled; if so, warn user since there's
+                       been an error. */
+                    if (capslock & 1)
+                    {
+                        lstrcpy((LPSTR)gbuf, (LPSTR)err_context);
+                        cp = gbuf + lstrlen((LPSTR)gbuf);
+                        if (cp != gbuf)
+                            *cp++ = ' ';
+                        lstrcpy(cp, "(This may be because your CAPS LOCK key is down.)");
+                        err_context = gbuf;
+                    }
+
+                    if ((lsh_errno =
+                         Leash_int_changepwd(principal, oldpassword,
+                                         newpassword, 0, 1))
+                        == 0){
+                        CloseMe(TRUE);
+                    }
+                    else {
+                        // XXX - DoNiftyErrorReport(lsh_errno, "Error while changing password.");
+                        NEXTSTATE(next_state);
+                        return TRUE;
+
+                    }
+               }
+                break;
+           }
+            /* increment state, but send the old state as a
+               parameter */
+            SendMessage(hDialog, WM_COMMAND, ID_NEXTSTATE, state + 1);
+       }
+       break;
+        case IDCANCEL:
+            CloseMe(FALSE);
+            break;
+        case ID_RESTART:
+       {
+            int i;
+
+            for (i = ID_OLDPASSWORD; i <= ids[lpdi->dlgstatemax]; i++)
+                SetDlgItemText(hDialog, i, "");
+            SendMessage(hDialog, WM_COMMAND, ID_NEXTSTATE,
+                        STATE_PRINCIPAL);
+       }
+       break;
+        }
+        break;
+
+    case WM_MOVE:
+        if (state != STATE_CLOSED)
+#ifdef _WIN32
+#define LONG2POINT(l,pt) ((pt).x=(SHORT)LOWORD(l),  \
+                         (pt).y=(SHORT)HIWORD(l))
+            LONG2POINT(lParam,Position);
+#else
+        Position = MAKEPOINT(lParam);
+#endif
+        break;
+    }
+    return FALSE;
+}
+
+
+#define KRB_FILE                "KRB.CON"
+#define KRBREALM_FILE           "KRBREALM.CON"
+#define KRB5_FILE               "KRB5.INI"
+
+BOOL
+GetProfileFile(
+    LPSTR confname,
+    UINT szConfname
+    )
+{
+    char **configFile = NULL;
+    if (hKrb5 &&
+         pkrb5_get_default_config_files(&configFile))
+    {
+        GetWindowsDirectory(confname,szConfname);
+        confname[szConfname-1] = '\0';
+        strncat(confname, "\\",sizeof(confname)-strlen(confname));
+        confname[szConfname-1] = '\0';
+        strncat(confname, KRB5_FILE,sizeof(confname)-strlen(confname));
+        confname[szConfname-1] = '\0';
+        return FALSE;
+    }
+
+    *confname = 0;
+
+    if (hKrb5 && configFile)
+    {
+        strncpy(confname, *configFile, szConfname);
+        pkrb5_free_config_files(configFile);
+    }
+
+    if (!*confname)
+    {
+        GetWindowsDirectory(confname,szConfname);
+        confname[szConfname-1] = '\0';
+        strncat(confname, "\\",sizeof(confname)-strlen(confname));
+        confname[szConfname-1] = '\0';
+        strncat(confname, KRB5_FILE,sizeof(confname)-strlen(confname));
+        confname[szConfname-1] = '\0';
+    }
+
+    return FALSE;
+}
+
+BOOL
+GetKrb4ConFile(
+    LPSTR confname,
+    UINT szConfname
+    )
+{
+    if (hKrb5
+#ifndef NO_KRB4
+         && !hKrb4
+#endif
+         )
+    { // hold krb.con where krb5.ini is located
+        CHAR krbConFile[MAX_PATH]="";
+        LPSTR pFind;
+
+        //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename);
+        if (GetProfileFile(krbConFile, sizeof(krbConFile)))
+        {
+            GetWindowsDirectory(krbConFile,sizeof(krbConFile));
+            krbConFile[MAX_PATH-1] = '\0';
+            strncat(krbConFile, "\\",sizeof(krbConFile)-strlen(krbConFile));
+            krbConFile[MAX_PATH-1] = '\0';
+            strncat(krbConFile, KRB5_FILE,sizeof(krbConFile)-strlen(krbConFile));
+            krbConFile[MAX_PATH-1] = '\0';
+        }
+
+        pFind = strrchr(krbConFile, '\\');
+        if (pFind)
+        {
+            *pFind = 0;
+            strncat(krbConFile, "\\",sizeof(krbConFile)-strlen(krbConFile));
+            krbConFile[MAX_PATH-1] = '\0';
+            strncat(krbConFile, KRB_FILE,sizeof(krbConFile)-strlen(krbConFile));
+            krbConFile[MAX_PATH-1] = '\0';
+        }
+        else
+            krbConFile[0] = 0;
+
+        strncpy(confname, krbConFile, szConfname);
+        confname[szConfname-1] = '\0';
+    }
+#ifndef NO_KRB4
+    else if (hKrb4)
+    {
+        unsigned int size = szConfname;
+        memset(confname, '\0', szConfname);
+        if (!pkrb_get_krbconf2(confname, &size))
+        { // Error has happened
+            GetWindowsDirectory(confname,szConfname);
+            confname[szConfname-1] = '\0';
+            strncat(confname, "\\",szConfname-strlen(confname));
+            confname[szConfname-1] = '\0';
+            strncat(confname,KRB_FILE,szConfname-strlen(confname));
+            confname[szConfname-1] = '\0';
+        }
+    }
+#endif
+    return FALSE;
+}
+
+BOOL
+GetKrb4RealmFile(
+    LPSTR confname,
+    UINT szConfname
+    )
+{
+    if (hKrb5
+#ifndef NO_KRB4
+         && !hKrb4
+#endif
+         )
+    { // hold krb.con where krb5.ini is located
+        CHAR krbRealmConFile[MAX_PATH];
+        LPSTR pFind;
+
+        //strcpy(krbRealmConFile, CLeashApp::m_krbv5_profile->first_file->filename);
+        if (GetProfileFile(krbRealmConFile, sizeof(krbRealmConFile)))
+        {
+            GetWindowsDirectory(krbRealmConFile,sizeof(krbRealmConFile));
+            krbRealmConFile[MAX_PATH-1] = '\0';
+            strncat(krbRealmConFile, "\\",sizeof(krbRealmConFile)-strlen(krbRealmConFile));
+            krbRealmConFile[MAX_PATH-1] = '\0';
+            strncat(krbRealmConFile, KRB5_FILE,sizeof(krbRealmConFile)-strlen(krbRealmConFile));
+            krbRealmConFile[MAX_PATH-1] = '\0';
+        }
+
+        pFind = strrchr(krbRealmConFile, '\\');
+        if (pFind)
+        {
+            *pFind = 0;
+            strncat(krbRealmConFile, "\\", sizeof(krbRealmConFile)-strlen(krbRealmConFile));
+            krbRealmConFile[MAX_PATH-1] = '\0';
+            strncat(krbRealmConFile, KRBREALM_FILE, sizeof(krbRealmConFile)-strlen(krbRealmConFile));
+            krbRealmConFile[MAX_PATH-1] = '\0';
+        }
+        else
+            krbRealmConFile[0] = 0;
+
+        strncpy(confname, krbRealmConFile, szConfname);
+        confname[szConfname-1] = '\0';
+    }
+#ifndef NO_KRB4
+    else if (hKrb4)
+    {
+        unsigned int size = szConfname;
+        memset(confname, '\0', szConfname);
+        if (!pkrb_get_krbrealm2(confname, &size))
+        {
+            GetWindowsDirectory(confname,szConfname);
+            confname[szConfname-1] = '\0';
+            strncat(confname, "\\",szConfname-strlen(confname));
+            confname[szConfname-1] = '\0';
+            strncat(confname,KRBREALM_FILE,szConfname-strlen(confname));
+            confname[szConfname-1] = '\0';
+            return TRUE;
+        }
+    }
+#endif
+    return FALSE;
+}
+
+static BOOL
+FindDLLName(CHAR * filename, UINT len)
+{
+    if ( !filename || len == 0 )
+        return 0;
+
+    filename[0] = 0;
+
+    if ( pEnumProcessModules ) {
+        char checkName[1024];
+        HMODULE hMods[1024];
+        HANDLE hProcess;
+        DWORD cbNeeded;
+        unsigned int i;
+
+        /* Get a list of all the modules in this process. */
+        hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
+
+        if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
+        {
+            for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
+            {
+                char szModName[2048];
+
+                /* Get the full path to the module's file. */
+                if (pGetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName)))
+                {
+                    lstrcpyn(checkName, szModName, sizeof(checkName));
+                    strupr(checkName);
+
+                    if (strstr(checkName, "LEASHW32")) {
+                        lstrcpyn(filename, checkName, len);
+                        break;
+                    }
+                }
+            }
+        }
+
+        CloseHandle(hProcess);
+    } else if (pCreateToolhelp32Snapshot && pModule32First && pModule32Next ) {
+        char checkName[1024];
+        MODULEENTRY32 me32 = {0};
+        HANDLE hProcessSnap = NULL;
+
+        hProcessSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
+        if (hProcessSnap == (HANDLE)-1)
+            return FALSE;
+
+        me32.dwSize = sizeof(MODULEENTRY32);
+        if (pModule32First(hProcessSnap, &me32))
+        {
+            do
+            {
+                lstrcpyn(checkName, me32.szExePath, sizeof(checkName));
+                strupr(checkName);
+
+                if (strstr(checkName, "LEASHW32")) {
+                    lstrcpyn(filename, checkName, len);
+                    break;
+                }
+            }
+            while (pModule32Next(hProcessSnap, &me32));
+        }
+    }
+
+    return filename[0] ? 1 : 0;
+}
+
+static DWORD
+SetVersionInfo(
+    HWND hDialog,
+    UINT id_version,
+    UINT id_copyright
+    )
+{
+    CHAR filename[1024];
+    DWORD dwVersionHandle;
+    LPVOID pVersionInfo = 0;
+    DWORD retval = 0;
+    LPDWORD pLangInfo = 0;
+    LPTSTR szVersion = 0;
+    LPTSTR szCopyright = 0;
+    UINT len = 0;
+    CHAR sname_version[] = "FileVersion";
+    CHAR sname_copyright[] = "LegalCopyright";
+    CHAR szVerQ[(sizeof("\\StringFileInfo\\12345678\\") +
+                  max(sizeof(sname_version) / sizeof(CHAR),
+                      sizeof(sname_copyright) / sizeof(CHAR)))];
+    CHAR szVerCopy[128] = "";
+    CHAR * cp = szVerQ;
+    DWORD size;
+
+    if (!FindDLLName(filename, sizeof(filename)))
+        return GetLastError();
+
+    size = GetFileVersionInfoSize(filename, &dwVersionHandle);
+
+    if (!size)
+        return GetLastError();
+
+    pVersionInfo = malloc(size);
+    if (!pVersionInfo)
+        return ERROR_NOT_ENOUGH_MEMORY;
+
+    if (!GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo))
+    {
+        retval = GetLastError();
+        goto cleanup;
+    }
+
+    if (!VerQueryValue(pVersionInfo, "\\VarFileInfo\\Translation",
+                       (LPVOID*)&pLangInfo, &len))
+    {
+        retval = GetLastError();
+        goto cleanup;
+    }
+
+
+    cp += wsprintf(szVerQ,
+                   "\\StringFileInfo\\%04x%04x\\",
+                   LOWORD(*pLangInfo), HIWORD(*pLangInfo));
+
+    lstrcpy(cp, sname_version);
+    if (!VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len))
+    {
+        retval = GetLastError() || ERROR_NOT_ENOUGH_MEMORY;
+        goto cleanup;
+    }
+
+    lstrcpy(cp, sname_copyright);
+    if (!VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szCopyright, &len))
+    {
+        retval = GetLastError() || ERROR_NOT_ENOUGH_MEMORY;
+        goto cleanup;
+    }
+
+    if ( strlen(szVersion) < sizeof(szVerCopy) - 8 ) {
+        wsprintf(szVerCopy, "Version %s", szVersion);
+        szVerCopy[sizeof(szVerCopy) - 1] = 0;
+
+        SetWindowText(GetDlgItem(hDialog,id_version),szVerCopy);
+    }
+    SetWindowText(GetDlgItem(hDialog,id_copyright),szCopyright);
+
+ cleanup:
+    if (pVersionInfo)
+        free(pVersionInfo);
+    return retval;
+}
+
+
+int
+readstring(FILE * file, char * buf, int len)
+{
+       int  c,i;
+       memset(buf, '\0', sizeof(buf));
+       for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++)
+       {
+               if (i < sizeof(buf)) {
+                       if (c == '\n') {
+                               buf[i] = '\0';
+                               return i;
+                       } else {
+                               buf[i] = c;
+                       }
+               } else {
+                       if (c == '\n') {
+                               buf[len-1] = '\0';
+                               return(i);
+                       }
+               }
+       }
+       if (c == EOF) {
+               if (i > 0 && i < len) {
+                       buf[i] = '\0';
+                       return(i);
+               } else {
+                       buf[len-1] = '\0';
+                       return(-1);
+               }
+       }
+    return(-1);
+}
+
+typedef struct _slider_info {
+       int slider_id;
+       int text_id;
+       int min;
+       int max;
+       int increment;
+       struct _slider_info * next;
+} slider_info;
+static slider_info * sliders = NULL;
+
+static slider_info *
+FreeSlider(slider_info * s)
+{
+       slider_info * n = NULL;
+
+       if (s) {
+               n = s->next;
+               free(s);
+       }
+       return n;
+}
+
+static void
+CleanupSliders(void)
+{
+       while(sliders)
+               sliders = FreeSlider(sliders);
+}
+
+
+static unsigned short
+NewSliderValue(HWND hDialog, int id)
+{
+       int value = 0;
+       slider_info * s = sliders;
+       while(s) {
+               if (s->slider_id == id) {
+                       int pos = CSendDlgItemMessage( hDialog, id,
+                                                                                TBM_GETPOS,
+                                                                                (WPARAM) 0, (LPARAM) 0);
+                       value = s->min + (pos * s->increment);
+                       break;
+               }
+               s = s->next;
+       }
+       return(value);
+}
+
+static const char *
+NewSliderString(int id, int pos)
+{
+       static char buf[64]="";
+       char * p = buf;
+       int value = 0;
+       int must_hours = 0;
+       slider_info * s = sliders;
+       while(s) {
+               if (s->slider_id == id) {
+                       value = s->min + pos * s->increment;
+                       *p = 0;
+                       if (value >= 60 * 24) {
+                               sprintf(p,"%d day(s) ",value / (60 * 24));
+                               value %= (60 * 24);
+                               p += strlen(p);
+                               must_hours = 1;
+                       }
+                       if (must_hours || value >= 60) {
+                               sprintf(p,"%d hour(s) ",value / 60);
+                               value %= 60;
+                               p += strlen(p);
+                       }
+                       sprintf(p,"%d minute(s) ",value);
+                       break;
+               }
+               s = s->next;
+       }
+       return(buf);
+}
+
+static void
+SetupSlider( HWND hDialog,
+                        int sliderID,
+                        int textFieldID,
+                        int minimum,
+                        int maximum,
+                        int value)
+{
+    int min = minimum;
+    int max = maximum;
+    int increment = 0;
+    int range;
+       int roundedMinimum;
+       int roundedMaximum;
+       int roundedValue;
+       slider_info * new_info;
+
+    if (max < min) {
+        // swap values
+        int temp = max;
+        max = min;
+        min = temp;
+    }
+       range = max - min;
+
+    if (range < 5*60)             { increment = 1;       //  1 s if under   5 m
+    } else if (range < 30*60)     { increment = 5;       //  5 s if under  30 m
+    } else if (range < 60*60)     { increment = 15;      // 15 s if under   1 h
+    } else if (range < 2*60*60)   { increment = 30;      // 30 s if under   2 h
+    } else if (range < 5*60*60)   { increment = 60;      //  1 m if under   5 h
+    } else if (range < 50*60*60)  { increment = 5*60;    //  5 m if under  50 h
+    } else if (range < 200*60*60) { increment = 15*60;   // 15 m if under 200 h
+    } else if (range < 500*60*60) { increment = 30*60;   // 30 m if under 500 h
+    } else                        { increment = 60*60; } //  1 h otherwise
+
+    roundedMinimum = (min / increment) * increment;
+    if (roundedMinimum > min) { roundedMinimum -= increment; }
+    if (roundedMinimum <= 0)  { roundedMinimum += increment; } // make positive
+
+    roundedMaximum = (max / increment) * increment;
+    if (roundedMaximum < max) { roundedMaximum += increment; }
+
+    roundedValue = (value / increment) * increment;
+    if (roundedValue < roundedMinimum) { roundedValue = roundedMinimum; }
+    if (roundedValue > roundedMaximum) { roundedValue = roundedMaximum; }
+
+    if (roundedMinimum == roundedMaximum) {
+        // [textField setTextColor: [NSColor grayColor]];
+               EnableWindow(GetDlgItem(hDialog,sliderID),FALSE);
+    } else {
+        // [textField setTextColor: [NSColor blackColor]];
+               EnableWindow(GetDlgItem(hDialog,sliderID),TRUE);
+    }
+
+       CSendDlgItemMessage( hDialog, sliderID,
+                                                TBM_SETRANGEMIN,
+                                                (WPARAM) FALSE,
+                                                (LPARAM) 0 );
+       CSendDlgItemMessage( hDialog, sliderID,
+                                                TBM_SETRANGEMAX,
+                                                (WPARAM) FALSE,
+                                                (LPARAM) (roundedMaximum - roundedMinimum) / increment );
+       CSendDlgItemMessage( hDialog, sliderID,
+                                                TBM_SETPOS,
+                                                (WPARAM) TRUE,
+                                                (LPARAM) (roundedValue - roundedMinimum) / increment);
+
+       new_info = (slider_info *) malloc(sizeof(slider_info));
+       new_info->slider_id = sliderID;
+       new_info->text_id = textFieldID;
+       new_info->min = roundedMinimum;
+       new_info->max = roundedMaximum;
+       new_info->increment = increment;
+       new_info->next = sliders;
+       sliders = new_info;
+
+       SetWindowText(GetDlgItem(hDialog, textFieldID),
+                                  NewSliderString(sliderID,(roundedValue - roundedMinimum) / increment));
+}
+
+
+static void
+AdjustOptions(HWND hDialog, int show, int hideDiff)
+{
+    RECT rect;
+    RECT dlgRect;
+    HWND hwnd;
+    int diff;
+
+    Leash_set_hide_kinit_options(!show);
+
+    ShowWindow(GetDlgItem(hDialog,IDC_STATIC_LIFETIME),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_STATIC_LIFETIME_VALUE),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_SLIDER_LIFETIME),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_SLIDER_RENEWLIFE),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_STATIC_RENEW),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_STATIC_RENEW_TILL_VALUE),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_CHECK_FORWARDABLE),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_CHECK_NOADDRESS),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_CHECK_RENEWABLE),show);
+    ShowWindow(GetDlgItem(hDialog,IDC_STATIC_KRB5),show);
+
+    GetWindowRect( hDialog, &dlgRect );
+    diff = dlgRect.top + GetSystemMetrics(SM_CYCAPTION)
+         + GetSystemMetrics(SM_CYDLGFRAME) + (show ? -1 : 1) * hideDiff;
+
+    hwnd = GetDlgItem(hDialog,IDOK);
+    GetWindowRect(hwnd,&rect);
+    SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE);
+    hwnd = GetDlgItem(hDialog,IDCANCEL);
+    GetWindowRect(hwnd,&rect);
+    SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE);
+    hwnd = GetDlgItem(hDialog,IDC_BUTTON_OPTIONS);
+    GetWindowRect(hwnd,&rect);
+    SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE);
+    hwnd = GetDlgItem(hDialog,IDC_STATIC_VERSION);
+    GetWindowRect(hwnd,&rect);
+    SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE);
+    hwnd = GetDlgItem(hDialog,IDC_STATIC_COPYRIGHT);
+    GetWindowRect(hwnd,&rect);
+    SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE);
+    SetWindowPos(hDialog,0,0,0,
+                 dlgRect.right-dlgRect.left,
+                 dlgRect.bottom-dlgRect.top+(show ? 1 : - 1) * hideDiff,
+                 SWP_NOZORDER|SWP_NOMOVE);
+
+    CSetDlgItemText(hDialog, IDC_BUTTON_OPTIONS, show ? "Hide Options" : "Show Options");
+
+}
+
+
+/* Callback function for the Authentication Dialog box that initializes and
+   renews tickets. */
+
+INT_PTR
+CALLBACK
+AuthenticateProc(
+    HWND hDialog,
+    UINT message,
+    WPARAM wParam,
+    LPARAM lParam
+    )
+{
+    static POINT Position = { -1, -1 };
+    static char username[LEASH_USERNAME_SZ]="";
+    static char realm[LEASH_REALM_SZ]="";
+    static char password[256]="";
+    static int  lifetime=0;
+    static int  renew_till=0;
+    static int  forwardable=0;
+    static int  noaddresses=0;
+    static int  proxiable=0;
+    static int  publicip=0;
+    static LPLSH_DLGINFO_EX lpdi;
+    static HWND hDlg=0;
+    static HWND hSliderLifetime=0;
+    static HWND hSliderRenew=0;
+    static RECT dlgRect;
+    static int  hideDiff = 0;
+    char principal[256];
+    long realm_count = 0;
+    int disable_noaddresses = 0;
+
+    switch (message) {
+
+    case WM_INITDIALOG:
+       hDlg = hDialog;
+
+        SetVersionInfo(hDialog,IDC_STATIC_VERSION,IDC_STATIC_COPYRIGHT);
+       hSliderLifetime = GetDlgItem(hDialog, IDC_STATIC_LIFETIME_VALUE);
+       hSliderRenew = GetDlgItem(hDialog, IDC_STATIC_RENEW_TILL_VALUE);
+
+        *( (LPLSH_DLGINFO_EX far *)(&lpdi) ) = (LPLSH_DLGINFO_EX)(LPSTR)lParam;
+
+       if ((lpdi->size != LSH_DLGINFO_EX_V1_SZ &&
+            lpdi->size != LSH_DLGINFO_EX_V2_SZ &&
+             lpdi->size < LSH_DLGINFO_EX_V3_SZ) ||
+            lpdi->dlgtype != DLGTYPE_PASSWD) {
+
+           MessageBox(hDialog, "An incorrect initialization data structure was provided.",
+                       "AuthenticateProc()",
+                       MB_OK | MB_ICONSTOP);
+           return FALSE;
+       }
+
+        if ( lpdi->size >= LSH_DLGINFO_EX_V2_SZ ) {
+            lpdi->out.username[0] = 0;
+            lpdi->out.realm[0] = 0;
+        }
+        if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ ) {
+            lpdi->out.ccache[0] = 0;
+        }
+
+        if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ )
+           SetWindowText(hDialog, lpdi->in.title);
+       else
+           SetWindowText(hDialog, lpdi->title);
+
+        SetProp(hDialog, "HANDLES_HELP", (HANDLE)1);
+
+        if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ )
+            lstrcpy(username, lpdi->in.username);
+        else if (lpdi->username)
+            lstrcpy(username, lpdi->username);
+        if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ )
+           lstrcpy(realm, lpdi->in.realm);
+       else if (lpdi->realm)
+           lstrcpy(realm, lpdi->realm);
+
+       if (lpdi->use_defaults) {
+           lifetime = Leash_get_default_lifetime();
+           if (lifetime <= 0)
+               lifetime = 600; /* 10 hours */
+           if (Leash_get_default_renewable()) {
+                renew_till = Leash_get_default_renew_till();
+                if (renew_till < 0)
+                    renew_till = 10800; /* 7 days */
+            } else
+                renew_till = 0;
+           forwardable = Leash_get_default_forwardable();
+           if (forwardable < 0)
+               forwardable = 0;
+           noaddresses = Leash_get_default_noaddresses();
+           if (noaddresses < 0)
+               noaddresses = 0;
+           proxiable = Leash_get_default_proxiable();
+           if (proxiable < 0)
+               proxiable = 0;
+           publicip = Leash_get_default_publicip();
+           if (publicip < 0)
+               publicip = 0;
+       } else {
+           forwardable = lpdi->forwardable;
+           noaddresses = lpdi->noaddresses;
+           lifetime = lpdi->lifetime;
+           renew_till = lpdi->renew_till;
+           proxiable = lpdi->proxiable;
+           publicip = lpdi->publicip;
+       }
+
+        CSetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, username);
+        CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD, "");
+
+#if 0  /* 20030619 - mjv wishes to return to the default character */
+        /* echo spaces */
+       CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD, EM_SETPASSWORDCHAR, 32, 0);
+#endif
+
+       /* Populate list of Realms */
+       CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_RESETCONTENT, 0, 0);
+       CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_LIMITTEXT, 192, 0);
+
+       if (pprofile_get_subsection_names && pprofile_free_list) {
+           const char*  rootSection[] = {"realms", NULL};
+           const char** rootsec = rootSection;
+           char **sections = NULL, **cpp = NULL, *value = NULL;
+
+           char krb5_conf[MAX_PATH+1];
+
+           if (!GetProfileFile(krb5_conf,sizeof(krb5_conf))) {
+               profile_t profile;
+               long retval;
+               const char *filenames[2];
+
+               filenames[0] = krb5_conf;
+               filenames[1] = NULL;
+               retval = pprofile_init(filenames, &profile);
+               if (!retval) {
+                   retval = pprofile_get_subsection_names(profile,     rootsec, &sections);
+
+                   if (!retval)
+                   {
+                       for (cpp = sections; *cpp; cpp++)
+                       {
+                           CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_ADDSTRING, 0, (LPARAM)*cpp);
+                           realm_count++;
+                       }
+                   }
+                   pprofile_free_list(sections);
+
+                    retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
+                    if ( value ) {
+                        disable_noaddresses = config_boolean_to_int(value);
+                        pprofile_release_string(value);
+                    }
+
+                   pprofile_release(profile);
+               }
+           }
+       } else {
+           FILE * file;
+           char krb_conf[MAX_PATH+1];
+           char * p;
+
+           if (!GetKrb4ConFile(krb_conf,sizeof(krb_conf)) &&
+                (file = fopen(krb_conf, "rt")))
+           {
+               char lineBuf[256];
+               // Skip the default realm
+               readstring(file,lineBuf,sizeof(lineBuf));
+
+               // Read the defined realms
+               while (TRUE)
+               {
+                   if (readstring(file,lineBuf,sizeof(lineBuf)) < 0)
+                       break;
+
+                   if (*(lineBuf + strlen(lineBuf) - 1) == '\r')
+                       *(lineBuf + strlen(lineBuf) - 1) = 0;
+
+                   for (p=lineBuf; *p ; p++)
+                   {
+                       if (isspace(*p)) {
+                           *p = 0;
+                           break;
+                       }
+                   }
+
+                   if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) {
+                       CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_ADDSTRING, 0, (LPARAM)lineBuf);
+                       realm_count++;
+                   }
+               }
+
+               fclose(file);
+           }
+       }
+       if (realm_count == 0)
+           CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_ADDSTRING, 0, (LPARAM)realm);
+
+       /* Select the default Realm */
+       if (!realm[0] && hKrb5) {
+           krb5_context ctx=0;
+           char * def = 0;
+           pkrb5_init_context(&ctx);
+           pkrb5_get_default_realm(ctx,&def);
+           if (def) {
+               lstrcpy(realm, def);
+               free(def);
+           }
+           pkrb5_free_context(ctx);
+       }
+       CSetDlgItemText(hDialog, IDC_COMBO_REALM, realm);
+
+       /* Set Lifetime Slider
+       *   min value = 5
+       *   max value = 1440
+       *   current value
+       */
+
+       SetupSlider( hDialog,
+                    IDC_SLIDER_LIFETIME,
+                    IDC_STATIC_LIFETIME_VALUE,
+                    Leash_get_default_life_min(),
+                    Leash_get_default_life_max(),
+                    lifetime );
+
+       /* Set Forwardable checkbox */
+       CheckDlgButton(hDialog, IDC_CHECK_FORWARDABLE, forwardable);
+       /* Set NoAddress checkbox */
+       CheckDlgButton(hDialog, IDC_CHECK_NOADDRESS, noaddresses);
+        if ( disable_noaddresses )
+            EnableWindow(GetDlgItem(hDialog,IDC_CHECK_NOADDRESS),FALSE);
+       /* Set Renewable checkbox */
+       CheckDlgButton(hDialog, IDC_CHECK_RENEWABLE, renew_till);
+       /* if not renewable, disable Renew Till slider */
+       /* if renewable, set Renew Till slider
+       *     min value
+       *     max value
+       *     current value
+       */
+       SetupSlider( hDialog,
+                    IDC_SLIDER_RENEWLIFE,
+                    IDC_STATIC_RENEW_TILL_VALUE,
+                    Leash_get_default_renew_min(),
+                    Leash_get_default_renew_max(),
+                    renew_till);
+       if (renew_till) {
+           EnableWindow(GetDlgItem(hDialog,IDC_SLIDER_RENEWLIFE),TRUE);
+       } else {
+           EnableWindow(GetDlgItem(hDialog,IDC_SLIDER_RENEWLIFE),FALSE);
+       }
+
+        // Compute sizes of items necessary to show/hide the advanced options
+        GetWindowRect( hDialog, &dlgRect );
+        {
+            RECT okRect, staticRect;
+            GetWindowRect(GetDlgItem(hDialog,IDC_STATIC_LIFETIME),&staticRect);
+            GetWindowRect(GetDlgItem(hDialog,IDOK),&okRect);
+            hideDiff = okRect.top - staticRect.top;
+        }
+
+        if ( hKrb5 ) {
+            if (Leash_get_hide_kinit_options())
+                AdjustOptions(hDialog,0,hideDiff);
+        } else {
+            AdjustOptions(hDialog,0,hideDiff);
+            EnableWindow(GetDlgItem(hDialog,IDC_BUTTON_OPTIONS),FALSE);
+            ShowWindow(GetDlgItem(hDialog,IDC_BUTTON_OPTIONS),SW_HIDE);
+        }
+
+        /* setup text of stuff. */
+
+        if (Position.x > 0 && Position.y > 0 &&
+            Position.x < GetSystemMetrics(SM_CXSCREEN) &&
+            Position.y < GetSystemMetrics(SM_CYSCREEN))
+            SetWindowPos(hDialog, HWND_TOP, Position.x, Position.y, 0, 0, SWP_NOSIZE);
+        else /* Center the window on the desktop */
+            SetWindowPos(hDialog, HWND_TOP,
+                         (GetSystemMetrics(SM_CXSCREEN) - dlgRect.right + dlgRect.left)/2,
+                         (GetSystemMetrics(SM_CYSCREEN) - dlgRect.bottom + dlgRect.top)/2,
+                         0, 0,
+                         SWP_NOSIZE);
+
+        /* Take keyboard focus */
+        SetActiveWindow(hDialog);
+        SetForegroundWindow(hDialog);
+        if (GetDlgCtrlID((HWND) wParam) != IDC_EDIT_PRINCIPAL)
+        {
+            SetFocus(GetDlgItem(hDialog, IDC_EDIT_PRINCIPAL));
+        }
+        break;
+
+       case WM_HSCROLL:
+       switch (LOWORD(wParam)) {
+       case TB_THUMBTRACK:
+       case TB_THUMBPOSITION:
+           {
+               long pos = HIWORD(wParam); // the position of the slider
+               int  ctrlID = GetDlgCtrlID((HWND)lParam);
+
+               if (ctrlID == IDC_SLIDER_RENEWLIFE) {
+                   SetWindowText(GetDlgItem(hDialog, IDC_STATIC_RENEW_TILL_VALUE),
+                                  NewSliderString(IDC_SLIDER_RENEWLIFE,pos));
+               }
+               if (ctrlID == IDC_SLIDER_LIFETIME) {
+                   SetWindowText(GetDlgItem(hDialog, IDC_STATIC_LIFETIME_VALUE),
+                                  NewSliderString(IDC_SLIDER_LIFETIME,pos));
+               }
+           }
+           break;
+        case TB_BOTTOM:
+        case TB_TOP:
+        case TB_ENDTRACK:
+        case TB_LINEDOWN:
+        case TB_LINEUP:
+        case TB_PAGEDOWN:
+        case TB_PAGEUP:
+       default:
+           {
+               int  ctrlID = GetDlgCtrlID((HWND)lParam);
+               long pos = SendMessage(GetDlgItem(hDialog,ctrlID), TBM_GETPOS, 0, 0); // the position of the slider
+
+               if (ctrlID == IDC_SLIDER_RENEWLIFE) {
+                   SetWindowText(GetDlgItem(hDialog, IDC_STATIC_RENEW_TILL_VALUE),
+                                  NewSliderString(IDC_SLIDER_RENEWLIFE,pos));
+               }
+               if (ctrlID == IDC_SLIDER_LIFETIME) {
+                   SetWindowText(GetDlgItem(hDialog, IDC_STATIC_LIFETIME_VALUE),
+                                  NewSliderString(IDC_SLIDER_LIFETIME,pos));
+               }
+           }
+       }
+        break;
+
+    case WM_COMMAND:
+        switch (wParam) {
+       case IDC_BUTTON_OPTIONS:
+           {
+                AdjustOptions(hDialog,Leash_get_hide_kinit_options(),hideDiff);
+                GetWindowRect(hDialog,&dlgRect);
+                if ( dlgRect.bottom > GetSystemMetrics(SM_CYSCREEN))
+                    SetWindowPos( hDialog,0,
+                                  dlgRect.left,
+                                  GetSystemMetrics(SM_CYSCREEN) - dlgRect.bottom + dlgRect.top,
+                                  0,0,
+                                  SWP_NOZORDER|SWP_NOSIZE);
+
+           }
+           break;
+       case IDC_CHECK_RENEWABLE:
+           {
+               if (IsDlgButtonChecked(hDialog, IDC_CHECK_RENEWABLE)) {
+                   EnableWindow(hSliderRenew,TRUE);
+               } else {
+                   EnableWindow(hSliderRenew,FALSE);
+               }
+           }
+           break;
+        case ID_HELP:
+           {
+               WinHelp(GetWindow(hDialog,GW_OWNER), KRB_HelpFile, HELP_CONTEXT,
+                        ID_INITTICKETS);
+           }
+           break;
+        case ID_CLOSEME:
+           {
+               CleanupSliders();
+               memset(password,0,sizeof(password));
+               RemoveProp(hDialog, "HANDLES_HELP");
+               EndDialog(hDialog, (int)lParam);
+                return TRUE;
+           }
+           break;
+        case IDOK:
+           {
+               DWORD value = 0;
+
+               CGetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, username, sizeof(username));
+               CGetDlgItemText(hDialog, IDC_EDIT_PASSWORD, password, sizeof(password));
+               CGetDlgItemText(hDialog, IDC_COMBO_REALM, realm, sizeof(realm));
+
+               if (!username[0])
+               {
+                   MessageBox(hDialog,
+                                "You are not allowed to enter a blank username.",
+                               "Invalid Principal",
+                               MB_OK | MB_ICONSTOP);
+                   return TRUE;
+               }
+               if (!realm[0])
+               {
+                   MessageBox(hDialog,
+                                "You are not allowed to enter a blank realm.",
+                               "Invalid Principal",
+                               MB_OK | MB_ICONSTOP);
+                   return TRUE;
+               }
+
+               if (Leash_get_default_uppercaserealm())
+               {
+                   // found
+                   strupr(realm);
+               }
+
+               if (!password[0])
+               {
+                   MessageBox(hDialog,
+                                "You are not allowed to enter a blank password.",
+                               "Invalid Password",
+                               MB_OK | MB_ICONSTOP);
+                   return TRUE;
+               }
+
+               lifetime = NewSliderValue(hDialog, IDC_SLIDER_LIFETIME);
+
+               forwardable = IsDlgButtonChecked(hDialog, IDC_CHECK_FORWARDABLE);
+               noaddresses = IsDlgButtonChecked(hDialog, IDC_CHECK_NOADDRESS);
+               if (IsDlgButtonChecked(hDialog, IDC_CHECK_RENEWABLE)) {
+                   renew_till = NewSliderValue(hDialog, IDC_SLIDER_RENEWLIFE);
+               } else {
+                   renew_till= 0;
+               }
+
+               sprintf(principal,"%s@%s",username,realm);
+               lsh_errno = Leash_int_kinit_ex( 0,
+                                               hDialog,
+                                               principal, password, lifetime,
+                                               forwardable,
+                                               proxiable,
+                                               renew_till,
+                                               noaddresses,
+                                               publicip,
+                                               1
+                                               );
+               if (lsh_errno != 0)
+               {
+                   LONG check_time;
+#ifdef COMMENT
+                   char gbuf[256];
+                   int capslock;
+                   char *cp;
+#endif
+                   err_context = "";
+                   switch(lsh_errno)
+                   {
+                   case LSH_INVPRINCIPAL:
+                   case LSH_INVINSTANCE:
+#ifndef NO_KRB4
+                    case KRBERR(KDC_PR_UNKNOWN):
+#endif
+                        CSendDlgItemMessage(hDialog, IDC_EDIT_PRINCIPAL, EM_SETSEL, 0, 256);
+                        SetFocus(GetDlgItem(hDialog,IDC_EDIT_PRINCIPAL));
+                        break;
+                   case LSH_INVREALM:
+                        CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, EM_SETSEL, 0, 256);
+                        SetFocus(GetDlgItem(hDialog,IDC_COMBO_REALM));
+                       break;
+#ifndef NO_KRB4
+                   case KRBERR(RD_AP_TIME):
+                   case KRBERR(KDC_SERVICE_EXP):
+                       check_time = Leash_timesync(1);
+                       if( check_time == 0 ){
+                           SendMessage(hDialog, WM_COMMAND, IDOK, 0);
+                           return(TRUE);
+                       } else {
+                           lsh_errno = check_time;
+                           return(TRUE);
+                       }
+                       break;
+#endif
+                    default:
+                        CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD, EM_SETSEL, 0, 256);
+                        SetFocus(GetDlgItem(hDialog,IDC_EDIT_PASSWORD));
+                       return(TRUE);
+                   }
+#ifdef COMMENT
+                   capslock = lsh_getkeystate(VK_CAPITAL);
+                   /* low-order bit means caps lock is
+                   toggled; if so, warn user since there's
+                   been an error. */
+                   if (capslock & 1)
+                   {
+                       lstrcpy((LPSTR)gbuf, (LPSTR)err_context);
+                       cp = gbuf + lstrlen((LPSTR)gbuf);
+                       if (cp != gbuf)
+                           *cp++ = ' ';
+                       lstrcpy(cp, "(This may be because your CAPS LOCK key is down.)");
+                       err_context = gbuf;
+                   }
+
+                   // XXX DoNiftyErrorReport(lsh_errno, ISCHPASSWD ? ""
+                   // XXX : "Ticket initialization failed.");
+#endif /* COMMENT */
+                   return TRUE;
+               }
+
+                if ( Leash_get_default_preserve_kinit_settings() )
+                {
+                    Leash_set_default_lifetime(lifetime);
+                    if ( renew_till > 0 ) {
+                        Leash_set_default_renew_till(renew_till);
+                        Leash_set_default_renewable(1);
+                    } else {
+                        Leash_set_default_renewable(0);
+                    }
+                    Leash_set_default_forwardable(forwardable);
+                    Leash_set_default_noaddresses(noaddresses);
+                }
+
+                if ( lpdi->size >= LSH_DLGINFO_EX_V2_SZ ) {
+                    strncpy(lpdi->out.username, username, LEASH_USERNAME_SZ);
+                    lpdi->out.username[LEASH_USERNAME_SZ-1] = 0;
+                    strncpy(lpdi->out.realm, realm, LEASH_REALM_SZ);
+                    lpdi->out.realm[LEASH_REALM_SZ-1] = 0;
+                }
+
+                CloseMe(TRUE); /* success */
+                return FALSE;
+           }
+           break;
+        case IDCANCEL:
+            CloseMe(FALSE);
+            break;
+        }
+        break;
+
+    case WM_MOVE:
+#ifdef _WIN32
+#define LONG2POINT(l,pt) ((pt).x=(SHORT)LOWORD(l),  \
+                        (pt).y=(SHORT)HIWORD(l))
+    LONG2POINT(lParam,Position);
+#else
+       Position = MAKEPOINT(lParam);
+#endif
+        break;
+    }
+    return FALSE;
+}
+
+/* Callback function for the Change Password Dialog box */
+
+INT_PTR
+CALLBACK
+NewPasswordProc(
+    HWND hDialog,
+    UINT message,
+    WPARAM wParam,
+    LPARAM lParam
+    )
+{
+    static POINT Position = { -1, -1 };
+    static char username[LEASH_USERNAME_SZ]="";
+    static char realm[LEASH_REALM_SZ]="";
+    static char password[256]="";
+    static char password2[256]="";
+    static char password3[256]="";
+    static LPLSH_DLGINFO_EX lpdi;
+    static HWND hDlg=0;
+    char principal[256];
+    long realm_count = 0;
+
+    switch (message) {
+
+    case WM_INITDIALOG:
+       hDlg = hDialog;
+
+        SetVersionInfo(hDialog,IDC_STATIC_VERSION,IDC_STATIC_COPYRIGHT);
+
+        *( (LPLSH_DLGINFO_EX far *)(&lpdi) ) = (LPLSH_DLGINFO_EX)(LPSTR)lParam;
+
+       if ((lpdi->size < LSH_DLGINFO_EX_V3_SZ &&
+             lpdi->size != LSH_DLGINFO_EX_V1_SZ &&
+             lpdi->size != LSH_DLGINFO_EX_V2_SZ) ||
+            lpdi->dlgtype != DLGTYPE_CHPASSWD) {
+
+           MessageBox(hDialog, "An incorrect initialization data structure was provided.",
+                       "PasswordProc()",
+                       MB_OK | MB_ICONSTOP);
+           return FALSE;
+       }
+
+        if ( lpdi->size >= LSH_DLGINFO_EX_V2_SZ ) {
+            lpdi->out.username[0] = 0;
+            lpdi->out.realm[0] = 0;
+        }
+        if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ ) {
+            lpdi->out.ccache[0] = 0;
+        }
+
+        if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ )
+           SetWindowText(hDialog, lpdi->in.title);
+       else
+           SetWindowText(hDialog, lpdi->title);
+
+        SetProp(hDialog, "HANDLES_HELP", (HANDLE)1);
+
+        if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ )
+            lstrcpy(username, lpdi->in.username);
+        else if (lpdi->username)
+            lstrcpy(username, lpdi->username);
+        if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ )
+           lstrcpy(realm, lpdi->in.realm);
+       else if (lpdi->realm)
+           lstrcpy(realm, lpdi->realm);
+
+        CSetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, username);
+        CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD, "");
+        CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD2, "");
+        CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD3, "");
+
+#if 0  /* 20030619 - mjv wishes to return to the default character */
+       /* echo spaces */
+       CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD, EM_SETPASSWORDCHAR, 32, 0);
+       CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD2, EM_SETPASSWORDCHAR, 32, 0);
+       CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD3, EM_SETPASSWORDCHAR, 32, 0);
+#endif
+
+       /* Populate list of Realms */
+       CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_RESETCONTENT, 0, 0);
+       CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_LIMITTEXT, 192, 0);
+
+       if (pprofile_get_subsection_names && pprofile_free_list) {
+           const char*  rootSection[] = {"realms", NULL};
+           const char** rootsec = rootSection;
+           char **sections = NULL, **cpp = NULL, *value = NULL;
+
+           char krb5_conf[MAX_PATH+1];
+
+           if (!GetProfileFile(krb5_conf,sizeof(krb5_conf))) {
+               profile_t profile;
+               long retval;
+               const char *filenames[2];
+
+               filenames[0] = krb5_conf;
+               filenames[1] = NULL;
+               retval = pprofile_init(filenames, &profile);
+               if (!retval) {
+                   retval = pprofile_get_subsection_names(profile,     rootsec, &sections);
+
+                   if (!retval)
+                   {
+                       for (cpp = sections; *cpp; cpp++)
+                       {
+                           CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_ADDSTRING, 0, (LPARAM)*cpp);
+                           realm_count++;
+                       }
+                   }
+                   pprofile_free_list(sections);
+                   pprofile_release(profile);
+               }
+           }
+       } else {
+           FILE * file;
+           char krb_conf[MAX_PATH+1];
+           char * p;
+
+           if (!GetKrb4ConFile(krb_conf,sizeof(krb_conf)) &&
+                (file = fopen(krb_conf, "rt")))
+           {
+               char lineBuf[256];
+               // Skip the default realm
+               readstring(file,lineBuf,sizeof(lineBuf));
+
+               // Read the defined realms
+               while (TRUE)
+               {
+                   if (readstring(file,lineBuf,sizeof(lineBuf)) < 0)
+                       break;
+
+                   if (*(lineBuf + strlen(lineBuf) - 1) == '\r')
+                       *(lineBuf + strlen(lineBuf) - 1) = 0;
+
+                   for (p=lineBuf; *p ; p++)
+                   {
+                       if (isspace(*p)) {
+                           *p = 0;
+                           break;
+                       }
+                   }
+
+                   if ( strncmp(".KERBEROS.OPTION.",lineBuf,17) ) {
+                       CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_ADDSTRING, 0, (LPARAM)lineBuf);
+                       realm_count++;
+                   }
+               }
+
+               fclose(file);
+           }
+       }
+       if (realm_count == 0)
+           CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, CB_ADDSTRING, 0, (LPARAM)realm);
+
+       /* Select the default Realm */
+       if (!realm[0] && hKrb5) {
+           krb5_context ctx=0;
+           char * def = 0;
+           pkrb5_init_context(&ctx);
+           pkrb5_get_default_realm(ctx,&def);
+           if (def) {
+               lstrcpy(realm, def);
+               free(def);
+           }
+           pkrb5_free_context(ctx);
+       }
+       CSetDlgItemText(hDialog, IDC_COMBO_REALM, realm);
+
+        /* setup text of stuff. */
+
+        if (Position.x > 0 && Position.y > 0 &&
+            Position.x < GetSystemMetrics(SM_CXSCREEN) &&
+            Position.y < GetSystemMetrics(SM_CYSCREEN))
+            SetWindowPos(hDialog, 0, Position.x, Position.y, 0, 0,
+                         SWP_NOSIZE | SWP_NOZORDER);
+        else { /* Center the window on the desktop */
+            RECT dlgRect;
+            GetWindowRect( hDialog, &dlgRect );
+            SetWindowPos(hDialog, 0,
+                         (GetSystemMetrics(SM_CXSCREEN) - dlgRect.right + dlgRect.left)/2,
+                         (GetSystemMetrics(SM_CYSCREEN) - dlgRect.bottom + dlgRect.top)/2,
+                         0, 0,
+                         SWP_NOSIZE | SWP_NOZORDER);
+        }
+        /* set window pos to last saved window pos */
+        break;
+
+    case WM_COMMAND:
+        switch (wParam) {
+        case ID_HELP:
+           {
+               WinHelp(GetWindow(hDialog,GW_OWNER), KRB_HelpFile, HELP_CONTEXT,
+                        ID_INITTICKETS);
+           }
+           break;
+        case ID_CLOSEME:
+           {
+               CleanupSliders();
+               memset(password,0,sizeof(password));
+               memset(password2,0,sizeof(password2));
+               memset(password3,0,sizeof(password3));
+               RemoveProp(hDialog, "HANDLES_HELP");
+               EndDialog(hDialog, (int)lParam);
+                return TRUE;
+           }
+           break;
+        case IDOK:
+           {
+               DWORD value = 0;
+               int i = 0;
+                int bit8 = 0;
+
+               CGetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, username, sizeof(username));
+               CGetDlgItemText(hDialog, IDC_EDIT_PASSWORD, password, sizeof(password));
+               CGetDlgItemText(hDialog, IDC_EDIT_PASSWORD2, password2, sizeof(password2));
+               CGetDlgItemText(hDialog, IDC_EDIT_PASSWORD3, password3, sizeof(password3));
+               CGetDlgItemText(hDialog, IDC_COMBO_REALM, realm, sizeof(realm));
+
+               if (!username[0])
+               {
+                   MessageBox(hDialog, "You are not allowed to enter a "
+                               "blank username.",
+                               "Invalid Principal",
+                               MB_OK | MB_ICONSTOP);
+                   return TRUE;
+               }
+               if (!realm[0])
+               {
+                   MessageBox(hDialog, "You are not allowed to enter a "
+                               "blank realm.",
+                               "Invalid Principal",
+                               MB_OK | MB_ICONSTOP);
+                   return TRUE;
+               }
+
+               if (Leash_get_default_uppercaserealm())
+               {
+                   // found
+                   strupr(realm);
+               }
+
+               if (!password[0] || !password2[0] || !password3[0])
+               {
+                   MessageBox(hDialog, "You are not allowed to enter a "
+                               "blank password.",
+                               "Invalid Password",
+                               MB_OK | MB_ICONSTOP);
+                   return TRUE;
+               }
+
+               for( i = 0; i < 255; i++ ){
+                    if( password2[i] == '\0' ){
+                        if ( bit8 ) {
+                            MessageBox(hDialog,
+                                        "Passwords should not contain non-ASCII characters.",
+                                        "Internationalization Warning",
+                                        MB_OK | MB_ICONINFORMATION);
+                        }
+                        i = 255;
+                        break;
+                    } else if( !isprint(password2[i]) ){
+                        memset(password2, '\0', sizeof(password2));
+                        memset(password3, '\0', sizeof(password3));
+                        /* I claim these passwords in the name of planet '\0'... */
+                        MessageBox(hDialog,
+                                   "Passwords may not contain non-printable characters.",
+                                    "Invalid Password",
+                                    MB_OK | MB_ICONSTOP);
+                        return TRUE;
+                    } else if ( password2[i] > 127 )
+                        bit8 = 1;
+               }
+
+               if (lstrcmp(password2, password3))
+               {
+                    MessageBox(hDialog,
+                                "The new password was not entered the same way twice.",
+                                "Password validation error",
+                                MB_OK | MB_ICONSTOP);
+                    return TRUE;
+               }
+
+               sprintf(principal,"%s@%s",username,realm);
+
+                lsh_errno = Leash_int_changepwd(principal, password, password2, 0, 1);
+               if (lsh_errno != 0)
+               {
+#ifdef COMMENT
+                   char gbuf[256];
+                   int capslock;
+                   char *cp;
+#endif /* COMMENT */
+                   LONG check_time;
+
+                   err_context = "";
+                   switch(lsh_errno)
+                   {
+                   case LSH_INVPRINCIPAL:
+                   case LSH_INVINSTANCE:
+                   case LSH_INVREALM:
+#ifndef NO_KRB4
+                   case KRBERR(KDC_PR_UNKNOWN):
+#endif
+                       break;
+#ifndef NO_KRB4
+                   case KRBERR(RD_AP_TIME):
+                   case KRBERR(KDC_SERVICE_EXP):
+                       check_time = Leash_timesync(1);
+                       if( check_time == 0 ){
+                           SendMessage(hDialog, WM_COMMAND, IDOK, 0);
+                           return(TRUE);
+                       } else {
+                           lsh_errno = check_time;
+                           return(TRUE);
+                       }
+                       break;
+#endif
+                   default:
+                       return(TRUE);
+                   }
+#ifdef COMMENT
+                   capslock = lsh_getkeystate(VK_CAPITAL);
+                   /* low-order bit means caps lock is
+                   toggled; if so, warn user since there's
+                   been an error. */
+                   if (capslock & 1)
+                   {
+                       lstrcpy((LPSTR)gbuf, (LPSTR)err_context);
+                       cp = gbuf + lstrlen((LPSTR)gbuf);
+                       if (cp != gbuf)
+                           *cp++ = ' ';
+                       lstrcpy(cp, "(This may be because your CAPS LOCK key is down.)");
+                       err_context = gbuf;
+                   }
+
+                   // XXX   DoNiftyErrorReport(lsh_errno, ISCHPASSWD ? ""
+                   // XXX   : "Ticket initialization failed.");
+#endif /* COMMENT */
+                    return TRUE;
+               }
+
+                if ( lpdi->size >= LSH_DLGINFO_EX_V2_SZ ) {
+                    strncpy(lpdi->out.username, username, LEASH_USERNAME_SZ);
+                    lpdi->out.username[LEASH_USERNAME_SZ-1] = 0;
+                    strncpy(lpdi->out.realm, realm, LEASH_REALM_SZ);
+                    lpdi->out.realm[LEASH_REALM_SZ-1] = 0;
+                }
+
+                CloseMe(TRUE); /* success */
+           }
+           break;
+        case IDCANCEL:
+            CloseMe(FALSE);
+            break;
+        }
+        break;
+
+    case WM_MOVE:
+#ifdef _WIN32
+#define LONG2POINT(l,pt) ((pt).x=(SHORT)LOWORD(l),  \
+                  (pt).y=(SHORT)HIWORD(l))
+    LONG2POINT(lParam,Position);
+#else
+       Position = MAKEPOINT(lParam);
+#endif
+        break;
+    }
+    return FALSE;
+}
diff --git a/src/windows/leashdll/lsh_pwd.rc b/src/windows/leashdll/lsh_pwd.rc
new file mode 100644 (file)
index 0000000..c6d5a1b
--- /dev/null
@@ -0,0 +1,261 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+#include "leashids.h"
+#include "winver.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+LOGOBITMAP              BITMAP  DISCARDABLE     "res\\islogo.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+LEASHICON               ICON    DISCARDABLE     "res\\leash.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+ENTERPASSWORDDLG DIALOG DISCARDABLE  23, 48, 262, 108
+STYLE DS_MODALFRAME | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
+CAPTION "Enter Password"
+FONT 10, "System"
+BEGIN
+    EDITTEXT        ID_PRINCIPAL,6,17,96,12,ES_AUTOHSCROLL
+    LTEXT           "Enter your username:",ID_PRINCCAPTION,6,7,140,8
+    DEFPUSHBUTTON   "OK",IDOK,110,42,32,14
+    EDITTEXT        ID_OLDPASSWORD,6,43,96,12,ES_PASSWORD | ES_AUTOHSCROLL
+    LTEXT           "Enter your password:",ID_OLDPCAPTION,6,33,91,8
+    EDITTEXT        ID_DURATION,40,59,20,12
+    LTEXT           "Duration:",-1,6,61,30,8
+    LTEXT           "minutes",-1,62,61,64,8
+    ICON            "LeashIcon",-1,6,78,18,20
+    PUSHBUTTON      "&Cancel",IDCANCEL,30,78,32,14
+    PUSHBUTTON      "&Restart",ID_RESTART,70,78,32,14
+    PUSHBUTTON      "&Help",ID_HELP,110,78,32,14
+    CONTROL         "",ID_PICFRAME,"Static",SS_BLACKFRAME,153,4,100,100
+END
+
+CHANGEPASSWORDDLG DIALOG DISCARDABLE  27, 41, 270, 155
+STYLE DS_MODALFRAME | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
+CAPTION "Change Password"
+FONT 8, "System"
+BEGIN
+    EDITTEXT        ID_PRINCIPAL,6,35,96,12,ES_AUTOHSCROLL
+    DEFPUSHBUTTON   "OK",IDOK,110,60,32,14
+    EDITTEXT        ID_OLDPASSWORD,6,61,96,12,ES_PASSWORD | ES_AUTOHSCROLL
+    EDITTEXT        ID_CONFIRMPASSWORD1,6,87,96,12,ES_PASSWORD |
+                    ES_AUTOHSCROLL
+    EDITTEXT        ID_CONFIRMPASSWORD2,6,113,96,12,ES_PASSWORD |
+                    ES_AUTOHSCROLL
+    LTEXT           "Enter your username:",ID_PRINCCAPTION,6,25,140,8
+    LTEXT           "Enter your old password:",ID_OLDPCAPTION,6,51,91,8
+    LTEXT           "Enter your new password:",ID_CONFIRMCAPTION1,6,77,96,8
+    LTEXT           "Retype your new password:",ID_CONFIRMCAPTION2,6,103,100,
+                    8
+    ICON            "LeashIcon",-1,6,134,18,20
+    PUSHBUTTON      "&Cancel",IDCANCEL,30,134,32,14
+    PUSHBUTTON      "&Restart",ID_RESTART,70,134,32,14
+    PUSHBUTTON      "&Help",ID_HELP,110,134,32,14
+    LTEXT           "To change your password, fill in the following fields as they appear.",
+                    -1,6,3,140,21
+    CONTROL         "",ID_PICFRAME,"Static",SS_BLACKFRAME,157,27,100,100
+END
+
+IDD_AUTHENTICATE DIALOGEX 0, 0, 370, 268
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Authenticate to Kerberos"
+FONT 8, "Microsoft Sans Serif"
+BEGIN
+    EDITTEXT        IDC_EDIT_PRINCIPAL,89,42,259,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_EDIT_PASSWORD,89,74,259,14,ES_PASSWORD |
+                    ES_AUTOHSCROLL
+    COMBOBOX        IDC_COMBO_REALM,89,57,259,79,CBS_DROPDOWN |
+                    CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+    DEFPUSHBUTTON   "OK",IDOK,302,235,49,14
+    PUSHBUTTON      "Cancel",IDCANCEL,249,235,49,14
+    PUSHBUTTON      "Hide Options",IDC_BUTTON_OPTIONS,186,235,49,14
+    CONTROL         "Ticket Lifetime",IDC_SLIDER_LIFETIME,"msctls_trackbar32",
+                    TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,90,113,258,15
+    CONTROL         "Get tickets that can be forwarded to other machines",
+                    IDC_CHECK_FORWARDABLE,"Button",BS_AUTOCHECKBOX |
+                    WS_TABSTOP,89,150,203,10
+    CONTROL         "Get tickets without IP addresses (NAT mode)",
+                    IDC_CHECK_NOADDRESS,"Button",BS_AUTOCHECKBOX |
+                    WS_TABSTOP,89,163,228,10
+    CONTROL         "Get tickets that can be renewed for:",
+                    IDC_CHECK_RENEWABLE,"Button",BS_AUTOCHECKBOX |
+                    WS_TABSTOP,89,176,186,10
+    CONTROL         "Slider2",IDC_SLIDER_RENEWLIFE,"msctls_trackbar32",
+                    TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,100,207,246,15
+    RTEXT           "Name:",IDC_STATIC_NAME,63,44,21,8
+    RTEXT           "Realm:",IDC_STATIC_REALM,62,60,23,8
+    RTEXT           "Password:",IDC_STATIC_PWD,13,76,74,8
+    RTEXT           "Ticket Lifetime:",IDC_STATIC_LIFETIME,19,103,65,8,0,
+                    WS_EX_RIGHT
+    LTEXT           "Kerberos 5 Options:",IDC_STATIC_KRB5,22,139,101,8
+    LTEXT           "HMS",IDC_STATIC_LIFETIME_VALUE,89,103,131,8
+    LTEXT           "HMS",IDC_STATIC_RENEW_TILL_VALUE,102,193,141,8
+    LTEXT           "",IDC_STATIC_VERSION,7,244,143,8
+    ICON            LEASHICON,IDC_PICTURE_LEASH,21,15,20,20
+    LTEXT           "You are required to type your Kerberos Password",
+                    IDC_STATIC_NOTICE,51,23,276,8
+    RTEXT           "Renew Till:",IDC_STATIC_RENEW,37,193,59,8
+    LTEXT           "",IDC_STATIC_COPYRIGHT,7,256,323,8
+END
+
+IDD_PASSWORD DIALOG DISCARDABLE  0, 0, 382, 198
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Change Password"
+FONT 8, "Microsoft Sans Serif"
+BEGIN
+    EDITTEXT        IDC_EDIT_PRINCIPAL,99,52,259,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_EDIT_PASSWORD,99,84,259,14,ES_PASSWORD |
+                    ES_AUTOHSCROLL
+    EDITTEXT        IDC_EDIT_PASSWORD2,99,112,259,14,ES_PASSWORD |
+                    ES_AUTOHSCROLL
+    EDITTEXT        IDC_EDIT_PASSWORD3,99,135,259,14,ES_PASSWORD |
+                    ES_AUTOHSCROLL
+    COMBOBOX        IDC_COMBO_REALM,99,67,259,79,CBS_DROPDOWN |
+                    CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+    DEFPUSHBUTTON   "OK",IDOK,313,165,49,14
+    PUSHBUTTON      "Cancel",IDCANCEL,256,165,49,14
+    RTEXT           "Name:",IDC_STATIC_NAME,73,55,21,8
+    RTEXT           "Realm:",IDC_STATIC_REALM,72,71,23,8
+    RTEXT           "Old Password:",IDC_STATIC_PWD,19,85,74,21
+    LTEXT           "Copyright 2003 MIT",IDC_STATIC_COPYRIGHT,7,183,329,8
+    ICON            LEASHICON,IDC_PICTURE_LEASH,15,15,20,20
+    LTEXT           "Change your Kerberos password or phrase",
+                    IDC_STATIC_NOTICE,48,20,276,8
+    RTEXT           "New Password:",IDC_STATIC_PWD2,23,112,74,16
+    RTEXT           "New Password (again):",IDC_STATIC_PWD3,22,135,74,18
+    LTEXT           "Version",IDC_STATIC_VERSION,7,170,172,8
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+    "#include ""windows.h""\r\n"
+    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+    "#include ""leashids.h""\r\n"
+    "#include ""ver.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "\r\n"
+    "#include ""ver.rc""\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+    IDD_PASSWORD, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 375
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 191
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+    LSH_TIME_HOST           "time"
+    LSH_DEFAULT_TICKET_LIFE "600"
+    LSH_DEFAULT_TICKET_RENEW_TILL "10080"
+    LSH_DEFAULT_TICKET_FORWARD "1"
+    LSH_DEFAULT_TICKET_NOADDRESS "1"
+    LSH_DEFAULT_TICKET_PROXIABLE "0"
+    LSH_DEFAULT_TICKET_PUBLICIP "0"
+    LSH_DEFAULT_TICKET_USEKRB4 "0"
+    LSH_DEFAULT_DIALOG_KINIT_OPT "1"
+    LSH_DEFAULT_DIALOG_LIFE_MIN "30"
+    LSH_DEFAULT_DIALOG_LIFE_MAX "1440"
+    LSH_DEFAULT_DIALOG_RENEW_MIN "600"
+    LSH_DEFAULT_DIALOG_RENEW_MAX "43200"
+    LSH_DEFAULT_TICKET_RENEW "1"
+    LSH_DEFAULT_UPPERCASEREALM "1"
+    LSH_DEFAULT_MSLSA_IMPORT "2"
+    LSH_DEFAULT_PRESERVE_KINIT "0"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+    LSH_DEFAULT_DIALOG_LOCK_LOCATION "0"
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+#include "ver.rc"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/src/windows/leashdll/lshcallb.c b/src/windows/leashdll/lshcallb.c
new file mode 100644 (file)
index 0000000..3f2afb3
--- /dev/null
@@ -0,0 +1,15 @@
+#include <windows.h>
+#include <krb.h>
+
+int (*Lcom_err)(LPSTR,long,LPSTR,...);
+LPSTR (*Lerror_message)(long);
+LPSTR (*Lerror_table_name)(long);
+
+void Leash_load_com_err_callback(FARPROC ce,
+                                 FARPROC em,
+                                 FARPROC etn)
+{
+    (FARPROC)Lcom_err=ce;
+    (FARPROC)Lerror_message=em;
+    (FARPROC)Lerror_table_name=etn;
+}
diff --git a/src/windows/leashdll/lshfunc.c b/src/windows/leashdll/lshfunc.c
new file mode 100644 (file)
index 0000000..73b10c3
--- /dev/null
@@ -0,0 +1,3867 @@
+#include <windows.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <winsock.h>
+#include "leashdll.h"
+#include <KerberosIV/krb.h>
+#include <prot.h>
+#include <time.h>
+
+#include <leashwin.h>
+#include "leasherr.h"
+#include "leash-int.h"
+#include "leashids.h"
+
+#include <mitwhich.h>
+
+#include <winkrbid.h>
+#include "reminder.h"
+
+static char FAR *err_context;
+
+char KRB_HelpFile[_MAX_PATH] = HELPFILE;
+
+#define LEN     64                /* Maximum Hostname Length */
+
+#define LIFE    DEFAULT_TKT_LIFE  /* lifetime of ticket in 5-minute units */
+
+#ifndef NO_KRB4
+char *
+short_date(dp)
+    long   *dp;
+{
+    register char *cp;
+    cp = ctime(dp) + 4; // skip day of week
+    // cp[15] = '\0';
+    cp[12] = '\0'; // Don't display seconds
+    return (cp);
+}
+#endif
+
+static
+char*
+clean_string(
+    char* s
+    )
+{
+    char* p = s;
+    char* b = s;
+
+    if (!s) return s;
+
+    for (p = s; *p; p++) {
+        switch (*p) {
+        case '\007':
+            /* Add more cases here */
+            break;
+        default:
+            *b = *p;
+            b++;
+        }
+    }
+    *b = *p;
+    return s;
+}
+
+static
+int
+leash_error_message(
+    const char *error,
+    int rcL,
+    int rc4,
+    int rc5,
+    int rcA,
+    char* result_string,
+    int  displayMB
+    )
+{
+    char message[2048];
+    char *p = message;
+    int size = sizeof(message);
+    int n;
+
+    // XXX: ignore AFS for now.
+
+    if (!rc5 && !rc4 && !rcL)
+        return 0;
+
+    n = _snprintf(p, size, "%s\n\n", error);
+    p += n;
+    size -= n;
+
+    if (rc5 && !result_string)
+    {
+        n = _snprintf(p, size,
+                      "Kerberos 5: %s (error %ld)\n",
+                      perror_message(rc5),
+                      rc5 & 255 // XXX: & 255??!!!
+            );
+        p += n;
+        size -= n;
+    }
+    if (rc4 && !result_string)
+    {
+        char buffer[1024];
+        n = _snprintf(p, size,
+                      "Kerberos 4: %s\n",
+                      err_describe(buffer, rc4)
+            );
+        p += n;
+        size -= n;
+    }
+    if (rcL)
+    {
+        char buffer[1024];
+        n = _snprintf(p, size,
+                      "\n%s\n",
+                      err_describe(buffer, rcL)
+            );
+        p += n;
+        size -= n;
+    }
+    if (result_string)
+    {
+        n = _snprintf(p, size,
+                      "%s\n",
+                      result_string);
+        p += n;
+        size -= n;
+    }
+    if ( displayMB )
+        MessageBox(NULL, message, "Leash", MB_OK | MB_ICONERROR | MB_TASKMODAL |
+                    MB_SETFOREGROUND);
+
+    if (rc5) return rc5;
+    if (rc4) return rc4;
+    if (rcL) return rcL;
+    return 0;
+}
+
+
+static
+char *
+make_postfix(
+    const char * base,
+    const char * postfix,
+    char ** rcopy
+    )
+{
+    int base_size;
+    int ret_size;
+    char * copy = 0;
+    char * ret = 0;
+
+    base_size = strlen(base) + 1;
+    ret_size = base_size + strlen(postfix) + 1;
+    copy = malloc(base_size);
+    ret = malloc(ret_size);
+
+    if (!copy || !ret)
+        goto cleanup;
+
+    strncpy(copy, base, base_size);
+    copy[base_size - 1] = 0;
+
+    strncpy(ret, base, base_size);
+    strncpy(ret + (base_size - 1), postfix, ret_size - (base_size - 1));
+    ret[ret_size - 1] = 0;
+
+ cleanup:
+    if (!copy || !ret) {
+        if (copy)
+            free(copy);
+        if (ret)
+            free(ret);
+        copy = ret = 0;
+    }
+    // INVARIANT: (ret ==> copy) && (copy ==> ret)
+    *rcopy = copy;
+    return ret;
+}
+
+#ifndef NO_KRB4
+static
+long
+make_temp_cache_v4(
+    const char * postfix
+    )
+{
+    static char * old_cache = 0;
+
+    if (!pkrb_set_tkt_string || !ptkt_string || !pdest_tkt)
+        return 0; // XXX - is this appropriate?
+
+    if (old_cache) {
+        pdest_tkt();
+        pkrb_set_tkt_string(old_cache);
+        free(old_cache);
+        old_cache = 0;
+    }
+
+    if (postfix)
+    {
+        char * tmp_cache = make_postfix(ptkt_string(), postfix, &old_cache);
+
+        if (!tmp_cache)
+            return KFAILURE;
+
+        pkrb_set_tkt_string(tmp_cache);
+        free(tmp_cache);
+    }
+    return 0;
+}
+#endif
+
+static
+long
+make_temp_cache_v5(
+    const char * postfix,
+    krb5_context * pctx
+    )
+{
+    static krb5_context ctx = 0;
+    static char * old_cache = 0;
+
+    // INVARIANT: old_cache ==> ctx && ctx ==> old_cache
+
+    if (pctx)
+        *pctx = 0;
+
+    if (!pkrb5_init_context || !pkrb5_free_context || !pkrb5_cc_resolve ||
+        !pkrb5_cc_default_name || !pkrb5_cc_set_default_name)
+        return 0;
+
+    if (old_cache) {
+        krb5_ccache cc = 0;
+        if (!pkrb5_cc_resolve(ctx, pkrb5_cc_default_name(ctx), &cc))
+            pkrb5_cc_destroy(ctx, cc);
+        pkrb5_cc_set_default_name(ctx, old_cache);
+        free(old_cache);
+        old_cache = 0;
+    }
+    if (ctx) {
+        pkrb5_free_context(ctx);
+        ctx = 0;
+    }
+
+    if (postfix)
+    {
+        char * tmp_cache = 0;
+        krb5_error_code rc = 0;
+
+        rc = pkrb5_init_context(&ctx);
+        if (rc) goto cleanup;
+
+        tmp_cache = make_postfix(pkrb5_cc_default_name(ctx), postfix,
+                                 &old_cache);
+
+        if (!tmp_cache) {
+            rc = ENOMEM;
+            goto cleanup;
+        }
+
+        rc = pkrb5_cc_set_default_name(ctx, tmp_cache);
+
+    cleanup:
+        if (rc && ctx) {
+            pkrb5_free_context(ctx);
+            ctx = 0;
+        }
+        if (tmp_cache)
+            free(tmp_cache);
+        if (pctx)
+            *pctx = ctx;
+        return rc;
+    }
+    return 0;
+}
+
+long
+Leash_checkpwd(
+    char *principal,
+    char *password
+    )
+{
+    return Leash_int_checkpwd(principal, password, 0);
+}
+
+long
+Leash_int_checkpwd(
+    char * principal,
+    char * password,
+    int    displayErrors
+    )
+{
+    long rc = 0;
+       krb5_context ctx = 0;   // statically allocated in make_temp_cache_v5
+    // XXX - we ignore errors in make_temp_cache_v?  This is BAD!!!
+#ifndef NO_KRB4
+    make_temp_cache_v4("_checkpwd");
+#endif
+    make_temp_cache_v5("_checkpwd", &ctx);
+    rc = Leash_int_kinit_ex( ctx, 0,
+                                                        principal, password, 0, 0, 0, 0,
+                                                        Leash_get_default_noaddresses(),
+                                                        Leash_get_default_publicip(),
+                             displayErrors
+                                                        );
+#ifndef NO_KRB4
+    make_temp_cache_v4(0);
+#endif
+    make_temp_cache_v5(0, &ctx);
+    return rc;
+}
+
+static
+long
+Leash_changepwd_v5(
+    char * principal,
+    char * password,
+    char * newpassword,
+    char** error_str
+    )
+{
+    krb5_error_code rc = 0;
+    int result_code;
+    krb5_data result_code_string, result_string;
+    krb5_context context = 0;
+    krb5_principal princ = 0;
+    krb5_get_init_creds_opt opts;
+    krb5_creds creds;
+    DWORD addressless = 0;
+
+    result_string.data = 0;
+    result_code_string.data = 0;
+
+    if ( !pkrb5_init_context )
+        goto cleanup;
+
+   if (rc = pkrb5_init_context(&context)) {
+#if 0
+       com_err(argv[0], ret, "initializing kerberos library");
+#endif
+       goto cleanup;
+   }
+
+   if (rc = pkrb5_parse_name(context, principal, &princ)) {
+#if 0
+       com_err(argv[0], ret, "parsing client name");
+#endif
+       goto cleanup;
+   }
+
+   pkrb5_get_init_creds_opt_init(&opts);
+   pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
+   pkrb5_get_init_creds_opt_set_renew_life(&opts, 0);
+   pkrb5_get_init_creds_opt_set_forwardable(&opts, 0);
+   pkrb5_get_init_creds_opt_set_proxiable(&opts, 0);
+
+   addressless = Leash_get_default_noaddresses();
+   if (addressless)
+       pkrb5_get_init_creds_opt_set_address_list(&opts,NULL);
+
+
+   if (rc = pkrb5_get_init_creds_password(context, &creds, princ, password,
+                                          0, 0, 0, "kadmin/changepw", &opts)) {
+       if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+#if 0
+           com_err(argv[0], 0,
+                   "Password incorrect while getting initial ticket");
+#endif
+       }
+       else {
+#if 0
+           com_err(argv[0], ret, "getting initial ticket");
+#endif
+       }
+       goto cleanup;
+   }
+
+   if (rc = pkrb5_change_password(context, &creds, newpassword,
+                                  &result_code, &result_code_string,
+                                  &result_string)) {
+#if 0
+       com_err(argv[0], ret, "changing password");
+#endif
+       goto cleanup;
+   }
+
+   if (result_code) {
+       int len = result_code_string.length +
+           (result_string.length ? (sizeof(": ") - 1) : 0) +
+           result_string.length;
+       if (len && error_str) {
+           *error_str = malloc(len + 1);
+           if (*error_str)
+               _snprintf(*error_str, len + 1,
+                         "%.*s%s%.*s",
+                         result_code_string.length, result_code_string.data,
+                         result_string.length?": ":"",
+                         result_string.length, result_string.data);
+       }
+      rc = result_code;
+      goto cleanup;
+   }
+
+ cleanup:
+   if (result_string.data)
+       pkrb5_free_data_contents(context, &result_string);
+
+   if (result_code_string.data)
+       pkrb5_free_data_contents(context, &result_code_string);
+
+   if (princ)
+       pkrb5_free_principal(context, princ);
+
+   if (context)
+       pkrb5_free_context(context);
+
+   return rc;
+}
+
+#ifndef NO_KRB4
+static
+long
+Leash_changepwd_v4(
+    char * principal,
+    char * password,
+    char * newpassword,
+    char** error_str
+    )
+{
+    long k_errno;
+
+    if (!pkrb_set_tkt_string || !ptkt_string || !pkadm_change_your_password ||
+        !pdest_tkt)
+        return KFAILURE;
+
+    k_errno = make_temp_cache_v4("_chgpwd");
+    if (k_errno) return k_errno;
+    k_errno = pkadm_change_your_password(principal, password, newpassword,
+                                         error_str);
+    make_temp_cache_v4(0);
+    return k_errno;
+}
+#endif
+
+/*
+ * Leash_changepwd
+ *
+ * Try to change the password using one of krb5 or krb4 -- whichever one
+ * works.  We return ok on the first one that works.
+ */
+long
+Leash_changepwd(
+    char * principal,
+    char * password,
+    char * newpassword,
+    char** result_string
+    )
+{
+    return Leash_int_changepwd(principal, password, newpassword, result_string, 0);
+}
+
+long
+Leash_int_changepwd(
+    char * principal,
+    char * password,
+    char * newpassword,
+    char** result_string,
+    int    displayErrors
+    )
+{
+    char* v5_error_str = 0;
+    char* v4_error_str = 0;
+    char* error_str = 0;
+    int rc4 = 0;
+    int rc5 = 0;
+    int rc = 0;
+    if (hKrb5)
+        rc = rc5 = Leash_changepwd_v5(principal, password, newpassword,
+                                      &v5_error_str);
+#ifndef NO_KRB4
+    if (hKrb4 &&
+         Leash_get_default_use_krb4() &&
+         (!hKrb5 || rc5))
+        rc = rc4 = Leash_changepwd_v4(principal, password, newpassword,
+                                      &v4_error_str);
+#endif
+    if (!rc)
+        return 0;
+    if (v5_error_str || v4_error_str) {
+        int len = 0;
+        char v5_prefix[] = "Kerberos 5: ";
+        char sep[] = "\n";
+        char v4_prefix[] = "Kerberos 4: ";
+
+        clean_string(v5_error_str);
+        clean_string(v4_error_str);
+
+        if (v5_error_str)
+            len += sizeof(sep) + sizeof(v5_prefix) + strlen(v5_error_str) +
+                sizeof(sep);
+        if (v4_error_str)
+            len += sizeof(sep) + sizeof(v4_prefix) + strlen(v4_error_str) +
+                sizeof(sep);
+        error_str = malloc(len + 1);
+        if (error_str) {
+            char* p = error_str;
+            int size = len + 1;
+            int n;
+            if (v5_error_str) {
+                n = _snprintf(p, size, "%s%s%s%s",
+                              sep, v5_prefix, v5_error_str, sep);
+                p += n;
+                size -= n;
+            }
+            if (v4_error_str) {
+                n = _snprintf(p, size, "%s%s%s%s",
+                              sep, v4_prefix, v4_error_str, sep);
+                p += n;
+                size -= n;
+            }
+            if (result_string)
+                *result_string = error_str;
+        }
+    }
+    return leash_error_message("Error while changing password.",
+                               rc4, rc4, rc5, 0, error_str,
+                               displayErrors
+                               );
+}
+
+int (*Lcom_err)(LPSTR,long,LPSTR,...);
+LPSTR (*Lerror_message)(long);
+LPSTR (*Lerror_table_name)(long);
+
+
+long
+Leash_kinit(
+    char * principal,
+    char * password,
+    int lifetime
+    )
+{
+    return Leash_int_kinit_ex( 0, 0,
+                               principal,
+                               password,
+                               lifetime,
+                               Leash_get_default_forwardable(),
+                               Leash_get_default_proxiable(),
+                               Leash_get_default_renew_till(),
+                               Leash_get_default_noaddresses(),
+                               Leash_get_default_publicip(),
+                               0
+                               );
+}
+
+long
+Leash_kinit_ex(
+    char * principal,
+    char * password,
+    int lifetime,
+    int forwardable,
+    int proxiable,
+    int renew_life,
+    int addressless,
+    unsigned long publicip
+    )
+{
+    return Leash_int_kinit_ex( 0, /* krb5 context */
+                              0, /* parent window */
+                               principal,
+                               password,
+                               lifetime,
+                              forwardable,
+                              proxiable,
+                              renew_life,
+                              addressless,
+                              publicip,
+                               0
+                              );
+}
+
+long
+Leash_int_kinit_ex(
+    krb5_context ctx,
+    HWND hParent,
+    char * principal,
+    char * password,
+    int lifetime,
+    int forwardable,
+    int proxiable,
+    int renew_life,
+    int addressless,
+    unsigned long publicip,
+    int displayErrors
+    )
+{
+    LPCSTR  functionName;
+    char    aname[ANAME_SZ];
+    char    inst[INST_SZ];
+    char    realm[REALM_SZ];
+    char    first_part[256];
+    char    second_part[256];
+    char    temp[1024];
+    int     count;
+    int     i;
+    int rc4 = 0;
+    int rc5 = 0;
+    int rcA = 0;
+    int rcB = 0;
+    int rcL = 0;
+
+    if (lifetime < 5)
+        lifetime = 1;
+    else
+        lifetime /= 5;
+
+    if (renew_life > 0 && renew_life < 5)
+       renew_life = 1;
+    else
+       renew_life /= 5;
+
+    /* This should be changed if the maximum ticket lifetime */
+    /* changes */
+
+    if (lifetime > 255)
+        lifetime = 255;
+
+    err_context = "parsing principal";
+
+    memset(temp, '\0', sizeof(temp));
+    memset(inst, '\0', sizeof(inst));
+    memset(realm, '\0', sizeof(realm));
+    memset(first_part, '\0', sizeof(first_part));
+    memset(second_part, '\0', sizeof(second_part));
+
+    sscanf(principal, "%[/0-9a-zA-Z._-]@%[/0-9a-zA-Z._-]", first_part, second_part);
+    strcpy(temp, first_part);
+    strcpy(realm, second_part);
+    memset(first_part, '\0', sizeof(first_part));
+    memset(second_part, '\0', sizeof(second_part));
+    if (sscanf(temp, "%[@0-9a-zA-Z._-]/%[@0-9a-zA-Z._-]", first_part, second_part) == 2)
+    {
+        strcpy(aname, first_part);
+        strcpy(inst, second_part);
+    }
+    else
+    {
+        count = 0;
+        i = 0;
+        for (i = 0; temp[i]; i++)
+        {
+            if (temp[i] == '.')
+                ++count;
+        }
+        if (count > 1)
+        {
+            strcpy(aname, temp);
+        }
+        else
+        {
+#ifndef NO_KRB4
+            if (pkname_parse != NULL)
+            {
+                memset(first_part, '\0', sizeof(first_part));
+                memset(second_part, '\0', sizeof(second_part));
+                sscanf(temp, "%[@/0-9a-zA-Z_-].%[@/0-9a-zA-Z_-]", first_part, second_part);
+                strcpy(aname, first_part);
+                strcpy(inst, second_part);
+            }
+            else
+#endif
+            {
+                strcpy(aname, temp);
+            }
+        }
+    }
+
+    memset(temp, '\0', sizeof(temp));
+    strcpy(temp, aname);
+    if (strlen(inst) != 0)
+    {
+        strcat(temp, "/");
+        strcat(temp, inst);
+    }
+    if (strlen(realm) != 0)
+    {
+        strcat(temp, "@");
+        strcat(temp, realm);
+    }
+
+    rc5 = Leash_krb5_kinit(ctx, hParent,
+                            temp, password, lifetime,
+                            forwardable,
+                            proxiable,
+                            renew_life,
+                            addressless,
+                            publicip
+                            );
+#ifndef NO_KRB4
+    if ( Leash_get_default_use_krb4() ) {
+        rc4 = KSUCCESS;
+
+        if ( !rc5 ) {
+            if (!Leash_convert524(ctx))
+                rc4 = KFAILURE;
+        }
+
+        if (rc4 != KSUCCESS) {
+            if (pkname_parse == NULL)
+            {
+                goto cleanup;
+            }
+
+            err_context = "getting realm";
+            if (!*realm && (rc4  = (int)(*pkrb_get_lrealm)(realm, 1)))
+            {
+                functionName = "krb_get_lrealm()";
+                rcL  = LSH_FAILEDREALM;
+                goto cleanup;
+            }
+
+            err_context = "checking principal";
+            if ((!*aname) || (!(rc4  = (int)(*pk_isname)(aname))))
+            {
+                functionName = "krb_get_lrealm()";
+                rcL = LSH_INVPRINCIPAL;
+                goto cleanup;
+            }
+
+            /* optional instance */
+            if (!(rc4 = (int)(*pk_isinst)(inst)))
+            {
+                functionName = "k_isinst()";
+                rcL = LSH_INVINSTANCE;
+                goto cleanup;
+            }
+
+            if (!(rc4 = (int)(*pk_isrealm)(realm)))
+            {
+                functionName = "k_isrealm()";
+                rcL = LSH_INVREALM;
+                goto cleanup;
+            }
+
+            err_context = "fetching ticket";
+            rc4 = (*pkrb_get_pw_in_tkt)(aname, inst, "", "krbtgt", realm,
+                                         lifetime, password);
+            if (rc4) /* XXX: do we want: && (rc != NO_TKT_FIL) as well? */
+            {
+                functionName = "krb_get_pw_in_tkt()";
+                rcL = KRBERR(rc4);
+                goto cleanup;
+            }
+        }
+    }
+#endif
+#ifndef NO_AFS
+    if ( !rc5 || (Leash_get_default_use_krb4() && !rc4) ) {
+        char c;
+        char *r;
+        char *t;
+        for ( r=realm, t=temp; c=*r; r++,t++ )
+            *t = isupper(c) ? tolower(c) : c;
+        *t = '\0';
+
+        rcA = Leash_afs_klog("afs", temp, "", lifetime);
+        rcB = Leash_afs_klog("afs", "", "", lifetime);
+        if (!(rcA && rcB))
+            rcA = 0;
+        else if (!rcA)
+            rcA = rcB;
+    }
+#endif /* NO_AFS */
+
+ cleanup:
+    return leash_error_message("Ticket initialization failed.",
+                               rcL,
+#ifdef NO_KRB4
+                               0,
+#else
+                               (rc5 && rc4)?KRBERR(rc4):0,
+#endif
+                               rc5, rcA, 0,
+                               displayErrors);
+}
+
+long FAR
+Leash_renew(void)
+{
+    if ( hKrb5 && !LeashKRB5_renew() ) {
+        int lifetime;
+        lifetime = Leash_get_default_lifetime() / 5;
+#ifndef NO_KRB4
+        if (hKrb4 && Leash_get_default_use_krb4())
+            Leash_convert524(0);
+#endif
+#ifndef NO_AFS
+        {
+            TicketList * list = NULL, * token;
+            not_an_API_LeashAFSGetToken(NULL,&list,NULL);
+            for ( token = list ; token ; token = token->next )
+                Leash_afs_klog("afs", token->realm, "", lifetime);
+            not_an_API_LeashFreeTicketList(&list);
+        }
+#endif /* NO_AFS */
+        return 1;
+    }
+    return 0;
+}
+
+BOOL
+GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
+{
+    NTSTATUS Status = 0;
+    HANDLE  TokenHandle;
+    TOKEN_STATISTICS Stats;
+    DWORD   ReqLen;
+    BOOL    Success;
+    PSECURITY_LOGON_SESSION_DATA pSessionData;
+
+    if (!ppSessionData)
+        return FALSE;
+    *ppSessionData = NULL;
+
+    Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+    if ( !Success )
+        return FALSE;
+
+    Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
+    CloseHandle( TokenHandle );
+    if ( !Success )
+        return FALSE;
+
+    Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, &pSessionData );
+    if ( FAILED(Status) || !pSessionData )
+        return FALSE;
+
+       *ppSessionData = pSessionData;
+    return TRUE;
+}
+
+// IsKerberosLogon() does not validate whether or not there are valid tickets in the
+// cache.  It validates whether or not it is reasonable to assume that if we
+// attempted to retrieve valid tickets we could do so.  Microsoft does not
+// automatically renew expired tickets.  Therefore, the cache could contain
+// expired or invalid tickets.  Microsoft also caches the user's password
+// and will use it to retrieve new TGTs if the cache is empty and tickets
+// are requested.
+
+BOOL
+IsKerberosLogon(VOID)
+{
+    PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
+    BOOL    Success = FALSE;
+
+    if ( GetSecurityLogonSessionData(&pSessionData) ) {
+        if ( pSessionData->AuthenticationPackage.Buffer ) {
+            WCHAR buffer[256];
+            WCHAR *usBuffer;
+            int usLength;
+
+            Success = FALSE;
+            usBuffer = (pSessionData->AuthenticationPackage).Buffer;
+            usLength = (pSessionData->AuthenticationPackage).Length;
+            if (usLength < 256)
+            {
+                lstrcpynW (buffer, usBuffer, usLength);
+                lstrcatW (buffer,L"");
+                if ( !lstrcmpW(L"Kerberos",buffer) )
+                    Success = TRUE;
+            }
+        }
+        pLsaFreeReturnBuffer(pSessionData);
+    }
+    return Success;
+}
+
+static BOOL
+IsWindowsVista (void)
+{
+    static BOOL fChecked = FALSE;
+    static BOOL fIsVista = FALSE;
+
+    if (!fChecked)
+    {
+        OSVERSIONINFO Version;
+
+        memset (&Version, 0x00, sizeof(Version));
+        Version.dwOSVersionInfoSize = sizeof(Version);
+
+        if (GetVersionEx (&Version))
+        {
+            if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT && Version.dwMajorVersion >= 6)
+                fIsVista = TRUE;
+        }
+        fChecked = TRUE;
+    }
+
+    return fIsVista;
+}
+
+static BOOL
+IsProcessUacLimited (void)
+{
+    static BOOL fChecked = FALSE;
+    static BOOL fIsUAC = FALSE;
+
+    if (!fChecked)
+    {
+        NTSTATUS Status = 0;
+        HANDLE  TokenHandle;
+        DWORD   ElevationLevel;
+        DWORD   ReqLen;
+        BOOL    Success;
+
+        if (IsWindowsVista()) {
+            Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
+            if ( Success ) {
+                Success = GetTokenInformation( TokenHandle,
+                                               TokenOrigin+1 /* ElevationLevel */,
+                                               &ElevationLevel, sizeof(DWORD), &ReqLen );
+                CloseHandle( TokenHandle );
+                if ( Success && ElevationLevel == 3 /* Limited */ )
+                    fIsUAC = TRUE;
+            }
+        }
+        fChecked = TRUE;
+    }
+    return fIsUAC;
+
+}
+
+// This looks really ugly because it is.  The result of IsKerberosLogon()
+// does not prove whether or not there are Kerberos tickets available to
+// be imported.  Only the call to Leash_ms2mit() which actually attempts
+// to import tickets can do that.  However, calling Leash_ms2mit() can
+// result in a TGS_REQ being sent to the KDC and since Leash_importable()
+// is called quite often we want to avoid this if at all possible.
+// Unfortunately, we have be shown at least one case in which the primary
+// authentication package was not Kerberos and yet there were Kerberos
+// tickets available.  Therefore, if IsKerberosLogon() is not TRUE we
+// must call Leash_ms2mit() but we still do not want to call it in a
+// tight loop so we cache the response and assume it won't change.
+
+// 2007-03-21
+// And the nightmare goes on.  On Vista the Lsa call we use to determine
+// whether or not Kerberos was used for logon fails to return and worse
+// corrupts the stack.  Therefore, we must now test to see if the
+// operating system is Vista and skip the call to IsKerberosLogon()
+// if it is.
+long FAR
+Leash_importable(void)
+{
+    if (IsProcessUacLimited())
+       return FALSE;
+
+    if ( !IsWindowsVista() && IsKerberosLogon() )
+        return TRUE;
+    else {
+        static int response = -1;
+        if (response == -1) {
+            response = Leash_ms2mit(0);
+        }
+        return response;
+    }
+}
+
+long FAR
+Leash_import(void)
+{
+    if ( Leash_ms2mit(1) ) {
+        int lifetime;
+        lifetime = Leash_get_default_lifetime() / 5;
+#ifndef NO_KRB4
+        if (hKrb4 && Leash_get_default_use_krb4())
+            Leash_convert524(0);
+#endif
+#ifndef NO_AFS
+        {
+            char c;
+            char *r;
+            char *t;
+            char  cell[256];
+            char  realm[256];
+            int   i = 0;
+            int   rcA = 0;
+            int   rcB = 0;
+
+            krb5_context ctx = 0;
+            krb5_error_code code = 0;
+            krb5_ccache cc = 0;
+            krb5_principal me = 0;
+
+            if ( !pkrb5_init_context )
+                goto cleanup;
+
+            code = pkrb5_init_context(&ctx);
+            if (code) goto cleanup;
+
+            code = pkrb5_cc_default(ctx, &cc);
+            if (code) goto cleanup;
+
+            if (code = pkrb5_cc_get_principal(ctx, cc, &me))
+                goto cleanup;
+
+            for ( r=realm, t=cell, i=0; i<krb5_princ_realm(ctx, me)->length; r++,t++,i++ ) {
+                c = krb5_princ_realm(ctx, me)->data[i];
+                *r = c;
+                *t = isupper(c) ? tolower(c) : c;
+            }
+            *r = *t = '\0';
+
+            rcA = Leash_afs_klog("afs", cell, "", lifetime);
+            rcB = Leash_afs_klog("afs", "", "", lifetime);
+            if (!(rcA && rcB))
+                rcA = 0;
+            else if (!rcA)
+                rcA = rcB;
+
+          cleanup:
+            if (me)
+                pkrb5_free_principal(ctx, me);
+            if (cc)
+                pkrb5_cc_close(ctx, cc);
+            if (ctx)
+                pkrb5_free_context(ctx);
+        }
+#endif /* NO_AFS */
+        return 1;
+    }
+    return 0;
+}
+
+long
+Leash_kdestroy(void)
+{
+#ifdef NO_KRB4
+    return 0;
+#else
+    int k_errno;
+
+    Leash_afs_unlog();
+    Leash_krb5_kdestroy();
+
+    if (pdest_tkt != NULL)
+    {
+        k_errno = (*pdest_tkt)();
+        if (k_errno && (k_errno != RET_TKFIL))
+            return KRBERR(k_errno);
+    }
+
+    return 0;
+#endif
+}
+
+#ifndef NO_KRB4
+int com_addr(void)
+{
+    long ipAddr;
+    char loc_addr[ADDR_SZ];
+    CREDENTIALS cred;
+    char service[40];
+    char instance[40];
+//    char addr[40];
+    char realm[40];
+    struct in_addr LocAddr;
+    int k_errno;
+
+    if (pkrb_get_cred == NULL)
+        return(KSUCCESS);
+
+    k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
+    if (k_errno)
+        return KRBERR(k_errno);
+
+
+    while(1) {
+       ipAddr = (*pLocalHostAddr)();
+       LocAddr.s_addr = ipAddr;
+        strcpy(loc_addr,inet_ntoa(LocAddr));
+       if ( strcmp(cred.address,loc_addr) != 0) {
+            Leash_kdestroy ();
+            break;
+       }
+        break;
+    } // while()
+    return 0;
+}
+#endif
+
+long FAR
+not_an_API_LeashFreeTicketList(TicketList** ticketList)
+{
+    TicketList* tempList = *ticketList, *killList;
+
+    //if (tempList == NULL)
+    //return -1;
+
+    while (tempList)
+    {
+        killList = tempList;
+
+        tempList = (TicketList*)tempList->next;
+        free(killList->theTicket);
+        if (killList->tktEncType)
+            free(killList->tktEncType);
+        if (killList->keyEncType)
+            free(killList->keyEncType);
+        if (killList->addrCount) {
+            int n;
+            for ( n=0; n<killList->addrCount; n++) {
+                if (killList->addrList[n])
+                    free(killList->addrList[n]);
+            }
+        }
+        if (killList->addrList)
+            free(killList->addrList);
+        if (killList->name)
+            free(killList->name);
+        if (killList->inst)
+            free(killList->inst);
+        if (killList->realm)
+            free(killList->realm);
+        free(killList);
+    }
+
+    *ticketList = NULL;
+    return 0;
+}
+
+long
+not_an_API_LeashKRB4GetTickets(TICKETINFO FAR* ticketinfo,
+                               TicketList** ticketList)
+{
+#ifdef NO_KRB4
+    return(KFAILURE);
+#else
+    // Puts tickets in a returned linklist - Can be used with many
+    // diff. controls
+    char    pname[ANAME_SZ];
+    char    pinst[INST_SZ];
+    char    prealm[REALM_SZ];
+    char    buf[MAX_K_NAME_SZ+40];
+    LPSTR   cp;
+    LPSTR   functionName;
+    long    expdate;
+    int     k_errno;
+    CREDENTIALS c;
+    int newtickets = 0;
+    int open = 0;
+
+    TicketList* list = NULL;
+    if ( ticketinfo ) {
+        ticketinfo->btickets = NO_TICKETS;
+        ticketinfo->principal[0] = '\0';
+    }
+
+    // Since krb_get_tf_realm will return a ticket_file error,
+    // we will call tf_init and tf_close first to filter out
+    // things like no ticket file.  Otherwise, the error that
+    // the user would see would be
+    // klist: can't find realm of ticket file: No ticket file (tf_util)
+    // instead of klist: No ticket file (tf_util)
+    if (ptf_init == NULL)
+        return(KSUCCESS);
+
+    com_addr();
+    err_context = (LPSTR)"tktf1";
+
+    // Open ticket file
+    if ((k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL)))
+    {
+        functionName = "ptf_init()";
+        goto cleanup;
+    }
+    // Close ticket file
+    (void) (*ptf_close)();
+
+    // We must find the realm of the ticket file here before calling
+    // tf_init because since the realm of the ticket file is not
+    // really stored in the principal section of the file, the
+    // routine we use must itself call tf_init and tf_close.
+
+    err_context = "tf realm";
+    if ((k_errno = (*pkrb_get_tf_realm)((*ptkt_string)(), prealm)) != KSUCCESS)
+    {
+        functionName = "pkrb_get_tf_realm()";
+        goto cleanup;
+    }
+
+    // Open ticket file
+    err_context = "tf init";
+    if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
+    {
+        functionName = "sptf_init()";
+        goto cleanup;
+    }
+
+    open = 1;
+    err_context = "tf pname";
+
+    // Get principal name and instance
+    if ((k_errno = (*ptf_get_pname)(pname)) || (k_errno = (*ptf_get_pinst)(pinst)))
+    {
+        functionName = "ptf_get_pname()";
+        goto cleanup;
+    }
+
+    // You may think that this is the obvious place to get the
+    // realm of the ticket file, but it can't be done here as the
+    // routine to do this must open the ticket file.  This is why
+    // it was done before tf_init.
+    wsprintf((LPSTR)ticketinfo->principal,"%s%s%s%s%s", (LPSTR)pname,
+             (LPSTR)(pinst[0] ? "." : ""), (LPSTR)pinst,
+             (LPSTR)(prealm[0] ? "@" : ""), (LPSTR)prealm);
+
+    newtickets = NO_TICKETS;
+    err_context = "tf cred";
+
+    // Get KRB4 tickets
+    while ((k_errno = (*ptf_get_cred)(&c)) == KSUCCESS)
+    {
+        if (!list)
+        {
+            list = (TicketList*) calloc(1, sizeof(TicketList));
+            (*ticketList) = list;
+        }
+        else
+        {
+            list->next = (struct TicketList*) calloc(1, sizeof(TicketList));
+            list = (TicketList*) list->next;
+        }
+
+        expdate = c.issue_date + c.lifetime * 5L * 60L;
+
+        if (!lstrcmp((LPSTR)c.service, (LPSTR)TICKET_GRANTING_TICKET) && !lstrcmp((LPSTR)c.instance, (LPSTR)prealm))
+        {
+            ticketinfo->issue_date = c.issue_date;
+            ticketinfo->lifetime = c.lifetime * 5L * 60L;
+            ticketinfo->renew_till = 0;
+        }
+
+        _tzset();
+        if ( ticketinfo->issue_date + ticketinfo->lifetime - time(0) <= 0L )
+            newtickets = EXPD_TICKETS;
+        else
+            newtickets = GOOD_TICKETS;
+
+        cp = (LPSTR)buf;
+        cp += wsprintf(cp, "%s     ",
+                       short_date(&c.issue_date));
+        wsprintf(cp, "%s     %s%s%s%s%s",
+                 short_date(&expdate),
+                 c.service,
+                 (c.instance[0] ? "." : ""),
+                 c.instance,
+                 (c.realm[0] ? "@" : ""),
+                 c.realm);
+
+        list->theTicket = (char*) calloc(1, sizeof(buf));
+        if (!list->theTicket)
+        {
+            MessageBox(NULL, "Memory Error", "Error", MB_OK);
+            return ENOMEM;
+        }
+
+        strcpy(list->theTicket, buf);
+        list->name = NULL;
+        list->inst = NULL;
+        list->realm = NULL;
+        list->tktEncType = NULL;
+        list->keyEncType = NULL;
+        list->addrCount = 0;
+        list->addrList = NULL;
+
+    } // while
+    functionName = "not_an_API_LeashKRB4GetTickets()";
+
+cleanup:
+    if (ptf_close == NULL)
+        return(KSUCCESS);
+
+    if (open)
+        (*ptf_close)(); //close ticket file
+
+    if (k_errno == EOF)
+        k_errno = 0;
+
+    // XXX the if statement directly below was inserted to eliminate
+    // an error NO_TKT_FIL on Leash startup. The error occurs from an
+    // error number thrown from krb_get_tf_realm.  We believe this
+    // change does not eliminate other errors, but it may.
+
+    if (k_errno == NO_TKT_FIL)
+        k_errno = 0;
+
+    ticketinfo->btickets = newtickets;
+
+    if (k_errno)
+    {
+        CHAR message[256];
+        CHAR errBuf[256];
+        LPCSTR errText;
+
+        if (!Lerror_message)
+            return -1;
+
+        errText = err_describe(errBuf, KRBERR(k_errno));
+
+        sprintf(message, "%s\n\n%s failed", errText, functionName);
+        MessageBox(NULL, message, "Kerberos Four",
+                   MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
+    }
+    return k_errno;
+#endif
+}
+
+long FAR Leash_klist(HWND hlist, TICKETINFO FAR *ticketinfo)
+{
+#ifdef NO_KRB4
+    return(KFAILURE);
+#else
+    // Don't think this function will be used anymore - ADL 5-15-99
+    // Old fucntion to put tickets in a listbox control
+    // Use function  "not_an_API_LeashKRB4GetTickets()" instead!
+    char    pname[ANAME_SZ];
+    char    pinst[INST_SZ];
+    char    prealm[REALM_SZ];
+    char    buf[MAX_K_NAME_SZ+40];
+    LPSTR   cp;
+    long    expdate;
+    int     k_errno;
+    CREDENTIALS c;
+    int newtickets = 0;
+    int open = 0;
+
+    /*
+     * Since krb_get_tf_realm will return a ticket_file error,
+     * we will call tf_init and tf_close first to filter out
+     * things like no ticket file.  Otherwise, the error that
+     * the user would see would be
+     * klist: can't find realm of ticket file: No ticket file (tf_util)
+     * instead of
+     * klist: No ticket file (tf_util)
+     */
+    if (ptf_init == NULL)
+        return(KSUCCESS);
+
+    if (hlist)
+    {
+        SendMessage(hlist, WM_SETREDRAW, FALSE, 0L);
+        SendMessage(hlist, LB_RESETCONTENT, 0, 0L);
+    }
+    com_addr();
+    newtickets = NO_TICKETS;
+
+    err_context = (LPSTR)"tktf1";
+
+    /* Open ticket file */
+    if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
+    {
+        goto cleanup;
+    }
+    /* Close ticket file */
+    (void) (*ptf_close)();
+    /*
+     * We must find the realm of the ticket file here before calling
+     * tf_init because since the realm of the ticket file is not
+     * really stored in the principal section of the file, the
+     * routine we use must itself call tf_init and tf_close.
+     */
+    err_context = "tf realm";
+    if ((k_errno = (*pkrb_get_tf_realm)((*ptkt_string)(), prealm)) != KSUCCESS)
+    {
+        goto cleanup;
+    }
+    /* Open ticket file */
+    err_context = "tf init";
+    if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
+    {
+        goto cleanup;
+    }
+
+    open = 1;
+    err_context = "tf pname";
+    /* Get principal name and instance */
+    if ((k_errno = (*ptf_get_pname)(pname)) || (k_errno = (*ptf_get_pinst)(pinst)))
+    {
+        goto cleanup;
+    }
+
+    /*
+     * You may think that this is the obvious place to get the
+     * realm of the ticket file, but it can't be done here as the
+     * routine to do this must open the ticket file.  This is why
+     * it was done before tf_init.
+     */
+
+    wsprintf((LPSTR)ticketinfo->principal,"%s%s%s%s%s", (LPSTR)pname,
+             (LPSTR)(pinst[0] ? "." : ""), (LPSTR)pinst,
+             (LPSTR)(prealm[0] ? "@" : ""), (LPSTR)prealm);
+    newtickets = GOOD_TICKETS;
+
+    err_context = "tf cred";
+    while ((k_errno = (*ptf_get_cred)(&c)) == KSUCCESS)
+    {
+        expdate = c.issue_date + c.lifetime * 5L * 60L;
+
+        if (!lstrcmp((LPSTR)c.service, (LPSTR)TICKET_GRANTING_TICKET) && !lstrcmp((LPSTR)c.instance, (LPSTR)prealm))
+        {
+            ticketinfo->issue_date = c.issue_date;
+            ticketinfo->lifetime = c.lifetime * 5L * 60L;
+            ticketinfo->renew_till = 0;
+        }
+
+        cp = (LPSTR)buf;
+        lstrcpy(cp, (LPSTR)short_date(&c.issue_date));
+        cp += lstrlen(cp);
+        wsprintf(cp,"\t%s\t%s%s%s%s%s",
+                 (LPSTR)short_date(&expdate), (LPSTR)c.service,
+                 (LPSTR)(c.instance[0] ? "." : ""),
+                 (LPSTR)c.instance, (LPSTR)(c.realm[0] ? "@" : ""),
+                 (LPSTR) c.realm);
+        if (hlist)
+            SendMessage(hlist, LB_ADDSTRING, 0, (LONG)(LPSTR)buf);
+    } /* WHILE */
+
+cleanup:
+
+    if (open)
+        (*ptf_close)(); /* close ticket file */
+
+    if (hlist)
+    {
+        SendMessage(hlist, WM_SETREDRAW, TRUE, 0L);
+        InvalidateRect(hlist, NULL, TRUE);
+        UpdateWindow(hlist);
+    }
+    if (k_errno == EOF)
+        k_errno = 0;
+
+    /* XXX the if statement directly below was inserted to eliminate
+       an error 20 on Leash startup. The error occurs from an error
+       number thrown from krb_get_tf_realm.  We believe this change
+       does not eliminate other errors, but it may. */
+
+    if (k_errno == RET_NOTKT)
+        k_errno = 0;
+
+    ticketinfo->btickets = newtickets;
+    if (k_errno != 0)
+        return KRBERR(k_errno);
+    return 0;
+#endif
+}
+
+
+// This function can be used to set the help file that will be
+// referenced the DLL's PasswordProcDLL function and err_describe
+// function.  Returns true if the help file has been set to the
+// argument or the environment variable KERB_HELP. Returns FALSE if
+// the default helpfile as defined in by HELPFILE in lsh_pwd.h is
+// used.
+BOOL Leash_set_help_file( char *szHelpFile )
+{
+    char tmpHelpFile[256];
+    BOOL ret = 0;
+
+    if( szHelpFile == NULL ){
+       GetEnvironmentVariable("KERB_HELP", tmpHelpFile, sizeof(tmpHelpFile));
+    } else {
+       strcpy( KRB_HelpFile, szHelpFile );
+       ret++;
+    }
+
+    if( !ret && tmpHelpFile[0] ){
+       strcpy( KRB_HelpFile, tmpHelpFile );
+       ret++;
+    }
+
+    if( !ret){
+       strcpy( KRB_HelpFile, HELPFILE );
+    }
+
+    return(ret);
+}
+
+
+
+LPSTR Leash_get_help_file(void)
+{
+    return( KRB_HelpFile);
+}
+
+#if 0
+/**************************************/
+/* LeashKrb4ErrorMessage():           */
+/**************************************/
+long
+LeashKrb4ErrorMessage(LONG rc, LPCSTR FailedFunctionName)
+{
+    // At this time the Leashw32.dll. takes care of all error messages. We
+    // may want to add a flag latter on so the .exe can handle it's own
+    // errors.
+
+    CHAR message[256];
+    CHAR errBuf[256];
+    LPCSTR errText;
+
+    if (!Lerror_message)
+      return -1;
+
+    errText = err_describe(errBuf, rc);
+
+    sprintf(message, "%s\n\n%s failed", errText, FailedFunctionName);
+    MessageBox(NULL, message, "Kerberos Four", MB_OK |
+                                               MB_ICONERROR |
+                                               MB_TASKMODAL |
+                                               MB_SETFOREGROUND);
+    return rc;
+}
+#endif
+
+int
+Leash_debug(
+    int class,
+    int priority,
+    char* fmt, ...
+    )
+{
+
+    return 0;
+}
+
+
+static int
+get_profile_file(LPSTR confname, UINT szConfname)
+{
+    char **configFile = NULL;
+    if (hKrb5) {
+        if (pkrb5_get_default_config_files(&configFile))
+        {
+            GetWindowsDirectory(confname,szConfname);
+            confname[szConfname-1] = '\0';
+            strncat(confname,"\\KRB5.INI",szConfname-strlen(confname));
+            confname[szConfname-1] = '\0';
+            return FALSE;
+        }
+
+        *confname = 0;
+
+        if (configFile)
+        {
+            strncpy(confname, *configFile, szConfname);
+            confname[szConfname-1] = '\0';
+            pkrb5_free_config_files(configFile);
+        }
+    }
+
+    if (!*confname)
+    {
+        GetWindowsDirectory(confname,szConfname);
+        confname[szConfname-1] = '\0';
+        strncat(confname,"\\KRB5.INI",szConfname-strlen(confname));
+        confname[szConfname-1] = '\0';
+    }
+
+    return FALSE;
+}
+
+static const char *const conf_yes[] = {
+    "y", "yes", "true", "t", "1", "on",
+    0,
+};
+
+static const char *const conf_no[] = {
+    "n", "no", "false", "nil", "0", "off",
+    0,
+};
+
+int
+config_boolean_to_int(const char *s)
+{
+    const char *const *p;
+
+    for(p=conf_yes; *p; p++) {
+        if (!strcasecmp(*p,s))
+            return 1;
+    }
+
+    for(p=conf_no; *p; p++) {
+        if (!strcasecmp(*p,s))
+            return 0;
+    }
+
+    /* Default to "no" */
+    return 0;
+}
+
+/*
+ * Leash_get_default_lifetime:
+ *
+ * This function is used to get the default ticket lifetime for this
+ * process in minutes.  A return value of 0 indicates no setting or
+ * "default" setting obtained.
+ *
+ * Here is where we look in order:
+ *
+ * - LIFETIME environment variable
+ * - HKCU\Software\MIT\Leash,lifetime
+ * - HKLM\Software\MIT\Leash,lifetime
+ * - string resource in the leash DLL
+ */
+
+BOOL
+get_DWORD_from_registry(
+    HKEY hBaseKey,
+    char * key,
+    char * value,
+    DWORD * result
+    )
+{
+    HKEY hKey;
+    DWORD dwCount;
+    LONG rc;
+
+    rc = RegOpenKeyEx(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey);
+    if (rc)
+        return FALSE;
+
+    dwCount = sizeof(DWORD);
+    rc = RegQueryValueEx(hKey, value, 0, 0, (LPBYTE) result, &dwCount);
+    RegCloseKey(hKey);
+
+    return rc?FALSE:TRUE;
+}
+
+BOOL
+get_STRING_from_registry(
+    HKEY hBaseKey,
+    char * key,
+    char * value,
+    char * outbuf,
+    DWORD  outlen
+    )
+{
+    HKEY hKey;
+    DWORD dwCount;
+    LONG rc;
+
+       if (!outbuf || outlen == 0)
+               return FALSE;
+
+    rc = RegOpenKeyEx(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey);
+    if (rc)
+        return FALSE;
+
+    dwCount = outlen;
+    rc = RegQueryValueEx(hKey, value, 0, 0, (LPBYTE) outbuf, &dwCount);
+    RegCloseKey(hKey);
+
+    return rc?FALSE:TRUE;
+}
+
+static
+BOOL
+get_default_lifetime_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_LIFETIME,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_lifetime(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFETIME);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_lifetime(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFETIME, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_lifetime(
+    )
+{
+    HMODULE hmLeash;
+    char env[32];
+    DWORD result;
+
+
+    if (GetEnvironmentVariable("LIFETIME",env,sizeof(env)))
+    {
+        return atoi(env);
+    }
+
+
+    if (get_default_lifetime_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_lifetime_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+       return result;
+    }
+
+    if ( hKrb5 ) {
+        CHAR confname[MAX_PATH];
+
+        if (!get_profile_file(confname, sizeof(confname)))
+        {
+            profile_t profile;
+            const char *filenames[2];
+            long retval;
+
+            filenames[0] = confname;
+            filenames[1] = NULL;
+            if (!pprofile_init(filenames, &profile)) {
+                char * value = NULL;
+
+                retval = pprofile_get_string(profile, "libdefaults", "ticket_lifetime", NULL, NULL, &value);
+                if (retval == 0 && value) {
+                    krb5_deltat d;
+
+                   retval = pkrb5_string_to_deltat(value, &d);
+
+                    if (retval == KRB5_DELTAT_BADFORMAT) {
+                        /* Historically some sites use relations of
+                           the form 'ticket_lifetime = 24000' where
+                           the unit is left out but is assumed to be
+                           seconds. Then there are other sites which
+                           use the form 'ticket_lifetime = 600' where
+                           the unit is assumed to be minutes.  While
+                           these are technically wrong (a unit needs
+                           to be specified), we try to accomodate for
+                           this using the safe assumption that the
+                           unit is seconds and tack an 's' to the end
+                           and see if that works. */
+
+                       /* Of course, Leash is one of the platforms
+                          that historically assumed no units and minutes
+                          so this change is going to break some people
+                          but its better to be consistent. */
+                        size_t cch;
+                        char buf[256];
+
+                       do {
+                           cch = strlen(value) + 2; /* NUL and new 's' */
+                           if (cch > sizeof(buf))
+                               break;
+
+                           strcpy(buf, value);
+                           strcat(buf, "s");
+
+                           retval = pkrb5_string_to_deltat(buf, &d);
+
+                           if (retval == 0) {
+                               result = d / 60;
+                           }
+                       } while(0);
+                    } else if (retval == 0) {
+                        result = d / 60;
+                    }
+
+                    pprofile_release_string(value);
+                }
+                pprofile_release(profile);
+               /* value has been released but we can still use a check for
+                * non-NULL to see if we were able to read a value.
+                */
+               if (retval == 0 && value)
+                   return result;
+            }
+        }
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char lifetime[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_TICKET_LIFE,
+                       lifetime, sizeof(lifetime)))
+        {
+            lifetime[sizeof(lifetime) - 1] = 0;
+            return atoi(lifetime);
+        }
+    }
+    return 0;
+}
+
+static
+BOOL
+get_default_renew_till_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_RENEW_TILL,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_renew_till(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_TILL);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_renew_till(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_TILL, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_renew_till(
+    )
+{
+    HMODULE hmLeash;
+    char env[32];
+    DWORD result;
+
+    if(GetEnvironmentVariable("RENEW_TILL",env,sizeof(env)))
+    {
+        return atoi(env);
+    }
+
+    if (get_default_renew_till_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_renew_till_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    if ( hKrb5 ) {
+        CHAR confname[MAX_PATH];
+        if (!get_profile_file(confname, sizeof(confname)))
+        {
+            profile_t profile;
+            const char *filenames[2];
+            int value=0;
+            long retval;
+            filenames[0] = confname;
+            filenames[1] = NULL;
+
+           if (!pprofile_init(filenames, &profile)) {
+                char * value = NULL;
+
+               retval = pprofile_get_string(profile, "libdefaults", "renew_lifetime", NULL, NULL, &value);
+                if (retval == 0 && value) {
+                    krb5_deltat d;
+
+                   retval = pkrb5_string_to_deltat(value, &d);
+                   if (retval == KRB5_DELTAT_BADFORMAT) {
+                        /* Historically some sites use relations of
+                           the form 'ticket_lifetime = 24000' where
+                           the unit is left out but is assumed to be
+                           seconds. Then there are other sites which
+                           use the form 'ticket_lifetime = 600' where
+                           the unit is assumed to be minutes.  While
+                           these are technically wrong (a unit needs
+                           to be specified), we try to accomodate for
+                           this using the safe assumption that the
+                           unit is seconds and tack an 's' to the end
+                           and see if that works. */
+
+                       /* Of course, Leash is one of the platforms
+                          that historically assumed no units and minutes
+                          so this change is going to break some people
+                          but its better to be consistent. */
+                        size_t cch;
+                        char buf[256];
+                       do {
+                           cch = strlen(value) + 2; /* NUL and new 's' */
+                           if (cch > sizeof(buf))
+                               break;
+
+                           strcpy(buf, value);
+                           strcat(buf, "s");
+
+                           retval = pkrb5_string_to_deltat(buf, &d);
+                           if (retval == 0) {
+                               result = d / 60;
+                           }
+                       } while(0);
+                    } else if (retval == 0) {
+                       result = d / 60;
+                    }
+                    pprofile_release_string(value);
+                }
+               pprofile_release(profile);
+               /* value has been released but we can still use a check for
+                * non-NULL to see if we were able to read a value.
+                */
+               if (retval == 0 && value)
+                   return result;
+
+               pprofile_release(profile);
+            }
+        }
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char renew_till[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_TICKET_RENEW_TILL,
+                       renew_till, sizeof(renew_till)))
+        {
+            renew_till[sizeof(renew_till) - 1] = 0;
+            return atoi(renew_till);
+        }
+    }
+    return 0;
+}
+
+static
+BOOL
+get_default_forwardable_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_FORWARDABLE,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_forwardable(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_FORWARDABLE);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_forwardable(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_FORWARDABLE, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_forwardable(
+    )
+{
+    HMODULE hmLeash;
+
+    char env[32];
+    DWORD result;
+
+    if(GetEnvironmentVariable("FORWARDABLE",env,sizeof(env)))
+    {
+        return atoi(env);
+    }
+
+    if (get_default_forwardable_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_forwardable_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    if ( hKrb5 ) {
+        CHAR confname[MAX_PATH];
+        if (!get_profile_file(confname, sizeof(confname)))
+        {
+            profile_t profile;
+            const char *filenames[2];
+            char *value=0;
+            long retval;
+            filenames[0] = confname;
+            filenames[1] = NULL;
+            if (!pprofile_init(filenames, &profile)) {
+                retval = pprofile_get_string(profile, "libdefaults","forwardable", 0, 0, &value);
+                if ( value ) {
+                    result = config_boolean_to_int(value);
+                    pprofile_release_string(value);
+                    pprofile_release(profile);
+                    return result;
+                }
+                pprofile_release(profile);
+            }
+        }
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char forwardable[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_TICKET_FORWARD,
+                       forwardable, sizeof(forwardable)))
+        {
+            forwardable[sizeof(forwardable) - 1] = 0;
+            return atoi(forwardable);
+        }
+    }
+    return 0;
+}
+
+static
+BOOL
+get_default_renewable_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_RENEWABLE,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_renewable(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEWABLE);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_renewable(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEWABLE, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_renewable(
+    )
+{
+    HMODULE hmLeash;
+    char env[32];
+    DWORD result;
+
+    if(GetEnvironmentVariable("RENEWABLE",env,sizeof(env)))
+    {
+        return atoi(env);
+    }
+
+    if (get_default_renewable_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_renewable_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    if ( hKrb5 ) {
+        CHAR confname[MAX_PATH];
+        if (!get_profile_file(confname, sizeof(confname)))
+        {
+            profile_t profile;
+            const char *filenames[2];
+            char *value=0;
+            long retval;
+            filenames[0] = confname;
+            filenames[1] = NULL;
+            if (!pprofile_init(filenames, &profile)) {
+                retval = pprofile_get_string(profile, "libdefaults","renewable", 0, 0, &value);
+                if ( value ) {
+                    result = config_boolean_to_int(value);
+                    pprofile_release_string(value);
+                    pprofile_release(profile);
+                    return result;
+                }
+                pprofile_release(profile);
+            }
+        }
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char renewable[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_TICKET_RENEW,
+                       renewable, sizeof(renewable)))
+        {
+            renewable[sizeof(renewable) - 1] = 0;
+            return atoi(renewable);
+        }
+    }
+    return 0;
+}
+
+static
+BOOL
+get_default_noaddresses_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_NOADDRESSES,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_noaddresses(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_NOADDRESSES);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_noaddresses(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_NOADDRESSES, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_noaddresses(
+    )
+{
+    HMODULE hmLeash;
+    char env[32];
+    DWORD result;
+
+    if ( hKrb5 ) {
+        // if the profile file cannot be opened then the value will be true
+        // if the noaddresses name cannot be found then the value will be true
+        // if true in the library, we can't alter it by other means
+        CHAR confname[MAX_PATH];
+        result = 1;
+        if (!get_profile_file(confname, sizeof(confname)))
+        {
+            profile_t profile;
+            const char *filenames[2];
+            char *value=0;
+            long retval;
+            filenames[0] = confname;
+            filenames[1] = NULL;
+            if (!pprofile_init(filenames, &profile)) {
+                retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
+                if ( value ) {
+                    result = config_boolean_to_int(value);
+                    pprofile_release_string(value);
+                }
+                pprofile_release(profile);
+            }
+        }
+
+        if ( result )
+            return 1;
+    }
+
+    // The library default is false, check other locations
+
+    if(GetEnvironmentVariable("NOADDRESSES",env,sizeof(env)))
+    {
+        return atoi(env);
+    }
+
+    if (get_default_noaddresses_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_noaddresses_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char noaddresses[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_TICKET_NOADDRESS,
+                       noaddresses, sizeof(noaddresses)))
+        {
+            noaddresses[sizeof(noaddresses) - 1] = 0;
+        }
+    }
+    return 1;
+}
+
+static
+BOOL
+get_default_proxiable_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_PROXIABLE,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_proxiable(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PROXIABLE);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_proxiable(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PROXIABLE, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_proxiable(
+    )
+{
+    HMODULE hmLeash;
+    char env[32];
+    DWORD result;
+
+    if(GetEnvironmentVariable("PROXIABLE",env,sizeof(env)))
+    {
+        return atoi(env);
+    }
+
+    if (get_default_proxiable_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_proxiable_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    if ( hKrb5 ) {
+        CHAR confname[MAX_PATH];
+        if (!get_profile_file(confname, sizeof(confname)))
+        {
+            profile_t profile;
+            const char *filenames[2];
+            char *value=0;
+            long retval;
+            filenames[0] = confname;
+            filenames[1] = NULL;
+            if (!pprofile_init(filenames, &profile)) {
+                retval = pprofile_get_string(profile, "libdefaults","proxiable", 0, 0, &value);
+                if ( value ) {
+                    result = config_boolean_to_int(value);
+                    pprofile_release_string(value);
+                    pprofile_release(profile);
+                    return result;
+                }
+                pprofile_release(profile);
+            }
+        }
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char proxiable[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_TICKET_PROXIABLE,
+                       proxiable, sizeof(proxiable)))
+        {
+            proxiable[sizeof(proxiable) - 1] = 0;
+            return atoi(proxiable);
+        }
+    }
+    return 0;
+}
+
+static
+BOOL
+get_default_publicip_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_PUBLICIP,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_publicip(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PUBLICIP);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_publicip(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PUBLICIP, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_publicip(
+    )
+{
+    HMODULE hmLeash;
+    char env[32];
+    DWORD result;
+
+    if(GetEnvironmentVariable("PUBLICIP",env,sizeof(env)))
+    {
+        return atoi(env);
+    }
+
+    if (get_default_publicip_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_publicip_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char publicip[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_TICKET_PUBLICIP,
+                       publicip, sizeof(publicip)))
+        {
+            publicip[sizeof(publicip) - 1] = 0;
+            return atoi(publicip);
+        }
+    }
+    return 0;
+}
+
+static
+BOOL
+get_default_use_krb4_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_USEKRB4,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_use_krb4(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_USEKRB4);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_use_krb4(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_USEKRB4, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_use_krb4(
+    )
+{
+    HMODULE hmLeash;
+    char env[32];
+    DWORD result;
+
+    if(GetEnvironmentVariable("USEKRB4",env,sizeof(env)))
+    {
+        return atoi(env);
+    }
+
+    if (get_default_use_krb4_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_use_krb4_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char use_krb4[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_TICKET_USEKRB4,
+                       use_krb4, sizeof(use_krb4)))
+        {
+            use_krb4[sizeof(use_krb4) - 1] = 0;
+            return atoi(use_krb4);
+        }
+    }
+    return 1;  /* use krb4 unless otherwise specified */
+}
+
+static
+BOOL
+get_hide_kinit_options_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_KINIT_OPT,
+                                   result);
+}
+
+DWORD
+Leash_reset_hide_kinit_options(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_KINIT_OPT);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_hide_kinit_options(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_KINIT_OPT, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_hide_kinit_options(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_hide_kinit_options_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_hide_kinit_options_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char use_krb4[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_KINIT_OPT,
+                       use_krb4, sizeof(use_krb4)))
+        {
+            use_krb4[sizeof(use_krb4) - 1] = 0;
+            return atoi(use_krb4);
+        }
+    }
+    return 0;  /* hide unless otherwise indicated */
+}
+
+
+
+static
+BOOL
+get_default_life_min_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_LIFE_MIN,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_life_min(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFE_MIN);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_life_min(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFE_MIN, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_life_min(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_default_life_min_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_life_min_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char use_krb4[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LIFE_MIN,
+                       use_krb4, sizeof(use_krb4)))
+        {
+            use_krb4[sizeof(use_krb4) - 1] = 0;
+            return atoi(use_krb4);
+        }
+    }
+    return 5;  /* 5 minutes */
+}
+
+static
+BOOL
+get_default_life_max_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_LIFE_MAX,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_life_max(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFE_MAX);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_life_max(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFE_MAX, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_life_max(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_default_life_max_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_life_max_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char use_krb4[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LIFE_MAX,
+                       use_krb4, sizeof(use_krb4)))
+        {
+            use_krb4[sizeof(use_krb4) - 1] = 0;
+            return atoi(use_krb4);
+        }
+    }
+    return 1440;
+}
+
+static
+BOOL
+get_default_renew_min_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_RENEW_MIN,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_renew_min(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_MIN);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_renew_min(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_MIN, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_renew_min(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_default_renew_min_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_renew_min_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char use_krb4[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_RENEW_MIN,
+                       use_krb4, sizeof(use_krb4)))
+        {
+            use_krb4[sizeof(use_krb4) - 1] = 0;
+            return atoi(use_krb4);
+        }
+    }
+    return 600;        /* 10 hours */
+}
+
+static
+BOOL
+get_default_renew_max_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_RENEW_MAX,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_renew_max(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_MAX);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_renew_max(
+    DWORD minutes
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_MAX, 0, REG_DWORD,
+                       (LPBYTE) &minutes, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_renew_max(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_default_renew_max_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_renew_max_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char use_krb4[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_RENEW_MAX,
+                       use_krb4, sizeof(use_krb4)))
+        {
+            use_krb4[sizeof(use_krb4) - 1] = 0;
+            return atoi(use_krb4);
+        }
+    }
+    return 60 * 24 * 30;
+}
+
+static
+BOOL
+get_lock_file_locations_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_LOCK_LOCATION,
+                                   result);
+}
+
+DWORD
+Leash_reset_lock_file_locations(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LOCK_LOCATION);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_lock_file_locations(
+    DWORD onoff
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LOCK_LOCATION, 0, REG_DWORD,
+                       (LPBYTE) &onoff, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_lock_file_locations(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_lock_file_locations_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_lock_file_locations_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char lock_file_locations[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LOCK_LOCATION,
+                       lock_file_locations, sizeof(lock_file_locations)))
+        {
+            lock_file_locations[sizeof(lock_file_locations) - 1] = 0;
+            return atoi(lock_file_locations);
+        }
+    }
+    return 0;
+}
+
+static
+BOOL
+get_default_uppercaserealm_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_SETTINGS_REGISTRY_KEY_NAME,
+                                   LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_uppercaserealm(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_uppercaserealm(
+    DWORD onoff
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM, 0, REG_DWORD,
+                       (LPBYTE) &onoff, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_uppercaserealm(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_default_uppercaserealm_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_uppercaserealm_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char uppercaserealm[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_UPPERCASEREALM,
+                       uppercaserealm, sizeof(uppercaserealm)))
+        {
+            uppercaserealm[sizeof(uppercaserealm) - 1] = 0;
+            return atoi(uppercaserealm);
+        }
+    }
+    return 1;
+}
+
+static
+BOOL
+get_default_mslsa_import_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_SETTINGS_REGISTRY_KEY_NAME,
+                                   LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_mslsa_import(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_mslsa_import(
+    DWORD onoffmatch
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT, 0, REG_DWORD,
+                       (LPBYTE) &onoffmatch, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_mslsa_import(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_default_mslsa_import_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_mslsa_import_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char mslsa_import[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_MSLSA_IMPORT,
+                       mslsa_import, sizeof(mslsa_import)))
+        {
+            mslsa_import[sizeof(mslsa_import) - 1] = 0;
+            return atoi(mslsa_import);
+        }
+    }
+    return 2;   /* import only when mslsa realm matches default */
+}
+
+
+static
+BOOL
+get_default_preserve_kinit_settings_from_registry(
+    HKEY hBaseKey,
+    DWORD * result
+    )
+{
+    return get_DWORD_from_registry(hBaseKey,
+                                   LEASH_REGISTRY_KEY_NAME,
+                                   LEASH_REGISTRY_VALUE_PRESERVE_KINIT,
+                                   result);
+}
+
+DWORD
+Leash_reset_default_preserve_kinit_settings(
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
+    if (rc)
+        return rc;
+
+    rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PRESERVE_KINIT);
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_set_default_preserve_kinit_settings(
+    DWORD onoff
+    )
+{
+    HKEY hKey;
+    LONG rc;
+
+    rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
+                        0, 0, KEY_WRITE, 0, &hKey, 0);
+    if (rc)
+        return rc;
+
+    rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PRESERVE_KINIT, 0, REG_DWORD,
+                       (LPBYTE) &onoff, sizeof(DWORD));
+    RegCloseKey(hKey);
+
+    return rc;
+}
+
+DWORD
+Leash_get_default_preserve_kinit_settings(
+    )
+{
+    HMODULE hmLeash;
+    DWORD result;
+
+    if (get_default_preserve_kinit_settings_from_registry(HKEY_CURRENT_USER, &result) ||
+        get_default_preserve_kinit_settings_from_registry(HKEY_LOCAL_MACHINE, &result))
+    {
+        return result;
+    }
+
+    hmLeash = GetModuleHandle(LEASH_DLL);
+    if (hmLeash)
+    {
+        char preserve_kinit_settings[80];
+        if (LoadString(hmLeash, LSH_DEFAULT_PRESERVE_KINIT,
+                       preserve_kinit_settings, sizeof(preserve_kinit_settings)))
+        {
+            preserve_kinit_settings[sizeof(preserve_kinit_settings) - 1] = 0;
+            return atoi(preserve_kinit_settings);
+        }
+    }
+    return 1;
+}
+
+void
+Leash_reset_defaults(void)
+{
+    Leash_reset_default_lifetime();
+    Leash_reset_default_renew_till();
+    Leash_reset_default_renewable();
+    Leash_reset_default_forwardable();
+    Leash_reset_default_noaddresses();
+    Leash_reset_default_proxiable();
+    Leash_reset_default_publicip();
+    Leash_reset_default_use_krb4();
+    Leash_reset_hide_kinit_options();
+    Leash_reset_default_life_min();
+    Leash_reset_default_life_max();
+    Leash_reset_default_renew_min();
+    Leash_reset_default_renew_max();
+    Leash_reset_default_uppercaserealm();
+    Leash_reset_default_mslsa_import();
+    Leash_reset_default_preserve_kinit_settings();
+}
+
+static BOOL CALLBACK
+EnumChildProc(HWND hwnd, LPARAM lParam)
+{
+    HWND * h = (HWND *)lParam;
+    *h = hwnd;
+    return FALSE;
+}
+
+
+static HWND
+FindFirstChildWindow(HWND parent)
+{
+    HWND hFirstChild = 0;
+    EnumChildWindows(parent, EnumChildProc, (LPARAM) &hFirstChild);
+    return hFirstChild;
+}
+
+static int
+acquire_tkt_send_msg(krb5_context ctx, const char * title,
+                    const char * ccachename,
+                    krb5_principal desiredKrb5Principal,
+                    const char * out_ccname, int out_cclen)
+{
+    krb5_error_code    err;
+    HWND               hNetIdMgr;
+    HWND               hForeground;
+    char               *desiredName = 0;
+    char                *desiredRealm = 0;
+
+    /* do we want a specific client principal? */
+    if (desiredKrb5Principal != NULL) {
+       err = pkrb5_unparse_name (ctx, desiredKrb5Principal, &desiredName);
+       if (!err) {
+           char * p;
+           for (p = desiredName; *p && *p != '@'; p++);
+           if ( *p == '@' ) {
+               *p = '\0';
+               desiredRealm = ++p;
+           }
+       }
+    }
+
+    hForeground = GetForegroundWindow();
+    hNetIdMgr = FindWindow("IDMgrRequestDaemonCls", "IDMgrRequestDaemon");
+    if (hNetIdMgr != NULL) {
+       HANDLE hMap;
+       DWORD  tid = GetCurrentThreadId();
+       char mapname[256];
+       NETID_DLGINFO *dlginfo;
+
+       sprintf(mapname,"Local\\NetIDMgr_DlgInfo_%lu",tid);
+
+       hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+                                0, 4096, mapname);
+       if (hMap == NULL) {
+           return -1;
+       } else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS) {
+           CloseHandle(hMap);
+           return -1;
+       }
+
+       dlginfo = (NETID_DLGINFO *)MapViewOfFileEx(hMap, FILE_MAP_READ|FILE_MAP_WRITE,
+                                                0, 0, 4096, NULL);
+       if (dlginfo == NULL) {
+           CloseHandle(hMap);
+           return -1;
+       }
+
+       memset(dlginfo, 0, sizeof(NETID_DLGINFO));
+
+       dlginfo->size = sizeof(NETID_DLGINFO);
+       dlginfo->dlgtype = NETID_DLGTYPE_TGT;
+       dlginfo->in.use_defaults = 1;
+
+       if (title) {
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               title, -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       } else if (desiredName && (strlen(desiredName) + strlen(desiredRealm) + 32 < NETID_TITLE_SZ)) {
+           char mytitle[NETID_TITLE_SZ];
+           sprintf(mytitle, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm);
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               mytitle, -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       } else {
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               "Obtain Kerberos TGT", -1,
+                               dlginfo->in.title, NETID_TITLE_SZ);
+       }
+       if (desiredName)
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               desiredName, -1,
+                               dlginfo->in.username, NETID_USERNAME_SZ);
+       if (desiredRealm)
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               desiredRealm, -1,
+                               dlginfo->in.realm, NETID_REALM_SZ);
+       if (ccachename)
+           MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
+                               ccachename, -1,
+                               dlginfo->in.ccache, NETID_CCACHE_NAME_SZ);
+       SendMessage(hNetIdMgr, 32810, 0, (LPARAM) tid);
+
+       if (out_ccname && out_cclen > 0) {
+           WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, dlginfo->out.ccache, -1,
+                               out_ccname, out_cclen, NULL, NULL);
+       }
+
+       UnmapViewOfFile(dlginfo);
+       CloseHandle(hMap);
+    } else {
+       HGLOBAL                 hData;
+       HWND hLeash = FindWindow("LEASH.0WNDCLASS", NULL);
+       hLeash = FindFirstChildWindow(hLeash);
+
+       /* construct a marshalling of data
+        *   <title><principal><realm><ccache>
+        * then send to Leash
+        */
+
+       hData = GlobalAlloc( GHND, 4096 );
+       SetForegroundWindow(hLeash);
+       if ( hData && hLeash ) {
+           char * strs = GlobalLock(hData);
+           if ( strs ) {
+               if (title)
+                   strcpy(strs, title);
+               else if (desiredName)
+                   sprintf(strs, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm);
+               else
+                   strcpy(strs, "Obtain Kerberos TGT");
+               strs += strlen(strs) + 1;
+               if ( desiredName ) {
+                   strcpy(strs, desiredName);
+                   strs += strlen(strs) + 1;
+                   if (desiredRealm) {
+                       strcpy(strs, desiredRealm);
+                       strs += strlen(strs) + 1;
+                   }
+               } else {
+                   *strs = 0;
+                   strs++;
+                   *strs = 0;
+                   strs++;
+               }
+
+               /* Append the ccache name */
+               if (ccachename)
+                   strcpy(strs, ccachename);
+               else
+                   *strs = 0;
+               strs++;
+
+               GlobalUnlock( hData );
+               SendMessage(hLeash, 32810, 0, (LPARAM) hData);
+           }
+       }
+       GlobalFree( hData );
+    }
+
+    SetForegroundWindow(hForeground);
+    if (desiredName != NULL)
+       pkrb5_free_unparsed_name(ctx, desiredName);
+
+    return 0;
+}
+
+static void
+acquire_tkt_no_princ(krb5_context context, char * ccname, int cclen)
+{
+    TicketList                 *list = NULL;
+    TICKETINFO         ticketinfo;
+    krb5_context        ctx;
+    DWORD              dwMsLsaImport = Leash_get_default_mslsa_import();
+    DWORD              gle;
+    char ccachename[272]="";
+    char loginenv[16];
+    BOOL prompt;
+
+    GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv));
+    prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+
+    ctx = context;
+
+    SetLastError(0);
+    GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
+    gle = GetLastError();
+    if ( (gle == ERROR_ENVVAR_NOT_FOUND) && context ) {
+       SetEnvironmentVariable("KRB5CCNAME", pkrb5_cc_default_name(ctx));
+       GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
+    }
+
+    not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
+    not_an_API_LeashFreeTicketList(&list);
+
+    if ( ticketinfo.btickets != GOOD_TICKETS &&
+         dwMsLsaImport && Leash_importable() ) {
+        // We have the option of importing tickets from the MSLSA
+        // but should we?  Do the tickets in the MSLSA cache belong
+        // to the default realm used by Leash?  Does the default
+       // ccache name specify a principal name?  Only import if we
+       // aren't going to break the default identity as specified
+       // by the user in Network Identity Manager.
+        int import = 0;
+       BOOL isCCPrinc;
+
+       /* Determine if the default ccachename is principal name.  If so, don't
+       * import the MSLSA: credentials into it unless the names match.
+       */
+       isCCPrinc = (strncmp("API:",ccachename, 4) == 0 && strchr(ccachename, '@'));
+
+        if ( dwMsLsaImport == 1 && !isCCPrinc ) { /* always import */
+            import = 1;
+        } else if ( dwMsLsaImport ) {            /* import when realms match */
+            krb5_error_code code;
+            krb5_ccache mslsa_ccache=NULL;
+            krb5_principal princ = NULL;
+           char *mslsa_principal = NULL;
+            char ms_realm[128] = "", *def_realm = NULL, *r;
+            int i;
+
+            if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
+                goto cleanup;
+
+            if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
+                goto cleanup;
+
+            for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
+                *r = krb5_princ_realm(ctx, princ)->data[i];
+            }
+            *r = '\0';
+
+            if (code = pkrb5_get_default_realm(ctx, &def_realm))
+                goto cleanup;
+
+           if (code = pkrb5_unparse_name(ctx, princ, &mslsa_principal))
+               goto cleanup;
+
+            import = (!isCCPrinc && !strcmp(def_realm, ms_realm)) ||
+               (isCCPrinc && !strcmp(&ccachename[4], mslsa_principal));
+
+          cleanup:
+           if (mslsa_principal)
+               pkrb5_free_unparsed_name(ctx, mslsa_principal);
+
+            if (def_realm)
+                pkrb5_free_default_realm(ctx, def_realm);
+
+            if (princ)
+                pkrb5_free_principal(ctx, princ);
+
+            if (mslsa_ccache)
+                pkrb5_cc_close(ctx, mslsa_ccache);
+        }
+
+        if ( import ) {
+            Leash_import();
+
+            not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
+            not_an_API_LeashFreeTicketList(&list);
+        }
+    }
+
+    if ( prompt && ticketinfo.btickets != GOOD_TICKETS ) {
+       acquire_tkt_send_msg(ctx, NULL, ccachename, NULL, ccname, cclen);
+    } else if (ccachename[0] && ccname) {
+       strncpy(ccname, ccachename, cclen);
+       ccname[cclen-1] = '\0';
+    }
+
+    if ( ccname && strcmp(ccachename,ccname) ) {
+       SetEnvironmentVariable("KRB5CCNAME",ccname);
+    }
+
+    if ( !context )
+        pkrb5_free_context(ctx);
+}
+
+
+static void
+acquire_tkt_for_princ(krb5_context context, krb5_principal desiredPrincipal,
+                     char * ccname, int cclen)
+{
+    TicketList                 *list = NULL;
+    TICKETINFO         ticketinfo;
+    krb5_context        ctx;
+    DWORD              dwMsLsaImport = Leash_get_default_mslsa_import();
+    DWORD              gle;
+    char               ccachename[272]="";
+    char               loginenv[16];
+    BOOL               prompt;
+    char               *name = NULL;
+
+    GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv));
+    prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+
+    ctx = context;
+
+    SetLastError(0);
+    GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
+    gle = GetLastError();
+    if ( (gle == ERROR_ENVVAR_NOT_FOUND) && context ) {
+       SetEnvironmentVariable("KRB5CCNAME", pkrb5_cc_default_name(ctx));
+       GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
+    }
+
+    not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
+    not_an_API_LeashFreeTicketList(&list);
+
+    pkrb5_unparse_name(ctx, desiredPrincipal, &name);
+
+    if ( ticketinfo.btickets != GOOD_TICKETS &&
+         dwMsLsaImport && Leash_importable() ) {
+        // We have the option of importing tickets from the MSLSA
+        // but should we?  Does the MSLSA principal match the requested
+       // principal?  If not, there is no benefit to importing.
+        int import = 0;
+       krb5_error_code code;
+       krb5_ccache mslsa_ccache=NULL;
+       krb5_principal princ = NULL;
+
+       if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
+           goto cleanup;
+
+       if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
+           goto cleanup;
+
+       import = pkrb5_principal_compare(ctx, desiredPrincipal, princ);
+
+      cleanup:
+       if (princ)
+           pkrb5_free_principal(ctx, princ);
+
+       if (mslsa_ccache)
+           pkrb5_cc_close(ctx, mslsa_ccache);
+
+
+        if ( import ) {
+           /* Construct a new default ccache name into which the MSLSA:
+            * credentials can be imported, set the default ccache to that
+            * ccache, and then only import if that ccache does not already
+            * contain valid tickets */
+           sprintf(ccachename, "API:%s", name);
+
+           SetEnvironmentVariable("KRB5CCNAME", ccachename);
+
+            not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
+            not_an_API_LeashFreeTicketList(&list);
+
+           if (ticketinfo.btickets != GOOD_TICKETS) {
+               Leash_import();
+
+               not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
+               not_an_API_LeashFreeTicketList(&list);
+           }
+       }
+    }
+
+    if (prompt) {
+       if (ticketinfo.btickets != GOOD_TICKETS || strcmp(name,ticketinfo.principal)) {
+           acquire_tkt_send_msg(ctx, NULL, ccachename, desiredPrincipal, ccname, cclen);
+       } else if (ccachename[0] && ccname) {
+           strncpy(ccname, ccachename, cclen);
+           ccname[cclen-1] = '\0';
+       }
+    }
+
+    if ( ccname && strcmp(ccachename,ccname) ) {
+       SetEnvironmentVariable("KRB5CCNAME",ccname);
+    }
+
+
+    if (name)
+       pkrb5_free_unparsed_name(ctx, name);
+
+    if ( !context )
+        pkrb5_free_context(ctx);
+}
+
+
+static int
+leash_int_get_princ_expiration_time(krb5_context ctx, krb5_ccache cc,
+                                   krb5_principal desiredPrincipal,
+                                   krb5_timestamp * pexpiration)
+{
+    krb5_principal principal = 0;
+    char * princ_name = NULL;
+    char * desired_name = NULL;
+    krb5_creds creds;
+    krb5_error_code code, code2;
+    krb5_error_code cc_code;
+    krb5_cc_cursor cur;
+    krb5_timestamp now, expiration = 0;
+
+    int rv = -1;
+
+    if (!ctx || !cc || !desiredPrincipal || !pexpiration)
+        return -1;
+
+    code = pkrb5_cc_get_principal(ctx, cc, &principal);
+    if ( code )
+        return -1;
+
+
+    code = pkrb5_unparse_name(ctx, desiredPrincipal, &desired_name);
+    code2 = pkrb5_unparse_name(ctx, principal, &princ_name);
+
+    /* compare principal to ident. */
+    if ( code || !princ_name ||        code2 || !desired_name ||
+        strcmp(princ_name, desired_name) ) {
+        if (princ_name)
+            pkrb5_free_unparsed_name(ctx, princ_name);
+        if (desired_name)
+            pkrb5_free_unparsed_name(ctx, desired_name);
+        pkrb5_free_principal(ctx, principal);
+        return -1;
+    }
+
+    pkrb5_free_unparsed_name(ctx, princ_name);
+    pkrb5_free_unparsed_name(ctx, desired_name);
+    pkrb5_free_principal(ctx, principal);
+
+    code = pkrb5_timeofday(ctx, &now);
+
+    if (code)
+        return -1;
+
+    cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
+
+    while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
+        krb5_data * c0 = krb5_princ_name(ctx, creds.server);
+        krb5_data * c1  = krb5_princ_component(ctx, creds.server, 1);
+        krb5_data * r = krb5_princ_realm(ctx, creds.server);
+
+        if ( c0 && c1 && r && c1->length == r->length &&
+             !strncmp(c1->data,r->data,r->length) &&
+             !strncmp("krbtgt",c0->data,c0->length) ) {
+
+            /* we have a TGT, check for the expiration time.
+             * if it is valid and renewable, use the renew time
+             */
+
+            if (!(creds.ticket_flags & TKT_FLG_INVALID) &&
+                creds.times.starttime < now && creds.times.endtime > now) {
+                expiration = creds.times.endtime;
+
+                if ((creds.ticket_flags & TKT_FLG_RENEWABLE) &&
+                    (creds.times.renew_till > creds.times.endtime)) {
+                    expiration = creds.times.renew_till;
+                }
+            }
+        }
+    }
+
+    if (cc_code == KRB5_CC_END) {
+        cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
+        rv = 0;
+        *pexpiration = expiration;
+    }
+
+    return rv;
+}
+
+/* returns 0 on success */
+static int
+leash_int_find_ccache_for_princ(krb5_context ctx, krb5_principal princ,
+                               char * buffer, int * pcbbuf)
+{
+    krb5_ccache         cache = 0;
+    krb5_error_code     code;
+    apiCB *             cc_ctx = 0;
+    struct _infoNC **   pNCi = NULL;
+    int                 i;
+    krb5_timestamp      expiration = 0;
+    krb5_timestamp      best_match_expiration = 0;
+    char                best_match_ccname[256] = "";
+    DWORD              dwMsLsaImport = Leash_get_default_mslsa_import();
+
+    if (!buffer || !pcbbuf)
+       return -1;
+
+    code = cc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
+    if (code)
+        goto _exit;
+
+    code = cc_get_NC_info(cc_ctx, &pNCi);
+    if (code)
+        goto _exit;
+
+    for(i=0; pNCi[i]; i++) {
+        if (pNCi[i]->vers != CC_CRED_V5)
+            continue;
+
+        code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cache);
+        if (code)
+            continue;
+
+        /* need a function to check the cache for the identity
+         * and determine if it has valid tickets.  If it has
+         * the right identity and valid tickets, store the
+         * expiration time and the cache name.  If it has the
+         * right identity but no valid tickets, store the ccache
+         * name and an expiration time of zero.  if it does not
+         * have the right identity don't save the name.
+         *
+         * Keep searching to find the best cache available.
+         */
+
+        if (!leash_int_get_princ_expiration_time(ctx, cache, princ,
+                                                &expiration)) {
+            if ( expiration > best_match_expiration ) {
+                best_match_expiration = expiration;
+                strncpy(best_match_ccname, "API:",
+                              sizeof(best_match_ccname));
+                strncat(best_match_ccname, pNCi[i]->name,
+                        sizeof(best_match_ccname));
+               best_match_ccname[sizeof(best_match_ccname)-1] = '\0';
+                expiration = 0;
+            }
+        }
+
+        if(ctx != NULL && cache != NULL)
+            pkrb5_cc_close(ctx, cache);
+        cache = 0;
+    }
+
+    if (dwMsLsaImport) {
+       code = pkrb5_cc_resolve(ctx, "MSLSA:", &cache);
+       if (code == 0 && cache) {
+           if (!leash_int_get_princ_expiration_time(ctx, cache, princ,
+                                                     &expiration)) {
+               if ( expiration > best_match_expiration ) {
+                   best_match_expiration = expiration;
+                   strcpy(best_match_ccname, "MSLSA:");
+                   expiration = 0;
+               }
+           }
+       }
+    }
+
+    if (ctx != NULL && cache != NULL)
+       pkrb5_cc_close(ctx, cache);
+
+    cache = 0;
+
+ _exit:
+    if (pNCi)
+        cc_free_NC_info(cc_ctx, &pNCi);
+
+    if (cc_ctx)
+        cc_shutdown(&cc_ctx);
+
+    if (best_match_ccname[0]) {
+       strncpy(buffer, best_match_ccname, *pcbbuf);
+       buffer[*pcbbuf-1]='\0';
+
+       *pcbbuf = strlen(buffer) + 1;
+       return 0;
+    }
+
+    return -1;
+}
+
+void FAR
+not_an_API_Leash_AcquireInitialTicketsIfNeeded(krb5_context context,
+                                              krb5_principal desiredKrb5Principal,
+                                              char * ccname, int cclen)
+{
+    char               *desiredName = 0;
+    char                *desiredRealm = 0;
+    TicketList                 *list = NULL;
+    char ccachename[272]="";
+
+    if (!desiredKrb5Principal) {
+       acquire_tkt_no_princ(context, ccname, cclen);
+    } else {
+       if (leash_int_find_ccache_for_princ(context, desiredKrb5Principal, ccname, &cclen))
+           acquire_tkt_for_princ(context, desiredKrb5Principal, ccname, cclen);
+    }
+    return;
+}
diff --git a/src/windows/leashdll/registry.c b/src/windows/leashdll/registry.c
new file mode 100644 (file)
index 0000000..7113d05
--- /dev/null
@@ -0,0 +1,105 @@
+#include <windows.h>
+#include "leash-int.h"
+
+static
+LONG
+write_registry_setting_ex(
+    HKEY hRoot,
+    char* setting,
+    DWORD type,
+    void* buffer,
+    size_t size
+    )
+{
+    HKEY hKey = 0;
+    LONG rc = 0;
+
+    if (rc = RegCreateKeyEx(hRoot, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, 0, 0,
+                            KEY_ALL_ACCESS, 0, &hKey, 0))
+        goto cleanup;
+
+    rc = RegSetValueEx(hKey, setting, 0, type, (LPBYTE)buffer, size);
+ cleanup:
+    if (hKey)
+        RegCloseKey(hKey);
+    return rc;
+}
+
+LONG
+write_registry_setting(
+    char* setting,
+    DWORD type,
+    void* buffer,
+    size_t size
+    )
+{
+    return write_registry_setting_ex(HKEY_CURRENT_USER,
+                                     setting,
+                                     type,
+                                     buffer,
+                                     size);
+}
+
+static
+LONG
+read_registry_setting_ex(
+    HKEY hRoot,
+    char* setting,
+    void* buffer,
+    size_t size
+    )
+{
+    HKEY hKey = 0;
+    LONG rc = 0;
+    DWORD dwType;
+    DWORD dwCount;
+
+    if (rc = RegOpenKeyEx(hRoot,
+                          LEASH_SETTINGS_REGISTRY_KEY_NAME,
+                          0, KEY_QUERY_VALUE, &hKey))
+        goto cleanup;
+
+    memset(buffer, 0, size);
+    dwCount = size;
+    rc = RegQueryValueEx(hKey, setting, NULL, &dwType, (LPBYTE)buffer,
+                         &dwCount);
+ cleanup:
+    if (hKey)
+        RegCloseKey(hKey);
+    return rc;
+}
+
+LONG
+read_registry_setting_user(
+    char* setting,
+    void* buffer,
+    size_t size
+    )
+{
+    return read_registry_setting_ex(HKEY_CURRENT_USER, setting, buffer, size);
+}
+
+static
+LONG
+read_registry_setting_machine(
+    char* setting,
+    void* buffer,
+    size_t size
+    )
+{
+    return read_registry_setting_ex(HKEY_LOCAL_MACHINE, setting, buffer, size);
+}
+
+LONG
+read_registry_setting(
+    char* setting,
+    void* buffer,
+    size_t size
+    )
+{
+    LONG rc;
+    rc = read_registry_setting_user(setting, buffer, size);
+    if (!rc) return rc;
+    rc = read_registry_setting_machine(setting, buffer, size);
+    return rc;
+}
diff --git a/src/windows/leashdll/reminder.h b/src/windows/leashdll/reminder.h
new file mode 100644 (file)
index 0000000..05dd4bd
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __REMINDER_H__
+#define __REMINDER_H__
+
+#define Stringize( L )        #L
+#define MakeString( M, L )    M(L)
+#define $LINE                 MakeString( Stringize, __LINE__ )
+#define Reminder              __FILE__ "(" $LINE ") : Reminder: "
+
+#endif
+
+//Put this in your .cpp file where ever you need it (NOTE: Don't end this statement with a ';' char)
+//i.e. -->> #pragma message(Reminder "Your message reminder here!!!")
diff --git a/src/windows/leashdll/res/islogo.bmp b/src/windows/leashdll/res/islogo.bmp
new file mode 100644 (file)
index 0000000..c4af48f
Binary files /dev/null and b/src/windows/leashdll/res/islogo.bmp differ
diff --git a/src/windows/leashdll/res/leash.ico b/src/windows/leashdll/res/leash.ico
new file mode 100644 (file)
index 0000000..9ef4f96
Binary files /dev/null and b/src/windows/leashdll/res/leash.ico differ
diff --git a/src/windows/leashdll/resource.h b/src/windows/leashdll/resource.h
new file mode 100644 (file)
index 0000000..637c938
--- /dev/null
@@ -0,0 +1,19 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by lsh_pwd.rc
+//
+#define IDOK2                           5
+#define IDCANCEL2                       6
+#define LEASHICON                       100
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC                     1
+#define _APS_NEXT_RESOURCE_VALUE        103
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1002
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/src/windows/leashdll/timesync.c b/src/windows/leashdll/timesync.c
new file mode 100644 (file)
index 0000000..c9feadb
--- /dev/null
@@ -0,0 +1,297 @@
+/* timesync stuff for leash - 7/28/94 - evanr */
+
+#include <windows.h>
+#include "leashdll.h"
+
+#include <time.h>
+#include <sys\timeb.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <winkrbid.h>
+
+#ifdef WSHELPER
+#include <wshelper.h>
+#endif
+
+#include <stdio.h>
+#include "leasherr.h"
+#include "leashids.h"
+
+int ProcessTimeSync(char *, int, char *);
+
+#define TM_OFFSET 2208988800
+
+/* timezone.h has a winsock.h conflict */
+struct timezone {
+    int     tz_minuteswest;
+    int     tz_dsttime;
+};
+
+/************************************/
+/* settimeofday():                  */
+/************************************/
+int
+settimeofday(
+    struct timeval *tv,
+    struct timezone *tz
+    )
+{
+    SYSTEMTIME systime;
+    struct tm *newtime;
+
+    newtime = gmtime((time_t *)&(tv->tv_sec));
+    systime.wYear = 1900+newtime->tm_year;
+    systime.wMonth = 1+newtime->tm_mon;
+    systime.wDay = newtime->tm_mday;
+    systime.wHour = newtime->tm_hour;
+    systime.wMinute = newtime->tm_min;
+    systime.wSecond = newtime->tm_sec;
+    systime.wMilliseconds = 0;
+    return SetSystemTime(&systime);
+}
+
+/************************************/
+/* gettimeofday():                  */
+/************************************/
+int
+gettimeofday(
+    struct timeval *tv,
+    struct timezone *tz
+    )
+{
+    struct _timeb tb;
+    _tzset();
+    _ftime(&tb);
+    if (tv) {
+       tv->tv_sec = tb.time;
+       tv->tv_usec = tb.millitm * 1000;
+    }
+    if (tz) {
+       tz->tz_minuteswest = tb.timezone;
+       tz->tz_dsttime = tb.dstflag;
+    }
+    return 0;
+}
+
+
+LONG
+not_an_API_LeashGetTimeServerName(
+    char *timeServerName,
+    const char *valueName
+    )
+{
+    HMODULE     hmLeash;
+    char        hostname[128];
+    char        value[80];
+    DWORD       dwType;
+    DWORD       dwCount;
+    int         check = 0;
+    HKEY       hKey;
+    HKEY        rKey1;
+    HKEY        rKey2;
+    LONG        lResult;
+    BOOL       bEnv;
+
+    memset(value, '\0', sizeof(value));
+    memset(hostname, '\0', sizeof(hostname));
+
+    GetEnvironmentVariable("TIMEHOST", hostname, sizeof(hostname));
+    bEnv = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+
+    if (!(bEnv && hostname[0]))
+    {
+        // Check registry for TIMEHOST
+        rKey1 = HKEY_CURRENT_USER;
+        rKey2 = HKEY_LOCAL_MACHINE;
+
+        for (check = 0; check < 2; check++)
+        {
+            if (ERROR_SUCCESS == RegOpenKeyEx(check == 0 ? rKey1 : rKey2,
+                                              "Software\\MIT\\Leash32\\Settings",
+                                              0, KEY_QUERY_VALUE, &hKey))
+            {
+                memset(value, '\0', sizeof(value));
+                lResult = RegQueryValueEx(hKey, (LPTSTR)valueName, NULL,
+                                          &dwType, NULL, &dwCount);
+                if (lResult == ERROR_SUCCESS)
+                {
+                    lResult = RegQueryValueEx(hKey, (LPTSTR)valueName,
+                                              NULL, &dwType,
+                                              (LPTSTR)value, &dwCount);
+                    if (lResult == ERROR_SUCCESS && *value)
+                    {
+                        // found
+                        strcpy(hostname, value);
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (!*hostname)
+        {
+            // Check resource string for TIMEHOST
+            if ((hmLeash = GetModuleHandle(LEASH_DLL)) != NULL)
+            {
+                if (!LoadString(hmLeash, LSH_TIME_HOST, hostname,
+                                sizeof(hostname)))
+                    memset(hostname, '\0', sizeof(hostname));
+            }
+        }
+        if (!*hostname)
+        {
+            // OK, _Default_ it will be! :)
+            strcpy(hostname, "time");
+        }
+    }
+    strcpy(timeServerName, hostname);
+    return 0;
+}
+
+/************************************/
+/* Leash_timesync():                */
+/************************************/
+LONG Leash_timesync(int MessageP)
+{
+    char                tmpstr[2048];
+    char                tmpstr1[2048];
+    char                hostname[128];
+    int                 Port;
+    int                 rc;
+    struct servent      *sp;
+    WORD                wVersionRequested;
+    WSADATA             wsaData;
+    char                name[80];
+
+    if ((pkrb5_init_context == NULL)
+#ifndef NO_KRB4
+        && (ptkt_string == NULL)
+#endif
+         )
+        return(0);
+
+    wVersionRequested = 0x0101;
+    memset(name, '\0', sizeof(name));
+    memset(hostname, '\0', sizeof(hostname));
+    memset(tmpstr, '\0', sizeof(tmpstr));
+
+    if ((rc = WSAStartup(wVersionRequested, &wsaData)))
+    {
+        wsprintf(tmpstr, "Couldn't initialize WinSock to synchronize time\n\rError Number: %d", rc);
+        WSACleanup();
+        return(LSH_BADWINSOCK);
+    }
+
+    sp = getservbyname("time", "udp");
+    if (sp == 0)
+        Port = htons(IPPORT_TIMESERVER);
+    else
+        Port = sp->s_port;
+
+    not_an_API_LeashGetTimeServerName(hostname, TIMEHOST);
+
+    rc = ProcessTimeSync(hostname, Port, tmpstr);
+
+    if(MessageP != 0)
+    {
+        if (rc && !*tmpstr)
+        {
+            strcpy(tmpstr, "Unable to syncronize time!\n\n");
+            if (*hostname)
+            {
+                memset(tmpstr1, '\0', sizeof(tmpstr1));
+                sprintf(tmpstr1, "Unreachable server: %s\n", hostname);
+                strcat(tmpstr, tmpstr1);
+            }
+        }
+
+       MessageBox(NULL, tmpstr, "Time Server",
+                   MB_ICONERROR | MB_OK);
+    }
+    WSACleanup();
+    return(rc);
+}
+
+
+/************************************/
+/* ProcessTimeSync():               */
+/************************************/
+int ProcessTimeSync(char *hostname, int Port, char *tmpstr)
+{
+    char                buffer[512];
+    int                 cc;
+    register long       *nettime;
+    register int        s;
+    long                hosttime;
+    struct hostent      *host;
+    struct              timeval tv;
+    struct              timezone tz;
+    u_long              argp;
+    struct sockaddr_in  sin;
+    int                 i;
+
+    if ((host = gethostbyname(hostname)) == NULL)
+        return(LSH_BADTIMESERV);
+
+    sin.sin_port = (short)Port;
+    sin.sin_family = host->h_addrtype;
+    memcpy((struct sockaddr *)&sin.sin_addr, host->h_addr, host->h_length);
+    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+    {
+        return(LSH_NOSOCKET);
+    }
+
+    argp = 1;
+    if (ioctlsocket(s, FIONBIO, &argp) != 0)
+    {
+        closesocket(s);
+        return(LSH_NOCONNECT);
+    }
+
+    if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+    {
+        closesocket(s);
+        return(LSH_NOCONNECT);
+    }
+    send(s, buffer, 40, 0);
+    if (gettimeofday (&tv, &tz) < 0)
+    {
+        closesocket(s);
+        return(LSH_GETTIMEOFDAY);
+    }
+
+    for (i = 0; i < 4; i++)
+    {
+        if ((cc = recv(s, buffer, 512, 0)) > 0)
+            break;
+        Sleep(500);
+    }
+    if (i == 4)
+    {
+        closesocket(s);
+        return(LSH_RECVTIME);
+    }
+
+    if (cc != 4)
+    {
+        closesocket(s);
+        return(LSH_RECVBYTES);
+    }
+
+    nettime = (long *)buffer;
+    hosttime = (long) ntohl (*nettime) - TM_OFFSET;
+    (&tv)->tv_sec = hosttime;
+    if (settimeofday(&tv, &tz) < 0)
+    {
+        closesocket(s);
+        return(LSH_SETTIMEOFDAY);
+    }
+
+    sprintf(tmpstr, "The time has been syncronized with the server:   %s\n\n", hostname);
+    strcat(tmpstr, "To be able to use the Kerberos server, it was necessary to \nset the system time to:  ") ;
+    strcat(tmpstr, ctime((time_t *)&hosttime));
+    strcat(tmpstr, "\n");
+    closesocket(s);
+    return(0);
+}
diff --git a/src/windows/leashdll/ver.rc b/src/windows/leashdll/ver.rc
new file mode 100644 (file)
index 0000000..88bb7d9
--- /dev/null
@@ -0,0 +1,4 @@
+#define VER_FILEDESCRIPTION_STR        "Leash Helper DLL"
+
+#include <kerberos.ver>
+#include <ver.inc>
diff --git a/src/windows/leashdll/winerr.c b/src/windows/leashdll/winerr.c
new file mode 100644 (file)
index 0000000..10806d8
--- /dev/null
@@ -0,0 +1,240 @@
+/*  WINERR.C
+
+    Jason Hunter
+    8/2/94
+    DCNS/IS MIT
+
+
+  Contains the error functions for leash and kerberos.  Prints out keen windows
+  error messages in english.
+
+*/
+
+#include <stdio.h>
+#include "conf.h"
+
+// Private Include files
+#include "leashdll.h"
+#include <krb.h>
+#include <leashwin.h>
+
+// Global Variables.
+static long lsh_errno;
+static char *err_context;       /* error context */
+extern int (*Lcom_err)(LPSTR,long,LPSTR,...);
+extern LPSTR (*Lerror_message)(long);
+extern LPSTR (*Lerror_table_name)(long);
+
+#ifdef WIN16
+#define UNDERSCORE "_"
+#else
+#define UNDERSCORE
+#endif
+
+HWND GetRootParent (HWND Child)
+{
+    HWND Last;
+    while (Child)
+    {
+        Last = Child;
+        Child = GetParent (Child);
+    }
+    return Last;
+}
+
+
+LPSTR err_describe(LPSTR buf, long code)
+{
+    LPSTR cp, com_err_msg;
+    int offset;
+    long table_num;
+    char *etype;
+
+    offset = (int) (code & 255);
+    table_num = code - offset;
+    com_err_msg = Lerror_message(code);
+
+    switch(table_num)
+    {
+#ifndef NO_KRB4
+    case krb_err_base:
+    case kadm_err_base:
+       break;
+#endif
+    default:
+       lstrcpy(buf, com_err_msg);
+       return buf;
+    }
+
+    cp = buf;
+#ifndef NO_KRB4
+    if (table_num == krb_err_base)
+        switch(offset)
+        {
+        case KDC_NAME_EXP:           /* 001 Principal expired */
+        case KDC_SERVICE_EXP:        /* 002 Service expired */
+        case KDC_AUTH_EXP:           /* 003 Auth expired */
+        case KDC_PKT_VER:            /* 004 Protocol version unknown */
+        case KDC_P_MKEY_VER:         /* 005 Wrong master key version */
+        case KDC_S_MKEY_VER:         /* 006 Wrong master key version */
+        case KDC_BYTE_ORDER:         /* 007 Byte order unknown */
+        case KDC_PR_N_UNIQUE:        /* 009 Principal not unique */
+        case KDC_NULL_KEY:           /* 010 Principal has null key */
+        case KDC_GEN_ERR:            /* 011 Generic error from KDC */
+        case INTK_W_NOTALL   :       /* 061 Not ALL tickets returned */
+        case INTK_PROT       :       /* 063 Protocol Error */
+        case INTK_ERR        :       /* 070 Other error */
+            com_err_msg = "Something weird happened... try again, and if Leash"
+                " continues to fail, contact Network Services as listed in the "
+                "About box.";
+            break;
+        case KDC_PR_UNKNOWN:         /* 008 Principal unknown */
+            com_err_msg = "You have entered an unknown username/instance/realm"
+                " combination.";
+            break;
+        case GC_TKFIL                :       /* 021 Can't read ticket file */
+        case GC_NOTKT                :       /* 022 Can't find ticket or TGT */
+            com_err_msg = "Something is wrong with the memory where your "
+                "tickets are stored. Try exiting Windows and restarting your "
+                "computer.";
+            break;
+        case MK_AP_TGTEXP    :       /* 026 TGT Expired */
+            /* no extra error msg */
+            break;
+        case RD_AP_TIME              :       /* 037 delta_t too big */
+            com_err_msg = "Your computer's clock is out of sync with the "
+                "Kerberos server.  Please see the help file about correcting "
+                "your clock.";
+            break;
+
+        case RD_AP_UNDEC             :       /* 031 Can't decode authenticator */
+        case RD_AP_EXP               :       /* 032 Ticket expired */
+        case RD_AP_NYV               :       /* 033 Ticket not yet valid */
+        case RD_AP_REPEAT    :       /* 034 Repeated request */
+        case RD_AP_NOT_US    :       /* 035 The ticket isn't for us */
+        case RD_AP_INCON             :       /* 036 Request is inconsistent */
+        case RD_AP_BADD              :       /* 038 Incorrect net address */
+        case RD_AP_VERSION   :       /* 039 protocol version mismatch */
+        case RD_AP_MSG_TYPE  :       /* 040 invalid msg type */
+        case RD_AP_MODIFIED  :       /* 041 message stream modified */
+        case RD_AP_ORDER             :       /* 042 message out of order */
+        case RD_AP_UNAUTHOR  :       /* 043 unauthorized request */
+            /* no extra error msg */
+            break;
+        case GT_PW_NULL:     /* 51    Current PW is null */
+        case GT_PW_BADPW:    /* 52    Incorrect current password */
+        case GT_PW_PROT:     /* 53    Protocol Error */
+        case GT_PW_KDCERR:   /* 54    Error returned by KDC */
+        case GT_PW_NULLTKT:  /* 55    Null tkt returned by KDC */
+            /* no error msg yet */
+            break;
+
+            /* Values returned by send_to_kdc */
+        case SKDC_RETRY   :  /* 56    Retry count exceeded */
+        case SKDC_CANT    :  /* 57    Can't send request */
+            com_err_msg = "Cannot contact the kerberos server for the selected realm.";
+            break;
+            /* no error message on purpose: */
+        case INTK_BADPW      :       /* 062 Incorrect password */
+            break;
+        default:
+            /* no extra error msg */
+            break;
+        }
+    else
+        switch(code)
+        {
+        case KADM_INSECURE_PW:
+            /* if( kadm_info != NULL ){
+             * wsprintf(buf, "%s\n%s", com_err_msg, kadm_info);
+             * } else {
+             * wsprintf(buf, "%s\nPlease see the help file for information "
+             * "about secure passwords.", com_err_msg);
+             * }
+             * com_err_msg = buf;
+             */
+
+            /* The above code would be preferred since it allows site specific
+             * information to be delivered from the Kerberos server. However the
+             * message box is too small for VGA screens.
+             * It does work well if we only have to support 1024x768
+             */
+
+            com_err_msg = "You have entered an insecure or weak password.";
+        default:
+            /* no extra error msg */
+            break;
+        }
+#endif /* NO_KRB4 */
+    if(com_err_msg != buf)
+        lstrcpy(buf, com_err_msg);
+    cp = buf + lstrlen(buf);
+    *cp++ = '\n';
+    switch(table_num) {
+#ifndef NO_KRB4
+    case krb_err_base:
+        etype = "Kerberos";
+        break;
+    case kadm_err_base:
+        etype = "Kerberos supplemental";
+        break;
+#endif
+    default:
+        etype = Lerror_table_name(table_num);
+        break;
+    }
+    wsprintf((LPSTR) cp, (LPSTR) "(%s error %d"
+#ifdef DEBUG_COM_ERR
+             " (absolute error %ld)"
+#endif
+             ")", etype, offset
+             //")\nPress F1 for help on this error.", etype, offset
+#ifdef DEBUG_COM_ERR
+             , code
+#endif
+        );
+
+    return (LPSTR)buf;
+}
+
+int _export lsh_com_err_proc (LPSTR whoami, long code,
+                              LPSTR fmt, va_list args)
+{
+    int retval;
+    HWND hOldFocus;
+    char buf[1024], *cp; /* changed to 512 by jms 8/23/93 */
+    WORD mbformat = MB_OK | MB_ICONEXCLAMATION;
+
+    cp = buf;
+    memset(buf, '\0', sizeof(buf));
+    cp[0] = '\0';
+
+    if (code)
+    {
+        err_describe(buf, code);
+        while (*cp)
+            cp++;
+    }
+
+    if (fmt)
+    {
+        if (fmt[0] == '%' && fmt[1] == 'b')
+       {
+            fmt += 2;
+            mbformat = va_arg(args, WORD);
+            /* if the first arg is a %b, we use it for the message
+               box MB_??? flags. */
+       }
+        if (code)
+       {
+            *cp++ = '\n';
+            *cp++ = '\n';
+       }
+        wvsprintf((LPSTR)cp, fmt, args);
+    }
+    hOldFocus = GetFocus();
+    retval = MessageBox(/*GetRootParent(hOldFocus)*/NULL, buf, whoami,
+                        mbformat | MB_ICONHAND | MB_TASKMODAL);
+    SetFocus(hOldFocus);
+    return retval;
+}
diff --git a/src/windows/leashdll/winutil.c b/src/windows/leashdll/winutil.c
new file mode 100644 (file)
index 0000000..65609bc
--- /dev/null
@@ -0,0 +1,138 @@
+#include <windows.h>
+#include "leash-int.h"
+
+//#include <string.h>
+
+static ATOM sAtom = 0;
+static HINSTANCE shInstance = 0;
+
+/* Callback for the MITPasswordControl
+This is a replacement for the normal edit control.  It does not show the
+annoying password char in the edit box so that the number of chars in the
+password are not known.
+*/
+
+#define PASSWORDCHAR '#'
+#define DLGHT(ht) (HIWORD(GetDialogBaseUnits())*(ht)/8)
+#define DLGWD(wd) (LOWORD(GetDialogBaseUnits())*(wd)/4)
+
+static
+LRESULT
+CALLBACK
+MITPasswordEditProc(
+    HWND hWnd,
+    UINT message,
+    WPARAM wParam,
+    LPARAM lParam
+    )
+{
+    static SIZE pwdcharsz;
+    BOOL pass_the_buck = FALSE;
+
+    if (message > WM_USER && message < 0x7FFF)
+        pass_the_buck = TRUE;
+
+    switch(message)
+    {
+    case WM_GETTEXT:
+    case WM_GETTEXTLENGTH:
+    case WM_SETTEXT:
+        pass_the_buck = TRUE;
+        break;
+    case WM_PAINT:
+    {
+        HDC hdc;
+        PAINTSTRUCT ps;
+        RECT r;
+
+        hdc = BeginPaint(hWnd, &ps);
+        GetClientRect(hWnd, &r);
+        Rectangle(hdc, 0, 0, r.right, r.bottom);
+        EndPaint(hWnd, &ps);
+    }
+    break;
+    case WM_SIZE:
+    {
+        MoveWindow(GetDlgItem(hWnd, 1), DLGWD(2), DLGHT(2),
+                  pwdcharsz.cx / 2, pwdcharsz.cy, TRUE);
+    }
+    break;
+    case WM_LBUTTONDOWN:
+    case WM_SETFOCUS:
+    {
+        SetFocus(GetDlgItem(hWnd, 1));
+    }
+    break;
+    case WM_CREATE:
+    {
+        HWND heditchild;
+        char pwdchar = PASSWORDCHAR;
+        HDC hdc;
+        /* Create a child window of this control for default processing. */
+        hdc = GetDC(hWnd);
+        GetTextExtentPoint32(hdc, &pwdchar, 1, &pwdcharsz);
+        ReleaseDC(hWnd, hdc);
+
+        heditchild =
+            CreateWindow("edit", "", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL |
+                         ES_LEFT | ES_PASSWORD | WS_TABSTOP,
+                         0, 0, 0, 0,
+                         hWnd,
+                         (HMENU)1,
+                         ((LPCREATESTRUCT)lParam)->hInstance,
+                         NULL);
+        SendMessage(heditchild, EM_SETPASSWORDCHAR, PASSWORDCHAR, 0L);
+    }
+    break;
+    }
+
+    if (pass_the_buck)
+        return SendMessage(GetDlgItem(hWnd, 1), message, wParam, lParam);
+    return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+BOOL
+Register_MITPasswordEditControl(
+    HINSTANCE hInst
+    )
+{
+    if (!sAtom) {
+        WNDCLASS wndclass;
+
+        memset(&wndclass, 0, sizeof(WNDCLASS));
+
+        shInstance = hInst;
+
+        wndclass.style = CS_HREDRAW | CS_VREDRAW;
+        wndclass.lpfnWndProc = (WNDPROC)MITPasswordEditProc;
+        wndclass.cbClsExtra = sizeof(HWND);
+        wndclass.cbWndExtra = 0;
+        wndclass.hInstance = shInstance;
+        wndclass.hbrBackground = (void *)(COLOR_WINDOW + 1);
+        wndclass.lpszClassName = MIT_PWD_DLL_CLASS;
+        wndclass.hCursor = LoadCursor((HINSTANCE)NULL, IDC_IBEAM);
+
+        sAtom = RegisterClass(&wndclass);
+    }
+    return sAtom ? TRUE : FALSE;
+}
+
+BOOL
+Unregister_MITPasswordEditControl(
+    HINSTANCE hInst
+    )
+{
+    BOOL result = TRUE;
+
+    if ((hInst != shInstance) || !sAtom) {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    result = UnregisterClass(MIT_PWD_DLL_CLASS, hInst);
+    if (result) {
+        sAtom = 0;
+        shInstance = 0;
+    }
+    return result;
+}
diff --git a/src/windows/wshelper/dllmain.c b/src/windows/wshelper/dllmain.c
new file mode 100644 (file)
index 0000000..5ae0016
--- /dev/null
@@ -0,0 +1,264 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winsock.h>
+#include "wsh-int.h"
+#include <windns.h>
+#include "hesiod.h"
+#include "pwd.h"
+
+
+DWORD dwHesIndex; // for hes_to_bind
+DWORD dwHesMailIndex; // for hes_getmailhost
+DWORD dwHesServIndex;  // for hes_getservbyname
+DWORD dwHesPwNamIndex; // for hes_getpwnam;
+DWORD dwHesPwUidIndex; // for hes_getpwuid
+DWORD dwGhnIndex; // for rgethostbyname
+DWORD dwGhaIndex; // for rgethostbyaddr
+
+#define LISTSIZE 15
+
+void FreeThreadLocalMemory();
+void AllocateThreadLocalMemory();
+void FreePasswdStruct(LPVOID lpvData);
+void FreeHostentStruct(LPVOID lpvData);
+
+BOOL
+WINAPI
+DllMain(
+    HINSTANCE hinstDLL,  // handle to DLL module
+    DWORD fdwReason,     // reason for calling function
+    LPVOID lpvReserved   // reserved
+)
+{
+    switch(fdwReason)
+    {
+    case DLL_PROCESS_ATTACH:
+        if ((dwHesIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+            return FALSE;
+        if ((dwHesMailIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+            return FALSE;
+        if ((dwHesServIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+            return FALSE;
+        if ((dwHesPwNamIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+            return FALSE;
+       if ((dwHesPwUidIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+            return FALSE;
+       if ((dwHesPwUidIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+            return FALSE;
+       if ((dwGhnIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+            return FALSE;
+       if ((dwGhaIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+            return FALSE;
+        res_init_startup();
+     case DLL_THREAD_ATTACH:
+        // Initialize the TLS index for this thread.
+        AllocateThreadLocalMemory();
+        break;
+
+     case DLL_THREAD_DETACH:
+
+        // Release the allocated memory for this thread.
+        FreeThreadLocalMemory();
+        break;
+
+
+    case DLL_PROCESS_DETACH:
+        // Release the TLS index.
+        FreeThreadLocalMemory();
+        TlsFree(dwHesIndex);
+        TlsFree(dwHesMailIndex);
+        TlsFree(dwHesServIndex);
+        TlsFree(dwHesPwNamIndex);
+       TlsFree(dwHesPwUidIndex);
+       TlsFree(dwGhnIndex);
+       TlsFree(dwGhaIndex);
+
+        res_init_cleanup();
+        break;
+    }
+    return TRUE;
+}
+
+void AllocateThreadLocalMemory()
+{
+    LPVOID lpvData;
+
+    lpvData = (LPVOID) LocalAlloc(LPTR, DNS_MAX_NAME_BUFFER_LENGTH);
+    if (lpvData != NULL)
+        TlsSetValue(dwHesIndex, lpvData);
+
+    lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct hes_postoffice));
+    if (lpvData != NULL)
+        TlsSetValue(dwHesMailIndex, lpvData);
+
+    lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct servent));
+    if (lpvData != NULL)
+        TlsSetValue(dwHesServIndex, lpvData);
+
+    lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct passwd));
+    if (lpvData != NULL)
+        TlsSetValue(dwHesPwNamIndex, lpvData);
+
+    lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct passwd));
+    if (lpvData != NULL)
+        TlsSetValue(dwHesPwUidIndex, lpvData);
+
+    lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct hostent));
+    if (lpvData != NULL)
+        TlsSetValue(dwGhnIndex, lpvData);
+
+    lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct hostent));
+    if (lpvData != NULL)
+        TlsSetValue(dwGhaIndex, lpvData);
+
+}
+void FreeThreadLocalMemory()
+{
+    LPVOID lpvData;
+    int i;
+
+    lpvData = TlsGetValue(dwHesIndex);
+    if (lpvData != NULL)
+        LocalFree((HLOCAL) lpvData);
+
+    // free hes_postoffice
+    lpvData = TlsGetValue(dwHesMailIndex);
+    if (lpvData)
+    {
+        struct hes_postoffice* p = (struct hes_postoffice*) lpvData;
+        if (p->po_type)
+        {
+            LocalFree(p->po_type);
+            p->po_type = NULL;
+        }
+        if (p->po_host)
+        {
+           LocalFree(p->po_host);
+           p->po_host = NULL;
+        }
+        if (p->po_name)
+        {
+            LocalFree(p->po_name);
+            p->po_name = NULL;
+        }
+        LocalFree((HLOCAL) lpvData);
+     }
+
+    // free servent
+    lpvData = TlsGetValue(dwHesServIndex);
+    if (lpvData)
+    {
+        struct servent* s = (struct servent*) lpvData;
+        if (s->s_name)
+        {
+            LocalFree(s->s_name);
+            s->s_name = NULL;
+        }
+        if (s->s_proto)
+        {
+            LocalFree(s->s_proto);
+            s->s_proto = NULL;
+        }
+        if (s->s_aliases)
+        {
+            for (i = 0; i<LISTSIZE; i++)
+            {
+                if (s->s_aliases[i])
+                {
+                    LocalFree(s->s_aliases[i]);
+                    s->s_aliases[i] = NULL;
+                }
+            }
+            LocalFree(s->s_aliases);
+        }
+        LocalFree((HLOCAL) lpvData);
+    }
+
+    // free struct passwd
+    lpvData = TlsGetValue(dwHesPwNamIndex);
+    FreePasswdStruct(lpvData);
+
+    lpvData = TlsGetValue(dwHesPwUidIndex);
+    FreePasswdStruct(lpvData);
+
+    // free struct hostent
+    lpvData = TlsGetValue(dwGhnIndex);
+    FreeHostentStruct(lpvData);
+
+    lpvData = TlsGetValue(dwGhaIndex);
+    FreeHostentStruct(lpvData);
+
+}
+
+
+void FreeHostentStruct(LPVOID lpvData)
+{
+    if (lpvData)
+    {
+       int i = 0;
+       struct hostent* host = (struct hostent*) lpvData;
+       if (host->h_name)
+           LocalFree(host->h_name);
+       if (host->h_aliases)
+       {
+           while(host->h_aliases[i])
+           {
+               LocalFree(host->h_aliases[i]);
+               host->h_aliases[i] = NULL;
+               i++;
+           }
+           LocalFree(host->h_aliases);
+       }
+       if (host->h_addr_list)
+       {
+           i = 0;
+           while (host->h_addr_list[i])
+           {
+               LocalFree(host->h_addr_list[i]);
+               host->h_addr_list[i] = NULL;
+               i++;
+           }
+           LocalFree(host->h_addr_list);
+       }
+       LocalFree((HLOCAL) lpvData);
+    }
+}
+
+void FreePasswdStruct(LPVOID lpvData)
+{
+    if (lpvData)
+    {
+        struct passwd* p = (struct passwd*) lpvData;
+        if (p->pw_name)
+        {
+            LocalFree(p->pw_name);
+            p->pw_name = NULL;
+        }
+        if (p->pw_passwd)
+        {
+            LocalFree(p->pw_passwd);
+            p->pw_passwd = NULL;
+        }
+        if (p->pw_comment)
+        {
+            LocalFree(p->pw_comment);
+            p->pw_comment = NULL;
+        }
+        if (p->pw_gecos)
+        {
+            LocalFree(p->pw_gecos);
+            p->pw_gecos = NULL;
+        }
+        if (p->pw_dir)
+        {
+            LocalFree(p->pw_dir);
+            p->pw_dir = NULL;
+        }
+        if (p->pw_shell)
+        {
+            LocalFree(p->pw_shell);
+            p->pw_shell = NULL;
+        }
+        LocalFree((HLOCAL) lpvData);
+    }
+}
diff --git a/src/windows/wshelper/gethna.c b/src/windows/wshelper/gethna.c
new file mode 100644 (file)
index 0000000..8914c32
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+*      @doc RESOLVE
+*
+*      @module gethna.c  |
+*
+*      This file contains the function definitions for:
+*              rgethostbyname,
+*              rgethostbyaddr,
+*              rdn_expand,
+*              gethinfobyname,
+*              getmxbyname,
+*              getrecordbyname,
+*              rrhost,
+*              rgetservbyname,
+*      and some other internal functions called by these functions.
+*
+*
+*      WSHelper DNS/Hesiod Library for WINSOCK
+*
+*/
+
+/*
+ * Copyright (c) 1985, 1988 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c    6.48 (Berkeley) 1/10/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <windows.h>
+#include <winsock.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <windns.h>
+
+#ifdef _WIN32
+#include <mitwhich.h>
+#endif
+
+#define MAXALIASES      35
+#define MAXADDRS        35
+
+extern DWORD dwGhnIndex;
+extern DWORD dwGhaIndex;
+
+unsigned long WINAPI inet_aton(register const char *, struct in_addr *);
+
+
+#ifdef _DEBUG
+#ifndef DEBUG
+#define DEBUG
+#endif
+#endif
+
+
+extern int WINAPI hes_error( void );
+DNS_STATUS doquery(const char* queryname, struct hostent* host);
+
+/*
+       query the dns name space for a host given the host name
+       \param[in]      name Pointer to the null-terminated name of the host to resolve. It can be a fully qualified host name such as x.mit.edu
+                               or it can be a simple host name such as x. If it is a simple host name, the default domain name is
+                               appended to do the search.
+       \retval         a pointer to the structure hostent. a structure allocated by the library. The hostent structure contains
+                               the results of a successful search for the host specified in the name parameter. The caller must never
+                               attempt to modify this structure or to free any of its components. Furthermore, only one copy of this
+                               structure is allocated per call per thread, so the application should copy any information it needs before
+                               issuing another rgethostbyname.
+                               NULL if the search has failed
+
+*/
+struct hostent *
+WINAPI
+rgethostbyname(char *name)
+{
+    struct hostent* host;
+    DNS_STATUS status;
+    const char *cp;
+    char queryname[DNS_MAX_NAME_BUFFER_LENGTH ];
+#ifdef DEBUG
+    char debstr[80];
+#endif
+    char** domain;
+    struct in_addr host_addr;
+
+    host = (struct hostent*)(TlsGetValue(dwGhnIndex));
+    if (host == NULL) {
+       LPVOID lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct hostent));
+       if (lpvData != NULL) {
+           TlsSetValue(dwGhnIndex, lpvData);
+           host = (struct hostent*)lpvData;
+       } else
+           return NULL;
+    }
+
+    if (host->h_name == NULL)
+       host->h_name = LocalAlloc(LPTR, DNS_MAX_LABEL_BUFFER_LENGTH);
+    if (host->h_aliases == NULL)
+       host->h_aliases = LocalAlloc(LPTR, 1*sizeof(LPSTR));
+    if (host->h_addr_list == NULL)
+    {
+       host->h_addr_list = LocalAlloc(LPTR, 2*sizeof(LPSTR));
+       host->h_addr_list[0] = LocalAlloc(LPTR, DNS_MAX_LABEL_BUFFER_LENGTH);
+    }
+
+
+    /*
+     * disallow names consisting only of digits/dots, unless
+     * they end in a dot.
+     */
+    if (isdigit(name[0])) {
+        for (cp = name;; ++cp) {
+            if (!*cp) {
+                if (*--cp == '.')
+                    break;
+                /*
+                 * All-numeric, no dot at the end.
+                 * Fake up a hostent as if we'd actually
+                 * done a lookup.
+                 */
+                if (!inet_aton(name, &host_addr)) {
+                    return((struct hostent *) NULL);
+                }
+                strcpy(host->h_name, name);
+                host->h_aliases[0] = NULL;
+                host->h_addrtype = AF_INET;
+                host->h_length = sizeof(u_long);
+                memcpy(host->h_addr_list[0], &host_addr, sizeof(host_addr));
+                               host->h_addr_list[1] = NULL;
+                return (host);
+            }
+            if (!isdigit(*cp) && *cp != '.')
+                break;
+        }
+    }
+
+    strcpy(queryname, name);
+
+    if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+        return NULL;
+    if (strchr(name, '.') == NULL)
+    {
+       if (_res.options & RES_DEFNAMES)
+       {
+           for (domain = _res.dnsrch; *domain; domain++) {
+               strcpy(queryname, name);
+               strcat(queryname, ".");
+               strcat(queryname, *domain);
+               status = doquery(queryname, host);
+               if (status == 0)
+                   break;
+           }
+       }
+    }
+    else {
+       status = doquery(queryname, host);
+    }
+
+    if (status) {
+#ifdef DEBUG
+       if (_res.options & RES_DEBUG)
+       {
+           wsprintf(debstr, "res_query failed\n");
+           OutputDebugString(debstr);
+       }
+#endif
+        return  NULL;
+    }
+    return host;
+}
+
+
+/*
+       an internal function used by rgethostbyname that does the actual DnsQuery call and populates the hostent
+       structure.
+
+       \param[in]      Name of the owner of the record set being queried
+       \param[in, out] populated hostent structure
+
+       \retval         DNS_STATUS value returned by DnsQuery
+
+*/
+DNS_STATUS doquery(const char* queryname, struct hostent* host)
+{
+    DNS_STATUS status;
+    PDNS_RECORD pDnsRecord, pDnsIter;
+    DNS_FREE_TYPE freetype ;
+    struct in_addr host_addr;
+    char querynamecp[DNS_MAX_NAME_BUFFER_LENGTH];
+    size_t len;
+
+    freetype =  DnsFreeRecordListDeep;
+    strcpy(querynamecp, queryname);
+    status = DnsQuery_A(queryname,          //pointer to OwnerName
+                       DNS_TYPE_A,         //Type of the record to be queried
+                        DNS_QUERY_STANDARD,
+                        NULL,               //contains DNS server IP address
+                        &pDnsRecord,        //Resource record comprising the response
+                        NULL);              //reserved for future use
+
+    if (status)
+       return status;
+
+    /* If the query name includes a trailing separator in order to prevent
+     * a local domain search, remove the separator during the file name
+     * comparisons. */
+    len = strlen(querynamecp);
+    if (querynamecp[len-1] == '.')
+       querynamecp[len-1] = '\0';
+
+    for (pDnsIter = pDnsRecord; pDnsIter; pDnsIter=pDnsIter->pNext) {
+       /* if we get an A record, keep it */
+       if (pDnsIter->wType == DNS_TYPE_A && stricmp(querynamecp, pDnsIter->pName)==0)
+           break;
+
+       /* if we get a CNAME, look for a corresponding A record */
+       if (pDnsIter->wType == DNS_TYPE_CNAME && stricmp(queryname, pDnsIter->pName)==0) {
+           strcpy(querynamecp, pDnsIter->Data.CNAME.pNameHost);
+       }
+    }
+    if (pDnsIter == NULL)
+       return DNS_ERROR_RCODE_NAME_ERROR;
+
+    strcpy(host->h_name, pDnsIter->pName);
+    host->h_addrtype = AF_INET;
+    host->h_length = sizeof(u_long);
+    host->h_aliases[0] = NULL;
+    host_addr.S_un.S_addr = (pDnsIter->Data.A.IpAddress);
+    memcpy(host->h_addr_list[0], (char*)&host_addr, sizeof(pDnsIter->Data.A.IpAddress));
+    host->h_addr_list[1] = NULL;
+    DnsRecordListFree(pDnsRecord, freetype);
+
+    return 0;
+}
+
+
+/*
+       retrieves the host information corresponding to a network address in the DNS database
+       \param[in]      addr Pointer to an address in network byte order
+       \param[in]      len  Length of the address, in bytes
+       \param[in]  type Type of the address, such as the AF_INET address family type (defined as TCP,
+                               UDP, and other associated Internet protocols). Address family types and their corresponding
+                               values are defined in the Winsock2.h header file.
+       \retval         returns a pointer to the hostent structure that contains the name and address corresponding
+                               to the given network address. The structure is allocated by the library.  The caller must never
+                               attempt to modify this structure or to free any of its components. Furthermore, only one copy of this
+                               structure is allocated per call per thread, so the application should copy any information it needs before
+                               issuing another rgethostbyaddr.
+                               NULL if the search has failed
+
+*/
+
+struct hostent *
+WINAPI
+rgethostbyaddr(const char *addr, int len, int type)
+{
+    DNS_STATUS status;
+    struct hostent* host;
+#ifdef DEBUG
+    char debstr[80];
+#endif
+
+    PDNS_RECORD pDnsRecord;
+    DNS_FREE_TYPE freetype ;
+    char qbuf[BUFSIZ];
+
+    if (type != AF_INET)
+        return ((struct hostent *) NULL);
+
+    wsprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+         ((unsigned)addr[3] & 0xff),
+         ((unsigned)addr[2] & 0xff),
+         ((unsigned)addr[1] & 0xff),
+         ((unsigned)addr[0] & 0xff));
+
+
+    freetype =  DnsFreeRecordListDeep;
+
+
+    status = DnsQuery_A(qbuf,                 //pointer to OwnerName
+                        DNS_TYPE_PTR,         //Type of the record to be queried
+                        DNS_QUERY_STANDARD,
+                        NULL,                   //contains DNS server IP address
+                        &pDnsRecord,                //Resource record comprising the response
+                        NULL);                     //reserved for future use
+
+    if (status) {
+#ifdef DEBUG
+        if (_res.options & RES_DEBUG)
+        {
+            wsprintf(debstr, "res_query failed\n");
+            OutputDebugString(debstr);
+        }
+#endif
+
+        return  NULL;
+    }
+
+    host = (struct hostent*)(TlsGetValue(dwGhaIndex));
+    if (host == NULL) {
+       LPVOID lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct hostent));
+       if (lpvData != NULL) {
+           TlsSetValue(dwGhaIndex, lpvData);
+           host = (struct hostent*)lpvData;
+       } else
+           return NULL;
+    }
+
+    if (host->h_name == NULL)
+       host->h_name = LocalAlloc(LPTR, DNS_MAX_LABEL_BUFFER_LENGTH);
+    if (host->h_aliases == NULL)
+       host->h_aliases = LocalAlloc(LPTR, 1*sizeof(LPSTR));
+    if (host->h_addr_list == NULL)
+    {
+       host->h_addr_list = LocalAlloc(LPTR, 2*sizeof(LPSTR));
+       host->h_addr_list[0] = LocalAlloc(LPTR, DNS_MAX_LABEL_BUFFER_LENGTH);
+    }
+
+    strcpy(host->h_name, pDnsRecord->Data.Ptr.pNameHost);
+    host->h_addrtype = type;
+    host->h_length = len;
+    host->h_aliases[0] = NULL;
+    memcpy(host->h_addr_list[0], addr, sizeof(unsigned long));
+    host->h_addr_list[1] = NULL;
+    DnsRecordListFree(pDnsRecord, freetype);
+
+    return host;
+
+}
+
+
+/*
+
+  @doc MISC
+
+  @func LPSTR WINAPI | gethinfobyname | Given the name
+  of a host query the nameservers for the T_HINFO information
+  associated with the host. unsupported
+
+  @parm LPSTR | name | pointer to the name of the host that the query is about.
+
+  @rdesc NULL or a pointer to the T_HINFO.
+
+
+*/
+
+LPSTR
+WINAPI
+gethinfobyname(LPSTR name)
+{
+    return NULL;
+
+}
+
+
+/*
+
+  @func struct mxent  * WINAPI | getmxbyname | This
+  function will query the nameservers for the MX records associated
+  with the given hostname. Note that the return is a pointer to the
+  mxent structure so an application making this call can iterate
+  through the different records returned and can also reference the
+  preference information associated with each hostname returned. unsupported
+
+  @parm LPSTR | name | The name of the host for which we want MX records.
+
+  @rdesc NULL or a pointer to a mxent structure.
+
+ */
+
+struct mxent  *
+WINAPI
+getmxbyname(LPSTR name)
+{
+    return NULL;
+}
+
+
+/*
+
+  @func LPSTR WINAPI | getrecordbyname | This function
+  will query the nameservers about the given hostname for and DNS
+  record type that the application wishes to query. unsupported
+
+  @parm LPSTR | name | a pointer to the hostname
+
+  @parm int | rectype | a DNS record type, e.g. T_MX, T_HINFO, ...
+
+  @rdesc The return is NULL or a pointer to a string containing the
+  data returned. It is up to the calling application to parse the
+  string appropriately for the rectype queried.
+
+*/
+
+LPSTR
+WINAPI
+getrecordbyname(LPSTR name, int rectype)
+{
+    return NULL;
+}
+
+
+/*
+
+  @func DWORD WINAPI | rrhost | This function emulates the
+  rhost function that was part of Excelan / Novell's LAN WorkPlace TCP/IP API.
+  Given a pointer to an IP hostname it will return the IP address as a 32 bit
+  integer.
+
+
+  @parm LPSTR | lpHost | a pointer to the hostname.
+
+  @rdesc 0 or the IP address as a 32 bit integer.
+
+*/
+
+DWORD WINAPI rrhost( LPSTR lpHost )
+{
+    return (DWORD) 0;
+}
+
+
+/*
+       retrieves service information corresponding to a service name and protocol.
+
+       \param[in]      name Pointer to a null-terminated service name.
+       \param[in]  proto pointer to a null-terminated protocol name. getservbyname should match both
+                               the name and the proto.
+
+       \retval         a pointer to the servent structure containing the name(s) and service number that match the name and proto
+                               parameters. The structure is allocated by the library.  The caller must never
+                               attempt to modify this structure or to free any of its components. Furthermore, only one copy of this
+                               structure is allocated per call per thread, so the application should copy any information it needs before
+                               issuing another rgetservbyname.
+                               NULL if the search has failed
+
+*/
+
+struct servent  * WINAPI rgetservbyname(LPCSTR name, LPCSTR proto)
+{
+    struct servent  * WINAPI hes_getservbyname(LPCSTR name, LPCSTR proto);
+    struct servent  *tmpent;
+
+    tmpent = hes_getservbyname(name, proto);
+    return (!hes_error()) ? tmpent : getservbyname(name, proto);
+}
diff --git a/src/windows/wshelper/hesiod.c b/src/windows/wshelper/hesiod.c
new file mode 100644 (file)
index 0000000..c912f7d
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+  @doc HESIOD
+
+  @module hesiod.c |
+
+  This module contains the defintions for the exported functions:
+               hes_to_bind
+               hes_resolve
+               hes_error
+        hes_free
+  as well as the internal function hes_init. The hes_init function
+  is the one that determines what the Hesiod servers are for your
+  site and will parse the configuration files, if any are
+  present.
+
+  WSHelper DNS/Hesiod Library for WINSOCK
+
+*/
+
+/* This file is part of the Hesiod library.
+ *
+ * The BIND 4.8.1 implementation of T_TXT is incorrect; BIND 4.8.1 declares
+ * it as a NULL terminated string.  The RFC defines T_TXT to be a length
+ * byte followed by arbitrary changes.
+ *
+ * Because of this incorrect declaration in BIND 4.8.1, when this bug is fixed,
+ * T_TXT requests between machines running different versions of BIND will
+ * not be compatible (nor is there any way of adding compatibility).
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.  See the
+ * file <mit-copyright.h> for copying and distribution information.
+ */
+
+#define index(str, c) strchr(str,c)
+#include <stdio.h>
+#include <errno.h>
+
+#include <windows.h>
+#include <winsock.h>
+#include <string.h>
+#include <hesiod.h>
+#include <resolv.h>
+#include <windns.h>
+
+#include "resource.h"
+
+
+#define USE_HS_QUERY   /* undefine this if your higher-level name servers */
+                       /* don't know class HS */
+
+char HesConfigFile[_MAX_PATH];
+static char Hes_LHS[256];
+static char Hes_RHS[256];
+static int Hes_Errno = HES_ER_UNINIT;
+
+extern  DWORD dwHesIndex;
+
+
+
+/*
+
+  @func int | hes_init |
+
+  This function is not exported.  It takes no arguments. However it is
+  important to understand how this works. It sets the global variables
+  Hes_LHS and Hes_RHS which are used to form the Hesiod
+  queries. Understanding how this works and setting up the correct
+  configuration will determine if the Hesiod queries will work at your
+  site. Settings can be configured by makgin source code changes and
+  rebuilding the DLL, editing resources in the DLL, using a
+  configuration file, or setting an environment variable.
+
+  The function first tries to open the HesConfigFile and set the
+  Hes_RHS and Hes_LHS variables from this. If there is no config file
+  then the function tries to load a string resource from the DLL to
+  set the LHS and RHS. If the string resources cannot be loaded then
+  the LHS and RHS will be set by the values of DEF_LHS and DEF_RHS,
+  these are defined in hesiod.h. Note that the string resources are by
+  default set to these same values since the RC files include hesiod.h
+
+  Finally if the user sets the environment variable HES_DOMAIN the RHS
+  will be overridden by the value of the HES_DOMAIN value.
+
+  Note that LoadString requires us to first find the module handle of
+  the DLL. We have to use the internal module name as defined in the
+  DEF file. If you change the library name within the DEF file you
+  also need to change the appropriate string in hesiod.c
+
+*/
+int hes_init( void )
+{
+    register FILE *fp;
+    register char  *key;
+    register char  *cp;
+    char buf[MAXDNAME+7];
+    HMODULE hModWSHelp;
+
+
+    Hes_Errno = HES_ER_UNINIT;
+    Hes_LHS[0] = '\0';
+    Hes_RHS[0] = '\0';
+
+    // Note: these must match the DEF file entries
+#if defined(_WIN64)
+       hModWSHelp = GetModuleHandle( "WSHELP64" );
+#else
+       hModWSHelp = GetModuleHandle( "WSHELP32" );
+#endif
+
+    if(!LoadString( hModWSHelp, IDS_DEF_HES_CONFIG_FILE,
+                    HesConfigFile, sizeof(HesConfigFile) )){
+        strcpy( HesConfigFile, HESIOD_CONF);
+    }
+
+    if ((fp = fopen(HesConfigFile, "r")) == NULL) {
+        /* use defaults compiled in */
+        /* no file or no access uses defaults */
+        /* but poorly formed file returns error */
+
+        if(!LoadString( hModWSHelp, IDS_DEF_HES_RHS, Hes_RHS, sizeof(Hes_RHS) )){
+            strcpy( Hes_RHS, DEF_RHS);
+        }
+
+        if(!LoadString( hModWSHelp, IDS_DEF_HES_LHS, Hes_LHS, sizeof(Hes_LHS) )){
+            strcpy( Hes_LHS, DEF_LHS);
+        }
+    } else {
+        while(fgets((LPSTR) buf, MAXDNAME+7, fp) != NULL) {
+            cp = (LPSTR) buf;
+            if (*cp == '#' || *cp == '\n'){
+                continue;
+            }
+            while(*cp == ' ' || *cp == '\t'){
+                cp++;
+            }
+            key = cp;
+            while(*cp != ' ' && *cp != '\t' && *cp != '='){
+                cp++;
+            }
+            *cp++ = '\0';
+            if (strcmp(key, "lhs") == 0){
+                strncpy(&Hes_LHS[0], cp, (strlen(cp)-1));
+            } else if (strcmp(key, "rhs") == 0){
+                strncpy(&Hes_RHS[0], cp, (strlen(cp)-1));
+            } else {
+                continue;
+            }
+            while(*cp == ' ' || *cp == '\t' || *cp == '='){
+                cp++;
+            }
+            if (*cp != '.') {
+                Hes_Errno = HES_ER_CONFIG;
+                fclose(fp);
+                return(Hes_Errno);
+            }
+            // len = strlen(cp);
+            // *cpp = calloc((unsigned int) len, sizeof(char));
+            // (void) strncpy(*cpp, cp, len-1);
+        }
+        fclose(fp);
+    }
+    /* see if the RHS is overridden by environment variable */
+    if ((cp = getenv("HES_DOMAIN")) != NULL){
+        // Hes_RHS = strcpy(malloc(strlen(cp)+1),cp);
+        strcpy(Hes_RHS,cp);
+    }
+    /* the LHS may be null, the RHS must not be null */
+    if (Hes_RHS == NULL)
+        Hes_Errno = HES_ER_CONFIG;
+    else
+        Hes_Errno = HES_ER_OK;
+    return(Hes_Errno);
+}
+
+
+/*
+  hes_to_bind function use the LHS and RHS values and
+  binds them with the parameters so that a well formed DNS query may
+  be performed.
+
+  \param[in]   HesiodName              The Hesiod name such as a username or service name
+  \param[in]   HesiodNameType  The Hesiod name type such as pobox, passwd, or sloc
+
+  \retval              Returns NULL if there was an error. Otherwise the pointer to a string containing a valid query is returned.
+
+*/
+char *
+WINAPI
+hes_to_bind(LPSTR HesiodName,
+            LPSTR HesiodNameType)
+{
+    register char *cp, **cpp;
+    char* bindname;
+    LPVOID lpvData;
+    char *RHS;
+
+    cp = NULL;
+    cpp = NULL;
+
+    bindname = (LPSTR)(TlsGetValue(dwHesIndex));
+    if (bindname == NULL)
+    {
+        lpvData = LocalAlloc(LPTR, DNS_MAX_NAME_BUFFER_LENGTH);
+        if (lpvData != NULL)
+        {
+            TlsSetValue(dwHesIndex, lpvData);
+            bindname = (LPSTR)lpvData;
+        }
+        else
+            return NULL;
+    }
+    if (Hes_Errno == HES_ER_UNINIT || Hes_Errno == HES_ER_CONFIG)
+        (void) hes_init();
+    if (Hes_Errno == HES_ER_CONFIG)
+       return(NULL);
+    if (cp = index(HesiodName,'@')) {
+        if (index(++cp,'.'))
+            RHS = cp;
+        else
+            if (cpp = hes_resolve(cp, "rhs-extension"))
+                RHS = *cpp;
+            else {
+                Hes_Errno = HES_ER_NOTFOUND;
+                return(NULL);
+            }
+        (void) strcpy(bindname,HesiodName);
+        (*index(bindname,'@')) = '\0';
+    } else {
+        RHS = Hes_RHS;
+        (void) strcpy(bindname, HesiodName);
+    }
+    (void) strcat(bindname, ".");
+    (void) strcat(bindname, HesiodNameType);
+    if (Hes_LHS) {
+        if (Hes_LHS[0] != '.')
+            (void) strcat(bindname,".");
+        (void) strcat(bindname, Hes_LHS);
+    }
+    if (RHS[0] != '.')
+        (void) strcat(bindname,".");
+    (void) strcat(bindname, RHS);
+
+    if(cpp != NULL )
+        hes_free(cpp);
+
+    return(bindname);
+}
+
+
+/*
+       This function calls hes_to_bind to form a valid hesiod query, then queries the dns database.
+       defined in hesiod.c
+
+       \param[in]      HesiodName              The Hesiod name such as a username or service name
+       \param[in]      HesiodNameType  The Hesiod name type such as pobox, passwd, or sloc
+
+       \retval         returns a NULL terminated vector of strings (a la argv),
+                               one for each resource record containing Hesiod data, or NULL if
+                               there is any error. If there is an error call hes_error() to get
+                               further information. You will need to call hes_free to free the result
+
+*/
+char **
+WINAPI
+hes_resolve(LPSTR HesiodName, LPSTR HesiodNameType)
+{
+    register char  *cp;
+    LPSTR* retvec;
+    DNS_STATUS status;
+
+    PDNS_RECORD pDnsRecord;
+    PDNS_RECORD pR;
+    DNS_FREE_TYPE freetype ;
+    int i = 0;
+    freetype =  DnsFreeRecordListDeep;
+
+
+    cp = hes_to_bind(HesiodName, HesiodNameType);
+    if (cp == NULL) return(NULL);
+    errno = 0;
+
+
+    status = DnsQuery_A(cp,                 //pointer to OwnerName
+                        DNS_TYPE_TEXT,         //Type of the record to be queried
+                        DNS_QUERY_STANDARD,     // Bypasses the resolver cache on the lookup.
+                        NULL,                   //contains DNS server IP address
+                        &pDnsRecord,                //Resource record comprising the response
+                        NULL);                     //reserved for future use
+
+    if (status) {
+        errno = status;
+        Hes_Errno = HES_ER_NOTFOUND;
+        return  NULL;
+    }
+
+    pR = pDnsRecord;
+    while (pR)
+    {
+        if (pR->wType == DNS_TYPE_TEXT)
+            i++;
+        pR = pR->pNext;
+    }
+    i++;
+    retvec = LocalAlloc(LPTR, i*sizeof(LPSTR));
+    pR = pDnsRecord;
+    i = 0;
+    while (pR)
+    {
+        if (pR->wType == DNS_TYPE_TEXT){
+            SIZE_T l = strlen(((pR->Data).Txt.pStringArray)[0]);
+            retvec[i] = LocalAlloc(LPTR, l+1);
+            strcpy(retvec[i], ((pR->Data).Txt.pStringArray)[0]);
+            i++;
+        }
+        pR = pR->pNext;
+    }
+    retvec[i] = NULL;
+    DnsRecordListFree(pDnsRecord, freetype);
+    return retvec;
+
+}
+
+
+/*
+       The  function  hes_error may be called to determine the
+       source of the error.  It does not take an argument.
+
+       \retval         return one of the HES_ER_* codes defined in hesiod.h.
+*/
+
+int
+WINAPI
+hes_error(void)
+{
+    return(Hes_Errno);
+}
+
+
+/*
+
+       The function hes_free should be called to free up memeory returned by
+       hes_resolve
+
+       \param[in]      hesinfo         a NULL terminiated array of strings returned by hes_resolve
+
+
+*/
+void
+WINAPI
+hes_free(LPSTR* info)
+{
+    int i= 0;
+    for (; info[i]; i++)
+    {
+        LocalFree(info[i]);
+    }
+    LocalFree(info);
+}
\ No newline at end of file
diff --git a/src/windows/wshelper/hesmailh.c b/src/windows/wshelper/hesmailh.c
new file mode 100644 (file)
index 0000000..32791e8
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *     @doc HESIOD
+ *
+ * @module hesmailh.c |
+ *
+ * This file contains hes_postoffice, which retrieves post-office information
+ * for a user.
+ *
+ *  For copying and distribution information, see the file
+ *  <lt> mit-copyright.h <gt>
+ *
+ *  Original version by Steve Dyer, IBM/Project Athena.
+ *
+ *     WSHelper DNS/Hesiod Library for WINSOCK
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h> /*s*/
+
+#include <hesiod.h>
+
+
+#define LINESIZE 80
+
+extern DWORD dwHesMailIndex;
+
+
+/*
+       This call is used to obtain a user's type of mail account and the location of that
+       account. E.g. POP PO10.MIT.EDU or IMAP IMAP-TEST.MIT.EDU
+
+       defined in hesmailh.c
+
+       \param[in]      user    The username to be used when querying for the Hesiod Name Type POBOX.
+
+       \retval                         NULL if there was an error or if there was no entry for the
+                                               username. Otherwise a pointer to a hes_postoffice structure is
+                                               returned. The caller must never attempt to modify this structure or to free
+                                               any of its components. Furthermore, only one copy of this structure is allocated per call per thread, so the application should copy any information it needs before
+                                               issuing another getmailhost call
+
+*/
+struct hes_postoffice  *
+WINAPI
+hes_getmailhost(LPSTR user)
+{
+    struct hes_postoffice* ret;
+    char linebuf[LINESIZE];
+    char *p, *tmp;
+    char **cp;
+
+
+    cp = hes_resolve(user, "pobox");
+    if (cp == NULL) return(NULL);
+
+    ret = (struct hes_postoffice*)(TlsGetValue(dwHesMailIndex));
+    if (ret == NULL) {
+       LPVOID lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct hes_postoffice));
+       if (lpvData != NULL) {
+           TlsSetValue(dwHesMailIndex, lpvData);
+           ret = (struct hes_postoffice*)lpvData;
+       } else
+           return NULL;
+    }
+    if (!ret->po_type)
+        ret->po_type = LocalAlloc(LPTR, LINESIZE);
+    if (!ret->po_host)
+        ret->po_host = LocalAlloc(LPTR, LINESIZE);
+    if (!ret->po_name)
+        ret->po_name = LocalAlloc(LPTR, LINESIZE);
+    strcpy(linebuf, *cp);
+
+    p = linebuf;
+    tmp = linebuf;
+    while(!isspace(*p)) p++;
+    *p++ = '\0';
+    strcpy(ret->po_type, tmp);
+    tmp = p;
+    while(!isspace(*p)) p++;
+    *p++ = '\0';
+    strcpy(ret->po_host, tmp);
+    strcpy(ret->po_name, p);
+    if (cp)
+        hes_free(cp);
+    return(ret);
+}
diff --git a/src/windows/wshelper/hespwnam.c b/src/windows/wshelper/hespwnam.c
new file mode 100644 (file)
index 0000000..55ddf01
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *     @doc HESIOD
+ *
+ * @module hespwnam.c |
+ *
+ * This file contains hes_getpwnam, for retrieving passwd information about
+ * a user.
+ *
+ * For copying and distribution information, see the file
+ * <lt> mit-copyright.h <gt>
+ *
+ * Original version by Steve Dyer, IBM/Project Athena.
+ *
+ *       WSHelper DNS/Hesiod Library for WINSOCK
+ *
+ *
+ */
+
+/* This file contains hes_getpwnam, for retrieving passwd information about
+ * a user.
+ *
+ * For copying and distribution information, see the file <mit-copyright.h>
+ *
+ * Original version by Steve Dyer, IBM/Project Athena.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h> /*s*/
+
+#include <stdlib.h>
+
+#include <windows.h>
+#include <hesiod.h>
+
+#include "pwd.h"
+
+extern DWORD dwHesPwNamIndex;
+extern DWORD dwHesPwUidIndex;
+
+#define MAX_PW_BUFFER_LENGTH  64
+
+static char *
+_NextPWField(char *ptr);
+
+struct passwd *  GetPasswdStruct(struct passwd* pw, char* buf);
+
+
+
+
+/*
+       Given a UID this function will return the pwd information, eg username, uid,
+       gid, fullname, office location, phone number, home directory, and default shell
+
+       defined in hespwnam.c
+       \param  uid                     The user ID
+       \retval                         NULL if there was an error or a pointer to the passwd structure. The caller must
+                                               never attempt to modify this structure or to free any of its components.
+                                               Furthermore, only one copy of this structure is allocated per call per thread, so the application should copy any information it needs before
+                                               issuing another hes_getpwuid call
+*/
+struct passwd *
+WINAPI
+hes_getpwuid(int uid)
+{
+    char **pp;
+    struct passwd* pw = NULL;
+    char buf[256];
+
+    char nam[8];
+    sprintf(nam, "%d", uid);
+
+    pp = hes_resolve(nam, "uid");
+    if (pp == NULL || *pp == NULL)
+        return(NULL);
+
+    pw = (struct passwd*)(TlsGetValue(dwHesPwUidIndex));
+    if (pw == NULL) {
+       LPVOID lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct passwd));
+       if (lpvData != NULL) {
+           TlsSetValue(dwHesPwUidIndex, lpvData);
+           pw = (struct passwd*)lpvData;
+       } else
+           return NULL;
+    }
+
+    strcpy(buf, pp[0]);
+    hes_free(pp);
+    return GetPasswdStruct(pw, buf);
+}
+
+
+/*
+       Given a username this function will return the pwd information, eg
+       username, uid, gid, fullname, office location, phone number, home
+       directory, and default shell
+
+       defined in hespwnam.c
+
+       \param  nam                     a pointer to the username
+
+       \retval                         NULL if there was an error or a pointer to the passwd structure. The caller must
+                                               never attempt to modify this structure or to free any of its components.
+                                               Furthermore, only one copy of this structure is allocated per call per thread, so the application should copy any information it needs before
+                                               issuing another hes_getpwnam call
+
+*/
+struct passwd *
+WINAPI
+hes_getpwnam(char *nam)
+{
+
+   char **pp;
+   struct passwd* pw = NULL;
+   char buf[256];
+
+    pp = hes_resolve(nam, "passwd");
+    if (pp == NULL || *pp == NULL)
+        return(NULL);
+
+    pw = (struct passwd*)(TlsGetValue(dwHesPwNamIndex));
+    if (pw == NULL) {
+       LPVOID lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct passwd));
+       if (lpvData != NULL) {
+           TlsSetValue(dwHesPwNamIndex, lpvData);
+           pw = (struct passwd*)lpvData;
+       } else
+           return NULL;
+    }
+
+    strcpy(buf, pp[0]);
+    hes_free(pp);
+    return GetPasswdStruct(pw, buf);
+}
+
+
+struct passwd*  GetPasswdStruct(struct passwd* pw, char* buf)
+{
+    char* temp;
+    char* p;
+
+    if (pw->pw_name == NULL)
+       pw->pw_name = LocalAlloc(LPTR, MAX_PW_BUFFER_LENGTH);
+    if (pw->pw_passwd == NULL)
+       pw->pw_passwd = LocalAlloc(LPTR, MAX_PW_BUFFER_LENGTH);
+    if (pw->pw_comment == NULL)
+       pw->pw_comment = LocalAlloc(LPTR, MAX_PW_BUFFER_LENGTH);
+    if (pw->pw_gecos == NULL)
+       pw->pw_gecos = LocalAlloc(LPTR, MAX_PW_BUFFER_LENGTH);
+    if (pw->pw_dir == NULL)
+       pw->pw_dir = LocalAlloc(LPTR, MAX_PW_BUFFER_LENGTH);
+    if (pw->pw_shell == NULL)
+       pw->pw_shell = LocalAlloc(LPTR, MAX_PW_BUFFER_LENGTH);
+    /* choose only the first response (only 1 expected) */
+    p = buf;
+    temp = p;
+    p = _NextPWField(p);
+    strcpy(pw->pw_name, temp);
+    temp = p;
+    p = _NextPWField(p);
+    strcpy(pw->pw_passwd, temp);
+    pw->pw_uid = atoi(p);
+    p = _NextPWField(p);
+    pw->pw_gid = atoi(p);
+    pw->pw_quota = 0;
+    strcpy(pw->pw_comment, "");
+    p = _NextPWField(p);
+    temp = p;
+    p = _NextPWField(p);
+    strcpy(pw->pw_gecos, temp);
+    temp = p;
+    p = _NextPWField(p);
+    strcpy(pw->pw_dir,  temp);
+    temp = p;
+    while (*p && *p != '\n')
+        p++;
+    *p = '\0';
+    strcpy(pw->pw_shell, temp);
+    return pw;
+
+
+}
+
+/* Move the pointer forward to the next colon-separated field in the
+ * password entry.
+ */
+
+static char *
+_NextPWField(char *ptr)
+{
+    while (*ptr && *ptr != '\n' && *ptr != ':')
+        ptr++;
+    if (*ptr)
+        *ptr++ = '\0';
+    return(ptr);
+}
diff --git a/src/windows/wshelper/hesservb.c b/src/windows/wshelper/hesservb.c
new file mode 100644 (file)
index 0000000..01db3a4
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *     @doc HESIOD
+ *
+ * @module hesservb.c |
+ *
+ *
+ *       Contains the definition for hes_getservbyname,
+ *
+ *       WSHelper DNS/Hesiod Library for WINSOCK
+ *
+ */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservbyname.c    5.3 (Berkeley) 5/19/86";
+#endif /* LIBC_SCCS and not lint */
+
+#include <hesiod.h>
+#include <windows.h>
+#include <winsock.h>
+#include <windns.h>
+
+#include <string.h>
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define cistrcmp stricmp
+
+#define LISTSIZE 15
+
+
+/*
+       This function will query a Hesiod server for a servent structure given
+       a service name and protocol. This is a replacement for the Winsock
+       getservbyname function which normally just uses a local services
+       file. This allows a site to use a centralized database for adding new
+       services.
+
+       defined in hesservb.c
+
+       \param[in]      name    pointer to the official name of the service, eg "POP3".
+       \param[in]      proto   pointer to the protocol to use when contacting the service, e.g. "TCP"
+
+       \retval                         NULL if there was an error or a pointer to a servent structure. The caller must
+                                               never attempt to modify this structure or to free any of its components.
+                                               Furthermore, only one copy of this structure is allocated per call per thread, so the application should copy any information it needs before
+                                               issuing another hes_getservbyname call
+
+*/
+
+extern DWORD dwHesServIndex;
+struct servent *
+WINAPI
+hes_getservbyname(char *name, char *proto)
+{
+    struct servent *p;
+    register char **cp;
+    register char** hesinfo;
+    register int i = 0;
+
+    char buf[DNS_MAX_NAME_BUFFER_LENGTH];
+    char* l;
+
+    hesinfo = hes_resolve(name, "service");
+    cp = hesinfo;
+    if (cp == NULL)
+       return(NULL);
+    p = (struct servent*)(TlsGetValue(dwHesServIndex));
+    if (p == NULL) {
+       LPVOID lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct servent));
+       if (lpvData != NULL) {
+           TlsSetValue(dwHesServIndex, lpvData);
+           p = (struct servent*)lpvData;
+       } else
+           return NULL;
+    }
+    if (!p->s_name)
+        p->s_name = LocalAlloc(LPTR, DNS_MAX_LABEL_BUFFER_LENGTH);
+    if (!p->s_proto)
+        p->s_proto = LocalAlloc(LPTR, DNS_MAX_LABEL_BUFFER_LENGTH);
+    if (!p->s_aliases)
+        p->s_aliases = LocalAlloc(LPTR, LISTSIZE*sizeof(LPSTR));
+
+    for (;*cp; cp++) {
+       register char *servicename, *protoname, *port;
+        strcpy(buf, *cp);
+        l = buf;
+       while(*l && (*l == ' ' || *l == '\t')) l++;
+       servicename = l;
+       while(*l && *l != ' ' && *l != '\t' && *l != ';') l++;
+       if (*l == '\0') continue; /* malformed entry */
+       *l++ = '\0';
+       while(*l && (*l == ' ' || *l == '\t')) l++;
+       protoname = l;
+       while(*l && *l != ' ' && *l != ';') l++;
+       if (*l == '\0') continue; /* malformed entry */
+       *l++ = '\0';
+       if (cistrcmp(proto, protoname)) continue; /* wrong port */
+       while(*l && (*l == ' ' || *l == '\t' || *l == ';')) l++;
+       if (*l == '\0') continue; /* malformed entry */
+       port = l;
+       while(*l && (*l != ' ' && *l != '\t' && *l != ';')) l++;
+       if (*l) *l++ = '\0';
+       if (*l != '\0') {
+           do {
+               char* tmp = l;
+               while(*l && !isspace(*l)) l++;
+               if (*l) *l++ = 0;
+                if (p->s_aliases[i])
+                    p->s_aliases[i] = LocalAlloc(LPTR, strlen(tmp));
+                strcpy(p->s_aliases[i], tmp);
+                i++;
+           } while(*l);
+       }
+       p->s_aliases[i] = NULL;
+        for (; i<LISTSIZE; i++)
+        {
+            if (p->s_aliases[i]){
+                LocalFree(p->s_aliases[i]);
+                p->s_aliases[i] = NULL;
+            }
+        }
+       strcpy(p->s_name, servicename);
+       p->s_port = htons((u_short)atoi(port));
+       strcpy(p->s_proto, protoname);
+        if (hesinfo)
+            hes_free(hesinfo);
+       return (p);
+    }
+    return(NULL);
+}
diff --git a/src/windows/wshelper/inetaton.c b/src/windows/wshelper/inetaton.c
new file mode 100644 (file)
index 0000000..bc7bd09
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *
+ *     @doc RESOLVE
+ *
+ * @module inetaton.c  |
+ *
+ *      from the BIND 4.9.x inetaddr.c
+ *
+ *       Contains implementation of inet_aton
+
+ *       WSHelper DNS/Hesiod Library for WINSOCK
+ *
+ */
+
+/*
+ * Copyright (c) 1983, 1990 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_addr.c        5.11 (Berkeley) 12/9/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <windows.h>
+#include <winsock.h>
+#include <ctype.h>
+
+
+/*
+       converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the in_addr structure
+
+       \param[in]      cp Null-terminated character string representing a number expressed in the
+       Internet standard ".'' (dotted) notation.
+       \param[in, out] addr pointer to the in_addr structure. The s_addr memeber will be populated
+
+
+       \retval Returns 1 if the address is valid, 0 if not.
+
+ */
+unsigned long
+WINAPI
+inet_aton(register const char *cp, struct in_addr *addr)
+{
+    register u_long val, base;
+       ULONG_PTR n;
+    register char c;
+    u_long parts[4], *pp = parts;
+
+    for (;;) {
+        /*
+         * Collect number up to ``.''.
+         * Values are specified as for C:
+         * 0x=hex, 0=octal, other=decimal.
+         */
+        val = 0; base = 10;
+        if (*cp == '0') {
+            if (*++cp == 'x' || *cp == 'X')
+                base = 16, cp++;
+            else
+                base = 8;
+        }
+        while ((c = *cp) != '\0') {
+            if (isascii(c) && isdigit(c)) {
+                val = (val * base) + (c - '0');
+                cp++;
+                continue;
+            }
+            if (base == 16 && isascii(c) && isxdigit(c)) {
+                val = (val << 4) +
+                    (c + 10 - (islower(c) ? 'a' : 'A'));
+                cp++;
+                continue;
+            }
+            break;
+        }
+        if (*cp == '.') {
+            /*
+             * Internet format:
+             * a.b.c.d
+             * a.b.c   (with c treated as 16-bits)
+             * a.b     (with b treated as 24 bits)
+             */
+            if (pp >= parts + 3 || val > 0xff)
+                return (0);
+            *pp++ = val, cp++;
+        } else
+            break;
+    }
+    /*
+     * Check for trailing characters.
+     */
+    if (*cp && (!isascii(*cp) || !isspace(*cp)))
+        return (0);
+    /*
+     * Concoct the address according to
+     * the number of parts specified.
+     */
+    n = pp - parts + 1;
+    switch (n) {
+
+    case 1:                            /* a -- 32 bits */
+        break;
+
+    case 2:                            /* a.b -- 8.24 bits */
+        if (val > 0xffffff)
+            return (0);
+        val |= parts[0] << 24;
+        break;
+
+       case 3:                         /* a.b.c -- 8.8.16 bits */
+            if (val > 0xffff)
+                return (0);
+            val |= (parts[0] << 24) | (parts[1] << 16);
+            break;
+
+       case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
+            if (val > 0xff)
+                return (0);
+            val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+            break;
+    }
+    if (addr)
+        addr->s_addr = htonl(val);
+    return (1);
+}
diff --git a/src/windows/wshelper/pwd.h b/src/windows/wshelper/pwd.h
new file mode 100644 (file)
index 0000000..6954fd7
--- /dev/null
@@ -0,0 +1,15 @@
+/*     pwd.h   4.1     83/05/03        */
+
+struct passwd { /* see getpwent(3) */
+       char    *pw_name;
+       char    *pw_passwd;
+       int     pw_uid;
+       int     pw_gid;
+       int     pw_quota;
+       char    *pw_comment;
+       char    *pw_gecos;
+       char    *pw_dir;
+       char    *pw_shell;
+};
+
+struct passwd *getpwent(), *getpwuid(), *getpwnam();
diff --git a/src/windows/wshelper/res_comp.c b/src/windows/wshelper/res_comp.c
new file mode 100644 (file)
index 0000000..18e8a7c
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ *
+ *     @doc RESOLVE
+ *
+ * @module res_comp.c |
+ *
+ *       Contains the implementations for dn_comp and rdn_expand as well as
+ *       some other functions used internally by these two functions.
+ *
+ *       WSHelper DNS/Hesiod Library for WINSOCK
+ *
+ */
+
+/*
+ * Copyright (c) 1985 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_comp.c 6.22 (Berkeley) 3/19/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <windows.h>
+#include <winsock.h>
+#include <resolv.h>
+#include <stdio.h>
+
+
+static dn_find();
+
+/*
+       replacement for dn_expand called rdn_expand. Older versions of
+       the DLL used to this as dn_expand but this has caused some
+       conflict with more recent versions of the MSDEV
+       libraries. rdn_expand() expands the compressed domain name comp_dn to
+       a full domain name.  Expanded names are converted to upper case.
+
+       \param[in]      msg             msg is a pointer to the  beginning  of  the  message
+       \param[in]      eomorig
+       \param[in]                      comp_dn the compressed domain name.
+       \param[in, out]         expn_dn a pointer to the result buffer
+       \param[in]                      length  size of the result in expn_dn
+
+       \retval                         the size of compressed name is returned or -1 if there was an error.
+*/
+
+
+
+int WINAPI
+rdn_expand(const u_char *msg, const u_char *eomorig,
+                  const u_char *comp_dn, u_char *exp_dn, int length)
+{
+    register u_char *cp, *dn;
+    register int n, c;
+    u_char *eom;
+       INT_PTR len = -1;
+    int checked = 0;
+
+    dn = exp_dn;
+    cp = (u_char *)comp_dn;
+    eom = exp_dn + length;
+    /*
+     * fetch next label in domain name
+     */
+    while (n = *cp++) {
+        /*
+         * Check for indirection
+         */
+        switch (n & INDIR_MASK) {
+        case 0:
+            if (dn != exp_dn) {
+                if (dn >= eom)
+                    return (-1);
+                *dn++ = '.';
+            }
+            if (dn+n >= eom)
+                return (-1);
+            checked += n + 1;
+            while (--n >= 0) {
+                if ((c = *cp++) == '.') {
+                    if (dn + n + 2 >= eom)
+                        return (-1);
+                    *dn++ = '\\';
+                }
+                *dn++ = c;
+                if (cp >= eomorig)      /* out of range */
+                    return(-1);
+            }
+            break;
+
+        case INDIR_MASK:
+            if (len < 0)
+                len = cp - comp_dn + 1;
+            cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+            if (cp < msg || cp >= eomorig)  /* out of range */
+                return(-1);
+            checked += 2;
+            /*
+             * Check for loops in the compressed name;
+             * if we've looked at the whole message,
+             * there must be a loop.
+             */
+            if (checked >= eomorig - msg)
+                return (-1);
+            break;
+
+        default:
+            return (-1);                    /* flag error */
+        }
+    }
+    *dn = '\0';
+    if (len < 0)
+        len = cp - comp_dn;
+    return (int)(len);
+}
+
+
+/*
+       Compress domain name 'exp_dn' into 'comp_dn'
+       \param[in]      exp_dn  name to compress
+       \param[in, out] comp_dn         result of the compression
+       \paramp[in]     length                  the size of the array pointed to by 'comp_dn'.
+       \param[in, out] dnptrs          a list of pointers to previous compressed names. dnptrs[0]
+                                                               is a pointer to the beginning of the message. The list ends with NULL.
+       \param[in]      lastdnptr               a pointer to the end of the arrary pointed to by 'dnptrs'. Side effect
+                                                               is to update the list of pointers for labels inserted into the
+                                                               message as we compress the name. If 'dnptr' is NULL, we don't try to
+                                                               compress names. If 'lastdnptr' is NULL, we don't update the list.
+       \retval                                         Return the size of the compressed name or -1
+ */
+int WINAPI
+dn_comp(const u_char *exp_dn, u_char *comp_dn, int length,
+        u_char **dnptrs, u_char **lastdnptr)
+{
+    register u_char *cp, *dn;
+    register int c, l;
+    u_char **cpp, **lpp, *sp, *eob;
+    u_char *msg;
+
+    dn = (u_char *)exp_dn;
+    cp = comp_dn;
+    eob = cp + length;
+    if (dnptrs != NULL) {
+        if ((msg = *dnptrs++) != NULL) {
+            for (cpp = dnptrs; *cpp != NULL; cpp++)
+                ;
+            lpp = cpp;      /* end of list to search */
+        }
+    } else
+        msg = NULL;
+    for (c = *dn++; c != '\0'; ) {
+        /* look to see if we can use pointers */
+        if (msg != NULL) {
+            if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
+                if (cp+1 >= eob)
+                    return (-1);
+                *cp++ = (l >> 8) | INDIR_MASK;
+                *cp++ = l % 256;
+                return (int)(cp - comp_dn);
+            }
+            /* not found, save it */
+            if (lastdnptr != NULL && cpp < lastdnptr-1) {
+                *cpp++ = cp;
+                *cpp = NULL;
+            }
+        }
+        sp = cp++;      /* save ptr to length byte */
+        do {
+            if (c == '.') {
+                c = *dn++;
+                break;
+            }
+            if (c == '\\') {
+                if ((c = *dn++) == '\0')
+                    break;
+            }
+            if (cp >= eob) {
+                if (msg != NULL)
+                    *lpp = NULL;
+                return (-1);
+            }
+            *cp++ = c;
+        } while ((c = *dn++) != '\0');
+        /* catch trailing '.'s but not '..' */
+        if ((l =(int)( cp - sp - 1)) == 0 && c == '\0') {
+            cp--;
+            break;
+        }
+        if (l <= 0 || l > MAXLABEL) {
+            if (msg != NULL)
+                *lpp = NULL;
+            return (-1);
+        }
+        *sp = l;
+    }
+    if (cp >= eob) {
+        if (msg != NULL)
+            *lpp = NULL;
+        return (-1);
+    }
+    *cp++ = '\0';
+    return (int)(cp - comp_dn);
+}
+
+/*
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+__dn_skipname(const u_char *comp_dn, const u_char *eom)
+{
+    register u_char *cp;
+    register int n;
+
+    cp = (u_char *)comp_dn;
+    while (cp < eom && (n = *cp++)) {
+        /*
+         * check for indirection
+         */
+        switch (n & INDIR_MASK) {
+        case 0:         /* normal case, n == len */
+            cp += n;
+            continue;
+        default:        /* illegal type */
+            return (-1);
+        case INDIR_MASK:        /* indirection */
+            cp++;
+        }
+        break;
+    }
+    return (int)(cp - comp_dn);
+}
+
+/*
+ * Search for expanded name from a list of previously compressed names.
+ * Return the offset from msg if found or -1.
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
+ */
+static
+dn_find(u_char *exp_dn, u_char *msg, u_char **dnptrs, u_char **lastdnptr)
+{
+    register u_char *dn, *cp, **cpp;
+    register int n;
+    u_char *sp;
+
+    for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+        dn = exp_dn;
+        sp = cp = *cpp;
+        while (n = *cp++) {
+            /*
+             * check for indirection
+             */
+            switch (n & INDIR_MASK) {
+            case 0:         /* normal case, n == len */
+                while (--n >= 0) {
+                    if (*dn == '.')
+                        goto next;
+                    if (*dn == '\\')
+                        dn++;
+                    if (*dn++ != *cp++)
+                        goto next;
+                }
+                if ((n = *dn++) == '\0' && *cp == '\0')
+                    return (int)(sp - msg);
+                if (n == '.')
+                    continue;
+                goto next;
+
+            default:        /* illegal type */
+                return (-1);
+
+            case INDIR_MASK:        /* indirection */
+                cp = msg + (((n & 0x3f) << 8) | *cp);
+            }
+        }
+        if (*dn == '\0')
+            return (int)(sp - msg);
+    next:   ;
+    }
+    return (-1);
+}
+
+/*
+ * Routines to insert/extract short/long's. Must account for byte
+ * order and non-alignment problems. This code at least has the
+ * advantage of being portable.
+ *
+ * used by sendmail.
+ */
+
+u_short
+_getshort(u_char *msgp)
+{
+    register u_char *p = (u_char *) msgp;
+#ifdef vax
+    /*
+     * vax compiler doesn't put shorts in registers
+     */
+    register u_long u;
+#else
+    register u_short u;
+#endif
+
+    u = *p++ << 8;
+    return ((u_short)(u | *p));
+}
+
+u_long
+_getlong(u_char *msgp)
+{
+    register u_char *p = (u_char *) msgp;
+    register u_long u;
+
+    u = *p++; u <<= 8;
+    u |= *p++; u <<= 8;
+    u |= *p++; u <<= 8;
+    return (u | *p);
+}
+
+void
+#ifdef __STDC__
+__putshort(register u_short s, register u_char *msgp)
+#else
+__putshort(s, msgp)
+    register u_short s;
+    register u_char *msgp;
+#endif
+{
+    msgp[1] = LOBYTE(s);
+    msgp[0] = HIBYTE(s);
+}
+
+void
+__putlong(l, msgp)
+    register u_long l;
+    register u_char *msgp;
+{
+    msgp[3] = LOBYTE(LOWORD(l));
+    msgp[2] = HIBYTE(LOWORD(l));
+    msgp[1] = LOBYTE(HIWORD(l));
+    msgp[0] = HIBYTE(HIWORD(l));
+}
diff --git a/src/windows/wshelper/res_init.c b/src/windows/wshelper/res_init.c
new file mode 100644 (file)
index 0000000..bf3d97b
--- /dev/null
@@ -0,0 +1,814 @@
+/*
+ * @doc RESOLVE
+ *
+ * @module res_init.c |
+ *
+ * Contains the implementation for res_init, res_getopts, res_setopts
+ * and supplementary internal functions. If you are adding support for a
+ * new TCP/IP stack of resolver configuration information this is where
+ * it will go.
+ * @xref <f res_init> <f res_setopts> <f res_getopts> <f WhichOS> <f getRegKey>
+ *
+ * WSHelper DNS/Hesiod Library for WINSOCK
+ *
+ */
+
+/*-
+ * Copyright (c) 1985, 1989 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_init.c  6.15 (Berkeley) 2/24/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <windows.h>
+#include <winsock.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windns.h>   //DNS api's
+
+#include <shellapi.h>
+
+
+#include <mitwhich.h>
+
+#include "resource.h"
+
+char debstr[80];
+
+#define index strchr
+
+#ifndef MAKELONG
+#define MAKELONG(a, b)      ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16))
+#endif
+
+#define TCPIP_PATH "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
+#define HKEY_MIT_PRIVATE HKEY_CLASSES_ROOT
+#define WSH_MIT_PRIVATE_DOMAIN_SUBKEY TCPIP_PATH"\\Domain"
+#define WSH_MIT_PRIVATE_NAMESERVER_SUBKEY TCPIP_PATH"\\NameServer"
+
+DWORD WhichOS( DWORD *check);
+
+static int const getRegKeyEx(const HKEY key, const char *subkey, const char *value, char *buf, unsigned int len);
+
+int WINAPI wsh_getdomainname(char* name, int size);
+
+static HMODULE this_module();
+
+
+/*
+ * Resolver state default settings
+ */
+// @struct _res | a structure of this type holds the state information for the
+// resolver options
+struct state _res = {
+    RES_TIMEOUT,                    /* @field retransmition time interval */
+    4,                              /* @field number of times to retransmit */
+    RES_DEFAULT,                    /* @field options flags */
+    1,                              /* @field number of name servers */
+};
+
+#ifndef _MSC_VER
+
+#define _upcase(c) (((c) <= 'Z' && (c) >= 'A') ? (c) + 'a' - 'A' : (c))
+#define _chricmp(a, b) (_upcase(a) - _upcase(b))
+
+int
+#ifdef __cplusplus
+inline
+#endif
+_strnicmp( register const char *a, register const char *b, register size_t n)
+{
+    register int cmp = 0; /* equal */
+    while( n-- && !(cmp = _chricmp(*a, *b)) && (a++, *b++) /* *a == *b anyways */ );
+    return cmp;
+};
+
+#endif
+
+
+/*
+       This function retrieves the default domain name and search order. It will look to see if an
+       environment variable LOCALDOMAIN is defined. Otherwise, the domain associated with the local host
+       is used. Otherwise, it will try to find the domain name from the registry
+
+       \retval         The return value is 0 if the operation was successful.
+                               Otherwise the value -1 is returned.
+
+*/
+int
+WINAPI
+res_init()
+{
+    register char *cp, **pp;
+
+    register int n;
+
+    int haveenv = 0;   /* have an environment variable for local domain */
+    int havedomain = 0; /* 0 or 1 do we have a value for the domain */
+
+    LONG result1 = -1995;
+
+#define WSH_SPACES " \t,;="
+
+    _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+    _res.nsaddr.sin_family = AF_INET;
+    _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+    _res.nscount = 1;
+
+
+    /* Allow user to override the local domain definition */
+    if ((cp = getenv("LOCALDOMAIN")) != NULL) {
+        strncpy(_res.defdname, cp, sizeof(_res.defdname));
+        haveenv++;
+        havedomain++;
+    };
+
+    if (!havedomain) {
+        if (!wsh_getdomainname(_res.defdname, sizeof(_res.defdname)))
+            havedomain++;
+    }
+
+
+
+    if( 0 != havedomain){
+        // return early, we've done our job
+        /* find components of local domain that might be searched */
+
+            pp = _res.dnsrch;
+            *pp++ = _res.defdname;
+            for (cp = _res.defdname, n = 0; *cp; cp++)
+                if (*cp == '.')
+                    n++;
+            cp = _res.defdname;
+            for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
+                 n--) {
+                cp = index(cp, '.');
+                *pp++ = ++cp;
+            }
+            *pp++ = 0;
+    }
+
+   _res.options |= RES_INIT;
+        return(0);
+}
+
+
+/*
+ res_setopts -- unsupported
+*/
+
+void
+WINAPI
+res_setopts(long opts)
+{
+}
+
+
+
+/*
+       res_getopts -- unsupported
+*/
+
+long
+WINAPI
+res_getopts()
+{
+    return -1;
+}
+
+/* --------------------------------------------------------------------------*/
+/* Excerpt from IPTYPES.H */
+#define MAX_HOSTNAME_LEN                128 // arb.
+#define MAX_DOMAIN_NAME_LEN             128 // arb.
+#define MAX_SCOPE_ID_LEN                256 // arb.
+
+
+
+/*
+
+  @doc MISC
+
+  @func DWORD | WhichOS | This function will attempt to
+  determine which Operating System and subsystem is being used by the
+  application. It should function under Win16, Windows NT amd Windows
+  95 at least.  It does call WSAStartup() and WSACleanup(). This
+  function does have side effects on some global variables.  See the
+  comments below.
+
+  @parm DWORD *| check | a pointer to a DWORD, a value indicating
+  which operating system and/or subsystem is being used will be stored
+  in this parameter upon return.
+
+  @rdesc a NULL will indicate that we could not determine what OS is
+  being used. The high word contains:
+
+
+  @flag MS_OS_WIN     (1) | The application is running under Windows or WFWG
+  @flag        MS_OS_95      (2) | The application is running under Windows 95
+  @flag        MS_OS_NT      (3) | The application is running under Windows NT
+  @flag        MS_OS_2000    (4) | The application is running under Windows 2000
+  @flag        MS_OS_XP      (5) | The application is running under Windows XP
+  @flag        MS_OS_2003    (6) | The application is running under Windows 2003
+  @flag        MS_OS_NT_UNKNOWN (7) | The application is running under Windows NT family beyond 2003
+  @flag        MS_OS_UNKNOWN (0) | It looks like Windows but not any version that
+                            we know of.
+
+  <nl>these are defined in mitwhich.h<nl>
+
+The low word contains one of the following, which is derived from the winsock implementation: <nl>
+
+  @flag MS_NT_32 (1) | The MS 32 bit Winsock stack for NT is being used
+  @flag MS_NT_16 (2) | The MS 16 bit Winsock stack under NT is being used
+  @flag        MS_95_32 (3) | The MS 32 bit Winsock stack under 95 is being used
+  @flag        MS_95_16 (4) | The MS 16 bit Winsock stack under 95 is being used
+  @flag        NOVELL_LWP_16       (5)  | The Novell 16 Winsock stack is being used
+  @flag UNKNOWN_16_UNDER_32 (-2) | We don't know the stack.
+  @flag UNKNOWN_16_UNDER_16 (-3) | We don't know the stack.
+  @flag UNKNOWN_32_UNDER_32 (-4) | We don't know the stack.
+  @flag UNKNOWN_32_UNDER_16 (-5) | We don't know the stack.
+
+*/
+DWORD
+WhichOS(
+    DWORD *check
+    )
+{
+    WORD wVersionRequested;
+    WSADATA wsaData; // should be a global?
+    int err;
+
+    int checkStack = 0;
+    int checkOS = 0;
+    static DWORD dwCheck = 0xFFFFFFFF;
+
+    if ( dwCheck != 0xFFFFFFFF ) {
+        if ( check )
+            *check = dwCheck;
+        return dwCheck;
+    }
+
+    // first get the information from WSAStartup because it may give
+    // more consistent information than Microsoft APIs.
+
+    wVersionRequested = 0x0101;
+
+    err = WSAStartup( wVersionRequested, &wsaData );
+
+    if( err != 0 ){
+        MessageBox( NULL,
+                    "It looks like a useable winsock.dll\n"
+                    "could not be located by the wshelp*.dll\n"
+                    "Please check your system configuration.",
+                    "Problem in wshelper.dll", MB_OK );
+        check = 0;
+        return(0);
+    }
+
+    WSACleanup();
+
+    if( _res.options & RES_DEBUG ){
+        wsprintf( debstr, wsaData.szDescription );
+        OutputDebugString( debstr );
+    }
+
+    if( (0 == checkStack) && (0 == stricmp( wsaData.szDescription, NT_32 ))){
+        // OK we appear to be running under NT in the 32 bit subsystem
+        // so we must be a 32 bit application.
+        // This also implies that we can get the TCPIP parameters out
+        // of the NT registry.
+        checkStack = MS_NT_32;
+    }
+
+    if( (0 == checkStack) && (0 == stricmp( wsaData.szDescription, NT_16 ))){
+        // this implies we're running under NT in the 16 bit subsystem
+        // so we must be a 16 bit application
+        // This means we have to go through some strange gyrations to read the
+        // TCPIP parameters out of the NT 32 bit registry.
+        checkStack = MS_NT_16;
+        checkOS = MS_OS_NT;
+    }
+
+    if( (0 == checkStack) && (0 == stricmp( wsaData.szDescription, W95_32 ))){
+       // get the TCPIP parameters out of the Win95 registry
+        checkStack = MS_95_32;
+        checkOS = MS_OS_95; // ??
+    }
+
+    if( (0 == checkStack) && (0 == stricmp( wsaData.szDescription, W95_16 ))){
+        // go through the pain of getting the TCPIP parameters out of the Win95
+        // 32 bit registry
+        checkStack = MS_95_16;
+        checkOS = MS_OS_95;
+    }
+
+    if( (0 == checkStack) && (0 == stricmp( wsaData.szDescription, LWP_16 ))){
+        // get the information out of the %NDIR%\TCP\RESOLV.CFG file
+        checkStack = NOVELL_LWP_16;
+        checkOS = MS_OS_WIN;
+    }
+
+    if( 0 == checkStack ){
+        // at this time we don't easily know how to support this stack
+        checkStack = STACK_UNKNOWN;
+    }
+
+#if !defined(_WIN32)
+    // Note, if this is the 32 bit DLL we can't use the following
+    // functions to determine the OS because they are
+    // obsolete. However, we should be able to use them in the 16 bit
+    // DLL.
+    {
+        DWORD dwVersion = 0;
+        DWORD dwFlags = 0;
+
+        dwFlags = GetWinFlags();
+        if( _res.options & RES_DEBUG ){
+            wsprintf( debstr, "dwFlags = %x ", dwFlags );
+            OutputDebugString( debstr );
+        }
+
+        dwVersion = GetVersion();
+
+        if( _res.options & RES_DEBUG ){
+            wsprintf( debstr, "dwVersion = %8lx ", dwVersion );
+            OutputDebugString( debstr );
+        }
+
+        if( 95 == (DWORD)(HIBYTE(LOWORD(dwVersion))) ){
+            // OK, we're a 16 bit app running on 95?
+            checkOS = MS_OS_95;
+        }
+
+        if( dwFlags & 0x4000 ){
+            // This means that this is a 16 bit application running
+            // under WOW layer on NT.
+
+            // So, we're going to get the TCPIP parameters out of the
+            // 32 bit registry, but we don't know which set of
+            // registry entries yet.
+
+            // Since we see these version numbers and we're under WOW
+            // we must be under NT 4.0 but we don't necessarily know
+            // the stack
+            checkOS = MS_OS_NT;
+        }
+
+
+        if( checkOS == 0 ){
+            // We are a 16 bit application running on a 16 bit operating system
+            checkOS = MS_OS_WIN; // assumption, but we're not under 95 and not under NT, it looks like
+            if( checkStack == STACK_UNKNOWN ){
+                checkStack = UNKNOWN_16_UNDER_16;
+            }
+        }
+    }
+#endif // !_WIN32
+
+#if defined(_WIN32)
+    // This must be a 32 bit application so we are either under NT,
+    // Win95, or WIN32s
+    {
+        OSVERSIONINFO osvi;
+
+        memset( &osvi, 0, sizeof(OSVERSIONINFO));
+        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+        GetVersionEx( &osvi );
+
+        if( osvi.dwPlatformId == VER_PLATFORM_WIN32s ){
+            if( checkStack == STACK_UNKNOWN ){
+                checkStack = UNKNOWN_16_UNDER_16;
+            }
+            checkOS = MS_OS_WIN;
+            wsprintf( debstr, "Microsoft Win32s %d.%d (Build %d)\n",
+                      osvi.dwMajorVersion,
+                      osvi.dwMinorVersion,
+                      osvi.dwBuildNumber & 0xFFFF );
+        }
+
+        if( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ){
+            if( checkStack == STACK_UNKNOWN ){
+                checkStack = UNKNOWN_32_UNDER_32;
+            }
+            checkOS = MS_OS_95;
+            wsprintf( debstr, "Microsoft Windows 95 %d.%d (Build %d)\n",
+                      osvi.dwMajorVersion,
+                      osvi.dwMinorVersion,
+                      osvi.dwBuildNumber & 0xFFFF );
+        }
+
+        if( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT ){
+            if( checkStack == STACK_UNKNOWN ){
+                checkStack = UNKNOWN_32_UNDER_32;
+            }
+            if ( osvi.dwMajorVersion <= 4 )
+                checkOS = MS_OS_NT;
+            else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
+                checkOS = MS_OS_2000;
+            else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
+                checkOS = MS_OS_XP;
+            else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
+                checkOS = MS_OS_2003;
+            else
+                checkOS = MS_OS_NT_UNKNOWN;
+            wsprintf( debstr, "Microsoft Windows NT family %d.%d (Build %d)\n",
+                      osvi.dwMajorVersion,
+                      osvi.dwMinorVersion,
+                      osvi.dwBuildNumber & 0xFFFF );
+        }
+
+        if( _res.options & RES_DEBUG ){
+            OutputDebugString( debstr );
+        }
+    }
+
+#endif // _WIN32
+
+    // At this point we should know the OS.
+    // We should also know the subsystem but not always the stack.
+
+    dwCheck = MAKELONG(checkOS, checkStack);
+    if ( check )
+        *check = dwCheck;
+    return( dwCheck );
+}
+
+
+static
+BOOL
+get_nt5_adapter_param(
+    char* param,
+    WORD skip,
+    char* buf,
+    unsigned int   len
+    )
+{
+    static char linkage[BUFSIZ*4];
+    char* p;
+    char* q;
+    HKEY hAdapters;
+
+    char* DEVICE_STR = "\\Device\\";
+    SIZE_T DEVICE_LEN = strlen(DEVICE_STR);
+
+#define TCPIP_PATH_ADAPTERS "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"
+#define TCPIP_PATH_LINKAGE "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage"
+
+    if (!getRegKeyEx(HKEY_LOCAL_MACHINE, TCPIP_PATH_LINKAGE, "Bind", linkage, sizeof(linkage)))
+        return FALSE;
+
+    p = linkage;
+
+    RegOpenKeyEx(HKEY_LOCAL_MACHINE, TCPIP_PATH_ADAPTERS, 0,
+                 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
+                 &hAdapters);
+
+    while (*p) {
+        q = strstr(p, DEVICE_STR);
+        if (!q) {
+            while (*p) p++;
+            p++;
+            continue;
+        }
+        q += DEVICE_LEN;
+        p = q;
+        while (*p) p++;
+        p++;
+        buf[0] = '\0';
+        if (getRegKeyEx(hAdapters, q, param, buf, len) && !buf[0]) {
+            if (!skip) {
+                RegCloseKey(hAdapters);
+                return TRUE;
+            }
+            else
+                skip--;
+        }
+    }
+    RegCloseKey(hAdapters);
+
+    // Bottom out by looking at default parameters
+    {
+        char Tcpip_path[_MAX_PATH];
+
+        if(!LoadString(this_module(), IDS_TCPIP_PATH_NT,
+                       Tcpip_path, sizeof(Tcpip_path)))
+            strcpy(Tcpip_path, NT_TCP_PATH);
+        return getRegKeyEx(HKEY_LOCAL_MACHINE, Tcpip_path, param, buf, len);
+    }
+    return FALSE;
+}
+
+
+
+static
+BOOL
+_getdomainname(
+    char* name,
+    int size
+    )
+{
+    char buf[BUFSIZ];
+
+    char* dhcp_param = "DhcpDomain";
+    char* param = "Domain";
+    BOOL ok = FALSE;
+    char* rbuf;
+    unsigned int rlen;
+
+    if (!name || (size <= 0))
+        return FALSE;
+
+    rbuf = (size >= sizeof(buf))?name:buf;
+    rlen = (size >= sizeof(buf))?size:sizeof(buf);
+
+
+    ok = get_nt5_adapter_param(dhcp_param, 0, rbuf, rlen);
+    if (!ok || !rbuf[0])
+        ok = get_nt5_adapter_param(param, 0, rbuf, rlen);
+
+    if (ok && rbuf[0]) {
+        if (size < (lstrlen(rbuf) + 1))
+            return FALSE;
+        if (rbuf != name)
+            strncpy(name, rbuf, size);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/*
+       Gets the base part of the hostname
+       defined in wshelper\res_init.c
+
+       \param[in, out] name pointer to a buffer that receives a null-terminated string containing the computer name
+       \param[in]              size specifies the size of the buffer, in chars (must be large
+                    enough to hold NULL-terminated host name)
+
+       \retval                 return 0 ifsuccess,  -1 on error.
+
+*/
+int WINAPI
+wsh_gethostname(char* name, int size)
+{
+    if (name){
+       // Get and display the name of the computer.
+
+        if( GetComputerName(name, &size) )
+        {
+            while (*name && (*name != '.'))
+            {
+                *name = tolower(*name);
+                name++;
+            }
+            if (*name == '.') *name = 0;
+                return 0;
+        }
+    }
+    return -1;
+}
+
+/*
+       Gets the machine's domain name
+
+       \param[in, out] name pointer to a buffer that receives a null-terminated string containing the domain name
+       \param[in]              size specifies the size of the buffer, in chars (must be large
+                    enough to hold NULL-terminated domain name)
+
+       \retval                 return 0 ifsuccess,  -1 on error.
+
+
+*/
+int WINAPI
+wsh_getdomainname(char* name, int size)
+{
+    DNS_STATUS status;
+
+    PDNS_RECORD pDnsRecord;
+    DNS_FREE_TYPE freetype ;
+
+    DWORD length;
+    char hostName[BUFSIZ];
+
+    length = BUFSIZ;
+    freetype =  DnsFreeRecordListDeep;
+
+
+   // Get and display the name of the computer.
+
+   if( GetComputerName(hostName, &length) )
+   {
+
+        status = DnsQuery_A(hostName,                 //pointer to OwnerName
+                        DNS_TYPE_A,                      //Type of the record to be queried
+                        DNS_QUERY_BYPASS_CACHE|DNS_QUERY_NO_LOCAL_NAME,     // Bypasses the resolver cache on the lookup.
+                        NULL,                   //contains DNS server IP address
+                        &pDnsRecord,                //Resource record comprising the response
+                        NULL);                     //reserved for future use
+
+        if (status)
+            return -1;
+        else
+        {
+            char* cp;
+            cp = index(pDnsRecord->pName, '.');
+            if (cp)
+            {
+                cp++;
+                strncpy(name, cp, size);
+                name[size-1] = '\0';
+                DnsRecordListFree(pDnsRecord, freetype);
+                return(0);
+            }
+            DnsRecordListFree(pDnsRecord, freetype);
+
+        }
+   }
+
+    /* try to get local domain from the registry */
+    if (_getdomainname(name, size))
+        return 0;
+    else
+        return -1;
+}
+
+
+
+
+
+
+
+
+// @func int | getRegKeyEx | This function is only used when the library is
+//                           running under a known 32-bit Microsoft Operating
+//                           system
+
+// @parm const HKEY | key | Specifies a a currently open key or any
+//  of the following predefined reserved handle values:
+//     HKEY_CLASSES_ROOT
+//     KEY_CURRENT_USER
+//     HKEY_LOCAL_MACHINE
+//     HKEY_USERS
+//
+// @parm const char * | subkey | Specifies a pointer to a null-terminated
+//  string containing the name of the subkey to open. If this parameter is NULL
+//  or a pointer to an empty string, the function will open a new handle
+//  of the key identified by the key parameter.
+//
+// @parm const char * | value | Specifiea a pointer to a null-terminated
+//  string containing the name of the value to be queried.
+//
+// @parm char * | buf | Specifies a pointer to a buffer that recieves the
+//  key's data. This parameter can be NULL if the data is not required.
+//
+// @parm unsigned int | len | Specifies the size of buffer 'buf'.
+//
+// @rdesc Returns an int  that can mean:
+//
+// FALSE - if the subkey cannot be queried or possibly opened.
+// TRUE  - if the subkey can be queried but it is not of type: REG_EXPAND_SZ
+// If the subkey can be queried, and its type is REG_EXPAND_SZ, and it can
+// be expanded the return value is the number of characters stored in the
+// buf parameter. If the number of characters is greater than the size of the
+// of the destination buffer, the return value should be the size of the
+// buffer required to hold the value.
+
+static
+int const
+getRegKeyEx(
+    const HKEY key,
+    const char *subkey,
+    const char *value,
+    char *buf,
+    unsigned int len
+    )
+{
+    HKEY hkTcpipParameters;
+    LONG err;
+    DWORD type, cb;
+    char *env_buf;
+
+
+    if (RegOpenKey(key, subkey, &hkTcpipParameters) == ERROR_SUCCESS) {
+        cb = len;
+        err = RegQueryValueEx(hkTcpipParameters, value, 0, &type, buf, &cb);
+        RegCloseKey(hkTcpipParameters);
+        if( err == ERROR_SUCCESS ){
+            if( type == REG_EXPAND_SZ ){
+                if( env_buf = malloc( cb ) ){
+                    err = ExpandEnvironmentStrings( strcpy( env_buf, buf ), buf, len );
+                    free( env_buf );
+                    return err;
+                } else {
+                    return FALSE;
+                }
+            }
+            return TRUE; // subkey could be queried but it was not of type REG_EXPAND_SZ
+        } else {
+            return FALSE; // subkey exists but could not be queried
+        }
+    }
+    else
+
+// #endif // WIN32
+
+        return FALSE; // subkey could not be opened
+}
+
+#ifdef __cplusplus
+inline
+#endif
+
+#include "wsh-int.h"
+
+static
+HMODULE
+this_module()
+{
+    static HMODULE hModWSHelp = 0;
+    if (!hModWSHelp)
+    {
+        // Note: these must match the DEF file entries
+#if defined (_WIN32)
+        hModWSHelp = GetModuleHandle("WSHELP32");
+#else
+        hModWSHelp = GetModuleHandle("WSHELPER");
+#endif
+    }
+    return hModWSHelp;
+}
+
+static
+int
+try_registry(
+    HKEY  hBaseKey,
+    const char * name,
+    DWORD * value
+    )
+{
+    HKEY hKey;
+    LONG err;
+    DWORD size;
+
+    err = RegOpenKeyEx(hBaseKey,
+                       "Software\\MIT\\WsHelper",
+                       0,
+                       KEY_QUERY_VALUE,
+                       &hKey);
+    if (err)
+        return 0;
+    size = sizeof(value);
+    err = RegQueryValueEx(hKey, name, 0, 0, value, &size);
+    RegCloseKey(hKey);
+    return !err;
+}
+
+void
+res_init_startup()
+{
+    DWORD debug_on = 0;
+
+
+    if (try_registry(HKEY_CURRENT_USER, "DebugOn", &debug_on) ||
+        try_registry(HKEY_LOCAL_MACHINE, "DebugOn", &debug_on))
+    {
+        if (debug_on)
+            _res.options |= RES_DEBUG;
+    }
+}
+
+void
+res_init_cleanup()
+{
+
+}
diff --git a/src/windows/wshelper/res_quer.c b/src/windows/wshelper/res_quer.c
new file mode 100644 (file)
index 0000000..ad36ec7
--- /dev/null
@@ -0,0 +1,561 @@
+/*
+ *
+ *     @doc RESOLVE
+ *
+ *
+ *     @module res_quer.c | Contains the implementation of res_query,
+ *     res_search, and res_querydomain
+ *
+ * WSHelper DNS/Hesiod Library for WINSOCK
+ *
+ */
+
+/*
+ * Copyright (c) 1988 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_query.c        5.11 (Berkeley) 3/6/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <windows.h>
+#include <winsock.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windns.h>
+
+#define MAX_MSG_SIZE 0x2003
+
+#define strcasecmp     stricmp
+
+#ifdef _DEBUG
+#define DEBUG
+#endif
+int
+__hostalias(register const char *name, char* abuf);
+DNS_STATUS do_res_search(const char *name, int qclass, int type, u_char *retanswer, int retanswerlen, int* anslen);
+void __putshort(register u_short, register u_char *);
+void __putlong(register u_long, u_char *);
+int build_rr(char* p, PDNS_RECORD ptr, int qclass);
+int put_qname(char* p, char* qname);
+
+
+
+/*
+       a generic query interface to the DNS name space. The query is performed with the dnsapi and
+       the answer buffer is populated based on the returned RR set.
+
+       \param[in]      name    domain name
+       \param[in]      qclass  class of query(such as DNS_CLASS_INTERNET, DNS_CLASS_CSNET, DNS_CLASS_CHAOS,
+                                               DNS_CLASS_HESIOD. Defined in windns.h)
+       \param[in]      type    type of query(such as DNS_TYPE_A, DNS_TYPE_NS, DNS_TYPE_MX, DNS_TYPE_SRV. Defined in
+                                               windns.h)
+       \param[in]      answer  buffer to put answer in
+       \param[in]      anslen  size of the answer buffer. compare the anslen with the return value, if the return
+                                               value is bigger than anslen, it means the answer buffer doesn't contain the complete
+                                               response. You will need to call this function again with a bigger answer buffer if
+                                               you care about the complete response
+
+       \retval         return the size of the response on success, -1 on error
+
+
+ */
+int WINAPI
+res_search(const char *name, int qclass, int type, u_char *answer, int anslen)
+    /* domain name, class and type of query, buffer to put answer, size of answer */
+{
+    char debstr[80];
+    int n = 0;
+    DNS_STATUS status;
+    char queryname[DNS_MAX_NAME_BUFFER_LENGTH ];
+    register const char *cp;
+    int len = 0;
+
+    char** domain;
+
+    status = -1;
+    memset(answer, 0, anslen);
+    memset(queryname, 0, sizeof(queryname));
+
+    if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+        return (-1);
+
+    for (cp = name, n = 0; *cp; cp++)
+        if (*cp == '.')
+            n++;
+
+    if (n == 0 && !__hostalias(name, queryname) && strlen(queryname)>0)
+    {
+       status = do_res_search(queryname, qclass, type, answer, anslen, &len);
+       if (status == 0)
+           return len;
+    }
+
+    if ((n == 0 && _res.options & RES_DEFNAMES))
+       // (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
+    {
+       for (domain = _res.dnsrch; *domain; domain++) {
+           strcpy(queryname, name);
+           strcat(queryname, ".");
+           strcat(queryname, *domain);
+           status = do_res_search(queryname, qclass, type, answer, anslen, &len);
+           if (status == 0)
+               return len;
+       }
+    }
+
+
+    strcpy(queryname, name);
+    status = do_res_search(queryname, qclass, type, answer, anslen, &len);
+
+
+    if (status)
+    {
+#ifdef DEBUG
+        if (_res.options & RES_DEBUG)
+        {
+            wsprintf(debstr, "res_query failed\n");
+            OutputDebugString(debstr);
+        }
+#endif
+       return -1;
+    }
+    return len;
+}
+
+int
+put_qname(char* cp, char* qname)
+{
+    char* p;
+    char* temp;
+    INT_PTR n = 0;
+    INT_PTR i = 0;
+    temp = qname;
+    while (p = strchr(temp, '.'))
+    {
+       n = p - temp;
+       if (n == 0)
+       {
+           temp++;
+           break;
+       }
+       cp[0] = (int)n;
+       cp++;
+       i++;
+       strncpy(cp, temp, n);
+       temp = p+1;
+       cp =  cp + n;
+       i = i + n;
+    }
+    n = strlen(temp);
+    if (n > 0)
+    {
+       cp[0] = (int)n;
+       cp++;
+       i++;
+       strcpy(cp, temp);
+       cp = cp+n;
+    }
+    cp[0] = 0;
+    i = i+n+1;
+    return (int)i;
+}
+
+DNS_STATUS
+do_res_search(const char *queryname, int qclass, int type, u_char *retanswer, int retanswerlen, int* anslen)
+{
+    PDNS_RECORD pDnsRecord;
+    PDNS_RECORD ptr;
+    DNS_STATUS status;
+    DNS_FREE_TYPE freetype ;
+    HEADER *hp;
+    char *cp;
+    int  n;
+    int i;
+    u_char  answer[MAX_MSG_SIZE];
+    DWORD options = DNS_QUERY_STANDARD;
+    freetype =  DnsFreeRecordListDeep;
+
+    memset(answer, 0, MAX_MSG_SIZE);
+    if (!(_res.options & RES_RECURSE))
+       options = options | DNS_QUERY_NO_RECURSION;
+    if (_res.options & RES_USEVC)
+       options = options | DNS_QUERY_USE_TCP_ONLY;
+    if (_res.options & RES_IGNTC)
+       options = options | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE;
+
+    status = DnsQuery_A(queryname,                 //pointer to OwnerName
+                        type,         //Type of the record to be queried
+                        options,
+                        NULL,                   //contains DNS server IP address
+                        &pDnsRecord,                //Resource record comprising the response
+                        NULL);                     //reserved for future use
+
+    if (status)
+        return  status;
+
+
+    hp = (HEADER *) answer;
+    cp = answer + sizeof(HEADER);
+
+    // populating the header
+    hp->id = htons(++_res.id); // query id
+    hp->qr = 1;  // 0 for query 1 for response
+    hp->opcode = 0; // standard query
+    hp->aa = 1; // authoritative answer
+    hp->tc = 0; // no truncation
+    hp->rd = (_res.options & RES_RECURSE) != 0; // resursion desired
+    hp->ra = 1;  // recursion available
+    hp->pr = (_res.options & RES_PRIMARY) != 0; // primary server required
+    hp->rcode = NOERROR;
+    hp->qdcount = htons(1); // number of question entries
+    i = put_qname(cp, (char*)queryname);
+    cp = cp + i;
+    __putshort(type, (u_char *)cp);
+    cp += sizeof(u_short);
+    __putshort(qclass, (u_char *)cp);
+    cp += sizeof(u_short);
+
+    // get the answer
+    for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
+    {
+       if ((ptr->Flags).S.Section == DNSREC_ANSWER ||
+            (type == DNS_TYPE_PTR && (ptr->Flags).S.Section==DNSREC_QUESTION))
+       {
+           i = build_rr(cp, ptr, qclass);
+           cp = cp + i;
+           //strcpy(cp, pDnsRecord->pName);
+           //cp += strlen(pDnsRecord->pName);
+           //cp++;
+
+           n++;
+       }
+    }
+    hp->ancount = htons(n);
+
+    // get the authority
+    for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
+    {
+       if ((ptr->Flags).S.Section == DNSREC_AUTHORITY )
+       {
+           i = build_rr(cp, ptr, qclass);
+           cp = cp + i;
+
+           n++;
+       }
+    }
+    hp->nscount = htons(n);
+
+    // get the additional resource
+    for (n = 0, ptr = pDnsRecord; ptr; ptr = ptr->pNext)
+    {
+       if ((ptr->Flags).S.Section == DNSREC_ADDITIONAL)
+       {
+           i = build_rr(cp, ptr, qclass);
+           cp = cp + i;
+
+           n++;
+       }
+
+    }
+    hp->arcount = htons(n);
+
+    *anslen = (int)(cp - answer);
+    if (*anslen > retanswerlen)
+       memcpy(retanswer, answer, retanswerlen); // partial copy
+    else
+       memcpy(retanswer, answer, *anslen);
+    DnsRecordListFree(pDnsRecord, freetype);
+    return status;
+}
+
+int
+build_rr(char* p, PDNS_RECORD ptr, int qclass)
+{
+    int i = 0;
+    int n = 0;
+    char* cp = p;
+    char* temp = NULL;
+    unsigned int index = 0;
+
+    i = put_qname(cp, ptr->pName);
+    cp = p + i;
+
+    __putshort(ptr->wType, (u_char *)cp);
+    i += sizeof(u_short);
+    cp = p + i;
+    __putshort(qclass, (u_char *)cp);
+    i += sizeof(u_short);
+    cp = p + i;
+    __putlong(ptr->dwTtl, (u_char*)cp);
+    i += sizeof(u_long);
+    cp = p + i;
+    switch (ptr->wType)
+    {
+    case DNS_TYPE_A:
+       __putshort(sizeof(ptr->Data.A), (u_char*)cp); //RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       memcpy(cp, &(ptr->Data.A), sizeof(ptr->Data.A));
+       i += sizeof(ptr->Data.A);
+       break;
+    case DNS_TYPE_NS:
+    case DNS_TYPE_MD:
+    case DNS_TYPE_MF:
+    case DNS_TYPE_CNAME:
+    case DNS_TYPE_MB:
+    case DNS_TYPE_MG:
+    case DNS_TYPE_MR:
+    case DNS_TYPE_PTR:
+       temp = cp;     // hold the spot for RD length
+       i += sizeof(u_short);
+       cp = p+i;
+       n = put_qname(cp, ptr->Data.Ptr.pNameHost);
+       i += n;
+       __putshort(n, (u_char*)temp); //set RDLENGTH
+       break;
+    case DNS_TYPE_TEXT:
+    case DNS_TYPE_HINFO:
+    case DNS_TYPE_ISDN:
+    case DNS_TYPE_X25:
+       temp = cp; // hold the spot for RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       n = 0;
+       for (index = 0; index < ptr->Data.Txt.dwStringCount; index++)
+       {
+           *cp = (int)(strlen(ptr->Data.Txt.pStringArray[index]));
+           n += *cp;
+           n++;
+           strcpy(++cp, ptr->Data.Txt.pStringArray[index]);
+       }
+       i += n;
+       __putshort(n,(u_char*)temp); // set RDLENGTH
+       break;
+    case DNS_TYPE_SRV:
+       temp = cp; // hold the spot for RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       // priority
+       __putshort(ptr->Data.Srv.wPriority, (u_char*)cp);
+       i += sizeof(u_short);
+       cp = p + i;
+       //weight
+       __putshort(ptr->Data.Srv.wWeight, (u_char*)cp);
+       i += sizeof(u_short);
+       cp = p + i;
+       //port
+       __putshort(ptr->Data.Srv.wPort, (u_char*)cp);
+       i += sizeof(u_short);
+       cp = p + i;
+
+       n = put_qname(cp, ptr->Data.Srv.pNameTarget);
+       i+=n;
+       __putshort((u_short)(n + sizeof(u_short)*3),(u_char*)temp);
+
+       break;
+    case DNS_TYPE_MX:
+    case DNS_TYPE_AFSDB:
+    case DNS_TYPE_RT:
+       temp = cp; // hold the spot for RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       __putshort(ptr->Data.Mx.wPreference, (u_char*)cp); // put wPreference
+       i += sizeof(u_short);
+       cp = p + i;
+       n = put_qname(cp, ptr->Data.Mx.pNameExchange);
+       i+=n;
+       __putshort((u_short)(n+sizeof(u_short)),(u_char*)temp);
+       break;
+       case DNS_TYPE_SOA:
+       temp = cp; // hold the spot for RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       // primary server name
+       n = put_qname(cp, ptr->Data.Soa.pNamePrimaryServer);
+       i+= n;
+       cp = p + i;
+       //the person responsible for this zone.
+       n += put_qname(cp, ptr->Data.Soa.pNameAdministrator);
+       i += n;
+       cp = p + i;
+       //SERIAL
+       __putlong(ptr->Data.Soa.dwSerialNo, cp);
+       n += sizeof(u_long);
+       i += sizeof(u_long);
+       cp = p + i;
+       //refresh
+       __putlong(ptr->Data.Soa.dwRefresh, cp);
+       n += sizeof(u_long);
+       i += sizeof(u_long);
+       cp = p + i;
+       //retry
+       __putlong(ptr->Data.Soa.dwRetry, cp);
+       n += sizeof(u_long);
+       i += sizeof(u_long);
+       cp = p + i;
+       // expire
+       __putlong(ptr->Data.Soa.dwExpire, cp);
+       n += sizeof(u_long);
+       i += sizeof(u_long);
+       cp = p + i;
+       // minimum TTL
+       __putlong(ptr->Data.Soa.dwDefaultTtl, cp);
+       n += sizeof(u_long);
+       i += sizeof(u_long);
+       // set RDLength
+       __putshort(n,(u_char*)temp);
+       break;
+       case DNS_TYPE_NULL:
+       __putshort((short)ptr->Data.Null.dwByteCount, (u_char*)cp); //RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       memcpy(cp, ptr->Data.Null.Data, ptr->Data.Null.dwByteCount);
+       i += ptr->Data.Null.dwByteCount;
+       break;
+       case DNS_TYPE_WKS:   // needs more work
+       temp = cp; // hold the spot for RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       // address
+       memcpy(cp, &(ptr->Data.Wks.IpAddress), sizeof(ptr->Data.Wks.IpAddress));
+       n = sizeof(ptr->Data.Wks.IpAddress);
+       i += sizeof(ptr->Data.Wks.IpAddress);
+       cp = p + i;
+       // protocol
+       *cp = ptr->Data.Wks.chProtocol;
+       i++;
+       n++;
+       cp = p + i;
+       //bit mask
+       memcpy(cp, &(ptr->Data.Wks.BitMask), sizeof(ptr->Data.Wks.BitMask));
+       n+=sizeof(ptr->Data.Wks.BitMask);
+       i += n;
+       // set RDLength
+       __putshort(n,(u_char*)temp);
+       break;
+       case DNS_TYPE_MINFO:
+       case DNS_TYPE_RP:
+       temp = cp; // hold the spot for RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       // pNameMailbox
+       n = put_qname(cp, ptr->Data.Minfo.pNameMailbox);
+       i+= n;
+       cp = p + i;
+       // pNameErrorsMailbox;
+       n += put_qname(cp, ptr->Data.Minfo.pNameMailbox);
+       i += n;
+       // set RDLength
+       __putshort(n,(u_char*)temp);
+    break;
+       case DNS_TYPE_AAAA:
+       __putshort(sizeof(ptr->Data.AAAA), (u_char*)cp); //RDLENGTH
+       i += sizeof(u_short);
+       cp = p + i;
+       memcpy(cp, &(ptr->Data.AAAA), sizeof(ptr->Data.AAAA));
+       i += sizeof(ptr->Data.AAAA);
+
+    break;
+    }
+    return i;
+}
+
+
+int
+__hostalias(register const char *name, char* abuf)
+{
+    register char *C1, *C2;
+    FILE *fp;
+    char *file;
+//  char *getenv(), *strcpy(), *strncpy();  // pbh XXX 11/1/96
+    char buf[BUFSIZ];
+
+
+    file = getenv("HOSTALIASES");
+    if (file == NULL || (fp = fopen(file, "r")) == NULL)
+        return -1;
+    buf[sizeof(buf) - 1] = '\0';
+    while (fgets(buf, sizeof(buf), fp)) {
+        for (C1 = buf; *C1 && !isspace(*C1); ++C1);
+        if (!*C1)
+            break;
+        *C1 = '\0';
+        if (!strcasecmp(buf, name)) {
+            while (isspace(*++C1));
+            if (!*C1)
+                break;
+            for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
+            abuf[sizeof(abuf) - 1] = *C2 = '\0';
+            (void)strncpy(abuf, C1, sizeof(abuf) - 1);
+            fclose(fp);
+            return 0;
+        }
+    }
+    fclose(fp);
+    return -1;
+}
+
+int  WINAPI
+res_mkquery(int op, const char  *dname,
+           int qclass, int type,
+           const char  *data, int datalen,
+           const struct rrec  *newrr,
+           char  *buf, int buflen)
+{
+    return -1;
+}
+
+int  WINAPI
+res_querydomain(const char  *name,
+               const char  *domain,
+               int qclass, int type,
+               u_char  *answer, int anslen)
+{
+    return -1;
+}
+
+int  WINAPI
+res_send(const char  *msg, int msglen,
+        char  *answer, int anslen)
+{
+       return -1;
+}
+
+int  WINAPI
+res_query(char *name, int qclass, int type, u_char *answer, int anslen)
+{
+    return -1;
+}
diff --git a/src/windows/wshelper/resource.h b/src/windows/wshelper/resource.h
new file mode 100644 (file)
index 0000000..cc5f082
--- /dev/null
@@ -0,0 +1,29 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+#define IDS_DEF_HES_RHS                 1
+#define IDS_DEF_HES_LHS                 2
+#define IDS_DEF_HES_CONFIG_FILE         3
+#define IDS_DEF_RESCONF_PATH            4
+#define IDS_DEF_DNS1                    5
+#define IDS_DEF_DNS2                    6
+#define IDS_DEF_DNS3                    7
+#define IDS_TCPIP_PATH_NT               8
+#define IDS_TCPIP_PATH_95               9
+#define IDS_NT_DOMAIN_KEY               10
+#define IDS_NT_NS_KEY                   11
+#define IDS_W95_DOMAIN_KEY              12
+#define IDS_W95_NS_KEY                  13
+#define IDS_TCPIP_PATH_NT_TRANSIENT     14
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/src/windows/wshelper/resource.rc b/src/windows/wshelper/resource.rc
new file mode 100644 (file)
index 0000000..d94e2de
--- /dev/null
@@ -0,0 +1,64 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <afxres.h>
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "#include <afxres.h>\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "#include ""version.rc""\r\n"
+    "#include ""string.rc""\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc"
+#include "string.rc"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
diff --git a/src/windows/wshelper/string.rc b/src/windows/wshelper/string.rc
new file mode 100644 (file)
index 0000000..6916dbc
--- /dev/null
@@ -0,0 +1,29 @@
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by App Studio
+#endif // APSTUDIO_INVOKED
+
+#include <hesiod.h>
+#include <mitwhich.h>
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+    IDS_DEF_HES_RHS             DEF_RHS
+    IDS_DEF_HES_LHS             DEF_LHS
+    IDS_DEF_HES_CONFIG_FILE     HESIOD_CONF
+    IDS_DEF_RESCONF_PATH        _PATH_RESCONF
+    IDS_DEF_DNS1                DNS1
+    IDS_DEF_DNS2                DNS2
+    IDS_DEF_DNS3               DNS3
+    IDS_TCPIP_PATH_NT           NT_TCP_PATH
+    IDS_TCPIP_PATH_95           W95_TCP_PATH
+    IDS_NT_DOMAIN_KEY           NT_DOMAIN_KEY
+    IDS_NT_NS_KEY               NT_NS_KEY
+    IDS_W95_DOMAIN_KEY          W95_DOMAIN_KEY
+    IDS_W95_NS_KEY              W95_NS_KEY
+    IDS_TCPIP_PATH_NT_TRANSIENT NT_TCP_PATH_TRANS
+END
diff --git a/src/windows/wshelper/ver.rc.inc b/src/windows/wshelper/ver.rc.inc
new file mode 100644 (file)
index 0000000..f927fb1
--- /dev/null
@@ -0,0 +1,57 @@
+#ifdef RC_INVOKED
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION    VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEFLAGSMASK  VER_FILEFLAGSMASK
+FILEFLAGS      VER_FILEFLAGS
+FILEOS         VER_FILEOS
+FILETYPE       VER_FILETYPE
+FILESUBTYPE    VER_FILESUBTYPE
+BEGIN
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0409, 0x04B0
+    END
+
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904B0"   /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
+        BEGIN
+#if defined(VER_EXTRA_LABEL) && defined(VER_EXTRA_VALUE)
+            VALUE VER_EXTRA_LABEL,   VER_EXTRA_VALUE
+#endif
+#ifdef VER_COMMENT
+            VALUE "Comment",         VER_COMMENT
+#endif
+#ifdef VER_USERNAME
+            VALUE "Built By",        VER_USERNAME
+#endif
+#ifdef VER_HOSTNAME
+            VALUE "Build Host",      VER_HOSTNAME
+#endif
+#ifdef VER_DATE
+            VALUE "Build Time",      VER_DATE
+#endif
+#ifdef VER_VENDOR
+            VALUE "Modified by Vendor",  VER_VENDOR
+#endif
+            VALUE "CompanyName",     VER_COMPANYNAME_STR
+            VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG
+            VALUE "FileVersion",     VER_FILEVERSION_STR
+            VALUE "InternalName",    VER_INTERNALNAME_STR
+            VALUE "LegalCopyright",  VER_LEGALCOPYRIGHT_STR
+#ifdef VER_LEGALTRADEMARK_STR
+            VALUE "LegalTrademark",  VER_LEGALTRADEMARK_STR
+#endif
+            VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR
+            VALUE "ProductName",     VER_PRODUCTNAME_STR
+            VALUE "ProductVersion",  VER_PRODUCTVERSION_STR
+#ifdef VER_SPECIALBUILD
+            VALUE "SpecialBuild",    VER_SPECIALBUILD
+#endif
+        END
+    END
+END
+
+#endif
diff --git a/src/windows/wshelper/version.rc b/src/windows/wshelper/version.rc
new file mode 100644 (file)
index 0000000..cc3a948
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by App Studio
+#endif // APSTUDIO_INVOKED
+
+#define VER_FILEDESCRIPTION_STR "Winsock Helper (wshelper) API DLL"
+
+#include <wshelper.ver>
+#include <ver.inc>
diff --git a/src/windows/wshelper/wsh-int.h b/src/windows/wshelper/wsh-int.h
new file mode 100644 (file)
index 0000000..0041d00
--- /dev/null
@@ -0,0 +1,2 @@
+void res_init_startup();
+void res_init_cleanup();
diff --git a/src/windows/wshelper/wshelp32.def b/src/windows/wshelper/wshelp32.def
new file mode 100644 (file)
index 0000000..b0a5aea
--- /dev/null
@@ -0,0 +1,33 @@
+LIBRARY        WSHELP32
+
+HEAPSIZE        1024
+EXPORTS
+;              WEP                     @1 RESIDENTNAME
+               res_init                @2
+               res_query               @3
+               res_search              @4
+               res_querydomain         @5
+               res_mkquery             @6
+               res_send                @7
+               dn_comp                 @8
+               rdn_expand              @9
+               rgethostbyname          @10
+               rgethostbyaddr          @11
+               hes_to_bind             @12
+               hes_resolve             @13
+               hes_error               @14
+               hes_getmailhost         @15
+               hes_getservbyname       @16
+               hes_getpwnam            @17
+               res_getopts             @18
+               res_setopts             @19
+               inet_aton               @20
+               gethinfobyname          @21
+               getmxbyname             @22
+               getrecordbyname         @23
+               rrhost                  @24
+               rgetservbyname          @25
+               hes_getpwuid            @26
+               wsh_gethostname
+               wsh_getdomainname
+               hes_free
diff --git a/src/windows/wshelper/wshelp64.def b/src/windows/wshelper/wshelp64.def
new file mode 100644 (file)
index 0000000..e28dd16
--- /dev/null
@@ -0,0 +1,33 @@
+LIBRARY        WSHELP64
+
+HEAPSIZE        1024
+EXPORTS
+;              WEP                     @1 RESIDENTNAME
+               res_init                @2
+               res_query               @3
+               res_search              @4
+               res_querydomain         @5
+               res_mkquery             @6
+               res_send                @7
+               dn_comp                 @8
+               rdn_expand              @9
+               rgethostbyname          @10
+               rgethostbyaddr          @11
+               hes_to_bind             @12
+               hes_resolve             @13
+               hes_error               @14
+               hes_getmailhost         @15
+               hes_getservbyname       @16
+               hes_getpwnam            @17
+               res_getopts             @18
+               res_setopts             @19
+               inet_aton               @20
+               gethinfobyname          @21
+               getmxbyname             @22
+               getrecordbyname         @23
+               rrhost                  @24
+               rgetservbyname          @25
+               hes_getpwuid            @26
+               wsh_gethostname
+               wsh_getdomainname
+               hes_free
diff --git a/src/windows/wshelper/wshelper.def b/src/windows/wshelper/wshelper.def
new file mode 100644 (file)
index 0000000..5b67a3d
--- /dev/null
@@ -0,0 +1,42 @@
+LIBRARY         WSHELPER
+
+DESCRIPTION     'WINSOCK DNS/Hesiod Resolver Library'
+EXETYPE         WINDOWS
+CODE            LOADONCALL MOVEABLE DISCARDABLE
+DATA            LOADONCALL PRELOAD FIXED SINGLE
+HEAPSIZE        1024
+SEGMENTS        _TEXT PRELOAD FIXED
+EXPORTS
+               WEP                     @1 RESIDENTNAME
+               res_init                @2
+               res_query               @3
+               res_search              @4
+               res_querydomain         @5
+               res_mkquery             @6
+               res_send                @7
+               dn_comp                 @8
+               rdn_expand              @9
+               rgethostbyname          @10
+               rgethostbyaddr          @11
+               hes_to_bind             @12
+               hes_resolve             @13
+               hes_error               @14
+               hes_getmailhost         @15
+               hes_getservbyname       @16
+               hes_getpwnam            @17
+               res_getopts             @18
+               res_setopts             @19
+               inet_aton               @20
+               gethinfobyname          @21
+               getmxbyname             @22
+               getrecordbyname         @23
+               rrhost                  @24
+               rgetservbyname          @25
+               hes_getpwuid            @26
+
+
+IMPORTS
+               kernel.LoadLibraryEx32W
+               kernel.FreeLibrary32W
+               kernel._CallProcEx32W
+               kernel.GetProcAddress32W