From: Sam Hartman Date: Wed, 28 Sep 2011 20:54:16 +0000 (+0000) Subject: Added leashdll/wshelper related files from KFW X-Git-Tag: krb5-1.10-alpha1~132 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=6a45252bb3a6a808bb6f3dc32a7f1d85a7c04df1;p=krb5.git Added leashdll/wshelper related files from KFW From: Alexey Melnikov git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25243 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/arpa/nameser.h b/src/include/arpa/nameser.h new file mode 100644 index 000000000..f9ddafce9 --- /dev/null +++ b/src/include/arpa/nameser.h @@ -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 +#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 index 000000000..3005929fc --- /dev/null +++ b/src/include/hesiod.h @@ -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 + +/*! \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 index 000000000..47ee5dab6 --- /dev/null +++ b/src/include/mitwhich.h @@ -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 index 000000000..929795957 --- /dev/null +++ b/src/include/resolv.h @@ -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 +#ifndef MAXDNAME +#include +#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 + +/* 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 index 000000000..1bd31f046 --- /dev/null +++ b/src/include/wshelper.h @@ -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 +#include +#include +#include + +#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 index 000000000..a67b164e3 --- /dev/null +++ b/src/windows/leashdll/AFSroutines.c @@ -0,0 +1,852 @@ +//* Module name: AFSroutines.c + +#include +#include +#include + +/* Private Include files */ +#include +#include +#include +#include "leashdll.h" +#include + +#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 index 000000000..65a8779ca --- /dev/null +++ b/src/windows/leashdll/include/krb4/conf-pc.h @@ -0,0 +1,108 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * 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 +#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 +#endif + +#ifdef WIN32 +#include +#endif + +#ifdef WIN16 +#pragma message ( "WIN16 in " __FILE__ ) +#include +#include +#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 index 000000000..2e2a84cd6 --- /dev/null +++ b/src/windows/leashdll/include/krb4/conf.h @@ -0,0 +1,74 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * 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 index 000000000..340421e86 --- /dev/null +++ b/src/windows/leashdll/include/krb4/osconf.h @@ -0,0 +1,59 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * . + * + * 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 index 000000000..834765fbb --- /dev/null +++ b/src/windows/leashdll/include/leasherr.h @@ -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 index 000000000..7365aa1b5 --- /dev/null +++ b/src/windows/leashdll/include/leashinfo.h @@ -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 index 000000000..477c6c30c --- /dev/null +++ b/src/windows/leashdll/include/leashwin.h @@ -0,0 +1,188 @@ +#ifndef __LEASHWIN__ +#define __LEASHWIN__ + +#include + +#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 index 000000000..a579749c1 --- /dev/null +++ b/src/windows/leashdll/include/loadfuncs-com_err.h @@ -0,0 +1,44 @@ +#ifndef __LOADFUNCS_COM_ERR_H__ +#define __LOADFUNCS_COM_ERR_H__ + +#include "loadfuncs.h" +#include + +#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 index 000000000..1fab67539 --- /dev/null +++ b/src/windows/leashdll/include/loadfuncs-krb5.h @@ -0,0 +1,1757 @@ +#ifndef __LOADFUNCS_KRB5_H__ +#define __LOADFUNCS_KRB5_H__ + +#include "loadfuncs.h" +#include + +#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 index 000000000..40138f5de --- /dev/null +++ b/src/windows/leashdll/include/loadfuncs-lsa.h @@ -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 index 000000000..ef7f6b7c8 --- /dev/null +++ b/src/windows/leashdll/include/loadfuncs-profile.h @@ -0,0 +1,151 @@ +#ifndef __LOADFUNCS_PROFILE_H__ +#define __LOADFUNCS_PROFILE_H__ + +#include "loadfuncs.h" +#include + +#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 index 000000000..7aef62d21 --- /dev/null +++ b/src/windows/leashdll/include/loadfuncs.h @@ -0,0 +1,41 @@ +#ifndef __LOADFUNCS_H__ +#define __LOADFUNCS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +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 index 000000000..7f2d28306 --- /dev/null +++ b/src/windows/leashdll/krb5routines.c @@ -0,0 +1,1530 @@ +// Module name: krb5routines.c + +#include +#define SECURITY_WIN32 +#include + +/* _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 +#include +#include +#include +#include + +/* Private Include files */ +#include "leashdll.h" +#include +#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; naddrCount; 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;icontents ) + 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; istyle = 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; istyle = 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 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 index 000000000..fb7617ed3 --- /dev/null +++ b/src/windows/leashdll/leash-int.h @@ -0,0 +1,357 @@ +#ifndef __LEASH_INT_H__ +#define __LEASH_INT_H__ + +#include +#include + +#include "leashdll.h" +#include + +#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 + +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 index 000000000..f5e265342 --- /dev/null +++ b/src/windows/leashdll/leashdll.c @@ -0,0 +1,444 @@ +#include +#include "leashdll.h" +#include +#include +#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 index 000000000..162fb4f21 --- /dev/null +++ b/src/windows/leashdll/leashdll.h @@ -0,0 +1,259 @@ +#ifndef _LEASHDLL_H_ +#define _LEASHDLL_H_ + +#include +#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 +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 + +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 +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 +#define SECURITY_WIN32 +#include + +/* _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 + +#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 +#include +#include +#ifndef NO_KRB4 +#include +#include +#endif +#include + +#include + +#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 index 000000000..ec2616b21 --- /dev/null +++ b/src/windows/leashdll/leasherr.c @@ -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 +#include + +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 + +void Leash_initialize_krb_error_func(err_func func, HANDLE *__et_list) +{ +#ifndef NO_KRB4 + (*pinitialize_krb_error_func)(func,__et_list); +#endif +} + +#include + +void Leash_initialize_kadm_error_table(HANDLE *__et_list) +{ +#ifndef NO_KRB4 + (*pinitialize_kadm_error_table)(__et_list); +#endif +} +#else +#include + +void Leash_initialize_krb_error_func(err_func func, struct et_list **__et_list) +{ + (*pinitialize_krb_error_func)(func,__et_list); +} + +#include + +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 index 000000000..d1d027bd1 --- /dev/null +++ b/src/windows/leashdll/leasherr.et @@ -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 index 000000000..64c8641cb --- /dev/null +++ b/src/windows/leashdll/leashids.h @@ -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 index 000000000..25af0e2ea --- /dev/null +++ b/src/windows/leashdll/leashw32.def @@ -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 index 000000000..44ec54dfa --- /dev/null +++ b/src/windows/leashdll/loadfuncs.c @@ -0,0 +1,88 @@ +#define WIN32_LEAN_AND_MEAN +#include +#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 index 000000000..6be1ea3c0 --- /dev/null +++ b/src/windows/leashdll/lsh_pwd.c @@ -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 + + 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 +#include +#include + +/* Private Inlclude files */ +#include "leashdll.h" +#include +#include +#include "leash-int.h" +#include "leashids.h" +#include +#include +#ifndef NO_KRB5 +#include +#endif /* NO_KRB5 */ +#include + +/* 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, §ions); + + 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, §ions); + + 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 index 000000000..c6d5a1bf1 --- /dev/null +++ b/src/windows/leashdll/lsh_pwd.rc @@ -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 index 000000000..3f2afb345 --- /dev/null +++ b/src/windows/leashdll/lshcallb.c @@ -0,0 +1,15 @@ +#include +#include + +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 index 000000000..73b10c357 --- /dev/null +++ b/src/windows/leashdll/lshfunc.c @@ -0,0 +1,3867 @@ +#include +#include +#include +#include +#include "leashdll.h" +#include +#include +#include + +#include +#include "leasherr.h" +#include "leash-int.h" +#include "leashids.h" + +#include + +#include +#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; ilength; 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; naddrCount; 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 + * <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 index 000000000..7113d056e --- /dev/null +++ b/src/windows/leashdll/registry.c @@ -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 index 000000000..05dd4bddd --- /dev/null +++ b/src/windows/leashdll/reminder.h @@ -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 index 000000000..c4af48f23 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 index 000000000..9ef4f96ff 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 index 000000000..637c93878 --- /dev/null +++ b/src/windows/leashdll/resource.h @@ -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 index 000000000..c9feadb3e --- /dev/null +++ b/src/windows/leashdll/timesync.c @@ -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 index 000000000..88bb7d943 --- /dev/null +++ b/src/windows/leashdll/ver.rc @@ -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 index 000000000..10806d8b8 --- /dev/null +++ b/src/windows/leashdll/winerr.c @@ -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 index 000000000..65609bcdf --- /dev/null +++ b/src/windows/leashdll/winutil.c @@ -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 index 000000000..5ae0016e6 --- /dev/null +++ b/src/windows/wshelper/dllmain.c @@ -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 index 000000000..8914c3270 --- /dev/null +++ b/src/windows/wshelper/gethna.c @@ -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 index 000000000..c912f7d44 --- /dev/null +++ b/src/windows/wshelper/hesiod.c @@ -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 index 000000000..32791e8d6 --- /dev/null +++ b/src/windows/wshelper/hesmailh.c @@ -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 index 000000000..55ddf01c1 --- /dev/null +++ b/src/windows/wshelper/hespwnam.c @@ -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 index 000000000..01db3a4bf --- /dev/null +++ b/src/windows/wshelper/hesservb.c @@ -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 index 000000000..bc7bd09a0 --- /dev/null +++ b/src/windows/wshelper/inetaton.c @@ -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 index 000000000..6954fd77d --- /dev/null +++ b/src/windows/wshelper/pwd.h @@ -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 index 000000000..18e8a7c47 --- /dev/null +++ b/src/windows/wshelper/res_comp.c @@ -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 index 000000000..bf3d97b50 --- /dev/null +++ b/src/windows/wshelper/res_init.c @@ -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 index 000000000..ad36ec745 --- /dev/null +++ b/src/windows/wshelper/res_quer.c @@ -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 index 000000000..cc5f082ff --- /dev/null +++ b/src/windows/wshelper/resource.h @@ -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 index 000000000..d94e2deb7 --- /dev/null +++ b/src/windows/wshelper/resource.rc @@ -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 index 000000000..6916dbc72 --- /dev/null +++ b/src/windows/wshelper/string.rc @@ -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 index 000000000..f927fb195 --- /dev/null +++ b/src/windows/wshelper/ver.rc.inc @@ -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 index 000000000..cc3a948b8 --- /dev/null +++ b/src/windows/wshelper/version.rc @@ -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 index 000000000..0041d004e --- /dev/null +++ b/src/windows/wshelper/wsh-int.h @@ -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 index 000000000..b0a5aeaaf --- /dev/null +++ b/src/windows/wshelper/wshelp32.def @@ -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 index 000000000..e28dd16cf --- /dev/null +++ b/src/windows/wshelper/wshelp64.def @@ -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 index 000000000..5b67a3d60 --- /dev/null +++ b/src/windows/wshelper/wshelper.def @@ -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