diff options
| author | Sam Hartman <hartmans@mit.edu> | 2011-09-28 20:57:53 +0000 |
|---|---|---|
| committer | Sam Hartman <hartmans@mit.edu> | 2011-09-28 20:57:53 +0000 |
| commit | 17ffebf7ff813118f15d7346e0211089fe2e95f0 (patch) | |
| tree | 9f88a39d8bbfd6589eb8cc9272fc759664eff953 /src/util/wshelper | |
| parent | 0a13c0a9bfd1a7cff850d60851500aea34dffa6d (diff) | |
| download | krb5-17ffebf7ff813118f15d7346e0211089fe2e95f0.tar.gz krb5-17ffebf7ff813118f15d7346e0211089fe2e95f0.tar.xz krb5-17ffebf7ff813118f15d7346e0211089fe2e95f0.zip | |
Windows fixes: enable DNS lookups; turn on KDC lookup by default
Moved wshelper from windows to util to fix build order dependencies.
Signed-off-by: Kevin Wasserman <kevin.wasserman@painless-security.com>
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25273 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/util/wshelper')
| -rw-r--r-- | src/util/wshelper/Makefile.in | 64 | ||||
| -rw-r--r-- | src/util/wshelper/dllmain.c | 264 | ||||
| -rw-r--r-- | src/util/wshelper/gethna.c | 477 | ||||
| -rw-r--r-- | src/util/wshelper/hesiod.c | 359 | ||||
| -rw-r--r-- | src/util/wshelper/hesmailh.c | 87 | ||||
| -rw-r--r-- | src/util/wshelper/hespwnam.c | 196 | ||||
| -rw-r--r-- | src/util/wshelper/hesservb.c | 137 | ||||
| -rw-r--r-- | src/util/wshelper/inetaton.c | 153 | ||||
| -rw-r--r-- | src/util/wshelper/pwd.h | 15 | ||||
| -rw-r--r-- | src/util/wshelper/res_comp.c | 361 | ||||
| -rw-r--r-- | src/util/wshelper/res_init.c | 814 | ||||
| -rw-r--r-- | src/util/wshelper/res_quer.c | 561 | ||||
| -rw-r--r-- | src/util/wshelper/resource.h | 29 | ||||
| -rw-r--r-- | src/util/wshelper/resource.rc | 64 | ||||
| -rw-r--r-- | src/util/wshelper/string.rc | 29 | ||||
| -rw-r--r-- | src/util/wshelper/ver.rc.inc | 57 | ||||
| -rw-r--r-- | src/util/wshelper/wsh-int.h | 5 | ||||
| -rw-r--r-- | src/util/wshelper/wshelp32.def | 33 | ||||
| -rw-r--r-- | src/util/wshelper/wshelp64.def | 33 | ||||
| -rw-r--r-- | src/util/wshelper/wshelper.def | 42 |
20 files changed, 3780 insertions, 0 deletions
diff --git a/src/util/wshelper/Makefile.in b/src/util/wshelper/Makefile.in new file mode 100644 index 000000000..3da2b5994 --- /dev/null +++ b/src/util/wshelper/Makefile.in @@ -0,0 +1,64 @@ +BUILDTOP=..\.. + +DLL_NAME=wshelp32 +DEF_FILE=wshelp32.def + +# Use 64-bit DLL_NAME and DEF_FILE on 64-bit platforms +!if ("$(CPU)" == "IA64") || ("$(CPU)" == "AMD64") || ("$(CPU)" == "ALPHA64") +DLL_NAME=wshelp64 +DEF_FILE=wshelp64.def +!endif + + +OBJS= $(OUTPRE)dllmain.$(OBJEXT) \ + $(OUTPRE)gethna.$(OBJEXT) \ + $(OUTPRE)hesiod.$(OBJEXT) \ + $(OUTPRE)hesmailh.$(OBJEXT) \ + $(OUTPRE)hespwnam.$(OBJEXT) \ + $(OUTPRE)hesservb.$(OBJEXT) \ + $(OUTPRE)inetaton.$(OBJEXT) \ + $(OUTPRE)res_comp.$(OBJEXT) \ + $(OUTPRE)res_init.$(OBJEXT) \ + $(OUTPRE)res_quer.$(OBJEXT) + +RESFILE = $(OUTPRE)resource.res +XOBJS = $(RESFILE) + +RCFLAGS = -I$(BUILDTOP)\include -I$(BUILDTOP) -DWSHELPER_LIB + +###From another project inside K 1.9: +###VERSIONRC = $(BUILDTOP)\windows\version.rc +###RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + + +# Set NODEBUG if building release instead of debug + +LOCALINCLUDES = -I$(BUILDTOP)\include + +WINLIBS = advapi32.lib user32.lib ws2_32.lib dnsapi.lib + +WINDLLFLAGS = /nologo /dll /incremental:no /release $(LOPTS) + +DEFINES = -DUNICODE -D_UNICODE +!ifdef NODEBUG +DEFINES = $(DEFINES) +!else +DEFINES = $(DEFINES) -DDBG +!endif + +all-windows:: +all-windows:: $(OUTPRE)$(DLL_NAME).dll + +clean-windows:: + $(RM) $(OUTPRE)$(DLL_NAME).dll + +$(OUTPRE)$(DLL_NAME).dll: $(DEF_FILE) $(OBJS) $(XOBJS) + link $(WINDLLFLAGS) -def:$(DEF_FILE) -out:$*.dll \ + $(OBJS) $(XOBJS) $(WINLIBS) $(SCLIB) + $(_VC_MANIFEST_EMBED_DLL) + +$(OUTPRE)dllmain.$(OBJEXT): pwd.h +$(OUTPRE)hespwnam.$(OBJEXT): pwd.h +$(OUTPRE)dllmain.$(OBJEXT): wsh-int.h +$(OUTPRE)res_init.$(OBJEXT): wsh-int.h +$(RESFILE): resource.rc ../../windows/version.rc ../../windows/kerberos.ver diff --git a/src/util/wshelper/dllmain.c b/src/util/wshelper/dllmain.c new file mode 100644 index 000000000..5ae0016e6 --- /dev/null +++ b/src/util/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/util/wshelper/gethna.c b/src/util/wshelper/gethna.c new file mode 100644 index 000000000..8914c3270 --- /dev/null +++ b/src/util/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/util/wshelper/hesiod.c b/src/util/wshelper/hesiod.c new file mode 100644 index 000000000..b448849cf --- /dev/null +++ b/src/util/wshelper/hesiod.c @@ -0,0 +1,359 @@ +/* + @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 <stdlib.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/util/wshelper/hesmailh.c b/src/util/wshelper/hesmailh.c new file mode 100644 index 000000000..32791e8d6 --- /dev/null +++ b/src/util/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/util/wshelper/hespwnam.c b/src/util/wshelper/hespwnam.c new file mode 100644 index 000000000..55ddf01c1 --- /dev/null +++ b/src/util/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/util/wshelper/hesservb.c b/src/util/wshelper/hesservb.c new file mode 100644 index 000000000..01db3a4bf --- /dev/null +++ b/src/util/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/util/wshelper/inetaton.c b/src/util/wshelper/inetaton.c new file mode 100644 index 000000000..bc7bd09a0 --- /dev/null +++ b/src/util/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/util/wshelper/pwd.h b/src/util/wshelper/pwd.h new file mode 100644 index 000000000..6954fd77d --- /dev/null +++ b/src/util/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/util/wshelper/res_comp.c b/src/util/wshelper/res_comp.c new file mode 100644 index 000000000..36cd77372 --- /dev/null +++ b/src/util/wshelper/res_comp.c @@ -0,0 +1,361 @@ +/* + * + * @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 +__putshort(register u_short s, register u_char *msgp) +{ + msgp[1] = LOBYTE(s); + msgp[0] = HIBYTE(s); +} + +void +__putlong(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/util/wshelper/res_init.c b/src/util/wshelper/res_init.c new file mode 100644 index 000000000..bf3d97b50 --- /dev/null +++ b/src/util/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/util/wshelper/res_quer.c b/src/util/wshelper/res_quer.c new file mode 100644 index 000000000..7836ed921 --- /dev/null +++ b/src/util/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 0x8000 + +#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/util/wshelper/resource.h b/src/util/wshelper/resource.h new file mode 100644 index 000000000..cc5f082ff --- /dev/null +++ b/src/util/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/util/wshelper/resource.rc b/src/util/wshelper/resource.rc new file mode 100644 index 000000000..3fb14771e --- /dev/null +++ b/src/util/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 ""..\\..\\windows\\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 "..\..\windows\version.rc" +#include "string.rc" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/src/util/wshelper/string.rc b/src/util/wshelper/string.rc new file mode 100644 index 000000000..6916dbc72 --- /dev/null +++ b/src/util/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/util/wshelper/ver.rc.inc b/src/util/wshelper/ver.rc.inc new file mode 100644 index 000000000..f927fb195 --- /dev/null +++ b/src/util/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/util/wshelper/wsh-int.h b/src/util/wshelper/wsh-int.h new file mode 100644 index 000000000..04b1cfe57 --- /dev/null +++ b/src/util/wshelper/wsh-int.h @@ -0,0 +1,5 @@ +void res_init_startup(); +void res_init_cleanup(); + +void __putshort(register u_short s, register u_char *msgp); +void __putlong(register u_long l, register u_char *msgp); diff --git a/src/util/wshelper/wshelp32.def b/src/util/wshelper/wshelp32.def new file mode 100644 index 000000000..b0a5aeaaf --- /dev/null +++ b/src/util/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/util/wshelper/wshelp64.def b/src/util/wshelper/wshelp64.def new file mode 100644 index 000000000..e28dd16cf --- /dev/null +++ b/src/util/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/util/wshelper/wshelper.def b/src/util/wshelper/wshelper.def new file mode 100644 index 000000000..5b67a3d60 --- /dev/null +++ b/src/util/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 |
