diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libresolv2 | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libresolv2')
443 files changed, 90498 insertions, 0 deletions
diff --git a/usr/src/lib/libresolv2/Makefile b/usr/src/lib/libresolv2/Makefile new file mode 100644 index 0000000000..cfb4e5d6d9 --- /dev/null +++ b/usr/src/lib/libresolv2/Makefile @@ -0,0 +1,114 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/Makefile +# + +include ../../Makefile.master +include ../Makefile.lib + +MANIFEST= client.xml +MANIFESTDIR= $(ROOT)/var/svc/manifest/network/dns +ROOTMANIFEST= $(MANIFEST:%=$(MANIFESTDIR)/%) + +$(ROOTMANIFEST) := FILEMODE = 444 +$(ROOTMANIFEST) := OWNER = root +$(ROOTMANIFEST) := GROUP = bin + +CHKMANIFEST= $(MANIFEST:%.xml=%.xmlchk) + +SUBDIRS= include spec $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) +SUBDIRS += .WAIT irs + +# EXPORT DELETE START +# CRYPT DELETE START +SUBDIRS += cylink dnssafe +# CRYPT DELETE END +# EXPORT DELETE END + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +lint := TARGET= lint +_msg := TARGET= _msg + +LIBRARY= libresolv.a +TEXT_DOMAIN= SUNW_OST_OSLIB +XGETFLAGS= -a +POFILE= $(LIBRARY:.a=.po) +POFILES= generic.po + +SED= sed +GREP= grep +CP= cp + +.KEEP_STATE: + +all clean clobber lint: $(SUBDIRS) + +install: $(SUBDIRS) $(ROOTMANIFEST) + +$(ROOTMANIFEST): $(MANIFESTDIR) + +$(MANIFESTDIR): + $(INS.dir) + +$(MANIFESTDIR)/%: % + $(INS.file) + +# install rule for install_h target +$(ROOTHDRDIR)/%: % + $(INS.file) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) $(CHKMANIFEST) + +# EXPORT DELETE START +# CRYPT DELETE START +# Special targets to clean up the source tree for export distribution +# Warning: These target change the source tree +EXPORT_SRC: + $(RM) Makefile+ + $(SED) -e "/^# EXPORT DELETE START/,/^# EXPORT DELETE END/d" \ + < Makefile > Makefile+ + $(MV) Makefile+ Makefile + $(CHMOD) 444 Makefile + /usr/bin/find cylink dnssafe common/cylink common/dnssafe \ + -name SCCS -prune -o -type f -exec $(RM) {} \; + +CRYPT_SRC: + $(RM) Makefile+ + $(SED) -e "/^# CRYPT DELETE START/,/^# CRYPT DELETE END/d" \ + < Makefile > Makefile+ + $(MV) Makefile+ Makefile + $(CHMOD) 444 Makefile + /usr/bin/find cylink dnssafe common/cylink common/dnssafe \ + -name SCCS -prune -o -type f -exec $(RM) {} \; + +# CRYPT DELETE END +# EXPORT DELETE END + +_msg: $(MSGDOMAIN) $(POFILE) + $(RM) $(MSGDOMAIN)/$(POFILE) + $(CP) $(POFILE) $(MSGDOMAIN) + +$(POFILE): $(POFILES) + $(RM) $@ + $(CAT) $(POFILES) > $@ + +$(POFILES): + $(RM) messages.po + $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]* + $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ + $(RM) messages.po + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET); echo + +FRC: diff --git a/usr/src/lib/libresolv2/Makefile.com b/usr/src/lib/libresolv2/Makefile.com new file mode 100644 index 0000000000..e2a59c440f --- /dev/null +++ b/usr/src/lib/libresolv2/Makefile.com @@ -0,0 +1,177 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/Makefile.com +# + +LIBRARY= libresolv.a +VERS= .2 + +BSDOBJS= daemon.o putenv.o strcasecmp.o strsep.o \ + ftruncate.o readv.o strdup.o strtoul.o \ + gettimeofday.o setenv.o strerror.o utimes.o \ + mktemp.o setitimer.o strpbrk.o writev.o + +DSTOBJS= dst_api.o prandom.o support.o + +DSTLINKOBJS= bsafe_link.o cylink_link.o eay_dss_link.o hmac_link.o \ + rsaref_link.o + +INETOBJS= inet_net_pton.o inet_ntop.o \ + inet_neta.o inet_pton.o inet_lnaof.o inet_netof.o \ + nsap_addr.o inet_makeaddr.o inet_network.o \ + inet_net_ntop.o inet_ntoa.o inet_cidr_ntop.o \ + inet_cidr_pton.o inet_data.o + +IRSOBJS= dns.o gen_ho.o getnetgrent.o lcl_ng.o \ + nis_nw.o dns_gr.o gen_ng.o getprotoent.o \ + lcl_nw.o nis_pr.o dns_ho.o gen_nw.o \ + getpwent.o lcl_pr.o nis_pw.o dns_nw.o \ + gen_pr.o getservent.o lcl_pw.o nis_sv.o \ + dns_pr.o gen_pw.o hesiod.o lcl_sv.o \ + nul_ng.o dns_pw.o gen_sv.o irs_data.o \ + nis.o util.o dns_sv.o getgrent.o \ + lcl.o nis_gr.o gen.o gethostent.o \ + lcl_gr.o nis_ho.o gen_gr.o getnetent.o \ + lcl_ho.o nis_ng.o getpwent_r.o \ + getservent_r.o gai_strerror.o getgrent_r.o \ + gethostent_r.o getnetent_r.o getnetgrent_r.o \ + getprotoent_r.o getnameinfo.o irp.o irpmarshall.o \ + irp_ho.o irp_nw.o irp_pr.o irp_sv.o \ + irp_gr.o irp_ng.o irp_pw.o + +IRSRESOBJS= dns.o gen_ho.o lcl_ng.o dns_gr.o \ + gen_ng.o lcl_nw.o dns_ho.o gen_nw.o \ + lcl_pr.o dns_nw.o gen_pr.o lcl_pw.o \ + dns_pr.o gen_pw.o hesiod.o lcl_sv.o \ + nul_ng.o dns_pw.o gen_sv.o irs_data.o \ + util.o dns_sv.o lcl.o gen.o \ + gethostent.o lcl_gr.o gen_gr.o lcl_ho.o \ + gethostent_r.o getaddrinfo.o + +IRSDYNOBJS= nis_nw.o nis_pr.o nis_pw.o nis_sv.o \ + nis.o nis_gr.o nis_ho.o nis_ng.o \ + irp.o irpmarshall.o irp_ho.o irp_nw.o \ + irp_pr.o irp_sv.o irp_gr.o irp_ng.o \ + irp_pw.o getnetent.o getpwent_r.o getgrent_r.o \ + getservent_r.o getnetent_r.o getnetgrent_r.o getgrent.o \ + getnetgrent.o getprotoent.o getpwent.o getservent.o \ + getprotoent_r.o getnameinfo.o gai_strerror.o + +ISCOBJS= base64.o ev_files.o ev_waits.o logging.o \ + bitncmp.o ev_streams.o eventlib.o tree.o \ + ev_connects.o ev_timers.o heap.o assertions.o \ + memcluster.o ctl_p.o ctl_clnt.o ctl_srvr.o \ + hex.o + +NAMESEROBJS= ns_name.o ns_netint.o ns_parse.o ns_print.o \ + ns_ttl.o ns_sign.o ns_verify.o ns_date.o \ + ns_samedomain.o + +RESOLVOBJS= herror.o res_debug.o res_data.o res_comp.o \ + res_init.o res_mkquery.o res_mkupdate.o res_query.o \ + res_send.o res_update.o res_sendsigned.o \ + res_findzonecut.o + +SUNWOBJS= sunw_mtctxres.o sunw_dst_init.o sunw_irs_init.o sunw_updrec.o + +OBJECTS= $(BSDOBJS) $(DSTOBJS) $(INETOBJS) $(IRSRESOBJS) $(ISCOBJS) \ + $(NAMESEROBJS) $(RESOLVOBJS) $(SUNWOBJS) + +# include library definitions +include ../../Makefile.lib + +# install this library in the root filesystem +include ../../Makefile.rootfs + +MAPFILE= $(MAPDIR)/mapfile +MAPFILES= $(MAPFILE) ../common/mapfile-vers +MAPOPTS= $(MAPFILES:%=-M%) + +SRCS= $(BSDOBJS:%.o=../common/bsd/%.c) \ + $(DSTOBJS:%.o=../common/dst/%.c) \ + $(INETOBJS:%.o=../common/inet/%.c) \ + $(IRSRESOBJS:%.o=../common/irs/%.c) \ + $(ISCOBJS:%.o=../common/isc/%.c) \ + $(NAMESEROBJS:%.o=../common/nameser/%.c) \ + $(RESOLVOBJS:%.o=../common/resolv/%.c) \ + $(SUNWOBJS:%.o=../common/sunw/%.c) + +LIBS = $(DYNLIB) $(LINTLIB) + +$(LINTLIB):= SRCS = ../common/llib-lresolv + +# Local Libresolv definitions +SOLCOMPAT = -Dgethostbyname=res_gethostbyname \ + -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \ + -Dgethostbyname2=res_gethostbyname2\ + -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \ + -Dendhostent=res_endhostent -Dgethostent=res_gethostent \ + -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \ + -Dgetnetent=res_getnetent -Dsocket=_socket \ + -Dgetipnodebyname=res_getipnodebyname \ + -Dgetipnodebyaddr=res_getipnodebyaddr \ + -Dfreehostent=res_freehostent \ + -Dgetaddrinfo=res_getaddrinfo \ + -Dfreeaddrinfo=res_freeaddrinfo + +CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE + +LOCFLAGS += $(CRYPTFLAGS) +LOCFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \ + $(SOLCOMPAT) -I../include + +CPPFLAGS += $(LOCFLAGS) +DYNFLAGS += $(MAPOPTS) $(ZNODELETE) +LDLIBS += -lsocket -lnsl -lc + +.KEEP_STATE: + +lint: lintcheck + +$(DYNLIB): $(MAPFILES) + +$(MAPFILE): + @cd $(MAPDIR); $(MAKE) mapfile + +# include library targets +include ../../Makefile.targ + +pics/%.o: ../common/bsd/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/dst/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/inet/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/irs/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/isc/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/nameser/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/resolv/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/sunw/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +# install rule for lint library target +$(ROOTLINTDIR)/%: ../common/% + $(INS.file) diff --git a/usr/src/lib/libresolv2/amd64/Makefile b/usr/src/lib/libresolv2/amd64/Makefile new file mode 100644 index 0000000000..682f635c8c --- /dev/null +++ b/usr/src/lib/libresolv2/amd64/Makefile @@ -0,0 +1,19 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +MAPDIR= ../spec/amd64 + +include ../Makefile.com +include ../../Makefile.lib.64 + +LIBS = $(DYNLIB) $(LINTLIB) + +.KEEP_STATE: + +all: $(LIBS) + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libresolv2/client.xml b/usr/src/lib/libresolv2/client.xml new file mode 100644 index 0000000000..e077e4f8fb --- /dev/null +++ b/usr/src/lib/libresolv2/client.xml @@ -0,0 +1,98 @@ +<?xml version="1.0"?> +<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> +<!-- + Copyright 2004 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + ident "%Z%%M% %I% %E% SMI" + + NOTE: This service manifest is not editable; its contents will + be overwritten by package or patch operations, including + operating system upgrade. Make customizations in a different + file. +--> + +<service_bundle type='manifest' name='SUNWcsr:dns-client'> + +<service + name='network/dns/client' + type='service' + version='1'> + + <create_default_instance enabled='false' /> + + <single_instance /> + + <dependency + name='usr' + grouping='require_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/system/filesystem/minimal' /> + </dependency> + + <!-- + Wait for potential DHCP modification of resolv.conf. + --> + <dependency + name='net' + grouping='require_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/network/service' /> + </dependency> + + <dependency + name='config_data' + grouping='require_all' + restart_on='none' + type='path'> + <service_fmri + value='file://localhost/etc/resolv.conf' /> + </dependency> + + <dependency + name='loopback' + grouping='require_any' + restart_on='error' + type='service'> + <service_fmri value='svc:/network/loopback' /> + </dependency> + + <dependency + name='network' + grouping='optional_all' + restart_on='error' + type='service'> + <service_fmri value='svc:/milestone/network' /> + </dependency> + + <exec_method + type='method' + name='start' + exec=':true' + timeout_seconds='10' /> + + <exec_method + type='method' + name='stop' + exec=':true' + timeout_seconds='10' /> + + <stability value='Unstable' /> + + <template> + <common_name> + <loctext xml:lang='C'> + DNS resolver + </loctext> + </common_name> + <documentation> + <manpage title='resolver' section='3RESOLV' + manpath='/usr/share/man' /> + </documentation> + </template> + +</service> + +</service_bundle> diff --git a/usr/src/lib/libresolv2/common/bsd/daemon.c b/usr/src/lib/libresolv2/common/bsd/daemon.c new file mode 100644 index 0000000000..aeb4f2c083 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/daemon.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: daemon.c,v 8.2 1999/10/13 16:39:20 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 1993 + * The 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <fcntl.h> +#include <paths.h> +#include <unistd.h> + +#include "port_after.h" + +#ifndef NEED_DAEMON +int __bind_daemon__; +#else + +int +daemon(int nochdir, int noclose) { + int fd; + + switch (fork()) { + case -1: + return (-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return (-1); + + if (!nochdir) + (void)chdir("/"); + + if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + (void)dup2(fd, STDIN_FILENO); + (void)dup2(fd, STDOUT_FILENO); + (void)dup2(fd, STDERR_FILENO); + if (fd > 2) + (void)close (fd); + } + return (0); +} +#endif diff --git a/usr/src/lib/libresolv2/common/bsd/ftruncate.c b/usr/src/lib/libresolv2/common/bsd/ftruncate.c new file mode 100644 index 0000000000..98b953b312 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/ftruncate.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef LINT +static const char rcsid[] = "$Id: ftruncate.c,v 8.4 1999/10/13 16:39:21 vixie Exp $"; +#endif + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * ftruncate - set file size, BSD Style + * + * shortens or enlarges the file as neeeded + * uses some undocumented locking call. It is known to work on SCO unix, + * other vendors should try. + * The #error directive prevents unsupported OSes + */ + +#include "port_before.h" + +#if defined(M_UNIX) +#define OWN_FTRUNCATE +#include <stdio.h> +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif +#ifdef _POSIX_SOURCE +#undef _POSIX_SOURCE +#endif + +#include <fcntl.h> + +#include "port_after.h" + +int +__ftruncate(int fd, long wantsize) { + long cursize; + + /* determine current file size */ + if ((cursize = lseek(fd, 0L, 2)) == -1) + return (-1); + + /* maybe lengthen... */ + if (cursize < wantsize) { + if (lseek(fd, wantsize - 1, 0) == -1 || + write(fd, "", 1) == -1) { + return (-1); + } + return (0); + } + + /* maybe shorten... */ + if (wantsize < cursize) { + struct flock fl; + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = wantsize; + fl.l_type = F_WRLCK; + return (fcntl(fd, F_FREESP, &fl)); + } + return (0); +} +#endif + +#ifndef OWN_FTRUNCATE +int __bindcompat_ftruncate; +#endif diff --git a/usr/src/lib/libresolv2/common/bsd/gettimeofday.c b/usr/src/lib/libresolv2/common/bsd/gettimeofday.c new file mode 100644 index 0000000000..68b5ca39a0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/gettimeofday.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef LINT +static const char rcsid[] = "$Id: gettimeofday.c,v 8.4 1999/10/13 16:39:21 vixie Exp $"; +#endif + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" +#include "port_after.h" + +#if !defined(NEED_GETTIMEOFDAY) +int __bindcompat_gettimeofday; +#else +int +gettimeofday(struct timeval *tvp, struct _TIMEZONE *tzp) { + time_t clock, time(time_t *); + + if (time(&clock) == (time_t) -1) + return (-1); + if (tvp) { + tvp->tv_sec = clock; + tvp->tv_usec = 0; + } + if (tzp) { + tzp->tz_minuteswest = 0; + tzp->tz_dsttime = 0; + } + return (0); +} +#endif /*NEED_GETTIMEOFDAY*/ diff --git a/usr/src/lib/libresolv2/common/bsd/mktemp.c b/usr/src/lib/libresolv2/common/bsd/mktemp.c new file mode 100644 index 0000000000..b29ae93d51 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/mktemp.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: mktemp.c,v 8.4 1999/10/13 16:39:21 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> + +#include "port_after.h" + +#if (!defined(NEED_MKTEMP)) && (!defined(NEED_MKSTEMP)) +int __mktemp_unneeded__; +#else + +static int gettemp(char *path, int *doopen); + +#ifdef NEED_MKSTEMP +mkstemp(char *path) { + int fd; + + return (gettemp(path, &fd) ? fd : -1); +} +#endif + +#ifdef NEED_MKTEMP +char * +mktemp(char *path) { + return(gettemp(path, (int *)NULL) ? path : (char *)NULL); +} +#endif + +static int +gettemp(char *path, int *doopen) { + char *start, *trv; + struct stat sbuf; + u_int pid; + + pid = getpid(); + for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) + return(1); + if (errno != EEXIST) + return(0); + } + else if (stat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return(0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} + +#endif /*NEED_MKTEMP*/ diff --git a/usr/src/lib/libresolv2/common/bsd/putenv.c b/usr/src/lib/libresolv2/common/bsd/putenv.c new file mode 100644 index 0000000000..08ef44463e --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/putenv.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef LINT +static const char rcsid[] = "$Id: putenv.c,v 8.4 1999/10/13 16:39:21 vixie Exp $"; +#endif + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" +#include "port_after.h" + +/* + * To give a little credit to Sun, SGI, + * and many vendors in the SysV world. + */ + +#if !defined(NEED_PUTENV) +int __bindcompat_putenv; +#else +int +putenv(char *str) { + char *tmp; + + for (tmp = str; *tmp && (*tmp != '='); tmp++) + ; + + return (setenv(str, tmp, 1)); +} +#endif diff --git a/usr/src/lib/libresolv2/common/bsd/readv.c b/usr/src/lib/libresolv2/common/bsd/readv.c new file mode 100644 index 0000000000..5852e2e20a --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/readv.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef LINT +static const char rcsid[] = "$Id: readv.c,v 8.2 1999/10/13 16:39:21 vixie Exp $"; +#endif + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include "port_after.h" + +#ifndef NEED_READV +int __bindcompat_readv; +#else + +int +__readv(fd, vp, vpcount) + int fd; + const struct iovec *vp; + int vpcount; +{ + int count = 0; + + while (vpcount-- > 0) { + int bytes = read(fd, vp->iov_base, vp->iov_len); + + if (bytes < 0) + return (-1); + count += bytes; + if (bytes != vp->iov_len) + break; + vp++; + } + return (count); +} +#endif /* NEED_READV */ diff --git a/usr/src/lib/libresolv2/common/bsd/setenv.c b/usr/src/lib/libresolv2/common/bsd/setenv.c new file mode 100644 index 0000000000..963d0e6e1b --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/setenv.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1997, by Sun Microsystems, Inc. + * All rights reserved. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: setenv.c,v 8.4 1997/04/24 22:00:38 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 1993 + * The 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. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#if !defined(NEED_SETENV) +int __bindcompat_setenv; +#else + +extern char **environ; + +static char *findenv(const char *name, int *offset); + +/* + * setenv -- + * Set the value of the environmental variable "name" to be + * "value". If rewrite is set, replace any current value. + */ +setenv(const char *name, const char *value, int rewrite) { + extern char **environ; + static int alloced; /* if allocated space before */ + char *c; + int l_value, offset; + + if (*value == '=') /* no `=' in value */ + ++value; + l_value = strlen(value); + if ((c = findenv(name, &offset))) { /* find if already exists */ + if (!rewrite) + return (0); + if (strlen(c) >= l_value) { /* old larger; copy over */ + while (*c++ = *value++); + return (0); + } + } else { /* create new slot */ + int cnt; + char **p; + + for (p = environ, cnt = 0; *p; ++p, ++cnt); + if (alloced) { /* just increase size */ + environ = (char **)realloc((char *)environ, + (size_t)(sizeof(char *) * (cnt + 2))); + if (!environ) + return (-1); + } + else { /* get new space */ + alloced = 1; /* copy old entries into it */ + p = malloc((size_t)(sizeof(char *) * (cnt + 2))); + if (!p) + return (-1); + memcpy(p, environ, cnt * sizeof(char *)); + environ = p; + } + environ[cnt + 1] = NULL; + offset = cnt; + } + for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */ + if (!(environ[offset] = /* name + `=' + value */ + malloc((size_t)((int)(c - name) + l_value + 2)))) + return (-1); + for (c = environ[offset]; (*c = *name++) && *c != '='; ++c); + for (*c++ = '='; *c++ = *value++;); + return (0); +} + +/* + * unsetenv(name) -- + * Delete environmental variable "name". + */ +void +unsetenv(const char *name) { + char **p; + int offset; + + while (findenv(name, &offset)) /* if set multiple times */ + for (p = &environ[offset];; ++p) + if (!(*p = *(p + 1))) + break; +} + +/* + * findenv -- + * Returns pointer to value associated with name, if any, else NULL. + * Sets offset to be the offset of the name/value combination in the + * environmental array, for use by setenv(3) and unsetenv(3). + * Explicitly removes '=' in argument name. + * + * This routine *should* be a static; don't use it. + */ +static char * +findenv(const char *name, int *offset) { + const char *np; + char **p, *c; + int len; + + if (name == NULL || environ == NULL) + return (NULL); + for (np = name; *np && *np != '='; ++np) + continue; + len = np - name; + for (p = environ; (c = *p) != NULL; ++p) + if (strncmp(c, name, len) == 0 && c[len] == '=') { + *offset = p - environ; + return (c + len + 1); + } + return (NULL); +} +#endif diff --git a/usr/src/lib/libresolv2/common/bsd/setitimer.c b/usr/src/lib/libresolv2/common/bsd/setitimer.c new file mode 100644 index 0000000000..a0185c9c1d --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/setitimer.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef LINT +static const char rcsid[] = "$Id: setitimer.c,v 8.4 1999/10/13 16:39:21 vixie Exp $"; +#endif + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/time.h> + +#include "port_after.h" + +/* + * Setitimer emulation routine. + */ +#ifndef NEED_SETITIMER +int __bindcompat_setitimer; +#else + +int +__setitimer(int which, const struct itimerval *value, + struct itimerval *ovalue) +{ + if (alarm(value->it_value.tv_sec) >= 0) + return (0); + else + return (-1); +} +#endif diff --git a/usr/src/lib/libresolv2/common/bsd/strcasecmp.c b/usr/src/lib/libresolv2/common/bsd/strcasecmp.c new file mode 100644 index 0000000000..69e71760f0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/strcasecmp.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strcasecmp.c,v 8.5 1999/10/13 16:39:21 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 1993 + * The 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. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/cdefs.h> + +#include <string.h> + +#include "port_after.h" + +#ifndef NEED_STRCASECMP +int __strcasecmp_unneeded__; +#else + +/* + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ascii character sequences. + */ +static const u_char charmap[] = { + 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, + 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, + 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, + 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, + 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, + 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, + 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, + 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, + 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 +}; + +int +strcasecmp(const char *s1, const char *s2) { + const u_char *cm = charmap, + *us1 = (const u_char *)s1, + *us2 = (const u_char *)s2; + + while (cm[*us1] == cm[*us2++]) + if (*us1++ == '\0') + return (0); + return (cm[*us1] - cm[*--us2]); +} + +int +strncasecmp(const char *s1, const char *s2, size_t n) { + if (n != 0) { + const u_char *cm = charmap, + *us1 = (const u_char *)s1, + *us2 = (const u_char *)s2; + + do { + if (cm[*us1] != cm[*us2++]) + return (cm[*us1] - cm[*--us2]); + if (*us1++ == '\0') + break; + } while (--n != 0); + } + return (0); +} + +#endif /*NEED_STRCASECMP*/ diff --git a/usr/src/lib/libresolv2/common/bsd/strdup.c b/usr/src/lib/libresolv2/common/bsd/strdup.c new file mode 100644 index 0000000000..d92ed9e91d --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/strdup.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1997, by Sun Microsystems, Inc. + * All rights reserved. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <stdlib.h> + +#include "port_after.h" + +#ifndef NEED_STRDUP +int __bind_strdup_unneeded; +#else +char * +strdup(const char *src) { + char *dst = malloc(strlen(src) + 1); + + if (dst) + strcpy(dst, src); + return (dst); +} +#endif diff --git a/usr/src/lib/libresolv2/common/bsd/strerror.c b/usr/src/lib/libresolv2/common/bsd/strerror.c new file mode 100644 index 0000000000..4d650edfc1 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/strerror.c @@ -0,0 +1,97 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strerror.c,v 8.7 2001/08/28 11:48:10 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1988, 1993 + * The 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/types.h> + +#include <string.h> + +#include "port_after.h" + +#ifndef NEED_STRERROR +int __strerror_unneeded__; +#else + +#ifdef USE_SYSERROR_LIST +extern int sys_nerr; +extern char *sys_errlist[]; +#endif + +const char * +isc_strerror(int num) { +#define UPREFIX "Unknown error: " + static char ebuf[40] = UPREFIX; /* 64-bit number + slop */ + u_int errnum; + char *p, *t; + const char *ret; + char tmp[40]; + + errnum = num; /* convert to unsigned */ +#ifdef USE_SYSERROR_LIST + if (errnum < sys_nerr) + return (sys_errlist[errnum]); +#else +#undef strerror + ret = strerror(num); /* call strerror() in libc */ + if (ret != NULL) + return(ret); +#endif + + /* Do this by hand, so we don't include stdio(3). */ + t = tmp; + do { + *t++ = "0123456789"[errnum % 10]; + } while (errnum /= 10); + for (p = ebuf + sizeof(UPREFIX) - 1;;) { + *p++ = *--t; + if (t <= tmp) + break; + } + return (ebuf); +} + +#endif /*NEED_STRERROR*/ diff --git a/usr/src/lib/libresolv2/common/bsd/strpbrk.c b/usr/src/lib/libresolv2/common/bsd/strpbrk.c new file mode 100644 index 0000000000..d001f28d31 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/strpbrk.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strpbrk.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strpbrk.c,v 8.4 1999/10/13 16:39:21 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1985, 1993 + * The 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. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/cdefs.h> + +#include <string.h> + +#include "port_after.h" + +#ifndef NEED_STRPBRK +int __strpbrk_unneeded__; +#else + +/* + * Find the first occurrence in s1 of a character in s2 (excluding NUL). + */ +char * +strpbrk(const char *s1, const char *s2) { + const char *scanp; + int c, sc; + + while ((c = *s1++) != 0) { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + return ((char *)(s1 - 1)); + } + return (NULL); +} + +#endif /*NEED_STRPBRK*/ diff --git a/usr/src/lib/libresolv2/common/bsd/strsep.c b/usr/src/lib/libresolv2/common/bsd/strsep.c new file mode 100644 index 0000000000..bbbdf3bc75 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/strsep.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1997, by Sun Microsystems, Inc. + * All rights reserved. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "strsep.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strsep.c,v 8.5 1996/11/18 09:09:04 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 1993 + * The 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" +#include <sys/cdefs.h> +#include <string.h> +#include <stdio.h> +#include "port_after.h" + +#ifndef NEED_STRSEP +int __strsep_unneeded__; +#else + +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char * +strsep(char **stringp, const char *delim) { + char *s; + const char *spanp; + int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +#endif /*NEED_STRSEP*/ diff --git a/usr/src/lib/libresolv2/common/bsd/strtoul.c b/usr/src/lib/libresolv2/common/bsd/strtoul.c new file mode 100644 index 0000000000..41e23c1124 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/strtoul.c @@ -0,0 +1,125 @@ +/* + * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strtoul.c,v 8.5 2002/07/06 02:35:04 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 1993 + * The 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. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifndef NEED_STRTOUL +int __strtoul_unneeded__; +#else + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +u_long +strtoul(const char *nptr, char **endptr, int base) { + const char *s = nptr; + u_long acc, cutoff; + int neg, c, any, cutlim; + + neg = 0; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *(unsigned char *)s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (u_long)ULONG_MAX / (u_long)base; + cutlim = (u_long)ULONG_MAX % (u_long)base; + for (acc = 0, any = 0;; c = *(unsigned char*)s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + +#endif /*NEED_STRTOUL*/ diff --git a/usr/src/lib/libresolv2/common/bsd/utimes.c b/usr/src/lib/libresolv2/common/bsd/utimes.c new file mode 100644 index 0000000000..8a461ddbd0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/utimes.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <utime.h> + +#include "port_after.h" + +#ifndef NEED_UTIMES +int __bind_utimes_unneeded; +#else + +int +__utimes(char *filename, struct timeval *tvp) { + struct utimbuf utb; + + utb.actime = (time_t)tvp[0].tv_sec; + utb.modtime = (time_t)tvp[1].tv_sec; + return (utime(filename, &utb)); +} + +#endif /* NEED_UTIMES */ diff --git a/usr/src/lib/libresolv2/common/bsd/writev.c b/usr/src/lib/libresolv2/common/bsd/writev.c new file mode 100644 index 0000000000..e3a97a0c39 --- /dev/null +++ b/usr/src/lib/libresolv2/common/bsd/writev.c @@ -0,0 +1,95 @@ +/* + * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef LINT +static const char rcsid[] = "$Id: writev.c,v 8.6 2003/04/30 05:21:18 marka Exp $"; +#endif + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include "port_after.h" + +#ifndef NEED_WRITEV +int __bindcompat_writev; +#else + +#ifdef _CRAY +#define OWN_WRITEV +int +__writev(int fd, struct iovec *iov, int iovlen) +{ + struct stat statbuf; + + if (fstat(fd, &statbuf) < 0) + return (-1); + + /* + * Allow for atomic writes to network. + */ + if (statbuf.st_mode & S_IFSOCK) { + struct msghdr mesg; + + memset(&mesg, 0, sizeof(mesg)); + mesg.msg_name = 0; + mesg.msg_namelen = 0; + mesg.msg_iov = iov; + mesg.msg_iovlen = iovlen; + mesg.msg_accrights = 0; + mesg.msg_accrightslen = 0; + return (sendmsg(fd, &mesg, 0)); + } else { + struct iovec *tv; + int i, rcode = 0, count = 0; + + for (i = 0, tv = iov; i <= iovlen; tv++) { + rcode = write(fd, tv->iov_base, tv->iov_len); + + if (rcode < 0) + break; + + count += rcode; + } + + if (count == 0) + return (rcode); + else + return (count); + } +} + +#else /*_CRAY*/ + +int +__writev(fd, vp, vpcount) + int fd; + const struct iovec *vp; + int vpcount; +{ + int count = 0; + + while (vpcount-- > 0) { + int written = write(fd, vp->iov_base, vp->iov_len); + + if (written < 0) + return (-1); + count += written; + if (written != vp->iov_len) + break; + vp++; + } + return (count); +} + +#endif /*_CRAY*/ + +#endif /*NEED_WRITEV*/ diff --git a/usr/src/lib/libresolv2/common/cylink/bits.c b/usr/src/lib/libresolv2/common/cylink/bits.c new file mode 100644 index 0000000000..21cadf7a50 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bits.c @@ -0,0 +1,366 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: bit.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Bit Utility Functions +* +* PUBLIC FUNCTIONS: +* +* +* PRIVATE FUNCTIONS: +* +* REVISION HISTORY: +* +* +****************************************************************************/ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ +/* bn files */ +#include "port_before.h" +#include <sys/types.h> +#include "bn.h" +/* system files */ +#ifdef VXD +#include <vtoolsc.h> +#else +#include <stdlib.h> +#include <string.h> +#endif +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "c_asm.h" +#include "port_after.h" + + +/**************************************************************************** +* NAME: void RShiftL( ord *X, +* u_int32_t len_X, +* u_int32_t n_bit ) +* +* DESCRIPTION: Shift array to the right by n_bit. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int32_t len_X Length of array +* u_int32_t n_bit Number of bits +* OUTPUT: +* PARAMETERS: +* ord *X Pointer to array +* +* RETURN: +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void RShiftL_big( ord *X, + u_int32_t len_X, + u_int32_t n_bit ) +{ + +struct BigNum dest; +bnInit(); +bnBegin(&dest); + +dest.ptr = X; +dest.size = len_X; +dest.allocated = len_X; + +bnRShift(&dest,n_bit); + +} + +/**************************************************************************** +* NAME: void LShiftL( ord *X, +* u_int32_t len_X, +* u_int32_t n_bit ) +* +* DESCRIPTION: Shifts array to the left by n_bit. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int32_t len_X Length of array +* u_int32_t n_bit Number of bits +* OUTPUT: +* PARAMETERS: +* ord *X Pointer to array +* +* RETURN: +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void LShiftL_big( ord *X, + u_int32_t len_X, + u_int32_t n_bit ) +{ +struct BigNum dest; +bnInit(); +bnBegin(&dest); + +dest.ptr = X; +dest.size = len_X; +dest.allocated = len_X; + +bnLShift(&dest,n_bit); +} + +/************9**************************************************************** +* NAME: int RShiftMostBit( ord *a, +* u_int32_t len ) +* +* DESCRIPTION: Find a least significant non zero bit +* and sfift array to the right +* +* INPUTS: +* PARAMETERS: +* ord *a Pointer to array +* u_int32_t len Number of elements in number +* OUTPUT: +* +* RETURN: +* Number of shifted bits +* +* REVISION HISTORY: +* +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int RShiftMostBit( ord *a, + u_int32_t len ) +{ + +struct BigNum n; +bnInit(); +bnBegin(&n); + +n.size = len; +n.ptr = a; +n.allocated = len; + +return (bnMakeOdd(&n)); + +} + + +/**************************************************************************** +* NAME: void ByteLong (uchar *X, u_int32_t X_bytes, +* u_int32_t *Y ) +* +* +* DESCRIPTION: Transfer bytes to u_int32_t. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to byte array +* u_int32_t X_bytes Number of bytes in array +* OUTPUT: +* PARAMETERS: +* u_int32_t *Y Pointer to long arrray +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void ByteLong( uchar *X, + u_int32_t X_bytes, + u_int32_t *Y ) +{ + u_int32_t i, j; /* counters */ + for ( i = 0, j = 0; j < X_bytes; i++, j += 4) + { + Y[i] = ( (u_int32_t)X[j] ) | ( ((u_int32_t)X[j+1]) << 8 ) | + ( ((u_int32_t)X[j+2]) << 16 ) | ( ((u_int32_t)X[j+3]) << 24 ); + } +} + +/**************************************************************************** +* NAME: void ByteOrd (uchar *X, u_int32_t X_bytes, +* ord *Y ) +* +* +* DESCRIPTION: Transfer bytes to ord. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to byte array +* u_int32_t X_bytes Number of bytes in array +* OUTPUT: +* PARAMETERS: +* ord *Y Pointer to long array +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void ByteOrd( uchar *X, + u_int32_t X_bytes, + ord *Y ) +{ + u_int32_t i, j; /* counters */ + for ( i = 0, j = 0; j < X_bytes; i++, j += sizeof(ord)) + { + Y[i] = ( (ord)X[j] ) | ( ((ord)X[j+1]) << 8 ) +#ifdef ORD_32 + | ( ((ord)X[j+2]) << 16 ) | ( ((ord)X[j+3]) << 24 ) +#endif + ; + } +} + +/**************************************************************************** +* NAME: void OrdByte (ord *X, u_int32_t X_bytes, +* uchar *Y ) +* +* +* DESCRIPTION: Transfer ord to bytes. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to ord array +* u_int32_t X_bytes Number of bytes in array +* OUTPUT: +* PARAMETERS: +* uchar *Y Pointer to byte array +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void OrdByte( ord *X, + u_int32_t X_bytes, + uchar *Y ) +{ + u_int32_t i, j; /* counters */ + for ( i=0, j=0; j < X_bytes; i++, j += sizeof(ord)) + { + Y[j] = (uchar ) ( X[i] & 0xff ); + Y[j+1] = (uchar)( (X[i] >> 8) & 0xff ); +#ifdef ORD_32 + Y[j+2] = (uchar)( (X[i] >> 16) & 0xff ); + Y[j+3] = (uchar)( (X[i] >> 24) & 0xff ); +#endif + } +} + +/**************************************************************************** +* NAME: void LongByte( u_int32_t *X, +* u_int32_t X_bytes, +* uchar *Y ) +* +* DESCRIPTION: Transfer u_int32_t to bytes. +* +* INPUTS: +* PARAMETERS: +* u_int32_t *X Pointer to long array +* u_int32_t X_bytes Number of longs in array +* OUTPUT: +* PARAMETERS: +* uchar *Y Pointer to bytes array +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void LongByte( u_int32_t *X, + u_int32_t X_bytes, + uchar *Y ) +{ + u_int32_t i, j; /* counters */ + for ( i=0, j=0; j < X_bytes; i++, j += 4) + { + Y[j] = (uchar ) ( X[i] & 0xff ); + Y[j+1] = (uchar)( (X[i] >> 8) & 0xff ); + Y[j+2] = (uchar)( (X[i] >> 16) & 0xff ); + Y[j+3] = (uchar)( (X[i] >> 24) & 0xff ); + } +} + + diff --git a/usr/src/lib/libresolv2/common/cylink/bn.c b/usr/src/lib/libresolv2/common/cylink/bn.c new file mode 100644 index 0000000000..8825e1dba6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn.c - the high-level bignum interface + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" +#include "bn.h" +#include "port_after.h" + +/* Functions */ +void +bnBegin(struct BigNum *bn) +{ + static int bninit = 0; + + if (!bninit) { + bnInit(); + bninit = 1; + } + + bn->ptr = 0; + bn->size = 0; + bn->allocated = 0; +} + +void +bnSwap(struct BigNum *a, struct BigNum *b) +{ + void *p; + unsigned t; + + p = a->ptr; + a->ptr = b->ptr; + b->ptr = p; + + t = a->size; + a->size = b->size; + b->size = t; + + t = a->allocated; + a->allocated = b->allocated; + b->allocated = t; +} + +void (*bnEnd)(struct BigNum *bn); +int (*bnPrealloc)(struct BigNum *bn, unsigned bits); +int (*bnCopy)(struct BigNum *dest, struct BigNum const *src); +void (*bnNorm)(struct BigNum *bn); +void (*bnExtractBigBytes)(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len); +int (*bnInsertBigBytes)(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +void (*bnExtractLittleBytes)(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len); +int (*bnInsertLittleBytes)(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +unsigned (*bnLSWord)(struct BigNum const *src); +unsigned (*bnBits)(struct BigNum const *src); +int (*bnAdd)(struct BigNum *dest, struct BigNum const *src); +int (*bnSub)(struct BigNum *dest, struct BigNum const *src); +int (*bnCmpQ)(struct BigNum const *a, unsigned b); +int (*bnSetQ)(struct BigNum *dest, unsigned src); +int (*bnAddQ)(struct BigNum *dest, unsigned src); +int (*bnSubQ)(struct BigNum *dest, unsigned src); +int (*bnCmp)(struct BigNum const *a, struct BigNum const *b); +int (*bnSquare)(struct BigNum *dest, struct BigNum const *src); +int (*bnMul)(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int (*bnMulQ)(struct BigNum *dest, struct BigNum const *a, unsigned b); +int (*bnDivMod)(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d); +int (*bnMod)(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *d); +unsigned (*bnModQ)(struct BigNum const *src, unsigned d); +int (*bnExpMod)(struct BigNum *result, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod); +int (*bnDoubleExpMod)(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod); +int (*bnTwoExpMod)(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod); +int (*bnGcd)(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int (*bnInv)(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod); +int (*bnLShift)(struct BigNum *dest, unsigned amt); +void (*bnRShift)(struct BigNum *dest, unsigned amt); +unsigned (*bnMakeOdd)(struct BigNum *n); diff --git a/usr/src/lib/libresolv2/common/cylink/bn.h b/usr/src/lib/libresolv2/common/cylink/bn.h new file mode 100644 index 0000000000..9246388117 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn.h - the interface to the bignum routines. + * All functions which return ints can potentially allocate memory + * and return -1 if they are unable to. All "const" arguments + * are unmodified. + * + * This is not particularly asymmetric, as some operations are of the + * form a = b @ c, while others do a @= b. In general, outputs may not + * point to the same struct BigNums as inputs, except as specified + * below. This relationship is referred to as "being the same as". + * This is not numerical equivalence. + * + * The "Q" operations take "unsigned" inputs. Higher values of the + * extra input may work on some implementations, but 65535 is the + * highest portable value. Just because UNSIGNED_MAX is larger than + * that, or you know that the word size of the library is larger than that, + * that, does *not* mean it's allowed. + */ +#ifndef BN_H +#define BN_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +struct BigNum { + void *ptr; + unsigned size; /* Note: in (variable-sized) words */ + unsigned allocated; +}; + +/* Functions */ + +/* + * You usually never have to call this function explicitly, as + * bnBegin() takes care of it. If the program jumps to address 0, + * this function has bot been called. + */ +void bnInit(void); + +/* + * This initializes an empty struct BigNum to a zero value. + * Do not use this on a BigNum which has had a value stored in it! + */ +void bnBegin(struct BigNum *bn); + +/* Swap two BigNums. Cheap. */ +void bnSwap(struct BigNum *a, struct BigNum *b); + +/* Reset an initialized bigNum to empty, pending deallocation. */ +extern void (*bnEnd)(struct BigNum *bn); + +/* + * If you know you'll need space in the number soon, you can use this function + * to ensure that there is room for at least "bits" bits. Optional. + * Returns <0 on out of memory, but the value is unaffected. + */ +extern int (*bnPrealloc)(struct BigNum *bn, unsigned bits); + +/* Hopefully obvious. dest = src. dest may be the same as src. */ +extern int (*bnCopy)(struct BigNum *dest, struct BigNum const *src); + +/* + * Mostly done automatically, but this removes leading zero words from + * the internal representation of the BigNum. Use is unclear. + */ +extern void (*bnNorm)(struct BigNum *bn); + +/* + * Move bytes between the given buffer and the given BigNum encoded in + * base 256. I.e. after either of these, the buffer will be equal to + * (bn / 256^lsbyte) % 256^len. The difference is which is altered to + * match the other! + */ +extern void (*bnExtractBigBytes)(struct BigNum const *bn, + unsigned char *dest, unsigned lsbyte, unsigned len); +extern int (*bnInsertBigBytes)(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); + +/* The same, but the buffer is little-endian. */ +extern void (*bnExtractLittleBytes)(struct BigNum const *bn, + unsigned char *dest, unsigned lsbyte, unsigned len); +extern int (*bnInsertLittleBytes)(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); + +/* Return the least-significant bits (at least 16) of the BigNum */ +extern unsigned (*bnLSWord)(struct BigNum const *src); + +/* + * Return the number of significant bits in the BigNum. + * 0 or 1+floor(log2(src)) + */ +extern unsigned (*bnBits)(struct BigNum const *src); + +/* + * dest += src. dest and src may be the same. Guaranteed not to + * allocate memory unnecessarily, so if you're sure bnBits(dest) + * won't change, you don't need to check the return value. + */ +extern int (*bnAdd)(struct BigNum *dest, struct BigNum const *src); + +/* + * dest -= src. dest and src may be the same, but bnSetQ(dest, 0) is faster. + * if dest < src, returns +1 and sets dest = src-dest. + */ +extern int (*bnSub)(struct BigNum *dest, struct BigNum const *src); + +/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmpQ(a, b) <=> 0 */ +extern int (*bnCmpQ)(struct BigNum const *a, unsigned b); + +/* dest = src, where 0 <= src < 2^16. */ +extern int (*bnSetQ)(struct BigNum *dest, unsigned src); + +/* dest += src, where 0 <= src < 2^16 */ +extern int (*bnAddQ)(struct BigNum *dest, unsigned src); + +/* dest -= src, where 0 <= src < 2^16 */ +extern int (*bnSubQ)(struct BigNum *dest, unsigned src); + +/* Return sign (-1, 0, +1) of a-b. a <=> b --> bnCmp(a, b) <=> 0 */ +extern int (*bnCmp)(struct BigNum const *a, struct BigNum const *b); + +/* dest = src^2. dest may be the same as src, but it costs time. */ +extern int (*bnSquare)(struct BigNum *dest, struct BigNum const *src); + +/* dest = a * b. dest may be the same as a or b, but it costs time. */ +extern int (*bnMul)(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); + +/* dest = a * b, where 0 <= b < 2^16. dest and a may be the same. */ +extern int (*bnMulQ)(struct BigNum *dest, struct BigNum const *a, unsigned b); + +/* + * q = n/d, r = n%d. r may be the same as n, but not d, + * and q may not be the same as n or d. + * re-entrancy issue: this temporarily modifies d, but restores + * it for return. + */ +extern int (*bnDivMod)(struct BigNum *q, struct BigNum *r, + struct BigNum const *n, struct BigNum const *d); +/* + * dest = src % d. dest and src may be the same, but not dest and d. + * re-entrancy issue: this temporarily modifies d, but restores + * it for return. + */ +extern int (*bnMod)(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *d); + +/* return src % d, where 0 <= d < 2^16. */ +extern unsigned int (*bnModQ)(struct BigNum const *src, unsigned d); + +/* n = n^exp, modulo "mod" "mod" *must* be odd */ +extern int (*bnExpMod)(struct BigNum *result, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod); + +/* + * dest = n1^e1 * n2^e2, modulo "mod". "mod" *must* be odd. + * dest may be the same as n1 or n2. + */ +extern int (*bnDoubleExpMod)(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod); + +/* n = 2^exp, modulo "mod" "mod" *must* be odd */ +extern int (*bnTwoExpMod)(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod); + +/* dest = gcd(a, b). The inputs may overlap arbitrarily. */ +extern int (*bnGcd)(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); + +/* dest = src^-1, modulo "mod". dest may be the same as src. */ +extern int (*bnInv)(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod); + +/* Shift dest left "amt" places */ +extern int (*bnLShift)(struct BigNum *dest, unsigned amt); +/* Shift dest right "amt" places, discarding low-order bits */ +extern void (*bnRShift)(struct BigNum *dest, unsigned amt); + +/* For the largest 2^k that divides n, divide n by it and return k. */ +extern unsigned (*bnMakeOdd)(struct BigNum *n); + +#endif/* !BN_H */ diff --git a/usr/src/lib/libresolv2/common/cylink/bn00.c b/usr/src/lib/libresolv2/common/cylink/bn00.c new file mode 100644 index 0000000000..affc76dc64 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn00.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn00.c - auto-size-detecting bn??.c file. + * + * Written in 1995 by Colin Plumb. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" +#include "bnsize00.h" + + +#if BNSIZE64 + +/* Include all of the C source file by reference */ +#include "bn64.c" +#include "bninit64.c" + +#elif BNSIZE32 + +/* Include all of the C source file by reference */ +#include "bn32.c" +#include "bninit32.c" + +#else /* BNSIZE16 */ + +/* Include all of the C source file by reference */ +#include "bn16.c" +#include "bninit16.c" + +#endif diff --git a/usr/src/lib/libresolv2/common/cylink/bn16.c b/usr/src/lib/libresolv2/common/cylink/bn16.c new file mode 100644 index 0000000000..3afa8f4751 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn16.c @@ -0,0 +1,956 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn16.c - the high-level bignum interface + * + * Like lbn16.c, this reserves the string "16" for textual replacement. + * The string must not appear anywhere unless it is intended to be replaced + * to generate other bignum interface functions. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_ASSERT_H +#define NO_ASSERT_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_ASSERT_H +#include <assert.h> +#else +#define assert(x) (void)0 +#endif + +#if !NO_STRING_H +#include <string.h> /* for memmove() in bnMakeOdd */ +#elif HAVE_STRINGS_H +#include <strings.h> +#endif +#if NEED_MEMORY_H +#include <memory.h> +#endif + +/* + * This was useful during debugging, so it's left in here. + * You can ignore it. DBMALLOC is generally undefined. + */ +#ifndef DBMALLOC +#define DBAMLLOC 0 +#endif +#if DBMALLOC +#include "../dbmalloc/malloc.h" +#define MALLOCDB malloc_chain_check(1) +#else +#define MALLOCDB (void)0 +#endif + +#include "lbn.h" +#include "lbn16.h" +#include "lbnmem.h" +#include "bn16.h" +#include "bn.h" + +/* Work-arounds for some particularly broken systems */ +#include "kludge.h" /* For memmove() */ +#include <port_after.h> + +/* Functions */ +void +bnInit_16(void) +{ + bnEnd = bnEnd_16; + bnPrealloc = bnPrealloc_16; + bnCopy = bnCopy_16; + bnNorm = bnNorm_16; + bnExtractBigBytes = bnExtractBigBytes_16; + bnInsertBigBytes = bnInsertBigBytes_16; + bnExtractLittleBytes = bnExtractLittleBytes_16; + bnInsertLittleBytes = bnInsertLittleBytes_16; + bnLSWord = bnLSWord_16; + bnBits = bnBits_16; + bnAdd = bnAdd_16; + bnSub = bnSub_16; + bnCmpQ = bnCmpQ_16; + bnSetQ = bnSetQ_16; + bnAddQ = bnAddQ_16; + bnSubQ = bnSubQ_16; + bnCmp = bnCmp_16; + bnSquare = bnSquare_16; + bnMul = bnMul_16; + bnMulQ = bnMulQ_16; + bnDivMod = bnDivMod_16; + bnMod = bnMod_16; + bnModQ = bnModQ_16; + bnExpMod = bnExpMod_16; + bnDoubleExpMod = bnDoubleExpMod_16; + bnTwoExpMod = bnTwoExpMod_16; + bnGcd = bnGcd_16; + bnInv = bnInv_16; + bnLShift = bnLShift_16; + bnRShift = bnRShift_16; + bnMakeOdd = bnMakeOdd_16; +} + +void +bnEnd_16(struct BigNum *bn) +{ + if (bn->ptr) { + LBNFREE((BNWORD16 *)bn->ptr, bn->allocated); + bn->ptr = 0; + } + bn->size = 0; + bn->allocated = 0; + + MALLOCDB; +} + +/* Internal function. It operates in words. */ +static int +bnResize_16(struct BigNum *bn, unsigned len) +{ + void *p; + + /* Round size up: most mallocs impose 8-byte granularity anyway */ + len = (len + (8/sizeof(BNWORD16) - 1)) & ~(8/sizeof(BNWORD16) - 1); + p = LBNREALLOC((BNWORD16 *)bn->ptr, bn->allocated, len); + if (!p) + return -1; + bn->ptr = p; + bn->allocated = len; + + MALLOCDB; + + return 0; +} + +#define bnSizeCheck(bn, size) \ + if (bn->allocated < size && bnResize_16(bn, size) < 0) \ + return -1 + +int +bnPrealloc_16(struct BigNum *bn, unsigned bits) +{ + bits = (bits + 16-1)/16; + bnSizeCheck(bn, bits); + MALLOCDB; + return 0; +} + +int +bnCopy_16(struct BigNum *dest, struct BigNum const *src) +{ + bnSizeCheck(dest, src->size); + dest->size = src->size; + lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, src->size); + MALLOCDB; + return 0; +} + +void +bnNorm_16(struct BigNum *bn) +{ + bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, bn->size); +} + +/* + * Convert a bignum to big-endian bytes. Returns, in big-endian form, a + * substring of the bignum starting from lsbyte and "len" bytes long. + * Unused high-order (leading) bytes are filled with 0. + */ +void +bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size * (16 / 8); + + /* Fill unused leading bytes with 0 */ + while (s < lsbyte+len) { + *dest++ = 0; + len--; + } + + if (len) + lbnExtractBigBytes_16((BNWORD16 *)bn->ptr, dest, lsbyte, len); + MALLOCDB; +} + +int +bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size; + unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16); + + /* Pad with zeros as required */ + bnSizeCheck(bn, words); + + if (s < words) { + lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s); + s = words; + } + + lbnInsertBigBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len); + + bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s); + + MALLOCDB; + return 0; +} + + +/* + * Convert a bignum to little-endian bytes. Returns, in little-endian form, a + * substring of the bignum starting from lsbyte and "len" bytes long. + * Unused high-order (trailing) bytes are filled with 0. + */ +void +bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size * (16 / 8); + + /* Fill unused leading bytes with 0 */ + while (s < lsbyte+len) + dest[--len] = 0; + + if (len) + lbnExtractLittleBytes_16((BNWORD16 *)bn->ptr, dest, + lsbyte, len); + MALLOCDB; +} + +int +bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size; + unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16); + + /* Pad with zeros as required */ + bnSizeCheck(bn, words); + + if (s < words) { + lbnZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s); + s = words; + } + + lbnInsertLittleBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len); + + bn->size = lbnNorm_16((BNWORD16 *)bn->ptr, s); + + MALLOCDB; + return 0; +} + +/* Return the least-significant word of the input. */ +unsigned +bnLSWord_16(struct BigNum const *src) +{ + return src->size ? (unsigned)((BNWORD16 *)src->ptr)[BIGLITTLE(-1,0)]: 0; +} + +unsigned +bnBits_16(struct BigNum const *src) +{ + return lbnBits_16((BNWORD16 *)src->ptr, src->size); +} + +int +bnAdd_16(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s = src->size, d = dest->size; + BNWORD16 t; + + if (!s) + return 0; + + bnSizeCheck(dest, s); + + if (d < s) { + lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d); + dest->size = d = s; + MALLOCDB; + } + t = lbnAddN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); + MALLOCDB; + if (t) { + if (d > s) { + t = lbnAdd1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s), + d-s, t); + MALLOCDB; + } + if (t) { + bnSizeCheck(dest, d+1); + ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t; + dest->size = d+1; + } + } + return 0; +} + +/* + * dest -= src. + * If dest goes negative, this produces the absolute value of + * the difference (the negative of the true value) and returns 1. + * Otherwise, it returls 0. + */ +int +bnSub_16(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s = src->size, d = dest->size; + BNWORD16 t; + + if (d < s && d < (s = lbnNorm_16((BNWORD16 *)src->ptr, s))) { + bnSizeCheck(dest, s); + lbnZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d); + dest->size = d = s; + MALLOCDB; + } + if (!s) + return 0; + t = lbnSubN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); + MALLOCDB; + if (t) { + if (d > s) { + t = lbnSub1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s), + d-s, t); + MALLOCDB; + } + if (t) { + lbnNeg_16((BNWORD16 *)dest->ptr, d); + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, + dest->size); + MALLOCDB; + return 1; + } + } + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size); + return 0; +} + +/* + * Compare the BigNum to the given value, which must be < 65536. + * Returns -1. 0 or 1 if a<b, a == b or a>b. + * a <=> b --> bnCmpQ(a,b) <=> 0 + */ +int +bnCmpQ_16(struct BigNum const *a, unsigned b) +{ + unsigned t; + BNWORD16 v; + + t = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + /* If a is more than one word long or zero, it's easy... */ + if (t != 1) + return (t > 1) ? 1 : (b ? -1 : 0); + v = (unsigned)((BNWORD16 *)a->ptr)[BIGLITTLE(-1,0)]; + return (v > b) ? 1 : ((v < b) ? -1 : 0); +} + +int +bnSetQ_16(struct BigNum *dest, unsigned src) +{ + if (src) { + bnSizeCheck(dest, 1); + + ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD16)src; + dest->size = 1; + } else { + dest->size = 0; + } + return 0; +} + +int +bnAddQ_16(struct BigNum *dest, unsigned src) +{ + BNWORD16 t; + + if (!dest->size) + return bnSetQ(dest, src); + + t = lbnAdd1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src); + MALLOCDB; + if (t) { + src = dest->size; + bnSizeCheck(dest, src+1); + ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t; + dest->size = src+1; + } + return 0; +} + +/* + * Return value as for bnSub: 1 if subtract underflowed, in which + * case the return is the negative of the computed value. + */ +int +bnSubQ_16(struct BigNum *dest, unsigned src) +{ + BNWORD16 t; + + if (!dest->size) + return bnSetQ(dest, src) < 0 ? -1 : (src != 0); + + t = lbnSub1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src); + MALLOCDB; + if (t) { + /* Underflow. <= 1 word, so do it simply. */ + lbnNeg_16((BNWORD16 *)dest->ptr, 1); + dest->size = 1; + return 1; + } +/* Try to normalize? Needing this is going to be very rare. */ +/* dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dest->size); */ + return 0; +} + +/* + * Compare two BigNums. Returns -1. 0 or 1 if a<b, a == b or a>b. + * a <=> b --> bnCmp(a,b) <=> 0 + */ +int +bnCmp_16(struct BigNum const *a, struct BigNum const *b) +{ + unsigned s, t; + + s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + t = lbnNorm_16((BNWORD16 *)b->ptr, b->size); + + if (s != t) + return s > t ? 1 : -1; + return lbnCmp_16((BNWORD16 *)a->ptr, (BNWORD16 *)b->ptr, s); +} + +int +bnSquare_16(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s; + BNWORD16 *srcbuf; + + s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); + if (!s) { + dest->size = 0; + return 0; + } + bnSizeCheck(dest, 2*s); + + if (src == dest) { + LBNALLOC(srcbuf, s); + if (!srcbuf) + return -1; + lbnCopy_16(srcbuf, (BNWORD16 *)src->ptr, s); + lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)srcbuf, s); + LBNFREE(srcbuf, s); + } else { + lbnSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s); + } + + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, 2*s); + MALLOCDB; + return 0; +} + +int +bnMul_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) +{ + unsigned s, t; + BNWORD16 *srcbuf; + + s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + t = lbnNorm_16((BNWORD16 *)b->ptr, b->size); + + if (!s || !t) { + dest->size = 0; + return 0; + } + + if (a == b) + return bnSquare_16(dest, a); + + bnSizeCheck(dest, s+t); + + if (dest == a) { + LBNALLOC(srcbuf, s); + if (!srcbuf) + return -1; + lbnCopy_16(srcbuf, (BNWORD16 *)a->ptr, s); + lbnMul_16((BNWORD16 *)dest->ptr, srcbuf, s, + (BNWORD16 *)b->ptr, t); + LBNFREE(srcbuf, s); + } else if (dest == b) { + LBNALLOC(srcbuf, t); + if (!srcbuf) + return -1; + lbnCopy_16(srcbuf, (BNWORD16 *)b->ptr, t); + lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, + srcbuf, t); + LBNFREE(srcbuf, t); + } else { + lbnMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, + (BNWORD16 *)b->ptr, t); + } + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+t); + MALLOCDB; + return 0; +} + +int +bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b) +{ + unsigned s; + + s = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + if (!s || !b) { + dest->size = 0; + return 0; + } + if (b == 1) + return bnCopy_16(dest, a); + bnSizeCheck(dest, s+1); + lbnMulN1_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, (BNWORD16)b); + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, s+1); + MALLOCDB; + return 0; +} + +int +bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d) +{ + unsigned dsize, nsize; + BNWORD16 qhigh; + + dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size); + nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size); + + if (nsize < dsize) { + q->size = 0; /* No quotient */ + r->size = nsize; + return 0; /* Success */ + } + + bnSizeCheck(q, nsize-dsize); + + if (r != n) { /* You are allowed to reduce in place */ + bnSizeCheck(r, nsize); + lbnCopy_16((BNWORD16 *)r->ptr, (BNWORD16 *)n->ptr, nsize); + } + + qhigh = lbnDiv_16((BNWORD16 *)q->ptr, (BNWORD16 *)r->ptr, nsize, + (BNWORD16 *)d->ptr, dsize); + nsize -= dsize; + if (qhigh) { + bnSizeCheck(q, nsize+1); + *((BNWORD16 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh; + q->size = nsize+1; + } else { + q->size = lbnNorm_16((BNWORD16 *)q->ptr, nsize); + } + r->size = lbnNorm_16((BNWORD16 *)r->ptr, dsize); + MALLOCDB; + return 0; +} + +int +bnMod_16(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d) +{ + unsigned dsize, nsize; + + nsize = lbnNorm_16((BNWORD16 *)src->ptr, src->size); + dsize = lbnNorm_16((BNWORD16 *)d->ptr, d->size); + + + if (dest != src) { + bnSizeCheck(dest, nsize); + lbnCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, nsize); + } + + if (nsize < dsize) { + dest->size = nsize; /* No quotient */ + return 0; + } + + (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-dsize,+dsize), + (BNWORD16 *)dest->ptr, nsize, + (BNWORD16 *)d->ptr, dsize); + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, dsize); + MALLOCDB; + return 0; +} + +unsigned +bnModQ_16(struct BigNum const *src, unsigned d) +{ + unsigned s; + + s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); + if (!s) + return 0; + + return lbnModQ_16((BNWORD16 *)src->ptr, s, d); +} + +int +bnExpMod_16(struct BigNum *dest, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod) +{ + unsigned nsize, esize, msize; + + nsize = lbnNorm_16((BNWORD16 *)n->ptr, n->size); + esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size); + msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(dest, msize); + + /* Special-case base of 2 */ + if (nsize == 1 && ((BNWORD16 *)n->ptr)[BIGLITTLE(-1,0)] == 2) { + if (lbnTwoExpMod_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)exp->ptr, esize, + (BNWORD16 *)mod->ptr, msize) < 0) + return -1; + } else { + if (lbnExpMod_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)n->ptr, nsize, + (BNWORD16 *)exp->ptr, esize, + (BNWORD16 *)mod->ptr, msize) < 0) + return -1; + } + + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnDoubleExpMod_16(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod) +{ + unsigned n1size, e1size, n2size, e2size, msize; + + n1size = lbnNorm_16((BNWORD16 *)n1->ptr, n1->size); + e1size = lbnNorm_16((BNWORD16 *)e1->ptr, e1->size); + n2size = lbnNorm_16((BNWORD16 *)n2->ptr, n2->size); + e2size = lbnNorm_16((BNWORD16 *)e2->ptr, e2->size); + msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(dest, msize); + + if (lbnDoubleExpMod_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)n1->ptr, n1size, (BNWORD16 *)e1->ptr, e1size, + (BNWORD16 *)n2->ptr, n2size, (BNWORD16 *)e2->ptr, e2size, + (BNWORD16 *)mod->ptr, msize) < 0) + return -1; + + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod) +{ + unsigned esize, msize; + + esize = lbnNorm_16((BNWORD16 *)exp->ptr, exp->size); + msize = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(n, msize); + + if (lbnTwoExpMod_16((BNWORD16 *)n->ptr, (BNWORD16 *)exp->ptr, esize, + (BNWORD16 *)mod->ptr, msize) < 0) + return -1; + + n->size = lbnNorm_16((BNWORD16 *)n->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnGcd_16(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) +{ + BNWORD16 *tmp; + unsigned asize, bsize; + int i; + + /* Kind of silly, but we might as well permit it... */ + if (a == b) + return dest == a ? 0 : bnCopy(dest, a); + + /* Ensure a is not the same as "dest" */ + if (a == dest) { + a = b; + b = dest; + } + + asize = lbnNorm_16((BNWORD16 *)a->ptr, a->size); + bsize = lbnNorm_16((BNWORD16 *)b->ptr, b->size); + + bnSizeCheck(dest, bsize+1); + + /* Copy a to tmp */ + LBNALLOC(tmp, asize+1); + if (!tmp) + return -1; + lbnCopy_16(tmp, (BNWORD16 *)a->ptr, asize); + + /* Copy b to dest,if necessary */ + if (dest != b) + lbnCopy_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)b->ptr, bsize); + if (bsize > asize || (bsize == asize && + lbnCmp_16((BNWORD16 *)b->ptr, (BNWORD16 *)a->ptr, asize) > 0)) + { + i = lbnGcd_16((BNWORD16 *)dest->ptr, bsize, tmp, asize); + if (i >= 0) { + dest->size = (unsigned)i; + } else { + lbnCopy_16((BNWORD16 *)dest->ptr, tmp, + (unsigned)-i); + dest->size = (unsigned)-i; + } + } else { + i = lbnGcd_16(tmp, asize, (BNWORD16 *)dest->ptr, bsize); + if (i <= 0) { + dest->size = (unsigned)-i; + } else { + lbnCopy_16((BNWORD16 *)dest->ptr, tmp, + (unsigned)i); + dest->size = (unsigned)i; + } + } + LBNFREE(tmp, asize+1); + MALLOCDB; + return 0; +} + +int +bnInv_16(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod) +{ + unsigned s, m; + int i; + + s = lbnNorm_16((BNWORD16 *)src->ptr, src->size); + m = lbnNorm_16((BNWORD16 *)mod->ptr, mod->size); + + /* lbnInv_16 requires that the input be less than the modulus */ + if (m < s || + (m==s && lbnCmp_16((BNWORD16 *)src->ptr, (BNWORD16 *)mod->ptr, s))) + { + bnSizeCheck(dest, s + (m==s)); + if (dest != src) + lbnCopy_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)src->ptr, s); + /* Pre-reduce modulo the modulus */ + (void)lbnDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-m,+m), + (BNWORD16 *)dest->ptr, s, + (BNWORD16 *)mod->ptr, m); + s = lbnNorm_16((BNWORD16 *)dest->ptr, m); + MALLOCDB; + } else { + bnSizeCheck(dest, m+1); + if (dest != src) + lbnCopy_16((BNWORD16 *)dest->ptr, + (BNWORD16 *)src->ptr, s); + } + + i = lbnInv_16((BNWORD16 *)dest->ptr, s, (BNWORD16 *)mod->ptr, m); + if (i == 0) + dest->size = lbnNorm_16((BNWORD16 *)dest->ptr, m); + + MALLOCDB; + return i; +} + +/* + * Shift a bignum left the appropriate number of bits, + * multiplying by 2^amt. + */ +int +bnLShift_16(struct BigNum *dest, unsigned amt) +{ + unsigned s = dest->size; + BNWORD16 carry; + + if (amt % 16) { + carry = lbnLshift_16(dest->ptr, s, amt % 16); + if (carry) { + s++; + bnSizeCheck(dest, s); + ((BNWORD16 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry; + } + } + + amt /= 16; + if (amt) { + bnSizeCheck(dest, s+amt); + memmove((BNWORD16 *)dest->ptr BIGLITTLE(-s-amt, +amt), + (BNWORD16 *)dest->ptr BIG(-s), + s * sizeof(BNWORD16)); + lbnZero_16((BNWORD16 *)dest->ptr, amt); + s += amt; + } + dest->size = s; + MALLOCDB; + return 0; +} + +/* + * Shift a bignum right the appropriate number of bits, + * dividing by 2^amt. + */ +void bnRShift_16(struct BigNum *dest, unsigned amt) +{ + unsigned s = dest->size; + + if (amt >= 16) { + memmove( + (BNWORD16 *)dest->ptr BIG(-s+amt/16), + (BNWORD16 *)dest->ptr BIGLITTLE(-s, +amt/16), + s-amt/16 * sizeof(BNWORD16)); + s -= amt/16; + amt %= 16; + } + + if (amt) + (void)lbnRshift_16(dest->ptr, s, amt); + + dest->size = lbnNorm_16(dest->ptr, s); + MALLOCDB; +} + +/* + * Shift a bignum right until it is odd, and return the number of + * bits shifted. n = d * 2^s. Replaces n with d and returns s. + * Returns 0 when given 0. (Another valid answer is infinity.) + */ +unsigned +bnMakeOdd_16(struct BigNum *n) +{ + unsigned size; + unsigned s; /* shift amount */ + BNWORD16 *p; + BNWORD16 t; + + p = (BNWORD16 *)n->ptr; + size = lbnNorm_16(p, n->size); + if (!size) + return 0; + + t = BIGLITTLE(p[-1],p[0]); + s = 0; + + /* See how many words we have to shift */ + if (!t) { + /* Shift by words */ + do { + + s++; + BIGLITTLE(--p,p++); + } while ((t = BIGLITTLE(p[-1],p[0])) == 0); + size -= s; + s *= 16; + memmove((BNWORD16 *)n->ptr BIG(-size), p BIG(-size), + size * sizeof(BNWORD16)); + p = (BNWORD16 *)n->ptr; + MALLOCDB; + } + + assert(t); + + /* Now count the bits */ + while ((t & 1) == 0) { + t >>= 1; + s++; + } + + /* Shift the bits */ + if (s & (16-1)) { + lbnRshift_16(p, size, s & (16-1)); + /* Renormalize */ + if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0) + --size; + } + n->size = size; + + MALLOCDB; + return s; +} diff --git a/usr/src/lib/libresolv2/common/cylink/bn16.h b/usr/src/lib/libresolv2/common/cylink/bn16.h new file mode 100644 index 0000000000..8f8402534e --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn16.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn16.h - interface to 16-bit bignum routines. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +struct BigNum; + +void bnInit_16(void); +void bnEnd_16(struct BigNum *bn); +int bnPrealloc_16(struct BigNum *bn, unsigned bits); +int bnCopy_16(struct BigNum *dest, struct BigNum const *src); +int bnSwap_16(struct BigNum *a, struct BigNum *b); +void bnNorm_16(struct BigNum *bn); +void bnExtractBigBytes_16(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned dlen); +int bnInsertBigBytes_16(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +void bnExtractLittleBytes_16(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned dlen); +int bnInsertLittleBytes_16(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +unsigned bnLSWord_16(struct BigNum const *src); +unsigned bnBits_16(struct BigNum const *src); +int bnAdd_16(struct BigNum *dest, struct BigNum const *src); +int bnSub_16(struct BigNum *dest, struct BigNum const *src); +int bnCmpQ_16(struct BigNum const *a, unsigned b); +int bnSetQ_16(struct BigNum *dest, unsigned src); +int bnAddQ_16(struct BigNum *dest, unsigned src); +int bnSubQ_16(struct BigNum *dest, unsigned src); +int bnCmp_16(struct BigNum const *a, struct BigNum const *b); +int bnSquare_16(struct BigNum *dest, struct BigNum const *src); +int bnMul_16(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int bnMulQ_16(struct BigNum *dest, struct BigNum const *a, unsigned b); +int bnDivMod_16(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d); +int bnMod_16(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *d); +unsigned bnModQ_16(struct BigNum const *src, unsigned d); +int bnExpMod_16(struct BigNum *dest, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod); +int bnDoubleExpMod_16(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod); +int bnTwoExpMod_16(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod); +int bnGcd_16(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int bnInv_16(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod); +int bnLShift_16(struct BigNum *dest, unsigned amt); +void bnRShift_16(struct BigNum *dest, unsigned amt); +unsigned bnMakeOdd_16(struct BigNum *n); diff --git a/usr/src/lib/libresolv2/common/cylink/bn32.c b/usr/src/lib/libresolv2/common/cylink/bn32.c new file mode 100644 index 0000000000..449cb90567 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn32.c @@ -0,0 +1,956 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn32.c - the high-level bignum interface + * + * Like lbn32.c, this reserves the string "32" for textual replacement. + * The string must not appear anywhere unless it is intended to be replaced + * to generate other bignum interface functions. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_ASSERT_H +#define NO_ASSERT_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_ASSERT_H +#include <assert.h> +#else +#define assert(x) (void)0 +#endif + +#if !NO_STRING_H +#include <string.h> /* for memmove() in bnMakeOdd */ +#elif HAVE_STRINGS_H +#include <strings.h> +#endif +#if NEED_MEMORY_H +#include <memory.h> +#endif + +/* + * This was useful during debugging, so it's left in here. + * You can ignore it. DBMALLOC is generally undefined. + */ +#ifndef DBMALLOC +#define DBAMLLOC 0 +#endif +#if DBMALLOC +#include "../dbmalloc/malloc.h" +#define MALLOCDB malloc_chain_check(1) +#else +#define MALLOCDB (void)0 +#endif + +#include "lbn.h" +#include "lbn32.h" +#include "lbnmem.h" +#include "bn32.h" +#include "bn.h" + +/* Work-arounds for some particularly broken systems */ +#include "kludge.h" /* For memmove() */ +#include <port_after.h> + +/* Functions */ +void +bnInit_32(void) +{ + bnEnd = bnEnd_32; + bnPrealloc = bnPrealloc_32; + bnCopy = bnCopy_32; + bnNorm = bnNorm_32; + bnExtractBigBytes = bnExtractBigBytes_32; + bnInsertBigBytes = bnInsertBigBytes_32; + bnExtractLittleBytes = bnExtractLittleBytes_32; + bnInsertLittleBytes = bnInsertLittleBytes_32; + bnLSWord = bnLSWord_32; + bnBits = bnBits_32; + bnAdd = bnAdd_32; + bnSub = bnSub_32; + bnCmpQ = bnCmpQ_32; + bnSetQ = bnSetQ_32; + bnAddQ = bnAddQ_32; + bnSubQ = bnSubQ_32; + bnCmp = bnCmp_32; + bnSquare = bnSquare_32; + bnMul = bnMul_32; + bnMulQ = bnMulQ_32; + bnDivMod = bnDivMod_32; + bnMod = bnMod_32; + bnModQ = bnModQ_32; + bnExpMod = bnExpMod_32; + bnDoubleExpMod = bnDoubleExpMod_32; + bnTwoExpMod = bnTwoExpMod_32; + bnGcd = bnGcd_32; + bnInv = bnInv_32; + bnLShift = bnLShift_32; + bnRShift = bnRShift_32; + bnMakeOdd = bnMakeOdd_32; +} + +void +bnEnd_32(struct BigNum *bn) +{ + if (bn->ptr) { + LBNFREE((BNWORD32 *)bn->ptr, bn->allocated); + bn->ptr = 0; + } + bn->size = 0; + bn->allocated = 0; + + MALLOCDB; +} + +/* Internal function. It operates in words. */ +static int +bnResize_32(struct BigNum *bn, unsigned len) +{ + void *p; + + /* Round size up: most mallocs impose 8-byte granularity anyway */ + len = (len + (8/sizeof(BNWORD32) - 1)) & ~(8/sizeof(BNWORD32) - 1); + p = LBNREALLOC((BNWORD32 *)bn->ptr, bn->allocated, len); + if (!p) + return -1; + bn->ptr = p; + bn->allocated = len; + + MALLOCDB; + + return 0; +} + +#define bnSizeCheck(bn, size) \ + if (bn->allocated < size && bnResize_32(bn, size) < 0) \ + return -1 + +int +bnPrealloc_32(struct BigNum *bn, unsigned bits) +{ + bits = (bits + 32-1)/32; + bnSizeCheck(bn, bits); + MALLOCDB; + return 0; +} + +int +bnCopy_32(struct BigNum *dest, struct BigNum const *src) +{ + bnSizeCheck(dest, src->size); + dest->size = src->size; + lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, src->size); + MALLOCDB; + return 0; +} + +void +bnNorm_32(struct BigNum *bn) +{ + bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, bn->size); +} + +/* + * Convert a bignum to big-endian bytes. Returns, in big-endian form, a + * substring of the bignum starting from lsbyte and "len" bytes long. + * Unused high-order (leading) bytes are filled with 0. + */ +void +bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size * (32 / 8); + + /* Fill unused leading bytes with 0 */ + while (s < lsbyte+len) { + *dest++ = 0; + len--; + } + + if (len) + lbnExtractBigBytes_32((BNWORD32 *)bn->ptr, dest, lsbyte, len); + MALLOCDB; +} + +int +bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size; + unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32); + + /* Pad with zeros as required */ + bnSizeCheck(bn, words); + + if (s < words) { + lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s); + s = words; + } + + lbnInsertBigBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len); + + bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s); + + MALLOCDB; + return 0; +} + + +/* + * Convert a bignum to little-endian bytes. Returns, in little-endian form, a + * substring of the bignum starting from lsbyte and "len" bytes long. + * Unused high-order (trailing) bytes are filled with 0. + */ +void +bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size * (32 / 8); + + /* Fill unused leading bytes with 0 */ + while (s < lsbyte+len) + dest[--len] = 0; + + if (len) + lbnExtractLittleBytes_32((BNWORD32 *)bn->ptr, dest, + lsbyte, len); + MALLOCDB; +} + +int +bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len) +{ + unsigned s = bn->size; + unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32); + + /* Pad with zeros as required */ + bnSizeCheck(bn, words); + + if (s < words) { + lbnZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s); + s = words; + } + + lbnInsertLittleBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len); + + bn->size = lbnNorm_32((BNWORD32 *)bn->ptr, s); + + MALLOCDB; + return 0; +} + +/* Return the least-significant word of the input. */ +unsigned +bnLSWord_32(struct BigNum const *src) +{ + return src->size ? (unsigned)((BNWORD32 *)src->ptr)[BIGLITTLE(-1,0)]: 0; +} + +unsigned +bnBits_32(struct BigNum const *src) +{ + return lbnBits_32((BNWORD32 *)src->ptr, src->size); +} + +int +bnAdd_32(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s = src->size, d = dest->size; + BNWORD32 t; + + if (!s) + return 0; + + bnSizeCheck(dest, s); + + if (d < s) { + lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d); + dest->size = d = s; + MALLOCDB; + } + t = lbnAddN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); + MALLOCDB; + if (t) { + if (d > s) { + t = lbnAdd1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s), + d-s, t); + MALLOCDB; + } + if (t) { + bnSizeCheck(dest, d+1); + ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t; + dest->size = d+1; + } + } + return 0; +} + +/* + * dest -= src. + * If dest goes negative, this produces the absolute value of + * the difference (the negative of the true value) and returns 1. + * Otherwise, it returls 0. + */ +int +bnSub_32(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s = src->size, d = dest->size; + BNWORD32 t; + + if (d < s && d < (s = lbnNorm_32((BNWORD32 *)src->ptr, s))) { + bnSizeCheck(dest, s); + lbnZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d); + dest->size = d = s; + MALLOCDB; + } + if (!s) + return 0; + t = lbnSubN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); + MALLOCDB; + if (t) { + if (d > s) { + t = lbnSub1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s), + d-s, t); + MALLOCDB; + } + if (t) { + lbnNeg_32((BNWORD32 *)dest->ptr, d); + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, + dest->size); + MALLOCDB; + return 1; + } + } + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size); + return 0; +} + +/* + * Compare the BigNum to the given value, which must be < 65536. + * Returns -1. 0 or 1 if a<b, a == b or a>b. + * a <=> b --> bnCmpQ(a,b) <=> 0 + */ +int +bnCmpQ_32(struct BigNum const *a, unsigned b) +{ + unsigned t; + BNWORD32 v; + + t = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + /* If a is more than one word long or zero, it's easy... */ + if (t != 1) + return (t > 1) ? 1 : (b ? -1 : 0); + v = (unsigned)((BNWORD32 *)a->ptr)[BIGLITTLE(-1,0)]; + return (v > b) ? 1 : ((v < b) ? -1 : 0); +} + +int +bnSetQ_32(struct BigNum *dest, unsigned src) +{ + if (src) { + bnSizeCheck(dest, 1); + + ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD32)src; + dest->size = 1; + } else { + dest->size = 0; + } + return 0; +} + +int +bnAddQ_32(struct BigNum *dest, unsigned src) +{ + BNWORD32 t; + + if (!dest->size) + return bnSetQ(dest, src); + + t = lbnAdd1_32((BNWORD32 *)dest->ptr, dest->size, (BNWORD32)src); + MALLOCDB; + if (t) { + src = dest->size; + bnSizeCheck(dest, src+1); + ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t; + dest->size = src+1; + } + return 0; +} + +/* + * Return value as for bnSub: 1 if subtract underflowed, in which + * case the return is the negative of the computed value. + */ +int +bnSubQ_32(struct BigNum *dest, unsigned src) +{ + BNWORD32 t; + + if (!dest->size) + return bnSetQ(dest, src) < 0 ? -1 : (src != 0); + + t = lbnSub1_32((BNWORD32 *)dest->ptr, dest->size, src); + MALLOCDB; + if (t) { + /* Underflow. <= 1 word, so do it simply. */ + lbnNeg_32((BNWORD32 *)dest->ptr, 1); + dest->size = 1; + return 1; + } +/* Try to normalize? Needing this is going to be very rare. */ +/* dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dest->size); */ + return 0; +} + +/* + * Compare two BigNums. Returns -1. 0 or 1 if a<b, a == b or a>b. + * a <=> b --> bnCmp(a,b) <=> 0 + */ +int +bnCmp_32(struct BigNum const *a, struct BigNum const *b) +{ + unsigned s, t; + + s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + t = lbnNorm_32((BNWORD32 *)b->ptr, b->size); + + if (s != t) + return s > t ? 1 : -1; + return lbnCmp_32((BNWORD32 *)a->ptr, (BNWORD32 *)b->ptr, s); +} + +int +bnSquare_32(struct BigNum *dest, struct BigNum const *src) +{ + unsigned s; + BNWORD32 *srcbuf; + + s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); + if (!s) { + dest->size = 0; + return 0; + } + bnSizeCheck(dest, 2*s); + + if (src == dest) { + LBNALLOC(srcbuf, s); + if (!srcbuf) + return -1; + lbnCopy_32(srcbuf, (BNWORD32 *)src->ptr, s); + lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)srcbuf, s); + LBNFREE(srcbuf, s); + } else { + lbnSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s); + } + + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, 2*s); + MALLOCDB; + return 0; +} + +int +bnMul_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) +{ + unsigned s, t; + BNWORD32 *srcbuf; + + s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + t = lbnNorm_32((BNWORD32 *)b->ptr, b->size); + + if (!s || !t) { + dest->size = 0; + return 0; + } + + if (a == b) + return bnSquare_32(dest, a); + + bnSizeCheck(dest, s+t); + + if (dest == a) { + LBNALLOC(srcbuf, s); + if (!srcbuf) + return -1; + lbnCopy_32(srcbuf, (BNWORD32 *)a->ptr, s); + lbnMul_32((BNWORD32 *)dest->ptr, srcbuf, s, + (BNWORD32 *)b->ptr, t); + LBNFREE(srcbuf, s); + } else if (dest == b) { + LBNALLOC(srcbuf, t); + if (!srcbuf) + return -1; + lbnCopy_32(srcbuf, (BNWORD32 *)b->ptr, t); + lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, + srcbuf, t); + LBNFREE(srcbuf, t); + } else { + lbnMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, + (BNWORD32 *)b->ptr, t); + } + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+t); + MALLOCDB; + return 0; +} + +int +bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b) +{ + unsigned s; + + s = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + if (!s || !b) { + dest->size = 0; + return 0; + } + if (b == 1) + return bnCopy_32(dest, a); + bnSizeCheck(dest, s+1); + lbnMulN1_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, b); + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, s+1); + MALLOCDB; + return 0; +} + +int +bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d) +{ + unsigned dsize, nsize; + BNWORD32 qhigh; + + dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size); + nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size); + + if (nsize < dsize) { + q->size = 0; /* No quotient */ + r->size = nsize; + return 0; /* Success */ + } + + bnSizeCheck(q, nsize-dsize); + + if (r != n) { /* You are allowed to reduce in place */ + bnSizeCheck(r, nsize); + lbnCopy_32((BNWORD32 *)r->ptr, (BNWORD32 *)n->ptr, nsize); + } + + qhigh = lbnDiv_32((BNWORD32 *)q->ptr, (BNWORD32 *)r->ptr, nsize, + (BNWORD32 *)d->ptr, dsize); + nsize -= dsize; + if (qhigh) { + bnSizeCheck(q, nsize+1); + *((BNWORD32 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh; + q->size = nsize+1; + } else { + q->size = lbnNorm_32((BNWORD32 *)q->ptr, nsize); + } + r->size = lbnNorm_32((BNWORD32 *)r->ptr, dsize); + MALLOCDB; + return 0; +} + +int +bnMod_32(struct BigNum *dest, struct BigNum const *src, struct BigNum const *d) +{ + unsigned dsize, nsize; + + nsize = lbnNorm_32((BNWORD32 *)src->ptr, src->size); + dsize = lbnNorm_32((BNWORD32 *)d->ptr, d->size); + + + if (dest != src) { + bnSizeCheck(dest, nsize); + lbnCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, nsize); + } + + if (nsize < dsize) { + dest->size = nsize; /* No quotient */ + return 0; + } + + (void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-dsize,+dsize), + (BNWORD32 *)dest->ptr, nsize, + (BNWORD32 *)d->ptr, dsize); + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, dsize); + MALLOCDB; + return 0; +} + +unsigned +bnModQ_32(struct BigNum const *src, unsigned d) +{ + unsigned s; + + s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); + if (!s) + return 0; + + return lbnModQ_32((BNWORD32 *)src->ptr, s, d); +} + +int +bnExpMod_32(struct BigNum *dest, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod) +{ + unsigned nsize, esize, msize; + + nsize = lbnNorm_32((BNWORD32 *)n->ptr, n->size); + esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size); + msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(dest, msize); + + /* Special-case base of 2 */ + if (nsize == 1 && ((BNWORD32 *)n->ptr)[BIGLITTLE(-1,0)] == 2) { + if (lbnTwoExpMod_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)exp->ptr, esize, + (BNWORD32 *)mod->ptr, msize) < 0) + return -1; + } else { + if (lbnExpMod_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)n->ptr, nsize, + (BNWORD32 *)exp->ptr, esize, + (BNWORD32 *)mod->ptr, msize) < 0) + return -1; + } + + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnDoubleExpMod_32(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod) +{ + unsigned n1size, e1size, n2size, e2size, msize; + + n1size = lbnNorm_32((BNWORD32 *)n1->ptr, n1->size); + e1size = lbnNorm_32((BNWORD32 *)e1->ptr, e1->size); + n2size = lbnNorm_32((BNWORD32 *)n2->ptr, n2->size); + e2size = lbnNorm_32((BNWORD32 *)e2->ptr, e2->size); + msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(dest, msize); + + if (lbnDoubleExpMod_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)n1->ptr, n1size, (BNWORD32 *)e1->ptr, e1size, + (BNWORD32 *)n2->ptr, n2size, (BNWORD32 *)e2->ptr, e2size, + (BNWORD32 *)mod->ptr, msize) < 0) + return -1; + + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod) +{ + unsigned esize, msize; + + esize = lbnNorm_32((BNWORD32 *)exp->ptr, exp->size); + msize = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); + + if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0) + return -1; /* Illegal modulus! */ + + bnSizeCheck(n, msize); + + if (lbnTwoExpMod_32((BNWORD32 *)n->ptr, (BNWORD32 *)exp->ptr, esize, + (BNWORD32 *)mod->ptr, msize) < 0) + return -1; + + n->size = lbnNorm_32((BNWORD32 *)n->ptr, msize); + MALLOCDB; + return 0; +} + +int +bnGcd_32(struct BigNum *dest, struct BigNum const *a, struct BigNum const *b) +{ + BNWORD32 *tmp; + unsigned asize, bsize; + int i; + + /* Kind of silly, but we might as well permit it... */ + if (a == b) + return dest == a ? 0 : bnCopy(dest, a); + + /* Ensure a is not the same as "dest" */ + if (a == dest) { + a = b; + b = dest; + } + + asize = lbnNorm_32((BNWORD32 *)a->ptr, a->size); + bsize = lbnNorm_32((BNWORD32 *)b->ptr, b->size); + + bnSizeCheck(dest, bsize+1); + + /* Copy a to tmp */ + LBNALLOC(tmp, asize+1); + if (!tmp) + return -1; + lbnCopy_32(tmp, (BNWORD32 *)a->ptr, asize); + + /* Copy b to dest,if necessary */ + if (dest != b) + lbnCopy_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)b->ptr, bsize); + if (bsize > asize || (bsize == asize && + lbnCmp_32((BNWORD32 *)b->ptr, (BNWORD32 *)a->ptr, asize) > 0)) + { + i = lbnGcd_32((BNWORD32 *)dest->ptr, bsize, tmp, asize); + if (i >= 0) { + dest->size = (unsigned)i; + } else { + lbnCopy_32((BNWORD32 *)dest->ptr, tmp, + (unsigned)-i); + dest->size = (unsigned)-i; + } + } else { + i = lbnGcd_32(tmp, asize, (BNWORD32 *)dest->ptr, bsize); + if (i <= 0) { + dest->size = (unsigned)-i; + } else { + lbnCopy_32((BNWORD32 *)dest->ptr, tmp, + (unsigned)i); + dest->size = (unsigned)i; + } + } + LBNFREE(tmp, asize+1); + MALLOCDB; + return 0; +} + +int +bnInv_32(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod) +{ + unsigned s, m; + int i; + + s = lbnNorm_32((BNWORD32 *)src->ptr, src->size); + m = lbnNorm_32((BNWORD32 *)mod->ptr, mod->size); + + /* lbnInv_32 requires that the input be less than the modulus */ + if (m < s || + (m==s && lbnCmp_32((BNWORD32 *)src->ptr, (BNWORD32 *)mod->ptr, s))) + { + bnSizeCheck(dest, s + (m==s)); + if (dest != src) + lbnCopy_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)src->ptr, s); + /* Pre-reduce modulo the modulus */ + (void)lbnDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-m,+m), + (BNWORD32 *)dest->ptr, s, + (BNWORD32 *)mod->ptr, m); + s = lbnNorm_32((BNWORD32 *)dest->ptr, m); + MALLOCDB; + } else { + bnSizeCheck(dest, m+1); + if (dest != src) + lbnCopy_32((BNWORD32 *)dest->ptr, + (BNWORD32 *)src->ptr, s); + } + + i = lbnInv_32((BNWORD32 *)dest->ptr, s, (BNWORD32 *)mod->ptr, m); + if (i == 0) + dest->size = lbnNorm_32((BNWORD32 *)dest->ptr, m); + + MALLOCDB; + return i; +} + +/* + * Shift a bignum left the appropriate number of bits, + * multiplying by 2^amt. + */ +int +bnLShift_32(struct BigNum *dest, unsigned amt) +{ + unsigned s = dest->size; + BNWORD32 carry; + + if (amt % 32) { + carry = lbnLshift_32(dest->ptr, s, amt % 32); + if (carry) { + s++; + bnSizeCheck(dest, s); + ((BNWORD32 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry; + } + } + + amt /= 32; + if (amt) { + bnSizeCheck(dest, s+amt); + memmove((BNWORD32 *)dest->ptr BIGLITTLE(-s-amt, +amt), + (BNWORD32 *)dest->ptr BIG(-s), + s * sizeof(BNWORD32)); + lbnZero_32((BNWORD32 *)dest->ptr, amt); + s += amt; + } + dest->size = s; + MALLOCDB; + return 0; +} + +/* + * Shift a bignum right the appropriate number of bits, + * dividing by 2^amt. + */ +void bnRShift_32(struct BigNum *dest, unsigned amt) +{ + unsigned s = dest->size; + + if (amt >= 32) { + memmove( + (BNWORD32 *)dest->ptr BIG(-s+amt/32), + (BNWORD32 *)dest->ptr BIGLITTLE(-s, +amt/32), + s-amt/32 * sizeof(BNWORD32)); + s -= amt/32; + amt %= 32; + } + + if (amt) + (void)lbnRshift_32(dest->ptr, s, amt); + + dest->size = lbnNorm_32(dest->ptr, s); + MALLOCDB; +} + +/* + * Shift a bignum right until it is odd, and return the number of + * bits shifted. n = d * 2^s. Replaces n with d and returns s. + * Returns 0 when given 0. (Another valid answer is infinity.) + */ +unsigned +bnMakeOdd_32(struct BigNum *n) +{ + unsigned size; + unsigned s; /* shift amount */ + BNWORD32 *p; + BNWORD32 t; + + p = (BNWORD32 *)n->ptr; + size = lbnNorm_32(p, n->size); + if (!size) + return 0; + + t = BIGLITTLE(p[-1],p[0]); + s = 0; + + /* See how many words we have to shift */ + if (!t) { + /* Shift by words */ + do { + + s++; + BIGLITTLE(--p,p++); + } while ((t = BIGLITTLE(p[-1],p[0])) == 0); + size -= s; + s *= 32; + memmove((BNWORD32 *)n->ptr BIG(-size), p BIG(-size), + size * sizeof(BNWORD32)); + p = (BNWORD32 *)n->ptr; + MALLOCDB; + } + + assert(t); + + /* Now count the bits */ + while ((t & 1) == 0) { + t >>= 1; + s++; + } + + /* Shift the bits */ + if (s & (32-1)) { + lbnRshift_32(p, size, s & (32-1)); + /* Renormalize */ + if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0) + --size; + } + n->size = size; + + MALLOCDB; + return s; +} diff --git a/usr/src/lib/libresolv2/common/cylink/bn32.h b/usr/src/lib/libresolv2/common/cylink/bn32.h new file mode 100644 index 0000000000..d6bdc189f6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn32.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn32.h - interface to 32-bit bignum routines. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +struct BigNum; + +void bnInit_32(void); +void bnEnd_32(struct BigNum *bn); +int bnPrealloc_32(struct BigNum *bn, unsigned bits); +int bnCopy_32(struct BigNum *dest, struct BigNum const *src); +int bnSwap_32(struct BigNum *a, struct BigNum *b); +void bnNorm_32(struct BigNum *bn); +void bnExtractBigBytes_32(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned dlen); +int bnInsertBigBytes_32(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +void bnExtractLittleBytes_32(struct BigNum const *bn, unsigned char *dest, + unsigned lsbyte, unsigned dlen); +int bnInsertLittleBytes_32(struct BigNum *bn, unsigned char const *src, + unsigned lsbyte, unsigned len); +unsigned bnLSWord_32(struct BigNum const *src); +unsigned bnBits_32(struct BigNum const *src); +int bnAdd_32(struct BigNum *dest, struct BigNum const *src); +int bnSub_32(struct BigNum *dest, struct BigNum const *src); +int bnCmpQ_32(struct BigNum const *a, unsigned b); +int bnSetQ_32(struct BigNum *dest, unsigned src); +int bnAddQ_32(struct BigNum *dest, unsigned src); +int bnSubQ_32(struct BigNum *dest, unsigned src); +int bnCmp_32(struct BigNum const *a, struct BigNum const *b); +int bnSquare_32(struct BigNum *dest, struct BigNum const *src); +int bnMul_32(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int bnMulQ_32(struct BigNum *dest, struct BigNum const *a, unsigned b); +int bnDivMod_32(struct BigNum *q, struct BigNum *r, struct BigNum const *n, + struct BigNum const *d); +int bnMod_32(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *d); +unsigned bnModQ_32(struct BigNum const *src, unsigned d); +int bnExpMod_32(struct BigNum *dest, struct BigNum const *n, + struct BigNum const *exp, struct BigNum const *mod); +int bnDoubleExpMod_32(struct BigNum *dest, + struct BigNum const *n1, struct BigNum const *e1, + struct BigNum const *n2, struct BigNum const *e2, + struct BigNum const *mod); +int bnTwoExpMod_32(struct BigNum *n, struct BigNum const *exp, + struct BigNum const *mod); +int bnGcd_32(struct BigNum *dest, struct BigNum const *a, + struct BigNum const *b); +int bnInv_32(struct BigNum *dest, struct BigNum const *src, + struct BigNum const *mod); +int bnLShift_32(struct BigNum *dest, unsigned amt); +void bnRShift_32(struct BigNum *dest, unsigned amt); +unsigned bnMakeOdd_32(struct BigNum *n); diff --git a/usr/src/lib/libresolv2/common/cylink/bn68000.c b/usr/src/lib/libresolv2/common/cylink/bn68000.c new file mode 100644 index 0000000000..91bcd1d7af --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn68000.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn68000.c - bnInit() for Motorola 680x0 family, 16 or 32-bit. + * + * Written in 1995 by Colin Plumb. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "lbn.h" +#include "bn16.h" +#include "bn32.h" + +#ifndef BNINCLUDE +#error You must define BNINCLUDE to lbn68000.h to use assembly primitives. +#endif + +void +bnInit(void) +{ + if (is68020()) + bnInit_32(); + else + bnInit_16(); +} diff --git a/usr/src/lib/libresolv2/common/cylink/bn8086.c b/usr/src/lib/libresolv2/common/cylink/bn8086.c new file mode 100644 index 0000000000..b50aab6ad6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bn8086.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bn8086.c - bnInit() for Intel x86 family in 16-bit mode. + * + * Written in 1995 by Colin Plumb. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "lbn.h" +#include "bn16.h" +#include "bn32.h" + +#ifndef BNINCLUDE +#error You must define BNINCLUDE to lbn8086.h to use assembly primitives. +#endif + +void +bnInit(void) +{ +/* if (not386()) + bnInit_16(); + else */ + bnInit_32(); +} diff --git a/usr/src/lib/libresolv2/common/cylink/bninit16.c b/usr/src/lib/libresolv2/common/cylink/bninit16.c new file mode 100644 index 0000000000..efe5bd3475 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bninit16.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bninit16.c - Provide an init function that sets things up for 16-bit + * operation. This is a seaparate tiny file so you can compile two bn + * packages into the library and write a custom init routine. + * + * Written in 1995 by Colin Plumb. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "bn.h" +#include "bn16.h" + +void +bnInit(void) +{ + bnInit_16(); +} diff --git a/usr/src/lib/libresolv2/common/cylink/bninit32.c b/usr/src/lib/libresolv2/common/cylink/bninit32.c new file mode 100644 index 0000000000..1f90d66780 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bninit32.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bninit32.c - Provide an init function that sets things up for 32-bit + * operation. This is a seaparate tiny file so you can compile two bn + * packages into the library and write a custom init routine. + * + * Written in 1995 by Colin Plumb. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "bn.h" +#include "bn32.h" + +void +bnInit(void) +{ + bnInit_32(); +} diff --git a/usr/src/lib/libresolv2/common/cylink/bnsize00.h b/usr/src/lib/libresolv2/common/cylink/bnsize00.h new file mode 100644 index 0000000000..d59f9f40ff --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/bnsize00.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * bnsize00.h - pick the correct machine word size to use. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "lbn.h" /* Get basic information */ + +#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD64) +# if defined(BNWORD128) || (defined(lbnMulAdd1_64) && defined(lbnMulSub1_64)) +# define BNSIZE64 1 +# elif defined(mul64_ppmm) || defined(mul64_ppmma) || defined(mul64_ppmmaa) +# define BNSIZE64 1 +# endif +#endif + +#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD32) +# if defined(BNWORD64) || (defined(lbnMulAdd1_32) && defined(lbnMulSub1_32)) +# define BNSIZE32 1 +# elif defined(mul32_ppmm) || defined(mul32_ppmma) || defined(mul32_ppmmaa) +# define BNSIZE32 1 +# endif +#endif + +#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD16) +# if defined(BNWORD32) || (defined(lbnMulAdd1_16) && defined(lbnMulSub1_16)) +# define BNSIZE16 1 +# elif defined(mul16_ppmm) || defined(mul16_ppmma) || defined(mul16_ppmmaa) +# define BNSIZE16 1 +# endif +#endif + +#if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 +#error Unable to find a viable word size to compile bignum library. +#endif diff --git a/usr/src/lib/libresolv2/common/cylink/c_asm.h b/usr/src/lib/libresolv2/common/cylink/c_asm.h new file mode 100644 index 0000000000..c22bc614fb --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/c_asm.h @@ -0,0 +1,140 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: c_asm.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: C / ASM Header File +* +* USAGE: File should be included to use Toolkit Functions +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 14 Oct 94 GKL For Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support ) +* +****************************************************************************/ +#if !defined( C_ASM_H ) +#define C_ASM_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include "cylink.h" +#include "ctk_endian.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + int Sum_big (ord *X, + ord *Y, + ord *Z, + int len_X ); + int Sum (ord *X, ord *Y, ushort len_X ); + int Sub_big (ord *X, + ord *Y, + ord *Z, + int len_X ); +/* + void Mul_big( ord *X, ord *Y,ord *XY, + ushort lx, ushort ly, + ushort elements_in_X, + ushort elements_in_Y);*/ + void Mul_big( ord *X, ord *Y,ord *XY, + ushort lx, ushort ly); + + void PReLo_big( ord *X, ord *P, + ushort len_X, ushort el); + + void Div_big( ord *X, ord *P, + ushort len_X, ushort el, + ord *div); + +int LeftMostBit_big ( ord X ); +int LeftMostEl_big( ord *X, ushort len_X ); +void RShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit ); +void LShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit ); +int RShiftMostBit(ord *a, u_int32_t len); +void ByteLong(uchar *X, u_int32_t X_bytes, u_int32_t *Y); +void ByteOrd(uchar *X, u_int32_t X_bytes, ord *Y); +void OrdByte(ord *X, u_int32_t X_bytes, uchar *Y); +void LongByte(u_int32_t *X, u_int32_t X_bytes, uchar *Y); +int BitValue_big( ord *X, ushort n_bits ); +int BitsValue_big( ord *X, ushort n_bits, ushort bit_count ); +void ByteSwap32_big( uchar *X, ushort X_len ); +void Complement_big( ord *X, ushort X_longs); +void Diagonal_big (ord *X, ushort X_len, ord *X2); +void Square_big( ord *X, ushort X_len, ord *X2); +void Mul_big_1( ord X, ord *Y, ord *XY, ushort ly ); +int Sum_Q(ord *X, ushort src, ushort len_X ); + + + +/* In-place DES encryption */ + void DES_encrypt(uchar *keybuf, uchar *block); + +/* In-place DES decryption */ + void DES_decrypt(uchar *keybuf, uchar *block); + +/* In-place KAPPA encryption */ + void KAPPA_encrypt(uchar *a, uchar *k, ushort r); + +/* In-place KAPPA decryption */ + void KAPPA_decrypt(uchar *a, uchar *k, ushort r); + +#ifdef __cplusplus +} +#endif + + +#endif /*C_ASM_H*/ + diff --git a/usr/src/lib/libresolv2/common/cylink/cencrint.h b/usr/src/lib/libresolv2/common/cylink/cencrint.h new file mode 100644 index 0000000000..16adb10348 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/cencrint.h @@ -0,0 +1,262 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: cencrint.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Internal Functions Header File +* +* USAGE: File should be included to use Toolkit Functions +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 23 Aug 94 KPZ Initial release +* 24 Sep 94 KPZ Added prototypes of internal functions +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context to Expo, VerPrime and GenPrime +* +****************************************************************************/ + +#ifndef CENCRINT_H /* Prevent multiple inclusions of same header file */ +#define CENCRINT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +/* system files */ +#include <sys/types.h> +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Compute a modulo */ + int PartReduct( u_int16_t X_bytes, ord *X, + u_int16_t P_bytes, ord *P, + ord *Z ); + +/* Compute a modulo product */ + int Mul( u_int16_t X_bytes, ord *X, + u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, + ord *Z ); +/*Compute a modulo squaring*/ +int Mul_Squr( u_int16_t X_bytes, ord *X, + u_int16_t P_bytes, ord *P, + ord *Z ); +int Square( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z ); + +/*Compare two array*/ +int Comp_Mont ( ord *X, ord *P, u_int16_t P_longs ); +/*Compute invers element*/ +ord Inv_Mont ( ord x ); +/*Modulo by the Mongomery*/ +void PartReduct_Mont( ord *X, u_int16_t P_bytes, ord *P, ord inv ); +/*Computes squaring by the Mongomery modulo*/ +int Mul_Squr_Mont(ord *X, u_int16_t P_bytes, + ord *P, ord *Z, + ord inv ); +/*Computes multiply by the montgomery modulo*/ +int Mul_Mont( ord *X, ord *Y, + u_int16_t P_bytes, ord *P, + ord *Z, ord inv ); + +/* Compute a modulo exponent */ + int Expo( u_int16_t X_bytes, ord *X, + u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, + ord *Z ); + /*Compute double exponent */ + int DoubleExpo( u_int16_t X1_bytes,ord *X1, + u_int16_t Y1_bytes,ord *Y1, + u_int16_t X2_bytes,ord *X2, + u_int16_t Y2_bytes,ord *Y2, + u_int16_t P_bytes,ord *P, + ord *Z); +/* Compute a modulo inverse element */ + int Inverse( u_int16_t X_bytes, ord *X, + u_int16_t P_bytes, ord *P, + ord *Z ); + +/* Verify Pseudo Prime number */ + int VerPrime( u_int16_t P_bytes, ord *P, + u_int16_t k, ord *RVAL, + YIELD_context *yield_cont ); /*TKL00601*/ + +/* Generate Random Pseudo Prime number */ + int GenPrime( u_int16_t P_bytes, ord *P, + u_int16_t k, ord *RVAL, + YIELD_context *yield_cont ); /*TKL00601*/ + +/* Transfer bytes to u_int32_t */ + void ByteLong( uchar *X, + u_int16_t X_bytes, + u_int32_t *Y ); + +/* Transfer u_int32_t to bytes */ + void LongByte( u_int32_t *X, + u_int16_t X_bytes, + uchar *Y ); + +/* Transfer bytes to ord */ + void ByteOrd( uchar *X, + u_int16_t X_bytes, + ord *Y ); + +/* Transfer ord to bytes */ + void OrdByte( ord *X, + u_int16_t X_bytes, + uchar *Y ); + +/* Find the left most non zero bit */ + int LeftMostBit ( ord X ); + +/* Find the left most element */ + int LeftMostEl( ord *X, + u_int16_t len_X ); + +/* Shift array to rigth by n_bit */ + void RShiftL( ord *X, + u_int16_t len_X, + u_int16_t n_bit ); + +/* Shifts array to left by n_bit */ + void LShiftL( ord *X, + u_int16_t len_X, + u_int16_t n_bit ); + +/* Find the value of bit */ + int BitValue( ord *X, + u_int16_t n_bits ); + +/* Perform byte reversal on an array of ordinar type (longword or shortword) */ + void ByteSwap( uchar *X, + u_int16_t X_len ); + +/* Perform byte reversal on an array from LSB to MSB */ + void BigSwap( uchar *X, + u_int16_t X_len ); + +/* Perform byte reversal on an array of longword */ + void ByteSwap32( uchar *X, + u_int16_t X_len ); + +/* Perform short reversal on an array of longword */ + void WordSwap( uchar *X, + u_int16_t X_len ); + +/* Perform SHS transformation */ + void shaTransform( u_int32_t *state, + const uchar *block ); + +/* Compute modulo addition + int Add( ord *X, + ord *Y, + u_int16_t P_len, + ord *P, + ord *Z ); + */ + int Add( ord *X, + ord *Y, + u_int16_t P_len, + ord *P ); +/* Initialize Secure Hash Function for generate + random number for DSS */ + void SHAInitK( SHA_context *hash_context ); + +/* Set parity bits */ + void SetKeyParity( uchar *key ); + +/* Find a least significant non zero bit + and sfift array to right */ + int RShiftMostBit( ord *a, u_int16_t len ); + +/*Compute great common divisor */ + int SteinGCD( ord *m, ord *b, u_int16_t len ); + +/* Compute a modulo and divisor */ + int DivRem( u_int16_t X_bytes, ord *X, + u_int16_t P_bytes, ord *P, + ord *Z, ord *D ); + +/* Generate random number */ +int MyGenRand( u_int16_t A_bytes, ord *A, + ord *RVAL); + +/* Compute a Secure Hash Function */ +int MySHA( uchar *message, + u_int16_t message_bytes, + uchar *hash_result ); + +/* Finalize Secure Hash Function */ + int MySHAFinal( SHA_context *hash_context, + uchar *hash_result ); + + void shaTransform_new( u_int32_t *state, + uchar *block ); + + +#ifdef __cplusplus +} +#endif + + +#endif /* CENCRINT_H */ + diff --git a/usr/src/lib/libresolv2/common/cylink/ctk_endian.h b/usr/src/lib/libresolv2/common/cylink/ctk_endian.h new file mode 100644 index 0000000000..1e5a27682f --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/ctk_endian.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**********************************************************************\ +* FILENAME: ctk_endian.h PRODUCT NAME: +* +* DESCRIPTION: header file of defines +* +* USAGE: Platform-dependend compilation modes header +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +\**********************************************************************/ + +#ifndef CTK_ENDIAN_H /* Prevent multiple inclusions of same header file */ +#define CTK_ENDIAN_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <ctype.h> +#include <arpa/nameser_compat.h> +#include "lbn.h" + +#if (defined(BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) +# undef BIG_ENDIAN +# undef _BIG_ENDIAN +# define BIG_ENDIAN 4321 +# define LITTLE_ENDIAN 1234 +# define BYTE_ORDER BIG_ENDIAN + +#elif !(defined(BIG_ENDIAN) || defined(_BIG_ENDIAN)) && (defined(LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) +# undef LITTLE_ENDIAN +# undef _LITTLE_ENDIAN +# define BIG_ENDIAN 4321 +# define LITTLE_ENDIAN 1234 +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if !defined(BYTE_ORDER) || \ + (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN) + /* you must determine what the correct bit order is for + * your compiler - the next line is an intentional error + * which will force your compiles to bomb until you fix + * the above macros. + */ +# if !defined(CTK_LITTLE_ENDIAN) && !defined(CTK_BIG_ENDIAN) +# error "Undefined or invalid BYTE_ORDER"; +# endif +#endif + +#if !defined(CTK_BIG_ENDIAN) && !defined(CTK_LITTLE_ENDIAN) +# ifdef BYTE_ORDER +# if (BYTE_ORDER == LITTLE_ENDIAN) +# define CTK_LITTLE_ENDIAN +# elif (BYTE_ORDER == BIG_ENDIAN) +# define CTK_BIG_ENDIAN +# else +# error CAN NOT determine ENDIAN with BYTE_ORDER +# endif +# elif defined(_LITTLE_ENDIAN) +# define CTK_LITTLE_ENDIAN +# elif defined(_BIG_ENDIAN) +# define CTK_BIG_ENDIAN +# else +# error CAN NOT determine ENDIAN +# endif +#endif + +#if !defined(CTK_BIG_ENDIAN) && !defined(CTK_LITTLE_ENDIAN) +# error NO CTK_???_ENDIAN defined +#endif + +#if defined( CTK_LITTLE_ENDIAN ) && defined( CTK_BIG_ENDIAN ) +# error Use only one define CPU type CTK_LITTLE or BIG ENDIAN. +#endif + +#if !defined( ORD_32 ) && !defined( ORD_16 ) +# ifdef BNSIZE64 +# error BNSIZE64 do not know how to do this +# elif defined(BNSIZE32) +# define ORD_32 +# elif defined(BNSIZE16) +# define ORD_16 +# elif !defined( UINT_MAX) /* No <limits.h> */ +# define ORD_16 /* default */ +# else +# if ULONG_MAX == 0xffffffff +# define ORD_16 +# else +# define ORD_32 +# endif +# endif +#endif + +#if !defined( ORD_32 ) && !defined( ORD_16 ) +#error Not defined basic word type ORD_32 or ORD_16. +#endif + +#if defined( ORD_32 ) && defined( ORD_16 ) +#error Use only one define basic word type ORD_32 or ORD_16. +#endif + + +#ifdef ORD_16 +/* typedef unsigned short ord; deleted by ogud@tis.com 1998/9/14 */ +typedef u_int16_t ord; +#define BITS_COUNT 16 +#define MAXDIGIT (ord)(0xFFFF) +#endif + +#ifdef ORD_32 +/* typedef unsigned long ord; deleted by ogud@tis.com 1998/9/14 */ +typedef u_int32_t ord; +#define BITS_COUNT 32 +#define MAXDIGIT (ord)(0xFFFFFFFF) +#endif /* ORD_32 */ + + + +#define CALLOC(var,type,len) \ + var=(type *)calloc(len,1); \ + if (var==NULL) \ + status=ERR_ALLOC +#ifdef CTK_BIG_ENDIAN +#define ALIGN_CALLOC(i,o,l) \ + CALLOC(o,ord,l) +#define ALIGN_CALLOC_COPY(i,o,l) \ + CALLOC(o,ord,l); \ + if (o) ByteOrd(i,l,o) +#define ALIGN_CALLOC_MOVE(i,o,l) \ + CALLOC(o,ord,l); \ + if (o) memcpy(o,i,l) +#define ALIGN_FREE(o) \ + free ( o ) +#define ALIGN_COPY_FREE(o,i,l) \ + if ((o) && (status==SUCCESS)) \ + OrdByte(o,l,i); \ + free (o) +#define ALIGN_MOVE_FREE(o,i,l) \ + if ((o) && (status==SUCCESS)) \ + memcpy(i,o,l); \ + memset(o,0,l); \ + free (o) +#else +#define ALIGN_CALLOC(i,o,l) o=(ord *)i +#define ALIGN_CALLOC_COPY(i,o,l) o=(ord *)i +#define ALIGN_CALLOC_MOVE(i,o,l) o=(ord *)i +#define ALIGN_FREE(o) ; +#define ALIGN_COPY_FREE(o,i,l) ; +#define ALIGN_MOVE_FREE(o,i,l) ; +#endif +#define DSS_P_ALIGN_CALLOC_COPY(i,o,l) \ + if (i) \ + { ALIGN_CALLOC_COPY(i,o,l);} \ + else \ + o = &DSS_P_NUMBERS[DSS_NUM_INDEX[(l-DSS_LENGTH_MIN)/LENGTH_STEP]] + +#define DSS_G_ALIGN_CALLOC_COPY(i,o,l) \ + if (i) \ + { ALIGN_CALLOC_COPY(i,o,l);} \ + else \ + o = &DSS_G_NUMBERS[DSS_NUM_INDEX[(l-DSS_LENGTH_MIN)/LENGTH_STEP]] + +#define DSS_Q_ALIGN_CALLOC_COPY(i,o,l) \ + if (i) \ + { ALIGN_CALLOC_COPY(i,o,l);} \ + else \ + o = DSS_Q_NUMBER + +#define DSS_ALIGN_FREE(o,i) \ + if (i) \ + { ALIGN_FREE(o);} +#endif /* CTK_ENDIAN_H */ diff --git a/usr/src/lib/libresolv2/common/cylink/ctk_prime.c b/usr/src/lib/libresolv2/common/cylink/ctk_prime.c new file mode 100644 index 0000000000..45b576eb3f --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/ctk_prime.c @@ -0,0 +1,442 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: prime.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Internal Functions File +* Prime Number functions +* PRIVATE FUNCTIONS: +* +* int VerPrime( u_int16_t P_bytes, ord *P, +* u_int16_t k, ord *RVAL, +* YIELD_context *yield_cont ) +* int GenPrime( u_int16_t P_bytes, ord *P, +* u_int16_t k, ord *RVAL, +* YIELD_context *yield_cont ) +* Copyright (c) Cylink Corporation 1996. All rights reserved. +* +* REVISION HISTORY: +* +* +****************************************************************************/ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +#include "port_before.h" +#include <sys/types.h> +#include "cylink.h" +#include "ctk_endian.h" + +/* system files */ +#ifdef VXD +#include <vtoolsc.h> +#else +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#endif + +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "cencrint.h" +#include "port_after.h" + +/**************************************************************************** +* PRIVATE FUNCTIONS DEFINITIONS +****************************************************************************/ +/**************************************************************************** +* NAME: int VerPrime( u_int16_t P_bytes, +* ord *P, +* u_int16_t k, +* ord *RVAL, +* YIELD_context *yield_cont ) +* +* DESCRIPTION: Verify Pseudo Prime number +* +* INPUTS: +* PARAMETERS: +* u_int16_t P_bytes Number of bytes in array +* u_int16_t k Number of testing +* ord *RVAL Pointer to random number generator value +* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used) +* OUTPUT: +* PARAMETERS: +* ord *P Pointer to prime number +* ord *RVAL Pointer to updated value +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_PRIME Number is not prime +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context +* +****************************************************************************/ + + int VerPrime( u_int16_t P_bytes, + ord *P, + u_int16_t k, + ord *RVAL, + YIELD_context *yield_cont ) /*TKL00601*/ + +{ + int status = SUCCESS; /*function return status*/ + ord *b, *n, *c, *pp; /*pointers to working buffers */ + ord *m, *buf, *P_buf; + u_int16_t max_bytes; /*number of maximum bytes*/ + u_int16_t P_longs; /*number of longs in Y*/ + u_int16_t i, j, s, k_b; /*counters*/ + u_int16_t exit ; /*flag for exit*/ +/* product of prime numbers from 3 to 379 (512-bit number) */ +#ifdef ORD_32 + ord b1[DSS_LENGTH_MIN/sizeof(ord)]={ + 0x2e30c48fL, 0x0decece9L, 0xbada8f98L, 0x9f7ecb29L, + 0xa4a11de4L, 0x6ef04659L, 0xcbc38405L, 0x233db117L, + 0x03e81187L, 0xc1b631a2L, 0x238bfb99L, 0x077ec3baL, + 0xc5d5f09fL, 0xb0813c28L, 0x7646fa6eL, 0x106aa9fbL }; +#else + ord b1[DSS_LENGTH_MIN/sizeof(ord)]={ + 0xc48f, 0x2e30, 0xece9, 0x0dec, 0x8f98, 0xbada, 0xcb29, 0x9f7e, + 0x1de4, 0xa4a1, 0x4659, 0x6ef0, 0x8405, 0xcbc3, 0xb117, 0x233d, + 0x1187, 0x03e8, 0x31a2, 0xc1b6, 0xfb99, 0x238b, 0xc3ba, 0x077e, + 0xf09f, 0xc5d5, 0x3c28, 0xb081, 0xfa6e, 0x7646, 0xa9fb, 0x106a }; +#endif + if ( P_bytes % sizeof(ord) != 0 ) /* not multiple 4 (32 bit) */ + { + status = ERR_INPUT_LEN; /* invalid length for input data */ + return status; + } + if ( P_bytes <= DSS_LENGTH_MIN ) + { + max_bytes = DSS_LENGTH_MIN; + } + else + { + max_bytes = P_bytes; + } + buf = (ord *)calloc( max_bytes / sizeof(ord), sizeof(ord) ); + P_buf = (ord *)calloc( max_bytes / sizeof(ord), sizeof(ord)); + if( !buf || !P_buf ) + { + if ( buf ) + free( buf ); + if( P_buf ) + free( P_buf ); + return ERR_ALLOC; + } + memcpy( buf, b1, DSS_LENGTH_MIN ); + memcpy( P_buf, P, P_bytes ); + + if ( (P_buf[0] & 0x1) == 0 ) + { +#ifdef DEBUG1 + printf ("\n P is not pseudoprime"); +#endif + status = ERR_PRIME; + free ( buf ); + free( P_buf ); + return status; + } + P_longs = (u_int16_t) (P_bytes / sizeof(ord)); + b = (ord *)calloc( P_longs, sizeof(ord) ); + m = (ord *)malloc( P_longs * sizeof(ord) ); + n = (ord *)calloc( P_longs, sizeof(ord) ); + c = (ord *)calloc( P_longs, sizeof(ord) ); + pp = (ord *)malloc( P_longs * sizeof(ord) ); + if( !b || !m || !n || !c || !pp ) + { + if( b ) + free( b ); + if( m ) + free( m ); + if( n ) + free( n ); + if( c ) + free( c ); + if( pp ) + free ( pp ); + } + memcpy( m, P, P_bytes ); + memcpy( pp, P, P_bytes ); + /* Compute great common divisor(gcd) */ + if ( SteinGCD( P_buf, buf, (u_int16_t)(max_bytes / sizeof(ord)) ) == 0 ) + { + pp[0] = pp[0] - 1; /* Initialized work buffer */ + m[0] = m[0] - 1; + s = (u_int16_t) RShiftMostBit( m, (u_int16_t)(P_bytes / sizeof(ord)) ); /* Right shift by number of*/ + exit = 0; /* zero bits at rigth */ + k_b = 0; + while( k_b != k ) + { + MyGenRand( 4, b, RVAL ); /* generate random number */ + if ( SteinGCD( P_buf, b , (u_int16_t)(P_bytes / sizeof(ord)) ) ) /* check gcd */ + { +#ifdef DEBUG1 + printf ("\n P is not pseudoprime"); +#endif + status = ERR_PRIME; + break; + } + k_b++; /* increment counter */ + if ( ( status = Expo ( 4, b, P_bytes, m, + P_bytes, P, c ) ) != SUCCESS ) /* c=b^m mod(P) */ /*TKL00601*/ + { + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free (buf ); + free( P_buf ); + return status; + } + if ( c[0] == 1 ) /* if c==1 number is pseudo prime */ + { + for ( i = 1; i < P_bytes / sizeof(ord); i++ ) + { + if ( c[i] != 0 ) + { + break; + } + } + if ( i == P_bytes / sizeof(ord) ) + { + if (yield_cont) /*TKL00601*/ +#ifdef VXD + if ( VXD_Yield (yield_cont->yield_proc) ) +#else + if ( yield_cont->yield_proc(0xFFFF) ) +#endif + + { + status = ERR_CANCEL; + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; + } +#ifdef DEBUG1 + printf ("\n P is a pseudoprime %d",k_b); +#endif + if ( k_b == k ) + { + break; + } + } + } + else + { + for ( j = 1; j <= s; j++ ) + { + for ( i = 0; i < P_bytes / sizeof(ord); i++ ) /* if c==pp number is pseudo prime */ + { + if ( c[i] != pp[i] ) + { + break; + } + } + if ( i == P_bytes / sizeof(ord) ) + { + if (yield_cont) /*TKL00601*/ +#ifdef VXD + if ( VXD_Yield (yield_cont->yield_proc) ) +#else + if ( yield_cont->yield_proc(0xFFFF) ) +#endif + + { + status = ERR_CANCEL; + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; + } +#ifdef DEBUG1 + printf ("\n P is a pseudoprime %d",k_b); +#endif + break; + } + if ( j == s ) + { +#ifdef DEBUG1 + printf ("\n P is not pseudoprime"); +#endif + status = ERR_PRIME; + exit = 1; + break; + } + else + { + if ( (status = Square(P_bytes, c, /*P_bytes, + c,*/ P_bytes, P, c) ) + != SUCCESS ) /* c=c^2mod(p) */ + { + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; + } + } + } + } + if ( exit == 1 ) /* Exit */ + { + break; + } + } + } + else + { + if (yield_cont) /*TKL00601*/ +#ifdef VXD + if ( VXD_Yield (yield_cont->yield_proc) ) +#else + if ( yield_cont->yield_proc(0xFFFF) ) +#endif + + { + status = ERR_CANCEL; + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; + } +#ifdef DEBUG1 + printf ("\n P is not pseudoprime"); +#endif + status = ERR_PRIME; + } + free( b ); + free( m ); + free( n ); + free( c ); + free( pp ); + free( P_buf ); + free (buf ); + return status; +} + +/**************************************************************************** +* NAME: int GenPrime( u_int16_t P_bytes, +* ord *P, +* u_int16_t k, +* ord *RVAL, +* YIELD_context *yield_cont ) +* +* DESCRIPTION: Generate Random Pseudo Prime number +* +* INPUTS: +* PARAMETERS: +* u_int16_t P_bytes Number of bytes in array +* u_int16_t k Number of testing +* ord *RVAL Pointer to random number generator value +* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used) +* OUTPUT: +* PARAMETERS: +* ord *P Pointer to prime number +* ord *RVAL Pointer to updated value +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_PRIME Number is not prime +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context +* +****************************************************************************/ + + int GenPrime( u_int16_t P_bytes, + ord *P, + u_int16_t k, + ord *RVAL, + YIELD_context *yield_cont ) /*TKL00601*/ +{ + int status = SUCCESS; /* function return status */ + if ( P_bytes % sizeof(ord) != 0 ) /* not multiple 4 (32 bit) */ + { + status = ERR_INPUT_LEN; /* invalid length for input data */ + return status; + } + do + { + MyGenRand( P_bytes, P, RVAL ); /* generate random number */ + P[0] |= 1; + P[(P_bytes/sizeof(ord))-1] |= ((ord)1 << (BITS_COUNT-1)); + status = VerPrime( P_bytes, P, k, RVAL, yield_cont); /*TKL00601*/ + } while ((status != SUCCESS) && (status != ERR_CANCEL)); /*TKL00601*/ + return status; +} + diff --git a/usr/src/lib/libresolv2/common/cylink/cylink.h b/usr/src/lib/libresolv2/common/cylink/cylink.h new file mode 100644 index 0000000000..1ebbfbbd92 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/cylink.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**********************************************************************\ +* FILENAME: cylink.h PRODUCT NAME: +* +* DESCRIPTION: Company standard include file +* +* USAGE: File should be #included +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +\**********************************************************************/ + +#ifndef CYLINK_H /* Prevent multiple inclusions of same header file */ +#define CYLINK_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +# include <sys/bitypes.h> +#else +# include <sys/types.h> +#endif + +#if ! ( defined(__alpha) && defined(__osf__) ) /* in sys/types.h */ +#if !defined(_H_INTTYPES) && !defined (_H_TYPES) /* AIX puts this in inttypes.h */ +typedef unsigned char uchar; +#endif /* _H_INTTYPES */ +#endif + +typedef u_int16_t USHORT; +typedef u_int32_t ULONG; + +#define FALSE 0 +#define TRUE 1 + +/*-- ANSI-recommended NULL Pointer definition --*/ +#ifndef NULL +#define NULL (void *) 0 +#endif + +#endif /* CYLINK_H */ diff --git a/usr/src/lib/libresolv2/common/cylink/dss.c b/usr/src/lib/libresolv2/common/cylink/dss.c new file mode 100644 index 0000000000..fe907a6f21 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/dss.c @@ -0,0 +1,1209 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: dss.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Functions File +* Digital Signature Algorithms +* PUBLIC FUNCTIONS: +* uchar *RVAL ) +* int GenDSSKey( u_int16_t dss_p_bytes, uchar *dss_p, +* uchar *dss_q, uchar *dss_g, +* uchar *dss_x, uchar *dss_y, +* uchar *XKEY ) +* +* int GenDSSNumber( uchar *dss_k, uchar dss_q, +* uchar *KKEY ) +* int GenDSSParameters( u_int16_t dss_p_bytes, uchar *dss_p, +* uchar *dss_q, uchar *dss_g, +* uchar *RVAL ); +* +* Copyright (c) Cylink Corporation 1996. All rights reserved. +* +* REVISION HISTORY: +* +* +****************************************************************************/ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +#include "port_before.h" +#include <sys/types.h> +#include "cylink.h" +#include "ctk_endian.h" + +/* system files */ +#ifdef VXD +#include <vtoolsc.h> +#else +#include <stdlib.h> +#include <string.h> +#endif + +/* program files */ +#ifdef VXD +#include "tkvxd.h" +#endif +#include "toolkit.h" +#include "cencrint.h" +#define INITIALIZ_PQG /*TKL01101*/ +#include "dssnum.h" /*TKL01101*/ +#include "sha.h" +#include "port_after.h" + +#define BEGIN_PROCESSING do { +#define END_PROCESSING } while (0); +#define ERROR_BREAK break +#define CONTINUE continue + +#define BEGIN_LOOP do { +#define END_LOOP } while (1); +#define BREAK break + + +extern u_int16_t DataOrder; + +/**************************************************************************** +* NAME: int GenDSSSignature( u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g, +* uchar *dss_x, +* uchar *dss_k, +* uchar *r, +* uchar *s, +* uchar *hash_result) +* +* DESCRIPTION: Compute a DSS Signature +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Length of dss_p +* uchar *dss_p Pointer to p prime +* uchar *dss_q Pointer to q prime +* uchar *dss_g Pointer to g +* uchar *dss_x Pointer to secret number +* uchar *dss_k Pointer to random secret number +* uchar *hash_result Pointer to message hashing result +* +* +* OUTPUT: +* PARAMETERS: +* uchar *r Pointer to r part of signature +* uchar *s Pointer to s part of signature +* +* RETURN: +* E_SUCCESS No errors +* E_DSS_LEN Invalid length for dss_p +* ERR_ALLOC Insufficient memory +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Dec 94 GKL Changed Expo call +* +****************************************************************************/ + +int GenDSSSignature( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *dss_x, + uchar *dss_k, + uchar *r, + uchar *s, + uchar *hash_result) + +{ + int status = SUCCESS; /* function return status */ + ord r_temp[DSS_LENGTH_MAX]; /* r intermidiate value */ + ord k_inverse[SHA_LENGTH+1]; + ord temp[SHA_LENGTH+1]; /* intermidiate values */ + ord *dss_p_a; + ord *dss_g_a; + ord *dss_q_a; + ord *dss_x_a; + ord *dss_k_a; + ord *hash_result_a; + ord *r_a; + ord *s_a; + + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + } + + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + + ALIGN_CALLOC_COPY(dss_x, dss_x_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(dss_k, dss_k_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(hash_result, hash_result_a, SHA_LENGTH); + ALIGN_CALLOC(r, r_a, SHA_LENGTH); + ALIGN_CALLOC(s, s_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( dss_p_a ) + DSS_ALIGN_FREE(dss_p_a,dss_p); + if( dss_g_a ) + DSS_ALIGN_FREE(dss_g_a,dss_g); + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_x_a ) + { + memset ( dss_x_a , 0 , SHA_LENGTH ); + ALIGN_FREE(dss_x_a); + } + if( dss_k_a ) + { + ALIGN_FREE(dss_k_a); + } + if( hash_result_a ) + { + ALIGN_FREE(hash_result_a); + } + if( r_a ) + { + ALIGN_COPY_FREE(r_a,r,SHA_LENGTH); + } + if( s_a ) + { + ALIGN_COPY_FREE(s_a,s,SHA_LENGTH); + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + +/* Compute DSS r value */ + BEGIN_PROCESSING + if (( status = Expo ( dss_p_bytes, + dss_g_a, + SHA_LENGTH, /* r_temp=(dss_g^dss_k)mod(dss_p)*/ + dss_k_a, + dss_p_bytes, + dss_p_a, + r_temp )) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( dss_p_bytes, + r_temp, + SHA_LENGTH, /* r=(r_temp)mod(dss_q) */ + dss_q_a, + r_a )) != SUCCESS ) + { + ERROR_BREAK; + } +/* Compute k modulo inverse value */ + if (( status = Inverse( SHA_LENGTH, /* k_inverse=dss_k^(-1)mod(dss_q)*/ + dss_k_a, + SHA_LENGTH, + dss_q_a, + k_inverse )) != SUCCESS ) + { + ERROR_BREAK; + } +/* Compute DSS s value */ + if (( status = Mul ( SHA_LENGTH, /* temp=(dss_x*r)mod(dss_q) */ + dss_x_a, + SHA_LENGTH, + r_a, + SHA_LENGTH, + dss_q_a, + temp )) != SUCCESS ) + { + ERROR_BREAK; + } + + /* Add( temp, hash_result_a, + SHA_LENGTH, dss_q_a, temp ); temp=(temp+hash_result)mod(dss_q)*/ + + Add( temp, hash_result_a, + SHA_LENGTH, dss_q_a ); + if (( status = Mul ( SHA_LENGTH, /* s=(temp*k_inverse)mod(dss_q) */ + temp, + SHA_LENGTH, + k_inverse, + SHA_LENGTH, + dss_q_a, + s_a )) != SUCCESS ) + { + ERROR_BREAK; + } + END_PROCESSING + + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_FREE(dss_x_a); + ALIGN_FREE(dss_k_a); + ALIGN_FREE(hash_result_a); + ALIGN_COPY_FREE(r_a,r,SHA_LENGTH); + ALIGN_COPY_FREE(s_a,s,SHA_LENGTH); + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + return status; +} + +/**************************************************************************** +* NAME: int VerDSSSignature( u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g, +* uchar *dss_y, +* uchar *r, +* uchar *s, +* uchar *hash_result) +* +* DESCRIPTION: Verify a DSS Signature +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Length of dss_p +* uchar *dss_p Pointer to p prime +* uchar *dss_q Pointer to q prime +* uchar *dss_g Pointer to g +* uchar *dss_y Pointer to public number +* uchar *hash_result Pointer to message hashing result +* OUTPUT: +* PARAMETERS: +* +* RETURN: +* SUCCESS No errors +* ERR_SIGNATURE Signature is not valid +* ERR_DSS_LEN Invalid length for dss_p +* ERR_ALLOC Insufficient memory +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Dec 94 GKL Changed Expo call +* 21 Aug 96 AAB DoubleExpo call +****************************************************************************/ + +int VerDSSSignature( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *dss_y, + uchar *r, + uchar *s, + uchar *hash_result) +{ + int status = SUCCESS; /* function return status */ + ord w[(SHA_LENGTH / sizeof(ord)) + 1]; + ord u1[SHA_LENGTH / sizeof(ord)]; + ord u2[SHA_LENGTH / sizeof(ord)]; + ord *v; + ord *dss_p_a; + ord *dss_g_a; + ord *dss_q_a; + ord *dss_y_a; + ord *hash_result_a; + ord *r_a; + ord *s_a; + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + + ALIGN_CALLOC_COPY(dss_y, dss_y_a, dss_p_bytes); + ALIGN_CALLOC_COPY(hash_result, hash_result_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(r, r_a, SHA_LENGTH); + ALIGN_CALLOC_COPY(s, s_a, SHA_LENGTH); + CALLOC(v,ord,dss_p_bytes); + + if ( status != SUCCESS ) + { + if( dss_p_a ) + { + DSS_ALIGN_FREE(dss_p_a,dss_p); + } + if( dss_g_a ) + { + DSS_ALIGN_FREE(dss_g_a,dss_g); + } + if ( dss_q_a ) + { + DSS_ALIGN_FREE(dss_q_a,dss_q); + } + if( dss_y_a ) + { + ALIGN_FREE(dss_y_a); + } + if( hash_result_a ) + { + ALIGN_FREE(hash_result_a); + } + if( r_a ) + { + ALIGN_FREE(r_a); + } + if( s_a ) + { + ALIGN_FREE(s_a); + } + if( v ) + { + free ( v ); + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + if (( status = Inverse( SHA_LENGTH, /* w=dss_k^(-1)mod(dss_q)*/ + s_a, + SHA_LENGTH, + dss_q_a, + w )) !=SUCCESS ) + { + ERROR_BREAK; + } + if (( status = Mul ( SHA_LENGTH, /* u1=(hash_result_*w)mod(dss_q) */ + hash_result_a, + SHA_LENGTH, + w, + SHA_LENGTH, + dss_q_a, + u1 )) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = Mul ( SHA_LENGTH, /* u2=(r*w)mod(dss_q) */ + r_a, + SHA_LENGTH, + w, + SHA_LENGTH, + dss_q_a, + u2 )) != SUCCESS ) + { + ERROR_BREAK; + } + /* v = dss_g_a^u1*dss_y_a^u2 moddss_p_a */ + if((status = DoubleExpo( dss_p_bytes, dss_g_a, + SHA_LENGTH, u1, + dss_p_bytes, dss_y_a, + SHA_LENGTH, u2, + dss_p_bytes, dss_p_a, v)) != SUCCESS ) + { + + ERROR_BREAK; + } + if (( status = PartReduct ( dss_p_bytes, /*v = v mod(dss_q)*/ + v, + SHA_LENGTH, + dss_q_a, + v )) != SUCCESS ) + { + ERROR_BREAK; + } + + if (( status = memcmp( r_a, v, SHA_LENGTH)) != 0) /*if v=r sign valid */ + { + status = ERR_SIGNATURE; /* signature is not valid */ + ERROR_BREAK; + } + END_PROCESSING + free ( v ); + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_FREE(dss_y_a); + ALIGN_FREE(hash_result_a); + ALIGN_FREE(r_a); + ALIGN_FREE(s_a); + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_y, dss_p_bytes); + BigSwap(hash_result, SHA_LENGTH); + BigSwap(r, SHA_LENGTH); + BigSwap(s, SHA_LENGTH); + } + + return status; +} + + +/**************************************************************************** +* NAME: int GenDSSKey( u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g, +* uchar *dss_x, +* uchar *dss_y, +* uchar *XKEY ) +* +* +* DESCRIPTION: Compute DSS public/secret number pair. +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Length of modulo +* uchar *dss_p Pointer to modulo +* uchar *dss_q Pointer to modulo +* uchar *dss_g Pointer to public key +* uchar *XKEY Pointer to user supplied random number +* +* +* OUTPUT: +* PARAMETERS: +* uchar *dss_x Pointer to secret key +* uchar *dss_y Pointer to public key +* uchar *XKEY Pointer to updated number +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data +* ERR_DATA Generic data error +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Dec 94 GKL Changed Expo call +* +****************************************************************************/ + +int GenDSSKey( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *dss_x, + uchar *dss_y, + uchar *XKEY ) +{ + + int status = SUCCESS; /* function return status */ + SHA_context hash_context; /* SHA context structure */ + uchar M[DSS_LENGTH_MIN]; /* message block */ + ord *dss_p_a; + ord *dss_q_a; + ord *dss_g_a; + ord *dss_x_a; + ord *dss_y_a; + ord *XKEY_a; + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + } + + DSS_P_ALIGN_CALLOC_COPY(dss_p, dss_p_a, dss_p_bytes); /*TKL01101*/ + DSS_G_ALIGN_CALLOC_COPY(dss_g, dss_g_a, dss_p_bytes); /*TKL01101*/ + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + ALIGN_CALLOC(dss_x, dss_x_a, SHA_LENGTH); + ALIGN_CALLOC(dss_y, dss_y_a, dss_p_bytes); + if ( status != SUCCESS ) + { + if( dss_p_a ) + DSS_ALIGN_FREE(dss_p_a,dss_p); + if( dss_g_a ) + DSS_ALIGN_FREE(dss_g_a,dss_g); + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_x_a ) + { + memset(dss_x_a, 0, SHA_LENGTH ); + ALIGN_COPY_FREE(dss_x_a,dss_x,SHA_LENGTH); + } + if( dss_y_a ) + { + ALIGN_COPY_FREE(dss_y_a,dss_y,dss_p_bytes); + } + + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + SHAInit ( &hash_context ); + memcpy( M, XKEY, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + ERROR_BREAK; + } + if ( (status = MySHAFinal (&hash_context, (uchar *)dss_x_a)) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( SHA_LENGTH, /* dss_x = dss_x mod(dss_q)*/ + dss_x_a, + SHA_LENGTH, + dss_q_a, + dss_x_a )) != SUCCESS ) + { + ERROR_BREAK; + } + + BigSwap(XKEY, SHA_LENGTH); + ALIGN_CALLOC_COPY(XKEY, XKEY_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( XKEY_a ) + { + ALIGN_COPY_FREE(XKEY_a,XKEY,SHA_LENGTH); + BigSwap(XKEY, SHA_LENGTH); + return status; /* ERR_ALLOC insufficient memory */ + } + } + + Sum_Q((ord*)XKEY_a, 1, SHA_LENGTH / sizeof (ord) ); + + Sum_big( XKEY_a, dss_x_a, /* XKEY=XKEY+dss_x */ + XKEY_a, SHA_LENGTH / sizeof(ord) ); + + ALIGN_COPY_FREE(XKEY_a,XKEY,SHA_LENGTH); + BigSwap(XKEY, SHA_LENGTH); + + if (( status = Expo ( dss_p_bytes, /*dss_y = g^dss_x mod(dss_p)*/ + dss_g_a, + SHA_LENGTH, + dss_x_a, + dss_p_bytes, + dss_p_a, + dss_y_a)) != SUCCESS ) /*TKL00601*/ + { + ERROR_BREAK; + } + END_PROCESSING + + DSS_ALIGN_FREE(dss_p_a,dss_p); /*TKL01101*/ + DSS_ALIGN_FREE(dss_g_a,dss_g); /*TKL01101*/ + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + ALIGN_COPY_FREE(dss_x_a,dss_x,SHA_LENGTH); + ALIGN_COPY_FREE(dss_y_a,dss_y,dss_p_bytes); + if (DataOrder) + { + if (dss_p) + BigSwap(dss_p, dss_p_bytes); + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + if (dss_g) + BigSwap(dss_g, dss_p_bytes); + BigSwap(dss_x, SHA_LENGTH); + BigSwap(dss_y, dss_p_bytes); + } + + return status; +} + + + +/**************************************************************************** +* NAME: int GenDSSNumber( uchar *dss_k, +* uchar *dss_q, +* uchar *KKEY ) +* +* DESCRIPTION: Generate secret number +* +* INPUTS: +* PARAMETERS: +* uchar *KKEY Pointer to input random number +* uchar *dss_q Pointer to modulo +* +* +* OUTPUT: +* PARAMETERS: +* uchar *dss_x Pointer to secret number +* uchar *KKEY Pointer to updated KKEY +* +* RETURN: +* SUCCESS No errors +* ERR_DATA Generic data error +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* +****************************************************************************/ + +int GenDSSNumber( uchar *dss_k, + uchar *dss_q, + uchar *KKEY ) +{ + + int status = SUCCESS; /* function return status */ + ord *dss_k_a; + ord *dss_q_a; + ord *KKEY_a; + SHA_context hash_context; /* SHA context structure*/ + uchar M[DSS_LENGTH_MIN]; /* message block */ + + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + } + + DSS_Q_ALIGN_CALLOC_COPY(dss_q, dss_q_a, SHA_LENGTH); /*TKL01101*/ + ALIGN_CALLOC(dss_k, dss_k_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + if( dss_q_a ) + DSS_ALIGN_FREE(dss_q_a,dss_q); + if( dss_k_a ) + { + ALIGN_COPY_FREE(dss_k_a,dss_k,SHA_LENGTH); + } + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + BEGIN_PROCESSING + SHAInitK ( &hash_context ); + memcpy( M, KKEY, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + ERROR_BREAK; + } + if ( (status = MySHAFinal (&hash_context, (uchar *)dss_k_a)) != SUCCESS ) + { + ERROR_BREAK; + } + if (( status = PartReduct ( SHA_LENGTH, /* dss_k = dss_k mod(dss_q)*/ + dss_k_a, + SHA_LENGTH, + dss_q_a, + dss_k_a )) != SUCCESS ) + { + ERROR_BREAK; + } + BigSwap(KKEY, SHA_LENGTH); + ALIGN_CALLOC_COPY(KKEY, KKEY_a, SHA_LENGTH ); + if ( status != SUCCESS ) + { + if ( KKEY_a ) + { + ALIGN_COPY_FREE(KKEY_a,KKEY,SHA_LENGTH); + BigSwap(KKEY, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + + Sum_Q( KKEY_a, 1, SHA_LENGTH / sizeof(ord)); + + Sum_big( KKEY_a, dss_k_a, /* KKEY=KKEY+dss_k*/ + KKEY_a, SHA_LENGTH / sizeof(ord) ); + + ALIGN_COPY_FREE(KKEY_a,KKEY,SHA_LENGTH); + BigSwap(KKEY, SHA_LENGTH); + + END_PROCESSING + + DSS_ALIGN_FREE(dss_q_a,dss_q); /*TKL01101*/ + + ALIGN_COPY_FREE(dss_k_a,dss_k,SHA_LENGTH); + if (DataOrder) + { + if (dss_q) + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_k, SHA_LENGTH); + } + + return status; +} + + +/**************************************************************************** +* NAME: int GenDSSParameters( u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g, +* uchar *RVAL, +* YIELD_context *yield_cont ) +* +* DESCRIPTION: Generate DSS Common Parameters +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Number of bytes in dss_p +* uchar *RVAL Pointer to user supplied random number +* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used) +* OUTPUT: +* PARAMETERS: +* uchar *dss_p Pointer to N-byte prime number +* uchar *dss_q Pointer to SHA_LENGTH prime number +* uchar *dss_g Pointer to N-byte number +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_DSS_LEN; Invalid length for dss_p +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Dec 94 GKL Added YIELD_context +* +****************************************************************************/ + + int GenDSSParameters( u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g, + uchar *RVAL, + YIELD_context *yield_cont ) /*TKL00701*/ +{ + int status = SUCCESS; /* function return status */ + ord seed[SHA_LENGTH / sizeof (ord)]; + ord u[SHA_LENGTH / sizeof (ord)]; /* work buffers */ + ord u1[SHA_LENGTH / sizeof (ord)]; + ord *dss_p_a; + ord *dss_q_a; + ord *dss_g_a; + ord *RVAL_a; + ord ofone[SHA_LENGTH / sizeof(ord)]; + ord dss_q2[SHA_LENGTH / sizeof(ord) + 1]; /* dss_q2 = 2 * q */ + ord v[SHA_LENGTH / sizeof(ord)]; + ord *w, *c, *c1, *one, *e; /* Pointers to work buffers */ + u_int16_t i, n, count, offset, k; /* counters */ + u_int16_t dss_p_longs; /* number of longs */ + if ( dss_p_bytes == 0 ) /* invalid length for input data (zero bytes) */ + { + status = ERR_INPUT_LEN; + return status; + } + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 4 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + + n = (u_int16_t) (dss_p_bytes / SHA_LENGTH); /* SHA passes count */ + dss_p_longs = (u_int16_t) (dss_p_bytes / sizeof(ord)); /* number of long in dss_p */ + CALLOC(w, ord, (n + 1) * SHA_LENGTH); + CALLOC(c, ord, dss_p_bytes); + CALLOC(c1, ord, dss_p_bytes); + CALLOC(one, ord, dss_p_bytes); + CALLOC(e,ord, dss_p_bytes - SHA_LENGTH + sizeof(ord)); + ALIGN_CALLOC_MOVE(RVAL, RVAL_a, SHA_LENGTH); + ALIGN_CALLOC(dss_p, dss_p_a, dss_p_bytes); + ALIGN_CALLOC(dss_q, dss_q_a, SHA_LENGTH); + ALIGN_CALLOC(dss_g, dss_g_a, dss_p_bytes); + if ( status != SUCCESS ) + { + if( e ) + free ( e ); + if( one ) + free ( one ); + if( c ) + free ( c ); + if( w ) + free ( w ); + if( c1 ) + free ( c1 ); + if( dss_p_a ) + { + ALIGN_COPY_FREE(dss_p_a, dss_p, dss_p_bytes); + } + if( dss_q_a ) + { + ALIGN_COPY_FREE(dss_q_a, dss_q, SHA_LENGTH); + } + if( dss_g_a ) + { + ALIGN_COPY_FREE(dss_g_a, dss_g, dss_p_bytes); + } + if( RVAL_a ) + { + ALIGN_MOVE_FREE(RVAL_a, RVAL, SHA_LENGTH); + } + return status; /* ERR_ALLOC insufficient memory */ + } + one[0] = 1; + BEGIN_PROCESSING /* Generate DSS Common Parameters */ + + BEGIN_LOOP /* Generate prime & dss_p */ /*TKL00501*/ + /* generate prime number of length 160-bit */ + do + { + MyGenRand( SHA_LENGTH, seed, RVAL_a); /* generate random number */ + /* compute message digest from seed */ + if ( (status = MySHA((uchar *)seed, SHA_LENGTH, (uchar *)u)) != SUCCESS ) + { + break; /* error */ + } + memcpy(ofone, seed,SHA_LENGTH); + Sum_Q( ofone, 1, SHA_LENGTH / sizeof(ord) ); + /* compute message digest from seed */ + if ( (status = MySHA( (uchar *)ofone, SHA_LENGTH,(uchar *)dss_q_a)) != SUCCESS ) + { + break; /* error */ + } + + for ( i = 0; i < (SHA_LENGTH / sizeof(ord)); i++ ) /* dss_q = dss_q ^ u */ + { + dss_q_a[i] = dss_q_a[i] ^ u[i]; + } + /* set least and most significant bits */ + dss_q_a[SHA_LENGTH / sizeof(ord) - 1] |= ((ord)1 << (BITS_COUNT-1)); + dss_q_a[0] |= 0x01; + } while ( VerPrime( SHA_LENGTH, dss_q_a, TEST_COUNT, RVAL_a, yield_cont) /*TKL00701*/ + != SUCCESS ); /* perform a robust primality test */ + if (status != SUCCESS ) + { + ERROR_BREAK; + } + /* dss_q2 = 2 * dss_q */ + memcpy( dss_q2, dss_q_a, SHA_LENGTH ); + dss_q2[SHA_LENGTH / sizeof(ord)] = 0; + LShiftL_big( dss_q2, SHA_LENGTH / sizeof(ord) +1, 1 ); + count = 0; + offset = 2; + memset( ofone, 0, SHA_LENGTH ); + do /* find dss_p */ + { + /* generate random number by dss_p bytes */ + for ( k = 0; k <= n; k++ ) + { + ofone[0] = offset + k; + /* v = ofone + seed */ + Sum_big( seed, ofone, v, SHA_LENGTH / sizeof(ord) ); + if ( (status = MySHA ( (uchar *)v, SHA_LENGTH, + (uchar *)( w + (SHA_LENGTH / sizeof(ord)) * k ))) + != SUCCESS ) /* compute message digest */ + { + break; /* error */ + } + } + if (status != SUCCESS ) + { + break; /* error */ + } + /* set most significant bit */ + w[dss_p_longs - 1] |= ((ord)1 << (BITS_COUNT-1)); + memcpy( c, w, dss_p_bytes); + /* c1 = c mod(dss_q2) */ + if( (status = PartReduct( dss_p_bytes, c, + SHA_LENGTH + sizeof(ord), + dss_q2, c1)) != SUCCESS ) + { + break; /* error */ + } + /* c1 = c1 - 1*/ + Sub_big( c1, one, c1, dss_p_longs ); + /* dss_p = w - c1 */ + Sub_big( w, c1, dss_p_a, dss_p_longs ); + if ( dss_p_a[dss_p_bytes / sizeof(ord) - 1] >= (ord)((ord)1 << (BITS_COUNT-1)) ) + { + if ( VerPrime ( dss_p_bytes, dss_p_a, TEST_COUNT, RVAL_a, yield_cont) /*TKL00701*/ + == SUCCESS ) /* perform a robust primality test */ + { + break; + } + } + count++; + offset = (u_int16_t) (offset + n + 1); + } while ( count < 4096); + if (status != SUCCESS ) + { + ERROR_BREAK; + } + if (count != 4096) /*TKL00501*/ + { + BREAK; /*TKL00501*/ + } + END_LOOP /* Generate dss_p */ /*TKL00501*/ + + if (status != SUCCESS ) + { + ERROR_BREAK; + } + dss_p_a[0] -= 1; /* dss_p = dss_p - 1 */ + if ( (status= DivRem (dss_p_bytes, dss_p_a, SHA_LENGTH, dss_q_a, u1, + e )) != SUCCESS ) /* e = dss_p / dss_q */ + { + ERROR_BREAK; + } + dss_p_a[0] += 1; /* dss_p = dss_p + 1 */ + + BEGIN_LOOP /* Generate dss_g */ /*TKL00501*/ + MyGenRand( SHA_LENGTH, u, RVAL_a ); /*generate random number*/ + u[SHA_LENGTH / sizeof(ord) - 1] &= ~((ord)1 << (BITS_COUNT-1)); /* u < dss_q */ + if ( (status = Expo( SHA_LENGTH, u, (u_int16_t)(dss_p_bytes - SHA_LENGTH + + sizeof(ord)), e, dss_p_bytes, dss_p_a, dss_g_a )) + != SUCCESS ) /* dss_g = e ^ u mod(dss_p) */ + { + ERROR_BREAK; + } + if ( dss_g_a[0] == 1 ) /* check dss_g == 1 */ + { + for ( i = 1; i < (dss_p_bytes / sizeof(ord)); i++ ) + { + if ( dss_g_a[i] != 0 ) + { + break; + } + } + if ( i == (dss_p_bytes / sizeof(ord)) ) + { + CONTINUE; + } + } + BREAK; /*TKL00501*/ + END_LOOP /* Generate dss_g */ /*TKL00501*/ + END_PROCESSING /* Generate DSS Common Parameters */ + free ( e ); + free ( one ); + free ( c ); + free ( w ); + free ( c1 ); + ALIGN_COPY_FREE(dss_p_a, dss_p, dss_p_bytes); + ALIGN_COPY_FREE(dss_q_a, dss_q, SHA_LENGTH); + ALIGN_COPY_FREE(dss_g_a, dss_g, dss_p_bytes); + ALIGN_MOVE_FREE(RVAL_a, RVAL, SHA_LENGTH); + if (DataOrder) + { + BigSwap(dss_p, dss_p_bytes); + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_g, dss_p_bytes); + } + return status; +} + + +/**************************************************************************** +* NAME: int GetDSSPQG(u_int16_t dss_p_bytes, +* uchar *dss_p, +* uchar *dss_q, +* uchar *dss_g) +* +* DESCRIPTION: Copy Cylink DSS P,Q,G numbers to *dss_p,*dss_q,*dss_g +* +* INPUTS: +* PARAMETERS: +* u_int16_t dss_p_bytes Number of bytes in dss_p +* uchar *dss_p Pointer to N-byte buffer +* uchar *dss_q Pointer to SHA_LENGTH-byte buffer +* uchar *dss_g Pointer to N-byte buffer +* OUTPUT: +* RETURN: +* SUCCESS No errors +* ERR_DSS_LEN; Invalid length for dss_p +* REVISION HISTORY: +* +* 22 Apr 95 GKL Initial release LOG TKL01201 +* +****************************************************************************/ +int GetDSSPQG(u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g) +{ + int status = SUCCESS; /* function return status */ + ord *dss_p_a; + ord *dss_g_a; + + if ( (dss_p_bytes < DSS_LENGTH_MIN) || /* less than minimal */ + (dss_p_bytes > DSS_LENGTH_MAX) ) /* more than maximal */ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + if ( dss_p_bytes & 0x07 ) /* not multiple 8 (64 bit)*/ + { + status = ERR_DSS_LEN; /* invalid length for dss_p */ + return status; + } + dss_p_a = &DSS_P_NUMBERS[DSS_NUM_INDEX[(dss_p_bytes-DSS_LENGTH_MIN)/LENGTH_STEP]]; + dss_g_a = &DSS_G_NUMBERS[DSS_NUM_INDEX[(dss_p_bytes-DSS_LENGTH_MIN)/LENGTH_STEP]]; + OrdByte(dss_p_a,dss_p_bytes,dss_p); + OrdByte(dss_g_a,dss_p_bytes,dss_g); + OrdByte(DSS_Q_NUMBER,SHA_LENGTH,dss_q); + if (DataOrder) + { + BigSwap(dss_p, dss_p_bytes); + BigSwap(dss_q, SHA_LENGTH); + BigSwap(dss_g, dss_p_bytes); + } + + return status; +} + + diff --git a/usr/src/lib/libresolv2/common/cylink/dssnum.h b/usr/src/lib/libresolv2/common/cylink/dssnum.h new file mode 100644 index 0000000000..f46f08fe61 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/dssnum.h @@ -0,0 +1,731 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**********************************************************************\ +* FILENAME: DSSNum.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* DESCRIPTION: Standard Cylink DSS numbers (P Q G) support. +* +* USAGE: File should be included to get access to +* Cylink DSS numbers +* +* +* Copyright (c) Cylink Corporation 1995. All rights reserved. +* +* REVISION HISTORY: +* 10 APR 95 GKL Initial release +* +\**********************************************************************/ +#ifndef DSSNUMBER_H /* Prevent multiple inclusions */ +#define DSSNUMBER_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "ctk_endian.h" + +#define LENGTH_MULT_TO_64 + +#define F0 0 +#define F1 (F0 + 1) +#define F2 (F1 + 2) +#define F3 (F2 + 3) +#define F4 (F3 + 4) +#define F5 (F4 + 5) +#define F6 (F5 + 6) +#define F7 (F6 + 7) +#define F8 (F7 + 8) +#define F9 (F8 + 9) +#define F10 (F9 + 10) +#define F11 (F10 + 11) +#define F12 (F11 + 12) +#define F13 (F12 + 13) +#define F14 (F13 + 14) +#define F15 (F14 + 15) + + +#ifdef LENGTH_MULT_TO_64 +#define LENGTH_STEP 8U +#define LAST_F F8 +#endif + +#ifdef LENGTH_MULT_TO_32 +#define LENGTH_STEP 4U +#define LAST_F (F15 + 16) +#endif + + +#define DSS_LENS_NUMBER (int) (1 + ( DSS_LENGTH_MAX - DSS_LENGTH_MIN )/LENGTH_STEP) + +#define DSS_LAST_INDEX (DSS_LENGTH_MIN*DSS_LENS_NUMBER + LENGTH_STEP*LAST_F)/sizeof(ord) + +#ifndef INITIALIZ_PQG + +extern ushort DSS_NUM_INDEX[ DSS_LENS_NUMBER ]; +extern ord DSS_Q_NUMBER[SHA_LENGTH/sizeof(ord)]; +extern ord DSS_P_NUMBERS[DSS_LAST_INDEX]; +extern ord DSS_G_NUMBERS[DSS_LAST_INDEX]; + +#else +ushort DSS_NUM_INDEX[ DSS_LENS_NUMBER ] = +{ + (DSS_LENGTH_MIN*0 + LENGTH_STEP*0 )/sizeof(ord), + (DSS_LENGTH_MIN*1 + LENGTH_STEP*F0 )/sizeof(ord), + (DSS_LENGTH_MIN*2 + LENGTH_STEP*F1 )/sizeof(ord), + (DSS_LENGTH_MIN*3 + LENGTH_STEP*F2 )/sizeof(ord), + (DSS_LENGTH_MIN*4 + LENGTH_STEP*F3 )/sizeof(ord), + (DSS_LENGTH_MIN*5 + LENGTH_STEP*F4 )/sizeof(ord), + (DSS_LENGTH_MIN*6 + LENGTH_STEP*F5 )/sizeof(ord), + (DSS_LENGTH_MIN*7 + LENGTH_STEP*F6 )/sizeof(ord), + (DSS_LENGTH_MIN*8 + LENGTH_STEP*F7 )/sizeof(ord) +#ifdef LENGTH_MULT_TO_32 + , + (DSS_LENGTH_MIN*9 + LENGTH_STEP*F8 )/sizeof(ord), + (DSS_LENGTH_MIN*10 + LENGTH_STEP*F9 )/sizeof(ord), + (DSS_LENGTH_MIN*11 + LENGTH_STEP*F10)/sizeof(ord), + (DSS_LENGTH_MIN*12 + LENGTH_STEP*F11)/sizeof(ord), + (DSS_LENGTH_MIN*13 + LENGTH_STEP*F12)/sizeof(ord), + (DSS_LENGTH_MIN*14 + LENGTH_STEP*F13)/sizeof(ord), + (DSS_LENGTH_MIN*15 + LENGTH_STEP*F14)/sizeof(ord), + (DSS_LENGTH_MIN*16 + LENGTH_STEP*F15)/sizeof(ord) +#endif +}; + +ord DSS_Q_NUMBER[SHA_LENGTH/sizeof(ord)] = +#ifdef ORD_16 + { + 0x8fb7, 0x81f0, 0x6b9e, 0x122a, 0x4dc4, 0x03ca, 0xc896, 0x8d0e, 0xbe3b, 0xed4b + }; +#else + { + 0x81f08fb7L, 0x122a6b9eL, 0x03ca4dc4L, 0x8d0ec896L, 0xed4bbe3bL + }; +#endif + + +ord DSS_P_NUMBERS[DSS_LAST_INDEX] = +#ifdef ORD_16 + { + /* dss_p length = 512*/ + 0x92b7, 0xbd96, 0x9aab, 0x584c, 0xd617, 0xf2f0, 0xda85, 0xd370, + 0xcc82, 0x273e, 0x6b04, 0xc171, 0x5c32, 0xd3ff, 0x352e, 0xf2f8, + 0x4fc2, 0x20bc, 0xbdec, 0xe96e, 0x3503, 0x4d89, 0xe92d, 0xeb7d, + 0x9c1a, 0x7852, 0xfe2a, 0x0a25, 0x4446, 0xce18, 0x7829, 0x95d8, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 544*/ + 0x12db, 0x0d31, 0x9950, 0x16c9, 0x3045, 0x0acb, 0x3c46, 0x3c5c, + 0x6c94, 0x2458, 0x0736, 0x13da, 0xa0af, 0x790f, 0xb177, 0xa6ae, + 0xd111, 0x2bda, 0x697c, 0x49a2, 0xe3e5, 0x6f27, 0x02f5, 0x9bc9, + 0xd4da, 0x7d9b, 0x89c6, 0x63bc, 0x0b6d, 0xfe2d, 0xc7a1, 0x435f, + 0x7fad, 0x9e40, +#endif + /* dss_p length = 576*/ + 0x626b, 0x41b5, 0xd218, 0x25bf, 0x1825, 0x42b3, 0x9eb0, 0xc244, + 0x96ce, 0x22ac, 0x3ac6, 0x713f, 0x321d, 0x398c, 0x3022, 0xbc49, + 0xdd03, 0x52d5, 0x29f8, 0x2a57, 0x8fa1, 0x2173, 0xee7d, 0xb90d, + 0xcc64, 0x5fae, 0xaa81, 0xe3d0, 0x648f, 0xfa6e, 0xdc6c, 0x039f, + 0x2cd6, 0xc552, 0xe2dc, 0xebec, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 608*/ + 0x35f5, 0xb2af, 0x27d0, 0x398b, 0x493d, 0x6f2e, 0xbe27, 0xe5b5, + 0x972c, 0x3470, 0x9638, 0xe90e, 0xf7b7, 0x98ad, 0xd091, 0xb4ca, + 0x3f43, 0x5f58, 0xb6c5, 0xd014, 0x25ee, 0x414d, 0xe2c1, 0x6fd6, + 0xd737, 0x9be6, 0x66ca, 0xe241, 0x1897, 0xf740, 0xe5df, 0xceb0, + 0xdb38, 0xabc8, 0x8af8, 0xc58b, 0xc6a0, 0x9a04, +#endif + /* dss_p length = 640*/ + 0x4095, 0xf6bf, 0x7568, 0x4032, 0x5c0f, 0x64f2, 0x5aae, 0xb099, + 0x346f, 0x0e81, 0x357a, 0x7aeb, 0x0291, 0xfd0a, 0x8d54, 0xce80, + 0x0c05, 0xbea3, 0x889f, 0x8a1b, 0xf1c1, 0x6049, 0x214a, 0x8ec3, + 0xb926, 0xdde1, 0x61b4, 0x384e, 0x404b, 0xb6d7, 0x2e2d, 0x4584, + 0xae6a, 0xcc7a, 0x7bfa, 0x9eb0, 0x3a26, 0x3904, 0x8cac, 0xc036, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 672*/ + 0x0abb, 0xaea3, 0xc749, 0x757c, 0x3035, 0x29d0, 0x46bd, 0xd56c, + 0xf49d, 0xa355, 0x1297, 0x8dcb, 0x9802, 0xc58c, 0xf1ec, 0x8aac, + 0x55dd, 0xb107, 0x0140, 0x26d1, 0x8a5d, 0x8a90, 0xf33e, 0xde0b, + 0xb844, 0xb429, 0x4db2, 0x9806, 0xf629, 0x4c3b, 0xcd76, 0x2f23, + 0x6c68, 0x7bf4, 0x2a7e, 0xd982, 0xc89f, 0x16a2, 0xfe84, 0x953c, + 0x3e4a, 0x8de8, +#endif + /* dss_p length = 704*/ + 0x0113, 0x1535, 0xca0b, 0x8faf, 0xa327, 0x989c, 0x12c8, 0xe512, + 0x796f, 0x1229, 0x12bf, 0x62c8, 0xa50a, 0x2b99, 0xc93b, 0x450c, + 0x71ad, 0x0826, 0xf4c6, 0x3913, 0x9b6e, 0x96da, 0xa08d, 0xbc5e, + 0xd4d3, 0x7b26, 0xf9fd, 0xdd76, 0x4e82, 0x2f06, 0x1f96, 0xbf47, + 0xcadf, 0x3610, 0x917b, 0x4e94, 0xe2e8, 0x0eaf, 0x1cb9, 0x6b90, + 0xb917, 0x6d6f, 0x92b9, 0xb329, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 736*/ + 0x6dad, 0xd878, 0xc913, 0xe61e, 0x87d9, 0xe275, 0xad24, 0xf090, + 0xe12b, 0xfdfe, 0x39a3, 0xc9a1, 0x8330, 0x138a, 0x4bed, 0xc319, + 0x8094, 0x88ba, 0x4b80, 0x1325, 0x7852, 0x67e2, 0x715e, 0x7313, + 0x3b4e, 0x7727, 0x9870, 0x5c6e, 0xe0ce, 0xc67a, 0xd057, 0xf3c5, + 0x55ea, 0x98ba, 0x6ea0, 0xaee7, 0x31e8, 0x3cd6, 0x0e28, 0x42d1, + 0x8946, 0xc395, 0x34fc, 0x1b9d, 0x19d1, 0x86f9, +#endif + /* dss_p length = 768*/ + 0xe293, 0xea08, 0xcdd0, 0xf668, 0x8b2a, 0x06db, 0x7c71, 0xadb2, + 0x943d, 0x6721, 0x54f5, 0xbc44, 0xf7ca, 0x3345, 0x1bf6, 0x0b90, + 0xb475, 0xd3c4, 0xbdb6, 0x7caa, 0xa45f, 0xe9b4, 0x6e0e, 0x0c1a, + 0xb5c3, 0x9760, 0x851a, 0x53af, 0x96b7, 0x4979, 0xf162, 0xe951, + 0x6a54, 0xd020, 0x9ded, 0xdecb, 0xfc81, 0x7d74, 0x5e92, 0x2aee, + 0x0946, 0x0eb5, 0x3700, 0x9bce, 0x845a, 0xa7a3, 0x157a, 0x8618, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 800*/ + 0xb0a1, 0xac27, 0xec4e, 0xf623, 0x55e2, 0x2cb6, 0x288b, 0x4b28, + 0xd74e, 0xbbe6, 0xfdf7, 0xaecd, 0x5758, 0xe251, 0x9074, 0x1aee, + 0xe6ed, 0x4d5e, 0x01d9, 0x529e, 0xf736, 0x0091, 0x0212, 0xc725, + 0x60ce, 0x966f, 0x851d, 0x5c4b, 0x80de, 0x34df, 0x1c88, 0x0636, + 0xbb71, 0x32ce, 0x45cb, 0x86da, 0x4d0e, 0x13e0, 0x7d7d, 0x544b, + 0x1272, 0x747f, 0xd6a7, 0xfa3b, 0xcb86, 0x6b43, 0x66f5, 0xd012, + 0xfe7a, 0xa0cb, +#endif + /* dss_p length = 832*/ + 0xed2d, 0x84dd, 0xf274, 0xdd8f, 0xcd5f, 0x7928, 0xbfc6, 0xa522, + 0xe4e4, 0x50f0, 0xcddf, 0x5842, 0xbb29, 0x7c4d, 0xeef4, 0x6946, + 0x87f6, 0xe486, 0x61b5, 0xc1b6, 0xadef, 0x575a, 0x360f, 0x724f, + 0xcb29, 0x591b, 0x9a4c, 0xf7bc, 0x309e, 0xa348, 0x0ff5, 0x94f3, + 0x932f, 0x9dc6, 0x992c, 0xc6d7, 0x12f6, 0xc2d7, 0x38aa, 0x8c01, + 0x5dca, 0x74f4, 0xfcfd, 0x4cf4, 0x588a, 0x7837, 0x097e, 0xd2e2, + 0x6eac, 0x8869, 0xe92f, 0xec62, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 864*/ + 0x7c21, 0x931e, 0x553d, 0x00f2, 0xa860, 0x940f, 0x411e, 0x7d20, + 0xb168, 0x52a3, 0x69ee, 0x166e, 0xb9e6, 0x1b23, 0xd5e0, 0xef64, + 0x2850, 0x724c, 0xc1fe, 0xea73, 0xda8c, 0xe342, 0x1d7b, 0xd256, + 0x359b, 0x180f, 0xd7f5, 0xca77, 0x06ac, 0x2162, 0xa977, 0x78bb, + 0x5018, 0x5de2, 0x6061, 0xe217, 0x4d42, 0xfed1, 0x3929, 0xd50f, + 0xc946, 0x2433, 0x15f8, 0x361b, 0xbf51, 0x3ff0, 0x3efa, 0x3157, + 0x7350, 0x53a0, 0xd1a4, 0x261b, 0xde5b, 0x9236, +#endif + /* dss_p length = 896*/ + 0x8e21, 0x0364, 0x86d2, 0xe58c, 0x2274, 0x780a, 0x9ffc, 0x4951, + 0x3f99, 0xbc96, 0x9e60, 0x5a7e, 0x010a, 0x23d4, 0x54d1, 0x48e9, + 0xfd6b, 0x979c, 0x5202, 0x8af3, 0x5d87, 0xfe8f, 0x3e3c, 0x1e0c, + 0xe294, 0xcc52, 0xa8d6, 0x480e, 0xa898, 0xd4ce, 0x5949, 0xd341, + 0xe325, 0xf41b, 0x72d6, 0x6a90, 0x7a8b, 0x6f14, 0x3e2b, 0x6636, + 0x3748, 0x4eea, 0xa590, 0x03e4, 0x0524, 0x9c32, 0xeb53, 0x02af, + 0xca71, 0x6792, 0xd673, 0xedf8, 0x6448, 0x59c3, 0x7319, 0x883f, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 928*/ + 0xc17d, 0xa4e8, 0xea08, 0x8ff8, 0x2cb0, 0x73f5, 0xd7ba, 0xc027, + 0xb9c8, 0x989d, 0xe5fe, 0xe3a1, 0xf324, 0x39d3, 0xf142, 0x5ba8, + 0xe6cb, 0x3708, 0xa0b7, 0xed9a, 0xb6b3, 0xe314, 0xf80a, 0x6778, + 0x4d27, 0x7107, 0x6ee8, 0xb9c2, 0xc6af, 0xab70, 0x53be, 0xc445, + 0x7926, 0x34bb, 0x5191, 0xe11d, 0x67f1, 0xcc3a, 0x5354, 0xd34d, + 0xa1ac, 0x08ba, 0x32d4, 0x068a, 0x7c3b, 0x415f, 0xbce0, 0xb549, + 0x0ecf, 0x538f, 0xb5d0, 0x22a3, 0x1d47, 0xe837, 0x14c0, 0x69dd, + 0xa02d, 0xce91, +#endif + /* dss_p length = 960*/ + 0x1ff3, 0xf77e, 0xae7a, 0x5a28, 0x43b1, 0xe187, 0x2e04, 0xb3ea, + 0x7394, 0xa3e8, 0x4985, 0xc9bc, 0x7b7d, 0x1e1c, 0xd99c, 0x55f8, + 0x447b, 0x5704, 0xd758, 0xbed1, 0xe698, 0x2a5e, 0x5c19, 0xc206, + 0x6d38, 0x1f88, 0x2ea4, 0x5f15, 0xebfd, 0xd716, 0x8a2a, 0xf960, + 0x83ac, 0xc493, 0xb966, 0x8f13, 0x4778, 0x9682, 0x4712, 0x84cd, + 0xbb4e, 0xe567, 0x644f, 0x0780, 0x133d, 0x0b0a, 0xe42e, 0x06e8, + 0xa4cc, 0x3131, 0x39d9, 0xfaf8, 0x12a3, 0x5550, 0x43b1, 0xb8a9, + 0xb0eb, 0x0fad, 0x986f, 0xd427, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 992*/ + 0xbcfd, 0x363f, 0x050a, 0x18f0, 0x78d8, 0xcac9, 0x423a, 0xf31e, + 0x198f, 0xd0c3, 0xb319, 0x5d1b, 0x917a, 0xc0b0, 0x8d1b, 0x6b91, + 0xea69, 0xa9d1, 0x02ce, 0x5345, 0x2c80, 0x6992, 0x4dad, 0x7a28, + 0xbb75, 0xd46d, 0x0faa, 0x5612, 0x6878, 0x8a0e, 0x63b4, 0x46ab, + 0xaca0, 0x5381, 0xb90a, 0x3e70, 0x19c4, 0xb639, 0xf778, 0xe751, + 0x5974, 0xb726, 0x589f, 0x8679, 0xeb04, 0xc0b5, 0xdffd, 0x2b32, + 0x4b51, 0xc632, 0xd8c6, 0x9501, 0x4f94, 0x2026, 0x253a, 0x0d27, + 0x07bb, 0x0838, 0x2725, 0xa3eb, 0x3c4e, 0x89b6, +#endif + /* dss_p length = 1024*/ + 0xa141, 0xecf7, 0xc6d6, 0x867d, 0xefa3, 0x1cdd, 0x6c9d, 0x6ca5, + 0x2e2f, 0x68af, 0x90e1, 0x1d3e, 0xd75f, 0x0c2a, 0x844b, 0x36c7, + 0x3420, 0xfd1a, 0xb9ee, 0xf6e5, 0x5fde, 0xc8ed, 0x0c90, 0xd353, + 0x6faa, 0x80a4, 0x5bbd, 0xa59d, 0x9e72, 0x3223, 0x8f59, 0xf33d, + 0x10eb, 0xeccd, 0x184e, 0x3e2a, 0x4c07, 0x564b, 0x4c0a, 0x3263, + 0xc535, 0x8aeb, 0xf982, 0x2be2, 0xe475, 0x9b87, 0xcca0, 0x4d08, + 0x3adf, 0x0484, 0xd528, 0x7acd, 0x304d, 0x55a0, 0x70ae, 0x8298, + 0x6a7a, 0x2298, 0x15c0, 0x7a86, 0x7fc5, 0x654a, 0x14ad, 0xd0aa + }; +#else + { +/* dss_p length = 512*/ + 0xbd9692b7L, 0x584c9aabL, 0xf2f0d617L, 0xd370da85L, + 0x273ecc82L, 0xc1716b04L, 0xd3ff5c32L, 0xf2f8352eL, + 0x20bc4fc2L, 0xe96ebdecL, 0x4d893503L, 0xeb7de92dL, + 0x78529c1aL, 0x0a25fe2aL, 0xce184446L, 0x95d87829L, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 544*/ + 0x0d3112dbL, 0x16c99950L, 0x0acb3045L, 0x3c5c3c46L, + 0x24586c94L, 0x13da0736L, 0x790fa0afL, 0xa6aeb177L, + 0x2bdad111L, 0x49a2697cL, 0x6f27e3e5L, 0x9bc902f5L, + 0x7d9bd4daL, 0x63bc89c6L, 0xfe2d0b6dL, 0x435fc7a1L, + 0x9e407fadL, +#endif + /* dss_p length = 576*/ + 0x41b5626bL, 0x25bfd218L, 0x42b31825L, 0xc2449eb0L, + 0x22ac96ceL, 0x713f3ac6L, 0x398c321dL, 0xbc493022L, + 0x52d5dd03L, 0x2a5729f8L, 0x21738fa1L, 0xb90dee7dL, + 0x5faecc64L, 0xe3d0aa81L, 0xfa6e648fL, 0x039fdc6cL, + 0xc5522cd6L, 0xebece2dcL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 608*/ + 0xb2af35f5L, 0x398b27d0L, 0x6f2e493dL, 0xe5b5be27L, + 0x3470972cL, 0xe90e9638L, 0x98adf7b7L, 0xb4cad091L, + 0x5f583f43L, 0xd014b6c5L, 0x414d25eeL, 0x6fd6e2c1L, + 0x9be6d737L, 0xe24166caL, 0xf7401897L, 0xceb0e5dfL, + 0xabc8db38L, 0xc58b8af8L, 0x9a04c6a0L, +#endif + /* dss_p length = 640*/ + 0xf6bf4095L, 0x40327568L, 0x64f25c0fL, 0xb0995aaeL, + 0x0e81346fL, 0x7aeb357aL, 0xfd0a0291L, 0xce808d54L, + 0xbea30c05L, 0x8a1b889fL, 0x6049f1c1L, 0x8ec3214aL, + 0xdde1b926L, 0x384e61b4L, 0xb6d7404bL, 0x45842e2dL, + 0xcc7aae6aL, 0x9eb07bfaL, 0x39043a26L, 0xc0368cacL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 672*/ + 0xaea30abbL, 0x757cc749L, 0x29d03035L, 0xd56c46bdL, + 0xa355f49dL, 0x8dcb1297L, 0xc58c9802L, 0x8aacf1ecL, + 0xb10755ddL, 0x26d10140L, 0x8a908a5dL, 0xde0bf33eL, + 0xb429b844L, 0x98064db2L, 0x4c3bf629L, 0x2f23cd76L, + 0x7bf46c68L, 0xd9822a7eL, 0x16a2c89fL, 0x953cfe84L, + 0x8de83e4aL, +#endif + /* dss_p length = 704*/ + 0x15350113L, 0x8fafca0bL, 0x989ca327L, 0xe51212c8L, + 0x1229796fL, 0x62c812bfL, 0x2b99a50aL, 0x450cc93bL, + 0x082671adL, 0x3913f4c6L, 0x96da9b6eL, 0xbc5ea08dL, + 0x7b26d4d3L, 0xdd76f9fdL, 0x2f064e82L, 0xbf471f96L, + 0x3610cadfL, 0x4e94917bL, 0x0eafe2e8L, 0x6b901cb9L, + 0x6d6fb917L, 0xb32992b9L, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 736*/ + 0xd8786dadL, 0xe61ec913L, 0xe27587d9L, 0xf090ad24L, + 0xfdfee12bL, 0xc9a139a3L, 0x138a8330L, 0xc3194bedL, + 0x88ba8094L, 0x13254b80L, 0x67e27852L, 0x7313715eL, + 0x77273b4eL, 0x5c6e9870L, 0xc67ae0ceL, 0xf3c5d057L, + 0x98ba55eaL, 0xaee76ea0L, 0x3cd631e8L, 0x42d10e28L, + 0xc3958946L, 0x1b9d34fcL, 0x86f919d1L, +#endif + /* dss_p length = 768*/ + 0xea08e293L, 0xf668cdd0L, 0x06db8b2aL, 0xadb27c71L, + 0x6721943dL, 0xbc4454f5L, 0x3345f7caL, 0x0b901bf6L, + 0xd3c4b475L, 0x7caabdb6L, 0xe9b4a45fL, 0x0c1a6e0eL, + 0x9760b5c3L, 0x53af851aL, 0x497996b7L, 0xe951f162L, + 0xd0206a54L, 0xdecb9dedL, 0x7d74fc81L, 0x2aee5e92L, + 0x0eb50946L, 0x9bce3700L, 0xa7a3845aL, 0x8618157aL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 800*/ + 0xac27b0a1L, 0xf623ec4eL, 0x2cb655e2L, 0x4b28288bL, + 0xbbe6d74eL, 0xaecdfdf7L, 0xe2515758L, 0x1aee9074L, + 0x4d5ee6edL, 0x529e01d9L, 0x0091f736L, 0xc7250212L, + 0x966f60ceL, 0x5c4b851dL, 0x34df80deL, 0x06361c88L, + 0x32cebb71L, 0x86da45cbL, 0x13e04d0eL, 0x544b7d7dL, + 0x747f1272L, 0xfa3bd6a7L, 0x6b43cb86L, 0xd01266f5L, + 0xa0cbfe7aL, +#endif + /* dss_p length = 832*/ + 0x84dded2dL, 0xdd8ff274L, 0x7928cd5fL, 0xa522bfc6L, + 0x50f0e4e4L, 0x5842cddfL, 0x7c4dbb29L, 0x6946eef4L, + 0xe48687f6L, 0xc1b661b5L, 0x575aadefL, 0x724f360fL, + 0x591bcb29L, 0xf7bc9a4cL, 0xa348309eL, 0x94f30ff5L, + 0x9dc6932fL, 0xc6d7992cL, 0xc2d712f6L, 0x8c0138aaL, + 0x74f45dcaL, 0x4cf4fcfdL, 0x7837588aL, 0xd2e2097eL, + 0x88696eacL, 0xec62e92fL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 864*/ + 0x931e7c21L, 0x00f2553dL, 0x940fa860L, 0x7d20411eL, + 0x52a3b168L, 0x166e69eeL, 0x1b23b9e6L, 0xef64d5e0L, + 0x724c2850L, 0xea73c1feL, 0xe342da8cL, 0xd2561d7bL, + 0x180f359bL, 0xca77d7f5L, 0x216206acL, 0x78bba977L, + 0x5de25018L, 0xe2176061L, 0xfed14d42L, 0xd50f3929L, + 0x2433c946L, 0x361b15f8L, 0x3ff0bf51L, 0x31573efaL, + 0x53a07350L, 0x261bd1a4L, 0x9236de5bL, +#endif + /* dss_p length = 896*/ + 0x03648e21L, 0xe58c86d2L, 0x780a2274L, 0x49519ffcL, + 0xbc963f99L, 0x5a7e9e60L, 0x23d4010aL, 0x48e954d1L, + 0x979cfd6bL, 0x8af35202L, 0xfe8f5d87L, 0x1e0c3e3cL, + 0xcc52e294L, 0x480ea8d6L, 0xd4cea898L, 0xd3415949L, + 0xf41be325L, 0x6a9072d6L, 0x6f147a8bL, 0x66363e2bL, + 0x4eea3748L, 0x03e4a590L, 0x9c320524L, 0x02afeb53L, + 0x6792ca71L, 0xedf8d673L, 0x59c36448L, 0x883f7319L, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 928*/ + 0xa4e8c17dL, 0x8ff8ea08L, 0x73f52cb0L, 0xc027d7baL, + 0x989db9c8L, 0xe3a1e5feL, 0x39d3f324L, 0x5ba8f142L, + 0x3708e6cbL, 0xed9aa0b7L, 0xe314b6b3L, 0x6778f80aL, + 0x71074d27L, 0xb9c26ee8L, 0xab70c6afL, 0xc44553beL, + 0x34bb7926L, 0xe11d5191L, 0xcc3a67f1L, 0xd34d5354L, + 0x08baa1acL, 0x068a32d4L, 0x415f7c3bL, 0xb549bce0L, + 0x538f0ecfL, 0x22a3b5d0L, 0xe8371d47L, 0x69dd14c0L, + 0xce91a02dL, +#endif + /* dss_p length = 960*/ + 0xf77e1ff3L, 0x5a28ae7aL, 0xe18743b1L, 0xb3ea2e04L, + 0xa3e87394L, 0xc9bc4985L, 0x1e1c7b7dL, 0x55f8d99cL, + 0x5704447bL, 0xbed1d758L, 0x2a5ee698L, 0xc2065c19L, + 0x1f886d38L, 0x5f152ea4L, 0xd716ebfdL, 0xf9608a2aL, + 0xc49383acL, 0x8f13b966L, 0x96824778L, 0x84cd4712L, + 0xe567bb4eL, 0x0780644fL, 0x0b0a133dL, 0x06e8e42eL, + 0x3131a4ccL, 0xfaf839d9L, 0x555012a3L, 0xb8a943b1L, + 0x0fadb0ebL, 0xd427986fL, +#ifdef LENGTH_MULT_TO_32 + /* dss_p length = 992*/ + 0x363fbcfdL, 0x18f0050aL, 0xcac978d8L, 0xf31e423aL, + 0xd0c3198fL, 0x5d1bb319L, 0xc0b0917aL, 0x6b918d1bL, + 0xa9d1ea69L, 0x534502ceL, 0x69922c80L, 0x7a284dadL, + 0xd46dbb75L, 0x56120faaL, 0x8a0e6878L, 0x46ab63b4L, + 0x5381aca0L, 0x3e70b90aL, 0xb63919c4L, 0xe751f778L, + 0xb7265974L, 0x8679589fL, 0xc0b5eb04L, 0x2b32dffdL, + 0xc6324b51L, 0x9501d8c6L, 0x20264f94L, 0x0d27253aL, + 0x083807bbL, 0xa3eb2725L, 0x89b63c4eL, +#endif + /* dss_p length = 1024*/ + 0xecf7a141L, 0x867dc6d6L, 0x1cddefa3L, 0x6ca56c9dL, + 0x68af2e2fL, 0x1d3e90e1L, 0x0c2ad75fL, 0x36c7844bL, + 0xfd1a3420L, 0xf6e5b9eeL, 0xc8ed5fdeL, 0xd3530c90L, + 0x80a46faaL, 0xa59d5bbdL, 0x32239e72L, 0xf33d8f59L, + 0xeccd10ebL, 0x3e2a184eL, 0x564b4c07L, 0x32634c0aL, + 0x8aebc535L, 0x2be2f982L, 0x9b87e475L, 0x4d08cca0L, + 0x04843adfL, 0x7acdd528L, 0x55a0304dL, 0x829870aeL, + 0x22986a7aL, 0x7a8615c0L, 0x654a7fc5L, 0xd0aa14adL + }; +#endif + +ord DSS_G_NUMBERS[DSS_LAST_INDEX] = +#ifdef ORD_16 + { + /* dss_g length = 512*/ + 0x8b1a, 0xedfe, 0xef16, 0xdb26, 0xeae0, 0x1f1d, 0xaf3a, 0x3e30, + 0x2bd6, 0x25ec, 0xa451, 0x6255, 0xbc75, 0x499c, 0x4071, 0x5da2, + 0x1149, 0xc7fc, 0x1402, 0x9b69, 0xc168, 0xb0ea, 0xaf92, 0x6a33, + 0xf45f, 0xd93a, 0x75a6, 0x263c, 0xb820, 0x7eb1, 0x5f5b, 0x4bd7, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 544*/ + 0x2772, 0xe0e6, 0xce97, 0x605b, 0x4aa8, 0x2586, 0x095a, 0xb83f, + 0x8b01, 0xfe53, 0x9250, 0x74ef, 0x74d4, 0xd9fa, 0xb78b, 0xa714, + 0x106f, 0x03a6, 0xb406, 0xc549, 0xc44d, 0xd559, 0x8100, 0xfef4, + 0x34a4, 0x1f4c, 0x3c6b, 0x4ae0, 0xe770, 0x158b, 0x3f8d, 0xf73d, + 0x0cc5, 0x61b7, +#endif + /* dss_g length = 576*/ + 0x3dde, 0x64fd, 0x2b69, 0x03c3, 0xad1d, 0x1751, 0x11dc, 0xfe67, + 0x6379, 0x76de, 0xe333, 0x3b8f, 0x242f, 0x27d8, 0x5f33, 0x3597, + 0xb98c, 0x11dc, 0x718c, 0xe3b5, 0xa3d4, 0x58f2, 0x71fa, 0x2675, + 0x49f9, 0xf2c7, 0x510e, 0xa4e1, 0xeca4, 0x7c64, 0x243b, 0x78fc, + 0x2ce2, 0x7017, 0x0095, 0x23b6, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 608*/ + 0xdad8, 0x1e27, 0x41f5, 0xd536, 0x528f, 0x7047, 0x028a, 0x56f5, + 0xe55f, 0xe20d, 0x612c, 0x520f, 0xebfd, 0x8c86, 0x0924, 0x562a, + 0x2185, 0xe5ac, 0xa113, 0x4b8c, 0x87da, 0xfa4c, 0x8788, 0x9d8d, + 0x41c0, 0x9d25, 0x9c77, 0xff33, 0x6861, 0xd10a, 0xc734, 0x8454, + 0xf803, 0x55ce, 0xfeac, 0x6580, 0x6cd2, 0x482b, +#endif + /* dss_g length = 640*/ + 0x4ff7, 0x2829, 0x8ab0, 0xa0bd, 0x7b1c, 0xf544, 0xe633, 0x6e7b, + 0x9824, 0x494a, 0xfb7f, 0xc8ad, 0x45b6, 0x956e, 0x0574, 0x5b0d, + 0xd40c, 0xf807, 0x7372, 0x56fd, 0xdd12, 0x8960, 0x255c, 0x019e, + 0xfc39, 0x06b3, 0x9f8e, 0x4cd9, 0xe714, 0x77f6, 0x76f7, 0xb573, + 0x010e, 0x9b52, 0x04d2, 0xe269, 0xd4bb, 0xbdec, 0x089d, 0x7f88, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 672*/ + 0x3d36, 0xb22d, 0x2144, 0xfda0, 0x1d4a, 0xc144, 0xef8f, 0x70e8, + 0xfd0f, 0xcbf9, 0x7433, 0xbf29, 0x1657, 0x757b, 0x011d, 0x5c7e, + 0xa0d3, 0xec5a, 0xd45d, 0xacd6, 0x136a, 0x9454, 0x61fd, 0xc3f6, + 0x3758, 0x5c89, 0xe4df, 0xd3c9, 0x6f99, 0xa113, 0x0992, 0x16b2, + 0xf92f, 0xfb67, 0x3f34, 0x57e6, 0xb224, 0xdfd1, 0x43c4, 0x639a, + 0xccf5, 0x86c4, +#endif + /* dss_g length = 704*/ + 0x1621, 0x8313, 0x216e, 0xcb3b, 0xde00, 0xa11b, 0xf27f, 0xd5d4, + 0x6d2e, 0xc870, 0x1c47, 0x2e21, 0x780b, 0x1db6, 0x8adf, 0xe5c6, + 0x837d, 0x7dba, 0x9c8c, 0x28b5, 0xd309, 0xf3fa, 0x6c65, 0xe37f, + 0x6a1e, 0x2601, 0xbb92, 0x56aa, 0x9c0e, 0x9db1, 0xb782, 0x642b, + 0x6cc9, 0xb9fb, 0x6a3c, 0x97b9, 0xf1a8, 0xd8a2, 0xfe6b, 0xcb93, + 0x59ee, 0x32a4, 0x0aa1, 0x58ad, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 736*/ + 0x648c, 0xa15c, 0x27b2, 0x8137, 0xefb3, 0x0e81, 0x258e, 0xabe0, + 0x9f2f, 0x6c67, 0xbed6, 0xd201, 0x3647, 0xbe9a, 0x0091, 0xba9a, + 0x4df1, 0xdc8c, 0x5b15, 0x5a37, 0xb5b1, 0x50f8, 0xdfe6, 0x081b, + 0x48d7, 0xd40b, 0x7c51, 0x0417, 0x97c7, 0x2565, 0xf960, 0x89b2, + 0xa1f0, 0x7aac, 0xed6f, 0x20fe, 0x1d98, 0x0eee, 0x48b8, 0xb062, + 0x70e7, 0xa3f3, 0xbe3f, 0x9183, 0x76ae, 0x6cbc, +#endif + /* dss_g length = 768*/ + 0x6216, 0x4b90, 0xc254, 0x7ab6, 0x7a04, 0xf90f, 0x42dd, 0x58c7, + 0xd015, 0x904d, 0xfbf7, 0x624a, 0x5010, 0x627f, 0x696c, 0x1a32, + 0xe0bc, 0xcdfd, 0xe32f, 0xb081, 0x1377, 0x1913, 0x5f96, 0x86c6, + 0x864a, 0x8429, 0x4bb9, 0xd0c6, 0x3361, 0xbc7d, 0xbd8d, 0xa3b2, + 0x47d5, 0x5086, 0xed0b, 0x3bb6, 0xdba6, 0x6f2c, 0x707a, 0x434b, + 0xd4cc, 0x7b10, 0x8ef0, 0x3466, 0x4737, 0x8f27, 0x3399, 0x3716, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 800*/ + 0x99a7, 0xa90c, 0xdf8e, 0xba50, 0x83b5, 0x7ea0, 0x1d8a, 0xe5bb, + 0x34c9, 0x8c4d, 0xb151, 0x3aba, 0xee2f, 0x76c8, 0xeebf, 0x3db9, + 0xc1e0, 0x2b9a, 0x774f, 0xb476, 0x9b93, 0x53b5, 0xc008, 0xed2c, + 0x0ad4, 0x8af4, 0xc0e6, 0x0e98, 0x2d7b, 0xdb37, 0x7b59, 0x8a31, + 0x0667, 0x1225, 0xb882, 0x0355, 0x58ba, 0xf079, 0x80d7, 0x8033, + 0x54bc, 0xf9cd, 0x461e, 0xc70a, 0x9170, 0x1dba, 0xc447, 0xd3e5, + 0xaf18, 0x04c4, +#endif + /* dss_g length = 832*/ + 0xd1b5, 0x3d20, 0xfbdb, 0xa0b6, 0x0505, 0x4e88, 0xa781, 0x7c65, + 0xd381, 0x5b6e, 0xfd1e, 0xbb71, 0xe085, 0x855d, 0x6d0b, 0x650a, + 0xa248, 0x82d0, 0xd4dd, 0x7ea0, 0x16d1, 0x6937, 0x2cc2, 0x2dec, + 0x5e07, 0x97b4, 0x0c5a, 0xcf21, 0x0299, 0x9b96, 0x4acf, 0xc732, + 0xfbcf, 0xeefb, 0x0032, 0x40bb, 0xc86e, 0xeacb, 0xae2b, 0x8adb, + 0x39aa, 0xbb47, 0xaf3a, 0xfd36, 0xf859, 0x97fc, 0x5535, 0x0d3d, + 0x627a, 0x3f62, 0x1f90, 0x5490, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 864*/ + 0xbf83, 0x8b52, 0xc2b1, 0x0808, 0x4a3e, 0x6ccb, 0x8aa8, 0xcfdd, + 0xb046, 0x4948, 0xcdf4, 0x9881, 0x13d8, 0x85b0, 0xa22a, 0x3786, + 0xe9db, 0xcb8a, 0x89ad, 0x5e27, 0xd925, 0x1fcb, 0x3855, 0x4afd, + 0x7f67, 0x83be, 0xb092, 0xe061, 0x6703, 0xf21f, 0x403e, 0x4c6a, + 0xa8bd, 0x536a, 0x89b6, 0xb25e, 0xe165, 0xd259, 0xb765, 0xd7f3, + 0xc474, 0xd8bc, 0x617d, 0x1a0a, 0xa054, 0x8c28, 0x9fb0, 0x9595, + 0x6f2d, 0x6254, 0xe1c2, 0xb450, 0xef81, 0x277f, +#endif + /* dss_g length = 896*/ + 0x7490, 0x2aea, 0xd005, 0xa3cc, 0x9211, 0x235a, 0x7b6d, 0xacec, + 0xfca5, 0x5407, 0x8515, 0x5bc1, 0x8b2a, 0x9388, 0x8ff9, 0xed56, + 0xf4e9, 0xf31e, 0x7e05, 0x172a, 0x6e2a, 0x8165, 0x7a24, 0x975b, + 0x1f6e, 0xd4d1, 0x8232, 0xd6ff, 0x2363, 0x4072, 0xa1f1, 0xd18b, + 0xe574, 0xb032, 0xc330, 0x81b6, 0x6033, 0x07d5, 0x5107, 0xb7cc, + 0x2c10, 0xbd8e, 0xc6a3, 0xe731, 0xfcd6, 0xe567, 0x3440, 0xbcde, + 0x1976, 0xdbb3, 0xd15a, 0x4e39, 0xc282, 0x4b0b, 0x82b3, 0x286b, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 928*/ + 0x9f66, 0xd0e5, 0xd7d2, 0xe875, 0x0707, 0x2dca, 0xa5a2, 0x266d, + 0x80c2, 0x6d20, 0x69b3, 0x759c, 0x497f, 0x74b4, 0x0f56, 0x4b63, + 0xa294, 0x4995, 0x3eda, 0xf5c4, 0x7951, 0x3a3d, 0x22e9, 0x617f, + 0x1906, 0xd45d, 0x047f, 0x2726, 0x27be, 0x660e, 0xc1d3, 0xa588, + 0xceb2, 0xe300, 0xca06, 0x8620, 0x1110, 0x76ae, 0xf7b8, 0xe368, + 0x89a7, 0x2ded, 0x2756, 0x3ed6, 0x5449, 0x4bd8, 0xb73d, 0xb406, + 0x25ec, 0x32f7, 0x989c, 0x6623, 0x6b1f, 0xf7f0, 0x4807, 0x0954, + 0x51e6, 0x97d0, +#endif + /* dss_g length = 960*/ + 0x4118, 0xe87c, 0x809a, 0x1287, 0x2a0f, 0x51d6, 0x7fc8, 0xdad8, + 0x8dc6, 0xddce, 0xd27c, 0x898a, 0x96a9, 0xaee1, 0xe44c, 0xd322, + 0x9d58, 0x3a34, 0xcebd, 0x322a, 0x5b48, 0x9c21, 0x6d04, 0x2d77, + 0x41f1, 0x5123, 0xaa5f, 0x2192, 0x8175, 0x5cac, 0xf547, 0xdc08, + 0xb0d9, 0x4f11, 0x85c9, 0xb5bf, 0x7147, 0x9fbf, 0x3c20, 0x7f7a, + 0xdd8a, 0xa163, 0x0ae4, 0xfcb2, 0x8251, 0x8162, 0xb96e, 0x84f9, + 0xd652, 0x94ba, 0xbb90, 0x9559, 0xac51, 0x6418, 0xdb54, 0x4739, + 0x3ec0, 0x9b7c, 0xae96, 0x3e14, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 992*/ + 0x4eff, 0x399a, 0x5da9, 0x1e5a, 0x9040, 0x4bad, 0xc85d, 0x5b9a, + 0x825b, 0x5464, 0x7538, 0xe2ea, 0xb957, 0x5def, 0xbfa6, 0x4916, + 0x89be, 0x93fe, 0xe5da, 0x919f, 0x791c, 0xe7a8, 0xef86, 0xc186, + 0xbf63, 0xa881, 0x1e38, 0x9abe, 0x8b58, 0x70b4, 0x9dfd, 0x0719, + 0x85e5, 0xc60a, 0xab36, 0xe07d, 0x0c49, 0xd6fe, 0xfdb4, 0x6619, + 0xe55d, 0x997e, 0x5f38, 0x824f, 0x47ff, 0xf800, 0xb137, 0x839d, + 0x2dae, 0xe0db, 0x2a74, 0x2f58, 0x6fb3, 0x1bab, 0x62ed, 0x0e02, + 0xbef2, 0xd7f1, 0xe566, 0xa9ae, 0xbc35, 0x6357, +#endif + /* dss_g length = 1024*/ + 0x914d, 0x76b2, 0xfee4, 0x9cf7, 0xa136, 0x07a1, 0x3808, 0x1857, + 0x8f96, 0x870c, 0x1f3c, 0x59f2, 0x6f01, 0x4d4d, 0x580e, 0xafc6, + 0x99af, 0xff1b, 0xc019, 0x6c1f, 0xe449, 0x1698, 0x4787, 0x0aa2, + 0x6e68, 0x768d, 0x5ff0, 0x27dc, 0xca9e, 0x630f, 0x01ae, 0x9981, + 0x688d, 0xf278, 0x7f3d, 0x17ad, 0x48aa, 0x65d6, 0x181f, 0x1802, + 0x647c, 0x9ef5, 0x7081, 0x5843, 0x1f0d, 0x9364, 0xebe9, 0x6330, + 0x033a, 0x5d2a, 0xb68a, 0x5639, 0xfa7c, 0xd77e, 0x4bdc, 0x4a62, + 0x5c6d, 0xfed5, 0xa8aa, 0x5eff, 0x1138, 0xae4a, 0xe993, 0x3a73 + }; +#else + { + /* dss_g length = 512*/ + 0xedfe8b1aL, 0xdb26ef16L, 0x1f1deae0L, 0x3e30af3aL, + 0x25ec2bd6L, 0x6255a451L, 0x499cbc75L, 0x5da24071L, + 0xc7fc1149L, 0x9b691402L, 0xb0eac168L, 0x6a33af92L, + 0xd93af45fL, 0x263c75a6L, 0x7eb1b820L, 0x4bd75f5bL, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 544*/ + 0xe0e62772L, 0x605bce97L, 0x25864aa8L, 0xb83f095aL, + 0xfe538b01L, 0x74ef9250L, 0xd9fa74d4L, 0xa714b78bL, + 0x03a6106fL, 0xc549b406L, 0xd559c44dL, 0xfef48100L, + 0x1f4c34a4L, 0x4ae03c6bL, 0x158be770L, 0xf73d3f8dL, + 0x61b70cc5L, +#endif + /* dss_g length = 576*/ + 0x64fd3ddeL, 0x03c32b69L, 0x1751ad1dL, 0xfe6711dcL, + 0x76de6379L, 0x3b8fe333L, 0x27d8242fL, 0x35975f33L, + 0x11dcb98cL, 0xe3b5718cL, 0x58f2a3d4L, 0x267571faL, + 0xf2c749f9L, 0xa4e1510eL, 0x7c64eca4L, 0x78fc243bL, + 0x70172ce2L, 0x23b60095L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 608*/ + 0x1e27dad8L, 0xd53641f5L, 0x7047528fL, 0x56f5028aL, + 0xe20de55fL, 0x520f612cL, 0x8c86ebfdL, 0x562a0924L, + 0xe5ac2185L, 0x4b8ca113L, 0xfa4c87daL, 0x9d8d8788L, + 0x9d2541c0L, 0xff339c77L, 0xd10a6861L, 0x8454c734L, + 0x55cef803L, 0x6580feacL, 0x482b6cd2L, +#endif + /* dss_g length = 640*/ + 0x28294ff7L, 0xa0bd8ab0L, 0xf5447b1cL, 0x6e7be633L, + 0x494a9824L, 0xc8adfb7fL, 0x956e45b6L, 0x5b0d0574L, + 0xf807d40cL, 0x56fd7372L, 0x8960dd12L, 0x019e255cL, + 0x06b3fc39L, 0x4cd99f8eL, 0x77f6e714L, 0xb57376f7L, + 0x9b52010eL, 0xe26904d2L, 0xbdecd4bbL, 0x7f88089dL, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 672*/ + 0xb22d3d36L, 0xfda02144L, 0xc1441d4aL, 0x70e8ef8fL, + 0xcbf9fd0fL, 0xbf297433L, 0x757b1657L, 0x5c7e011dL, + 0xec5aa0d3L, 0xacd6d45dL, 0x9454136aL, 0xc3f661fdL, + 0x5c893758L, 0xd3c9e4dfL, 0xa1136f99L, 0x16b20992L, + 0xfb67f92fL, 0x57e63f34L, 0xdfd1b224L, 0x639a43c4L, + 0x86c4ccf5L, +#endif + /* dss_g length = 704*/ + 0x83131621L, 0xcb3b216eL, 0xa11bde00L, 0xd5d4f27fL, + 0xc8706d2eL, 0x2e211c47L, 0x1db6780bL, 0xe5c68adfL, + 0x7dba837dL, 0x28b59c8cL, 0xf3fad309L, 0xe37f6c65L, + 0x26016a1eL, 0x56aabb92L, 0x9db19c0eL, 0x642bb782L, + 0xb9fb6cc9L, 0x97b96a3cL, 0xd8a2f1a8L, 0xcb93fe6bL, + 0x32a459eeL, 0x58ad0aa1L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 736*/ + 0xa15c648cL, 0x813727b2L, 0x0e81efb3L, 0xabe0258eL, + 0x6c679f2fL, 0xd201bed6L, 0xbe9a3647L, 0xba9a0091L, + 0xdc8c4df1L, 0x5a375b15L, 0x50f8b5b1L, 0x081bdfe6L, + 0xd40b48d7L, 0x04177c51L, 0x256597c7L, 0x89b2f960L, + 0x7aaca1f0L, 0x20feed6fL, 0x0eee1d98L, 0xb06248b8L, + 0xa3f370e7L, 0x9183be3fL, 0x6cbc76aeL, +#endif + /* dss_g length = 768*/ + 0x4b906216L, 0x7ab6c254L, 0xf90f7a04L, 0x58c742ddL, + 0x904dd015L, 0x624afbf7L, 0x627f5010L, 0x1a32696cL, + 0xcdfde0bcL, 0xb081e32fL, 0x19131377L, 0x86c65f96L, + 0x8429864aL, 0xd0c64bb9L, 0xbc7d3361L, 0xa3b2bd8dL, + 0x508647d5L, 0x3bb6ed0bL, 0x6f2cdba6L, 0x434b707aL, + 0x7b10d4ccL, 0x34668ef0L, 0x8f274737L, 0x37163399L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 800*/ + 0xa90c99a7L, 0xba50df8eL, 0x7ea083b5L, 0xe5bb1d8aL, + 0x8c4d34c9L, 0x3abab151L, 0x76c8ee2fL, 0x3db9eebfL, + 0x2b9ac1e0L, 0xb476774fL, 0x53b59b93L, 0xed2cc008L, + 0x8af40ad4L, 0x0e98c0e6L, 0xdb372d7bL, 0x8a317b59L, + 0x12250667L, 0x0355b882L, 0xf07958baL, 0x803380d7L, + 0xf9cd54bcL, 0xc70a461eL, 0x1dba9170L, 0xd3e5c447L, + 0x04c4af18L, +#endif + /* dss_g length = 832*/ + 0x3d20d1b5L, 0xa0b6fbdbL, 0x4e880505L, 0x7c65a781L, + 0x5b6ed381L, 0xbb71fd1eL, 0x855de085L, 0x650a6d0bL, + 0x82d0a248L, 0x7ea0d4ddL, 0x693716d1L, 0x2dec2cc2L, + 0x97b45e07L, 0xcf210c5aL, 0x9b960299L, 0xc7324acfL, + 0xeefbfbcfL, 0x40bb0032L, 0xeacbc86eL, 0x8adbae2bL, + 0xbb4739aaL, 0xfd36af3aL, 0x97fcf859L, 0x0d3d5535L, + 0x3f62627aL, 0x54901f90L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 864*/ + 0x8b52bf83L, 0x0808c2b1L, 0x6ccb4a3eL, 0xcfdd8aa8L, + 0x4948b046L, 0x9881cdf4L, 0x85b013d8L, 0x3786a22aL, + 0xcb8ae9dbL, 0x5e2789adL, 0x1fcbd925L, 0x4afd3855L, + 0x83be7f67L, 0xe061b092L, 0xf21f6703L, 0x4c6a403eL, + 0x536aa8bdL, 0xb25e89b6L, 0xd259e165L, 0xd7f3b765L, + 0xd8bcc474L, 0x1a0a617dL, 0x8c28a054L, 0x95959fb0L, + 0x62546f2dL, 0xb450e1c2L, 0x277fef81L, +#endif + /* dss_g length = 896*/ + 0x2aea7490L, 0xa3ccd005L, 0x235a9211L, 0xacec7b6dL, + 0x5407fca5L, 0x5bc18515L, 0x93888b2aL, 0xed568ff9L, + 0xf31ef4e9L, 0x172a7e05L, 0x81656e2aL, 0x975b7a24L, + 0xd4d11f6eL, 0xd6ff8232L, 0x40722363L, 0xd18ba1f1L, + 0xb032e574L, 0x81b6c330L, 0x07d56033L, 0xb7cc5107L, + 0xbd8e2c10L, 0xe731c6a3L, 0xe567fcd6L, 0xbcde3440L, + 0xdbb31976L, 0x4e39d15aL, 0x4b0bc282L, 0x286b82b3L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 928*/ + 0xd0e59f66L, 0xe875d7d2L, 0x2dca0707L, 0x266da5a2L, + 0x6d2080c2L, 0x759c69b3L, 0x74b4497fL, 0x4b630f56L, + 0x4995a294L, 0xf5c43edaL, 0x3a3d7951L, 0x617f22e9L, + 0xd45d1906L, 0x2726047fL, 0x660e27beL, 0xa588c1d3L, + 0xe300ceb2L, 0x8620ca06L, 0x76ae1110L, 0xe368f7b8L, + 0x2ded89a7L, 0x3ed62756L, 0x4bd85449L, 0xb406b73dL, + 0x32f725ecL, 0x6623989cL, 0xf7f06b1fL, 0x09544807L, + 0x97d051e6L, +#endif + /* dss_g length = 960*/ + 0xe87c4118L, 0x1287809aL, 0x51d62a0fL, 0xdad87fc8L, + 0xddce8dc6L, 0x898ad27cL, 0xaee196a9L, 0xd322e44cL, + 0x3a349d58L, 0x322acebdL, 0x9c215b48L, 0x2d776d04L, + 0x512341f1L, 0x2192aa5fL, 0x5cac8175L, 0xdc08f547L, + 0x4f11b0d9L, 0xb5bf85c9L, 0x9fbf7147L, 0x7f7a3c20L, + 0xa163dd8aL, 0xfcb20ae4L, 0x81628251L, 0x84f9b96eL, + 0x94bad652L, 0x9559bb90L, 0x6418ac51L, 0x4739db54L, + 0x9b7c3ec0L, 0x3e14ae96L, +#ifdef LENGTH_MULT_TO_32 + /* dss_g length = 992*/ + 0x399a4effL, 0x1e5a5da9L, 0x4bad9040L, 0x5b9ac85dL, + 0x5464825bL, 0xe2ea7538L, 0x5defb957L, 0x4916bfa6L, + 0x93fe89beL, 0x919fe5daL, 0xe7a8791cL, 0xc186ef86L, + 0xa881bf63L, 0x9abe1e38L, 0x70b48b58L, 0x07199dfdL, + 0xc60a85e5L, 0xe07dab36L, 0xd6fe0c49L, 0x6619fdb4L, + 0x997ee55dL, 0x824f5f38L, 0xf80047ffL, 0x839db137L, + 0xe0db2daeL, 0x2f582a74L, 0x1bab6fb3L, 0x0e0262edL, + 0xd7f1bef2L, 0xa9aee566L, 0x6357bc35L, +#endif + /* dss_g length = 1024*/ + 0x76b2914dL, 0x9cf7fee4L, 0x07a1a136L, 0x18573808L, + 0x870c8f96L, 0x59f21f3cL, 0x4d4d6f01L, 0xafc6580eL, + 0xff1b99afL, 0x6c1fc019L, 0x1698e449L, 0x0aa24787L, + 0x768d6e68L, 0x27dc5ff0L, 0x630fca9eL, 0x998101aeL, + 0xf278688dL, 0x17ad7f3dL, 0x65d648aaL, 0x1802181fL, + 0x9ef5647cL, 0x58437081L, 0x93641f0dL, 0x6330ebe9L, + 0x5d2a033aL, 0x5639b68aL, 0xd77efa7cL, 0x4a624bdcL, + 0xfed55c6dL, 0x5effa8aaL, 0xae4a1138L, 0x3a73e993L + }; +#endif + +#endif /*INITIALIZ_PQG*/ + +#endif /*DSSNUMBER_H*/ diff --git a/usr/src/lib/libresolv2/common/cylink/kludge.h b/usr/src/lib/libresolv2/common/cylink/kludge.h new file mode 100644 index 0000000000..7c85615e89 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/kludge.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef KLUDGE_H +#define KLUDGE_H + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Kludges for not-quite-ANSI systems. + * This should always be the last file included, because it may + * mess up some system header files. + */ + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef ASSERT_NEEDS_STDIO +#define ASSERT_NEEDS_STDIO 0 +#endif +#ifndef ASSERT_NEEDS_STDLIB +#define ASSERT_NEEDS_STDLIB 0 +#endif +#ifndef NO_STDLIB_H +#define NO_STDLIB_H 0 +#endif + +/* SunOS 4.1.x <assert.h> needs "stderr" defined, and "exit" declared... */ +#ifdef assert +#if ASSERT_NEEDS_STDIO +#include <stdio.h> +#endif +#if ASSERT_NEEDS_STDLIB +#if !NO_STDLIB_H +#include <stdlib.h> +#endif +#endif +#endif + +#ifndef NO_MEMMOVE +#define NO_MEMMOVE 0 +#endif +#if NO_MEMMOVE /* memove() not in libraries */ +#define memmove(dest,src,len) bcopy(src,dest,len) +#endif + +#ifndef NO_MEMCPY +#define NO_MEMCPY 0 +#endif +#if NO_MEMCPY /* memcpy() not in libraries */ +#define memcpy(dest,src,len) bcopy(src,dest,len) +#endif + +#ifndef MEM_PROTOS_BROKEN +#define MEM_PROTOS_BROKEN 0 +#endif +#if MEM_PROTOS_BROKEN +#define memcpy(d,s,l) memcpy((void *)(d), (void const *)(s), l) +#define memmove(d,s,l) memmove((void *)(d), (void const *)(s), l) +#define memcmp(d,s,l) memcmp((void const *)(d), (void const *)(s), l) +#define memset(d,v,l) memset((void *)(d), v, l) +#endif + +/* + * If there are no prototypes for the stdio functions, use these to + * reduce compiler warnings. Uses EOF as a giveaway to indicate + * that <stdio.h> was #included. + */ +#ifndef NO_STDIO_PROTOS +#define NO_STDIO_PROTOS 0 +#endif +#if NO_STDIO_PROTOS /* Missing prototypes for "simple" functions */ +#ifdef EOF +#ifdef __cplusplus +extern "C" { +#endif +int (puts)(char const *); +int (fputs)(char const *, FILE *); +int (fflush)(FILE *); +int (printf)(char const *, ...); +int (fprintf)(FILE *, char const *, ...); +/* If we have a sufficiently old-fashioned stdio, it probably uses these... */ +int (_flsbuf)(int, FILE *); +int (_filbuf)(FILE *); +#ifdef __cplusplus +} +#endif +#endif /* EOF */ +#endif /* NO_STDIO_PROTOS */ + +/* + * Borland C seems to think that it's a bad idea to decleare a + * structure tag and not declare the contents. I happen to think + * it's a *good* idea to use such "opaque" structures wherever + * possible. So shut up. + */ +#ifdef __BORLANDC__ +#pragma warn -stu +#ifndef MSDOS +#define MSDOS 1 +#endif +#endif + +/* Turn off warning about negation of unsigned values */ +#ifdef _MSC_VER +#pragma warning(disable:4146) +#endif + +/* Cope with people forgetting to define the OS, if possible... */ + +#ifndef MSDOS +#ifdef __MSDOS +#define MSDOS 1 +#endif +#endif +#ifndef MSDOS +#ifdef __MSDOS__ +#define MSDOS 1 +#endif +#endif + +#endif /* KLUDGE_H */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbn.h b/usr/src/lib/libresolv2/common/cylink/lbn.h new file mode 100644 index 0000000000..c0385c60cc --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn.h - Low-level bignum header. + * Defines various word sizes and useful macros. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + */ +#ifndef LBN_H +#define LBN_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_LIMITS_H +#define NO_LIMITS_H 0 +#endif + +/* Make sure we have 8-bit bytes */ +#if !NO_LIMITS_H +#include <limits.h> +#if UCHAR_MAX != 0xff || CHAR_BIT != 8 +#error The bignum library requires 8-bit unsigned characters. +#endif +#endif /* !NO_LIMITS_H */ + +#ifdef BNINCLUDE /* If this is defined as, say, foo.h */ +#define STR(x) #x /* STR(BNINCLUDE) -> "BNINCLUDE" */ +#define XSTR(x) STR(x) /* XSTR(BNINCLUDE) -> STR(foo.h) -> "foo.h" */ +#include XSTR(BNINCLUDE) /* #include "foo.h" */ +#undef XSTR +#undef STR +#endif + +/* Figure out the endianness */ +/* Error if more than one is defined */ +#if BN_BIG_ENDIAN && BN_LITTLE_ENDIAN +#error Only one of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN may be defined +#endif + +/* + * If no preference is stated, little-endian C code is slightly more + * efficient, so prefer that. (The endianness here does NOT have to + * match the machine's native byte sex; the library's C code will work + * either way. The flexibility is allowed for assembly routines + * that do care. + */ +#if !defined(BN_BIG_ENDIAN) && !defined(BN_LITTLE_ENDIAN) +#define BN_LITTLE_ENDIAN 1 +#endif /* !BN_BIG_ENDIAN && !BN_LITTLE_ENDIAN */ + +/* Macros to choose between big and little endian */ +#if BN_BIG_ENDIAN +#define BIG(b) b +#define LITTLE(l) /*nothing*/ +#define BIGLITTLE(b,l) b +#elif BN_LITTLE_ENDIAN +#define BIG(b) /*nothing*/ +#define LITTLE(l) l +#define BIGLITTLE(b,l) l +#else +#error One of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN must be defined as 1 +#endif + + +/* + * Find a 16-bit unsigned type. + * Unsigned short is preferred over unsigned int to make the type chosen + * by this file more stable on platforms (such as many 68000 compilers) + * which support both 16- and 32-bit ints. + */ +#ifndef BNWORD16 +#ifndef USHRT_MAX /* No <limits.h> available - guess */ +typedef unsigned short bnword16; +#define BNWORD16 bnword16 +#elif USHRT_MAX == 0xffff +typedef unsigned short bnword16; +#define BNWORD16 bnword16 +#elif UINT_MAX == 0xffff +typedef unsigned bnword16; +#define BNWORD16 bnword16 +#endif +#endif /* BNWORD16 */ + +/* + * Find a 32-bit unsigned type. + * Unsigned long is preferred over unsigned int to make the type chosen + * by this file more stable on platforms (such as many 68000 compilers) + * which support both 16- and 32-bit ints. + */ +#ifndef BNWORD32 +#ifndef ULONG_MAX /* No <limits.h> available - guess */ +typedef unsigned long bnword32; +#define BNWORD32 bnword32 +#elif ULONG_MAX == 0xfffffffful +typedef unsigned long bnword32; +#define BNWORD32 bnword32 +#elif UINT_MAX == 0xffffffff +typedef unsigned bnword32; +#define BNWORD32 bnword32 +#elif USHRT_MAX == 0xffffffff +typedef unsigned short bnword32; +#define BNWORD32 bnword32 +#endif +#endif /* BNWORD16 */ + +/* + * Find a 64-bit unsigned type. + * The conditions here are more complicated to avoid using numbers that + * will choke lesser preprocessors (like 0xffffffffffffffff) unless + * we're reasonably certain that they'll be acceptable. + */ +#if !defined(BNWORD64) && ULONG_MAX > 0xfffffffful +#if ULONG_MAX == 0xffffffffffffffff +typedef unsigned long bnword64; +#define BNWORD64 bnword64 +#endif +#endif + +#if 0 +/* + * I would test the value of unsigned long long, but some *preprocessors* + * don't constants that long even if the compiler can accept them, so it + * doesn't work reliably. So cross our fingers and hope that it's a 64-bit + * type. + * + * GCC uses ULONG_LONG_MAX. Solaris uses ULLONG_MAX. IRIX uses ULONGLONG_MAX. + * Are there any other names for this? + */ +#if !defined(BNWORD64) && \ + (defined(ULONG_LONG_MAX) || defined (ULLONG_MAX) || defined(ULONGLONG_MAX)) +typedef unsigned long long bnword64; +#define BNWORD64 bnword64 +#endif +#endif + +/* We don't even try to find a 128-bit type at the moment */ + +#endif /* !LBN_H */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbn00.c b/usr/src/lib/libresolv2/common/cylink/lbn00.c new file mode 100644 index 0000000000..f6686d7b00 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn00.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn00.c - auto-size-detecting lbn??.c file. + * + * Written in 1995 by Colin Plumb. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" +#include "bnsize00.h" + + +#if BNSIZE64 + +/* Include all of the C source file by reference */ +#include "lbn64.c" + +#elif BNSIZE32 + +/* Include all of the C source file by reference */ +#include "lbn32.c" + +#else /* BNSIZE16 */ + +/* Include all of the C source file by reference */ +#include "lbn16.c" + +#endif diff --git a/usr/src/lib/libresolv2/common/cylink/lbn16.c b/usr/src/lib/libresolv2/common/cylink/lbn16.c new file mode 100644 index 0000000000..938651d1d4 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn16.c @@ -0,0 +1,3651 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn16.c - Low-level bignum routines, 16-bit version. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * NOTE: the magic constants "16" and "32" appear in many places in this + * file, including inside identifiers. Because it is not possible to + * ask "#ifdef" of a macro expansion, it is not possible to use the + * preprocessor to conditionalize these properly. Thus, this file is + * intended to be edited with textual search and replace to produce + * alternate word size versions. Any reference to the number of bits + * in a word must be the string "16", and that string must not appear + * otherwise. Any reference to twice this number must appear as "32", + * which likewise must not appear otherwise. Is that clear? + * + * Remember, when doubling the bit size replace the larger number (32) + * first, then the smaller (16). When halving the bit size, do the + * opposite. Otherwise, things will get wierd. Also, be sure to replace + * every instance that appears. (:%s/foo/bar/g in vi) + * + * These routines work with a pointer to the least-significant end of + * an array of WORD16s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros + * defined in lbn.h (which expand to x on a big-edian machine and y on a + * little-endian machine) are used to conditionalize the code to work + * either way. If you have no assembly primitives, it doesn't matter. + * Note that on a big-endian machine, the least-significant-end pointer + * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len]. + * On little-endian, they are ptr[0] through ptr[len-1]. This makes + * perfect sense if you consider pointers to point *between* bytes rather + * than at them. + * + * Because the array index values are unsigned integers, ptr[-i] + * may not work properly, since the index -i is evaluated as an unsigned, + * and if pointers are wider, zero-extension will produce a positive + * number rahter than the needed negative. The expression used in this + * code, *(ptr-i) will, however, work. (The array syntax is equivalent + * to *(ptr+-i), which is a pretty subtle difference.) + * + * Many of these routines will get very unhappy if fed zero-length inputs. + * They use assert() to enforce this. An higher layer of code must make + * sure that these aren't called with zero-length inputs. + * + * Any of these routines can be replaced with more efficient versions + * elsewhere, by just #defining their names. If one of the names + * is #defined, the C code is not compiled in and no declaration is + * made. Use the BNINCLUDE file to do that. Typically, you compile + * asm subroutines with the same name and just, e.g. + * #define lbnMulAdd1_16 lbnMulAdd1_16 + * + * If you want to write asm routines, start with lbnMulAdd1_16(). + * This is the workhorse of modular exponentiation. lbnMulN1_16() is + * also used a fair bit, although not as much and it's defined in terms + * of lbnMulAdd1_16 if that has a custom version. lbnMulSub1_16 and + * lbnDiv21_16 are used in the usual division and remainder finding. + * (Not the Montgomery reduction used in modular exponentiation, though.) + * Once you have lbnMulAdd1_16 defined, writing the other two should + * be pretty easy. (Just make sure you get the sign of the subtraction + * in lbnMulSub1_16 right - it's dest = dest - source * k.) + * + * The only definitions that absolutely need a double-word (BNWORD32) + * type are lbnMulAdd1_16 and lbnMulSub1_16; if those are provided, + * the rest follows. lbnDiv21_16, however, is a lot slower unless you + * have them, and lbnModQ_16 takes after it. That one is used quite a + * bit for prime sieving. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_ASSERT_H +#define NO_ASSERT_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_ASSERT_H +#include <assert.h> +#else +#define assert(x) (void)0 +#endif + +#if !NO_STRING_H +#include <string.h> /* For memcpy */ +#elif HAVE_STRINGS_H +#include <strings.h> +#endif +#if NEED_MEMORY_H +#include <memory.h> +#endif + +#include "lbn.h" +#include "lbn16.h" +#include "lbnmem.h" +#include "legal.h" + +#include "kludge.h" +#include <port_after.h> + +#ifndef BNWORD16 +#error 16-bit bignum library requires a 16-bit data type +#endif + +/* Make sure the copyright notice gets included */ +volatile const char * volatile const lbnCopyright_16 = bnCopyright; + +/* + * Most of the multiply (and Montgomery reduce) routines use an outer + * loop that iterates over one of the operands - a so-called operand + * scanning approach. One big advantage of this is that the assembly + * support routines are simpler. The loops can be rearranged to have + * an outer loop that iterates over the product, a so-called product + * scanning approach. This has the advantage of writing less data + * and doing fewer adds to memory, so is supposedly faster. Some + * code has been written using a product-scanning approach, but + * it appears to be slower, so it is turned off by default. Some + * experimentation would be appreciated. + * + * (The code is also annoying to get right and not very well commented, + * one of my pet peeves about math libraries. I'm sorry.) + */ +#ifndef PRODUCT_SCAN +#define PRODUCT_SCAN 0 +#endif + +/* + * Copy an array of words. <Marvin mode on> Thrilling, isn't it? </Marvin> + * This is a good example of how the byte offsets and BIGLITTLE() macros work. + * Another alternative would have been + * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD16)), but I find that + * putting operators into conditional macros is confusing. + */ +#ifndef lbnCopy_16 +void +lbnCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len) +{ + memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src), + len * sizeof(*src)); +} +#endif /* !lbnCopy_16 */ + +/* + * Fill n words with zero. This does it manually rather than calling + * memset because it can assume alignment to make things faster while + * memset can't. Note how big-endian numbers are naturally addressed + * using predecrement, while little-endian is postincrement. + */ +#ifndef lbnZero_16 +void +lbnZero_16(BNWORD16 *num, unsigned len) +{ + while (len--) + BIGLITTLE(*--num,*num++) = 0; +} +#endif /* !lbnZero_16 */ + +/* + * Negate an array of words. + * Negation is subtraction from zero. Negating low-order words + * entails doing nothing until a non-zero word is hit. Once that + * is negated, a borrow is generated and never dies until the end + * of the number is hit. Negation with borrow, -x-1, is the same as ~x. + * Repeat that until the end of the number. + * + * Doesn't return borrow out because that's pretty useless - it's + * always set unless the input is 0, which is easy to notice in + * normalized form. + */ +#ifndef lbnNeg_16 +void +lbnNeg_16(BNWORD16 *num, unsigned len) +{ + assert(len); + + /* Skip low-order zero words */ + while (BIGLITTLE(*--num,*num) == 0) { + if (!--len) + return; + LITTLE(num++;) + } + /* Negate the lowest-order non-zero word */ + *num = -*num; + /* Complement all the higher-order words */ + while (--len) { + BIGLITTLE(--num,++num); + *num = ~*num; + } +} +#endif /* !lbnNeg_16 */ + + +/* + * lbnAdd1_16: add the single-word "carry" to the given number. + * Used for minor increments and propagating the carry after + * adding in a shorter bignum. + * + * Technique: If we have a double-width word, presumably the compiler + * can add using its carry in inline code, so we just use a larger + * accumulator to compute the carry from the first addition. + * If not, it's more complex. After adding the first carry, which may + * be > 1, compare the sum and the carry. If the sum wraps (causing a + * carry out from the addition), the result will be less than each of the + * inputs, since the wrap subtracts a number (2^16) which is larger than + * the other input can possibly be. If the sum is >= the carry input, + * return success immediately. + * In either case, if there is a carry, enter a loop incrementing words + * until one does not wrap. Since we are adding 1 each time, the wrap + * will be to 0 and we can test for equality. + */ +#ifndef lbnAdd1_16 /* If defined, it's provided as an asm subroutine */ +#ifdef BNWORD32 +BNWORD16 +lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry) +{ + BNWORD32 t; + assert(len > 0); /* Alternative: if (!len) return carry */ + + t = (BNWORD32)BIGLITTLE(*--num,*num) + carry; + BIGLITTLE(*num,*num++) = (BNWORD16)t; + if ((t >> 16) == 0) + return 0; + while (--len) { + if (++BIGLITTLE(*--num,*num++) != 0) + return 0; + } + return 1; +} +#else /* no BNWORD32 */ +BNWORD16 +lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry) +{ + assert(len > 0); /* Alternative: if (!len) return carry */ + + if ((BIGLITTLE(*--num,*num++) += carry) >= carry) + return 0; + while (--len) { + if (++BIGLITTLE(*--num,*num++) != 0) + return 0; + } + return 1; +} +#endif +#endif/* !lbnAdd1_16 */ + +/* + * lbnSub1_16: subtract the single-word "borrow" from the given number. + * Used for minor decrements and propagating the borrow after + * subtracting a shorter bignum. + * + * Technique: Similar to the add, above. If there is a double-length type, + * use that to generate the first borrow. + * If not, after subtracting the first borrow, which may be > 1, compare + * the difference and the *negative* of the carry. If the subtract wraps + * (causing a borrow out from the subtraction), the result will be at least + * as large as -borrow. If the result < -borrow, then no borrow out has + * appeared and we may return immediately, except when borrow == 0. To + * deal with that case, use the identity that -x = ~x+1, and instead of + * comparing < -borrow, compare for <= ~borrow. + * Either way, if there is a borrow out, enter a loop decrementing words + * until a non-zero word is reached. + * + * Note the cast of ~borrow to (BNWORD16). If the size of an int is larger + * than BNWORD16, C rules say the number is expanded for the arithmetic, so + * the inversion will be done on an int and the value won't be quite what + * is expected. + */ +#ifndef lbnSub1_16 /* If defined, it's provided as an asm subroutine */ +#ifdef BNWORD32 +BNWORD16 +lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow) +{ + BNWORD32 t; + assert(len > 0); /* Alternative: if (!len) return borrow */ + + t = (BNWORD32)BIGLITTLE(*--num,*num) - borrow; + BIGLITTLE(*num,*num++) = (BNWORD16)t; + if ((t >> 16) == 0) + return 0; + while (--len) { + if ((BIGLITTLE(*--num,*num++))-- != 0) + return 0; + } + return 1; +} +#else /* no BNWORD32 */ +BNWORD16 +lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow) +{ + assert(len > 0); /* Alternative: if (!len) return borrow */ + + if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD16)~borrow) + return 0; + while (--len) { + if ((BIGLITTLE(*--num,*num++))-- != 0) + return 0; + } + return 1; +} +#endif +#endif /* !lbnSub1_16 */ + +/* + * lbnAddN_16: add two bignums of the same length, returning the carry (0 or 1). + * One of the building blocks, along with lbnAdd1, of adding two bignums of + * differing lengths. + * + * Technique: Maintain a word of carry. If there is no double-width type, + * use the same technique as in lbnAdd1, above, to maintain the carry by + * comparing the inputs. Adding the carry sources is used as an OR operator; + * at most one of the two comparisons can possibly be true. The first can + * only be true if carry == 1 and x, the result, is 0. In that case the + * second can't possibly be true. + */ +#ifndef lbnAddN_16 +#ifdef BNWORD32 +BNWORD16 +lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) +{ + BNWORD32 t; + + assert(len > 0); + + t = (BNWORD32)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++); + BIGLITTLE(*num1,*num1++) = (BNWORD16)t; + while (--len) { + t = (BNWORD32)BIGLITTLE(*--num1,*num1) + + (BNWORD32)BIGLITTLE(*--num2,*num2++) + (t >> 16); + BIGLITTLE(*num1,*num1++) = (BNWORD16)t; + } + + return (BNWORD16)(t>>16); +} +#else /* no BNWORD32 */ +BNWORD16 +lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) +{ + BNWORD16 x, carry = 0; + + assert(len > 0); /* Alternative: change loop to test at start */ + + do { + x = BIGLITTLE(*--num2,*num2++); + carry = (x += carry) < carry; + carry += (BIGLITTLE(*--num1,*num1++) += x) < x; + } while (--len); + + return carry; +} +#endif +#endif /* !lbnAddN_16 */ + +/* + * lbnSubN_16: add two bignums of the same length, returning the carry (0 or 1). + * One of the building blocks, along with subn1, of subtracting two bignums of + * differing lengths. + * + * Technique: If no double-width type is availble, maintain a word of borrow. + * First, add the borrow to the subtrahend (did you have to learn all those + * awful words in elementary school, too?), and if it overflows, set the + * borrow again. Then subtract the modified subtrahend from the next word + * of input, using the same technique as in subn1, above. + * Adding the borrows is used as an OR operator; at most one of the two + * comparisons can possibly be true. The first can only be true if + * borrow == 1 and x, the result, is 0. In that case the second can't + * possibly be true. + * + * In the double-word case, (BNWORD16)-(t>>16) is subtracted, rather than + * adding t>>16, because the shift would need to sign-extend and that's + * not guaranteed to happen in ANSI C, even with signed types. + */ +#ifndef lbnSubN_16 +#ifdef BNWORD32 +BNWORD16 +lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) +{ + BNWORD32 t; + + assert(len > 0); + + t = (BNWORD32)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++); + BIGLITTLE(*num1,*num1++) = (BNWORD16)t; + + while (--len) { + t = (BNWORD32)BIGLITTLE(*--num1,*num1) - + (BNWORD32)BIGLITTLE(*--num2,*num2++) - (BNWORD16)-(t >> 16); + BIGLITTLE(*num1,*num1++) = (BNWORD16)t; + } + + return -(BNWORD16)(t>>16); +} +#else +BNWORD16 +lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len) +{ + BNWORD16 x, borrow = 0; + + assert(len > 0); /* Alternative: change loop to test at start */ + + do { + x = BIGLITTLE(*--num2,*num2++); + borrow = (x += borrow) < borrow; + borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD16)~x; + } while (--len); + + return borrow; +} +#endif +#endif /* !lbnSubN_16 */ + +#ifndef lbnCmp_16 +/* + * lbnCmp_16: compare two bignums of equal length, returning the sign of + * num1 - num2. (-1, 0 or +1). + * + * Technique: Change the little-endian pointers to big-endian pointers + * and compare from the most-significant end until a difference if found. + * When it is, figure out the sign of the difference and return it. + */ +int +lbnCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len) +{ + BIGLITTLE(num1 -= len, num1 += len); + BIGLITTLE(num2 -= len, num2 += len); + + while (len--) { + if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) { + if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2)) + return -1; + else + return 1; + } + } + return 0; +} +#endif /* !lbnCmp_16 */ + +/* + * mul16_ppmmaa(ph,pl,x,y,a,b) is an optional routine that + * computes (ph,pl) = x * y + a + b. mul16_ppmma and mul16_ppmm + * are simpler versions. If you want to be lazy, all of these + * can be defined in terms of the others, so here we create any + * that have not been defined in terms of the ones that have been. + */ + +/* Define ones with fewer a's in terms of ones with more a's */ +#if !defined(mul16_ppmma) && defined(mul16_ppmmaa) +#define mul16_ppmma(ph,pl,x,y,a) mul16_ppmmaa(ph,pl,x,y,a,0) +#endif + +#if !defined(mul16_ppmm) && defined(mul16_ppmma) +#define mul16_ppmm(ph,pl,x,y) mul16_ppmma(ph,pl,x,y,0) +#endif + +/* + * Use this definition to test the mul16_ppmm-based operations on machines + * that do not provide mul16_ppmm. Change the final "0" to a "1" to + * enable it. + */ +#if !defined(mul16_ppmm) && defined(BNWORD32) && 0 /* Debugging */ +#define mul16_ppmm(ph,pl,x,y) \ + ({BNWORD32 _ = (BNWORD32)(x)*(y); (pl) = _; (ph) = _>>16;}) +#endif + +#if defined(mul16_ppmm) && !defined(mul16_ppmma) +#define mul16_ppmma(ph,pl,x,y,a) \ + (mul16_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a)) +#endif + +#if defined(mul16_ppmma) && !defined(mul16_ppmmaa) +#define mul16_ppmmaa(ph,pl,x,y,a,b) \ + (mul16_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b)) +#endif + +/* + * lbnMulN1_16: Multiply an n-word input by a 1-word input and store the + * n+1-word product. This uses either the mul16_ppmm and mul16_ppmma + * macros, or C multiplication with the BNWORD32 type. This uses mul16_ppmma + * if available, assuming you won't bother defining it unless you can do + * better than the normal multiplication. + */ +#ifndef lbnMulN1_16 +#ifdef lbnMulAdd1_16 /* If we have this asm primitive, use it. */ +void +lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + lbnZero_16(out, len); + BIGLITTLE(*(out-len),*(out+len)) = lbnMulAdd1_16(out, in, len, k); +} +#elif defined(mul16_ppmm) +void +lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD16 prod, carry, carryin; + + assert(len > 0); + + BIG(--out;--in;); + mul16_ppmm(carry, *out, *in, k); + LITTLE(out++;in++;) + + while (--len) { + BIG(--out;--in;) + carryin = carry; + mul16_ppmma(carry, *out, *in, k, carryin); + LITTLE(out++;in++;) + } + BIGLITTLE(*--out,*out) = carry; +} +#elif defined(BNWORD32) +void +lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD32 p; + + assert(len > 0); + + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k; + BIGLITTLE(*--out,*out++) = (BNWORD16)p; + + while (--len) { + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + (BNWORD16)(p >> 16); + BIGLITTLE(*--out,*out++) = (BNWORD16)p; + } + BIGLITTLE(*--out,*out) = (BNWORD16)(p >> 16); +} +#else +#error No 16x16 -> 32 multiply available for 16-bit bignum package +#endif +#endif /* lbnMulN1_16 */ + +/* + * lbnMulAdd1_16: Multiply an n-word input by a 1-word input and add the + * low n words of the product to the destination. *Returns the n+1st word + * of the product.* (That turns out to be more convenient than adding + * it into the destination and dealing with a possible unit carry out + * of *that*.) This uses either the mul16_ppmma and mul16_ppmmaa macros, + * or C multiplication with the BNWORD32 type. + * + * If you're going to write assembly primitives, this is the one to + * start with. It is by far the most commonly called function. + */ +#ifndef lbnMulAdd1_16 +#if defined(mul16_ppmm) +BNWORD16 +lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD16 prod, carry, carryin; + + assert(len > 0); + + BIG(--out;--in;); + carryin = *out; + mul16_ppmma(carry, *out, *in, k, carryin); + LITTLE(out++;in++;) + + while (--len) { + BIG(--out;--in;); + carryin = carry; + mul16_ppmmaa(carry, prod, *in, k, carryin, *out); + *out = prod; + LITTLE(out++;in++;) + } + + return carry; +} +#elif defined(BNWORD32) +BNWORD16 +lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD32 p; + + assert(len > 0); + + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out); + BIGLITTLE(*out,*out++) = (BNWORD16)p; + + while (--len) { + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + + (BNWORD16)(p >> 16) + BIGLITTLE(*--out,*out); + BIGLITTLE(*out,*out++) = (BNWORD16)p; + } + + return (BNWORD16)(p >> 16); +} +#else +#error No 16x16 -> 32 multiply available for 16-bit bignum package +#endif +#endif /* lbnMulAdd1_16 */ + +/* + * lbnMulSub1_16: Multiply an n-word input by a 1-word input and subtract the + * n-word product from the destination. Returns the n+1st word of the product. + * This uses either the mul16_ppmm and mul16_ppmma macros, or + * C multiplication with the BNWORD32 type. + * + * This is rather uglier than adding, but fortunately it's only used in + * division which is not used too heavily. + */ +#ifndef lbnMulN1_16 +#if defined(mul16_ppmm) +BNWORD16 +lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD16 prod, carry, carryin; + + assert(len > 0); + + BIG(--in;) + mul16_ppmm(carry, prod, *in, k); + LITTLE(in++;) + carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod; + + while (--len) { + BIG(--in;); + carryin = carry; + mul16_ppmma(carry, prod, *in, k, carryin); + LITTLE(in++;) + carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod; + } + + return carry; +} +#elif defined(BNWORD32) +BNWORD16 +lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + BNWORD32 p; + BNWORD16 carry, t; + + assert(len > 0); + + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k; + t = BIGLITTLE(*--out,*out); + carry = (BNWORD16)(p>>16) + ((BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t); + + while (--len) { + p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + carry; + t = BIGLITTLE(*--out,*out); + carry = (BNWORD16)(p>>16) + + ( (BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t ); + } + + return carry; +} +#else +#error No 16x16 -> 32 multiply available for 16-bit bignum package +#endif +#endif /* !lbnMulSub1_16 */ + +/* + * Shift n words left "shift" bits. 0 < shift < 16. Returns the + * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift). + */ +#ifndef lbnLshift_16 +BNWORD16 +lbnLshift_16(BNWORD16 *num, unsigned len, unsigned shift) +{ + BNWORD16 x, carry; + + assert(shift > 0); + assert(shift < 16); + + carry = 0; + while (len--) { + BIG(--num;) + x = *num; + *num = (x<<shift) | carry; + LITTLE(num++;) + carry = x >> (16-shift); + } + return carry; +} +#endif /* !lbnLshift_16 */ + +/* + * An optimized version of the above, for shifts of 1. + * Some machines can use add-with-carry tricks for this. + */ +#ifndef lbnDouble_16 +BNWORD16 +lbnDouble_16(BNWORD16 *num, unsigned len) +{ + BNWORD16 x, carry; + + carry = 0; + while (len--) { + BIG(--num;) + x = *num; + *num = (x<<1) | carry; + LITTLE(num++;) + carry = x >> (16-1); + } + return carry; +} +#endif /* !lbnDouble_16 */ + +/* + * Shift n words right "shift" bits. 0 < shift < 16. Returns the + * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift). + */ +#ifndef lbnRshift_16 +BNWORD16 +lbnRshift_16(BNWORD16 *num, unsigned len, unsigned shift) +{ + BNWORD16 x, carry = 0; + + assert(shift > 0); + assert(shift < 16); + + BIGLITTLE(num -= len, num += len); + + while (len--) { + LITTLE(--num;) + x = *num; + *num = (x>>shift) | carry; + BIG(num++;) + carry = x << (16-shift); + } + return carry >> (16-shift); +} +#endif /* !lbnRshift_16 */ + +/* + * Multiply two numbers of the given lengths. prod and num2 may overlap, + * provided that the low len1 bits of prod are free. (This corresponds + * nicely to the place the result is returned from lbnMontReduce_16.) + * + * TODO: Use Karatsuba multiply. The overlap constraints may have + * to get rewhacked. + */ +#ifndef lbnMul_16 +void +lbnMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1, + BNWORD16 const *num2, unsigned len2) +{ + /* Special case of zero */ + if (!len1 || !len2) { + lbnZero_16(prod, len1+len2); + return; + } + + /* Multiply first word */ + lbnMulN1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); + + /* + * Add in subsequent words, storing the most significant word, + * which is new each time. + */ + while (--len2) { + BIGLITTLE(--prod,prod++); + BIGLITTLE(*(prod-len1-1),*(prod+len1)) = + lbnMulAdd1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); + } +} +#endif /* !lbnMul_16 */ + +/* + * lbnMulX_16 is a square multiply - both inputs are the same length. + * It's normally just a macro wrapper around the general multiply, + * but might be implementable in assembly more efficiently (such as + * when product scanning). + */ +#ifndef lbnMulX_16 +#if defined(BNWORD32) && PRODUCT_SCAN +/* + * Test code to see whether product scanning is any faster. It seems + * to make the C code slower, so PRODUCT_SCAN is not defined. + */ +static void +lbnMulX_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2, + unsigned len) +{ + BNWORD32 x, y; + BNWORD16 const *p1, *p2; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); + BIGLITTLE(*--prod, *prod++) = (BNWORD16)x; + x >>= 16; + + for (i = 1; i < len; i++) { + carry = 0; + p1 = num1; + p2 = BIGLITTLE(num2-i-1,num2+i+1); + for (j = 0; j <= i; j++) { + BIG(y = (BNWORD32)*--p1 * *p2++;) + LITTLE(y = (BNWORD32)*p1++ * *--p2;) + x += y; + carry += (x < y); + } + BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + for (i = 1; i < len; i++) { + carry = 0; + p1 = BIGLITTLE(num1-i,num1+i); + p2 = BIGLITTLE(num2-len,num2+len); + for (j = i; j < len; j++) { + BIG(y = (BNWORD32)*--p1 * *p2++;) + LITTLE(y = (BNWORD32)*p1++ * *--p2;) + x += y; + carry += (x < y); + } + BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + + BIGLITTLE(*--prod,*prod) = (BNWORD16)x; +} +#else /* !defined(BNWORD32) || !PRODUCT_SCAN */ +/* Default trivial macro definition */ +#define lbnMulX_16(prod, num1, num2, len) lbnMul_16(prod, num1, len, num2, len) +#endif /* !defined(BNWORD32) || !PRODUCT_SCAN */ +#endif /* !lbmMulX_16 */ + +#if !defined(lbnMontMul_16) && defined(BNWORD32) && PRODUCT_SCAN +/* + * Test code for product-scanning multiply. This seems to slow the C + * code down rather than speed it up. + * This does a multiply and Montgomery reduction together, using the + * same loops. The outer loop scans across the product, twice. + * The first pass computes the low half of the product and the + * Montgomery multipliers. These are stored in the product array, + * which contains no data as of yet. x and carry add up the columns + * and propagate carries forward. + * + * The second half multiplies the upper half, adding in the modulus + * times the Montgomery multipliers. The results of this multiply + * are stored. + */ +static void +lbnMontMul_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2, + BNWORD16 const *mod, unsigned len, BNWORD16 inv) +{ + BNWORD32 x, y; + BNWORD16 const *p1, *p2, *pm; + BNWORD16 *pp; + BNWORD16 t; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + /* + * This computes directly into the high half of prod, so just + * shift the pointer and consider prod only "len" elements long + * for the rest of the code. + */ + BIGLITTLE(prod -= len, prod += len); + + /* Pass 1 - compute Montgomery multipliers */ + /* First iteration can have certain simplifications. */ + x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); + BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD16)x; + y = (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]); + x += y; + /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */ + carry = (x < y); + assert((BNWORD16)x == 0); + x = x >> 16 | (BNWORD32)carry << 16; + + for (i = 1; i < len; i++) { + carry = 0; + p1 = num1; + p2 = BIGLITTLE(num2-i-1,num2+i+1); + pp = prod; + pm = BIGLITTLE(mod-i-1,mod+i+1); + for (j = 0; j < i; j++) { + y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); + x += y; + carry += (x < y); + y = (BNWORD32)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm); + x += y; + carry += (x < y); + } + y = (BNWORD32)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]); + x += y; + carry += (x < y); + assert(BIGLITTLE(pp == prod-i, pp == prod+i)); + BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD16)x; + assert(BIGLITTLE(pm == mod-1, pm == mod+1)); + y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]); + x += y; + carry += (x < y); + assert((BNWORD16)x == 0); + x = x >> 16 | (BNWORD32)carry << 16; + } + + /* Pass 2 - compute reduced product and store */ + for (i = 1; i < len; i++) { + carry = 0; + p1 = BIGLITTLE(num1-i,num1+i); + p2 = BIGLITTLE(num2-len,num2+len); + pm = BIGLITTLE(mod-i,mod+i); + pp = BIGLITTLE(prod-len,prod+len); + for (j = i; j < len; j++) { + y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); + x += y; + carry += (x < y); + y = (BNWORD32)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pm == mod-len, pm == mod+len)); + assert(BIGLITTLE(pp == prod-i, pp == prod+i)); + BIGLITTLE(pp[0],pp[-1]) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + + /* Last round of second half, simplified. */ + BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD16)x; + carry = (x >> 16); + + while (carry) + carry -= lbnSubN_16(prod, mod, len); + while (lbnCmp_16(prod, mod, len) >= 0) + (void)lbnSubN_16(prod, mod, len); +} +/* Suppress later definition */ +#define lbnMontMul_16 lbnMontMul_16 +#endif + +#if !defined(lbnSquare_16) && defined(BNWORD32) && PRODUCT_SCAN +/* + * Trial code for product-scanning squaring. This seems to slow the C + * code down rather than speed it up. + */ +void +lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len) +{ + BNWORD32 x, y, z; + BNWORD16 const *p1, *p2; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + /* Word 0 of product */ + x = (BNWORD32)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]); + BIGLITTLE(*--prod, *prod++) = (BNWORD16)x; + x >>= 16; + + /* Words 1 through len-1 */ + for (i = 1; i < len; i++) { + carry = 0; + y = 0; + p1 = num; + p2 = BIGLITTLE(num-i-1,num+i+1); + for (j = 0; j < (i+1)/2; j++) { + BIG(z = (BNWORD32)*--p1 * *p2++;) + LITTLE(z = (BNWORD32)*p1++ * *--p2;) + y += z; + carry += (y < z); + } + y += z = y; + carry += carry + (y < z); + if ((i & 1) == 0) { + assert(BIGLITTLE(--p1 == p2, p1 == --p2)); + BIG(z = (BNWORD32)*p2 * *p2;) + LITTLE(z = (BNWORD32)*p1 * *p1;) + y += z; + carry += (y < z); + } + x += y; + carry += (x < y); + BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + /* Words len through 2*len-2 */ + for (i = 1; i < len; i++) { + carry = 0; + y = 0; + p1 = BIGLITTLE(num-i,num+i); + p2 = BIGLITTLE(num-len,num+len); + for (j = 0; j < (len-i)/2; j++) { + BIG(z = (BNWORD32)*--p1 * *p2++;) + LITTLE(z = (BNWORD32)*p1++ * *--p2;) + y += z; + carry += (y < z); + } + y += z = y; + carry += carry + (y < z); + if ((len-i) & 1) { + assert(BIGLITTLE(--p1 == p2, p1 == --p2)); + BIG(z = (BNWORD32)*p2 * *p2;) + LITTLE(z = (BNWORD32)*p1 * *p1;) + y += z; + carry += (y < z); + } + x += y; + carry += (x < y); + BIGLITTLE(*--prod,*prod++) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + + /* Word 2*len-1 */ + BIGLITTLE(*--prod,*prod) = (BNWORD16)x; +} +/* Suppress later definition */ +#define lbnSquare_16 lbnSquare_16 +#endif + +/* + * Square a number, using optimized squaring to reduce the number of + * primitive multiples that are executed. There may not be any + * overlap of the input and output. + * + * Technique: Consider the partial products in the multiplication + * of "abcde" by itself: + * + * a b c d e + * * a b c d e + * ================== + * ae be ce de ee + * ad bd cd dd de + * ac bc cc cd ce + * ab bb bc bd be + * aa ab ac ad ae + * + * Note that everything above the main diagonal: + * ae be ce de = (abcd) * e + * ad bd cd = (abc) * d + * ac bc = (ab) * c + * ab = (a) * b + * + * is a copy of everything below the main diagonal: + * de + * cd ce + * bc bd be + * ab ac ad ae + * + * Thus, the sum is 2 * (off the diagonal) + diagonal. + * + * This is accumulated beginning with the diagonal (which + * consist of the squares of the digits of the input), which is then + * divided by two, the off-diagonal added, and multiplied by two + * again. The low bit is simply a copy of the low bit of the + * input, so it doesn't need special care. + * + * TODO: Merge the shift by 1 with the squaring loop. + * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W. + */ +#ifndef lbnSquare_16 +void +lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len) +{ + BNWORD16 t; + BNWORD16 *prodx = prod; /* Working copy of the argument */ + BNWORD16 const *numx = num; /* Working copy of the argument */ + unsigned lenx = len; /* Working copy of the argument */ + + if (!len) + return; + + /* First, store all the squares */ + while (lenx--) { +#ifdef mul16_ppmm + BNWORD16 ph, pl; + t = BIGLITTLE(*--numx,*numx++); + mul16_ppmm(ph,pl,t,t); + BIGLITTLE(*--prodx,*prodx++) = pl; + BIGLITTLE(*--prodx,*prodx++) = ph; +#elif defined(BNWORD32) /* use BNWORD32 */ + BNWORD32 p; + t = BIGLITTLE(*--numx,*numx++); + p = (BNWORD32)t * t; + BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)p; + BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)(p>>16); +#else /* Use lbnMulN1_16 */ + t = BIGLITTLE(numx[-1],*numx); + lbnMulN1_16(prodx, numx, 1, t); + BIGLITTLE(--numx,numx++); + BIGLITTLE(prodx -= 2, prodx += 2); +#endif + } + /* Then, shift right 1 bit */ + (void)lbnRshift_16(prod, 2*len, 1); + + /* Then, add in the off-diagonal sums */ + lenx = len; + numx = num; + prodx = prod; + while (--lenx) { + t = BIGLITTLE(*--numx,*numx++); + BIGLITTLE(--prodx,prodx++); + t = lbnMulAdd1_16(prodx, numx, lenx, t); + lbnAdd1_16(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t); + BIGLITTLE(--prodx,prodx++); + } + + /* Shift it back up */ + lbnDouble_16(prod, 2*len); + + /* And set the low bit appropriately */ + BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1; +} +#endif /* !lbnSquare_16 */ + +/* + * lbnNorm_16 - given a number, return a modified length such that the + * most significant digit is non-zero. Zero-length input is okay. + */ +#ifndef lbnNorm_16 +unsigned +lbnNorm_16(BNWORD16 const *num, unsigned len) +{ + BIGLITTLE(num -= len,num += len); + while (len && BIGLITTLE(*num++,*--num) == 0) + --len; + return len; +} +#endif /* lbnNorm_16 */ + +/* + * lbnBits_16 - return the number of significant bits in the array. + * It starts by normalizing the array. Zero-length input is okay. + * Then assuming there's anything to it, it fetches the high word, + * generates a bit length by multiplying the word length by 16, and + * subtracts off 16/2, 16/4, 16/8, ... bits if the high bits are clear. + */ +#ifndef lbnBits_16 +unsigned +lbnBits_16(BNWORD16 const *num, unsigned len) +{ + BNWORD16 t; + unsigned i; + + len = lbnNorm_16(num, len); + if (len) { + t = BIGLITTLE(*(num-len),*(num+(len-1))); + assert(t); + len *= 16; + i = 16/2; + do { + if (t >> i) + t >>= i; + else + len -= i; + } while ((i /= 2) != 0); + } + return len; +} +#endif /* lbnBits_16 */ + +/* + * If defined, use hand-rolled divide rather than compiler's native. + * If the machine doesn't do it in line, the manual code is probably + * faster, since it can assume normalization and the fact that the + * quotient will fit into 16 bits, which a general 32-bit divide + * in a compiler's run-time library can't do. + */ +#ifndef BN_SLOW_DIVIDE_32 +/* Assume that divisors of more than thirty-two bits are slow */ +#define BN_SLOW_DIVIDE_32 (32 > 0x20) +#endif + +/* + * Return (nh<<16|nl) % d, and place the quotient digit into *q. + * It is guaranteed that nh < d, and that d is normalized (with its high + * bit set). If we have a double-width type, it's easy. If not, ooh, + * yuk! + */ +#ifndef lbnDiv21_16 +#if defined(BNWORD32) && !BN_SLOW_DIVIDE_32 +BNWORD16 +lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d) +{ + BNWORD32 n = (BNWORD32)nh << 16 | nl; + + /* Divisor must be normalized */ + assert(d >> (16-1) == 1); + + *q = (BNWORD16)(n / d); + return (BNWORD16)(n % d); +} +#else +/* + * This is where it gets ugly. + * + * Do the division in two halves, using Algorithm D from section 4.3.1 + * of Knuth. Note Theorem B from that section, that the quotient estimate + * is never more than the true quotient, and is never more than two + * too low. + * + * The mapping onto conventional long division is (everything a half word): + * _____________qh___ql_ + * dh dl ) nh.h nh.l nl.h nl.l + * - (qh * d) + * ----------- + * rrrr rrrr nl.l + * - (ql * d) + * ----------- + * rrrr rrrr + * + * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way: + * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from + * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the + * low part of the subtractor, qh * dl. This also needs to be subtracted + * from (nh.h nh.l nl.h) to get the final remainder. So we take the + * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and + * try to subtract qh * dl from that. Since the remainder is 1/2-word + * long, shifting and adding nl.h results in a single word r. + * It is possible that the remainder we're working with, r, is less than + * the product qh * dl, if we estimated qh too high. The estimation + * technique can produce a qh that is too large (never too small), leading + * to r which is too small. In that case, decrement the digit qh, add + * shifted dh to r (to correct for that error), and subtract dl from the + * product we're comparing r with. That's the "correct" way to do it, but + * just adding dl to r instead of subtracting it from the product is + * equivalent and a lot simpler. You just have to watch out for overflow. + * + * The process is repeated with (rrrr rrrr nl.l) for the low digit of the + * quotient ql. + * + * The various uses of 16/2 for shifts are because of the note about + * automatic editing of this file at the very top of the file. + */ +#define highhalf(x) ( (x) >> 16/2 ) +#define lowhalf(x) ( (x) & (((BNWORD16)1 << 16/2)-1) ) +BNWORD16 +lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d) +{ + BNWORD16 dh = highhalf(d), dl = lowhalf(d); + BNWORD16 qh, ql, prod, r; + + /* Divisor must be normalized */ + assert((d >> (16-1)) == 1); + + /* Do first half-word of division */ + qh = nh / dh; + r = nh % dh; + prod = qh * dl; + + /* + * Add next half-word of numerator to remainder and correct. + * qh may be up to two too large. + */ + r = (r << (16/2)) | highhalf(nl); + if (r < prod) { + --qh; r += d; + if (r >= d && r < prod) { + --qh; r += d; + } + } + r -= prod; + + /* Do second half-word of division */ + ql = r / dh; + r = r % dh; + prod = ql * dl; + + r = (r << (16/2)) | lowhalf(nl); + if (r < prod) { + --ql; r += d; + if (r >= d && r < prod) { + --ql; r += d; + } + } + r -= prod; + + *q = (qh << (16/2)) | ql; + + return r; +} +#endif +#endif /* lbnDiv21_16 */ + + +/* + * In the division functions, the dividend and divisor are referred to + * as "n" and "d", which stand for "numerator" and "denominator". + * + * The quotient is (nlen-dlen+1) digits long. It may be overlapped with + * the high (nlen-dlen) words of the dividend, but one extra word is needed + * on top to hold the top word. + */ + +/* + * Divide an n-word number by a 1-word number, storing the remainder + * and n-1 words of the n-word quotient. The high word is returned. + * It IS legal for rem to point to the same address as n, and for + * q to point one word higher. + * + * TODO: If BN_SLOW_DIVIDE_32, add a divnhalf_16 which uses 16-bit + * dividends if the divisor is half that long. + * TODO: Shift the dividend on the fly to avoid the last division and + * instead have a remainder that needs shifting. + * TODO: Use reciprocals rather than dividing. + */ +#ifndef lbnDiv1_16 +BNWORD16 +lbnDiv1_16(BNWORD16 *q, BNWORD16 *rem, BNWORD16 const *n, unsigned len, + BNWORD16 d) +{ + unsigned shift; + unsigned xlen; + BNWORD16 r; + BNWORD16 qhigh; + + assert(len > 0); + assert(d); + + if (len == 1) { + r = *n; + *rem = r%d; + return r/d; + } + + shift = 0; + r = d; + xlen = 16/2; + do { + if (r >> xlen) + r >>= xlen; + else + shift += xlen; + } while ((xlen /= 2) != 0); + assert((d >> (16-1-shift)) == 1); + d <<= shift; + + BIGLITTLE(q -= len-1,q += len-1); + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + if (r < d) { + qhigh = 0; + } else { + qhigh = r/d; + r %= d; + } + + xlen = len; + while (--xlen) + r = lbnDiv21_16(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d); + + /* + * Final correction for shift - shift the quotient up "shift" + * bits, and merge in the extra bits of quotient. Then reduce + * the final remainder mod the real d. + */ + if (shift) { + d >>= shift; + qhigh = (qhigh << shift) | lbnLshift_16(q, len-1, shift); + BIGLITTLE(q[-1],*q) |= r/d; + r %= d; + } + *rem = r; + + return qhigh; +} +#endif + +/* + * This function performs a "quick" modulus of a number with a divisor + * d which is guaranteed to be at most sixteen bits, i.e. less than 65536. + * This applies regardless of the word size the library is compiled with. + * + * This function is important to prime generation, for sieving. + */ +#ifndef lbnModQ_16 +/* If there's a custom lbnMod21_16, no normalization needed */ +#ifdef lbnMod21_16 +unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) +{ + unsigned i, shift; + BNWORD16 r; + + assert(len > 0); + + BIGLITTLE(n -= len,n += len); + + /* Try using a compare to avoid the first divide */ + r = BIGLITTLE(*n++,*--n); + if (r >= d) + r %= d; + while (--len) + r = lbnMod21_16(r, BIGLITTLE(*n++,*--n), d); + + return r; +} +#elif defined(BNWORD32) && !BN_SLOW_DIVIDE_32 +unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) +{ + BNWORD16 r; + + if (!--len) + return BIGLITTLE(n[-1],n[0]) % d; + + BIGLITTLE(n -= len,n += len); + r = BIGLITTLE(n[-1],n[0]); + + do { + r = (BNWORD16)((((BNWORD32)r<<16) | BIGLITTLE(*n++,*--n)) % d); + } while (--len); + + return r; +} +#elif 16 >= 0x20 +/* + * If the single word size can hold 65535*65536, then this function + * is avilable. + */ +#ifndef highhalf +#define highhalf(x) ( (x) >> 16/2 ) +#define lowhalf(x) ( (x) & ((1 << 16/2)-1) ) +#endif +unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) +{ + BNWORD16 r, x; + + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + while (--len) { + x = BIGLITTLE(*n++,*--n); + r = (r%d << 16/2) | highhalf(x); + r = (r%d << 16/2) | lowhalf(x); + } + + return r%d; +} +#else +/* Default case - use lbnDiv21_16 */ +unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d) +{ + unsigned i, shift; + BNWORD16 r; + BNWORD16 q; + + assert(len > 0); + + shift = 0; + r = d; + i = 16; + while (i /= 2) { + if (r >> i) + r >>= i; + else + shift += i; + } + assert(d >> (16-1-shift) == 1); + d <<= shift; + + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + if (r >= d) + r %= d; + + while (--len) + r = lbnDiv21_16(&q, r, BIGLITTLE(*n++,*--n), d); + + /* + * Final correction for shift - shift the quotient up "shift" + * bits, and merge in the extra bits of quotient. Then reduce + * the final remainder mod the real d. + */ + if (shift) + r %= d >> shift; + + return r; +} +#endif +#endif /* lbnModQ_16 */ + +/* + * Reduce n mod d and return the quotient. That is, find: + * q = n / d; + * n = n % d; + * d is altered during the execution of this subroutine by normalizing it. + * It must already have its most significant word non-zero; it is shifted + * so its most significant bit is non-zero. + * + * The quotient q is nlen-dlen+1 words long. To make it possible to + * overlap the quptient with the input (you can store it in the high dlen + * words), the high word of the quotient is *not* stored, but is returned. + * (If all you want is the remainder, you don't care about it, anyway.) + * + * This uses algorithm D from Knuth (4.3.1), except that we do binary + * (shift) normalization of the divisor. WARNING: This is hairy! + * + * This function is used for some modular reduction, but it is not used in + * the modular exponentiation loops; they use Montgomery form and the + * corresponding, more efficient, Montgomery reduction. This code + * is needed for the conversion to Montgomery form, however, so it + * has to be here and it might as well be reasonably efficient. + * + * The overall operation is as follows ("top" and "up" refer to the + * most significant end of the number; "bottom" and "down", the least): + * + * - Shift the divisor up until the most significant bit is set. + * - Shift the dividend up the same amount. This will produce the + * correct quotient, and the remainder can be recovered by shifting + * it back down the same number of bits. This may produce an overflow + * word, but the word is always strictly less than the most significant + * divisor word. + * - Estimate the first quotient digit qhat: + * - First take the top two words (one of which is the overflow) of the + * dividend and divide by the top word of the divisor: + * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit + * and, since dh is normalized, it is at most two over. + * - Second, correct by comparing the top three words. If + * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again. + * The second iteration can be simpler because there can't be a third. + * The computation can be simplified by subtracting dh*qhat from + * both sides, suitably shifted. This reduces the left side to + * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the + * remainder r from (nh,nm)%dh, so the right is (r,nl). + * This produces qhat that is almost always correct and at + * most (prob ~ 2/2^16) one too high. + * - Subtract qhat times the divisor (suitably shifted) from the dividend. + * If there is a borrow, qhat was wrong, so decrement it + * and add the divisor back in (once). + * - Store the final quotient digit qhat in the quotient array q. + * + * Repeat the quotient digit computation for successive digits of the + * quotient until the whole quotient has been computed. Then shift the + * divisor and the remainder down to correct for the normalization. + * + * TODO: Special case 2-word divisors. + * TODO: Use reciprocals rather than dividing. + */ +#ifndef divn_16 +BNWORD16 +lbnDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen) +{ + BNWORD16 nh,nm,nl; /* Top three words of the dividend */ + BNWORD16 dh,dl; /* Top two words of the divisor */ + BNWORD16 qhat; /* Extimate of quotient word */ + BNWORD16 r; /* Remainder from quotient estimate division */ + BNWORD16 qhigh; /* High word of quotient */ + unsigned i; /* Temp */ + unsigned shift; /* Bits shifted by normalization */ + unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */ +#ifdef mul16_ppmm + BNWORD16 t16; +#elif defined(BNWORD32) + BNWORD32 t32; +#else /* use lbnMulN1_16 */ + BNWORD16 t2[2]; +#define t2high BIGLITTLE(t2[0],t2[1]) +#define t2low BIGLITTLE(t2[1],t2[0]) +#endif + + assert(dlen); + assert(nlen >= dlen); + + /* + * Special cases for short divisors. The general case uses the + * top top 2 digits of the divisor (d) to estimate a quotient digit, + * so it breaks if there are fewer digits available. Thus, we need + * special cases for a divisor of length 1. A divisor of length + * 2 can have a *lot* of administrivia overhead removed removed, + * so it's probably worth special-casing that case, too. + */ + if (dlen == 1) + return lbnDiv1_16(q, BIGLITTLE(n-1,n), n, nlen, + BIGLITTLE(d[-1],d[0])); + +#if 0 + /* + * @@@ This is not yet written... The general loop will do, + * albeit less efficiently + */ + if (dlen == 2) { + /* + * divisor two digits long: + * use the 3/2 technique from Knuth, but we know + * it's exact. + */ + dh = BIGLITTLE(d[-1],d[0]); + dl = BIGLITTLE(d[-2],d[1]); + shift = 0; + if ((sh & ((BNWORD16)1 << 16-1-shift)) == 0) { + do { + shift++; + } while (dh & (BNWORD16)1<<16-1-shift) == 0); + dh = dh << shift | dl >> (16-shift); + dl <<= shift; + + + } + + + for (shift = 0; (dh & (BNWORD16)1 << 16-1-shift)) == 0; shift++) + ; + if (shift) { + } + dh = dh << shift | dl >> (16-shift); + shift = 0; + while (dh + } +#endif + + dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); + assert(dh); + + /* Normalize the divisor */ + shift = 0; + r = dh; + i = 16/2; + do { + if (r >> i) + r >>= i; + else + shift += i; + } while ((i /= 2) != 0); + + nh = 0; + if (shift) { + lbnLshift_16(d, dlen, shift); + dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); + nh = lbnLshift_16(n, nlen, shift); + } + + /* Assert that dh is now normalized */ + assert(dh >> (16-1)); + + /* Also get the second-most significant word of the divisor */ + dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2))); + + /* + * Adjust pointers: n to point to least significant end of first + * first subtract, and q to one the most-significant end of the + * quotient array. + */ + BIGLITTLE(n -= qlen,n += qlen); + BIGLITTLE(q -= qlen,q += qlen); + + /* Fetch the most significant stored word of the dividend */ + nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + + /* + * Compute the first digit of the quotient, based on the + * first two words of the dividend (the most significant of which + * is the overflow word h). + */ + if (nh) { + assert(nh < dh); + r = lbnDiv21_16(&qhat, nh, nm, dh); + } else if (nm >= dh) { + qhat = nm/dh; + r = nm % dh; + } else { /* Quotient is zero */ + qhigh = 0; + goto divloop; + } + + /* Now get the third most significant word of the dividend */ + nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); + + /* + * Correct qhat, the estimate of quotient digit. + * qhat can only be high, and at most two words high, + * so the loop can be unrolled and abbreviated. + */ +#ifdef mul16_ppmm + mul16_ppmm(nm, t16, qhat, dl); + if (nm > r || (nm == r && t16 > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + nm -= (t16 < dl); + t16 -= dl; + if (nm > r || (nm == r && t16 > nl)) + qhat--; + } + } +#elif defined(BNWORD32) + t32 = (BNWORD32)qhat * dl; + if (t32 > ((BNWORD32)r << 16) + nl) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) > dh) { + t32 -= dl; + if (t32 > ((BNWORD32)r << 16) + nl) + qhat--; + } + } +#else /* Use lbnMulN1_16 */ + lbnMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat); + if (t2high > r || (t2high == r && t2low > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t2high -= (t2low < dl); + t2low -= dl; + if (t2high > r || (t2high == r && t2low > nl)) + qhat--; + } + } +#endif + + /* Do the multiply and subtract */ + r = lbnMulSub1_16(n, d, dlen, qhat); + /* If there was a borrow, add back once. */ + if (r > nh) { /* Borrow? */ + (void)lbnAddN_16(n, d, dlen); + qhat--; + } + + /* Remember the first quotient digit. */ + qhigh = qhat; + + /* Now, the main division loop: */ +divloop: + while (qlen--) { + + /* Advance n */ + nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + BIGLITTLE(++n,--n); + nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + + if (nh == dh) { + qhat = ~(BNWORD16)0; + /* Optimized computation of r = (nh,nm) - qhat * dh */ + r = nh + nm; + if (r < nh) + goto subtract; + } else { + assert(nh < dh); + r = lbnDiv21_16(&qhat, nh, nm, dh); + } + + nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); +#ifdef mul16_ppmm + mul16_ppmm(nm, t16, qhat, dl); + if (nm > r || (nm == r && t16 > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + nm -= (t16 < dl); + t16 -= dl; + if (nm > r || (nm == r && t16 > nl)) + qhat--; + } + } +#elif defined(BNWORD32) + t32 = (BNWORD32)qhat * dl; + if (t32 > ((BNWORD32)r<<16) + nl) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t32 -= dl; + if (t32 > ((BNWORD32)r << 16) + nl) + qhat--; + } + } +#else /* Use lbnMulN1_16 */ + lbnMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat); + if (t2high > r || (t2high == r && t2low > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t2high -= (t2low < dl); + t2low -= dl; + if (t2high > r || (t2high == r && t2low > nl)) + qhat--; + } + } +#endif + + /* + * As a point of interest, note that it is not worth checking + * for qhat of 0 or 1 and installing special-case code. These + * occur with probability 2^-16, so spending 1 cycle to check + * for them is only worth it if we save more than 2^15 cycles, + * and a multiply-and-subtract for numbers in the 1024-bit + * range just doesn't take that long. + */ +subtract: + /* + * n points to the least significant end of the substring + * of n to be subtracted from. qhat is either exact or + * one too large. If the subtract gets a borrow, it was + * one too large and the divisor is added back in. It's + * a dlen+1 word add which is guaranteed to produce a + * carry out, so it can be done very simply. + */ + r = lbnMulSub1_16(n, d, dlen, qhat); + if (r > nh) { /* Borrow? */ + (void)lbnAddN_16(n, d, dlen); + qhat--; + } + /* Store the quotient digit */ + BIGLITTLE(*q++,*--q) = qhat; + } + /* Tah dah! */ + + if (shift) { + lbnRshift_16(d, dlen, shift); + lbnRshift_16(n, dlen, shift); + } + + return qhigh; +} +#endif + +/* + * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^16. + * + * This just performs Newton's iteration until it gets the + * inverse. The initial estimate is always correct to 3 bits, and + * sometimes 4. The number of valid bits doubles each iteration. + * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable + * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow + * the iteration through.) + */ +#ifndef lbnMontInv1_16 +BNWORD16 +lbnMontInv1_16(BNWORD16 const x) +{ + BNWORD16 y = x, z; + + assert(x & 1); + + while ((z = x*y) != 1) + y *= 2 - z; + return -y; +} +#endif /* !lbnMontInv1_16 */ + +#if defined(BNWORD32) && PRODUCT_SCAN +/* + * Test code for product-scanning Montgomery reduction. + * This seems to slow the C code down rather than speed it up. + * + * The first loop computes the Montgomery multipliers, storing them over + * the low half of the number n. + * + * The second half multiplies the upper half, adding in the modulus + * times the Montgomery multipliers. The results of this multiply + * are stored. + */ +void +lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned mlen, BNWORD16 inv) +{ + BNWORD32 x, y; + BNWORD16 const *pm; + BNWORD16 *pn; + BNWORD16 t; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!mlen) + return; + + /* Pass 1 - compute Montgomery multipliers */ + /* First iteration can have certain simplifications. */ + t = BIGLITTLE(n[-1],n[0]); + x = t; + t *= inv; + BIGLITTLE(n[-1], n[0]) = t; + x += (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */ + assert((BNWORD16)x == 0); + x = x >> 16; + + for (i = 1; i < mlen; i++) { + carry = 0; + pn = n; + pm = BIGLITTLE(mod-i-1,mod+i+1); + for (j = 0; j < i; j++) { + y = (BNWORD32)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pn == n-i, pn == n+i)); + y = t = BIGLITTLE(pn[-1], pn[0]); + x += y; + carry += (x < y); + BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD16)x; + assert(BIGLITTLE(pm == mod-1, pm == mod+1)); + y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]); + x += y; + carry += (x < y); + assert((BNWORD16)x == 0); + x = x >> 16 | (BNWORD32)carry << 16; + } + + BIGLITTLE(n -= mlen, n += mlen); + + /* Pass 2 - compute upper words and add to n */ + for (i = 1; i < mlen; i++) { + carry = 0; + pm = BIGLITTLE(mod-i,mod+i); + pn = n; + for (j = i; j < mlen; j++) { + y = (BNWORD32)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen)); + assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i)); + y = t = BIGLITTLE(*(n-i),*(n+i-1)); + x += y; + carry += (x < y); + BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD16)x; + x = (x >> 16) | (BNWORD32)carry << 16; + } + + /* Last round of second half, simplified. */ + t = BIGLITTLE(*(n-mlen),*(n+mlen-1)); + x += t; + BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD16)x; + carry = (unsigned)(x >> 16); + + while (carry) + carry -= lbnSubN_16(n, mod, mlen); + while (lbnCmp_16(n, mod, mlen) >= 0) + (void)lbnSubN_16(n, mod, mlen); +} +#define lbnMontReduce_16 lbnMontReduce_16 +#endif + +/* + * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by + * 2^(16*mlen). Returns the result in the *top* mlen words of the argument n. + * This is ready for another multiplication using lbnMul_16. + * + * Montgomery representation is a very useful way to encode numbers when + * you're doing lots of modular reduction. What you do is pick a multiplier + * R which is relatively prime to the modulus and very easy to divide by. + * Since the modulus is odd, R is closen as a power of 2, so the division + * is a shift. In fact, it's a shift of an integral number of words, + * so the shift can be implicit - just drop the low-order words. + * + * Now, choose R *larger* than the modulus m, 2^(16*mlen). Then convert + * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the + * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that: + * - The Montgomery form of a number depends on the modulus m. + * A fixed modulus m is assumed throughout this discussion. + * - Since R is relaitvely prime to m, multiplication by R is invertible; + * no information about the numbers is lost, they're just scrambled. + * - Adding (and subtracting) numbers in this form works just as usual. + * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m + * - Multiplying numbers in this form produces a*b*R*R. The problem + * is to divide out the excess factor of R, modulo m as well as to + * reduce to the given length mlen. It turns out that this can be + * done *faster* than a normal divide, which is where the speedup + * in Montgomery division comes from. + * + * Normal reduction chooses a most-significant quotient digit q and then + * subtracts q*m from the number to be reduced. Choosing q is tricky + * and involved (just look at lbnDiv_16 to see!) and is usually + * imperfect, requiring a check for correction after the subtraction. + * + * Montgomery reduction *adds* a multiple of m to the *low-order* part + * of the number to be reduced. This multiple is chosen to make the + * low-order part of the number come out to zero. This can be done + * with no trickery or error using a precomputed inverse of the modulus. + * In this code, the "part" is one word, but any width can be used. + * + * Repeating this step sufficiently often results in a value which + * is a multiple of R (a power of two, remember) but is still (since + * the additions were to the low-order part and thus did not increase + * the value of the number being reduced very much) still not much + * larger than m*R. Then implicitly divide by R and subtract off + * m until the result is in the correct range. + * + * Since the low-order part being cancelled is less than R, the + * multiple of m added must have a multiplier which is at most R-1. + * Assuming that the input is at most m*R-1, the final number is + * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from + * the high-order part, equivalent to subtracting m*R from the + * while number, produces a result which is at most m*R - m - 1, + * which divided by R is at most m-1. + * + * To convert *to* Montgomery form, you need a regular remainder + * routine, although you can just compute R*R (mod m) and do the + * conversion using Montgomery multiplication. To convert *from* + * Montgomery form, just Montgomery reduce the number to + * remove the extra factor of R. + * + * TODO: Change to a full inverse and use Karatsuba's multiplication + * rather than this word-at-a-time. + */ +#ifndef lbnMontReduce_16 +void +lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen, + BNWORD16 inv) +{ + BNWORD16 t; + BNWORD16 c = 0; + unsigned len = mlen; + + /* inv must be the negative inverse of mod's least significant word */ + assert((BNWORD16)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD16)-1); + + assert(len); + + do { + t = lbnMulAdd1_16(n, mod, mlen, (BNWORD16)(inv * BIGLITTLE(n[-1],n[0]))); + c += lbnAdd1_16(BIGLITTLE(n-mlen,n+mlen), len, t); + BIGLITTLE(--n,++n); + } while (--len); + + /* + * All that adding can cause an overflow past the modulus size, + * but it's unusual, and never by much, so a subtraction loop + * is the right way to deal with it. + * This subtraction happens infrequently - I've only ever seen it + * invoked once per reduction, and then just under 22.5% of the time. + */ + while (c) + c -= lbnSubN_16(n, mod, mlen); + while (lbnCmp_16(n, mod, mlen) >= 0) + (void)lbnSubN_16(n, mod, mlen); +} +#endif /* !lbnMontReduce_16 */ + +/* + * A couple of helpers that you might want to implement atomically + * in asm sometime. + */ +#ifndef lbnMontMul_16 +/* + * Multiply "num1" by "num2", modulo "mod", all of length "len", and + * place the result in the high half of "prod". "inv" is the inverse + * of the least-significant word of the modulus, modulo 2^16. + * This uses numbers in Montgomery form. Reduce using "len" and "inv". + * + * This is implemented as a macro to win on compilers that don't do + * inlining, since it's so trivial. + */ +#define lbnMontMul_16(prod, n1, n2, mod, len, inv) \ + (lbnMulX_16(prod, n1, n2, len), lbnMontReduce_16(prod, mod, len, inv)) +#endif /* !lbnMontMul_16 */ + +#ifndef lbnMontSquare_16 +/* + * Square "num", modulo "mod", both of length "len", and place the result + * in the high half of "prod". "inv" is the inverse of the least-significant + * word of the modulus, modulo 2^16. + * This uses numbers in Montgomery form. Reduce using "len" and "inv". + * + * This is implemented as a macro to win on compilers that don't do + * inlining, since it's so trivial. + */ +#define lbnMontSquare_16(prod, n, mod, len, inv) \ + (lbnSquare_16(prod, n, len), lbnMontReduce_16(prod, mod, len, inv)) + +#endif /* !lbnMontSquare_16 */ + +/* + * Convert a number to Montgomery form - requires mlen + nlen words + * of memory in "n". + */ +void +lbnToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen) +{ + /* Move n up "mlen" words */ + lbnCopy_16(BIGLITTLE(n-mlen,n+mlen), n, nlen); + lbnZero_16(n, mlen); + /* Do the division - dump the quotient in the high-order words */ + (void)lbnDiv_16(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen); +} + +/* + * Convert from Montgomery form. Montgomery reduction is all that is + * needed. + */ +void +lbnFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len) +{ + /* Zero the high words of n */ + lbnZero_16(BIGLITTLE(n-len,n+len), len); + lbnMontReduce_16(n, mod, len, lbnMontInv1_16(BIGLITTLE(mod[-1],mod[0]))); + /* Move n down len words */ + lbnCopy_16(n, BIGLITTLE(n-len,n+len), len); +} + +/* + * The windowed exponentiation algorithm, precomputes a table of odd + * powers of n up to 2^k. It takes 2^(k-1)-1 multiplies to compute + * the table, and (e-1)/(k+1) multiplies (on average) to perform the + * exponentiation. To minimize the sum, k must vary with e. + * The optimal window sizes vary with the exponent length. Here are + * some selected values and the boundary cases. + * (An underscore _ has been inserted into some of the numbers to ensure + * that magic strings like 16 do not appear in this table. It should be + * ignored.) + * + * At e = 1 bits, k=1 (0.000000) is best. + * At e = 2 bits, k=1 (0.500000) is best. + * At e = 4 bits, k=1 (1.500000) is best. + * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000) + * At e = 1_6 bits, k=2 (6.000000) is best. + * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333) + * At e = 3_2 bits, k=3 (10.750000) is best. + * At e = 6_4 bits, k=3 (18.750000) is best. + * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000) + * At e = 128 bits, k=4 (3_2.400000) is best. + * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000) + * At e = 256 bits, k=5 (57.500000) is best. + * At e = 512 bits, k=5 (100.1_66667) is best. + * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667) + * At e = 1024 bits, k=6 (177.142857) is best. + * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857) + * At e = 2048 bits, k=7 (318.875000) is best. + * At e = 4096 bits, k=7 (574.875000) is best. + * + * The numbers in parentheses are the expected number of multiplications + * needed to do the computation. The normal russian-peasant modular + * exponentiation technique always uses (e-1)/2. For exponents as + * small as 192 bits (below the range of current factoring algorithms), + * half of the multiplies are eliminated, 45.2 as opposed to the naive + * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring + * proper is just over half of multiplying, but the Montgomery + * reduction in each case is also a multiply), that's 143.25 + * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings. + * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a + * 24.3% savings. It asymptotically approaches 25%. + * + * Given that exponents for which k>7 are useful are uncommon, + * a fixed size table for k <= 7 is used for simplicity. + * k = 8 is uzeful at 4610 bits, k = 9 at 11522 bits. + * + * The basic number of squarings needed is e-1, although a k-bit + * window (for k > 1) can save, on average, k-2 of those, too. + * That savings currently isn't counted here. It would drive the + * crossover points slightly lower. + * (Actually, this win is also reduced in the DoubleExpMod case, + * meaning we'd have to split the tables. Except for that, the + * multiplies by powers of the two bases are independent, so + * the same logic applies to each as the single case.) + * + * Table entry i is the largest number of bits in an exponent to + * process with a window size of i+1. So the window never goes above 7 + * bits, requiring 2^(7-1) = 0x40 precomputed multiples. + */ +#define BNEXPMOD_MAX_WINDOW 7 +static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = { + 7, 25, 81, 241, 673, 1793, (unsigned)-1 +}; + +/* + * Perform modular exponentiation, as fast as possible! This uses + * Montgomery reduction, optimized squaring, and windowed exponentiation. + * The modulus "mod" MUST be odd! + * + * This returns 0 on success, -1 on out of memory. + * + * The window algorithm: + * The idea is to keep a running product of b1 = n^(high-order bits of exp), + * and then keep appending exponent bits to it. The following patterns + * apply to a 3-bit window (k = 3): + * To append 0: square + * To append 1: square, multiply by n^1 + * To append 10: square, multiply by n^1, square + * To append 11: square, square, multiply by n^3 + * To append 100: square, multiply by n^1, square, square + * To append 101: square, square, square, multiply by n^5 + * To append 110: square, square, multiply by n^3, square + * To append 111: square, square, square, multiply by n^7 + * + * Since each pattern involves only one multiply, the longer the pattern + * the better, except that a 0 (no multiplies) can be appended directly. + * We precompute a table of odd powers of n, up to 2^k, and can then + * multiply k bits of exponent at a time. Actually, assuming random + * exponents, there is on average one zero bit between needs to + * multiply (1/2 of the time there's none, 1/4 of the time there's 1, + * 1/8 of the time, there's 2, 1/16 of the time, there's 3, etc.), so + * you have to do one multiply per k+1 bits of exponent. + * + * The loop walks down the exponent, squaring the result buffer as + * it goes. There is a wbits+1 bit lookahead buffer, buf, that is + * filled with the upcoming exponent bits. (What is read after the + * end of the exponent is unimportant, but it is filled with zero here.) + * When the most-significant bit of this buffer becomes set, i.e. + * (buf & tblmask) != 0, we have to decide what pattern to multiply + * by, and when to do it. We decide, remember to do it in future + * after a suitable number of squarings have passed (e.g. a pattern + * of "100" in the buffer requires that we multiply by n^1 immediately; + * a pattern of "110" calls for multiplying by n^3 after one more + * squaring), clear the buffer, and continue. + * + * When we start, there is one more optimization: the result buffer + * is implcitly one, so squaring it or multiplying by it can be + * optimized away. Further, if we start with a pattern like "100" + * in the lookahead window, rather than placing n into the buffer + * and then starting to square it, we have already computed n^2 + * to compute the odd-powers table, so we can place that into + * the buffer and save a squaring. + * + * This means that if you have a k-bit window, to compute n^z, + * where z is the high k bits of the exponent, 1/2 of the time + * it requires no squarings. 1/4 of the time, it requires 1 + * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings. + * And the remaining 1/2^(k-1) of the time, the top k bits are a + * 1 followed by k-1 0 bits, so it again only requires k-2 + * squarings, not k-1. The average of these is 1. Add that + * to the one squaring we have to do to compute the table, + * and you'll see that a k-bit window saves k-2 squarings + * as well as reducing the multiplies. (It actually doesn't + * hurt in the case k = 1, either.) + * + * n must have mlen words allocated. Although fewer may be in use + * when n is passed in, all are in use on exit. + */ +int +lbnExpMod_16(BNWORD16 *result, BNWORD16 const *n, unsigned nlen, + BNWORD16 const *e, unsigned elen, BNWORD16 *mod, unsigned mlen) +{ + BNWORD16 *table[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n */ + unsigned ebits; /* Exponent bits */ + unsigned wbits; /* Window size */ + unsigned tblmask; /* Mask of exponentiation window */ + BNWORD16 bitpos; /* Mask of current look-ahead bit */ + unsigned buf; /* Buffer of exponent bits */ + unsigned multpos; /* Where to do pending multiply */ + BNWORD16 const *mult; /* What to multiply by */ + unsigned i; /* Loop counter */ + int isone; /* Flag: accum. is implicitly one */ + BNWORD16 *a, *b; /* Working buffers/accumulators */ + BNWORD16 *t; /* Pointer into the working buffers */ + BNWORD16 inv; /* mod^-1 modulo 2^16 */ + + assert(mlen); + assert(nlen <= mlen); + + /* First, a couple of trivial cases. */ + elen = lbnNorm_16(e, elen); + if (!elen) { + /* x ^ 0 == 1 */ + lbnZero_16(result, mlen); + BIGLITTLE(result[-1],result[0]) = 1; + return 0; + } + ebits = lbnBits_16(e, elen); + if (ebits == 1) { + /* x ^ 1 == x */ + if (n != result) + lbnCopy_16(result, n, nlen); + if (mlen > nlen) + lbnZero_16(BIGLITTLE(result-nlen,result+nlen), + mlen-nlen); + return 0; + } + + /* Okay, now move the exponent pointer to the most-significant word */ + e = BIGLITTLE(e-elen, e+elen-1); + + /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ + wbits = 0; + while (ebits > bnExpModThreshTable[wbits]) + wbits++; + + /* Allocate working storage: two product buffers and the tables. */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ + tblmask = 1u << wbits; + + /* We have the result buffer available, so use it. */ + table[0] = result; + + /* + * Okay, we now have a minimal-sized table - expand it. + * This is allowed to fail! If so, scale back the table size + * and proceed. + */ + for (i = 1; i < tblmask; i++) { + LBNALLOC(t, mlen); + if (!t) /* Out of memory! Quit the loop. */ + break; + table[i] = t; + } + + /* If we stopped, with i < tblmask, shrink the tables appropriately */ + while (tblmask > i) { + wbits--; + tblmask >>= 1; + } + /* Free up our overallocations */ + while (--i > tblmask) + LBNFREE(table[i], mlen); + + /* Okay, fill in the table */ + + /* Compute the necessary modular inverse */ + inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ + + /* Convert n to Montgomery form */ + + /* Move n up "mlen" words into a */ + t = BIGLITTLE(a-mlen, a+mlen); + lbnCopy_16(t, n, nlen); + lbnZero_16(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_16(t, a, mlen+nlen, mod, mlen); + /* Copy into first table entry */ + lbnCopy_16(table[0], a, mlen); + + /* Square a into b */ + lbnMontSquare_16(b, a, mod, mlen, inv); + + /* Use high half of b to initialize the table */ + t = BIGLITTLE(b-mlen, b+mlen); + for (i = 1; i < tblmask; i++) { + lbnMontMul_16(a, t, table[i-1], mod, mlen, inv); + lbnCopy_16(table[i], BIGLITTLE(a-mlen, a+mlen), mlen); + } + + /* We might use b = n^2 later... */ + + /* Initialze the fetch pointer */ + bitpos = (BNWORD16)1 << ((ebits-1) & (16-1)); /* Initialize mask */ + + /* This should point to the msbit of e */ + assert((*e & bitpos) != 0); + + /* + * Pre-load the window. Becuase the window size is + * never larger than the exponent size, there is no need to + * detect running off the end of e in here. + * + * The read-ahead is controlled by elen and the bitpos mask. + * Note that this is *ahead* of ebits, which tracks the + * most significant end of the window. The purpose of this + * initialization is to get the two wbits+1 bits apart, + * like they should be. + * + * Note that bitpos and e1len together keep track of the + * lookahead read pointer in the exponent that is used here. + */ + buf = 0; + for (i = 0; i <= wbits; i++) { + buf = (buf << 1) | ((*e & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e++,e--); + bitpos = (BNWORD16)1 << (16-1); + elen--; + } + } + assert(buf & tblmask); + + /* + * Set the pending multiply positions to a location that will + * never be encountered, thus ensuring that nothing will happen + * until the need for a multiply appears and one is scheduled. + */ + multpos = ebits; /* A NULL value */ + mult = 0; /* Force a crash if we use these */ + + /* + * Okay, now begins the real work. The first step is + * slightly magic, so it's done outside the main loop, + * but it's very similar to what's inside. + */ + ebits--; /* Start processing the first bit... */ + isone = 1; + + /* + * This is just like the multiply in the loop, except that + * - We know the msbit of buf is set, and + * - We have the extra value n^2 floating around. + * So, do the usual computation, and if the result is that + * the buffer should be multiplied by n^1 immediately + * (which we'd normally then square), we multiply it + * (which reduces to a copy, which reduces to setting a flag) + * by n^2 and skip the squaring. Thus, we do the + * multiply and the squaring in one step. + */ + assert(buf & tblmask); + multpos = ebits - wbits; + while ((buf & 1) == 0) { + buf >>= 1; + multpos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(multpos <= ebits); + mult = table[buf>>1]; + buf = 0; + + /* Special case: use already-computed value sitting in buffer */ + if (multpos == ebits) + isone = 0; + + /* + * At this point, the buffer (which is the high half of b) holds + * either 1 (implicitly, as the "isone" flag is set), or n^2. + */ + + /* + * The main loop. The procedure is: + * - Advance the window + * - If the most-significant bit of the window is set, + * schedule a multiply for the appropriate time in the + * future (may be immediately) + * - Perform any pending multiples + * - Check for termination + * - Square the buffer + * + * At any given time, the acumulated product is held in + * the high half of b. + */ + for (;;) { + ebits--; + + /* Advance the window */ + assert(buf < tblmask); + buf <<= 1; + /* + * This reads ahead of the current exponent position + * (controlled by ebits), so we have to be able to read + * past the lsb of the exponents without error. + */ + if (elen) { + buf |= ((*e & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e++,e--); + bitpos = (BNWORD16)1 << (16-1); + elen--; + } + } + + /* Examine the window for pending multiplies */ + if (buf & tblmask) { + multpos = ebits - wbits; + while ((buf & 1) == 0) { + buf >>= 1; + multpos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(multpos <= ebits); + mult = table[buf>>1]; + buf = 0; + } + + /* If we have a pending multiply, do it */ + if (ebits == multpos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_16(t, mult, mlen); + isone = 0; + } else { + lbnMontMul_16(a, t, mult, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* Are we done? */ + if (!ebits) + break; + + /* Square the input */ + if (!isone) { + t = BIGLITTLE(b-mlen, b+mlen); + lbnMontSquare_16(a, t, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } /* for (;;) */ + + assert(!isone); + assert(!buf); + + /* DONE! */ + + /* Convert result out of Montgomery form */ + t = BIGLITTLE(b-mlen, b+mlen); + lbnCopy_16(b, t, mlen); + lbnZero_16(t, mlen); + lbnMontReduce_16(b, mod, mlen, inv); + lbnCopy_16(result, t, mlen); + /* + * Clean up - free intermediate storage. + * Do NOT free table[0], which is the result + * buffer. + */ + while (--tblmask) + LBNFREE(table[tblmask], mlen); + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + +/* + * Compute and return n1^e1 * n2^e2 mod "mod". + * result may be either input buffer, or something separate. + * It must be "mlen" words long. + * + * There is a current position in the exponents, which is kept in e1bits. + * (The exponents are swapped if necessary so e1 is the longer of the two.) + * At any given time, the value in the accumulator is + * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod". + * As e1bits is counted down, this is updated, by squaring it and doing + * any necessary multiplies. + * To decide on the necessary multiplies, two windows, each w1bits+1 bits + * wide, are maintained in buf1 and buf2, which read *ahead* of the + * e1bits position (with appropriate handling of the case when e1bits + * drops below w1bits+1). When the most-significant bit of either window + * becomes set, indicating that something needs to be multiplied by + * the accumulator or it will get out of sync, the window is examined + * to see which power of n1 or n2 to multiply by, and when (possibly + * later, if the power is greater than 1) the multiply should take + * place. Then the multiply and its location are remembered and the + * window is cleared. + * + * If we had every power of n1 in the table, the multiply would always + * be w1bits steps in the future. But we only keep the odd powers, + * so instead of waiting w1bits squarings and then multiplying + * by n1^k, we wait w1bits-k squarings and multiply by n1. + * + * Actually, w2bits can be less than w1bits, but the window is the same + * size, to make it easier to keep track of where we're reading. The + * appropriate number of low-order bits of the window are just ignored. + */ +int +lbnDoubleExpMod_16(BNWORD16 *result, + BNWORD16 const *n1, unsigned n1len, + BNWORD16 const *e1, unsigned e1len, + BNWORD16 const *n2, unsigned n2len, + BNWORD16 const *e2, unsigned e2len, + BNWORD16 *mod, unsigned mlen) +{ + BNWORD16 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n1 */ + BNWORD16 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n2 */ + unsigned e1bits, e2bits; /* Exponent bits */ + unsigned w1bits, w2bits; /* Window sizes */ + unsigned tblmask; /* Mask of exponentiation window */ + BNWORD16 bitpos; /* Mask of current look-ahead bit */ + unsigned buf1, buf2; /* Buffer of exponent bits */ + unsigned mult1pos, mult2pos; /* Where to do pending multiply */ + BNWORD16 const *mult1, *mult2; /* What to multiply by */ + unsigned i; /* Loop counter */ + int isone; /* Flag: accum. is implicitly one */ + BNWORD16 *a, *b; /* Working buffers/accumulators */ + const BNWORD16 *ct; /* Temp pointer */ + BNWORD16 *t; /* Pointer into the working buffers */ + BNWORD16 inv; /* mod^-1 modulo 2^16 */ + + assert(mlen); + assert(n1len <= mlen); + assert(n2len <= mlen); + + /* First, a couple of trivial cases. */ + e1len = lbnNorm_16(e1, e1len); + e2len = lbnNorm_16(e2, e2len); + + /* Ensure that the first exponent is the longer */ + e1bits = lbnBits_16(e1, e1len); + e2bits = lbnBits_16(e2, e2len); + if (e1bits < e2bits) { + i = e1len; e1len = e2len; e2len = i; + i = e1bits; e1bits = e2bits; e2bits = i; + ct = (const BNWORD16 *)n1; n1 = n2; n2 = ct; + ct = (const BNWORD16 *)e1; e1 = e2; e2 = ct; + } + assert(e1bits >= e2bits); + + /* Handle a trivial case */ + if (!e2len) + return lbnExpMod_16(result, n1, n1len, e1, e1len, mod, mlen); + assert(e2bits); + + /* The code below breaks if the exponents aren't at least 2 bits */ + if (e1bits == 1) { + assert(e2bits == 1); + + LBNALLOC(a, n1len+n2len); + if (!a) + return -1; + + lbnMul_16(a, n1, n1len, n2, n2len); + /* Do a direct modular reduction */ + if (n1len + n2len >= mlen) + (void)lbnDiv_16(a+mlen, a, n1len+n2len, mod, mlen); + lbnCopy_16(result, a, mlen); + LBNFREE(a, n1len+n2len); + return 0; + } + + /* Okay, now move the exponent pointers to the most-significant word */ + e1 = BIGLITTLE(e1-e1len, e1+e1len-1); + e2 = BIGLITTLE(e2-e2len, e2+e2len-1); + + /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ + w1bits = 0; + while (e1bits > bnExpModThreshTable[w1bits]) + w1bits++; + w2bits = 0; + while (e2bits > bnExpModThreshTable[w2bits]) + w2bits++; + + assert(w1bits >= w2bits); + + /* Allocate working storage: two product buffers and the tables. */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ + tblmask = 1u << w1bits; + /* Use buf2 for its size, temporarily */ + buf2 = 1u << w2bits; + + LBNALLOC(t, mlen); + if (!t) { + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + return -1; + } + table1[0] = t; + table2[0] = result; + + /* + * Okay, we now have some minimal-sized tables - expand them. + * This is allowed to fail! If so, scale back the table sizes + * and proceed. We allocate both tables at the same time + * so if it fails partway through, they'll both be a reasonable + * size rather than one huge and one tiny. + * When i passes buf2 (the number of entries in the e2 window, + * which may be less than the number of entries in the e1 window), + * stop allocating e2 space. + */ + for (i = 1; i < tblmask; i++) { + LBNALLOC(t, mlen); + if (!t) /* Out of memory! Quit the loop. */ + break; + table1[i] = t; + if (i < buf2) { + LBNALLOC(t, mlen); + if (!t) { + LBNFREE(table1[i], mlen); + break; + } + table2[i] = t; + } + } + + /* If we stopped, with i < tblmask, shrink the tables appropriately */ + while (tblmask > i) { + w1bits--; + tblmask >>= 1; + } + /* Free up our overallocations */ + while (--i > tblmask) { + if (i < buf2) + LBNFREE(table2[i], mlen); + LBNFREE(table1[i], mlen); + } + /* And shrink the second window too, if needed */ + if (w2bits > w1bits) { + w2bits = w1bits; + buf2 = tblmask; + } + + /* + * From now on, use the w2bits variable for the difference + * between w1bits and w2bits. + */ + w2bits = w1bits-w2bits; + + /* Okay, fill in the tables */ + + /* Compute the necessary modular inverse */ + inv = lbnMontInv1_16(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ + + /* Convert n1 to Montgomery form */ + + /* Move n1 up "mlen" words into a */ + t = BIGLITTLE(a-mlen, a+mlen); + lbnCopy_16(t, n1, n1len); + lbnZero_16(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_16(t, a, mlen+n1len, mod, mlen); + /* Copy into first table entry */ + lbnCopy_16(table1[0], a, mlen); + + /* Square a into b */ + lbnMontSquare_16(b, a, mod, mlen, inv); + + /* Use high half of b to initialize the first table */ + t = BIGLITTLE(b-mlen, b+mlen); + for (i = 1; i < tblmask; i++) { + lbnMontMul_16(a, t, table1[i-1], mod, mlen, inv); + lbnCopy_16(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen); + } + + /* Convert n2 to Montgomery form */ + + t = BIGLITTLE(a-mlen, a+mlen); + /* Move n2 up "mlen" words into a */ + lbnCopy_16(t, n2, n2len); + lbnZero_16(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_16(t, a, mlen+n2len, mod, mlen); + /* Copy into first table entry */ + lbnCopy_16(table2[0], a, mlen); + + /* Square it into a */ + lbnMontSquare_16(a, table2[0], mod, mlen, inv); + /* Copy to b, low half */ + lbnCopy_16(b, t, mlen); + + /* Use b to initialize the second table */ + for (i = 1; i < buf2; i++) { + lbnMontMul_16(a, b, table2[i-1], mod, mlen, inv); + lbnCopy_16(table2[i], t, mlen); + } + + /* + * Okay, a recap: at this point, the low part of b holds + * n2^2, the high part holds n1^2, and the tables are + * initialized with the odd powers of n1 and n2 from 1 + * through 2*tblmask-1 and 2*buf2-1. + * + * We might use those squares in b later, or we might not. + */ + + /* Initialze the fetch pointer */ + bitpos = (BNWORD16)1 << ((e1bits-1) & (16-1)); /* Initialize mask */ + + /* This should point to the msbit of e1 */ + assert((*e1 & bitpos) != 0); + + /* + * Pre-load the windows. Becuase the window size is + * never larger than the exponent size, there is no need to + * detect running off the end of e1 in here. + * + * The read-ahead is controlled by e1len and the bitpos mask. + * Note that this is *ahead* of e1bits, which tracks the + * most significant end of the window. The purpose of this + * initialization is to get the two w1bits+1 bits apart, + * like they should be. + * + * Note that bitpos and e1len together keep track of the + * lookahead read pointer in the exponent that is used here. + * e2len is not decremented, it is only ever compared with + * e1len as *that* is decremented. + */ + buf1 = buf2 = 0; + for (i = 0; i <= w1bits; i++) { + buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0); + if (e1len <= e2len) + buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e1++,e1--); + if (e1len <= e2len) + BIGLITTLE(e2++,e2--); + bitpos = (BNWORD16)1 << (16-1); + e1len--; + } + } + assert(buf1 & tblmask); + + /* + * Set the pending multiply positions to a location that will + * never be encountered, thus ensuring that nothing will happen + * until the need for a multiply appears and one is scheduled. + */ + mult1pos = mult2pos = e1bits; /* A NULL value */ + mult1 = mult2 = 0; /* Force a crash if we use these */ + + /* + * Okay, now begins the real work. The first step is + * slightly magic, so it's done outside the main loop, + * but it's very similar to what's inside. + */ + isone = 1; /* Buffer is implicitly 1, so replace * by copy */ + e1bits--; /* Start processing the first bit... */ + + /* + * This is just like the multiply in the loop, except that + * - We know the msbit of buf1 is set, and + * - We have the extra value n1^2 floating around. + * So, do the usual computation, and if the result is that + * the buffer should be multiplied by n1^1 immediately + * (which we'd normally then square), we multiply it + * (which reduces to a copy, which reduces to setting a flag) + * by n1^2 and skip the squaring. Thus, we do the + * multiply and the squaring in one step. + */ + assert(buf1 & tblmask); + mult1pos = e1bits - w1bits; + while ((buf1 & 1) == 0) { + buf1 >>= 1; + mult1pos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(mult1pos <= e1bits); + mult1 = table1[buf1>>1]; + buf1 = 0; + + /* Special case: use already-computed value sitting in buffer */ + if (mult1pos == e1bits) + isone = 0; + + /* + * The first multiply by a power of n2. Similar, but + * we might not even want to schedule a multiply if e2 is + * shorter than e1, and the window might be shorter so + * we have to leave the low w2bits bits alone. + */ + if (buf2 & tblmask) { + /* Remember low-order bits for later */ + i = buf2 & ((1u << w2bits) - 1); + buf2 >>= w2bits; + mult2pos = e1bits - w1bits + w2bits; + while ((buf2 & 1) == 0) { + buf2 >>= 1; + mult2pos++; + } + assert(mult2pos <= e1bits); + mult2 = table2[buf2>>1]; + buf2 = i; + + if (mult2pos == e1bits) { + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + lbnCopy_16(t, b, mlen); /* Copy low to high */ + isone = 0; + } else { + lbnMontMul_16(a, t, b, mod, mlen, inv); + t = a; a = b; b = t; + } + } + } + + /* + * At this point, the buffer (which is the high half of b) + * holds either 1 (implicitly, as the "isone" flag is set), + * n1^2, n2^2 or n1^2 * n2^2. + */ + + /* + * The main loop. The procedure is: + * - Advance the windows + * - If the most-significant bit of a window is set, + * schedule a multiply for the appropriate time in the + * future (may be immediately) + * - Perform any pending multiples + * - Check for termination + * - Square the buffers + * + * At any given time, the acumulated product is held in + * the high half of b. + */ + for (;;) { + e1bits--; + + /* Advance the windows */ + assert(buf1 < tblmask); + buf1 <<= 1; + assert(buf2 < tblmask); + buf2 <<= 1; + /* + * This reads ahead of the current exponent position + * (controlled by e1bits), so we have to be able to read + * past the lsb of the exponents without error. + */ + if (e1len) { + buf1 |= ((*e1 & bitpos) != 0); + if (e1len <= e2len) + buf2 |= ((*e2 & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e1++,e1--); + if (e1len <= e2len) + BIGLITTLE(e2++,e2--); + bitpos = (BNWORD16)1 << (16-1); + e1len--; + } + } + + /* Examine the first window for pending multiplies */ + if (buf1 & tblmask) { + mult1pos = e1bits - w1bits; + while ((buf1 & 1) == 0) { + buf1 >>= 1; + mult1pos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(mult1pos <= e1bits); + mult1 = table1[buf1>>1]; + buf1 = 0; + } + + /* + * Examine the second window for pending multiplies. + * Window 2 can be smaller than window 1, but we + * keep the same number of bits in buf2, so we need + * to ignore any low-order bits in the buffer when + * computing what to multiply by, and recompute them + * later. + */ + if (buf2 & tblmask) { + /* Remember low-order bits for later */ + i = buf2 & ((1u << w2bits) - 1); + buf2 >>= w2bits; + mult2pos = e1bits - w1bits + w2bits; + while ((buf2 & 1) == 0) { + buf2 >>= 1; + mult2pos++; + } + assert(mult2pos <= e1bits); + mult2 = table2[buf2>>1]; + buf2 = i; + } + + + /* If we have a pending multiply for e1, do it */ + if (e1bits == mult1pos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_16(t, mult1, mlen); + isone = 0; + } else { + lbnMontMul_16(a, t, mult1, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* If we have a pending multiply for e2, do it */ + if (e1bits == mult2pos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_16(t, mult2, mlen); + isone = 0; + } else { + lbnMontMul_16(a, t, mult2, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* Are we done? */ + if (!e1bits) + break; + + /* Square the buffer */ + if (!isone) { + t = BIGLITTLE(b-mlen, b+mlen); + lbnMontSquare_16(a, t, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } /* for (;;) */ + + assert(!isone); + assert(!buf1); + assert(!buf2); + + /* DONE! */ + + /* Convert result out of Montgomery form */ + t = BIGLITTLE(b-mlen, b+mlen); + lbnCopy_16(b, t, mlen); + lbnZero_16(t, mlen); + lbnMontReduce_16(b, mod, mlen, inv); + lbnCopy_16(result, t, mlen); + + /* Clean up - free intermediate storage */ + buf2 = tblmask >> w2bits; + while (--tblmask) { + if (tblmask < buf2) + LBNFREE(table2[tblmask], mlen); + LBNFREE(table1[tblmask], mlen); + } + t = table1[0]; + LBNFREE(t, mlen); + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + +/* + * 2^exp (mod mod). This is an optimized version for use in Fermat + * tests. The input value of n is ignored; it is returned with + * "mlen" words valid. + */ +int +lbnTwoExpMod_16(BNWORD16 *n, BNWORD16 const *exp, unsigned elen, + BNWORD16 *mod, unsigned mlen) +{ + unsigned e; /* Copy of high words of the exponent */ + unsigned bits; /* Assorted counter of bits */ + BNWORD16 const *bitptr; + BNWORD16 bitword, bitpos; + BNWORD16 *a, *b, *a1; + BNWORD16 inv; + + assert(mlen); + + bitptr = BIGLITTLE(exp-elen, exp+elen-1); + bitword = *bitptr; + assert(bitword); + + /* Clear n for future use. */ + lbnZero_16(n, mlen); + + bits = lbnBits_16(exp, elen); + + /* First, a couple of trivial cases. */ + if (bits <= 1) { + /* 2 ^ 0 == 1, 2 ^ 1 == 2 */ + BIGLITTLE(n[-1],n[0]) = (BNWORD16)1<<elen; + return 0; + } + + /* Set bitpos to the most significant bit */ + bitpos = (BNWORD16)1 << ((bits-1) & (16-1)); + + /* Now, count the bits in the modulus. */ + bits = lbnBits_16(mod, mlen); + assert(bits > 1); /* a 1-bit modulus is just stupid... */ + + /* + * We start with 1<<e, where "e" is as many high bits of the + * exponent as we can manage without going over the modulus. + * This first loop finds "e". + */ + e = 1; + while (elen) { + /* Consume the first bit */ + bitpos >>= 1; + if (!bitpos) { + if (!--elen) + break; + bitword = BIGLITTLE(*++bitptr,*--bitptr); + bitpos = (BNWORD16)1<<(16-1); + } + e = (e << 1) | ((bitpos & bitword) != 0); + if (e >= bits) { /* Overflow! Back out. */ + e >>= 1; + break; + } + } + /* + * The bit in "bitpos" being examined by the bit buffer has NOT + * been consumed yet. This may be past the end of the exponent, + * in which case elen == 1. + */ + + /* Okay, now, set bit "e" in n. n is already zero. */ + inv = (BNWORD16)1 << (e & (16-1)); + e /= 16; + BIGLITTLE(n[-e-1],n[e]) = inv; + /* + * The effective length of n in words is now "e+1". + * This is used a little bit later. + */ + + if (!elen) + return 0; /* That was easy! */ + + /* + * We have now processed the first few bits. The next step + * is to convert this to Montgomery form for further squaring. + */ + + /* Allocate working storage: two product buffers */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert n to Montgomery form */ + inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ + assert(inv & 1); /* Modulus must be odd */ + inv = lbnMontInv1_16(inv); + /* Move n (length e+1, remember?) up "mlen" words into b */ + /* Note that we lie about a1 for a bit - it's pointing to b */ + a1 = BIGLITTLE(b-mlen,b+mlen); + lbnCopy_16(a1, n, e+1); + lbnZero_16(b, mlen); + /* Do the division - dump the quotient into the high-order words */ + (void)lbnDiv_16(a1, b, mlen+e+1, mod, mlen); + /* + * Now do the first squaring and modular reduction to put + * the number up in a1 where it belongs. + */ + lbnMontSquare_16(a, b, mod, mlen, inv); + /* Fix up a1 to point to where it should go. */ + a1 = BIGLITTLE(a-mlen,a+mlen); + + /* + * Okay, now, a1 holds the number being accumulated, and + * b is a scratch register. Start working: + */ + for (;;) { + /* + * Is the bit set? If so, double a1 as well. + * A modular doubling like this is very cheap. + */ + if (bitpos & bitword) { + /* + * Double the number. If there was a carry out OR + * the result is greater than the modulus, subract + * the modulus. + */ + if (lbnDouble_16(a1, mlen) || + lbnCmp_16(a1, mod, mlen) > 0) + (void)lbnSubN_16(a1, mod, mlen); + } + + /* Advance to the next exponent bit */ + bitpos >>= 1; + if (!bitpos) { + if (!--elen) + break; /* Done! */ + bitword = BIGLITTLE(*++bitptr,*--bitptr); + bitpos = (BNWORD16)1<<(16-1); + } + + /* + * The elen/bitword/bitpos bit buffer is known to be + * non-empty, i.e. there is at least one more unconsumed bit. + * Thus, it's safe to square the number. + */ + lbnMontSquare_16(b, a1, mod, mlen, inv); + /* Rename result (in b) back to a (a1, really). */ + a1 = b; b = a; a = a1; + a1 = BIGLITTLE(a-mlen,a+mlen); + } + + /* DONE! Just a little bit of cleanup... */ + + /* + * Convert result out of Montgomery form... this is + * just a Montgomery reduction. + */ + lbnCopy_16(a, a1, mlen); + lbnZero_16(a1, mlen); + lbnMontReduce_16(a, mod, mlen, inv); + lbnCopy_16(n, a1, mlen); + + /* Clean up - free intermediate storage */ + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + + +/* + * Returns a substring of the big-endian array of bytes representation + * of the bignum array based on two parameters, the least significant + * byte number (0 to start with the least significant byte) and the + * length. I.e. the number returned is a representation of + * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). + * + * It is an error if the bignum is not at least buflen + lsbyte bytes + * long. + * + * This code assumes that the compiler has the minimal intelligence + * neded to optimize divides and modulo operations on an unsigned data + * type with a power of two. + */ +void +lbnExtractBigBytes_16(BNWORD16 const *n, unsigned char *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD16 t = 0; /* Needed to shut up uninitialized var warnings */ + unsigned shift; + + lsbyte += buflen; + + shift = (8 * lsbyte) % 16; + lsbyte /= (16/8); /* Convert to word offset */ + BIGLITTLE(n -= lsbyte, n += lsbyte); + + if (shift) + t = BIGLITTLE(n[-1],n[0]); + + while (buflen--) { + if (!shift) { + t = BIGLITTLE(*n++,*--n); + shift = 16; + } + shift -= 8; + *buf++ = (unsigned char)(t>>shift); + } +} + +/* + * Merge a big-endian array of bytes into a bignum array. + * The array had better be big enough. This is + * equivalent to extracting the entire bignum into a + * large byte array, copying the input buffer into the + * middle of it, and converting back to a bignum. + * + * The buf is "len" bytes long, and its *last* byte is at + * position "lsbyte" from the end of the bignum. + * + * Note that this is a pain to get right. Fortunately, it's hardly + * critical for efficiency. + */ +void +lbnInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD16 t = 0; /* Shut up uninitialized varibale warnings */ + + lsbyte += buflen; + + BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); + + /* Load up leading odd bytes */ + if (lsbyte % (16/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte * 8) % 16; + } + + /* The main loop - merge into t, storing at each word boundary. */ + while (buflen--) { + t = (t << 8) | *buf++; + if ((--lsbyte % (16/8)) == 0) + BIGLITTLE(*n++,*--n) = t; + } + + /* Merge odd bytes in t into last word */ + lsbyte = (lsbyte * 8) % 16; + if (lsbyte) { + t <<= lsbyte; + t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); + BIGLITTLE(n[0],n[-1]) = t; + } + + return; +} + +/* + * Returns a substring of the little-endian array of bytes representation + * of the bignum array based on two parameters, the least significant + * byte number (0 to start with the least significant byte) and the + * length. I.e. the number returned is a representation of + * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). + * + * It is an error if the bignum is not at least buflen + lsbyte bytes + * long. + * + * This code assumes that the compiler has the minimal intelligence + * neded to optimize divides and modulo operations on an unsigned data + * type with a power of two. + */ +void +lbnExtractLittleBytes_16(BNWORD16 const *n, unsigned char *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD16 t = 0; /* Needed to shut up uninitialized var warnings */ + + BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); + + if (lsbyte % (16/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte % (16/8)) * 8 ; + } + + while (buflen--) { + if ((lsbyte++ % (16/8)) == 0) + t = BIGLITTLE(*--n,*n++); + *buf++ = (unsigned char)t; + t >>= 8; + } +} + +/* + * Merge a little-endian array of bytes into a bignum array. + * The array had better be big enough. This is + * equivalent to extracting the entire bignum into a + * large byte array, copying the input buffer into the + * middle of it, and converting back to a bignum. + * + * The buf is "len" bytes long, and its first byte is at + * position "lsbyte" from the end of the bignum. + * + * Note that this is a pain to get right. Fortunately, it's hardly + * critical for efficiency. + */ +void +lbnInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD16 t = 0; /* Shut up uninitialized varibale warnings */ + + /* Move to most-significant end */ + lsbyte += buflen; + buf += buflen; + + BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8)); + + /* Load up leading odd bytes */ + if (lsbyte % (16/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte * 8) % 16; + } + + /* The main loop - merge into t, storing at each word boundary. */ + while (buflen--) { + t = (t << 8) | *--buf; + if ((--lsbyte % (16/8)) == 0) + BIGLITTLE(*n++,*--n) = t; + } + + /* Merge odd bytes in t into last word */ + lsbyte = (lsbyte * 8) % 16; + if (lsbyte) { + t <<= lsbyte; + t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); + BIGLITTLE(n[0],n[-1]) = t; + } + + return; +} + +#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */ +/* + * Convert a big-endian array of bytes to a bignum. + * Returns the number of words in the bignum. + * Note the expression "16/8" for the number of bytes per word. + * This is so the word-size adjustment will work. + */ +unsigned +lbnFromBytes_16(BNWORD16 *a, unsigned char const *b, unsigned blen) +{ + BNWORD16 t; + unsigned alen = (blen + (16/8-1))/(16/8); + BIGLITTLE(a -= alen, a += alen); + + while (blen) { + t = 0; + do { + t = t << 8 | *b++; + } while (--blen & (16/8-1)); + BIGLITTLE(*a++,*--a) = t; + } + return alen; +} +#endif + +/* + * Computes the GCD of a and b. Modifies both arguments; + * when it returns, one of them is the GCD and the other is trash. + * The return value is the length of the GCD, with the sign telling + * whether it is in a (+ve) or b (-ve). Both inputs must have + * one extra word of precision. alen must be >= blen. + * + * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B). + * This is based on taking out common powers of 2, then repeatedly: + * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted. + * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced. + * It gets less reduction per step, but the steps are much faster than + * the division case. + */ +int +lbnGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen) +{ + assert(alen >= blen); + + while (blen != 0) { + (void)lbnDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); + alen = lbnNorm_16(a, blen); + if (alen == 0) + return -(int)blen; + (void)lbnDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); + blen = lbnNorm_16(b, alen); + } + return alen; +} + +/* + * Invert "a" modulo "mod" using the extended Euclidean algorithm. + * Note that this only computes one of the cosequences, and uses the + * theorem that the signs flip every step and the absolute value of + * the cosequence values are always bounded by the modulus to avoid + * having to work with negative numbers. + * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1. + * a must be one word longer than "mod". It is overwritten with the + * result. + * TODO: Use Richard Schroeppel's *much* faster algorithm. + */ +int +lbnInv_16(BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen) +{ + BNWORD16 *b; /* Hold a copy of mod during GCD reduction */ + BNWORD16 *p; /* Temporary for products added to t0 and t1 */ + BNWORD16 *t0, *t1; /* Inverse accumulators */ + BNWORD16 cy; + unsigned blen, t0len, t1len, plen; + + alen = lbnNorm_16(a, alen); + if (!alen) + return 1; /* No inverse */ + + mlen = lbnNorm_16(mod, mlen); + + assert (alen <= mlen); + + /* Inverse of 1 is 1 */ + if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) { + lbnZero_16(BIGLITTLE(a-alen,a+alen), mlen-alen); + return 0; + } + + /* Allocate a pile of space */ + LBNALLOC(b, mlen+1); + if (b) { + /* + * Although products are guaranteed to always be less than the + * modulus, it can involve multiplying two 3-word numbers to + * get a 5-word result, requiring a 6th word to store a 0 + * temporarily. Thus, mlen + 1. + */ + LBNALLOC(p, mlen+1); + if (p) { + LBNALLOC(t0, mlen); + if (t0) { + LBNALLOC(t1, mlen); + if (t1) + goto allocated; + LBNFREE(t0, mlen); + } + LBNFREE(p, mlen+1); + } + LBNFREE(b, mlen+1); + } + return -1; + +allocated: + + /* Set t0 to 1 */ + t0len = 1; + BIGLITTLE(t0[-1],t0[0]) = 1; + + /* b = mod */ + lbnCopy_16(b, mod, mlen); + /* blen = mlen (implicitly) */ + + /* t1 = b / a; b = b % a */ + cy = lbnDiv_16(t1, b, mlen, a, alen); + *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy; + t1len = lbnNorm_16(t1, mlen-alen+1); + blen = lbnNorm_16(b, alen); + + /* while (b > 1) */ + while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD16)1) { + /* q = a / b; a = a % b; */ + if (alen < blen || (alen == blen && lbnCmp_16(a, a, alen) < 0)) + assert(0); + cy = lbnDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); + *(BIGLITTLE(a-alen-1,a+alen)) = cy; + plen = lbnNorm_16(BIGLITTLE(a-blen,a+blen), alen-blen+1); + assert(plen); + alen = lbnNorm_16(a, blen); + if (!alen) + goto failure; /* GCD not 1 */ + + /* t0 += q * t1; */ + assert(plen+t1len <= mlen+1); + lbnMul_16(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len); + plen = lbnNorm_16(p, plen + t1len); + assert(plen <= mlen); + if (plen > t0len) { + lbnZero_16(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len); + t0len = plen; + } + cy = lbnAddN_16(t0, p, plen); + if (cy) { + if (t0len > plen) { + cy = lbnAdd1_16(BIGLITTLE(t0-plen,t0+plen), + t0len-plen, cy); + } + if (cy) { + BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy; + t0len++; + } + } + + /* if (a <= 1) return a ? t0 : FAIL; */ + if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD16)1) { + if (alen == 0) + goto failure; /* FAIL */ + assert(t0len <= mlen); + lbnCopy_16(a, t0, t0len); + lbnZero_16(BIGLITTLE(a-t0len, a+t0len), mlen-t0len); + goto success; + } + + /* q = b / a; b = b % a; */ + if (blen < alen || (blen == alen && lbnCmp_16(b, a, alen) < 0)) + assert(0); + cy = lbnDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); + *(BIGLITTLE(b-blen-1,b+blen)) = cy; + plen = lbnNorm_16(BIGLITTLE(b-alen,b+alen), blen-alen+1); + assert(plen); + blen = lbnNorm_16(b, alen); + if (!blen) + goto failure; /* GCD not 1 */ + + /* t1 += q * t0; */ + assert(plen+t0len <= mlen+1); + lbnMul_16(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len); + plen = lbnNorm_16(p, plen + t0len); + assert(plen <= mlen); + if (plen > t1len) { + lbnZero_16(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len); + t1len = plen; + } + cy = lbnAddN_16(t1, p, plen); + if (cy) { + if (t1len > plen) { + cy = lbnAdd1_16(BIGLITTLE(t1-plen,t0+plen), + t1len-plen, cy); + } + if (cy) { + BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy; + t1len++; + } + } + } + + if (!blen) + goto failure; /* gcd(a, mod) != 1 -- FAIL */ + + /* return mod-t1 */ + lbnCopy_16(a, mod, mlen); + assert(t1len <= mlen); + cy = lbnSubN_16(a, t1, t1len); + if (cy) { + assert(mlen > t1len); + cy = lbnSub1_16(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy); + assert(!cy); + } + +success: + LBNFREE(t1, mlen); + LBNFREE(t0, mlen); + LBNFREE(p, mlen+1); + LBNFREE(b, mlen+1); + + return 0; + +failure: + LBNFREE(t1, mlen); + LBNFREE(t0, mlen); + LBNFREE(p, mlen+1); + LBNFREE(b, mlen+1); + + return 1; +} diff --git a/usr/src/lib/libresolv2/common/cylink/lbn16.h b/usr/src/lib/libresolv2/common/cylink/lbn16.h new file mode 100644 index 0000000000..52e156886e --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn16.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef LBN16_H +#define LBN16_H + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "lbn.h" + +#ifndef BNWORD16 +#error 16-bit bignum library requires a 16-bit data type +#endif + +#ifndef lbnCopy_16 +void lbnCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len); +#endif +#ifndef lbnZero_16 +void lbnZero_16(BNWORD16 *num, unsigned len); +#endif +#ifndef lbnNeg_16 +void lbnNeg_16(BNWORD16 *num, unsigned len); +#endif + +#ifndef lbnAdd1_16 +BNWORD16 lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry); +#endif +#ifndef lbnSub1_16 +BNWORD16 lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow); +#endif + +#ifndef lbnAddN_16 +BNWORD16 lbnAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len); +#endif +#ifndef lbnSubN_16 +BNWORD16 lbnSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len); +#endif + +#ifndef lbnCmp_16 +int lbnCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len); +#endif + +#ifndef lbnMulN1_16 +void lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); +#endif +#ifndef lbnMulAdd1_16 +BNWORD16 +lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); +#endif +#ifndef lbnMulSub1_16 +BNWORD16 lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k); +#endif + +#ifndef lbnLshift_16 +BNWORD16 lbnLshift_16(BNWORD16 *num, unsigned len, unsigned shift); +#endif +#ifndef lbnDouble_16 +BNWORD16 lbnDouble_16(BNWORD16 *num, unsigned len); +#endif +#ifndef lbnRshift_16 +BNWORD16 lbnRshift_16(BNWORD16 *num, unsigned len, unsigned shift); +#endif + +#ifndef lbnMul_16 +void lbnMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1, + BNWORD16 const *num2, unsigned len2); +#endif +#ifndef lbnSquare_16 +void lbnSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len); +#endif + +#ifndef lbnNorm_16 +unsigned lbnNorm_16(BNWORD16 const *num, unsigned len); +#endif +#ifndef lbnBits_16 +unsigned lbnBits_16(BNWORD16 const *num, unsigned len); +#endif + +#ifndef lbnExtractBigBytes_16 +void lbnExtractBigBytes_16(BNWORD16 const *bn, unsigned char *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnInsertBigytes_16 +void lbnInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnExtractLittleBytes_16 +void lbnExtractLittleBytes_16(BNWORD16 const *bn, unsigned char *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnInsertLittleBytes_16 +void lbnInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen); +#endif + +#ifndef lbnDiv21_16 +BNWORD16 lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d); +#endif +#ifndef lbnDiv1_16 +BNWORD16 lbnDiv1_16(BNWORD16 *q, BNWORD16 *rem, + BNWORD16 const *n, unsigned len, BNWORD16 d); +#endif +#ifndef lbnModQ_16 +unsigned lbnModQ_16(BNWORD16 const *n, unsigned len, unsigned d); +#endif +#ifndef lbnDiv_16 +BNWORD16 +lbnDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen); +#endif + +#ifndef lbnMontInv1_16 +BNWORD16 lbnMontInv1_16(BNWORD16 const x); +#endif +#ifndef lbnMontReduce_16 +void lbnMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen, + BNWORD16 inv); +#endif +#ifndef lbnToMont_16 +void lbnToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen); +#endif +#ifndef lbnFromMont_16 +void lbnFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len); +#endif + +#ifndef lbnExpMod_16 +int lbnExpMod_16(BNWORD16 *result, BNWORD16 const *n, unsigned nlen, + BNWORD16 const *exp, unsigned elen, BNWORD16 *mod, unsigned mlen); +#endif +#ifndef lbnDoubleExpMod_16 +int lbnDoubleExpMod_16(BNWORD16 *result, + BNWORD16 const *n1, unsigned n1len, BNWORD16 const *e1, unsigned e1len, + BNWORD16 const *n2, unsigned n2len, BNWORD16 const *e2, unsigned e2len, + BNWORD16 *mod, unsigned mlen); +#endif +#ifndef lbnTwoExpMod_16 +int lbnTwoExpMod_16(BNWORD16 *n, BNWORD16 const *exp, unsigned elen, + BNWORD16 *mod, unsigned mlen); +#endif +#ifndef lbnGcd_16 +int lbnGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen); +#endif +#ifndef lbnInv_16 +int lbnInv_16(BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen); +#endif + +#endif /* LBN16_H */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbn32.c b/usr/src/lib/libresolv2/common/cylink/lbn32.c new file mode 100644 index 0000000000..4cdfabf48e --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn32.c @@ -0,0 +1,3650 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn32.c - Low-level bignum routines, 32-bit version. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * NOTE: the magic constants "32" and "64" appear in many places in this + * file, including inside identifiers. Because it is not possible to + * ask "#ifdef" of a macro expansion, it is not possible to use the + * preprocessor to conditionalize these properly. Thus, this file is + * intended to be edited with textual search and replace to produce + * alternate word size versions. Any reference to the number of bits + * in a word must be the string "32", and that string must not appear + * otherwise. Any reference to twice this number must appear as "64", + * which likewise must not appear otherwise. Is that clear? + * + * Remember, when doubling the bit size replace the larger number (64) + * first, then the smaller (32). When halving the bit size, do the + * opposite. Otherwise, things will get wierd. Also, be sure to replace + * every instance that appears. (:%s/foo/bar/g in vi) + * + * These routines work with a pointer to the least-significant end of + * an array of WORD32s. The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros + * defined in lbn.h (which expand to x on a big-edian machine and y on a + * little-endian machine) are used to conditionalize the code to work + * either way. If you have no assembly primitives, it doesn't matter. + * Note that on a big-endian machine, the least-significant-end pointer + * is ONE PAST THE END. The bytes are ptr[-1] through ptr[-len]. + * On little-endian, they are ptr[0] through ptr[len-1]. This makes + * perfect sense if you consider pointers to point *between* bytes rather + * than at them. + * + * Because the array index values are unsigned integers, ptr[-i] + * may not work properly, since the index -i is evaluated as an unsigned, + * and if pointers are wider, zero-extension will produce a positive + * number rahter than the needed negative. The expression used in this + * code, *(ptr-i) will, however, work. (The array syntax is equivalent + * to *(ptr+-i), which is a pretty subtle difference.) + * + * Many of these routines will get very unhappy if fed zero-length inputs. + * They use assert() to enforce this. An higher layer of code must make + * sure that these aren't called with zero-length inputs. + * + * Any of these routines can be replaced with more efficient versions + * elsewhere, by just #defining their names. If one of the names + * is #defined, the C code is not compiled in and no declaration is + * made. Use the BNINCLUDE file to do that. Typically, you compile + * asm subroutines with the same name and just, e.g. + * #define lbnMulAdd1_32 lbnMulAdd1_32 + * + * If you want to write asm routines, start with lbnMulAdd1_32(). + * This is the workhorse of modular exponentiation. lbnMulN1_32() is + * also used a fair bit, although not as much and it's defined in terms + * of lbnMulAdd1_32 if that has a custom version. lbnMulSub1_32 and + * lbnDiv21_32 are used in the usual division and remainder finding. + * (Not the Montgomery reduction used in modular exponentiation, though.) + * Once you have lbnMulAdd1_32 defined, writing the other two should + * be pretty easy. (Just make sure you get the sign of the subtraction + * in lbnMulSub1_32 right - it's dest = dest - source * k.) + * + * The only definitions that absolutely need a double-word (BNWORD64) + * type are lbnMulAdd1_32 and lbnMulSub1_32; if those are provided, + * the rest follows. lbnDiv21_32, however, is a lot slower unless you + * have them, and lbnModQ_32 takes after it. That one is used quite a + * bit for prime sieving. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_ASSERT_H +#define NO_ASSERT_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_ASSERT_H +#include <assert.h> +#else +#define assert(x) (void)0 +#endif + +#if !NO_STRING_H +#include <string.h> /* For memcpy */ +#elif HAVE_STRINGS_H +#include <strings.h> +#endif +#if NEED_MEMORY_H +#include <memory.h> +#endif + +#include "lbn.h" +#include "lbn32.h" +#include "lbnmem.h" +#include "legal.h" + +#include "kludge.h" +#include <port_after.h> + +#ifndef BNWORD32 +#error 32-bit bignum library requires a 32-bit data type +#endif + +/* Make sure the copyright notice gets included */ +volatile const char * volatile const lbnCopyright_32 = bnCopyright; + +/* + * Most of the multiply (and Montgomery reduce) routines use an outer + * loop that iterates over one of the operands - a so-called operand + * scanning approach. One big advantage of this is that the assembly + * support routines are simpler. The loops can be rearranged to have + * an outer loop that iterates over the product, a so-called product + * scanning approach. This has the advantage of writing less data + * and doing fewer adds to memory, so is supposedly faster. Some + * code has been written using a product-scanning approach, but + * it appears to be slower, so it is turned off by default. Some + * experimentation would be appreciated. + * + * (The code is also annoying to get right and not very well commented, + * one of my pet peeves about math libraries. I'm sorry.) + */ +#ifndef PRODUCT_SCAN +#define PRODUCT_SCAN 0 +#endif + +/* + * Copy an array of words. <Marvin mode on> Thrilling, isn't it? </Marvin> + * This is a good example of how the byte offsets and BIGLITTLE() macros work. + * Another alternative would have been + * memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD32)), but I find that + * putting operators into conditional macros is confusing. + */ +#ifndef lbnCopy_32 +void +lbnCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len) +{ + memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src), + len * sizeof(*src)); +} +#endif /* !lbnCopy_32 */ + +/* + * Fill n words with zero. This does it manually rather than calling + * memset because it can assume alignment to make things faster while + * memset can't. Note how big-endian numbers are naturally addressed + * using predecrement, while little-endian is postincrement. + */ +#ifndef lbnZero_32 +void +lbnZero_32(BNWORD32 *num, unsigned len) +{ + while (len--) + BIGLITTLE(*--num,*num++) = 0; +} +#endif /* !lbnZero_32 */ + +/* + * Negate an array of words. + * Negation is subtraction from zero. Negating low-order words + * entails doing nothing until a non-zero word is hit. Once that + * is negated, a borrow is generated and never dies until the end + * of the number is hit. Negation with borrow, -x-1, is the same as ~x. + * Repeat that until the end of the number. + * + * Doesn't return borrow out because that's pretty useless - it's + * always set unless the input is 0, which is easy to notice in + * normalized form. + */ +#ifndef lbnNeg_32 +void +lbnNeg_32(BNWORD32 *num, unsigned len) +{ + assert(len); + + /* Skip low-order zero words */ + while (BIGLITTLE(*--num,*num) == 0) { + if (!--len) + return; + LITTLE(num++;) + } + /* Negate the lowest-order non-zero word */ + *num = -*num; + /* Complement all the higher-order words */ + while (--len) { + BIGLITTLE(--num,++num); + *num = ~*num; + } +} +#endif /* !lbnNeg_32 */ + + +/* + * lbnAdd1_32: add the single-word "carry" to the given number. + * Used for minor increments and propagating the carry after + * adding in a shorter bignum. + * + * Technique: If we have a double-width word, presumably the compiler + * can add using its carry in inline code, so we just use a larger + * accumulator to compute the carry from the first addition. + * If not, it's more complex. After adding the first carry, which may + * be > 1, compare the sum and the carry. If the sum wraps (causing a + * carry out from the addition), the result will be less than each of the + * inputs, since the wrap subtracts a number (2^32) which is larger than + * the other input can possibly be. If the sum is >= the carry input, + * return success immediately. + * In either case, if there is a carry, enter a loop incrementing words + * until one does not wrap. Since we are adding 1 each time, the wrap + * will be to 0 and we can test for equality. + */ +#ifndef lbnAdd1_32 /* If defined, it's provided as an asm subroutine */ +#ifdef BNWORD64 +BNWORD32 +lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry) +{ + BNWORD64 t; + assert(len > 0); /* Alternative: if (!len) return carry */ + + t = (BNWORD64)BIGLITTLE(*--num,*num) + carry; + BIGLITTLE(*num,*num++) = (BNWORD32)t; + if ((t >> 32) == 0) + return 0; + while (--len) { + if (++BIGLITTLE(*--num,*num++) != 0) + return 0; + } + return 1; +} +#else /* no BNWORD64 */ +BNWORD32 +lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry) +{ + assert(len > 0); /* Alternative: if (!len) return carry */ + + if ((BIGLITTLE(*--num,*num++) += carry) >= carry) + return 0; + while (--len) { + if (++BIGLITTLE(*--num,*num++) != 0) + return 0; + } + return 1; +} +#endif +#endif/* !lbnAdd1_32 */ + +/* + * lbnSub1_32: subtract the single-word "borrow" from the given number. + * Used for minor decrements and propagating the borrow after + * subtracting a shorter bignum. + * + * Technique: Similar to the add, above. If there is a double-length type, + * use that to generate the first borrow. + * If not, after subtracting the first borrow, which may be > 1, compare + * the difference and the *negative* of the carry. If the subtract wraps + * (causing a borrow out from the subtraction), the result will be at least + * as large as -borrow. If the result < -borrow, then no borrow out has + * appeared and we may return immediately, except when borrow == 0. To + * deal with that case, use the identity that -x = ~x+1, and instead of + * comparing < -borrow, compare for <= ~borrow. + * Either way, if there is a borrow out, enter a loop decrementing words + * until a non-zero word is reached. + * + * Note the cast of ~borrow to (BNWORD32). If the size of an int is larger + * than BNWORD32, C rules say the number is expanded for the arithmetic, so + * the inversion will be done on an int and the value won't be quite what + * is expected. + */ +#ifndef lbnSub1_32 /* If defined, it's provided as an asm subroutine */ +#ifdef BNWORD64 +BNWORD32 +lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow) +{ + BNWORD64 t; + assert(len > 0); /* Alternative: if (!len) return borrow */ + + t = (BNWORD64)BIGLITTLE(*--num,*num) - borrow; + BIGLITTLE(*num,*num++) = (BNWORD32)t; + if ((t >> 32) == 0) + return 0; + while (--len) { + if ((BIGLITTLE(*--num,*num++))-- != 0) + return 0; + } + return 1; +} +#else /* no BNWORD64 */ +BNWORD32 +lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow) +{ + assert(len > 0); /* Alternative: if (!len) return borrow */ + + if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD32)~borrow) + return 0; + while (--len) { + if ((BIGLITTLE(*--num,*num++))-- != 0) + return 0; + } + return 1; +} +#endif +#endif /* !lbnSub1_32 */ + +/* + * lbnAddN_32: add two bignums of the same length, returning the carry (0 or 1). + * One of the building blocks, along with lbnAdd1, of adding two bignums of + * differing lengths. + * + * Technique: Maintain a word of carry. If there is no double-width type, + * use the same technique as in lbnAdd1, above, to maintain the carry by + * comparing the inputs. Adding the carry sources is used as an OR operator; + * at most one of the two comparisons can possibly be true. The first can + * only be true if carry == 1 and x, the result, is 0. In that case the + * second can't possibly be true. + */ +#ifndef lbnAddN_32 +#ifdef BNWORD64 +BNWORD32 +lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) +{ + BNWORD64 t; + + assert(len > 0); + + t = (BNWORD64)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++); + BIGLITTLE(*num1,*num1++) = (BNWORD32)t; + while (--len) { + t = (BNWORD64)BIGLITTLE(*--num1,*num1) + + (BNWORD64)BIGLITTLE(*--num2,*num2++) + (t >> 32); + BIGLITTLE(*num1,*num1++) = (BNWORD32)t; + } + + return (BNWORD32)(t>>32); +} +#else /* no BNWORD64 */ +BNWORD32 +lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) +{ + BNWORD32 x, carry = 0; + + assert(len > 0); /* Alternative: change loop to test at start */ + + do { + x = BIGLITTLE(*--num2,*num2++); + carry = (x += carry) < carry; + carry += (BIGLITTLE(*--num1,*num1++) += x) < x; + } while (--len); + + return carry; +} +#endif +#endif /* !lbnAddN_32 */ + +/* + * lbnSubN_32: add two bignums of the same length, returning the carry (0 or 1). + * One of the building blocks, along with subn1, of subtracting two bignums of + * differing lengths. + * + * Technique: If no double-width type is availble, maintain a word of borrow. + * First, add the borrow to the subtrahend (did you have to learn all those + * awful words in elementary school, too?), and if it overflows, set the + * borrow again. Then subtract the modified subtrahend from the next word + * of input, using the same technique as in subn1, above. + * Adding the borrows is used as an OR operator; at most one of the two + * comparisons can possibly be true. The first can only be true if + * borrow == 1 and x, the result, is 0. In that case the second can't + * possibly be true. + * + * In the double-word case, (BNWORD32)-(t>>32) is subtracted, rather than + * adding t>>32, because the shift would need to sign-extend and that's + * not guaranteed to happen in ANSI C, even with signed types. + */ +#ifndef lbnSubN_32 +#ifdef BNWORD64 +BNWORD32 +lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) +{ + BNWORD64 t; + + assert(len > 0); + + t = (BNWORD64)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++); + BIGLITTLE(*num1,*num1++) = (BNWORD32)t; + + while (--len) { + t = (BNWORD64)BIGLITTLE(*--num1,*num1) - + (BNWORD64)BIGLITTLE(*--num2,*num2++) - (BNWORD32)-(t >> 32); + BIGLITTLE(*num1,*num1++) = (BNWORD32)t; + } + + return -(BNWORD32)(t>>32); +} +#else +BNWORD32 +lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len) +{ + BNWORD32 x, borrow = 0; + + assert(len > 0); /* Alternative: change loop to test at start */ + + do { + x = BIGLITTLE(*--num2,*num2++); + borrow = (x += borrow) < borrow; + borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD32)~x; + } while (--len); + + return borrow; +} +#endif +#endif /* !lbnSubN_32 */ + +#ifndef lbnCmp_32 +/* + * lbnCmp_32: compare two bignums of equal length, returning the sign of + * num1 - num2. (-1, 0 or +1). + * + * Technique: Change the little-endian pointers to big-endian pointers + * and compare from the most-significant end until a difference if found. + * When it is, figure out the sign of the difference and return it. + */ +int +lbnCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len) +{ + BIGLITTLE(num1 -= len, num1 += len); + BIGLITTLE(num2 -= len, num2 += len); + + while (len--) { + if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) { + if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2)) + return -1; + else + return 1; + } + } + return 0; +} +#endif /* !lbnCmp_32 */ + +/* + * mul32_ppmmaa(ph,pl,x,y,a,b) is an optional routine that + * computes (ph,pl) = x * y + a + b. mul32_ppmma and mul32_ppmm + * are simpler versions. If you want to be lazy, all of these + * can be defined in terms of the others, so here we create any + * that have not been defined in terms of the ones that have been. + */ + +/* Define ones with fewer a's in terms of ones with more a's */ +#if !defined(mul32_ppmma) && defined(mul32_ppmmaa) +#define mul32_ppmma(ph,pl,x,y,a) mul32_ppmmaa(ph,pl,x,y,a,0) +#endif + +#if !defined(mul32_ppmm) && defined(mul32_ppmma) +#define mul32_ppmm(ph,pl,x,y) mul32_ppmma(ph,pl,x,y,0) +#endif + +/* + * Use this definition to test the mul32_ppmm-based operations on machines + * that do not provide mul32_ppmm. Change the final "0" to a "1" to + * enable it. + */ +#if !defined(mul32_ppmm) && defined(BNWORD64) && 0 /* Debugging */ +#define mul32_ppmm(ph,pl,x,y) \ + ({BNWORD64 _ = (BNWORD64)(x)*(y); (pl) = _; (ph) = _>>32;}) +#endif + +#if defined(mul32_ppmm) && !defined(mul32_ppmma) +#define mul32_ppmma(ph,pl,x,y,a) \ + (mul32_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a)) +#endif + +#if defined(mul32_ppmma) && !defined(mul32_ppmmaa) +#define mul32_ppmmaa(ph,pl,x,y,a,b) \ + (mul32_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b)) +#endif + +/* + * lbnMulN1_32: Multiply an n-word input by a 1-word input and store the + * n+1-word product. This uses either the mul32_ppmm and mul32_ppmma + * macros, or C multiplication with the BNWORD64 type. This uses mul32_ppmma + * if available, assuming you won't bother defining it unless you can do + * better than the normal multiplication. + */ +#ifndef lbnMulN1_32 +#ifdef lbnMulAdd1_32 /* If we have this asm primitive, use it. */ +void +lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + lbnZero_32(out, len); + BIGLITTLE(*(out-len),*(out+len)) = lbnMulAdd1_32(out, in, len, k); +} +#elif defined(mul32_ppmm) +void +lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD32 prod, carry, carryin; + + assert(len > 0); + + BIG(--out;--in;); + mul32_ppmm(carry, *out, *in, k); + LITTLE(out++;in++;) + + while (--len) { + BIG(--out;--in;) + carryin = carry; + mul32_ppmma(carry, *out, *in, k, carryin); + LITTLE(out++;in++;) + } + BIGLITTLE(*--out,*out) = carry; +} +#elif defined(BNWORD64) +void +lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD64 p; + + assert(len > 0); + + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k; + BIGLITTLE(*--out,*out++) = (BNWORD32)p; + + while (--len) { + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + (BNWORD32)(p >> 32); + BIGLITTLE(*--out,*out++) = (BNWORD32)p; + } + BIGLITTLE(*--out,*out) = (BNWORD32)(p >> 32); +} +#else +#error No 32x32 -> 64 multiply available for 32-bit bignum package +#endif +#endif /* lbnMulN1_32 */ + +/* + * lbnMulAdd1_32: Multiply an n-word input by a 1-word input and add the + * low n words of the product to the destination. *Returns the n+1st word + * of the product.* (That turns out to be more convenient than adding + * it into the destination and dealing with a possible unit carry out + * of *that*.) This uses either the mul32_ppmma and mul32_ppmmaa macros, + * or C multiplication with the BNWORD64 type. + * + * If you're going to write assembly primitives, this is the one to + * start with. It is by far the most commonly called function. + */ +#ifndef lbnMulAdd1_32 +#if defined(mul32_ppmm) +BNWORD32 +lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD32 prod, carry, carryin; + + assert(len > 0); + + BIG(--out;--in;); + carryin = *out; + mul32_ppmma(carry, *out, *in, k, carryin); + LITTLE(out++;in++;) + + while (--len) { + BIG(--out;--in;); + carryin = carry; + mul32_ppmmaa(carry, prod, *in, k, carryin, *out); + *out = prod; + LITTLE(out++;in++;) + } + + return carry; +} +#elif defined(BNWORD64) +BNWORD32 +lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD64 p; + + assert(len > 0); + + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out); + BIGLITTLE(*out,*out++) = (BNWORD32)p; + + while (--len) { + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + + (BNWORD32)(p >> 32) + BIGLITTLE(*--out,*out); + BIGLITTLE(*out,*out++) = (BNWORD32)p; + } + + return (BNWORD32)(p >> 32); +} +#else +#error No 32x32 -> 64 multiply available for 32-bit bignum package +#endif +#endif /* lbnMulAdd1_32 */ + +/* + * lbnMulSub1_32: Multiply an n-word input by a 1-word input and subtract the + * n-word product from the destination. Returns the n+1st word of the product. + * This uses either the mul32_ppmm and mul32_ppmma macros, or + * C multiplication with the BNWORD64 type. + * + * This is rather uglier than adding, but fortunately it's only used in + * division which is not used too heavily. + */ +#ifndef lbnMulN1_32 +#if defined(mul32_ppmm) +BNWORD32 +lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD32 prod, carry, carryin; + + assert(len > 0); + + BIG(--in;) + mul32_ppmm(carry, prod, *in, k); + LITTLE(in++;) + carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod; + + while (--len) { + BIG(--in;); + carryin = carry; + mul32_ppmma(carry, prod, *in, k, carryin); + LITTLE(in++;) + carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod; + } + + return carry; +} +#elif defined(BNWORD64) +BNWORD32 +lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + BNWORD64 p; + BNWORD32 carry, t; + + assert(len > 0); + + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k; + t = BIGLITTLE(*--out,*out); + carry = (BNWORD32)(p>>32) + ((BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t); + + while (--len) { + p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + carry; + t = BIGLITTLE(*--out,*out); + carry = (BNWORD32)(p>>32) + + ( (BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t ); + } + + return carry; +} +#else +#error No 32x32 -> 64 multiply available for 32-bit bignum package +#endif +#endif /* !lbnMulSub1_32 */ + +/* + * Shift n words left "shift" bits. 0 < shift < 32. Returns the + * carry, any bits shifted off the left-hand side (0 <= carry < 2^shift). + */ +#ifndef lbnLshift_32 +BNWORD32 +lbnLshift_32(BNWORD32 *num, unsigned len, unsigned shift) +{ + BNWORD32 x, carry; + + assert(shift > 0); + assert(shift < 32); + + carry = 0; + while (len--) { + BIG(--num;) + x = *num; + *num = (x<<shift) | carry; + LITTLE(num++;) + carry = x >> (32-shift); + } + return carry; +} +#endif /* !lbnLshift_32 */ + +/* + * An optimized version of the above, for shifts of 1. + * Some machines can use add-with-carry tricks for this. + */ +#ifndef lbnDouble_32 +BNWORD32 +lbnDouble_32(BNWORD32 *num, unsigned len) +{ + BNWORD32 x, carry; + + carry = 0; + while (len--) { + BIG(--num;) + x = *num; + *num = (x<<1) | carry; + LITTLE(num++;) + carry = x >> (32-1); + } + return carry; +} +#endif /* !lbnDouble_32 */ + +/* + * Shift n words right "shift" bits. 0 < shift < 32. Returns the + * carry, any bits shifted off the right-hand side (0 <= carry < 2^shift). + */ +#ifndef lbnRshift_32 +BNWORD32 +lbnRshift_32(BNWORD32 *num, unsigned len, unsigned shift) +{ + BNWORD32 x, carry = 0; + + assert(shift > 0); + assert(shift < 32); + + BIGLITTLE(num -= len, num += len); + + while (len--) { + LITTLE(--num;) + x = *num; + *num = (x>>shift) | carry; + BIG(num++;) + carry = x << (32-shift); + } + return carry >> (32-shift); +} +#endif /* !lbnRshift_32 */ + +/* + * Multiply two numbers of the given lengths. prod and num2 may overlap, + * provided that the low len1 bits of prod are free. (This corresponds + * nicely to the place the result is returned from lbnMontReduce_32.) + * + * TODO: Use Karatsuba multiply. The overlap constraints may have + * to get rewhacked. + */ +#ifndef lbnMul_32 +void +lbnMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1, + BNWORD32 const *num2, unsigned len2) +{ + /* Special case of zero */ + if (!len1 || !len2) { + lbnZero_32(prod, len1+len2); + return; + } + + /* Multiply first word */ + lbnMulN1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); + + /* + * Add in subsequent words, storing the most significant word, + * which is new each time. + */ + while (--len2) { + BIGLITTLE(--prod,prod++); + BIGLITTLE(*(prod-len1-1),*(prod+len1)) = + lbnMulAdd1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++)); + } +} +#endif /* !lbnMul_32 */ + +/* + * lbnMulX_32 is a square multiply - both inputs are the same length. + * It's normally just a macro wrapper around the general multiply, + * but might be implementable in assembly more efficiently (such as + * when product scanning). + */ +#ifndef lbnMulX_32 +#if defined(BNWORD64) && PRODUCT_SCAN +/* + * Test code to see whether product scanning is any faster. It seems + * to make the C code slower, so PRODUCT_SCAN is not defined. + */ +static void +lbnMulX_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2, + unsigned len) +{ + BNWORD64 x, y; + BNWORD32 const *p1, *p2; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); + BIGLITTLE(*--prod, *prod++) = (BNWORD32)x; + x >>= 32; + + for (i = 1; i < len; i++) { + carry = 0; + p1 = num1; + p2 = BIGLITTLE(num2-i-1,num2+i+1); + for (j = 0; j <= i; j++) { + BIG(y = (BNWORD64)*--p1 * *p2++;) + LITTLE(y = (BNWORD64)*p1++ * *--p2;) + x += y; + carry += (x < y); + } + BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + for (i = 1; i < len; i++) { + carry = 0; + p1 = BIGLITTLE(num1-i,num1+i); + p2 = BIGLITTLE(num2-len,num2+len); + for (j = i; j < len; j++) { + BIG(y = (BNWORD64)*--p1 * *p2++;) + LITTLE(y = (BNWORD64)*p1++ * *--p2;) + x += y; + carry += (x < y); + } + BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + + BIGLITTLE(*--prod,*prod) = (BNWORD32)x; +} +#else /* !defined(BNWORD64) || !PRODUCT_SCAN */ +/* Default trivial macro definition */ +#define lbnMulX_32(prod, num1, num2, len) lbnMul_32(prod, num1, len, num2, len) +#endif /* !defined(BNWORD64) || !PRODUCT_SCAN */ +#endif /* !lbmMulX_32 */ + +#if !defined(lbnMontMul_32) && defined(BNWORD64) && PRODUCT_SCAN +/* + * Test code for product-scanning multiply. This seems to slow the C + * code down rather than speed it up. + * This does a multiply and Montgomery reduction together, using the + * same loops. The outer loop scans across the product, twice. + * The first pass computes the low half of the product and the + * Montgomery multipliers. These are stored in the product array, + * which contains no data as of yet. x and carry add up the columns + * and propagate carries forward. + * + * The second half multiplies the upper half, adding in the modulus + * times the Montgomery multipliers. The results of this multiply + * are stored. + */ +static void +lbnMontMul_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2, + BNWORD32 const *mod, unsigned len, BNWORD32 inv) +{ + BNWORD64 x, y; + BNWORD32 const *p1, *p2, *pm; + BNWORD32 *pp; + BNWORD32 t; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + /* + * This computes directly into the high half of prod, so just + * shift the pointer and consider prod only "len" elements long + * for the rest of the code. + */ + BIGLITTLE(prod -= len, prod += len); + + /* Pass 1 - compute Montgomery multipliers */ + /* First iteration can have certain simplifications. */ + x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]); + BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD32)x; + y = (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]); + x += y; + /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */ + carry = (x < y); + assert((BNWORD32)x == 0); + x = x >> 32 | (BNWORD64)carry << 32; + + for (i = 1; i < len; i++) { + carry = 0; + p1 = num1; + p2 = BIGLITTLE(num2-i-1,num2+i+1); + pp = prod; + pm = BIGLITTLE(mod-i-1,mod+i+1); + for (j = 0; j < i; j++) { + y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); + x += y; + carry += (x < y); + y = (BNWORD64)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm); + x += y; + carry += (x < y); + } + y = (BNWORD64)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]); + x += y; + carry += (x < y); + assert(BIGLITTLE(pp == prod-i, pp == prod+i)); + BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD32)x; + assert(BIGLITTLE(pm == mod-1, pm == mod+1)); + y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]); + x += y; + carry += (x < y); + assert((BNWORD32)x == 0); + x = x >> 32 | (BNWORD64)carry << 32; + } + + /* Pass 2 - compute reduced product and store */ + for (i = 1; i < len; i++) { + carry = 0; + p1 = BIGLITTLE(num1-i,num1+i); + p2 = BIGLITTLE(num2-len,num2+len); + pm = BIGLITTLE(mod-i,mod+i); + pp = BIGLITTLE(prod-len,prod+len); + for (j = i; j < len; j++) { + y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2); + x += y; + carry += (x < y); + y = (BNWORD64)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pm == mod-len, pm == mod+len)); + assert(BIGLITTLE(pp == prod-i, pp == prod+i)); + BIGLITTLE(pp[0],pp[-1]) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + + /* Last round of second half, simplified. */ + BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD32)x; + carry = (x >> 32); + + while (carry) + carry -= lbnSubN_32(prod, mod, len); + while (lbnCmp_32(prod, mod, len) >= 0) + (void)lbnSubN_32(prod, mod, len); +} +/* Suppress later definition */ +#define lbnMontMul_32 lbnMontMul_32 +#endif + +#if !defined(lbnSquare_32) && defined(BNWORD64) && PRODUCT_SCAN +/* + * Trial code for product-scanning squaring. This seems to slow the C + * code down rather than speed it up. + */ +void +lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len) +{ + BNWORD64 x, y, z; + BNWORD32 const *p1, *p2; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!len) + return; + + /* Word 0 of product */ + x = (BNWORD64)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]); + BIGLITTLE(*--prod, *prod++) = (BNWORD32)x; + x >>= 32; + + /* Words 1 through len-1 */ + for (i = 1; i < len; i++) { + carry = 0; + y = 0; + p1 = num; + p2 = BIGLITTLE(num-i-1,num+i+1); + for (j = 0; j < (i+1)/2; j++) { + BIG(z = (BNWORD64)*--p1 * *p2++;) + LITTLE(z = (BNWORD64)*p1++ * *--p2;) + y += z; + carry += (y < z); + } + y += z = y; + carry += carry + (y < z); + if ((i & 1) == 0) { + assert(BIGLITTLE(--p1 == p2, p1 == --p2)); + BIG(z = (BNWORD64)*p2 * *p2;) + LITTLE(z = (BNWORD64)*p1 * *p1;) + y += z; + carry += (y < z); + } + x += y; + carry += (x < y); + BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + /* Words len through 2*len-2 */ + for (i = 1; i < len; i++) { + carry = 0; + y = 0; + p1 = BIGLITTLE(num-i,num+i); + p2 = BIGLITTLE(num-len,num+len); + for (j = 0; j < (len-i)/2; j++) { + BIG(z = (BNWORD64)*--p1 * *p2++;) + LITTLE(z = (BNWORD64)*p1++ * *--p2;) + y += z; + carry += (y < z); + } + y += z = y; + carry += carry + (y < z); + if ((len-i) & 1) { + assert(BIGLITTLE(--p1 == p2, p1 == --p2)); + BIG(z = (BNWORD64)*p2 * *p2;) + LITTLE(z = (BNWORD64)*p1 * *p1;) + y += z; + carry += (y < z); + } + x += y; + carry += (x < y); + BIGLITTLE(*--prod,*prod++) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + + /* Word 2*len-1 */ + BIGLITTLE(*--prod,*prod) = (BNWORD32)x; +} +/* Suppress later definition */ +#define lbnSquare_32 lbnSquare_32 +#endif + +/* + * Square a number, using optimized squaring to reduce the number of + * primitive multiples that are executed. There may not be any + * overlap of the input and output. + * + * Technique: Consider the partial products in the multiplication + * of "abcde" by itself: + * + * a b c d e + * * a b c d e + * ================== + * ae be ce de ee + * ad bd cd dd de + * ac bc cc cd ce + * ab bb bc bd be + * aa ab ac ad ae + * + * Note that everything above the main diagonal: + * ae be ce de = (abcd) * e + * ad bd cd = (abc) * d + * ac bc = (ab) * c + * ab = (a) * b + * + * is a copy of everything below the main diagonal: + * de + * cd ce + * bc bd be + * ab ac ad ae + * + * Thus, the sum is 2 * (off the diagonal) + diagonal. + * + * This is accumulated beginning with the diagonal (which + * consist of the squares of the digits of the input), which is then + * divided by two, the off-diagonal added, and multiplied by two + * again. The low bit is simply a copy of the low bit of the + * input, so it doesn't need special care. + * + * TODO: Merge the shift by 1 with the squaring loop. + * TODO: Use Karatsuba. (a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W. + */ +#ifndef lbnSquare_32 +void +lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len) +{ + BNWORD32 t; + BNWORD32 *prodx = prod; /* Working copy of the argument */ + BNWORD32 const *numx = num; /* Working copy of the argument */ + unsigned lenx = len; /* Working copy of the argument */ + + if (!len) + return; + + /* First, store all the squares */ + while (lenx--) { +#ifdef mul32_ppmm + BNWORD32 ph, pl; + t = BIGLITTLE(*--numx,*numx++); + mul32_ppmm(ph,pl,t,t); + BIGLITTLE(*--prodx,*prodx++) = pl; + BIGLITTLE(*--prodx,*prodx++) = ph; +#elif defined(BNWORD64) /* use BNWORD64 */ + BNWORD64 p; + t = BIGLITTLE(*--numx,*numx++); + p = (BNWORD64)t * t; + BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)p; + BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)(p>>32); +#else /* Use lbnMulN1_32 */ + t = BIGLITTLE(numx[-1],*numx); + lbnMulN1_32(prodx, numx, 1, t); + BIGLITTLE(--numx,numx++); + BIGLITTLE(prodx -= 2, prodx += 2); +#endif + } + /* Then, shift right 1 bit */ + (void)lbnRshift_32(prod, 2*len, 1); + + /* Then, add in the off-diagonal sums */ + lenx = len; + numx = num; + prodx = prod; + while (--lenx) { + t = BIGLITTLE(*--numx,*numx++); + BIGLITTLE(--prodx,prodx++); + t = lbnMulAdd1_32(prodx, numx, lenx, t); + lbnAdd1_32(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t); + BIGLITTLE(--prodx,prodx++); + } + + /* Shift it back up */ + lbnDouble_32(prod, 2*len); + + /* And set the low bit appropriately */ + BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1; +} +#endif /* !lbnSquare_32 */ + +/* + * lbnNorm_32 - given a number, return a modified length such that the + * most significant digit is non-zero. Zero-length input is okay. + */ +#ifndef lbnNorm_32 +unsigned +lbnNorm_32(BNWORD32 const *num, unsigned len) +{ + BIGLITTLE(num -= len,num += len); + while (len && BIGLITTLE(*num++,*--num) == 0) + --len; + return len; +} +#endif /* lbnNorm_32 */ + +/* + * lbnBits_32 - return the number of significant bits in the array. + * It starts by normalizing the array. Zero-length input is okay. + * Then assuming there's anything to it, it fetches the high word, + * generates a bit length by multiplying the word length by 32, and + * subtracts off 32/2, 32/4, 32/8, ... bits if the high bits are clear. + */ +#ifndef lbnBits_32 +unsigned +lbnBits_32(BNWORD32 const *num, unsigned len) +{ + BNWORD32 t; + unsigned i; + + len = lbnNorm_32(num, len); + if (len) { + t = BIGLITTLE(*(num-len),*(num+(len-1))); + assert(t); + len *= 32; + i = 32/2; + do { + if (t >> i) + t >>= i; + else + len -= i; + } while ((i /= 2) != 0); + } + return len; +} +#endif /* lbnBits_32 */ + +/* + * If defined, use hand-rolled divide rather than compiler's native. + * If the machine doesn't do it in line, the manual code is probably + * faster, since it can assume normalization and the fact that the + * quotient will fit into 32 bits, which a general 64-bit divide + * in a compiler's run-time library can't do. + */ +#ifndef BN_SLOW_DIVIDE_64 +/* Assume that divisors of more than thirty-two bits are slow */ +#define BN_SLOW_DIVIDE_64 (64 > 0x20) +#endif + +/* + * Return (nh<<32|nl) % d, and place the quotient digit into *q. + * It is guaranteed that nh < d, and that d is normalized (with its high + * bit set). If we have a double-width type, it's easy. If not, ooh, + * yuk! + */ +#ifndef lbnDiv21_32 +#if defined(BNWORD64) && !BN_SLOW_DIVIDE_64 +BNWORD32 +lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d) +{ + BNWORD64 n = (BNWORD64)nh << 32 | nl; + + /* Divisor must be normalized */ + assert(d >> (32-1) == 1); + + *q = n / d; + return n % d; +} +#else +/* + * This is where it gets ugly. + * + * Do the division in two halves, using Algorithm D from section 4.3.1 + * of Knuth. Note Theorem B from that section, that the quotient estimate + * is never more than the true quotient, and is never more than two + * too low. + * + * The mapping onto conventional long division is (everything a half word): + * _____________qh___ql_ + * dh dl ) nh.h nh.l nl.h nl.l + * - (qh * d) + * ----------- + * rrrr rrrr nl.l + * - (ql * d) + * ----------- + * rrrr rrrr + * + * The implicit 3/2-digit d*qh and d*ql subtractors are computed this way: + * First, estimate a q digit so that nh/dh works. Subtracting qh*dh from + * the (nh.h nh.l) list leaves a 1/2-word remainder r. Then compute the + * low part of the subtractor, qh * dl. This also needs to be subtracted + * from (nh.h nh.l nl.h) to get the final remainder. So we take the + * remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and + * try to subtract qh * dl from that. Since the remainder is 1/2-word + * long, shifting and adding nl.h results in a single word r. + * It is possible that the remainder we're working with, r, is less than + * the product qh * dl, if we estimated qh too high. The estimation + * technique can produce a qh that is too large (never too small), leading + * to r which is too small. In that case, decrement the digit qh, add + * shifted dh to r (to correct for that error), and subtract dl from the + * product we're comparing r with. That's the "correct" way to do it, but + * just adding dl to r instead of subtracting it from the product is + * equivalent and a lot simpler. You just have to watch out for overflow. + * + * The process is repeated with (rrrr rrrr nl.l) for the low digit of the + * quotient ql. + * + * The various uses of 32/2 for shifts are because of the note about + * automatic editing of this file at the very top of the file. + */ +#define highhalf(x) ( (x) >> 32/2 ) +#define lowhalf(x) ( (x) & (((BNWORD32)1 << 32/2)-1) ) +BNWORD32 +lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d) +{ + BNWORD32 dh = highhalf(d), dl = lowhalf(d); + BNWORD32 qh, ql, prod, r; + + /* Divisor must be normalized */ + assert((d >> (32-1)) == 1); + + /* Do first half-word of division */ + qh = nh / dh; + r = nh % dh; + prod = qh * dl; + + /* + * Add next half-word of numerator to remainder and correct. + * qh may be up to two too large. + */ + r = (r << (32/2)) | highhalf(nl); + if (r < prod) { + --qh; r += d; + if (r >= d && r < prod) { + --qh; r += d; + } + } + r -= prod; + + /* Do second half-word of division */ + ql = r / dh; + r = r % dh; + prod = ql * dl; + + r = (r << (32/2)) | lowhalf(nl); + if (r < prod) { + --ql; r += d; + if (r >= d && r < prod) { + --ql; r += d; + } + } + r -= prod; + + *q = (qh << (32/2)) | ql; + + return r; +} +#endif +#endif /* lbnDiv21_32 */ + + +/* + * In the division functions, the dividend and divisor are referred to + * as "n" and "d", which stand for "numerator" and "denominator". + * + * The quotient is (nlen-dlen+1) digits long. It may be overlapped with + * the high (nlen-dlen) words of the dividend, but one extra word is needed + * on top to hold the top word. + */ + +/* + * Divide an n-word number by a 1-word number, storing the remainder + * and n-1 words of the n-word quotient. The high word is returned. + * It IS legal for rem to point to the same address as n, and for + * q to point one word higher. + * + * TODO: If BN_SLOW_DIVIDE_64, add a divnhalf_32 which uses 32-bit + * dividends if the divisor is half that long. + * TODO: Shift the dividend on the fly to avoid the last division and + * instead have a remainder that needs shifting. + * TODO: Use reciprocals rather than dividing. + */ +#ifndef lbnDiv1_32 +BNWORD32 +lbnDiv1_32(BNWORD32 *q, BNWORD32 *rem, BNWORD32 const *n, unsigned len, + BNWORD32 d) +{ + unsigned shift; + unsigned xlen; + BNWORD32 r; + BNWORD32 qhigh; + + assert(len > 0); + assert(d); + + if (len == 1) { + r = *n; + *rem = r%d; + return r/d; + } + + shift = 0; + r = d; + xlen = 32/2; + do { + if (r >> xlen) + r >>= xlen; + else + shift += xlen; + } while ((xlen /= 2) != 0); + assert((d >> (32-1-shift)) == 1); + d <<= shift; + + BIGLITTLE(q -= len-1,q += len-1); + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + if (r < d) { + qhigh = 0; + } else { + qhigh = r/d; + r %= d; + } + + xlen = len; + while (--xlen) + r = lbnDiv21_32(BIGLITTLE(q++,--q), r, BIGLITTLE(*n++,*--n), d); + + /* + * Final correction for shift - shift the quotient up "shift" + * bits, and merge in the extra bits of quotient. Then reduce + * the final remainder mod the real d. + */ + if (shift) { + d >>= shift; + qhigh = (qhigh << shift) | lbnLshift_32(q, len-1, shift); + BIGLITTLE(q[-1],*q) |= r/d; + r %= d; + } + *rem = r; + + return qhigh; +} +#endif + +/* + * This function performs a "quick" modulus of a number with a divisor + * d which is guaranteed to be at most sixteen bits, i.e. less than 65536. + * This applies regardless of the word size the library is compiled with. + * + * This function is important to prime generation, for sieving. + */ +#ifndef lbnModQ_32 +/* If there's a custom lbnMod21_32, no normalization needed */ +#ifdef lbnMod21_32 +unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + unsigned i, shift; + BNWORD32 r; + + assert(len > 0); + + BIGLITTLE(n -= len,n += len); + + /* Try using a compare to avoid the first divide */ + r = BIGLITTLE(*n++,*--n); + if (r >= d) + r %= d; + while (--len) + r = lbnMod21_32(r, BIGLITTLE(*n++,*--n), d); + + return r; +} +#elif defined(BNWORD64) && !BN_SLOW_DIVIDE_64 +unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + BNWORD32 r; + + if (!--len) + return BIGLITTLE(n[-1],n[0]) % d; + + BIGLITTLE(n -= len,n += len); + r = BIGLITTLE(n[-1],n[0]); + + do { + r = (BNWORD32)((((BNWORD64)r<<32) | BIGLITTLE(*n++,*--n)) % d); + } while (--len); + + return r; +} +#elif 32 >= 0x20 +/* + * If the single word size can hold 65535*65536, then this function + * is avilable. + */ +#ifndef highhalf +#define highhalf(x) ( (x) >> 32/2 ) +#define lowhalf(x) ( (x) & ((1 << 32/2)-1) ) +#endif +unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + BNWORD32 r, x; + + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + while (--len) { + x = BIGLITTLE(*n++,*--n); + r = (r%d << 32/2) | highhalf(x); + r = (r%d << 32/2) | lowhalf(x); + } + + return r%d; +} +#else +/* Default case - use lbnDiv21_32 */ +unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + unsigned i, shift; + BNWORD32 r; + BNWORD32 q; + + assert(len > 0); + + shift = 0; + r = d; + i = 32; + while (i /= 2) { + if (r >> i) + r >>= i; + else + shift += i; + } + assert(d >> (32-1-shift) == 1); + d <<= shift; + + BIGLITTLE(n -= len,n += len); + + r = BIGLITTLE(*n++,*--n); + if (r >= d) + r %= d; + + while (--len) + r = lbnDiv21_32(&q, r, BIGLITTLE(*n++,*--n), d); + + /* + * Final correction for shift - shift the quotient up "shift" + * bits, and merge in the extra bits of quotient. Then reduce + * the final remainder mod the real d. + */ + if (shift) + r %= d >> shift; + + return r; +} +#endif +#endif /* lbnModQ_32 */ + +/* + * Reduce n mod d and return the quotient. That is, find: + * q = n / d; + * n = n % d; + * d is altered during the execution of this subroutine by normalizing it. + * It must already have its most significant word non-zero; it is shifted + * so its most significant bit is non-zero. + * + * The quotient q is nlen-dlen+1 words long. To make it possible to + * overlap the quptient with the input (you can store it in the high dlen + * words), the high word of the quotient is *not* stored, but is returned. + * (If all you want is the remainder, you don't care about it, anyway.) + * + * This uses algorithm D from Knuth (4.3.1), except that we do binary + * (shift) normalization of the divisor. WARNING: This is hairy! + * + * This function is used for some modular reduction, but it is not used in + * the modular exponentiation loops; they use Montgomery form and the + * corresponding, more efficient, Montgomery reduction. This code + * is needed for the conversion to Montgomery form, however, so it + * has to be here and it might as well be reasonably efficient. + * + * The overall operation is as follows ("top" and "up" refer to the + * most significant end of the number; "bottom" and "down", the least): + * + * - Shift the divisor up until the most significant bit is set. + * - Shift the dividend up the same amount. This will produce the + * correct quotient, and the remainder can be recovered by shifting + * it back down the same number of bits. This may produce an overflow + * word, but the word is always strictly less than the most significant + * divisor word. + * - Estimate the first quotient digit qhat: + * - First take the top two words (one of which is the overflow) of the + * dividend and divide by the top word of the divisor: + * qhat = (nh,nm)/dh. This qhat is >= the correct quotient digit + * and, since dh is normalized, it is at most two over. + * - Second, correct by comparing the top three words. If + * (dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again. + * The second iteration can be simpler because there can't be a third. + * The computation can be simplified by subtracting dh*qhat from + * both sides, suitably shifted. This reduces the left side to + * dl*qhat. On the right, (nh,nm)-dh*qhat is simply the + * remainder r from (nh,nm)%dh, so the right is (r,nl). + * This produces qhat that is almost always correct and at + * most (prob ~ 2/2^32) one too high. + * - Subtract qhat times the divisor (suitably shifted) from the dividend. + * If there is a borrow, qhat was wrong, so decrement it + * and add the divisor back in (once). + * - Store the final quotient digit qhat in the quotient array q. + * + * Repeat the quotient digit computation for successive digits of the + * quotient until the whole quotient has been computed. Then shift the + * divisor and the remainder down to correct for the normalization. + * + * TODO: Special case 2-word divisors. + * TODO: Use reciprocals rather than dividing. + */ +#ifndef divn_32 +BNWORD32 +lbnDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen) +{ + BNWORD32 nh,nm,nl; /* Top three words of the dividend */ + BNWORD32 dh,dl; /* Top two words of the divisor */ + BNWORD32 qhat; /* Extimate of quotient word */ + BNWORD32 r; /* Remainder from quotient estimate division */ + BNWORD32 qhigh; /* High word of quotient */ + unsigned i; /* Temp */ + unsigned shift; /* Bits shifted by normalization */ + unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */ +#ifdef mul32_ppmm + BNWORD32 t32; +#elif defined(BNWORD64) + BNWORD64 t64; +#else /* use lbnMulN1_32 */ + BNWORD32 t2[2]; +#define t2high BIGLITTLE(t2[0],t2[1]) +#define t2low BIGLITTLE(t2[1],t2[0]) +#endif + + assert(dlen); + assert(nlen >= dlen); + + /* + * Special cases for short divisors. The general case uses the + * top top 2 digits of the divisor (d) to estimate a quotient digit, + * so it breaks if there are fewer digits available. Thus, we need + * special cases for a divisor of length 1. A divisor of length + * 2 can have a *lot* of administrivia overhead removed removed, + * so it's probably worth special-casing that case, too. + */ + if (dlen == 1) + return lbnDiv1_32(q, BIGLITTLE(n-1,n), n, nlen, + BIGLITTLE(d[-1],d[0])); + +#if 0 + /* + * @@@ This is not yet written... The general loop will do, + * albeit less efficiently + */ + if (dlen == 2) { + /* + * divisor two digits long: + * use the 3/2 technique from Knuth, but we know + * it's exact. + */ + dh = BIGLITTLE(d[-1],d[0]); + dl = BIGLITTLE(d[-2],d[1]); + shift = 0; + if ((sh & ((BNWORD32)1 << 32-1-shift)) == 0) { + do { + shift++; + } while (dh & (BNWORD32)1<<32-1-shift) == 0); + dh = dh << shift | dl >> (32-shift); + dl <<= shift; + + + } + + + for (shift = 0; (dh & (BNWORD32)1 << 32-1-shift)) == 0; shift++) + ; + if (shift) { + } + dh = dh << shift | dl >> (32-shift); + shift = 0; + while (dh + } +#endif + + dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); + assert(dh); + + /* Normalize the divisor */ + shift = 0; + r = dh; + i = 32/2; + do { + if (r >> i) + r >>= i; + else + shift += i; + } while ((i /= 2) != 0); + + nh = 0; + if (shift) { + lbnLshift_32(d, dlen, shift); + dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1))); + nh = lbnLshift_32(n, nlen, shift); + } + + /* Assert that dh is now normalized */ + assert(dh >> (32-1)); + + /* Also get the second-most significant word of the divisor */ + dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2))); + + /* + * Adjust pointers: n to point to least significant end of first + * first subtract, and q to one the most-significant end of the + * quotient array. + */ + BIGLITTLE(n -= qlen,n += qlen); + BIGLITTLE(q -= qlen,q += qlen); + + /* Fetch the most significant stored word of the dividend */ + nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + + /* + * Compute the first digit of the quotient, based on the + * first two words of the dividend (the most significant of which + * is the overflow word h). + */ + if (nh) { + assert(nh < dh); + r = lbnDiv21_32(&qhat, nh, nm, dh); + } else if (nm >= dh) { + qhat = nm/dh; + r = nm % dh; + } else { /* Quotient is zero */ + qhigh = 0; + goto divloop; + } + + /* Now get the third most significant word of the dividend */ + nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); + + /* + * Correct qhat, the estimate of quotient digit. + * qhat can only be high, and at most two words high, + * so the loop can be unrolled and abbreviated. + */ +#ifdef mul32_ppmm + mul32_ppmm(nm, t32, qhat, dl); + if (nm > r || (nm == r && t32 > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + nm -= (t32 < dl); + t32 -= dl; + if (nm > r || (nm == r && t32 > nl)) + qhat--; + } + } +#elif defined(BNWORD64) + t64 = (BNWORD64)qhat * dl; + if (t64 > ((BNWORD64)r << 32) + nl) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) > dh) { + t64 -= dl; + if (t64 > ((BNWORD64)r << 32) + nl) + qhat--; + } + } +#else /* Use lbnMulN1_32 */ + lbnMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat); + if (t2high > r || (t2high == r && t2low > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t2high -= (t2low < dl); + t2low -= dl; + if (t2high > r || (t2high == r && t2low > nl)) + qhat--; + } + } +#endif + + /* Do the multiply and subtract */ + r = lbnMulSub1_32(n, d, dlen, qhat); + /* If there was a borrow, add back once. */ + if (r > nh) { /* Borrow? */ + (void)lbnAddN_32(n, d, dlen); + qhat--; + } + + /* Remember the first quotient digit. */ + qhigh = qhat; + + /* Now, the main division loop: */ +divloop: + while (qlen--) { + + /* Advance n */ + nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + BIGLITTLE(++n,--n); + nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1))); + + if (nh == dh) { + qhat = ~(BNWORD32)0; + /* Optimized computation of r = (nh,nm) - qhat * dh */ + r = nh + nm; + if (r < nh) + goto subtract; + } else { + assert(nh < dh); + r = lbnDiv21_32(&qhat, nh, nm, dh); + } + + nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2))); +#ifdef mul32_ppmm + mul32_ppmm(nm, t32, qhat, dl); + if (nm > r || (nm == r && t32 > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + nm -= (t32 < dl); + t32 -= dl; + if (nm > r || (nm == r && t32 > nl)) + qhat--; + } + } +#elif defined(BNWORD64) + t64 = (BNWORD64)qhat * dl; + if (t64 > ((BNWORD64)r<<32) + nl) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t64 -= dl; + if (t64 > ((BNWORD64)r << 32) + nl) + qhat--; + } + } +#else /* Use lbnMulN1_32 */ + lbnMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat); + if (t2high > r || (t2high == r && t2low > nl)) { + /* Decrement qhat and adjust comparison parameters */ + qhat--; + if ((r += dh) >= dh) { + t2high -= (t2low < dl); + t2low -= dl; + if (t2high > r || (t2high == r && t2low > nl)) + qhat--; + } + } +#endif + + /* + * As a point of interest, note that it is not worth checking + * for qhat of 0 or 1 and installing special-case code. These + * occur with probability 2^-32, so spending 1 cycle to check + * for them is only worth it if we save more than 2^15 cycles, + * and a multiply-and-subtract for numbers in the 1024-bit + * range just doesn't take that long. + */ +subtract: + /* + * n points to the least significant end of the substring + * of n to be subtracted from. qhat is either exact or + * one too large. If the subtract gets a borrow, it was + * one too large and the divisor is added back in. It's + * a dlen+1 word add which is guaranteed to produce a + * carry out, so it can be done very simply. + */ + r = lbnMulSub1_32(n, d, dlen, qhat); + if (r > nh) { /* Borrow? */ + (void)lbnAddN_32(n, d, dlen); + qhat--; + } + /* Store the quotient digit */ + BIGLITTLE(*q++,*--q) = qhat; + } + /* Tah dah! */ + + if (shift) { + lbnRshift_32(d, dlen, shift); + lbnRshift_32(n, dlen, shift); + } + + return qhigh; +} +#endif + +/* + * Find the negative multiplicative inverse of x (x must be odd!) modulo 2^32. + * + * This just performs Newton's iteration until it gets the + * inverse. The initial estimate is always correct to 3 bits, and + * sometimes 4. The number of valid bits doubles each iteration. + * (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable + * for the error mod 2^2n. x * y == 1 + k*2^n (mod 2^2n) and follow + * the iteration through.) + */ +#ifndef lbnMontInv1_32 +BNWORD32 +lbnMontInv1_32(BNWORD32 const x) +{ + BNWORD32 y = x, z; + + assert(x & 1); + + while ((z = x*y) != 1) + y *= 2 - z; + return -y; +} +#endif /* !lbnMontInv1_32 */ + +#if defined(BNWORD64) && PRODUCT_SCAN +/* + * Test code for product-scanning Montgomery reduction. + * This seems to slow the C code down rather than speed it up. + * + * The first loop computes the Montgomery multipliers, storing them over + * the low half of the number n. + * + * The second half multiplies the upper half, adding in the modulus + * times the Montgomery multipliers. The results of this multiply + * are stored. + */ +void +lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv) +{ + BNWORD64 x, y; + BNWORD32 const *pm; + BNWORD32 *pn; + BNWORD32 t; + unsigned carry; + unsigned i, j; + + /* Special case of zero */ + if (!mlen) + return; + + /* Pass 1 - compute Montgomery multipliers */ + /* First iteration can have certain simplifications. */ + t = BIGLITTLE(n[-1],n[0]); + x = t; + t *= inv; + BIGLITTLE(n[-1], n[0]) = t; + x += (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */ + assert((BNWORD32)x == 0); + x = x >> 32; + + for (i = 1; i < mlen; i++) { + carry = 0; + pn = n; + pm = BIGLITTLE(mod-i-1,mod+i+1); + for (j = 0; j < i; j++) { + y = (BNWORD64)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pn == n-i, pn == n+i)); + y = t = BIGLITTLE(pn[-1], pn[0]); + x += y; + carry += (x < y); + BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD32)x; + assert(BIGLITTLE(pm == mod-1, pm == mod+1)); + y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]); + x += y; + carry += (x < y); + assert((BNWORD32)x == 0); + x = x >> 32 | (BNWORD64)carry << 32; + } + + BIGLITTLE(n -= mlen, n += mlen); + + /* Pass 2 - compute upper words and add to n */ + for (i = 1; i < mlen; i++) { + carry = 0; + pm = BIGLITTLE(mod-i,mod+i); + pn = n; + for (j = i; j < mlen; j++) { + y = (BNWORD64)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn); + x += y; + carry += (x < y); + } + assert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen)); + assert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i)); + y = t = BIGLITTLE(*(n-i),*(n+i-1)); + x += y; + carry += (x < y); + BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD32)x; + x = (x >> 32) | (BNWORD64)carry << 32; + } + + /* Last round of second half, simplified. */ + t = BIGLITTLE(*(n-mlen),*(n+mlen-1)); + x += t; + BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD32)x; + carry = (unsigned)(x >> 32); + + while (carry) + carry -= lbnSubN_32(n, mod, mlen); + while (lbnCmp_32(n, mod, mlen) >= 0) + (void)lbnSubN_32(n, mod, mlen); +} +#define lbnMontReduce_32 lbnMontReduce_32 +#endif + +/* + * Montgomery reduce n, modulo mod. This reduces modulo mod and divides by + * 2^(32*mlen). Returns the result in the *top* mlen words of the argument n. + * This is ready for another multiplication using lbnMul_32. + * + * Montgomery representation is a very useful way to encode numbers when + * you're doing lots of modular reduction. What you do is pick a multiplier + * R which is relatively prime to the modulus and very easy to divide by. + * Since the modulus is odd, R is closen as a power of 2, so the division + * is a shift. In fact, it's a shift of an integral number of words, + * so the shift can be implicit - just drop the low-order words. + * + * Now, choose R *larger* than the modulus m, 2^(32*mlen). Then convert + * all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the + * relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. Note that: + * - The Montgomery form of a number depends on the modulus m. + * A fixed modulus m is assumed throughout this discussion. + * - Since R is relaitvely prime to m, multiplication by R is invertible; + * no information about the numbers is lost, they're just scrambled. + * - Adding (and subtracting) numbers in this form works just as usual. + * M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m + * - Multiplying numbers in this form produces a*b*R*R. The problem + * is to divide out the excess factor of R, modulo m as well as to + * reduce to the given length mlen. It turns out that this can be + * done *faster* than a normal divide, which is where the speedup + * in Montgomery division comes from. + * + * Normal reduction chooses a most-significant quotient digit q and then + * subtracts q*m from the number to be reduced. Choosing q is tricky + * and involved (just look at lbnDiv_32 to see!) and is usually + * imperfect, requiring a check for correction after the subtraction. + * + * Montgomery reduction *adds* a multiple of m to the *low-order* part + * of the number to be reduced. This multiple is chosen to make the + * low-order part of the number come out to zero. This can be done + * with no trickery or error using a precomputed inverse of the modulus. + * In this code, the "part" is one word, but any width can be used. + * + * Repeating this step sufficiently often results in a value which + * is a multiple of R (a power of two, remember) but is still (since + * the additions were to the low-order part and thus did not increase + * the value of the number being reduced very much) still not much + * larger than m*R. Then implicitly divide by R and subtract off + * m until the result is in the correct range. + * + * Since the low-order part being cancelled is less than R, the + * multiple of m added must have a multiplier which is at most R-1. + * Assuming that the input is at most m*R-1, the final number is + * at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from + * the high-order part, equivalent to subtracting m*R from the + * while number, produces a result which is at most m*R - m - 1, + * which divided by R is at most m-1. + * + * To convert *to* Montgomery form, you need a regular remainder + * routine, although you can just compute R*R (mod m) and do the + * conversion using Montgomery multiplication. To convert *from* + * Montgomery form, just Montgomery reduce the number to + * remove the extra factor of R. + * + * TODO: Change to a full inverse and use Karatsuba's multiplication + * rather than this word-at-a-time. + */ +#ifndef lbnMontReduce_32 +void +lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen, + BNWORD32 inv) +{ + BNWORD32 t; + BNWORD32 c = 0; + unsigned len = mlen; + + /* inv must be the negative inverse of mod's least significant word */ + assert((BNWORD32)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD32)-1); + + assert(len); + + do { + t = lbnMulAdd1_32(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0])); + c += lbnAdd1_32(BIGLITTLE(n-mlen,n+mlen), len, t); + BIGLITTLE(--n,++n); + } while (--len); + + /* + * All that adding can cause an overflow past the modulus size, + * but it's unusual, and never by much, so a subtraction loop + * is the right way to deal with it. + * This subtraction happens infrequently - I've only ever seen it + * invoked once per reduction, and then just under 22.5% of the time. + */ + while (c) + c -= lbnSubN_32(n, mod, mlen); + while (lbnCmp_32(n, mod, mlen) >= 0) + (void)lbnSubN_32(n, mod, mlen); +} +#endif /* !lbnMontReduce_32 */ + +/* + * A couple of helpers that you might want to implement atomically + * in asm sometime. + */ +#ifndef lbnMontMul_32 +/* + * Multiply "num1" by "num2", modulo "mod", all of length "len", and + * place the result in the high half of "prod". "inv" is the inverse + * of the least-significant word of the modulus, modulo 2^32. + * This uses numbers in Montgomery form. Reduce using "len" and "inv". + * + * This is implemented as a macro to win on compilers that don't do + * inlining, since it's so trivial. + */ +#define lbnMontMul_32(prod, n1, n2, mod, len, inv) \ + (lbnMulX_32(prod, n1, n2, len), lbnMontReduce_32(prod, mod, len, inv)) +#endif /* !lbnMontMul_32 */ + +#ifndef lbnMontSquare_32 +/* + * Square "num", modulo "mod", both of length "len", and place the result + * in the high half of "prod". "inv" is the inverse of the least-significant + * word of the modulus, modulo 2^32. + * This uses numbers in Montgomery form. Reduce using "len" and "inv". + * + * This is implemented as a macro to win on compilers that don't do + * inlining, since it's so trivial. + */ +#define lbnMontSquare_32(prod, n, mod, len, inv) \ + (lbnSquare_32(prod, n, len), lbnMontReduce_32(prod, mod, len, inv)) + +#endif /* !lbnMontSquare_32 */ + +/* + * Convert a number to Montgomery form - requires mlen + nlen words + * of memory in "n". + */ +void +lbnToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen) +{ + /* Move n up "mlen" words */ + lbnCopy_32(BIGLITTLE(n-mlen,n+mlen), n, nlen); + lbnZero_32(n, mlen); + /* Do the division - dump the quotient in the high-order words */ + (void)lbnDiv_32(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen); +} + +/* + * Convert from Montgomery form. Montgomery reduction is all that is + * needed. + */ +void +lbnFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len) +{ + /* Zero the high words of n */ + lbnZero_32(BIGLITTLE(n-len,n+len), len); + lbnMontReduce_32(n, mod, len, lbnMontInv1_32(BIGLITTLE(mod[-1],mod[0]))); + /* Move n down len words */ + lbnCopy_32(n, BIGLITTLE(n-len,n+len), len); +} + +/* + * The windowed exponentiation algorithm, precomputes a table of odd + * powers of n up to 2^k. It takes 2^(k-1)-1 multiplies to compute + * the table, and (e-1)/(k+1) multiplies (on average) to perform the + * exponentiation. To minimize the sum, k must vary with e. + * The optimal window sizes vary with the exponent length. Here are + * some selected values and the boundary cases. + * (An underscore _ has been inserted into some of the numbers to ensure + * that magic strings like 32 do not appear in this table. It should be + * ignored.) + * + * At e = 1 bits, k=1 (0.000000) is best. + * At e = 2 bits, k=1 (0.500000) is best. + * At e = 4 bits, k=1 (1.500000) is best. + * At e = 8 bits, k=2 (3.333333) < k=1 (3.500000) + * At e = 1_6 bits, k=2 (6.000000) is best. + * At e = 26 bits, k=3 (9.250000) < k=2 (9.333333) + * At e = 3_2 bits, k=3 (10.750000) is best. + * At e = 6_4 bits, k=3 (18.750000) is best. + * At e = 82 bits, k=4 (23.200000) < k=3 (23.250000) + * At e = 128 bits, k=4 (3_2.400000) is best. + * At e = 242 bits, k=5 (55.1_66667) < k=4 (55.200000) + * At e = 256 bits, k=5 (57.500000) is best. + * At e = 512 bits, k=5 (100.1_66667) is best. + * At e = 674 bits, k=6 (127.142857) < k=5 (127.1_66667) + * At e = 1024 bits, k=6 (177.142857) is best. + * At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857) + * At e = 2048 bits, k=7 (318.875000) is best. + * At e = 4096 bits, k=7 (574.875000) is best. + * + * The numbers in parentheses are the expected number of multiplications + * needed to do the computation. The normal russian-peasant modular + * exponentiation technique always uses (e-1)/2. For exponents as + * small as 192 bits (below the range of current factoring algorithms), + * half of the multiplies are eliminated, 45.2 as opposed to the naive + * 95.5. Counting the 191 squarings as 3/4 a multiply each (squaring + * proper is just over half of multiplying, but the Montgomery + * reduction in each case is also a multiply), that's 143.25 + * multiplies, for totals of 188.45 vs. 238.75 - a 21% savings. + * For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a + * 24.3% savings. It asymptotically approaches 25%. + * + * Given that exponents for which k>7 are useful are uncommon, + * a fixed size table for k <= 7 is used for simplicity. + * k = 8 is uzeful at 4610 bits, k = 9 at 11522 bits. + * + * The basic number of squarings needed is e-1, although a k-bit + * window (for k > 1) can save, on average, k-2 of those, too. + * That savings currently isn't counted here. It would drive the + * crossover points slightly lower. + * (Actually, this win is also reduced in the DoubleExpMod case, + * meaning we'd have to split the tables. Except for that, the + * multiplies by powers of the two bases are independent, so + * the same logic applies to each as the single case.) + * + * Table entry i is the largest number of bits in an exponent to + * process with a window size of i+1. So the window never goes above 7 + * bits, requiring 2^(7-1) = 0x40 precomputed multiples. + */ +#define BNEXPMOD_MAX_WINDOW 7 +static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = { + 7, 25, 81, 241, 673, 1793, (unsigned)-1 +}; + +/* + * Perform modular exponentiation, as fast as possible! This uses + * Montgomery reduction, optimized squaring, and windowed exponentiation. + * The modulus "mod" MUST be odd! + * + * This returns 0 on success, -1 on out of memory. + * + * The window algorithm: + * The idea is to keep a running product of b1 = n^(high-order bits of exp), + * and then keep appending exponent bits to it. The following patterns + * apply to a 3-bit window (k = 3): + * To append 0: square + * To append 1: square, multiply by n^1 + * To append 10: square, multiply by n^1, square + * To append 11: square, square, multiply by n^3 + * To append 100: square, multiply by n^1, square, square + * To append 101: square, square, square, multiply by n^5 + * To append 110: square, square, multiply by n^3, square + * To append 111: square, square, square, multiply by n^7 + * + * Since each pattern involves only one multiply, the longer the pattern + * the better, except that a 0 (no multiplies) can be appended directly. + * We precompute a table of odd powers of n, up to 2^k, and can then + * multiply k bits of exponent at a time. Actually, assuming random + * exponents, there is on average one zero bit between needs to + * multiply (1/2 of the time there's none, 1/4 of the time there's 1, + * 1/8 of the time, there's 2, 1/32 of the time, there's 3, etc.), so + * you have to do one multiply per k+1 bits of exponent. + * + * The loop walks down the exponent, squaring the result buffer as + * it goes. There is a wbits+1 bit lookahead buffer, buf, that is + * filled with the upcoming exponent bits. (What is read after the + * end of the exponent is unimportant, but it is filled with zero here.) + * When the most-significant bit of this buffer becomes set, i.e. + * (buf & tblmask) != 0, we have to decide what pattern to multiply + * by, and when to do it. We decide, remember to do it in future + * after a suitable number of squarings have passed (e.g. a pattern + * of "100" in the buffer requires that we multiply by n^1 immediately; + * a pattern of "110" calls for multiplying by n^3 after one more + * squaring), clear the buffer, and continue. + * + * When we start, there is one more optimization: the result buffer + * is implcitly one, so squaring it or multiplying by it can be + * optimized away. Further, if we start with a pattern like "100" + * in the lookahead window, rather than placing n into the buffer + * and then starting to square it, we have already computed n^2 + * to compute the odd-powers table, so we can place that into + * the buffer and save a squaring. + * + * This means that if you have a k-bit window, to compute n^z, + * where z is the high k bits of the exponent, 1/2 of the time + * it requires no squarings. 1/4 of the time, it requires 1 + * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings. + * And the remaining 1/2^(k-1) of the time, the top k bits are a + * 1 followed by k-1 0 bits, so it again only requires k-2 + * squarings, not k-1. The average of these is 1. Add that + * to the one squaring we have to do to compute the table, + * and you'll see that a k-bit window saves k-2 squarings + * as well as reducing the multiplies. (It actually doesn't + * hurt in the case k = 1, either.) + * + * n must have mlen words allocated. Although fewer may be in use + * when n is passed in, all are in use on exit. + */ +int +lbnExpMod_32(BNWORD32 *result, BNWORD32 const *n, unsigned nlen, + BNWORD32 const *e, unsigned elen, BNWORD32 *mod, unsigned mlen) +{ + BNWORD32 *table[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n */ + unsigned ebits; /* Exponent bits */ + unsigned wbits; /* Window size */ + unsigned tblmask; /* Mask of exponentiation window */ + BNWORD32 bitpos; /* Mask of current look-ahead bit */ + unsigned buf; /* Buffer of exponent bits */ + unsigned multpos; /* Where to do pending multiply */ + BNWORD32 const *mult; /* What to multiply by */ + unsigned i; /* Loop counter */ + int isone; /* Flag: accum. is implicitly one */ + BNWORD32 *a, *b; /* Working buffers/accumulators */ + BNWORD32 *t; /* Pointer into the working buffers */ + BNWORD32 inv; /* mod^-1 modulo 2^32 */ + + assert(mlen); + assert(nlen <= mlen); + + /* First, a couple of trivial cases. */ + elen = lbnNorm_32(e, elen); + if (!elen) { + /* x ^ 0 == 1 */ + lbnZero_32(result, mlen); + BIGLITTLE(result[-1],result[0]) = 1; + return 0; + } + ebits = lbnBits_32(e, elen); + if (ebits == 1) { + /* x ^ 1 == x */ + if (n != result) + lbnCopy_32(result, n, nlen); + if (mlen > nlen) + lbnZero_32(BIGLITTLE(result-nlen,result+nlen), + mlen-nlen); + return 0; + } + + /* Okay, now move the exponent pointer to the most-significant word */ + e = BIGLITTLE(e-elen, e+elen-1); + + /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ + wbits = 0; + while (ebits > bnExpModThreshTable[wbits]) + wbits++; + + /* Allocate working storage: two product buffers and the tables. */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ + tblmask = 1u << wbits; + + /* We have the result buffer available, so use it. */ + table[0] = result; + + /* + * Okay, we now have a minimal-sized table - expand it. + * This is allowed to fail! If so, scale back the table size + * and proceed. + */ + for (i = 1; i < tblmask; i++) { + LBNALLOC(t, mlen); + if (!t) /* Out of memory! Quit the loop. */ + break; + table[i] = t; + } + + /* If we stopped, with i < tblmask, shrink the tables appropriately */ + while (tblmask > i) { + wbits--; + tblmask >>= 1; + } + /* Free up our overallocations */ + while (--i > tblmask) + LBNFREE(table[i], mlen); + + /* Okay, fill in the table */ + + /* Compute the necessary modular inverse */ + inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ + + /* Convert n to Montgomery form */ + + /* Move n up "mlen" words into a */ + t = BIGLITTLE(a-mlen, a+mlen); + lbnCopy_32(t, n, nlen); + lbnZero_32(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_32(t, a, mlen+nlen, mod, mlen); + /* Copy into first table entry */ + lbnCopy_32(table[0], a, mlen); + + /* Square a into b */ + lbnMontSquare_32(b, a, mod, mlen, inv); + + /* Use high half of b to initialize the table */ + t = BIGLITTLE(b-mlen, b+mlen); + for (i = 1; i < tblmask; i++) { + lbnMontMul_32(a, t, table[i-1], mod, mlen, inv); + lbnCopy_32(table[i], BIGLITTLE(a-mlen, a+mlen), mlen); + } + + /* We might use b = n^2 later... */ + + /* Initialze the fetch pointer */ + bitpos = (BNWORD32)1 << ((ebits-1) & (32-1)); /* Initialize mask */ + + /* This should point to the msbit of e */ + assert((*e & bitpos) != 0); + + /* + * Pre-load the window. Becuase the window size is + * never larger than the exponent size, there is no need to + * detect running off the end of e in here. + * + * The read-ahead is controlled by elen and the bitpos mask. + * Note that this is *ahead* of ebits, which tracks the + * most significant end of the window. The purpose of this + * initialization is to get the two wbits+1 bits apart, + * like they should be. + * + * Note that bitpos and e1len together keep track of the + * lookahead read pointer in the exponent that is used here. + */ + buf = 0; + for (i = 0; i <= wbits; i++) { + buf = (buf << 1) | ((*e & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e++,e--); + bitpos = (BNWORD32)1 << (32-1); + elen--; + } + } + assert(buf & tblmask); + + /* + * Set the pending multiply positions to a location that will + * never be encountered, thus ensuring that nothing will happen + * until the need for a multiply appears and one is scheduled. + */ + multpos = ebits; /* A NULL value */ + mult = 0; /* Force a crash if we use these */ + + /* + * Okay, now begins the real work. The first step is + * slightly magic, so it's done outside the main loop, + * but it's very similar to what's inside. + */ + ebits--; /* Start processing the first bit... */ + isone = 1; + + /* + * This is just like the multiply in the loop, except that + * - We know the msbit of buf is set, and + * - We have the extra value n^2 floating around. + * So, do the usual computation, and if the result is that + * the buffer should be multiplied by n^1 immediately + * (which we'd normally then square), we multiply it + * (which reduces to a copy, which reduces to setting a flag) + * by n^2 and skip the squaring. Thus, we do the + * multiply and the squaring in one step. + */ + assert(buf & tblmask); + multpos = ebits - wbits; + while ((buf & 1) == 0) { + buf >>= 1; + multpos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(multpos <= ebits); + mult = table[buf>>1]; + buf = 0; + + /* Special case: use already-computed value sitting in buffer */ + if (multpos == ebits) + isone = 0; + + /* + * At this point, the buffer (which is the high half of b) holds + * either 1 (implicitly, as the "isone" flag is set), or n^2. + */ + + /* + * The main loop. The procedure is: + * - Advance the window + * - If the most-significant bit of the window is set, + * schedule a multiply for the appropriate time in the + * future (may be immediately) + * - Perform any pending multiples + * - Check for termination + * - Square the buffer + * + * At any given time, the acumulated product is held in + * the high half of b. + */ + for (;;) { + ebits--; + + /* Advance the window */ + assert(buf < tblmask); + buf <<= 1; + /* + * This reads ahead of the current exponent position + * (controlled by ebits), so we have to be able to read + * past the lsb of the exponents without error. + */ + if (elen) { + buf |= ((*e & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e++,e--); + bitpos = (BNWORD32)1 << (32-1); + elen--; + } + } + + /* Examine the window for pending multiplies */ + if (buf & tblmask) { + multpos = ebits - wbits; + while ((buf & 1) == 0) { + buf >>= 1; + multpos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(multpos <= ebits); + mult = table[buf>>1]; + buf = 0; + } + + /* If we have a pending multiply, do it */ + if (ebits == multpos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_32(t, mult, mlen); + isone = 0; + } else { + lbnMontMul_32(a, t, mult, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* Are we done? */ + if (!ebits) + break; + + /* Square the input */ + if (!isone) { + t = BIGLITTLE(b-mlen, b+mlen); + lbnMontSquare_32(a, t, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } /* for (;;) */ + + assert(!isone); + assert(!buf); + + /* DONE! */ + + /* Convert result out of Montgomery form */ + t = BIGLITTLE(b-mlen, b+mlen); + lbnCopy_32(b, t, mlen); + lbnZero_32(t, mlen); + lbnMontReduce_32(b, mod, mlen, inv); + lbnCopy_32(result, t, mlen); + /* + * Clean up - free intermediate storage. + * Do NOT free table[0], which is the result + * buffer. + */ + while (--tblmask) + LBNFREE(table[tblmask], mlen); + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + +/* + * Compute and return n1^e1 * n2^e2 mod "mod". + * result may be either input buffer, or something separate. + * It must be "mlen" words long. + * + * There is a current position in the exponents, which is kept in e1bits. + * (The exponents are swapped if necessary so e1 is the longer of the two.) + * At any given time, the value in the accumulator is + * n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod". + * As e1bits is counted down, this is updated, by squaring it and doing + * any necessary multiplies. + * To decide on the necessary multiplies, two windows, each w1bits+1 bits + * wide, are maintained in buf1 and buf2, which read *ahead* of the + * e1bits position (with appropriate handling of the case when e1bits + * drops below w1bits+1). When the most-significant bit of either window + * becomes set, indicating that something needs to be multiplied by + * the accumulator or it will get out of sync, the window is examined + * to see which power of n1 or n2 to multiply by, and when (possibly + * later, if the power is greater than 1) the multiply should take + * place. Then the multiply and its location are remembered and the + * window is cleared. + * + * If we had every power of n1 in the table, the multiply would always + * be w1bits steps in the future. But we only keep the odd powers, + * so instead of waiting w1bits squarings and then multiplying + * by n1^k, we wait w1bits-k squarings and multiply by n1. + * + * Actually, w2bits can be less than w1bits, but the window is the same + * size, to make it easier to keep track of where we're reading. The + * appropriate number of low-order bits of the window are just ignored. + */ +int +lbnDoubleExpMod_32(BNWORD32 *result, + BNWORD32 const *n1, unsigned n1len, + BNWORD32 const *e1, unsigned e1len, + BNWORD32 const *n2, unsigned n2len, + BNWORD32 const *e2, unsigned e2len, + BNWORD32 *mod, unsigned mlen) +{ + BNWORD32 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n1 */ + BNWORD32 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)]; + /* Table of odd powers of n2 */ + unsigned e1bits, e2bits; /* Exponent bits */ + unsigned w1bits, w2bits; /* Window sizes */ + unsigned tblmask; /* Mask of exponentiation window */ + BNWORD32 bitpos; /* Mask of current look-ahead bit */ + unsigned buf1, buf2; /* Buffer of exponent bits */ + unsigned mult1pos, mult2pos; /* Where to do pending multiply */ + BNWORD32 const *mult1, *mult2; /* What to multiply by */ + unsigned i; /* Loop counter */ + int isone; /* Flag: accum. is implicitly one */ + BNWORD32 *a, *b; /* Working buffers/accumulators */ + BNWORD32 *t; /* Pointer into the working buffers */ + BNWORD32 inv; /* mod^-1 modulo 2^32 */ + + assert(mlen); + assert(n1len <= mlen); + assert(n2len <= mlen); + + /* First, a couple of trivial cases. */ + e1len = lbnNorm_32(e1, e1len); + e2len = lbnNorm_32(e2, e2len); + + /* Ensure that the first exponent is the longer */ + e1bits = lbnBits_32(e1, e1len); + e2bits = lbnBits_32(e2, e2len); + if (e1bits < e2bits) { + i = e1len; e1len = e2len; e2len = i; + i = e1bits; e1bits = e2bits; e2bits = i; + t = (BNWORD32 *)n1; n1 = n2; n2 = t; + t = (BNWORD32 *)e1; e1 = e2; e2 = t; + } + assert(e1bits >= e2bits); + + /* Handle a trivial case */ + if (!e2len) + return lbnExpMod_32(result, n1, n1len, e1, e1len, mod, mlen); + assert(e2bits); + + /* The code below breaks if the exponents aren't at least 2 bits */ + if (e1bits == 1) { + assert(e2bits == 1); + + LBNALLOC(a, n1len+n2len); + if (!a) + return -1; + + lbnMul_32(a, n1, n1len, n2, n2len); + /* Do a direct modular reduction */ + if (n1len + n2len >= mlen) + (void)lbnDiv_32(a+mlen, a, n1len+n2len, mod, mlen); + lbnCopy_32(result, a, mlen); + LBNFREE(a, n1len+n2len); + return 0; + } + + /* Okay, now move the exponent pointers to the most-significant word */ + e1 = BIGLITTLE(e1-e1len, e1+e1len-1); + e2 = BIGLITTLE(e2-e2len, e2+e2len-1); + + /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */ + w1bits = 0; + while (e1bits > bnExpModThreshTable[w1bits]) + w1bits++; + w2bits = 0; + while (e2bits > bnExpModThreshTable[w2bits]) + w2bits++; + + assert(w1bits >= w2bits); + + /* Allocate working storage: two product buffers and the tables. */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert to the appropriate table size: tblmask = 1<<(k-1) */ + tblmask = 1u << w1bits; + /* Use buf2 for its size, temporarily */ + buf2 = 1u << w2bits; + + LBNALLOC(t, mlen); + if (!t) { + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + return -1; + } + table1[0] = t; + table2[0] = result; + + /* + * Okay, we now have some minimal-sized tables - expand them. + * This is allowed to fail! If so, scale back the table sizes + * and proceed. We allocate both tables at the same time + * so if it fails partway through, they'll both be a reasonable + * size rather than one huge and one tiny. + * When i passes buf2 (the number of entries in the e2 window, + * which may be less than the number of entries in the e1 window), + * stop allocating e2 space. + */ + for (i = 1; i < tblmask; i++) { + LBNALLOC(t, mlen); + if (!t) /* Out of memory! Quit the loop. */ + break; + table1[i] = t; + if (i < buf2) { + LBNALLOC(t, mlen); + if (!t) { + LBNFREE(table1[i], mlen); + break; + } + table2[i] = t; + } + } + + /* If we stopped, with i < tblmask, shrink the tables appropriately */ + while (tblmask > i) { + w1bits--; + tblmask >>= 1; + } + /* Free up our overallocations */ + while (--i > tblmask) { + if (i < buf2) + LBNFREE(table2[i], mlen); + LBNFREE(table1[i], mlen); + } + /* And shrink the second window too, if needed */ + if (w2bits > w1bits) { + w2bits = w1bits; + buf2 = tblmask; + } + + /* + * From now on, use the w2bits variable for the difference + * between w1bits and w2bits. + */ + w2bits = w1bits-w2bits; + + /* Okay, fill in the tables */ + + /* Compute the necessary modular inverse */ + inv = lbnMontInv1_32(mod[BIGLITTLE(-1,0)]); /* LSW of modulus */ + + /* Convert n1 to Montgomery form */ + + /* Move n1 up "mlen" words into a */ + t = BIGLITTLE(a-mlen, a+mlen); + lbnCopy_32(t, n1, n1len); + lbnZero_32(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_32(t, a, mlen+n1len, mod, mlen); + /* Copy into first table entry */ + lbnCopy_32(table1[0], a, mlen); + + /* Square a into b */ + lbnMontSquare_32(b, a, mod, mlen, inv); + + /* Use high half of b to initialize the first table */ + t = BIGLITTLE(b-mlen, b+mlen); + for (i = 1; i < tblmask; i++) { + lbnMontMul_32(a, t, table1[i-1], mod, mlen, inv); + lbnCopy_32(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen); + } + + /* Convert n2 to Montgomery form */ + + t = BIGLITTLE(a-mlen, a+mlen); + /* Move n2 up "mlen" words into a */ + lbnCopy_32(t, n2, n2len); + lbnZero_32(a, mlen); + /* Do the division - lose the quotient into the high-order words */ + (void)lbnDiv_32(t, a, mlen+n2len, mod, mlen); + /* Copy into first table entry */ + lbnCopy_32(table2[0], a, mlen); + + /* Square it into a */ + lbnMontSquare_32(a, table2[0], mod, mlen, inv); + /* Copy to b, low half */ + lbnCopy_32(b, t, mlen); + + /* Use b to initialize the second table */ + for (i = 1; i < buf2; i++) { + lbnMontMul_32(a, b, table2[i-1], mod, mlen, inv); + lbnCopy_32(table2[i], t, mlen); + } + + /* + * Okay, a recap: at this point, the low part of b holds + * n2^2, the high part holds n1^2, and the tables are + * initialized with the odd powers of n1 and n2 from 1 + * through 2*tblmask-1 and 2*buf2-1. + * + * We might use those squares in b later, or we might not. + */ + + /* Initialze the fetch pointer */ + bitpos = (BNWORD32)1 << ((e1bits-1) & (32-1)); /* Initialize mask */ + + /* This should point to the msbit of e1 */ + assert((*e1 & bitpos) != 0); + + /* + * Pre-load the windows. Becuase the window size is + * never larger than the exponent size, there is no need to + * detect running off the end of e1 in here. + * + * The read-ahead is controlled by e1len and the bitpos mask. + * Note that this is *ahead* of e1bits, which tracks the + * most significant end of the window. The purpose of this + * initialization is to get the two w1bits+1 bits apart, + * like they should be. + * + * Note that bitpos and e1len together keep track of the + * lookahead read pointer in the exponent that is used here. + * e2len is not decremented, it is only ever compared with + * e1len as *that* is decremented. + */ + buf1 = buf2 = 0; + for (i = 0; i <= w1bits; i++) { + buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0); + if (e1len <= e2len) + buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e1++,e1--); + if (e1len <= e2len) + BIGLITTLE(e2++,e2--); + bitpos = (BNWORD32)1 << (32-1); + e1len--; + } + } + assert(buf1 & tblmask); + + /* + * Set the pending multiply positions to a location that will + * never be encountered, thus ensuring that nothing will happen + * until the need for a multiply appears and one is scheduled. + */ + mult1pos = mult2pos = e1bits; /* A NULL value */ + mult1 = mult2 = 0; /* Force a crash if we use these */ + + /* + * Okay, now begins the real work. The first step is + * slightly magic, so it's done outside the main loop, + * but it's very similar to what's inside. + */ + isone = 1; /* Buffer is implicitly 1, so replace * by copy */ + e1bits--; /* Start processing the first bit... */ + + /* + * This is just like the multiply in the loop, except that + * - We know the msbit of buf1 is set, and + * - We have the extra value n1^2 floating around. + * So, do the usual computation, and if the result is that + * the buffer should be multiplied by n1^1 immediately + * (which we'd normally then square), we multiply it + * (which reduces to a copy, which reduces to setting a flag) + * by n1^2 and skip the squaring. Thus, we do the + * multiply and the squaring in one step. + */ + assert(buf1 & tblmask); + mult1pos = e1bits - w1bits; + while ((buf1 & 1) == 0) { + buf1 >>= 1; + mult1pos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(mult1pos <= e1bits); + mult1 = table1[buf1>>1]; + buf1 = 0; + + /* Special case: use already-computed value sitting in buffer */ + if (mult1pos == e1bits) + isone = 0; + + /* + * The first multiply by a power of n2. Similar, but + * we might not even want to schedule a multiply if e2 is + * shorter than e1, and the window might be shorter so + * we have to leave the low w2bits bits alone. + */ + if (buf2 & tblmask) { + /* Remember low-order bits for later */ + i = buf2 & ((1u << w2bits) - 1); + buf2 >>= w2bits; + mult2pos = e1bits - w1bits + w2bits; + while ((buf2 & 1) == 0) { + buf2 >>= 1; + mult2pos++; + } + assert(mult2pos <= e1bits); + mult2 = table2[buf2>>1]; + buf2 = i; + + if (mult2pos == e1bits) { + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + lbnCopy_32(t, b, mlen); /* Copy low to high */ + isone = 0; + } else { + lbnMontMul_32(a, t, b, mod, mlen, inv); + t = a; a = b; b = t; + } + } + } + + /* + * At this point, the buffer (which is the high half of b) + * holds either 1 (implicitly, as the "isone" flag is set), + * n1^2, n2^2 or n1^2 * n2^2. + */ + + /* + * The main loop. The procedure is: + * - Advance the windows + * - If the most-significant bit of a window is set, + * schedule a multiply for the appropriate time in the + * future (may be immediately) + * - Perform any pending multiples + * - Check for termination + * - Square the buffers + * + * At any given time, the acumulated product is held in + * the high half of b. + */ + for (;;) { + e1bits--; + + /* Advance the windows */ + assert(buf1 < tblmask); + buf1 <<= 1; + assert(buf2 < tblmask); + buf2 <<= 1; + /* + * This reads ahead of the current exponent position + * (controlled by e1bits), so we have to be able to read + * past the lsb of the exponents without error. + */ + if (e1len) { + buf1 |= ((*e1 & bitpos) != 0); + if (e1len <= e2len) + buf2 |= ((*e2 & bitpos) != 0); + bitpos >>= 1; + if (!bitpos) { + BIGLITTLE(e1++,e1--); + if (e1len <= e2len) + BIGLITTLE(e2++,e2--); + bitpos = (BNWORD32)1 << (32-1); + e1len--; + } + } + + /* Examine the first window for pending multiplies */ + if (buf1 & tblmask) { + mult1pos = e1bits - w1bits; + while ((buf1 & 1) == 0) { + buf1 >>= 1; + mult1pos++; + } + /* Intermediates can wrap, but final must NOT */ + assert(mult1pos <= e1bits); + mult1 = table1[buf1>>1]; + buf1 = 0; + } + + /* + * Examine the second window for pending multiplies. + * Window 2 can be smaller than window 1, but we + * keep the same number of bits in buf2, so we need + * to ignore any low-order bits in the buffer when + * computing what to multiply by, and recompute them + * later. + */ + if (buf2 & tblmask) { + /* Remember low-order bits for later */ + i = buf2 & ((1u << w2bits) - 1); + buf2 >>= w2bits; + mult2pos = e1bits - w1bits + w2bits; + while ((buf2 & 1) == 0) { + buf2 >>= 1; + mult2pos++; + } + assert(mult2pos <= e1bits); + mult2 = table2[buf2>>1]; + buf2 = i; + } + + + /* If we have a pending multiply for e1, do it */ + if (e1bits == mult1pos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_32(t, mult1, mlen); + isone = 0; + } else { + lbnMontMul_32(a, t, mult1, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* If we have a pending multiply for e2, do it */ + if (e1bits == mult2pos) { + /* Multiply by the table entry remembered previously */ + t = BIGLITTLE(b-mlen, b+mlen); + if (isone) { + /* Multiply by 1 is a trivial case */ + lbnCopy_32(t, mult2, mlen); + isone = 0; + } else { + lbnMontMul_32(a, t, mult2, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } + + /* Are we done? */ + if (!e1bits) + break; + + /* Square the buffer */ + if (!isone) { + t = BIGLITTLE(b-mlen, b+mlen); + lbnMontSquare_32(a, t, mod, mlen, inv); + /* Swap a and b */ + t = a; a = b; b = t; + } + } /* for (;;) */ + + assert(!isone); + assert(!buf1); + assert(!buf2); + + /* DONE! */ + + /* Convert result out of Montgomery form */ + t = BIGLITTLE(b-mlen, b+mlen); + lbnCopy_32(b, t, mlen); + lbnZero_32(t, mlen); + lbnMontReduce_32(b, mod, mlen, inv); + lbnCopy_32(result, t, mlen); + + /* Clean up - free intermediate storage */ + buf2 = tblmask >> w2bits; + while (--tblmask) { + if (tblmask < buf2) + LBNFREE(table2[tblmask], mlen); + LBNFREE(table1[tblmask], mlen); + } + t = table1[0]; + LBNFREE(t, mlen); + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + +/* + * 2^exp (mod mod). This is an optimized version for use in Fermat + * tests. The input value of n is ignored; it is returned with + * "mlen" words valid. + */ +int +lbnTwoExpMod_32(BNWORD32 *n, BNWORD32 const *exp, unsigned elen, + BNWORD32 *mod, unsigned mlen) +{ + unsigned e; /* Copy of high words of the exponent */ + unsigned bits; /* Assorted counter of bits */ + BNWORD32 const *bitptr; + BNWORD32 bitword, bitpos; + BNWORD32 *a, *b, *a1; + BNWORD32 inv; + + assert(mlen); + + bitptr = BIGLITTLE(exp-elen, exp+elen-1); + bitword = *bitptr; + assert(bitword); + + /* Clear n for future use. */ + lbnZero_32(n, mlen); + + bits = lbnBits_32(exp, elen); + + /* First, a couple of trivial cases. */ + if (bits <= 1) { + /* 2 ^ 0 == 1, 2 ^ 1 == 2 */ + BIGLITTLE(n[-1],n[0]) = (BNWORD32)1<<elen; + return 0; + } + + /* Set bitpos to the most significant bit */ + bitpos = (BNWORD32)1 << ((bits-1) & (32-1)); + + /* Now, count the bits in the modulus. */ + bits = lbnBits_32(mod, mlen); + assert(bits > 1); /* a 1-bit modulus is just stupid... */ + + /* + * We start with 1<<e, where "e" is as many high bits of the + * exponent as we can manage without going over the modulus. + * This first loop finds "e". + */ + e = 1; + while (elen) { + /* Consume the first bit */ + bitpos >>= 1; + if (!bitpos) { + if (!--elen) + break; + bitword = BIGLITTLE(*++bitptr,*--bitptr); + bitpos = (BNWORD32)1<<(32-1); + } + e = (e << 1) | ((bitpos & bitword) != 0); + if (e >= bits) { /* Overflow! Back out. */ + e >>= 1; + break; + } + } + /* + * The bit in "bitpos" being examined by the bit buffer has NOT + * been consumed yet. This may be past the end of the exponent, + * in which case elen == 1. + */ + + /* Okay, now, set bit "e" in n. n is already zero. */ + inv = (BNWORD32)1 << (e & (32-1)); + e /= 32; + BIGLITTLE(n[-e-1],n[e]) = inv; + /* + * The effective length of n in words is now "e+1". + * This is used a little bit later. + */ + + if (!elen) + return 0; /* That was easy! */ + + /* + * We have now processed the first few bits. The next step + * is to convert this to Montgomery form for further squaring. + */ + + /* Allocate working storage: two product buffers */ + LBNALLOC(a, 2*mlen); + if (!a) + return -1; + LBNALLOC(b, 2*mlen); + if (!b) { + LBNFREE(a, 2*mlen); + return -1; + } + + /* Convert n to Montgomery form */ + inv = BIGLITTLE(mod[-1],mod[0]); /* LSW of modulus */ + assert(inv & 1); /* Modulus must be odd */ + inv = lbnMontInv1_32(inv); + /* Move n (length e+1, remember?) up "mlen" words into b */ + /* Note that we lie about a1 for a bit - it's pointing to b */ + a1 = BIGLITTLE(b-mlen,b+mlen); + lbnCopy_32(a1, n, e+1); + lbnZero_32(b, mlen); + /* Do the division - dump the quotient into the high-order words */ + (void)lbnDiv_32(a1, b, mlen+e+1, mod, mlen); + /* + * Now do the first squaring and modular reduction to put + * the number up in a1 where it belongs. + */ + lbnMontSquare_32(a, b, mod, mlen, inv); + /* Fix up a1 to point to where it should go. */ + a1 = BIGLITTLE(a-mlen,a+mlen); + + /* + * Okay, now, a1 holds the number being accumulated, and + * b is a scratch register. Start working: + */ + for (;;) { + /* + * Is the bit set? If so, double a1 as well. + * A modular doubling like this is very cheap. + */ + if (bitpos & bitword) { + /* + * Double the number. If there was a carry out OR + * the result is greater than the modulus, subract + * the modulus. + */ + if (lbnDouble_32(a1, mlen) || + lbnCmp_32(a1, mod, mlen) > 0) + (void)lbnSubN_32(a1, mod, mlen); + } + + /* Advance to the next exponent bit */ + bitpos >>= 1; + if (!bitpos) { + if (!--elen) + break; /* Done! */ + bitword = BIGLITTLE(*++bitptr,*--bitptr); + bitpos = (BNWORD32)1<<(32-1); + } + + /* + * The elen/bitword/bitpos bit buffer is known to be + * non-empty, i.e. there is at least one more unconsumed bit. + * Thus, it's safe to square the number. + */ + lbnMontSquare_32(b, a1, mod, mlen, inv); + /* Rename result (in b) back to a (a1, really). */ + a1 = b; b = a; a = a1; + a1 = BIGLITTLE(a-mlen,a+mlen); + } + + /* DONE! Just a little bit of cleanup... */ + + /* + * Convert result out of Montgomery form... this is + * just a Montgomery reduction. + */ + lbnCopy_32(a, a1, mlen); + lbnZero_32(a1, mlen); + lbnMontReduce_32(a, mod, mlen, inv); + lbnCopy_32(n, a1, mlen); + + /* Clean up - free intermediate storage */ + LBNFREE(b, 2*mlen); + LBNFREE(a, 2*mlen); + + return 0; /* Success */ +} + + +/* + * Returns a substring of the big-endian array of bytes representation + * of the bignum array based on two parameters, the least significant + * byte number (0 to start with the least significant byte) and the + * length. I.e. the number returned is a representation of + * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). + * + * It is an error if the bignum is not at least buflen + lsbyte bytes + * long. + * + * This code assumes that the compiler has the minimal intelligence + * neded to optimize divides and modulo operations on an unsigned data + * type with a power of two. + */ +void +lbnExtractBigBytes_32(BNWORD32 const *n, unsigned char *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD32 t = 0; /* Needed to shut up uninitialized var warnings */ + unsigned shift; + + lsbyte += buflen; + + shift = (8 * lsbyte) % 32; + lsbyte /= (32/8); /* Convert to word offset */ + BIGLITTLE(n -= lsbyte, n += lsbyte); + + if (shift) + t = BIGLITTLE(n[-1],n[0]); + + while (buflen--) { + if (!shift) { + t = BIGLITTLE(*n++,*--n); + shift = 32; + } + shift -= 8; + *buf++ = (unsigned char)(t>>shift); + } +} + +/* + * Merge a big-endian array of bytes into a bignum array. + * The array had better be big enough. This is + * equivalent to extracting the entire bignum into a + * large byte array, copying the input buffer into the + * middle of it, and converting back to a bignum. + * + * The buf is "len" bytes long, and its *last* byte is at + * position "lsbyte" from the end of the bignum. + * + * Note that this is a pain to get right. Fortunately, it's hardly + * critical for efficiency. + */ +void +lbnInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD32 t = 0; /* Shut up uninitialized varibale warnings */ + + lsbyte += buflen; + + BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); + + /* Load up leading odd bytes */ + if (lsbyte % (32/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte * 8) % 32; + } + + /* The main loop - merge into t, storing at each word boundary. */ + while (buflen--) { + t = (t << 8) | *buf++; + if ((--lsbyte % (32/8)) == 0) + BIGLITTLE(*n++,*--n) = t; + } + + /* Merge odd bytes in t into last word */ + lsbyte = (lsbyte * 8) % 32; + if (lsbyte) { + t <<= lsbyte; + t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); + BIGLITTLE(n[0],n[-1]) = t; + } + + return; +} + +/* + * Returns a substring of the little-endian array of bytes representation + * of the bignum array based on two parameters, the least significant + * byte number (0 to start with the least significant byte) and the + * length. I.e. the number returned is a representation of + * (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen). + * + * It is an error if the bignum is not at least buflen + lsbyte bytes + * long. + * + * This code assumes that the compiler has the minimal intelligence + * neded to optimize divides and modulo operations on an unsigned data + * type with a power of two. + */ +void +lbnExtractLittleBytes_32(BNWORD32 const *n, unsigned char *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD32 t = 0; /* Needed to shut up uninitialized var warnings */ + + BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); + + if (lsbyte % (32/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte % (32/8)) * 8 ; + } + + while (buflen--) { + if ((lsbyte++ % (32/8)) == 0) + t = BIGLITTLE(*--n,*n++); + *buf++ = (unsigned char)t; + t >>= 8; + } +} + +/* + * Merge a little-endian array of bytes into a bignum array. + * The array had better be big enough. This is + * equivalent to extracting the entire bignum into a + * large byte array, copying the input buffer into the + * middle of it, and converting back to a bignum. + * + * The buf is "len" bytes long, and its first byte is at + * position "lsbyte" from the end of the bignum. + * + * Note that this is a pain to get right. Fortunately, it's hardly + * critical for efficiency. + */ +void +lbnInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen) +{ + BNWORD32 t = 0; /* Shut up uninitialized varibale warnings */ + + /* Move to most-significant end */ + lsbyte += buflen; + buf += buflen; + + BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8)); + + /* Load up leading odd bytes */ + if (lsbyte % (32/8)) { + t = BIGLITTLE(*--n,*n++); + t >>= (lsbyte * 8) % 32; + } + + /* The main loop - merge into t, storing at each word boundary. */ + while (buflen--) { + t = (t << 8) | *--buf; + if ((--lsbyte % (32/8)) == 0) + BIGLITTLE(*n++,*--n) = t; + } + + /* Merge odd bytes in t into last word */ + lsbyte = (lsbyte * 8) % 32; + if (lsbyte) { + t <<= lsbyte; + t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]); + BIGLITTLE(n[0],n[-1]) = t; + } + + return; +} + +#ifdef DEADCODE /* This was a precursor to the more flexible lbnExtractBytes */ +/* + * Convert a big-endian array of bytes to a bignum. + * Returns the number of words in the bignum. + * Note the expression "32/8" for the number of bytes per word. + * This is so the word-size adjustment will work. + */ +unsigned +lbnFromBytes_32(BNWORD32 *a, unsigned char const *b, unsigned blen) +{ + BNWORD32 t; + unsigned alen = (blen + (32/8-1))/(32/8); + BIGLITTLE(a -= alen, a += alen); + + while (blen) { + t = 0; + do { + t = t << 8 | *b++; + } while (--blen & (32/8-1)); + BIGLITTLE(*a++,*--a) = t; + } + return alen; +} +#endif + +/* + * Computes the GCD of a and b. Modifies both arguments; + * when it returns, one of them is the GCD and the other is trash. + * The return value is the length of the GCD, with the sign telling + * whether it is in a (+ve) or b (-ve). Both inputs must have + * one extra word of precision. alen must be >= blen. + * + * TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B). + * This is based on taking out common powers of 2, then repeatedly: + * gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted. + * gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced. + * It gets less reduction per step, but the steps are much faster than + * the division case. + */ +int +lbnGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen) +{ + assert(alen >= blen); + + while (blen != 0) { + (void)lbnDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); + alen = lbnNorm_32(a, blen); + if (alen == 0) + return -(int)blen; + (void)lbnDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); + blen = lbnNorm_32(b, alen); + } + return alen; +} + +/* + * Invert "a" modulo "mod" using the extended Euclidean algorithm. + * Note that this only computes one of the cosequences, and uses the + * theorem that the signs flip every step and the absolute value of + * the cosequence values are always bounded by the modulus to avoid + * having to work with negative numbers. + * gcd(a,mod) had better equal 1. Returns 1 if the GCD is NOT 1. + * a must be one word longer than "mod". It is overwritten with the + * result. + * TODO: Use Richard Schroeppel's *much* faster algorithm. + */ +int +lbnInv_32(BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen) +{ + BNWORD32 *b; /* Hold a copy of mod during GCD reduction */ + BNWORD32 *p; /* Temporary for products added to t0 and t1 */ + BNWORD32 *t0, *t1; /* Inverse accumulators */ + BNWORD32 cy; + unsigned blen, t0len, t1len, plen; + + alen = lbnNorm_32(a, alen); + if (!alen) + return 1; /* No inverse */ + + mlen = lbnNorm_32(mod, mlen); + + assert (alen <= mlen); + + /* Inverse of 1 is 1 */ + if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) { + lbnZero_32(BIGLITTLE(a-alen,a+alen), mlen-alen); + return 0; + } + + /* Allocate a pile of space */ + LBNALLOC(b, mlen+1); + if (b) { + /* + * Although products are guaranteed to always be less than the + * modulus, it can involve multiplying two 3-word numbers to + * get a 5-word result, requiring a 6th word to store a 0 + * temporarily. Thus, mlen + 1. + */ + LBNALLOC(p, mlen+1); + if (p) { + LBNALLOC(t0, mlen); + if (t0) { + LBNALLOC(t1, mlen); + if (t1) + goto allocated; + LBNFREE(t0, mlen); + } + LBNFREE(p, mlen+1); + } + LBNFREE(b, mlen+1); + } + return -1; + +allocated: + + /* Set t0 to 1 */ + t0len = 1; + BIGLITTLE(t0[-1],t0[0]) = 1; + + /* b = mod */ + lbnCopy_32(b, mod, mlen); + /* blen = mlen (implicitly) */ + + /* t1 = b / a; b = b % a */ + cy = lbnDiv_32(t1, b, mlen, a, alen); + *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy; + t1len = lbnNorm_32(t1, mlen-alen+1); + blen = lbnNorm_32(b, alen); + + /* while (b > 1) */ + while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD32)1) { + /* q = a / b; a = a % b; */ + if (alen < blen || (alen == blen && lbnCmp_32(a, a, alen) < 0)) + assert(0); + cy = lbnDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen); + *(BIGLITTLE(a-alen-1,a+alen)) = cy; + plen = lbnNorm_32(BIGLITTLE(a-blen,a+blen), alen-blen+1); + assert(plen); + alen = lbnNorm_32(a, blen); + if (!alen) + goto failure; /* GCD not 1 */ + + /* t0 += q * t1; */ + assert(plen+t1len <= mlen+1); + lbnMul_32(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len); + plen = lbnNorm_32(p, plen + t1len); + assert(plen <= mlen); + if (plen > t0len) { + lbnZero_32(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len); + t0len = plen; + } + cy = lbnAddN_32(t0, p, plen); + if (cy) { + if (t0len > plen) { + cy = lbnAdd1_32(BIGLITTLE(t0-plen,t0+plen), + t0len-plen, cy); + } + if (cy) { + BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy; + t0len++; + } + } + + /* if (a <= 1) return a ? t0 : FAIL; */ + if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD32)1) { + if (alen == 0) + goto failure; /* FAIL */ + assert(t0len <= mlen); + lbnCopy_32(a, t0, t0len); + lbnZero_32(BIGLITTLE(a-t0len, a+t0len), mlen-t0len); + goto success; + } + + /* q = b / a; b = b % a; */ + if (blen < alen || (blen == alen && lbnCmp_32(b, a, alen) < 0)) + assert(0); + cy = lbnDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen); + *(BIGLITTLE(b-blen-1,b+blen)) = cy; + plen = lbnNorm_32(BIGLITTLE(b-alen,b+alen), blen-alen+1); + assert(plen); + blen = lbnNorm_32(b, alen); + if (!blen) + goto failure; /* GCD not 1 */ + + /* t1 += q * t0; */ + assert(plen+t0len <= mlen+1); + lbnMul_32(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len); + plen = lbnNorm_32(p, plen + t0len); + assert(plen <= mlen); + if (plen > t1len) { + lbnZero_32(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len); + t1len = plen; + } + cy = lbnAddN_32(t1, p, plen); + if (cy) { + if (t1len > plen) { + cy = lbnAdd1_32(BIGLITTLE(t1-plen,t0+plen), + t1len-plen, cy); + } + if (cy) { + BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy; + t1len++; + } + } + } + + if (!blen) + goto failure; /* gcd(a, mod) != 1 -- FAIL */ + + /* return mod-t1 */ + lbnCopy_32(a, mod, mlen); + assert(t1len <= mlen); + cy = lbnSubN_32(a, t1, t1len); + if (cy) { + assert(mlen > t1len); + cy = lbnSub1_32(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy); + assert(!cy); + } + +success: + LBNFREE(t1, mlen); + LBNFREE(t0, mlen); + LBNFREE(p, mlen+1); + LBNFREE(b, mlen+1); + + return 0; + +failure: + LBNFREE(t1, mlen); + LBNFREE(t0, mlen); + LBNFREE(p, mlen+1); + LBNFREE(b, mlen+1); + + return 1; +} diff --git a/usr/src/lib/libresolv2/common/cylink/lbn32.h b/usr/src/lib/libresolv2/common/cylink/lbn32.h new file mode 100644 index 0000000000..d0347390c2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn32.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef LBN32_H +#define LBN32_H + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "lbn.h" + +#ifndef BNWORD32 +#error 32-bit bignum library requires a 32-bit data type +#endif + +#ifndef lbnCopy_32 +void lbnCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len); +#endif +#ifndef lbnZero_32 +void lbnZero_32(BNWORD32 *num, unsigned len); +#endif +#ifndef lbnNeg_32 +void lbnNeg_32(BNWORD32 *num, unsigned len); +#endif + +#ifndef lbnAdd1_32 +BNWORD32 lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry); +#endif +#ifndef lbnSub1_32 +BNWORD32 lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow); +#endif + +#ifndef lbnAddN_32 +BNWORD32 lbnAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len); +#endif +#ifndef lbnSubN_32 +BNWORD32 lbnSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len); +#endif + +#ifndef lbnCmp_32 +int lbnCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len); +#endif + +#ifndef lbnMulN1_32 +void lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); +#endif +#ifndef lbnMulAdd1_32 +BNWORD32 +lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); +#endif +#ifndef lbnMulSub1_32 +BNWORD32 lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k); +#endif + +#ifndef lbnLshift_32 +BNWORD32 lbnLshift_32(BNWORD32 *num, unsigned len, unsigned shift); +#endif +#ifndef lbnDouble_32 +BNWORD32 lbnDouble_32(BNWORD32 *num, unsigned len); +#endif +#ifndef lbnRshift_32 +BNWORD32 lbnRshift_32(BNWORD32 *num, unsigned len, unsigned shift); +#endif + +#ifndef lbnMul_32 +void lbnMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1, + BNWORD32 const *num2, unsigned len2); +#endif +#ifndef lbnSquare_32 +void lbnSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len); +#endif + +#ifndef lbnNorm_32 +unsigned lbnNorm_32(BNWORD32 const *num, unsigned len); +#endif +#ifndef lbnBits_32 +unsigned lbnBits_32(BNWORD32 const *num, unsigned len); +#endif + +#ifndef lbnExtractBigBytes_32 +void lbnExtractBigBytes_32(BNWORD32 const *bn, unsigned char *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnInsertBigytes_32 +void lbnInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnExtractLittleBytes_32 +void lbnExtractLittleBytes_32(BNWORD32 const *bn, unsigned char *buf, + unsigned lsbyte, unsigned buflen); +#endif +#ifndef lbnInsertLittleBytes_32 +void lbnInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf, + unsigned lsbyte, unsigned buflen); +#endif + +#ifndef lbnDiv21_32 +BNWORD32 lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d); +#endif +#ifndef lbnDiv1_32 +BNWORD32 lbnDiv1_32(BNWORD32 *q, BNWORD32 *rem, + BNWORD32 const *n, unsigned len, BNWORD32 d); +#endif +#ifndef lbnModQ_32 +unsigned lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d); +#endif +#ifndef lbnDiv_32 +BNWORD32 +lbnDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen); +#endif + +#ifndef lbnMontInv1_32 +BNWORD32 lbnMontInv1_32(BNWORD32 const x); +#endif +#ifndef lbnMontReduce_32 +void lbnMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen, + BNWORD32 inv); +#endif +#ifndef lbnToMont_32 +void lbnToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen); +#endif +#ifndef lbnFromMont_32 +void lbnFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len); +#endif + +#ifndef lbnExpMod_32 +int lbnExpMod_32(BNWORD32 *result, BNWORD32 const *n, unsigned nlen, + BNWORD32 const *exp, unsigned elen, BNWORD32 *mod, unsigned mlen); +#endif +#ifndef lbnDoubleExpMod_32 +int lbnDoubleExpMod_32(BNWORD32 *result, + BNWORD32 const *n1, unsigned n1len, BNWORD32 const *e1, unsigned e1len, + BNWORD32 const *n2, unsigned n2len, BNWORD32 const *e2, unsigned e2len, + BNWORD32 *mod, unsigned mlen); +#endif +#ifndef lbnTwoExpMod_32 +int lbnTwoExpMod_32(BNWORD32 *n, BNWORD32 const *exp, unsigned elen, + BNWORD32 *mod, unsigned mlen); +#endif +#ifndef lbnGcd_32 +int lbnGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen); +#endif +#ifndef lbnInv_32 +int lbnInv_32(BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen); +#endif + +#endif /* LBN32_H */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68000.c b/usr/src/lib/libresolv2/common/cylink/lbn68000.c new file mode 100644 index 0000000000..96404d674f --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn68000.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn68000.c - 16-bit bignum primitives for the 68000 (or 68010) processors. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * This was written for Metrowerks C, and while it should be reasonably + * portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2. + * Some 680x0 compilers make d2 callee-save, so instructions to save it + * will have to be added. + * + * This code supports 16 or 32-bit ints, based on UINT_MAX. + * Regardless of UINT_MAX, only bignums up to 64K words (1 million bits) + * are supported. (68k hackers will recognize this as a consequence of + * using dbra.) + * + * These primitives use little-endian word order. + * (The order of bytes within words is irrelevant to this issue.) + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <limits.h> + +#include "lbn.h" /* Should include lbn68000.h */ + +/* + * The Metrowerks C compiler (1.2.2) produces bad 68k code for the + * following input, which happens to be the inner loop of lbnSub1, + * so a few less than critical routines have been recoded in assembly + * to avoid the bug. (Optimizer on or off does not matter.) + * + * unsigned + * decrement(unsigned *num, unsigned len) + * { + * do { + * if ((*num++)-- != 0) + * return 0; + * } while (--len); + * return 1; + * } + */ +asm BNWORD16 +lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow) +{ + movea.l 4(sp),a0 /* num */ +#if UINT_MAX == 0xffff + move.w 10(sp),d0 /* borrow */ +#else + move.w 12(sp),d0 /* borrow */ +#endif + sub.w d0,(a0)+ + bcc done +#if UINT_MAX == 0xffff + move.w 8(sp),d0 /* len */ +#else + move.w 10(sp),d0 /* len */ +#endif + subq.w #2,d0 + bcs done +loop: + subq.w #1,(a0)+ + dbcc d0,loop +done: + moveq.l #0,d0 + addx.w d0,d0 + rts +} + +asm BNWORD16 +lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry) +{ + movea.l 4(sp),a0 /* num */ +#if UINT_MAX == 0xffff + move.w 10(sp),d0 /* carry */ +#else + move.w 12(sp),d0 /* carry */ +#endif + add.w d0,(a0)+ + bcc done +#if UINT_MAX == 0xffff + move.w 8(sp),d0 /* len */ +#else + move.w 10(sp),d0 /* len */ +#endif + subq.w #2,d0 + bcs done +loop: + addq.w #1,(a0)+ + dbcc d0,loop +done: + moveq.l #0,d0 + addx.w d0,d0 + rts +} + +asm void +lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + move.w d3,-(sp) /* 2 bytes of stack frame */ + move.l 2+4(sp),a1 /* out */ + move.l 2+8(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 2+12(sp),d3 /* len */ + move.w 2+14(sp),d2 /* k */ +#else + move.w 2+14(sp),d3 /* len (low 16 bits) */ + move.w 2+16(sp),d2 /* k */ +#endif + + move.w (a0)+,d1 /* First multiply */ + mulu.w d2,d1 + move.w d1,(a1)+ + clr.w d1 + swap d1 + + subq.w #1,d3 /* Setup for loop unrolling */ + lsr.w #1,d3 + bcs.s m16_even + beq.s m16_short + + subq.w #1,d3 /* Set up software pipeline properly */ + move.l d1,d0 + +m16_loop: + move.w (a0)+,d1 + mulu.w d2,d1 + add.l d0,d1 + move.w d1,(a1)+ + clr.w d1 + swap d1 +m16_even: + + move.w (a0)+,d0 + mulu.w d2,d0 + add.l d1,d0 + move.w d0,(a1)+ + clr.w d0 + swap d0 + + dbra d3,m16_loop + + move.w d0,(a1) + move.w (sp)+,d3 + rts +m16_short: + move.w d1,(a1) + move.w (sp)+,d3 + rts +} + + +asm BNWORD16 +lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + move.w d4,-(sp) + clr.w d4 + move.w d3,-(sp) /* 4 bytes of stack frame */ + move.l 4+4(sp),a1 /* out */ + move.l 4+8(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 4+12(sp),d3 /* len */ + move.w 4+14(sp),d2 /* k */ +#else + move.w 4+14(sp),d3 /* len (low 16 bits) */ + move.w 4+16(sp),d2 /* k */ +#endif + + move.w (a0)+,d1 /* First multiply */ + mulu.w d2,d1 + add.w d1,(a1)+ + clr.w d1 + swap d1 + addx.w d4,d1 + + subq.w #1,d3 /* Setup for loop unrolling */ + lsr.w #1,d3 + bcs.s ma16_even + beq.s ma16_short + + subq.w #1,d3 /* Set up software pipeline properly */ + move.l d1,d0 + +ma16_loop: + move.w (a0)+,d1 + mulu.w d2,d1 + add.l d0,d1 + add.w d1,(a1)+ + clr.w d1 + swap d1 + addx.w d4,d1 +ma16_even: + + move.w (a0)+,d0 + mulu.w d2,d0 + add.l d1,d0 + add.w d0,(a1)+ + clr.w d0 + swap d0 + addx.w d4,d0 + + dbra d3,ma16_loop + + move.w (sp)+,d3 + move.w (sp)+,d4 + rts +ma16_short: + move.w (sp)+,d3 + move.l d1,d0 + move.w (sp)+,d4 + rts +} + + + +asm BNWORD16 +lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k) +{ + move.w d4,-(sp) + clr.w d4 + move.w d3,-(sp) /* 4 bytes of stack frame */ + move.l 4+4(sp),a1 /* out */ + move.l 4+8(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 4+12(sp),d3 /* len */ + move.w 4+14(sp),d2 /* k */ +#else + move.w 4+14(sp),d3 /* len (low 16 bits) */ + move.w 4+16(sp),d2 /* k */ +#endif + + move.w (a0)+,d1 /* First multiply */ + mulu.w d2,d1 + sub.w d1,(a1)+ + clr.w d1 + swap d1 + addx.w d4,d1 + + subq.w #1,d3 /* Setup for loop unrolling */ + lsr.w #1,d3 + bcs.s ms16_even + beq.s ms16_short + + subq.w #1,d3 /* Set up software pipeline properly */ + move.l d1,d0 + +ms16_loop: + move.w (a0)+,d1 + mulu.w d2,d1 + add.l d0,d1 + sub.w d1,(a1)+ + clr.w d1 + swap d1 + addx.w d4,d1 +ms16_even: + + move.w (a0)+,d0 + mulu.w d2,d0 + add.l d1,d0 + sub.w d0,(a1)+ + clr.w d0 + swap d0 + addx.w d4,d0 + + dbra d3,ms16_loop + + move.w (sp)+,d3 + move.w (sp)+,d4 + rts +ms16_short: + move.w (sp)+,d3 + move.l d1,d0 + move.w (sp)+,d4 + rts +} + +/* The generic long/short divide doesn't know that nh < d */ +asm BNWORD16 +lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d) +{ + move.l 8(sp),d0 /* nh *and* nl */ + divu.w 12(sp),d0 + move.l 4(sp),a0 + move.w d0,(a0) + clr.w d0 + swap d0 + rts +} + +asm unsigned +lbnModQ_16(BNWORD16 const *n, unsigned len, BNWORD16 d) +{ + move.l 4(sp),a0 /* n */ + moveq.l #0,d1 +#if UINT_MAX == 0xffff + move.w 8(sp),d1 /* len */ + move.w 10(sp),d2 /* d */ +#else + move.w 10(sp),d1 /* len (low 16 bits) */ + move.w 12(sp),d2 /* d */ +#endif + + add.l d1,a0 + add.l d1,a0 /* n += len */ + moveq.l #0,d0 + subq.w #1,d1 + +mq16_loop: + move.w -(a0),d0 /* Assemble remainder and new word */ + divu.w d2,d0 /* Put remainder in high half of d0 */ + dbra d1,mq16_loop + +mq16_done: + clr.w d0 + swap d0 + rts +} + +/* + * Detect if this is a 32-bit processor (68020+ *or* CPU32). + * Both the 68020+ and CPU32 processors (which have 32x32->64-bit + * multiply, what the 32-bit math library wants) support scaled indexed + * addressing. The 68000 and 68010 ignore the scale selection + * bits, treating it as *1 all the time. So a 32-bit processor + * will evaluate -2(a0,a0.w*2) as 1+1*2-2 = 1. + * A 16-bit processor will compute 1+1-2 = 0. + * + * Thus, the return value will indicate whether the chip this is + * running on supports 32x32->64-bit multiply (mulu.l). + */ +asm int +is68020(void) +{ + machine 68020 + lea 1,a0 +#if 0 + lea -2(a0,a0.w*2),a0 /* Metrowerks won't assemble this, arrgh */ +#else + dc.w 0x41f0, 0x82fe +#endif + move.l a0,d0 + rts +} +/* + * Since I had to hand-assemble that fancy addressing mode, I had to study + * up on 680x0 addressing modes. + * A summary of 680x0 addressing modes. + * A 68000 effective address specifies an operand on an instruction, which + * may be a register or in memory. It is made up of a 3-bit mode and a + * 3-bit register specifier. The meanings of the various modes are: + * + * 000 reg - Dn, n specified by "reg" + * 001 reg - An, n specified by "reg" + * 010 reg - (An) + * 011 reg - (An)+ + * 100 reg - -(An) + * 101 reg - d16(An), one 16-bit displacement word follows, sign-extended + * 110 reg - Fancy addressing mode off of An, see extension word below + * 111 000 - abs.W, one 16-bit signed absolute address follows + * 111 001 - abs.L, one 32-bit absolute address follows + * 111 010 - d16(PC), one 16-bit displacemnt word follows, sign-extended + * 111 011 - Fancy addressing mode off of PC, see extension word below + * 111 100 - #immediate, followed by 16 or 32 bits of immediate value + * 111 101 - unused, reserved + * 111 110 - unused, reserved + * 111 111 - unused, reserved + * + * Memory references are to data space, except that PC-relative references + * are to program space, and are read-only. + * + * Fancy addressing modes are followed by a 16-bit extension word, and come + * in "brief" and "full" forms. + * The "brief" form looks like this. Bit 8 is 0 to indicate this form: + * + * 1 1 1 1 1 1 1 + * 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * |A/D| register |L/W| scale | 0 | 8-bit signed displacement | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * The basic effective address specifies a 32-bit base register - A0 through + * A7 or PC (the address of the following instruction). + * The A/D and register fields specify an index register. A/D is 1 for + * address registers, and 0 for data registers. L/W specifies the length + * of the index register, 1 for 32 bits, and 0 for 16 bits (sign-extended). + * The scale field is a left shift amount (0 to 3 bits) to apply to the + * sign-extended index register. The final address is d8(An,Rn.X*SCALE), + * also written (d8,An,Rn.X*SCALE). X is "W" or "L", SCALE is 1, 2, 4 or 8. + * "*1" may be omitted, as may a d8 of 0. + * + * The 68000 supports this form, but only with a scale field of 0. + * It does NOT (says the MC68030 User's Manual MC68030UM/AD, section 2.7) + * decode the scale field and the following format bit. They are treated + * as 0. + * I recall (I don't have the data book handy) that the CPU32 processor + * core used in the 683xx series processors supports variable scales, + * but only the brief extension word form. I suspect it decodes the + * format bit and traps if it is not zero, but I don't recall. + * + * The "full" form (680x0, x >= 2 processors only) looks like this: + * + * 1 1 1 1 1 1 1 + * 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * |A/D| register |L/W| scale | 1 | BS| IS|BD size| 0 | P |OD size| + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * The first 8 bits are interpreted the same way as in the brief form, + * except that bit 8 is set to 1 to indicate the full form. + * BS, Base Suppress, if set, causes a value of 0 to be used in place of + * the base register value. If this is set, the base register + * specified is irrelevant, except that if it is the PC, the fetch is + * still done from program space. The specifier "ZPC" can be used in + * place of "PC" in the effective address mnemonic to represent this + * case. + * IS, Index Suppress, if set, causes a value of 0 to be used in place + * of the scaled index register. In this case, the first 7 bits of the + * extension word are irrelevant. + * BD size specifies the base displacement size. A value of 00 + * in this field is illegal, while 01, 10 and 11 indicate that the + * extension word is followed by 0, 1 or 2 16-bit words of base displacement + * (zero, sign-extended to 32 bits, and most-significant word first, + * respectively) to add to the base register value. + * Bit 3 is unused. + * The P bit is the pre/post indexing bit, and only applies if an outer + * displacement is used. This is explained later. + * OD size specifies the size of an outer displacement. In the simple + * case, this field is set to 00 and the effective address is + * (disp,An,Rn.X*SCALE) or (disp,PC,Rn.X*SCALE). + * In this case the P bit must be 0. Any of those compnents may be + * suppressed, with a BD size of 01, the BS bit, or the IS bit. + * If the OD size is not 00, it encodes an outer displacement in the same + * manner as the BD size, and 0, 1 or 2 16-bit words of outer displacement + * follow the base displacement in the instruction stream. In this case, + * this is a double-indirect addressing mode. The base, base displacement, + * and possibly the index, specify a 32-bit memory word which holds a value + * which is fetched, and the outer displacement and possibly the index are + * added to produce the address of the operand. + * If the P bit is 0, this is pre-indexed, and the index value is added + * before the fetch of the indirect word, producing an effective address + * of ([disp,An,Rn.X*SCALE],disp). If the P bit is 1, the post-indexed case, + * the memory word is fectched from base+base displacement, then the index + * and outer displacement are added to compute the address of the operand. + * This effective address is written ([disp,An],Rn.X*SCALE,disp). + * (In both cases, "An" may also be "PC" or "ZPC".) + * Any of the components may be omitted. If the index is omitted (using the + * IS bit), the P bit is irrelevant, but must be written as 0. + * Thus, legal combinations of IS, P and OD size are: + * 0 0 00 - (disp,An,Rn.X*SCALE), also written disp(An,Rn.X*SCALE) + * 0 0 01 - ([disp,An,Rn.X*SCALE]) + * 0 0 10 - ([disp,An,Rn.X*SCALE],d16) + * 0 0 11 - ([disp,An,Rn.X*SCALE],d32) + * 0 1 01 - ([disp,An],Rn.X*SCALE) + * 0 1 10 - ([disp,An],Rn.X*SCALE,d16) + * 0 1 11 - ([disp,An],Rn.X*SCALE,d32) + * 1 0 00 - (disp,An), also written disp(An) + * 1 0 01 - ([disp,An]) + * 1 0 10 - ([disp,An],d16) + * 1 0 11 - ([disp,An],d32) + */ + +/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68000.h b/usr/src/lib/libresolv2/common/cylink/lbn68000.h new file mode 100644 index 0000000000..ebd667d177 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn68000.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn68000.h - 16-bit bignum primitives for the 68000 (or 68010) processors. + * + * These primitives use little-endian word order. + * (The order of bytes within words is irrelevant.) + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define BN_LITTLE_ENDIAN 1 + +typedef unsigned short bnword16 +#define BNWORD16 bnword16 + +bnword16 lbnSub1_16(bnword16 *num, unsigned len, bnword16 borrow); +bnword16 lbnAdd1_16(bnword16 *num, unsigned len, bnword16 carry); +void lbnMulN1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k); +bnword16 +lbnMulAdd1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k); +bnword16 +lbnMulSub1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k); +bnword16 lbnDiv21_16(bnword16 *q, bnword16 nh, bnword16 nl, bnword16 d); +unsigned lbnModQ_16(bnword16 const *n, unsigned len, bnword16 d); + +int is68020(void); + +/* #define the values to exclude the C versions */ +#define lbnSub1_16 lbnSub1_16 +#define lbnAdd1_16 lbnAdd1_16 +#define lbnMulN1_16 lbnMulN1_16 +#define lbnMulAdd1_16 lbnMulAdd1_16 +#define lbnMulSub1_16 lbnMulSub1_16 +#define lbnDiv21_16 lbnDiv21_16 +#define lbnModQ_16 lbnModQ_16 + +/* Also include the 68020 definitions for 16/32 bit switching versions. */ +#include <lbn68020.h> diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68020.c b/usr/src/lib/libresolv2/common/cylink/lbn68020.c new file mode 100644 index 0000000000..f3562a3463 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn68020.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn68020.c - 32-bit bignum primitives for the 68020+ (0r 683xx) processors. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * This was written for Metrowerks C, and while it should be reasonably + * portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2. + * Some 680x0 compilers make d2 callee-save, so instructions to save it + * will have to be added. + * + * This code supports 16 or 32-bit ints, based on UINT_MAX. + * Regardless of UINT_MAX, only bignums up to 64K words (2 million bits) + * are supported. (68k hackers will recognize this as a consequence of + * using dbra.) + * + * These primitives use little-endian word order. + * (The order of bytes within words is irrelevant to this issue.) + * + * TODO: Schedule this for the 68040's pipeline. (When I get a 68040 manual.) + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <limits.h> + +#include "lbn.h" /* Should include lbn68020.h */ + +/* + * The Metrowerks C compiler (1.2.2) produces bad 68k code for the + * following input, which happens to be the inner loop of lbnSub1, + * so a few less than critical routines have been recoded in assembly + * to avoid the bug. (Optimizer on or off does not matter.) + * + * unsigned + * decrement(unsigned *num, unsigned len) + * { + * do { + * if ((*num++)-- != 0) + * return 0; + * } while (--len); + * return 1; + * } + */ +asm BNWORD32 +lbnSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow) +{ + movea.l 4(sp),a0 /* num */ +#if UINT_MAX == 0xffff + move.l 10(sp),d0 /* borrow */ +#else + move.l 12(sp),d0 /* borrow */ +#endif + sub.l d0,(a0)+ + bcc done +#if UINT_MAX == 0xffff + move.w 8(sp),d0 /* len */ +#else + move.w 10(sp),d0 /* len */ +#endif + subq.w #2,d0 + bcs done +loop: + subq.l #1,(a0)+ + dbcc d0,loop +done: + moveq.l #0,d0 + addx.w d0,d0 + rts +} + +asm BNWORD32 +lbnAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry) +{ + movea.l 4(sp),a0 /* num */ +#if UINT_MAX == 0xffff + move.l 10(sp),d0 /* carry */ +#else + move.l 12(sp),d0 /* carry */ +#endif + add.l d0,(a0)+ + bcc done +#if UINT_MAX == 0xffff + move.w 8(sp),d0 /* len */ +#else + move.w 10(sp),d0 /* len */ +#endif + subq.w #2,d0 + bcs done +loop: + addq.l #1,(a0)+ + dbcc d0,loop +done: + moveq.l #0,d0 + addx.w d0,d0 + rts +} + +asm void +lbnMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + machine 68020 + + movem.l d3-d5,-(sp) /* 12 bytes of extra data */ + moveq.l #0,d4 + move.l 16(sp),a1 /* out */ + move.l 20(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 24(sp),d5 /* len */ + move.l 26(sp),d2 /* k */ +#else + move.w 26(sp),d5 /* len */ + move.l 28(sp),d2 /* k */ +#endif + + move.l (a0)+,d3 /* First multiply */ + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + move.l d3,(a1)+ + + subq.w #1,d5 /* Setup for loop unrolling */ + lsr.w #1,d5 + bcs.s m32_even + beq.s m32_short + + subq.w #1,d5 /* Set up software pipeline properly */ + move.l d1,d0 + +m32_loop: + move.l (a0)+,d3 + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + add.l d0,d3 + addx.l d4,d1 + move.l d3,(a1)+ +m32_even: + + move.l (a0)+,d3 + mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */ + add.l d1,d3 + addx.l d4,d0 + move.l d3,(a1)+ + + dbra d5,m32_loop + + move.l d0,(a1) + movem.l (sp)+,d3-d5 + rts +m32_short: + move.l d1,(a1) + movem.l (sp)+,d3-d5 + rts +} + + +asm BNWORD32 +lbnMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + machine 68020 + movem.l d3-d5,-(sp) /* 12 bytes of extra data */ + moveq.l #0,d4 + move.l 16(sp),a1 /* out */ + move.l 20(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 24(sp),d5 /* len */ + move.l 26(sp),d2 /* k */ +#else + move.w 26(sp),d5 /* len */ + move.l 28(sp),d2 /* k */ +#endif + + move.l (a0)+,d3 /* First multiply */ + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + add.l d3,(a1)+ + addx.l d4,d1 + + subq.w #1,d5 /* Setup for loop unrolling */ + lsr.w #1,d5 + bcs.s ma32_even + beq.s ma32_short + + subq.w #1,d5 /* Set up software pipeline properly */ + move.l d1,d0 + +ma32_loop: + move.l (a0)+,d3 + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + add.l d0,d3 + addx.l d4,d1 + add.l d3,(a1)+ + addx.l d4,d1 +ma32_even: + + move.l (a0)+,d3 + mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */ + add.l d1,d3 + addx.l d4,d0 + add.l d3,(a1)+ + addx.l d4,d0 + + dbra d5,ma32_loop + + movem.l (sp)+,d3-d5 + rts +ma32_short: + move.l d1,d0 + movem.l (sp)+,d3-d5 + rts +} + + +asm BNWORD32 +lbnMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k) +{ + machine 68020 + movem.l d3-d5,-(sp) /* 12 bytes of extra data */ + moveq.l #0,d4 + move.l 16(sp),a1 /* out */ + move.l 20(sp),a0 /* in */ +#if UINT_MAX == 0xffff + move.w 24(sp),d5 /* len */ + move.l 26(sp),d2 /* k */ +#else + move.w 26(sp),d5 /* len */ + move.l 28(sp),d2 /* k */ +#endif + + move.l (a0)+,d3 /* First multiply */ + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + sub.l d3,(a1)+ + addx.l d4,d1 + + subq.w #1,d5 /* Setup for loop unrolling */ + lsr.w #1,d5 + bcs.s ms32_even + beq.s ms32_short + + subq.w #1,d5 /* Set up software pipeline properly */ + move.l d1,d0 + +ms32_loop: + move.l (a0)+,d3 + mulu.l d2,d1:d3 /* dc.w 0x4c02, 0x3401 */ + add.l d0,d3 + addx.l d4,d1 + sub.l d3,(a1)+ + addx.l d4,d1 +ms32_even: + + move.l (a0)+,d3 + mulu.l d2,d0:d3 /* dc.w 0x4c02, 0x3400 */ + add.l d1,d3 + addx.l d4,d0 + sub.l d3,(a1)+ + addx.l d4,d0 + + dbra d5,ms32_loop + + movem.l (sp)+,d3-d5 + rts + +ms32_short: + move.l d1,d0 + movem.l (sp)+,d3-d5 + rts +} + + +asm BNWORD32 +lbnDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d) +{ + machine 68020 + move.l 8(sp),d0 + move.l 12(sp),d1 + move.l 4(sp),a0 + divu.l 16(sp),d0:d1 /* dc.w 0x4c6f, 0x1400, 16 */ + move.l d1,(a0) + rts +} + +asm unsigned +lbnModQ_32(BNWORD32 const *n, unsigned len, unsigned d) +{ + machine 68020 + move.l 4(sp),a0 /* n */ + move.l d3,a1 +#if UINT_MAX == 0xffff + moveq.l #0,d2 + move.w 8(sp),d1 /* len */ + move.w 10(sp),d2 /* d */ +#else + move.w 10(sp),d1 /* len */ + move.l 12(sp),d2 /* d */ +#endif + dc.w 0x41f0, 0x1cfc /* lea -4(a0,d1.L*4),a0 */ + + /* First time, divide 32/32 - may be faster than 64/32 */ + move.l (a0),d3 + divul.l d2,d0:d3 /* dc.w 0x4c02, 0x3000 */ + subq.w #2,d1 + bmi mq32_done + +mq32_loop: + move.l -(a0),d3 + divu.l d2,d0:d3 /* dc.w 0x4c02,0x3400 */ + dbra d1,mq32_loop + +mq32_done: + move.l a1,d3 + rts +} + +/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbn68020.h b/usr/src/lib/libresolv2/common/cylink/lbn68020.h new file mode 100644 index 0000000000..4aff67f5ed --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn68020.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn68020.h - 32-bit bignum primitives for the 68020 (or 683xx) processors. + * + * These primitives use little-endian word order. + * (The order of bytes within words is irrelevant.) + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define BN_LITTLE_ENDIAN 1 + +typedef unsigned long bnword32 +#define BNWORD32 bnword32 + +bnword32 lbnSub1_32(bnword32 *num, unsigned len, bnword32 borrow); +bnword32 lbnAdd1_32(bnword32 *num, unsigned len, bnword32 carry); +void lbnMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +bnword32 +lbnMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +bnword32 +lbnMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +bnword32 lbnDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d); +unsigned lbnModQ_32(bnword32 const *n, unsigned len, unsigned d); + +/* #define the values to exclude the C versions */ +#define lbnSub1_32 lbnSub1_32 +#define lbnAdd1_32 lbnAdd1_32 +#define lbnMulN1_32 lbnMulN1_32 +#define lbnMulAdd1_32 lbnMulAdd1_32 +#define lbnMulSub1_32 lbnMulSub1_32 +#define lbnDiv21_32 lbnDiv21_32 +#define lbnModQ_32 lbnModQ_32 diff --git a/usr/src/lib/libresolv2/common/cylink/lbn80386.h b/usr/src/lib/libresolv2/common/cylink/lbn80386.h new file mode 100644 index 0000000000..10e10e10a5 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn80386.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn80386.h - This file defines the interfaces to the 80386 + * assembly primitives. It is intended to be included in "lbn.h" + * via the "#include BNINCLUDE" mechanism. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define BN_LITTLE_ENDIAN 1 + +typedef unsigned long bnword32; +#define BNWORD32 bnword32 + +/* MS-DOS needs the calling convention described to it. */ +#ifndef MSDOS +#ifdef __MSDOS__ +#define MSDOS 1 +#endif +#endif + +#ifdef MSDOS +#define CDECL __cdecl +#else +#define CDECL /*nothing*/ +#endif + +#ifdef __cplusplus +/* These assembly-language primitives use C names */ +extern "C" { +#endif + +/* Function prototypes for the asm routines */ +void CDECL +lbnMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +#define lbnMulN1_32 lbnMulN1_32 + +bnword32 CDECL +lbnMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +#define lbnMulAdd1_32 lbnMulAdd1_32 + +bnword32 CDECL +lbnMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k); +#define lbnMulSub1_32 lbnMulSub1_32 + +bnword32 CDECL +lbnDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d); +#define lbnDiv21_32 lbnDiv21_32 + +unsigned CDECL +lbnModQ_32(bnword32 const *n, unsigned len, bnword32 d); +#define lbnModQ_32 lbnModQ_32 + +#ifdef __cplusplus +} +#endif + + +#if __GNUC__ +/* + * Use the (massively cool) GNU inline-assembler extension to define + * inline expansions for various operations. + * + * The massively cool part is that the assembler can have inputs + * and outputs, and you specify the operands and which effective + * addresses are legal and they get substituted into the code. + * (For example, some of the code requires a zero. Rather than + * specify an immediate constant, the expansion specifies an operand + * of zero which can be in various places. This lets GCC use an + * immediate zero, or a register which contains zero if it's available.) + * + * The syntax is asm("asm_code" : outputs : inputs : trashed) + * %0, %1 and so on in the asm code are substituted by the operands + * in left-to-right order (outputs, then inputs). + * The operands contain constraint strings and values to use. + * Outputs must be lvalues, inputs may be rvalues. In the constraints: + * "a" means that the operand must be in eax. + * "d" means that the operand must be in edx. + * "g" means that the operand may be any effective address. + * "=" means that the operand is assigned to. + * "%" means that this operand and the following one may be + * interchanged if desirable. + * "bcDSmn" means that the operand must be in ebx, ecx, esi, edi, memory, + * or an immediate constant. (This is almost the same as "g" + * but allowing it in eax wouldn't help because x is already + * assigned there, and it must not be in edx, since edx is + * overwritten by the multiply before a and b are read.) + * + * Note that GCC uses AT&T assembler syntax, which is rather + * different from Intel syntax. The length (b, w or l) of the + * operation is appended to the opcode, and the *second* operand + * is the destination, not the first. Finally, the register names + * are all preceded with "%". (Doubled here because % is a + * magic character.) + */ + +/* (ph<<32) + pl = x*y */ +#define mul32_ppmm(ph,pl,x,y) \ + __asm__("mull %3" : "=d"(ph), "=a"(pl) : "%a"(x), "g"(y)) + +/* (ph<<32) + pl = x*y + a */ +#define mul32_ppmma(ph,pl,x,y,a) \ + __asm__("mull %3\n\t" \ + "addl %4,%%eax\n\t" \ + "adcl %5,%%edx" \ + : "=&d"(ph), "=a"(pl) \ + : "%a"(x), "g"(y), "bcDSmn"(a), "bcDSmn"(0)) + +/* (ph<<32) + pl = x*y + a + b */ +#define mul32_ppmmaa(ph,pl,x,y,a,b) \ + __asm__("mull %3\n\t" \ + "addl %4,%%eax\n\t" \ + "adcl %6,%%edx\n\t" \ + "addl %5,%%eax\n\t" \ + "adcl %6,%%edx" \ + : "=&d"(ph), "=a"(pl) \ + : "%a"(x), "g"(y), "%bcDSmn"(a), "bcDSmn"(b), "bcDSmn"(0)) + +/* q = ((nh<<32) + nl) / d, return remainder. nh guaranteed < d. */ +#undef lbnDiv21_32 +#define lbnDiv21_32(q,nh,nl,d) \ + ({unsigned _; \ + __asm__("divl %4" : "=d"(_), "=a"(*q) : "d"(nh), "a"(nl), "g"(d)); \ + _;}) + +/* No quotient, just return remainder ((nh<<32) + nl) % d */ +#define lbnMod21_32(nh,nl,d) \ + ({unsigned _; \ + __asm__("divl %3" : "=d"(_) : "d"(nh), "a"(nl), "g"(d) : "ax"); \ + _;}) + +#endif /* __GNUC__ */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbn8086.h b/usr/src/lib/libresolv2/common/cylink/lbn8086.h new file mode 100644 index 0000000000..be9c2fab27 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbn8086.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbn8086.h - This file defines the interfaces to the 8086 + * assembly primitives for 16-bit MS-DOS environments. + * It is intended to be included in "lbn.h" + * via the "#include BNINCLUDE" mechanism. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define BN_LITTLE_ENDIAN 1 + +#ifdef __cplusplus +/* These assembly-language primitives use C names */ +extern "C" { +#endif + +/* Set up the appropriate types */ +typedef unsigned short bnword16; +#define BNWORD16 bnword16 +typedef unsigned long bnword32; +#define BNWORD32 bnword32 + +void __cdecl __far +lbnMulN1_16(bnword16 __far *out, bnword16 const __far *in, + unsigned len, bnword16 k); +#define lbnMulN1_16 lbnMulN1_16 + +bnword16 __cdecl __far +lbnMulAdd1_16(bnword16 __far *out, bnword16 const __far *in, + unsigned len, bnword16 k); +#define lbnMulAdd1_16 lbnMulAdd1_16 + +bnword16 __cdecl __far +lbnMulSub1_16(bnword16 __far *out, bnword16 const __far *in, + unsigned len, bnword16 k); +#define lbnMulSub1_16 lbnMulSub1_16 + +bnword16 __cdecl __far +lbnDiv21_16(bnword16 __far *q, bnword16 nh, bnword16 nl, bnword16 d); +#define lbnDiv21_16 lbnDiv21_16 + +bnword16 __cdecl __far +lbnModQ_16(bnword16 const __far *n, unsigned len, bnword16 d); +#define lbnModQ_16 lbnModQ_16 + + + +void __cdecl __far +lbnMulN1_32(bnword32 __far *out, bnword32 const __far *in, + unsigned len, bnword32 k); +#define lbnMulN1_32 lbnMulN1_32 + +bnword32 __cdecl __far +lbnMulAdd1_32(bnword32 __far *out, bnword32 const __far *in, + unsigned len, bnword32 k); +#define lbnMulAdd1_32 lbnMulAdd1_32 + +bnword32 __cdecl __far +lbnMulSub1_32(bnword32 __far *out, bnword32 const __far *in, + unsigned len, bnword32 k); +#define lbnMulSub1_32 lbnMulSub1_32 + +bnword32 __cdecl __far +lbnDiv21_32(bnword32 __far *q, bnword32 nh, bnword32 nl, bnword32 d); +#define lbnDiv21_32 lbnDiv21_32 + +bnword16 __cdecl __far +lbnModQ_32(bnword32 const __far *n, unsigned len, bnword32 d); +#define lbnModQ_32 lbnModQ_32 + +int __cdecl __far not386(void); + +#ifdef __cplusplus +} +#endif diff --git a/usr/src/lib/libresolv2/common/cylink/lbnmem.c b/usr/src/lib/libresolv2/common/cylink/lbnmem.c new file mode 100644 index 0000000000..ebb44a2aae --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbnmem.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/* + * lbnmem.c - low-level bignum memory handling. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c. + * + * Note that in all cases, the pointers passed around + * are pointers to the *least* significant end of the word. + * On big-endian machines, these are pointers to the *end* + * of the allocated range. + * + * BNSECURE is a simple level of security; for more security + * change these function to use locked unswappable memory. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#ifndef HAVE_CONFIG_H +#define HAVE_CONFIG_H 0 +#endif +#if HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Some compilers complain about #if FOO if FOO isn't defined, + * so do the ANSI-mandated thing explicitly... + */ +#ifndef NO_STDLIB_H +#define NO_STDLIB_H 0 +#endif +#ifndef NO_STRING_H +#define NO_STRING_H 0 +#endif +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 0 +#endif +#ifndef NEED_MEMORY_H +#define NEED_MEMORY_H 0 +#endif + +#if !NO_STDLIB_H +#include <stdlib.h> /* For malloc() & co. */ +#else +void *malloc(); +void *realloc(); +void free(); +#endif + +#if !NO_STRING_H +#include <string.h> /* For memset */ +#elif HAVE_STRINGS_H +#include <strings.h> +#endif +#if NEED_MEMORY_H +#include <memory.h> +#endif + +#ifndef DBMALLOC +#define DBMALLOC 0 +#endif +#if DBMALLOC +/* Development debugging */ +#include "../dbmalloc/malloc.h" +#endif + +#include "lbn.h" +#include "lbnmem.h" + +#include "kludge.h" + +#ifndef lbnMemWipe +void +lbnMemWipe(void *ptr, unsigned bytes) +{ + memset(ptr, 0, bytes); +} +#define lbnMemWipe(ptr, bytes) memset(ptr, 0, bytes) +#endif + +#ifndef lbnMemAlloc +void * +lbnMemAlloc(unsigned bytes) +{ + return malloc(bytes); +} +#define lbnMemAlloc(bytes) malloc(bytes) +#endif + +#ifndef lbnMemFree +void +lbnMemFree(void *ptr, unsigned bytes) +{ + lbnMemWipe(ptr, bytes); + free(ptr); +} +#endif + +#ifndef lbnRealloc +#if defined(lbnMemRealloc) || !BNSECURE +void * +lbnRealloc(void *ptr, unsigned oldbytes, unsigned newbytes) +{ + if (ptr) { + BIG(ptr = (char *)ptr - oldbytes;) + if (newbytes < oldbytes) + memmove(ptr, (char *)ptr + oldbytes-newbytes, oldbytes); + } +#ifdef lbnMemRealloc + ptr = lbnMemRealloc(ptr, oldbytes, newbytes); +#else + ptr = realloc(ptr, newbytes); +#endif + if (ptr) { + if (newbytes > oldbytes) + memmove((char *)ptr + newbytes-oldbytes, ptr, oldbytes); + BIG(ptr = (char *)ptr + newbytes;) + } + + return ptr; +} + +#else /* BNSECURE */ + +void * +lbnRealloc(void *oldptr, unsigned oldbytes, unsigned newbytes) +{ + void *newptr = lbnMemAlloc(newbytes); + + if (!newptr) + return newptr; + if (!oldptr) + return BIGLITTLE((char *)newptr+newbytes, newptr); + + /* + * The following copies are a bit non-obvious in the big-endian case + * because one of the pointers points to the *end* of allocated memory. + */ + if (newbytes > oldbytes) { /* Copy all of old into part of new */ + BIG(newptr = (char *)newptr + newbytes;) + BIG(oldptr = (char *)oldptr - oldbytes;) + memcpy(BIGLITTLE((char *)newptr-oldbytes, newptr), oldptr, + oldbytes); + } else { /* Copy part of old into all of new */ + memcpy(newptr, BIGLITTLE((char *)oldptr-newbytes, oldptr), + newbytes); + BIG(newptr = (char *)newptr + newbytes;) + BIG(oldptr = (char *)oldptr - oldbytes;) + } + + lbnMemFree(oldptr, oldbytes); + return newptr; +} +#endif /* BNSECURE */ +#endif /* !lbnRealloc */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbnmem.h b/usr/src/lib/libresolv2/common/cylink/lbnmem.h new file mode 100644 index 0000000000..8a86eeaf0e --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbnmem.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Operations on the usual buffers of bytes + */ +#ifndef BNSECURE +#define BNSECURE 1 +#endif + +/* + * These operations act on buffers of memory, just like malloc & free. + * One exception: it is not legal to pass a NULL pointer to lbnMemFree. + */ + +#ifndef lbnMemAlloc +void *lbnMemAlloc(unsigned bytes); +#endif + +#ifndef lbnMemFree +void lbnMemFree(void *ptr, unsigned bytes); +#endif + +/* This wipes out a buffer of bytes if necessary needed. */ + +#ifndef lbnMemWipe +#if BNSECURE +void lbnMemWipe(void *ptr, unsigned bytes); +#else +#define lbnMemWipe(ptr, bytes) (void)(ptr,bytes) +#endif +#endif /* !lbnMemWipe */ + +/* + * lbnRealloc is NOT like realloc(); it's endian-sensitive! + * If lbnMemRealloc is #defined, lbnRealloc will be defined in terms of it. + * It is legal to pass a NULL pointer to lbnRealloc, although oldbytes + * will always be sero. + */ +#ifndef lbnRealloc +void *lbnRealloc(void *ptr, unsigned oldbytes, unsigned newbytes); +#endif + + +/* + * These macros are the ones actually used most often in the math library. + * They take and return pointers to the *end* of the given buffer, and + * take sizes in terms of words, not bytes. + * + * Note that LBNALLOC takes the pointer as an argument instead of returning + * the value. + * + * Note also that these macros are only useable if you have included + * lbn.h (for the BIG and BIGLITTLE macros), which this file does NOT include. + */ + +#define LBNALLOC(p,words) BIGLITTLE( \ + if ( ((p) = lbnMemAlloc((words)*sizeof*(p))) != 0) (p) += (words), \ + (p) = lbnMemAlloc((words) * sizeof*(p)) \ + ) +#define LBNFREE(p,words) lbnMemFree((p) BIG(-(words)), (words) * sizeof*(p)) +#define LBNREALLOC(p,old,new) \ + lbnRealloc(p, (old) * sizeof*(p), (new) * sizeof*(p)) +#define LBNWIPE(p,words) lbnMemWipe((p) BIG(-(words)), (words) * sizeof*(p)) + diff --git a/usr/src/lib/libresolv2/common/cylink/lbnppc.c b/usr/src/lib/libresolv2/common/cylink/lbnppc.c new file mode 100644 index 0000000000..15eef0e28e --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbnppc.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "lbnppc.h" + +/* + * lbnppc.c - Assembly primitives for the bignum library, PowerPC version. + * + * Copyright (c) 1995 Colin Plumb. All rights reserved. + * For licensing and other legal details, see the file legal.c + * + * Register usage during function calls is: + * r0 - volatile + * r1 - stack pointer, preserved + * r2 - TOC pointer, preserved + * r3 - First argument and return value register + * r4-r10 - More argument registers, volatile + * r11-r12 - Volatile + * r13-r31 - Preserved + * LR, CTR, XER and MQ are all volatile. + * LR holds return address on entry. + * + * On the PPC 601, unrolling the loops more doesn't seem to speed things + * up at all. I'd be curious if other chips differed. + */ +#if __MWERKS__ < 0x800 + +#include "ppcasm.h" /* PowerPC assembler */ + +/* + * MulN1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + */ +static const unsigned mulN1[] = { + PPC_LWZ(7,4,0), /* Load first word of in in r7 */ + PPC_MULLW(8,7,6), /* Low half of multiply in r8 */ + PPC_MTCTR(5), /* Move len into CTR */ + PPC_ADDIC(0,0,0), /* Clear carry bit for loop */ + PPC_MULHWU(5,7,6), /* High half of multiply in r5 */ + PPC_STW(8,3,0), + PPC_BC(18,31,7), /* Branch to Label if --ctr == 0 */ +/* Loop: */ + PPC_LWZU(7,4,4), /* r7 = *++in */ + PPC_MULLW(8,7,6), /* r8 = low word of product */ + PPC_ADDE(8,8,5), /* Add carry word r5 and bit CF to r8 */ + PPC_STWU(8,3,4), /* *++out = r8 */ + PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */ + PPC_BC(16,31,-5), /* Branch to Loop if --ctr != 0 */ +/* Label: */ + PPC_ADDZE(5,5), /* Add carry flag to r5 */ + PPC_STW(5,3,4), /* out[1] = r5 */ + PPC_BLR() +}; + +/* + * MulAdd1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + */ +static unsigned const mulAdd1[] = { + PPC_LWZ(7,4,0), /* Load first word of in in r7 */ + PPC_LWZ(0,3,0), /* Load first word of out into r0 */ + PPC_MULLW(8,7,6), /* Low half of multiply in r8 */ + PPC_MTCTR(5), /* Move len into CTR */ + PPC_MULHWU(5,7,6), /* High half of multiply in r5 */ + PPC_ADDC(8,8,0), /* r8 = r8 + r0 */ + PPC_STW(8,3,0), /* Store result to memory */ + PPC_BC(18,31,10), /* Branch to Label if --ctr == 0 */ +/* Loop: */ + PPC_LWZU(7,4,4), /* r7 = *++in */ + PPC_LWZU(0,3,4), /* r0 = *++out */ + PPC_MULLW(8,7,6), /* r8 = low word of product */ + PPC_ADDE(8,8,5), /* Add carry word r5 and carry bit CF to r8 */ + PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */ + PPC_ADDZE(5,5), /* Add carry bit from low add to r5 */ + PPC_ADDC(8,8,0), /* r8 = r8 + r0 */ + PPC_STW(8,3,0), /* *out = r8 */ + PPC_BC(16,31,-8), /* Branch to Loop if --ctr != 0 */ +/* Label: */ + PPC_ADDZE(3,5), /* Add carry flag to r5 and move to r3 */ + PPC_BLR() +}; + +/* + * MulSub1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + * + * Multiply and subtract is rather a pain. If the subtract of the + * low word of the product from out[i] generates a borrow, we want to + * increment the carry word (initially in the range 0..0xfffffffe). + * However, the PPC's carry bit CF is *clear* after a subtract, so + * we want to add (1-CF) to the carry word. This is done using two + * instructions: + * + * SUBFME, subtract from minus one extended. This computes + * rD = ~rS + 0xffffffff + CF. Since rS is from 0 to 0xfffffffe, + * ~rS is from 1 through 0xffffffff, and the sum with 0xffffffff+CF is + * from 0 through 0xfffffffff, setting the carry flag unconditionally, and + * NOR, which is used as a bitwise invert NOT instruction. + * + * The SUBFME performs the computation rD = ~rS + 0xffffffff + CF, + * = (-rS - 1) + (CF - 1) = -(rS - CF + 1) - 1 = ~(rS + 1-CF), + * which is the bitwise complement of the value we want. + * We want to add the complement of that result to the low word of the + * product, which is just what a subtract would do, if only we could get + * the carry flag clear. But it's always set, except for SUBFE, and the + * operation we just performed unconditionally *sets* the carry flag. Ugh. + * So find the complement in a separate instruction. + */ +static unsigned const mulSub1[] = { + PPC_LWZ(7,4,0), /* Load first word of in in r7 */ + PPC_LWZ(0,3,0), /* Load first word of out into r0 */ + PPC_MTCTR(5), /* Move len into CTR */ + PPC_MULLW(8,7,6), /* Low half of multiply in r8 */ + PPC_MULHWU(5,7,6), /* High half of multiply in r5 */ + PPC_SUBFC(8,8,0), /* r8 = r0 - r8, setting CF */ + PPC_STW(8,3,0), /* Store result to memory */ + PPC_SUBFME(5,5), /* First of two insns to add (1-CF) to r5 */ + PPC_BC(18,31,12), /* Branch to Label if --ctr == 0 */ +/* Loop: */ + PPC_LWZU(7,4,4), /* r7 = *++in */ + PPC_LWZU(0,3,4), /* r0 = *++out */ + PPC_NOR(5,5,5), /* Second of two insns to add (1-CF) to r5 */ + PPC_MULLW(8,7,6), /* r8 = low word of product */ + PPC_ADDC(8,8,5), /* Add carry word r5 to r8 */ + PPC_MULHWU(5,7,6), /* r5 is high word of product, for carry word */ + PPC_ADDZE(5,5), /* Add carry bit from low add to r5 */ + PPC_SUBFC(8,8,0), /* r8 = r0 - r8, setting CF */ + PPC_STW(8,3,0), /* *out = r8 */ + PPC_SUBFME(5,5), /* First of two insns to add (1-CF) to r5 */ + PPC_BC(16,31,-10), /* Branch to Loop if --ctr != 0 */ +/* Label: */ + PPC_NOR(3,5,5), /* Finish adding (1-CF) to r5, store in r3 */ + PPC_BLR() +}; + +#if 0 +/* + * Args: BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv) + * r3 r4 r5 r6 + * r7, r8 and r9 are the triple-width accumulator. + * r0 and r10 are temporary registers. + * r11 and r12 are temporary pointers into n and mod, respectively. + * r2 (!) is another temporary register. + */ +static unsigned const montReduce[] = { + PPC_MTCTR(5), /* ??? */ + PPC_LWZ(7,3,0), /* Load low word of n into r7 */ + PPC_LWZ(10,4,0), /* Fetch low word of mod */ + PPC_MULLW(0,7,6), /* Invert r7 into r0 */ + PPC_STW(0,3,0), /* Store back for future use */ + PPC_MULHWU(8,10,7), /* Get high word of whatnot */ + PPC_MULLW(10,10,7), /* Get low word of it */ + PPC_ADDC(7,7,10), /* Add low word of product to r7 */ + PPC_ADDZE(8,8), /* Add carry to high word */ + PPC_ + + + PPC_MULHW(8,7,6), + PPC_ADDC(7,7,0), /* Add inverse back to r7 */ + PPC_ADDZE(8,8), + PPC_ + + PPC_LWZU( +/* Loop: */ + PPC_LWZU(0,11,4), + PPC_LWZU(10,23,-4), + PPC_MULLW(2,0,10), + PPC_ADDC(7,7,2), + PPC_MULHWU(0,0,10), + PPC_ADDE(8,8,0), + PPC_ADDZE(9,9), + PPC_BC(16,31,-7), /* Branch to Loop if --ctr != 0 */ + + PPC_ADDIC_(count,-1), + PPC_LWZU(0,x,4), + PPC_ADDC(0,7,0), + PPC_STW(0,x,0), + PPC_ADDZE(7,8), + PPC_ADDZE(8,9), + PPC_LI(9,0), + PPC_BC(xx,2,yy), + +}; +#endif + +/* + * Three overlapped transition vectors for three functions. + * A PowerPC transition vector for a (potentially) inter-module + * jump or call consists of two words, an instruction address + * and a Table Of Contents (TOC) pointer, which is loaded into + * r1. Since none of the routines here have global variables, + * they don't need a TOC pointer, so the value is unimportant. + * This array places an unintersting 32-bit value after each address. + */ +unsigned const * const lbnPPC_tv[] = { + mulN1, + mulAdd1, + mulSub1, + 0 +}; + +#else /* __MWERKS >= 0x800 */ + +/* + * MulN1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + */ +asm void +lbnMulN1_32(register unsigned *out, register unsigned const *in, + register unsigned len, register unsigned k) +{ + lwz r7,0(in) /* Load first word of in in r7 */ + mtctr len /* Move len into CTR */ + mullw r8,r7,k /* Low half of multiply in r8 */ + addic r0,r0,0 /* Clear carry bit for loop */ + mulhwu len,r7,k /* High half of multiply in len */ + stw r8,0(out) /* *out = r8 */ + mulhwu len,r7,k /* len is high word of product, for carry */ + bdz- label /* Branch to Label if --ctr == 0 */ +loop: + lwzu r7,4(in) /* r7 = *++in */ + mullw r8,r7,k /* Low half of multiply in r8 */ + adde r8,r8,len /* Add carry word len and bit CF to r8 */ + stwu r8,4(out) /* *++out = r8 */ + mulhwu len,r7,k /* len is high word of product, for carry */ + bdnz+ loop /* Branch to Loop if --ctr != 0 */ +label: + addze len,len /* Add carry flag to carry word */ + stw len,4(out) + blr +} + +/* + * MulAdd1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + */ +asm unsigned +lbnMulAdd1_32(register unsigned *out, register unsigned const *in, + register unsigned len, register unsigned k) +{ + lwz r7,0(in) /* Load first word of in in r7 */ + lwz r0,0(out) /* Load first word of out into r0 */ + mullw r8,r7,k /* Low half of multiply in r8 */ + mtctr len /* Move len into CTR */ + mulhwu len,r7,k /* High half of multiply in len */ + addc r8,r8,r0 /* r8 = r8 + r0 */ + stw r8,0(out) /* Store result to memory */ + bdz- label /* Branch to Label if --ctr == 0 */ +loop: + lwzu r7,4(in) /* r7 = *++in */ + lwzu r0,4(out) /* r0 = *++out */ + mullw r8,r7,k /* r8 = low word of product */ + adde r8,r8,len /* Add carry word len and carry bit CF to r8 */ + mulhwu len,r7,k /* len is high word of product, for carry */ + addze len,len /* Add carry bit from low add to r5 */ + addc r8,r8,r0 /* r8 = r8 + r0 */ + stw r8,0(out) /* *out = r8 */ + bdnz+ loop /* Branch to Loop if --ctr != 0 */ +label: + addze r3,r5 /* Add carry flag to r5 and move to r3 */ + blr +} + +/* + * MulSub1 expects (*out, *in, len, k), count >= 1 + * r3 r4 r5 r6 + * + * Multiply and subtract is rather a pain. If the subtract of the + * low word of the product from out[i] generates a borrow, we want to + * increment the carry word (initially in the range 0..0xfffffffe). + * However, the PPC's carry bit CF is *clear* after a subtract, so + * we want to add (1-CF) to the carry word. This is done using two + * instructions: + * + * SUBFME, subtract from minus one extended. This computes + * rD = ~rS + 0xffffffff + CF. Since rS is from 0 to 0xfffffffe, + * ~rS is from 1 through 0xffffffff, and the sum with 0xffffffff+CF is + * from 0 through 0xfffffffff, setting the carry flag unconditionally, and + * NOR, which is used as a bitwise invert NOT instruction. + * + * The SUBFME performs the computation rD = ~rS + 0xffffffff + CF, + * = (-rS - 1) + (CF - 1) = -(rS - CF + 1) - 1 = ~(rS + 1-CF), + * which is the bitwise complement of the value we want. + * We want to add the complement of that result to the low word of the + * product, which is just what a subtract would do, if only we could get + * the carry flag clear. But it's always set, except for SUBFE, and the + * operation we just performed unconditionally *sets* the carry flag. Ugh. + * So find the complement in a separate instruction. + */ +asm unsigned +lbnMulSub1_32(register unsigned *out, register unsigned const *in, + register unsigned len, register unsigned k) +{ + lwz r7,0(in) /* Load first word of in in r7 */ + lwz r0,0(out) /* Load first word of out into r0 */ + mtctr len /* Move len into CTR */ + mullw r8,r7,k /* Low half of multiply in r8 */ + mulhwu len,r7,k /* High half of multiply in len */ + subfc r8,r8,r0 /* r8 = r0 - r8, setting CF */ + stw r8,0(out) /* Store result to memory */ + subfme len,len /* First of two insns to add (1-CF) to len */ + bdz- label /* Branch to Label if --ctr == 0 */ +loop: + lwzu r7,4(in) /* r7 = *++in */ + lwzu r0,4(out) /* r0 = *++out */ + nor len,len,len /* Second of two insns to add (1-CF) to len */ + mullw r8,r7,k /* r8 = low word of product */ + addc r8,r8,len /* Add carry word len to r8 */ + mulhwu len,r7,k /* len is high word of product, for carry */ + addze len,len /* Add carry bit from low add to len */ + subfc r8,r8,r0 /* r8 = r0 - r8 */ + stw r8,0(out) /* *out = r8 */ + subfme len,len /* First of two insns to add (1-CF) to len */ + bdnz+ loop /* Branch to Loop if --ctr != 0 */ +label: + nor r3,r5,r5 /* Finish adding (1-CF) to len, store in r3 */ + blr +} + +#endif /* __MWERKS >= 0x800 */ +/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */ diff --git a/usr/src/lib/libresolv2/common/cylink/lbnppc.h b/usr/src/lib/libresolv2/common/cylink/lbnppc.h new file mode 100644 index 0000000000..1d9d6e5418 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/lbnppc.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef LBNPPC_H +#define LBNPPC_H +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Assembly-language routines for the Power PC processor. + * Annoyingly, the Power PC does not have 64/32->32 bit divide, + * so the C code should be reasonably fast. But it does have + * 32x32->64-bit multiplies, and these routines provide access + * to that. + * + * In versions of CodeWarrior before 8.0, there was no PPC assembler, + * so a kludged-up one in CPP is used. This requires casting an + * array of unsigneds to function pointer type, and a function pointer + * is not a pointer to the code, but rather a pointer to a (code,TOC) + * pointer pair which we fake up. + * + * CodeWarrior 8.0 supports PCC assembly, which is used directly. + */ + +/* + * Bignums are stored in arrays of 32-bit words, and the least + * significant 32-bit word has the lowest address, thus "little-endian". + * The C code is slightly more efficient this way, so unless the + * processor cares (the PowerPC, like most RISCs, doesn't), it is + * best to use BN_LITTLE_ENDIAN. + * Note that this has NOTHING to do with the order of bytes within a 32-bit + * word; the math library is insensitive to that. + */ +#define BN_LITTLE_ENDIAN 1 + +typedef unsigned bnword32; +#define BNWORD32 bnword32 + +#if __MWERKS__ < 0x800 + +/* Shared transition vector array */ +extern unsigned const * const lbnPPC_tv[]; + +/* A function pointer on the PowerPC is a pointer to a transition vector */ +#define lbnMulN1_32 \ +((void (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+0)) +#define lbnMulAdd1_32 \ +((bnword32 (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+1)) +#define lbnMulSub1_32 \ +((bnword32 (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(lbnPPC_tv+2)) + +#else /* __MWERKS__ >= 0x800 */ + +void lbnMulN1_32(bnword32 *, bnword32 const *, unsigned, bnword32); +#define lbnMulN1_32 lbnMulN1_32 +bnword32 lbnMulAdd1_32(bnword32 *, bnword32 const *, unsigned, bnword32); +#define lbnMulAdd1_32 lbnMulAdd1_32 +bnword32 lbnMulSub1_32(bnword32 *, bnword32 const *, unsigned, bnword32); +#define lbnMulSub1_32 lbnMulSub1_32 + +#endif /* __MWERKS__ >= 0x800 */ + +#endif /* LBNPPC_H */ diff --git a/usr/src/lib/libresolv2/common/cylink/legal.c b/usr/src/lib/libresolv2/common/cylink/legal.c new file mode 100644 index 0000000000..09447c8d3c --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/legal.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Force inclusion of this... */ +#include "legal.h" +volatile const char bnCopyright[] = + "bnlib 1.0.1 Copyright (c) 1995,1996 Colin Plumb."; diff --git a/usr/src/lib/libresolv2/common/cylink/legal.h b/usr/src/lib/libresolv2/common/cylink/legal.h new file mode 100644 index 0000000000..49c7c163bd --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/legal.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * ANSI C standard, section 3.5.3: "An object that has volatile-qualified + * type may be modified in ways unknown to the implementation or have + * other unknown side effects." Yes, we can't expect a compiler to + * understand law... + */ +extern volatile const char bnCopyright[]; diff --git a/usr/src/lib/libresolv2/common/cylink/math.c b/usr/src/lib/libresolv2/common/cylink/math.c new file mode 100644 index 0000000000..4c7b0e6a5e --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/math.c @@ -0,0 +1,1158 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: math.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Math Routines for the ToolKit +* +* PUBLIC FUNCTIONS: +* +* int Sum_big (ord *X, +* ord *Y, +* ord *Z, +* u_int16_t len_X ) +* +* int Sub_big (ord *X, +* ord *Y, +* ord *Z, +* u_int16_t len_X ) +* +* void Mul_big( ord *X, ord *Y,ord *XY, +* u_int16_t lx, u_int16_t ly) +* +* +* PRIVATE FUNCTIONS: +* +* REVISION HISTORY: +* +* 14 Oct 94 GKL Initial release +* 26 Oct 94 GKL (alignment for big endian support ) +* +****************************************************************************/ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ +/* bn files */ +#include "port_before.h" +#include "bn.h" +/* system files */ +#ifdef VXD +#include <vtoolsc.h> +#else +#include <stdlib.h> +#include <string.h> +#endif +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "port_after.h" + +/**************************************************************************** +* NAME: void BigNumInit( void ) +* +* +* DESCRIPTION: Initialize BigNum +* +* INPUTS: +* PARAMETERS: +* OUTPUT: +* PARAMETERS: +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 29 Sep 96 Initial release +* +****************************************************************************/ + +void BigNumInit() +{ +static int bignuminit = 0; +if(!bignuminit){ + bnInit(); + bignuminit = 1; + } +} +/**************************************************************************** +* NAME: int Sum_big (ord *X, +* ord *Y, +* ord *Z, +* u_int16_t len_X ) +* +* DESCRIPTION: Compute addition. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first array +* ord *Y Pointer to second array +* int len_X Number of longs in X_l +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result arrray +* +* RETURN: +* Carry bit +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + + int Sum_big (ord *X, + ord *Y, + ord *Z, + u_int16_t len_X ) +{ + +struct BigNum src2,temp_bn; +ord *temp; +BigNumInit(); + +/*bnInit(); +bnBegin(&src2); +bnBegin(&temp_bn); +*/ +temp = (ord *) malloc((len_X*sizeof(ord)) + sizeof(ord)); +temp_bn.size = len_X; +temp_bn.ptr = temp; +temp_bn.allocated = len_X + 1; + +src2.ptr = Y; +src2.size = len_X; +src2.allocated = len_X; + +memcpy(temp,X,len_X*sizeof(ord)); +bnAdd(&temp_bn,&src2); +memcpy(Z,temp_bn.ptr,len_X*sizeof(ord)); +/*bn package increments the size of dest by 1 if the carry bit is 1*/ +free(temp); +if (temp_bn.size > len_X) + return 1; +else + return 0; +} + + int Sum (ord *X, ord *Y, u_int16_t len_X ) +{ + +struct BigNum dest,src; +/*ord *temp;*/ +BigNumInit(); +#if 0 +bnInit(); +bnBegin(&src2); +bnBegin(&temp_bn); + +temp = (ord *) malloc((len_X*sizeof(ord)) + sizeof(ord)); +temp_bn.size = len_X; +temp_bn.ptr = temp; +temp_bn.allocated = len_X + 1; +#endif + +dest.ptr = X; +dest.size = len_X-1; +dest.allocated = len_X; + +src.ptr = Y; +src.size = len_X; +src.allocated = len_X; + +/*memcpy(temp,X,len_X*sizeof(ord));*/ +bnAdd(&dest,&src); +/*memcpy(Z,temp_bn.ptr,len_X*sizeof(ord));*/ +/*bn package increments the size of dest by 1 if the carry bit is 1*/ +/*free(temp);*/ +if (dest.size > (u_int16_t)(len_X -1)) + return 1; +else + return 0; +} + + +/**************************************************************************** +* NAME: int Sum_Q(ord *X, +* u_int16_t src, +* u_int16_t len_X ) +* DESCRIPTION: Compute addition X += src. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first array +* u_int16_t src Second operand must be <65535 +* int len_X Number of ords in X_l +* OUTPUT: +* PARAMETERS: +* ord *X Pointer to result arrray +* +* RETURN: +* SUCCESS or -1 +* +* REVISION HISTORY: +* +* 21 Sep 96 AAB Initial release +****************************************************************************/ + int Sum_Q(ord *X, u_int16_t src, u_int16_t len_X ) + { + int status = SUCCESS; + struct BigNum des; + BigNumInit(); + /*bnInit();*/ + des.ptr = X; + des.size = len_X; + des.allocated = len_X; + status = bnAddQ(&des, src); + return status; + } + + +/**************************************************************************** +* NAME: int Sub_big (ord *X, +* ord *Y, +* ord *Z, +* u_int16_t len_X ) +* +* +* DESCRIPTION: Compute subtraction. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first array +* ord *Y Pointer to second array +* u_int16_t len_X Number of longs in X_l +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result arrray +* +* RETURN: +* Carry bit +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int Sub_big (ord *X, + ord *Y, + ord *Z, + u_int16_t len_X ) +{ +/* carry is not returned in bn version */ +struct BigNum dest, src; +int status; +ord *temp; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +*/ +src.ptr = Y; +src.size = len_X; +src.allocated = len_X; + +temp = (ord*)malloc(len_X*sizeof(ord)); +dest.ptr = temp; +dest.size = len_X; +dest.allocated = len_X; +memcpy(dest.ptr,X,len_X*sizeof(ord)); + +status = bnSub(&dest,&src); +memcpy(Z,dest.ptr,len_X*sizeof(ord)); +free(temp); +return status; +} + +#if 0 +/**************************************************************************** +* NAME: void Mul_big( ord *X, ord *Y, ord *XY, +* u_int16_t lx, u_int16_t ly) +* +* +* +* DESCRIPTION: Compute a product. +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first long array +* ord *Y Pointer to second long array +* u_int16_t lx Leftmost non zero element of first array +* u_int16_t ly Leftmost non zero element of second array +* OUTPUT: +* PARAMETERS: +* ord *XY Pointer to result +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Sep 95 AAB Comment out calloc and discard the elements_in_X, +* elements_in_Y +****************************************************************************/ +void Mul_big( ord *X, ord *Y, ord *XY, + u_int16_t lx, u_int16_t ly ) +{ +struct BigNum dest, src1, src2; +BigNumInit(); +/*bnInit();*/ +bnBegin(&dest); +/* +bnBegin(&src1); +bnBegin(&src2); +*/ +src1.size = lx + 1; +src1.ptr = X; +src1.allocated = lx + 1; + +src2.ptr = Y; +src2.size = ly + 1; +src2.allocated = ly + 1; + +dest.ptr = XY; +dest.size = lx + ly + 2; +dest.allocated = lx + ly + 2; + +/* Call bn routine */ +bnMul(&dest, &src1,&src2); +} + +#endif +/**************************************************************************** +* NAME: void Mul_big_1( ord X, ord *Y, ord *XY, +* u_int16_t lx, u_int16_t ly ) +* +* +* +* DESCRIPTION: Compute a product. +* +* INPUTS: +* PARAMETERS: +* ord X Number +* ord *Y Pointer to long array +* u_int16_t ly Leftmost non zero element of second array +* OUTPUT: +* PARAMETERS: +* ord *XY Pointer to result +* +* RETURN: +* +* +* REVISION HISTORY: +* +* 08 Oct 95 AAB Initial relaese +* +****************************************************************************/ +void Mul_big_1( ord X, ord *Y, ord *XY, + u_int16_t ly ) +{ +struct BigNum dest, src; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +*/ +src.ptr = Y; +src.size = ly + 1; +src.allocated = ly + 1; + +dest.ptr = XY; +dest.size = ly + 2; +dest.allocated = ly + 2; + +bnMulQ(&dest, &src, (unsigned)X); + +} + +/**************************************************************************** +* NAME: int Mul( u_int16_t X_bytes, +* ord *X, +* u_int16_t Y_bytes, +* ord *Y, +* u_int16_t P_bytes, +* ord *P, +* ord *Z ) +* +* DESCRIPTION: Compute a modulo product +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first operand +* u_int16_t X_bytes Number of bytes in X +* ord *Y Pointer to second operand +* u_int16_t Y_bytes Number of bytes in Y +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int Mul( u_int16_t X_bytes, + ord *X, + u_int16_t Y_bytes, + ord *Y, + u_int16_t P_bytes, + ord *P, + ord *Z ) + +{ + int status = SUCCESS; /*function return status*/ + u_int16_t X_longs; /*number of longs in X*/ + u_int16_t Y_longs; /*number of longs in Y*/ + ord *XY; /*pointer to product (temporary)*/ + + +struct BigNum dest, src1,src2, mod; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src1); +bnBegin(&src2); +bnBegin(&mod); +*/ + +src1.size = X_bytes/sizeof(ord); +src1.ptr = X; +src1.allocated = X_bytes/sizeof(ord); + +src2.size = Y_bytes/sizeof(ord); +src2.ptr = Y; +src2.allocated =Y_bytes/sizeof(ord); + +mod.size = P_bytes/sizeof(ord); +mod.ptr = P; +mod.allocated = P_bytes/sizeof(ord); + + if ( P_bytes == 0 || X_bytes == 0 || Y_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + if ( (X_bytes % sizeof(ord) != 0) || + (Y_bytes % sizeof(ord) != 0) || + (P_bytes % sizeof(ord) != 0) ) + { + status = ERR_INPUT_LEN; + return status; + } + X_longs = (u_int16_t) (X_bytes / sizeof(ord)); + Y_longs = (u_int16_t) (Y_bytes / sizeof(ord)); + XY = (ord *)calloc( X_longs + Y_longs, sizeof(ord) ); + if( !XY ) + { + return ERR_ALLOC; + } +dest.size = X_longs + Y_longs; +dest.ptr = XY; +dest.allocated = X_longs + Y_longs; + +bnMul (&dest,&src1,&src2); + +status = bnMod(&dest, &dest, &mod); +memcpy(Z, dest.ptr, P_bytes); +free( XY ); + return status; +} + +/**************************************************************************** +* NAME: int Square( u_int16_t X_bytes, +* ord *X, +* u_int16_t P_bytes, +* ord *P, +* ord *Z ) +* +* DESCRIPTION: Compute a modulo square +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array to be squared +* u_int16_t X_bytes Number of bytes in X +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* +* REVISION HISTORY: +* +* 1 Sep 95 AAB Initial release +****************************************************************************/ + +int Square( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z ) + +{ + int status = SUCCESS; /*function return status*/ + +ord *XY; +struct BigNum dest, src, mod; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&mod); +*/ + if ( P_bytes == 0 || X_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + if ( (X_bytes % sizeof(ord) != 0) || + (P_bytes % sizeof(ord) != 0) ) + { + status = ERR_INPUT_LEN; + return status; + } + XY = (ord *)malloc( 2*X_bytes ); + if( !XY ) + { + return ERR_ALLOC; + } + +src.size = X_bytes/sizeof(ord); +src.ptr = X; +src.allocated = X_bytes/sizeof(ord); + +dest.size = 2*X_bytes/sizeof(ord); +dest.ptr = XY; +dest.allocated = 2*X_bytes/sizeof(ord); + +mod.size = P_bytes/sizeof(ord); +mod.ptr = P; +mod.allocated = P_bytes/sizeof(ord); + +status = bnSquare(&dest, &src); +status = bnMod(&dest, &dest, &mod); +memcpy(Z, dest.ptr, P_bytes); +free(XY); +return status; +} + + +/**************************************************************************** +* NAME: int PartReduct( u_int16_t X_bytes, +* ord *X, +* u_int16_t P_bytes, +* ord *P, +* ord *Z ) +* +* DESCRIPTION: Compute a modulo +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int16_t X_bytes Number of bytes in X +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int PartReduct( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z ) +{ + int status = SUCCESS; /*function return status */ + + +struct BigNum dest, /*src,*/ d; +ord *temp; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&d); + +src.size = X_bytes/sizeof(ord); +src.ptr = X; +src.allocated = X_bytes/sizeof(ord); +*/ +d.size = P_bytes/sizeof(ord); +d.ptr = P; +d.allocated = P_bytes/sizeof(ord); + +temp = (ord*)malloc(X_bytes); +dest.size = X_bytes/sizeof(ord); +dest.ptr = temp; +dest.allocated = X_bytes/sizeof(ord); +memcpy(dest.ptr, X, X_bytes); + +status = bnMod(&dest, &dest, &d); + +memcpy(Z, dest.ptr, P_bytes); +free(temp); + +return status; + +} + +/**************************************************************************** +* NAME: int Expo( u_int16_t X_bytes, +* ord *X, +* u_int16_t Y_bytes, +* ord *Y, +* u_int16_t P_bytes, +* ord *P, +* ord *Z, +* YIELD_context *yield_cont ) +* +* DESCRIPTION: Compute a modulo exponent +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to base array +* u_int16_t X_bytes Number of bytes in base +* ord *Y Pointer to exponent array +* u_int16_t Y_bytes Number of bytes in exponent +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* YIELD_context *yield_cont Pointer to yield_cont structure (NULL if not used) +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context +* 01 Sep 95 Fast exponentation algorithm +****************************************************************************/ + +int Expo( u_int16_t X_bytes, ord *X, + u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, + ord *Z ) +{ + +int status = SUCCESS; /*function return status*/ + +struct BigNum dest, n, exp, mod; +BigNumInit(); +#if 0 +/*bnInit();*/ +bnBegin(&dest); +bnBegin(&n); +bnBegin(&exp); +bnBegin(&mod); +#endif + +n.size = X_bytes/sizeof(ord); +n.ptr = X; +n.allocated = X_bytes/sizeof(ord); + +exp.ptr = Y; +exp.size = Y_bytes/sizeof(ord); +exp.allocated = Y_bytes/sizeof(ord); + +mod.ptr = P; +mod.size = P_bytes/sizeof(ord); +mod.allocated = P_bytes/sizeof(ord); + +dest.ptr = Z; +dest.size = P_bytes/sizeof(ord); +dest.allocated = P_bytes/sizeof(ord); + +/* Call bn routine */ + +status = bnExpMod(&dest, &n, + &exp, &mod); + +return status; +} + + +/**************************************************************************** +* NAME: int DoubleExpo( u_int16_t X1_bytes, +* ord *X1, +* u_int16_t Y1_bytes, +* ord *Y1, +* u_int16_t X2_bytes, +* ord *X2, +* u_int16_t Y2_bytes, +* ord *Y2, +* u_int16_t P_bytes, +* ord *P, +* ord *Z) +* +* DESCRIPTION: Compute a modulo exponent +* +* INPUTS: +* PARAMETERS: +* ord *X1 Pointer to first base array +* u_int16_t X1_bytes Number of bytes in first base +* ord *Y1 Pointer to first exponent array +* u_int16_t Y1_bytes Number of bytes in first exponent +* ord *X2 Pointer to second base array +* u_int16_t X2_bytes Number of bytes in second base +* ord *Y2 Pointer to second exponent array +* u_int16_t Y2_bytes Number of bytes in second exponent ord *P Pointer to modulo +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* +* REVISION HISTORY: +* +* 21 Aug 96 AAB Initial release +****************************************************************************/ + + +int DoubleExpo( u_int16_t X1_bytes,ord *X1, + u_int16_t Y1_bytes,ord *Y1, + u_int16_t X2_bytes,ord *X2, + u_int16_t Y2_bytes,ord *Y2, + u_int16_t P_bytes,ord *P, + ord *Z) +{ +int status = SUCCESS; /*function return status*/ +struct BigNum res, n1, e1, n2, e2, mod; +BigNumInit(); + +n1.size = X1_bytes/sizeof(ord); +n1.ptr = X1; +n1.allocated = X1_bytes/sizeof(ord); + +e1.size = Y1_bytes/sizeof(ord); +e1.ptr = Y1; +e1.allocated = Y1_bytes/sizeof(ord); + +n2.size = X2_bytes/sizeof(ord); +n2.ptr = X2; +n2.allocated = X2_bytes/sizeof(ord); + +e2.size = Y2_bytes/sizeof(ord); +e2.ptr = Y2; +e2.allocated = Y2_bytes/sizeof(ord); + +mod.ptr = P; +mod.size = P_bytes/sizeof(ord); +mod.allocated = P_bytes/sizeof(ord); + +res.ptr = Z; +res.size = P_bytes/sizeof(ord); +res.allocated = P_bytes/sizeof(ord); +status = bnDoubleExpMod(&res, &n1, &e1, &n2, &e2, &mod); +return status; +} + +/**************************************************************************** +* NAME: int Inverse( u_int16_t X_bytes, +* ord *X, +* u_int16_t P_bytes, +* ord *P, +* ord *Z ) +* +* +* +* +* DESCRIPTION: Compute a modulo inverse element +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int16_t X_bytes Number of bytes in array +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_INPUT_VALUE Invalid input value +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 08 Nov 94 GKL Added input parameters check +* 01 Sep 95 Improve fuction +****************************************************************************/ + +int Inverse( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z ) +{ +int status = SUCCESS; /* function return status */ + +struct BigNum dest, src, mod; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&mod); +*/ +src.size = X_bytes/sizeof(ord); +src.ptr = X; +src.allocated = X_bytes/sizeof(ord); + +mod.ptr = P; +mod.size = P_bytes/sizeof(ord); +mod.allocated = P_bytes/sizeof(ord); + +dest.ptr = Z; +dest.size = (P_bytes/sizeof(ord)) ; +dest.allocated = (P_bytes/sizeof(ord)) + 1; +status = bnInv(&dest,&src,&mod); +return status; +} + + +/**************************************************************************** +* NAME: void Add( ord *X, +* ord *Y, +* u_int16_t P_len, +* ord *P, +* ord *Z ) + +* +* DESCRIPTION: Compute modulo addition +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to first operand +* ord *Y Pointer to second operand +* u_int16_t P_len Length of modulo +* ord *P Pointer to modulo +* OUTPUT: +* ord *Z Pointer to result +* RETURN: +* +* REVISION HISTORY: +* +* 24 sep 94 KPZ Initial release +* 10 Oct 94 KPZ Fixed bugs +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + /* + int Add( ord *X, + ord *Y, + u_int16_t P_len, + ord *P, + ord *Z ) +{ + int status = SUCCESS; + ord *temp; + struct BigNum dest, src, mod; + +bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&mod); + +temp = (ord*)malloc(P_len + sizeof(ord)); +memcpy(temp, X, P_len); + +dest.size = P_len/sizeof(ord); +dest.ptr = temp; +dest.allocated = P_len/sizeof(ord) + 1; + +src.ptr = Y; +src.size = P_len/sizeof(ord); +src.allocated = P_len/sizeof(ord); + +mod.ptr = P; +mod.size = P_len/sizeof(ord); +mod.allocated = P_len/sizeof(ord); + +status = bnAdd(&dest,&src); +status = bnMod(&dest,&dest,&mod); +memcpy(Z,temp,P_len); +free(temp); +return status; +} + */ + int Add( ord *X, + ord *Y, + u_int16_t P_len, + ord *P) +{ + int status = SUCCESS; +/* ord *temp;*/ + struct BigNum dest, src, mod; + +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&src); +bnBegin(&mod); +*/ +/* +temp = (ord*)malloc(P_len + sizeof(ord)); +memcpy(temp, X, P_len); +*/ +dest.size = P_len/sizeof(ord); +/*dest.ptr = temp;*/ +dest.ptr = X; +dest.allocated = P_len/sizeof(ord) + 1; + +src.ptr = Y; +src.size = P_len/sizeof(ord); +src.allocated = P_len/sizeof(ord); + +mod.ptr = P; +mod.size = P_len/sizeof(ord); +mod.allocated = P_len/sizeof(ord); + +status = bnAdd(&dest,&src); +status = bnMod(&dest,&dest,&mod); +/* +memcpy(Z,temp,P_len); +free(temp); +*/ +return status; +} + + + + +/**************************************************************************** +* NAME: int SteinGCD( ord *m, +* ord *b +* u_int16_t len ) +* +* DESCRIPTION: Compute great common divisor +* +* INPUTS: +* PARAMETERS: +* ord *m Pointer to first number +* ord *b Pointer to second number +* u_int16_t len Number of elements in number +* OUTPUT: +* +* RETURN: +* TRUE if gcd != 1 +* FALSE if gcd == 1 +* REVISION HISTORY: +* +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 01 Sep 95 AAB Speed up +* +****************************************************************************/ + + +/* test if GCD equal 1 */ +int SteinGCD ( ord *m, + ord *n, + u_int16_t len ) +{ + +int status; +struct BigNum dest, a, b; +ord *temp; +BigNumInit(); +/*bnInit(); +bnBegin(&dest); +bnBegin(&a); +bnBegin(&b); +*/ +a.size = len; +a.ptr = m; +a.allocated = len; + +b.size = len; +b.ptr = n; +b.allocated = len; + +temp = (ord*)malloc((len+1)*sizeof(ord)); +dest.size = len; +dest.ptr = temp; +dest.allocated = len+1; + +status = bnGcd(&dest, &a, &b); + +if (*(ord *)(dest.ptr) == 0x01 && dest.size == 1) + status = 0; +else + status = 1; + +free(temp); + +return status; + +} + + +/**************************************************************************** +* NAME: int DivRem( u_int16_t X_bytes, +* ord *X, +* u_int16_t P_bytes, +* ord *P, +* ord *Z, +* ord *D) +* +* DESCRIPTION: Compute a modulo and quotient +* +* INPUTS: +* PARAMETERS: +* ord *X Pointer to array +* u_int16_t X_bytes Number of bytes in X +* ord *P Pointer to modulo +* u_int16_t P_bytes Number of bytes in P +* +* OUTPUT: +* PARAMETERS: +* ord *Z Pointer to result +* ord *D Pointer to quotient +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Fixed bugs +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +int DivRem( u_int16_t X_bytes, + ord *X, + u_int16_t P_bytes, + ord *P, + ord *Z, + ord *D) +{ + int status = SUCCESS; /* function return status */ + +struct BigNum q, r, /*n,*/ d; +ord *temp; +BigNumInit(); +/*bnInit(); +bnBegin(&q); +bnBegin(&r); +bnBegin(&n); +bnBegin(&d); + +n.size = X_bytes/sizeof(ord); +n.ptr = X; +n.allocated = X_bytes/sizeof(ord); +*/ +d.size = P_bytes/sizeof(ord); +d.ptr = P; +d.allocated = P_bytes/sizeof(ord); + +q.size = (X_bytes/sizeof(ord)) - (P_bytes/sizeof(ord)) + 1; +q.ptr = D; +q.allocated = (X_bytes/sizeof(ord)) - (P_bytes/sizeof(ord)) + 1; + +temp = (ord *)malloc(X_bytes); +r.size = X_bytes/sizeof(ord); +r.ptr = temp; +r.allocated = X_bytes/sizeof(ord); +memcpy(r.ptr, X, X_bytes); + +status = bnDivMod(&q, &r, &r, &d); + +memcpy(Z, r.ptr, P_bytes); +free(temp); + +return status; + +} diff --git a/usr/src/lib/libresolv2/common/cylink/ppcasm.h b/usr/src/lib/libresolv2/common/cylink/ppcasm.h new file mode 100644 index 0000000000..23e1b28341 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/ppcasm.h @@ -0,0 +1,582 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef PPCASM_H +#define PPCASM_H +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * A PowerPC assembler in the C preprocessor. + * This assumes that ints are 32 bits, and uses them for the values. + * + * An assembly-language routine is simply an array of unsigned ints, + * initialized with the macros defined here. + * + * In the PowerPC, a generic function pointer does *not* point to the + * first word of code, but to a two (or possibly more) word "transition + * vector." The first word of the TV points to the function's code. + * The second word is the function's TOC (Table Of Contents) pointer, + * which is loaded into r2. The function's global variables are + * accessed via the TOC pointed to by r2. TOC pointers are changed, + * for example, when a dynamically linked library is called, so the + * library can have private global variables. + * + * Saving r2 and reloading r2 each function call is a hassle that + * I'd really rather avoid, since a lot of useful assembly language routines + * can be written without global variables at all, so they don't need a TOC + * pointer. But I haven't figured out how to persuade CodeWarrior 7 to + * generate an intra-TOC call to an array. (CodeWarrior 8 supports + * PowerPC asm, which obviates the need to do the cast-to-function-pointer + * trick, which obviates the need for cross-TOC calls.) + * + * The basic PowerPC calling conventions for integers are: + * r0 - scratch. May be modified by function calls. + * r1 - stack pointer. Must be preserved across function calls. + * See IMPORTANT notes on stack frame format below. + * This must *ALWAYS*, at every instruction boundary, be 16-byte + * aligned and point to a valid stack frame. If a procedure + * needs to create a stack frame, the recommended way is to do: + * stwu r1,-frame_size(r1) + * and on exit, recover with one of: + * addi r1,r1,frame_size, OR + * lwz r1,0(r1) + * r2 - TOC pointer. Points to the current table of contents. + * Must be preserved across function calls. + * r3 - First argument register and return value register. + * Arguments are passed in r3 through r10, and values returned in + * r3 through r6, as needed. (Usually only r3 for single word.) + * r4-r10 - More argument registers + * r11 - Scratch, may be modified by function calls. + * On entry to indirect function calls, this points to the + * transition vector, and additional words may be loaded + * at offsets from it. Some conventions use r12 instead. + * r12 - Scratch, may be modified by function calls. + * r13-r31 - Callee-save registers, may not be modified by function + * calls. + * The LR, CTR and XER may be modified by function calls, as may the MQ + * register, on those processors for which it is implemented. + * CR fields 0, 1, 5, 6 and 7 are scratch and may be modified by function + * calls. CR fields 2, 3 and 4 must be preserved across function calls. + * + * Stack frame format - READ + * + * r1 points to a stack frame, which must *ALWAYS*, meaning after each and + * every instruction, without excpetion, point to a valid 16-byte-aligned + * stack frame, defined as follows: + * - The 296 bytes below r1 (from -296(r1) to -1(r1)) are the so-called Red + * Zone reserved for leaf procedures, which may use it without allocating + * a stack frame and without decrementing r1. The size comes from the room + * needed to store all the callee-save registers: 19 64-bit integer registers + * and 18 64-bit floating-point registers. (18+19)*8 = 296. So any + * procedure can save all the registers it needs to save before creating + * a stack frame and moving r1. + * The bytes at -297(r1) and below may be used by interrupt and exception + * handlers *at any time*. Anything placed there may disappear before + * the next instruction. + * The word at 0(r1) is the previous r1, and so on in a linked list. + * This is the minimum needed to be a valid stack frame, but some other + * offsets from r1 are preallocated by the calling procedure for the called + * procedure's use. These are: + * Offset 0: Link to previous stack frame - saved r1, if the called + * procedure alters it. + * Offset 4: Saved CR, if the called procedure alters the callee-save + * fields. There's no important reason to save it here, + * but the space is reserved and you might as well use it + * for its intended purpose unless you have good reason to + * do otherwise. (This may help some debuggers.) + * Offset 8: Saved LR, if the called procedure needs to save it for + * later function return. Saving the LR here helps a debugger + * track the chain of return addresses on the stack. + * Note that a called procedure does not need to preserve the + * LR for it's caller's sake, but it uually wants to preserve + * the value for its own sake until it finishes and it's + * time to return. At that point, this is usually loaded + * back into the LR and the branch accomplished with BLR. + * However, if you want to be preverse, you could load it + * into the CTR and use BCTR instead. + * Offset 12: Reserved to compiler. I can't find what this is for. + * Offset 16: Reserved to compiler. I can't find what this is for. + * Offset 20: Saved TOC pointer. In a cross-TOC call, the old TOC (r2) + * is saved here before r2 is loaded with the new TOC value. + * Again, it's not important to use this slot for this, but + * you might as well. + * Beginning at offset 24 is the argument area. This area is at least 8 words + * (32 bytes; I don't know what happens with 64 bits) long, and may be longer, + * up to the length of the longest argument list in a function called by + * the function which allocated this stack frame. Generally, arguments + * to functions are passed in registers, but if those functions notice + * the address of the arguments being taken, the registers are stored + * into the space reserved for them in this area and then used from memory. + * Additional arguments that will not fit into registers are also stored + * here. Variadic functions (like printf) generally start by saving + * all the integer argument registers from the "..." onwards to this space. + * For that reason, the space must be large enough to store all the argument + * registers, even if they're never used. + * (It could probably be safely shrunk if you're not calling any variadic + * functions, but be careful!) + * + * Offsets above that are private to the calling function and shouldn't + * be messed with. Generally, what appears there is locals, then saved + * registers. + * + * + * The floating-point instruction set isn't implemented yet (I'm too + * lazy, as I don't need it yet), but for when it is, the register + * usage convention is: + * FPSCR - Scratch, except for floating point exception enable fields, + * which should only be modified by functions defined to do so. + * fr0 - scratch + * fr1 - first floating point parameter and return value, scratch + * fr2 - second floating point parameter and return value (if needed), scratch + * fr3 - third floating point parameter and return value (if needed), scratch + * fr4 - fourth floating point parameter and return value (if needed), scratch + * fr5-fr13 - More floating point argument registers, scratch + * fr14-fr31 - Callee-save registers, may not be modified across a function call + * + * Complex values store the real part in the lower-numberd register of a pair. + * When mixing floating-point and integer arguments, reserve space (one register + * for single-precision, two for double-precision values) in the integer + * argument list for the floating-point values. Those integer registers + * generally have undefined values, UNLESS there is no prototype for the call, + * in which case they should contain a copy of the floating-point value's + * bit pattern to cope with wierd software. + * If the floating point arguments go past the end of the integer registers, + * they are stored in the argument area as well as being passed in here. + * + * After the argument area comes the calling function's private storage. + * Typically, there are locals, followed by saved GP rgisters, followed + * by saved FP registers. + * + * Suggested instruction for allocating a stack frame: + * stwu r1,-frame_size(r1) + * Suggested instructions for deallocating a stack frame: + * addi r1,r1,frame_size + * or + * lwz r1,0(r1) + * If frame_size is too big, you'll have to load the offset into a temp + * register, but be sure that r1 is updated atomically. + * + * + * Basic PowerPC instructions look like this: + * + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | | | | | | | | | | | | | | | | | | | | | | | | | | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Branch instructions look like this: + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | Branch offset |A|L| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * The L, or LK, or Link bit indicates that the return address for the + * branch should be copied to the link register (LR). + * The A, or AA, or absolute address bit, indicates that the address + * of the current instruction (NOTE: not next instruction!) should NOT + * be added to the branch offset; it is relative to address 0. + * + * Conditional branches looks like this: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | BO | BI | Branch offset |A|L| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * The BI field specifies the condition bit of interest (from the CR). + * The BO field specifies what's interesting. You can branch on a + * combination of a bit of the condition register and --ctr, the CTR + * register. Two bits encode the branch condition to use: + * BRANCH IF + * 00--- = Bit BI is 0 + * 01--- = Bit BI is 1 + * 1z--- = don't care about bit BI (always true) + * AND + * --00- = --ctr != 0 + * --01- = --ctr == 0 + * --1z- = don't decrement ctr (always true) + * The last bit us used as a branch prediction bit. If set, it reverses + * the usual backward-branch-taken heuristic. + * + * y = branch prediction bit. z = unused, must be 0 + * 0000y - branch if --ctr != 0 && BI == 0 + * don't branch if --ctr == 0 || BI != 0 + * 0001y - branch if --ctr == 0 && BI == 0 + * don't branch if --ctr != 0 || BI != 0 + * 001zy - branch if BI == 0 + * don't branch if BI != 0 + * 0100y - branch if --ctr != 0 && BI != 0 + * don't branch if --ctr == 0 || BI == 0 + * 0101y - branch if --ctr == 0 && BI != 0 + * don't branch if --ctr != 0 || BI == 0 + * 011zy - branch if BI != 0 + * don't branch if BI == 0 + * 1z00y - branch if --ctr != 0 + * don't branch if --ctr == 0 + * 1z01y - branch if --ctr == 0 + * don't branch if --ctr != 0 + * 1z1zz - branch always + * If y is 1, the usual branch prediction (usually not taken, taken for + * backwards branches with immediate offsets) is reversed. + * + * Instructions with 2 operands and a 16-bit immediate field look like this: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | D | A | 16-bit immediate value | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Now, there are three variations of note. In some instructions, the 16-bit + * value is sign-extended. In others, it's zero-extended. These are noted + * below as "simm" (signed immediate) and "uimm", respectively. Also, which + * field is the destination and which is the source sometimes switches. + * Sometimes it's d = a OP imm, and sometimes it's a = s OP imm. In the + * latter cases, the "d" field is referred to as "s" ("source" instead of + * "destination". These are logical and shift instructions. (Store also + * refers to the s register, but that's the source of the value to be stored.) + * The assembly mnemonics, however, always lists the destination first, + * swapping the order in the instruction if necessary. + * Third, quite often, if r0 is specified for the source a, then the constant + * value 0 is used instead. Thus, r0 is of limited use - it can be used for + * some things, but not all. + * + * Instructions with three register operands look like this: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opcode | D | A | B | Subopcode |C| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * For most of the instructions of interest the Opcode is 31 and the subopcode + * determines what the instruction does. For a few instructions (mostly loads + * and stores), if the A field is 0, the constant 0 is used. The "C" + * bit (also known as the "RC" bit) controls whether or not the condition + * codes are updated. If it is set (indicated by a "." suffix on the official + * PowerPC opcodes, and a "_" suffix on these macros), condition code register + * field 0 (for integer instructions; field 1 for floating point) is updated + * to reflect the result of the operation. + * Some arithmetic instructions use the most significant bit of the subopcode + * field as an overflow enable bit (o suffix). + * + * Then there are the rotate and mask instructions, which have 5 operands, and + * fill the subopcode field with 2 more 5-bit fields. See below for them. + * + * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE + * These macros fully parenthesize their arguments, but are not themselves + * fully parenthesized. They are intended to be used for initializer lists, + * and if you want to do tricks with their numeric values, wrap them in + * parentheses. + */ + +#define PPC_MAJOR(x) ((x)<<26) /* Major opcode (0..63) */ +#define PPC_MINOR(x) ((x)<<1) /* Minor opcode (0..1023) */ +#define PPC_RC 1 /* Record carry (. suffix, represented as _) */ +#define PPC_OE 1024 /* Overflow enable (o suffix) */ +#define PPC_DEST(reg) ((reg)<<21) /* Dest register field */ +#define PPC_SRCA(reg) ((reg)<<16) /* First source register field */ +#define PPC_SRCB(reg) ((reg)<<11) /* Second source register field */ +#define PPC_AA 2 /* Branch is absolute, relative to address 0 */ +#define PPC_LK 1 /* Branch with link (L suffix) */ + +/* Unconditional branch (dest is 26 bits, +/- 2^25 bytes) */ +#define PPC_B(dest) PPC_MAJOR(18)|(((dest)<<2) & 0x03fffffc) +#define PPC_BA(dest) PPC_B(dest)|PPC_AA +#define PPC_BL(dest) PPC_B(dest)|PPC_LK +#define PPC_BLA(dest) PPC_B(dest)|PPC_AA|PPC_LK + +/* Three-operand instructions */ +#define PPC_TYPE31(minor,d,a,b) \ + PPC_MAJOR(31)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor) +#define PPC_ADD(d,a,b) PPC_TYPE31(266,d,a,b) +#define PPC_ADD_(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_RC +#define PPC_ADDO(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_OE +#define PPC_ADDO_(d,a,b) PPC_TYPE31(266,d,a,b)|PPC_OE|PPC_RC +#define PPC_ADDC(d,a,b) PPC_TYPE31(10,d,a,b) +#define PPC_ADDC_(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_RC +#define PPC_ADDCO(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_OE +#define PPC_ADDCO_(d,a,b) PPC_TYPE31(10,d,a,b)|PPC_OE|PPC_RC +#define PPC_ADDE(d,a,b) PPC_TYPE31(138,d,a,b) +#define PPC_ADDE_(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_RC +#define PPC_ADDEO(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_OE +#define PPC_ADDEO_(d,a,b) PPC_TYPE31(138,d,a,b)|PPC_OE|PPC_RC +#define PPC_ADDME(d,a) PPC_TYPE31(234,d,a,0) +#define PPC_ADDME_(d,a) PPC_TYPE31(234,d,a,0)|PPC_RC +#define PPC_ADDMEO(d,a) PPC_TYPE31(234,d,a,0)|PPC_OE +#define PPC_ADDMEO_(d,a) PPC_TYPE31(234,d,a,0)|PPC_OE|PPC_RC +#define PPC_ADDZE(d,a) PPC_TYPE31(202,d,a,0) +#define PPC_ADDZE_(d,a) PPC_TYPE31(202,d,a,0)|PPC_RC +#define PPC_ADDZEO(d,a) PPC_TYPE31(202,d,a,0)|PPC_OE +#define PPC_ADDZEO_(d,a) PPC_TYPE31(202,d,a,0)|PPC_OE|PPC_RC +#define PPC_AND(a,s,b) PPC_TYPE31(28,s,a,b) +#define PPC_AND_(a,s,b) PPC_TYPE31(28,s,a,b)|PPC_RC +#define PPC_ANDC(a,s,b) PPC_TYPE31(60,s,a,b) +#define PPC_ANDC_(a,s,b) PPC_TYPE31(60,s,a,b)|PPC_RC +#define PPC_CMP(cr,a,b) PPC_TYPE31(0,(cr)<<2,a,b) +#define PPC_CMPL(cr,a,b) PPC_TYPE31(32,(cr)<<2,a,b) +#define PPC_CNTLZW(a,s) PPC_TYPE31(26,s,a,0) +#define PPC_CNTLZW_(a,s) PPC_TYPE31(26,s,a,0)|PPC_RC +#define PPC_DCBF(a,b) PPC_TYPE31(86,0,a,b) +#define PPC_DCBI(a,b) PPC_TYPE31(470,0,a,b) +#define PPC_DCBST(a,b) PPC_TYPE31(54,0,a,b) +#define PPC_DCBT(a,b) PPC_TYPE31(278,0,a,b) +#define PPC_DCBTST(a,b) PPC_TYPE31(246,0,a,b) +#define PPC_DCBZ(a,b) PPC_TYPE31(1014,0,a,b) +#define PPC_DIVW(d,a,b) PPC_TYPE31(491,d,a,b) +#define PPC_DIVW_(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_RC +#define PPC_DIVWO(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_OE +#define PPC_DIVWO_(d,a,b) PPC_TYPE31(491,d,a,b)|PPC_OE|PPC_RC +#define PPC_DIVWU(d,a,b) PPC_TYPE31(459,d,a,b) +#define PPC_DIVWU_(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_RC +#define PPC_DIVWUO(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_OE +#define PPC_DIVWUO_(d,a,b) PPC_TYPE31(459,d,a,b)|PPC_OE|PPC_RC +#define PPC_EIEIO() PPC_TYPE31(854,0,0,0) +#define PPC_EQV(a,s,b) PPC_TYPE31(284,s,a,b) +#define PPC_EQV_(a,s,b) PPC_TYPE31(284,s,a,b)|PPC_RC +#define PPC_EXTSB(a,s,b) PPC_TYPE31(954,s,a,b) +#define PPC_EXTSB_(a,s,b) PPC_TYPE31(954,s,a,b)|PPC_RC +#define PPC_EXTSH(a,s,b) PPC_TYPE31(922,s,a,b) +#define PPC_EXTSH_(a,s,b) PPC_TYPE31(922,s,a,b)|PPC_RC +#define PPC_ICBI(a,b) PPC_TYPE31(982,0,a,b) +#define PPC_ISYNC() PPC_TYPE31(150,0,0,0) +#define PPC_LBZUX(d,a,b) PPC_TYPE31(119,d,a,b) +#define PPC_LBZX(d,a,b) PPC_TYPE31(87,d,a,b) +#define PPC_LHAUX(d,a,b) PPC_TYPE31(375,d,a,b) +#define PPC_LHAX(d,a,b) PPC_TYPE31(343,d,a,b) +#define PPC_LHBRX(d,a,b) PPC_TYPE31(790,d,a,b) +#define PPC_LHZUX(d,a,b) PPC_TYPE31(311,d,a,b) +#define PPC_LHZX(d,a,b) PPC_TYPE31(279,d,a,b) +#define PPC_LSWI(d,a,nb) PPC_TYPE31(597,d,a,nb) +#define PPC_LSWX(d,a,b) PPC_TYPE31(533,d,a,b) +#define PPC_LSARX(d,a,b) PPC_TYPE31(20,d,a,b) +#define PPC_LSBRX(d,a,b) PPC_TYPE31(534,d,a,b) +#define PPC_MCRXR(crd) PPC_TYPE31(512,(crd)<<2,0,0) +#define PPC_MFCR(d) PPC_TYPE31(19,d,0,0) +#define PPC_MFSPR(d,spr) PPC_TYPE31(339,d,(spr)&31,(spr)>>5) +#define PPC_MFTB(d) PPC_TYPE31(371,d,12,8) +#define PPC_MFTBU(d) PPC_TYPE31(371,d,13,8) +#define PPC_MTCRF(mask,s) PPC_TYPE31(144,s,0,(mask)&0xff) +#define PPC_MTSPR(s,spr) PPC_TYPE31(467,s,(spr)&31,(spr)>>5) +#define PPC_MULHW(d,a,b) PPC_TYPE31(75,d,a,b) +#define PPC_MULHW_(d,a,b) PPC_TYPE31(75,d,a,b)|PPC_RC +#define PPC_MULHWU(d,a,b) PPC_TYPE31(11,d,a,b) +#define PPC_MULHWU_(d,a,b) PPC_TYPE31(11,d,a,b)|PPC_RC +#define PPC_MULLW(d,a,b) PPC_TYPE31(235,d,a,b) +#define PPC_MULLW_(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_RC +#define PPC_MULLWO(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_OE +#define PPC_MULLWO_(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_OE|PPC_RC +#define PPC_NAND(a,s,b) PPC_TYPE31(476,s,a,b) +#define PPC_NAND_(a,s,b) PPC_TYPE31(476,s,a,b)|PPC_RC +#define PPC_NEG(d,a) PPC_TYPE31(104,d,a,b) +#define PPC_NEG_(d,a) PPC_TYPE31(104,d,a,b)|PPC_RC +#define PPC_NEGO(d,a) PPC_TYPE31(104,d,a,b)|PPC_OE +#define PPC_NEGO_(d,a) PPC_TYPE31(104,d,a,b)|PPC_OE|PPC_RC +#define PPC_NOR(a,s,b) PPC_TYPE31(124,s,a,b) +#define PPC_NOR_(a,s,b) PPC_TYPE31(124,s,a,b)|PPC_RC +#define PPC_OR(a,s,b) PPC_TYPE31(444,s,a,b) +#define PPC_OR_(a,s,b) PPC_TYPE31(444,s,a,b)|PPC_RC +#define PPC_ORC(a,s,b) PPC_TYPE31(412,s,a,b) +#define PPC_ORC_(a,s,b) PPC_TYPE31(412,s,a,b)|PPC_RC +#define PPC_SLW(a,s,b) PPC_TYPE31(24,s,a,b) +#define PPC_SLW_(a,s,b) PPC_TYPE31(24,s,a,b)|PPC_RC +#define PPC_SRAW(a,s,b) PPC_TYPE31(792,s,a,b) +#define PPC_SRAW_(a,s,b) PPC_TYPE31(792,s,a,b)|PPC_RC +#define PPC_SRAWI(a,s,sh) PPC_TYPE31(824,s,a,sh) +#define PPC_SRAWI_(a,s,sh) PPC_TYPE31(824,s,a,sh)|PPC_RC +#define PPC_SRW(a,s,b) PPC_TYPE31(536,s,a,b) +#define PPC_SRW_(a,s,b) PPC_TYPE31(536,s,a,b)|PPC_RC +#define PPC_STBUX(s,a,b) PPC_TYPE31(247,s,a,b) +#define PPC_STBX(s,a,b) PPC_TYPE31(215,s,a,b) +#define PPC_STHBRX(s,a,b) PPC_TYPE31(918,s,a,b) +#define PPC_STHUX(s,a,b) PPC_TYPE31(439,s,a,b) +#define PPC_STHX(s,a,b) PPC_TYPE31(407,s,a,b) +#define PPC_STSWI(s,a,nb) PPC_TYPE31(725,s,a,nb) +#define PPC_STSWX(s,a,b) PPC_TYPE31(661,s,a,b) +#define PPC_STWBRX(s,a,b) PPC_TYPE31(662,s,a,b) +#define PPC_STWCX_(s,a,b) PPC_TYPE31(150,s,a,b)|PPC_RC +#define PPC_STWUX(s,a,b) PPC_TYPE31(183,s,a,b) +#define PPC_STWX(s,a,b) PPC_TYPE31(151,s,a,b) +#define PPC_SUBF(d,a,b) PPC_TYPE31(40,d,a,b) +#define PPC_SUBF_(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_RC +#define PPC_SUBFO(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_OE +#define PPC_SUBFO_(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_OE|PPC_RC +#define PPC_SUB(d,b,a) PPC_SUBF(d,a,b) +#define PPC_SUB_(d,b,a) PPC_SUBF_(d,a,b) +#define PPC_SUBO(d,b,a) PPC_SUBFO(d,a,b) +#define PPC_SUBO_(d,b,a) PPC_SUBFO_(d,a,b) +#define PPC_SUBFC(d,a,b) PPC_TYPE31(8,d,a,b) +#define PPC_SUBFC_(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_RC +#define PPC_SUBFCO(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_OE +#define PPC_SUBFCO_(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_OE|PPC_RC +#define PPC_SUBFE(d,a,b) PPC_TYPE31(136,d,a,b) +#define PPC_SUBFE_(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_RC +#define PPC_SUBFEO(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_OE +#define PPC_SUBFEO_(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_OE|PPC_RC +#define PPC_SUBFME(d,a) PPC_TYPE31(232,d,a,0) +#define PPC_SUBFME_(d,a) PPC_TYPE31(232,d,a,0)|PPC_RC +#define PPC_SUBFMEO(d,a) PPC_TYPE31(232,d,a,0)|PPC_OE +#define PPC_SUBFMEO_(d,a) PPC_TYPE31(232,d,a,0)|PPC_OE|PPC_RC +#define PPC_SUBFZE(d,a) PPC_TYPE31(200,d,a,0) +#define PPC_SUBFZE_(d,a) PPC_TYPE31(200,d,a,0)|PPC_RC +#define PPC_SUBFZEO(d,a) PPC_TYPE31(200,d,a,0)|PPC_OE +#define PPC_SUBFZEO_(d,a) PPC_TYPE31(200,d,a,0)|PPC_OE|PPC_RC +#define PPC_SYNC() PPC_TYPE31(598,0,0,0) +#define PPC_TW(to,a,b) PPC_TYPE31(4,to,a,b) +#define PPC_XOR(a,s,b) PPC_TYPE31(316,s,a,b) + +/* Immediate-operand instructions. Take a 16-bit immediate operand */ +#define PPC_IMM(major,d,a,imm) \ + PPC_MAJOR(major)|PPC_DEST(d)|PPC_SRCA(a)|((imm)&0xffff) +/* Trap word immediate */ +#define PPV_TWI(to,a,simm) PPC_IMM(3,to,a,simm) +/* Integer arithmetic */ +#define PPC_MULLI(d,a,simm) PPC_IMM(7,d,a,simm) +#define PPC_SUBFIC(s,a,simm) PPC_IMM(8,s,a,simm) +#define PPC_CMPLI(cr,a,uimm) PPC_IMM(10,(cr)<<2,a,uimm) +#define PPC_CMPI(cr,a,simm) PPC_IMM(11,(cr)<<2,a,simm) +#define PPC_ADDIC(d,a,simm) PPC_IMM(12,d,a,simm) +#define PPC_ADDIC_(d,a,simm) PPC_IMM(13,d,a,simm) +#define PPC_ADDI(d,a,simm) PPC_IMM(14,d,a,simm) +#define PPC_ADDIS(d,a,simm) PPC_IMM(15,d,a,simm) + +/* Conditional branch (dest is 16 bits, +/- 2^15 bytes) */ +#define PPC_BC(bo,bi,dest) PPC_IMM(16,bo,bi,((dest)<<2)&0xfffc) +#define PPC_BCA(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_AA +#define PPC_BCL(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_LK +#define PPC_BCLA(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_AA|PPC_LK + +/* Logical operations */ +#define PPC_ORI(a,s,uimm) PPC_IMM(24,s,a,uimm) +#define PPC_ORIS(a,s,uimm) PPC_IMM(25,s,a,uimm) +#define PPC_XORI(a,s,uimm) PPC_IMM(26,s,a,uimm) +#define PPC_XORIS(a,s,uimm) PPC_IMM(27,s,a,uimm) +#define PPC_ANDI_(a,s,uimm) PPC_IMM(28,s,a,uimm) +#define PPC_ANDIS(a,s,uimm) PPC_IMM(29,s,a,uimm) + +/* Load/store */ +#define PPC_LWZ(d,a,simm) PPC_IMM(32,d,a,simm) +#define PPC_LWZU(d,a,simm) PPC_IMM(33,d,a,simm) +#define PPC_LBZ(d,a,simm) PPC_IMM(34,d,a,simm) +#define PPC_LBZU(d,a,simm) PPC_IMM(35,d,a,simm) +#define PPC_STW(s,a,simm) PPC_IMM(36,s,a,simm) +#define PPC_STWU(s,a,simm) PPC_IMM(37,s,a,simm) +#define PPC_STB(s,a,simm) PPC_IMM(38,s,a,simm) +#define PPC_STBU(s,a,simm) PPC_IMM(39,s,a,simm) +#define PPC_LHZ(d,a,simm) PPC_IMM(40,d,a,simm) +#define PPC_LHZU(d,a,simm) PPC_IMM(41,d,a,simm) +#define PPC_LHA(d,a,simm) PPC_IMM(42,d,a,simm) +#define PPC_STH(s,a,simm) PPC_IMM(44,s,a,simm) +#define PPC_STHU(s,a,simm) PPC_IMM(45,s,a,simm) +#define PPC_LHAU(d,a,simm) PPC_IMM(43,d,a,simm) +#define PPC_LMW(d,a,simm) PPC_IMM(46,d,a,simm) +#define PPC_STMW(s,a,simm) PPC_IMM(47,s,a,simm) + +/* Major number = 19 - condition register operations. d, a and b are CR bits */ +#define PPC_TYPE19(minor,d,a,b) \ + PPC_MAJOR(19)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor) +#define PPC_MCRF(d,s) PPC_TYPE19(0,(d)<<2,(s)<<2,0) +#define PPC_CRNOR(d,a,b) PPC_TYPE19(33,d,a,b) +#define PPC_CRANDC(d,a,b) PPC_TYPE19(129,d,a,b) +#define PPC_CRXOR(d,a,b) PPC_TYPE19(193,d,a,b) +#define PPC_CRNAND(d,a,b) PPC_TYPE19(225,d,a,b) +#define PPC_CRAND(d,a,b) PPC_TYPE19(257,d,a,b) +#define PPC_CREQV(d,a,b) PPC_TYPE19(289,d,a,b) +#define PPC_CRORC(d,a,b) PPC_TYPE19(417,d,a,b) +#define PPC_CROR(d,a,b) PPC_TYPE19(449,d,a,b) + +/* Indirect conditional branch */ +#define PPC_BCLR(bo,bi) PPC_TYPE19(16,bo,bi,0) +#define PPC_BCLRL(bo,bi) PPC_TYPE19(16,bo,bi,0)|PPC_LK +#define PPC_BCCTR(bo,bi) PPC_TYPE19(528,bo,bi,0) +#define PPC_BCCTRL(bo,bi) PPC_TYPE19(528,bo,bi,0)|PPC_LK +#define PPC_BLR() PPC_BCLR(20,31) +#define PPC_BCTR() PPC_BCCTR(20,31) + +/* Other */ +#define PPC_RLWIMI(a,s,sh,mb,me) \ + PPC_MAJOR(20)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1 +#define PPC_RLWIMI_(a,s,sh,mb,me) PPC_RLWIMI(a,s,sh,mb,me)|PPC_RC +#define PPC_RLWINM(a,s,sh,mb,me) \ + PPC_MAJOR(21)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1 +#define PPC_RLWINM_(a,s,sh,mb,me) PPC_RLWINM(a,s,sh,mb,me)|PPC_RC +#define PPC_RLWNM(a,s,b,mb,me) \ + PPC_MAJOR(23)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(b)|(mb)<<6|(me)<<1 +#define PPC_RLWNM_(a,s,b,mb,me) PPC_RLWNM(a,s,b,mb,me)|PPC_RC + +#define PPC_SC() PPC_MAJOR(17)|2 +/* Major number = 63 Floating-point operations (not implemented for now) */ + +/* Simplified Mnemonics */ +/* Fabricate immediate subtract out of add negative */ +#define PPC_SUBI(d,a,simm) PPC_ADDI(d,a,-(simm)) +#define PPC_SUBIS(d,a,simm) PPC_ADDIS(d,a,-(simm)) +#define PPC_SUBIC(d,a,simm) PPC_ADDIC(d,a,-(simm)) +#define PPC_SUBIC_(d,a,simm) PPC_ADDIC_(d,a,-(simm)) +/* Fabricate subtract out of subtract from */ +#define PPC_SUBC(d,b,a) PPC_SUBFC(d,a,b) +#define PPC_SUBC_(d,b,a) PPC_SUBFC_(d,a,b) +#define PPC_SUBCO(d,b,a) PPC_SUBFCO(d,a,b) +#define PPC_SUBCO_(d,b,a) PPC_SUBFCO_(d,a,b) +/* Messy compare bits omitted */ +/* Shift and rotate omitted */ +/* Branch coding omitted */ +#define PPC_CRSET(d) PPC_CREQV(d,d,d) +#define PPC_CRCLR(d) PPC_CRXOR(d,d,d) +#define PPC_CRMOVE(d,s) PPC_CROR(d,s,s) +#define PPC_CRNOT(d,s) PPC_CRNOR(d,s,s) +/* Trap menmonics omitted */ +/* Menmonics for user-accessible SPRs */ +#define PPC_MFXER(d) PPC_MFSPR(d,1) +#define PPC_MFLR(d) PPC_MFSPR(d,8) +#define PPC_MFCTR(d) PPC_MFSPR(d,9) +#define PPC_MTXER(s) PPC_MTSPR(s,1) +#define PPC_MTLR(s) PPC_MTSPR(s,8) +#define PPC_MTCTR(s) PPC_MTSPR(s,9) +/* Recommended mnemonics */ +#define PPC_NOP() PPC_ORI(0,0,0) +#define PPC_LI(d,simm) PPC_ADDI(d,0,simm) +#define PPC_LIS(d,simm) PPC_ADDIS(d,0,simm) +#define PPC_LA(d,a,simm) PPC_ADDI(d,a,simm) +#define PPC_MR(d,s) PPC_OR(d,s,s) +#define PPC_NOT(d,s) PPC_NOR(d,s,s) +#define PPC_MTCR(s) PPC_MTCRF(0xff,s) + +#endif /* PPCASM_H */ + +/* 45678901234567890123456789012345678901234567890123456789012345678901234567 */ diff --git a/usr/src/lib/libresolv2/common/cylink/rand.c b/usr/src/lib/libresolv2/common/cylink/rand.c new file mode 100644 index 0000000000..b2b6d6f85b --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/rand.c @@ -0,0 +1,340 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: rand.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Functions File +* Random Number Generation Files +* PUBLIC FUNCTIONS: +* int InitRand( u_int16_t SEED_bytes, uchar *SEED, +* uchar *RVAL ) +* int GenRand( u_int16_t A_bytes, uchar *A, +* uchar *RVAL ) +* int MyGenRand( u_int16_t A_bytes, +* ord *A, +* ord *RVAL ) + +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Added Shamir Key Sharing functions +* 10 Oct 94 KPZ Modified SHA functions for arbitrary message length +* 12 Oct 94 KPZ Modified SHA functions (new standard) +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* +****************************************************************************/ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +#include "port_before.h" + +/* system files */ +#ifdef VXD +#include <vtoolsc.h> +#else +#include <stdlib.h> +#include <string.h> +#endif + +/* program files */ +#ifdef VXD +#include "tkvxd.h" +#endif +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "cencrint.h" +#include "sha.h" + +#include "port_after.h" +extern u_int16_t DataOrder; +/**************************************************************************** +* PUBLIC FUNCTIONS DEFINITIONS +****************************************************************************/ + +/**************************************************************************** +* NAME: int InitRand( u_int16_t SEED_bytes, +* uchar *SEED, +* uchar *RVAL) +* +* DESCRIPTION: Initialize Random number Generator +* +* INPUTS: +* PARAMETERS: +* u_int16_t SEED_bytes Length of SEED +* uchar *SEED Pointer to SEED value +* +* OUTPUT: +* PARAMETERS: +* uchar *RVAL Pointer to RVAL +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data +* ERR_DATA Generic data error +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ + +int InitRand( u_int16_t SEED_bytes, + uchar *SEED, + uchar *RVAL ) +{ + int status = SUCCESS; /* function return status */ + if ( SEED_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + if ( SEED_bytes < SHA_LENGTH ) + { + status = ERR_DATA; + return status; + } + memcpy( RVAL, SEED, SHA_LENGTH); + return status; +} + + +/**************************************************************************** +* NAME: int GenRand( u_int16_t A_bytes, +* uchar *A, +* uchar *RVAL) +* +* DESCRIPTION: Generate random number. +* +* INPUTS: +* PARAMETERS: +* u_int16_t A_bytes Length of A +* uchar *A Pointer to A value +* +* OUTPUT: +* PARAMETERS: +* uchar *RVAL Pointer to RVAL +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data +* ERR_DATA Generic data error +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* +****************************************************************************/ +int GenRand( u_int16_t A_bytes, + uchar *A, + uchar *RVAL ) +{ + int status = SUCCESS; /* function return status */ + ord *RVAL_a; + SHA_context hash_context; /* SHA context structure */ + uchar M[DSS_LENGTH_MIN]; /* message block */ + uchar hash_result[SHA_LENGTH]; + u_int16_t i; + u_int16_t sha_block; /* number of sha blocks */ + u_int16_t sha_rem; /* size of last block */ + if ( A_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + sha_block = (u_int16_t) (A_bytes / SHA_LENGTH); /* number of sha blocks */ + sha_rem = (u_int16_t) (A_bytes % SHA_LENGTH); /* size of last block */ + if ( sha_rem == 0 ) /* last block = SHA_LENGTH */ + { + sha_block--; + } + for ( i = 0; i <= sha_block; i++) + { + SHAInit ( &hash_context ); + memcpy( M, RVAL, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + return status; /* error */ + } + if ( (status=MySHAFinal (&hash_context, hash_result )) != SUCCESS ) + { + return status; /* error */ + } + + BigSwap(RVAL, SHA_LENGTH); + ALIGN_CALLOC_COPY(RVAL, RVAL_a, SHA_LENGTH); + if ( status != SUCCESS ) + { + ALIGN_COPY_FREE(RVAL_a,RVAL,SHA_LENGTH); + BigSwap(RVAL, SHA_LENGTH); + return status; /* ERR_ALLOC insufficient memory */ + } + Sum_Q( RVAL_a, 1, SHA_LENGTH / sizeof(ord) ); + Sum_big( RVAL_a, /* RVAL=RVAL+hash_result*/ + (ord *)hash_result, + RVAL_a, SHA_LENGTH / sizeof(ord) ); + ALIGN_COPY_FREE(RVAL_a,RVAL,SHA_LENGTH); + BigSwap(RVAL, SHA_LENGTH); +#ifdef CTK_BIG_ENDIAN + ByteSwap(hash_result,SHA_LENGTH); +#endif + BigSwap(hash_result, SHA_LENGTH); + if ( i == sha_block && sha_rem != 0 ) /* last block < SHA_LENGTH*/ + { + memcpy( A + i * SHA_LENGTH, hash_result, + sha_rem * sizeof (uchar)); + } + else /* last block = SHA_LENGTH*/ + { + memcpy( A + i * SHA_LENGTH, hash_result, + SHA_LENGTH * sizeof (uchar)); + } + } + return status; +} + + + +/**************************************************************************** +* NAME: int MyGenRand( u_int16_t A_bytes, +* ord *A, +* ord *RVAL) +* +* DESCRIPTION: Generate random number. +* +* INPUTS: +* PARAMETERS: +* u_int16_t A_bytes Length of A +* ord *A Pointer to A value +* +* OUTPUT: +* PARAMETERS: +* ord *RVAL Pointer to RVAL +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data +* ERR_DATA Generic data error +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ +int MyGenRand( u_int16_t A_bytes, + ord *A, + ord *RVAL ) +{ + int status = SUCCESS; /* function return status */ + SHA_context hash_context; /* SHA context structure */ + uchar M[DSS_LENGTH_MIN]; /* message block */ + uchar hash_result[SHA_LENGTH]; + u_int16_t i; + u_int16_t sha_block; /* number of sha blocks */ + u_int16_t sha_rem; /* size of last block */ + if ( A_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; + } + sha_block = (u_int16_t) (A_bytes / SHA_LENGTH); /* number of sha blocks */ + sha_rem = (u_int16_t) (A_bytes % SHA_LENGTH); /* size of last block */ + if ( sha_rem == 0 ) /* last block = SHA_LENGTH */ + { + sha_block--; + } + for ( i = 0; i <= sha_block; i++) + { + SHAInit ( &hash_context ); + memcpy( M, RVAL, SHA_LENGTH); + memset( M + SHA_LENGTH, 0, DSS_LENGTH_MIN - SHA_LENGTH ); + if ( (status = SHAUpdate( &hash_context, M, DSS_LENGTH_MIN )) + != SUCCESS ) + { + return status; /* error */ + } + if ( (status=MySHAFinal (&hash_context, hash_result )) != SUCCESS ) + { + return status; /* error */ + } +#ifdef CTK_BIG_ENDIAN + ByteSwap((uchar*)RVAL,SHA_LENGTH); +#endif + BigSwap((uchar*)RVAL, SHA_LENGTH); + Sum_Q(RVAL, 1,SHA_LENGTH / sizeof(ord)); + Sum_big( RVAL, /* RVAL=RVAL+hash_result*/ + (ord*)hash_result, + RVAL, SHA_LENGTH / sizeof(ord) ); + BigSwap((uchar*)RVAL, SHA_LENGTH); +#ifdef CTK_BIG_ENDIAN + ByteSwap((uchar*)RVAL,SHA_LENGTH); +#endif + if ( i == sha_block && sha_rem != 0 ) /* last block < SHA_LENGTH*/ + { + memcpy( &A[ i*SHA_LENGTH / sizeof(ord)], hash_result, + sha_rem * sizeof (uchar)); + } + else /* last block = SHA_LENGTH*/ + { + memcpy( &A[ i*SHA_LENGTH / sizeof(ord)], hash_result, + SHA_LENGTH * sizeof (uchar)); + } + } + return status; +} + diff --git a/usr/src/lib/libresolv2/common/cylink/sha.c b/usr/src/lib/libresolv2/common/cylink/sha.c new file mode 100644 index 0000000000..bc67fcac79 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/sha.c @@ -0,0 +1,706 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: cencrint.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Internal Functions File +* +* PRIVATE FUNCTIONS: +* +* +* void shaTransform( u_int32_t *state, uchar *block ) +* void SHAInitK( SHA_context *hash_context ) +* int MySHA( uchar *message, u_int16_t message_bytes, +* uchar *hash_result ) +* int MySHAFinal( SHA_context *hash_context, uchar *hash_result ) +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Fixed bugs in Add(), DivRem() +* 12 Oct 94 KPZ Modified shaTransform() +* 14 Oct 94 GKL Second version (big endian support) +* 26 Oct 94 GKL (alignment for big endian support & ERR_ALLOC) +* 08 Nov 94 GKL Added input parameters check to Inverse +* 08 Dec 94 GKL Added YIELD_context to Expo, VerPrime and GenPrime +* +****************************************************************************/ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +#include "port_before.h" +#include <sys/types.h> + +/* system files */ +#ifdef VXD +#include <vtoolsc.h> +#else +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#endif + +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "cencrint.h" +#include "sha.h" +#include "port_after.h" +extern u_int16_t DataOrder; + +/**************************************************************************** +* NAME: int SHA( uchar *message, +* u_int16_t message_bytes, +* uchar *hash_result ) +* +* DESCRIPTION: Compute a Secure Hash Function. +* +* INPUTS: +* PARAMETERS: +* uchar *message Pointer to message +* u_int16_t message_bytes Number of bytes in message +* uchar *hash_result Pointer to message digest +* +* OUTPUT: +* PARAMETERS: +* uchar *hash_result Message digest +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ + +int SHA( uchar *message, + u_int16_t message_bytes, + uchar *hash_result ) +{ + SHA_context hash_context; /* SHA context structure */ + int status = SUCCESS; /* function return status */ + if (message_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; /* invalid length for input data */ + } + SHAInit ( &hash_context ); /* initialize SHA */ + if ( (status = SHAUpdate( &hash_context, message, message_bytes )) + != SUCCESS ) + { + return status; /* error */ + } + if ((status=SHAFinal (&hash_context, hash_result)) != SUCCESS ) + { + return status; /* error */ + } + + return status; +} + +/**************************************************************************** +* PRIVATE FUNCTIONS DEFINITIONS +****************************************************************************/ + + +/**************************************************************************** +* NAME: void shaTransform( u_int32_t *state, +* uchar *block ) +* +* DESCRIPTION: Perform SHS transformation. +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context Pointer to SHA_context structure +* OUTPUT: +* +* SHA_context *hash_context Pointer to SHA_context structure +* (updated) +* REVISION HISTORY: +* +* 24 sep 94 KPZ Initial release +* 12 Oct 94 KPZ Modified buffers copy +* 14 Oct 94 GKL Second version (big endian support) +* 1 Sep 95 AAB Speedup the function +****************************************************************************/ + + void shaTransform( u_int32_t *state, + const uchar *block ) +{ + u_int32_t W[80]; + u_int32_t A,B,C,D,E; /*,temp;*/ + memcpy( W, block, 64); /*TKL00201*/ +#ifdef CTK_LITTLE_ENDIAN /*TKL00201*/ + ByteSwap32( (uchar *)W, 64); /*TKL00201*/ +#endif /*TKL00201*/ + /* Expand the 16 words into 80 words */ + expand(16);expand(17);expand(18);expand(19);expand(20);expand(21); + expand(22);expand(23);expand(24);expand(25);expand(26);expand(27); + expand(28);expand(29);expand(30);expand(31);expand(32);expand(33); + expand(34);expand(35);expand(36);expand(37);expand(38);expand(39); + expand(40);expand(41);expand(42);expand(43);expand(44);expand(45); + expand(46);expand(47);expand(48);expand(49);expand(50);expand(51); + expand(52);expand(53);expand(54);expand(55);expand(56);expand(57); + expand(58);expand(59);expand(60);expand(61);expand(62);expand(63); + expand(64);expand(65);expand(66);expand(67);expand(68);expand(69); + expand(70);expand(71);expand(72);expand(73);expand(74);expand(75); + expand(76);expand(77);expand(78);expand(79); + /*Set up first buffer*/ + A = state[0]; + B = state[1]; + C = state[2]; + D = state[3]; + E = state[4]; + + /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ + subRound( A, B, C, D, E, f1, k1SHA, W[ 0] ); + subRound( E, A, B, C, D, f1, k1SHA, W[ 1] ); + subRound( D, E, A, B, C, f1, k1SHA, W[ 2] ); + subRound( C, D, E, A, B, f1, k1SHA, W[ 3] ); + subRound( B, C, D, E, A, f1, k1SHA, W[ 4] ); + subRound( A, B, C, D, E, f1, k1SHA, W[ 5] ); + subRound( E, A, B, C, D, f1, k1SHA, W[ 6] ); + subRound( D, E, A, B, C, f1, k1SHA, W[ 7] ); + subRound( C, D, E, A, B, f1, k1SHA, W[ 8] ); + subRound( B, C, D, E, A, f1, k1SHA, W[ 9] ); + subRound( A, B, C, D, E, f1, k1SHA, W[10] ); + subRound( E, A, B, C, D, f1, k1SHA, W[11] ); + subRound( D, E, A, B, C, f1, k1SHA, W[12] ); + subRound( C, D, E, A, B, f1, k1SHA, W[13] ); + subRound( B, C, D, E, A, f1, k1SHA, W[14] ); + subRound( A, B, C, D, E, f1, k1SHA, W[15] ); + subRound( E, A, B, C, D, f1, k1SHA, W[16] ); + subRound( D, E, A, B, C, f1, k1SHA, W[17] ); + subRound( C, D, E, A, B, f1, k1SHA, W[18] ); + subRound( B, C, D, E, A, f1, k1SHA, W[19] ); + + subRound( A, B, C, D, E, f2, k2SHA, W[20]); + subRound( E, A, B, C, D, f2, k2SHA, W[21]); + subRound( D, E, A, B, C, f2, k2SHA, W[22]); + subRound( C, D, E, A, B, f2, k2SHA, W[23]); + subRound( B, C, D, E, A, f2, k2SHA, W[24]); + subRound( A, B, C, D, E, f2, k2SHA, W[25]); + subRound( E, A, B, C, D, f2, k2SHA, W[26]); + subRound( D, E, A, B, C, f2, k2SHA, W[27]); + subRound( C, D, E, A, B, f2, k2SHA, W[28]); + subRound( B, C, D, E, A, f2, k2SHA, W[29]); + subRound( A, B, C, D, E, f2, k2SHA, W[30]); + subRound( E, A, B, C, D, f2, k2SHA, W[31]); + subRound( D, E, A, B, C, f2, k2SHA, W[32]); + subRound( C, D, E, A, B, f2, k2SHA, W[33]); + subRound( B, C, D, E, A, f2, k2SHA, W[34]); + subRound( A, B, C, D, E, f2, k2SHA, W[35]); + subRound( E, A, B, C, D, f2, k2SHA, W[36]); + subRound( D, E, A, B, C, f2, k2SHA, W[37]); + subRound( C, D, E, A, B, f2, k2SHA, W[38]); + subRound( B, C, D, E, A, f2, k2SHA, W[39]); + + subRound( A, B, C, D, E, f3, k3SHA, W[40]); + subRound( E, A, B, C, D, f3, k3SHA, W[41]); + subRound( D, E, A, B, C, f3, k3SHA, W[42]); + subRound( C, D, E, A, B, f3, k3SHA, W[43]); + subRound( B, C, D, E, A, f3, k3SHA, W[44]); + subRound( A, B, C, D, E, f3, k3SHA, W[45]); + subRound( E, A, B, C, D, f3, k3SHA, W[46]); + subRound( D, E, A, B, C, f3, k3SHA, W[47]); + subRound( C, D, E, A, B, f3, k3SHA, W[48]); + subRound( B, C, D, E, A, f3, k3SHA, W[49]); + subRound( A, B, C, D, E, f3, k3SHA, W[50]); + subRound( E, A, B, C, D, f3, k3SHA, W[51]); + subRound( D, E, A, B, C, f3, k3SHA, W[52]); + subRound( C, D, E, A, B, f3, k3SHA, W[53]); + subRound( B, C, D, E, A, f3, k3SHA, W[54]); + subRound( A, B, C, D, E, f3, k3SHA, W[55]); + subRound( E, A, B, C, D, f3, k3SHA, W[56]); + subRound( D, E, A, B, C, f3, k3SHA, W[57]); + subRound( C, D, E, A, B, f3, k3SHA, W[58]); + subRound( B, C, D, E, A, f3, k3SHA, W[59]); + + subRound( A, B, C, D, E, f4, k4SHA, W[60]); + subRound( E, A, B, C, D, f4, k4SHA, W[61]); + subRound( D, E, A, B, C, f4, k4SHA, W[62]); + subRound( C, D, E, A, B, f4, k4SHA, W[63]); + subRound( B, C, D, E, A, f4, k4SHA, W[64]); + subRound( A, B, C, D, E, f4, k4SHA, W[65]); + subRound( E, A, B, C, D, f4, k4SHA, W[66]); + subRound( D, E, A, B, C, f4, k4SHA, W[67]); + subRound( C, D, E, A, B, f4, k4SHA, W[68]); + subRound( B, C, D, E, A, f4, k4SHA, W[69]); + subRound( A, B, C, D, E, f4, k4SHA, W[70]); + subRound( E, A, B, C, D, f4, k4SHA, W[71]); + subRound( D, E, A, B, C, f4, k4SHA, W[72]); + subRound( C, D, E, A, B, f4, k4SHA, W[73]); + subRound( B, C, D, E, A, f4, k4SHA, W[74]); + subRound( A, B, C, D, E, f4, k4SHA, W[75]); + subRound( E, A, B, C, D, f4, k4SHA, W[76]); + subRound( D, E, A, B, C, f4, k4SHA, W[77]); + subRound( C, D, E, A, B, f4, k4SHA, W[78]); + subRound( B, C, D, E, A, f4, k4SHA, W[79]); + + state[0] += A; + state[1] += B; + state[2] += C; + state[3] += D; + state[4] += E; + +} + + + + +/**************************************************************************** +* NAME: void SHAInitK( SHA_context *hash_context ) +* +* DESCRIPTION: Initialize Secure Hash Function for generate +* random number for DSS. +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* OUTPUT: +* PARAMETERS: +* SHA_context *hash_context Initialized SHA context structure +* +* RETURN: +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void SHAInitK( SHA_context *hash_context ) +{ +/*Set up first buffer*/ + /* on28 port: silence compiler warnings by changing 0x...L to 0x...U */ + hash_context->state[0] = 0xEFCDAB89U; + hash_context->state[1] = 0x98BADCFEU; + hash_context->state[2] = 0x10325476U; + hash_context->state[3] = 0xC3D2E1F0U; + hash_context->state[4] = 0x67452301U; +/*Initialise buffer */ + memset( hash_context->buffer, 0, sizeof(hash_context->buffer)); + memset( hash_context->count, 0, sizeof(hash_context->count)); +} + + +/**************************************************************************** +* NAME: int MySHA( uchar *message, +* u_int16_t message_bytes, +* uchar *hash_result ) +* +* DESCRIPTION: Compute a Secure Hash Function. +* +* INPUTS: +* PARAMETERS: +* uchar *message Pointer to message +* u_int16_t message_bytes Number of bytes in message +* uchar *hash_result Pointer to message digest +* +* OUTPUT: +* PARAMETERS: +* uchar *hash_result Message digest +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ +int MySHA( uchar *message, + u_int16_t message_bytes, + uchar *hash_result ) +{ + SHA_context hash_context; /* SHA context structure */ + int status = SUCCESS; /* function return status */ + if (message_bytes == 0 ) + { + status = ERR_INPUT_LEN; + return status; /* invalid length for input data */ + } + SHAInit ( &hash_context ); /* initialize SHA */ +#ifdef CTK_BIG_ENDIAN + ByteSwap(message,message_bytes); +#endif + status = SHAUpdate( &hash_context, message, message_bytes ); +#ifdef CTK_BIG_ENDIAN + ByteSwap(message,message_bytes); +#endif + if ( status != SUCCESS ) + { + return status; /* error */ + } + if ((status=MySHAFinal (&hash_context, hash_result)) != SUCCESS ) + { + return status; /* error */ + } + return status; +} + +/**************************************************************************** +* NAME: int MySHAFinal( SHA_context *hash_context, +* uchar *hash_result ) +* DESCRIPTION: Finalize Secure Hash Function +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* uchar *hash_result Pointer to hash +* OUTPUT: +* PARAMETERS: +* uchar *hash_result Final value +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Modified for arbitrary message length +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + int MySHAFinal( SHA_context *hash_context, + uchar *hash_result ) +{ + int status = SUCCESS; /* function return status */ + uchar bits[8]; + u_int16_t index, padLen; + u_int32_t ex; + uchar PADDING[64] = { /* padding string */ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if ( hash_context->count[0] == 0 && hash_context->count[1] == 0 ) + { + status= ERR_INPUT_LEN; + return status; + } + /* Save number of bits */ + LongByte( &hash_context->count[1] , 4, bits ); + LongByte( &hash_context->count[0] , 4, bits + 4 ); + ByteSwap32( bits, 8 ); + /* Pad out to 56 mod 64.*/ + index = (u_int16_t )((hash_context->count[0] >> 3) & 0x3f); + padLen = (u_int16_t) ((index < 56) ? (56 - index) : (120 - index)); + SHAUpdate( hash_context, PADDING, padLen ); + + /* Append length (before padding) */ + SHAUpdate (hash_context, bits, 8); + + /* Set order of hash_context */ + ex = hash_context->state[0]; + hash_context->state[0] = hash_context->state[4]; + hash_context->state[4] = ex; + ex = hash_context->state[1]; + hash_context->state[1] = hash_context->state[3]; + hash_context->state[3] = ex; + /* Store state in digest */ + memcpy(hash_result,hash_context->state,SHA_LENGTH); + /* Zeroize sensitive information.*/ + memset( hash_context, 0, sizeof(hash_context) ); +#if defined ( ORD_16 ) && defined( CTK_BIG_ENDIAN ) + WordSwap(hash_result,SHA_LENGTH); +#endif + return status; +} + + +/**************************************************************************** +* NAME: int SHAUpdate( SHA_context *hash_context, +* uchar *message, +* u_int16_t message_bytes ) +* DESCRIPTION: Update Secure Hash Function +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* uchar *message Pointer to message +* u_int16_t message_bytes Number of bytes +* OUTPUT: +* PARAMETERS: +* SHA_context *hash_context Updated SHA context structure +* +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Modified for arbitrary message length +* +****************************************************************************/ + +int SHAUpdate( SHA_context *hash_context, + const uchar *message, + u_int16_t message_bytes ) + +{ + int status = SUCCESS; /* function return status */ + u_int16_t i, index, partLen; + if ( message_bytes == 0 ) + { + status = ERR_INPUT_LEN; /*invalid length for input data (zero bytes)*/ + return status; + } + + /* Compute number of bytes mod 64 */ + index = (u_int16_t)((hash_context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ( (hash_context->count[0] += ((u_int32_t )message_bytes << 3)) + < ((u_int32_t )message_bytes << 3) ) + { + hash_context->count[1]++; + } + hash_context->count[1] += ((u_int32_t )message_bytes >> 29); + + partLen = (u_int16_t) (64 - index); + /* Transform as many times as possible.*/ + if ( message_bytes >= partLen ) + { + memcpy( &hash_context->buffer[index], message, partLen ); + shaTransform( hash_context->state, hash_context->buffer ); + + for ( i = partLen; (u_int16_t)(i + 63) < message_bytes; i += 64 ) + { + shaTransform ( hash_context->state, &message[i] ); + } + index = 0; + } + else + { + i = 0; + } + /* Buffer remaining input */ + memcpy( &hash_context->buffer[index], &message[i], + message_bytes - i ); + return status; +} + + +/**************************************************************************** +* NAME: void SHAInit( SHA_context *hash_context ) +* +* DESCRIPTION: Initialize Secure Hash Function +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* OUTPUT: +* PARAMETERS: +* SHA_context *hash_context Initialized SHA context structure +* +* RETURN: +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ + +void SHAInit( SHA_context *hash_context ) +{ +/*Set up first buffer*/ + hash_context->state[0] = h0SHA; + hash_context->state[1] = h1SHA; + hash_context->state[2] = h2SHA; + hash_context->state[3] = h3SHA; + hash_context->state[4] = h4SHA; + +/* Initialise buffer */ + memset( hash_context->buffer, 0, sizeof(hash_context->buffer)); + /*Initialize bit count*/ + hash_context->count[0] = hash_context->count[1] = 0; +} + +/**************************************************************************** +* NAME: int SHAFinal( SHA_context *hash_context, +* uchar *hash_result ) +* DESCRIPTION: Finalize Secure Hash Function +* +* INPUTS: +* PARAMETERS: +* SHA_context *hash_context SHA context structure +* uchar *hash_result Pointer to hash +* OUTPUT: +* PARAMETERS: +* uchar *hash_result Final value +* RETURN: +* SUCCESS No errors +* ERR_INPUT_LEN Invalid length for input data (zero bytes) +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 10 Oct 94 KPZ Modified for arbitrary message length +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + + +int SHAFinal( SHA_context *hash_context, + uchar *hash_result ) +{ + int status = SUCCESS; /* function return status */ + status = MySHAFinal( hash_context, hash_result ); +#ifdef CTK_BIG_ENDIAN + if (status == SUCCESS) + { + ByteSwap(hash_result, SHA_LENGTH); + } +#endif + if (DataOrder) + { + BigSwap(hash_result, SHA_LENGTH); + } + return status; +} + +/**************************************************************************** +* NAME: int GetPasswordKeySHA( u_int16_t Password_bytes, +* uchar *Password, +* uchar *salt, +* u_int16_t Count, +* uchar *K, +* uchar *IV ) +* +* DESCRIPTION: Get Password-Based DES/KAPPA Key by SHA +* +* INPUTS: +* PARAMETERS: +* u_int16_t Password_bytes Number of bytes in password +* uchar *Password Pointer to password +* uchar *salt Pointer to salt(8-byte) +* u_int16_t Count Number of iteration +* OUTPUT: +* PARAMETERS: +* uchar *K Pointer to DES/KAPPA key +* uchar *IV Pointer to initialization vector +* RETURN: +* SUCCESS No errors +* ERR_COUNT Invalid iteration count (zero) +* ERR_INPUT_LEN Invalid length for input data(zero bytes) +* ERR_ALLOC Insufficient memory +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 26 Oct 94 GKL (ERR_ALLOC) +* +****************************************************************************/ + int GetPasswordKeySHA( u_int16_t Password_bytes, + uchar *Password, + uchar *salt, + u_int16_t Count, + uchar *K, + uchar *IV ) + +{ + int status = SUCCESS; /* function return status */ + uchar digest[SHA_LENGTH]; + uchar *buf; + if ( Count == 0 ) /* invalid iteration count (zero) */ + { + status = ERR_COUNT; + return status; + } + CALLOC(buf,uchar,Password_bytes + 8); + if ( status != SUCCESS ) + { + return status; /* ERR_ALLOC insufficient memory */ + } + if ( Password_bytes != 0 ) /* if number of bytes password non equals zero */ + { + memcpy( buf, Password, Password_bytes ); + } + memcpy( buf + Password_bytes, salt, 8); +/* Compute message digest */ + status = SHA( buf, (u_int16_t)(Password_bytes + 8), digest); + if (!DataOrder) + { + BigSwap(digest, SHA_LENGTH); + } + + if ( status != SUCCESS ) + { + free ( buf ); + return status; + } + Count --; /* decrement Count */ +/* Count times compute message digest */ + while ( Count != 0 ) + { + if ( (status = SHA( digest, SHA_LENGTH, digest)) != SUCCESS ) + { + free ( buf ); + return status; + } + if (!DataOrder) + { + BigSwap(digest, SHA_LENGTH); + } + Count --; + } + memcpy( K, digest, 8 ); + memcpy( IV, digest + SHA_LENGTH -8, 8 ); + free ( buf ); + return status; +} diff --git a/usr/src/lib/libresolv2/common/cylink/sha.h b/usr/src/lib/libresolv2/common/cylink/sha.h new file mode 100644 index 0000000000..8442b3bfab --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/sha.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: sha.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Internal Functions Header File +* +* USAGE: File should be included in Toolkit functions files +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* +****************************************************************************/ +#ifndef SHA_H +#define SHA_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "cylink.h" + +#define SHS_BLOCKSIZE 64 +/* +#define FSHA(x,y,z) ( ( x & y ) | ( ~x & z ) ) +#define GSHA(x,y,z) ( x ^ y ^ z ) +#define HSHA(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) +#define ISHA(x,y,z) (x ^ y ^ z) +*/ +/*#define f1(x,y,z) ( (x & y) | (~x & z) ) // Rounds 0-19 */ +#define f1(x,y,z) ( z ^ (x & (y ^ z) ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +/*#define f3(x,y,z) ( (x & y) | (x & z) | (y & z) ) // Rounds 40-59 */ +#define f3(x,y,z) ( (x & y) | (z & (x | y) ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + + +#define RotateLeft(x,n) (( x << n )|( x >> (32-n) ) ) /*Circular left shift operation*/ + +/* + * Note: for on28 port, and to silence compiler warnings when the value is + * larger than or equal to 0x80000000, change constants to be U rather + * than L. + */ + +/*SHS Constants */ +#define k1SHA 0x5a827999U +#define k2SHA 0x6ed9eba1U +#define k3SHA 0x8f1bbcdcU +#define k4SHA 0xca62c1d6U + +/*SHS initial value */ +#define h0SHA 0x67452301U +#define h1SHA 0xefcdab89U +#define h2SHA 0x98badcfeU +#define h3SHA 0x10325476U +#define h4SHA 0xc3d2e1f0U + +/*The initial expanding function*/ +#define expand(count) \ + {\ + W[count] = W[count-3] ^ W[count-8] ^ W[count-14] ^ W[count-16];\ + W[count] = RotateLeft( W[count], 1 );\ + } + +/*New variant */ +#define subRound(a, b, c, d, e, f, k, data) \ + ( e += RotateLeft(a,5) + f(b, c, d) + k + data, b = RotateLeft( b,30) ) + + + +/*The four sub_rounds*/ +/* +#define subR1(count) \ + {\ + temp=RotateLeft(A,5) + FSHA(B,C,D) + E +W[count] +k1SHA;\ + E = D; \ + D = C; \ + C = RotateLeft(B,30); \ + B = A; \ + A = temp; \ + } + +#define subR2(count) \ + {\ + temp=RotateLeft(A,5) + GSHA(B,C,D) + E +W[count] +k2SHA;\ + E = D; \ + D = C; \ + C = RotateLeft(B,30);\ + B = A; \ + A = temp; \ + } + +#define subR3(count) \ + {\ + temp=RotateLeft(A,5) + HSHA(B,C,D) + E +W[count] +k3SHA;\ + E = D; \ + D = C; \ + C = RotateLeft(B,30);\ + B = A; \ + A = temp; \ + } + +#define subR4(count) \ + {\ + temp=RotateLeft(A,5) + ISHA(B,C,D) + E + W[count] +k4SHA;\ + E = D; \ + D = C; \ + C = RotateLeft(B,30);\ + B = A; \ + A = temp; \ + } +*/ +#endif /* SHA_H */ + diff --git a/usr/src/lib/libresolv2/common/cylink/sizetest.c b/usr/src/lib/libresolv2/common/cylink/sizetest.c new file mode 100644 index 0000000000..6fc9a9ee89 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/sizetest.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "bnsize00.h" + +#if BNSIZE16 +#error Using 16-bit math library +#elif BNSIZE32 +#error Using 32-bit math library +#elif BNSIZE64 +#error Using 64-bit math library +#else +#error No math library size defined +#endif diff --git a/usr/src/lib/libresolv2/common/cylink/swap.c b/usr/src/lib/libresolv2/common/cylink/swap.c new file mode 100644 index 0000000000..6e4f33b967 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/swap.c @@ -0,0 +1,218 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + + +/**************************************************************************** +* FILENAME: swap.c PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Byte and Word Swap functions +* +* PUBLIC FUNCTIONS: +* +* +* PRIVATE FUNCTIONS: +* +* REVISION HISTORY: +* +* 14 Oct 94 GKL Initial release +* 26 Oct 94 GKL (alignment for big endian support ) +* +****************************************************************************/ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ +/* system files */ + +#include "port_before.h" +#ifdef VXD +#include <vtoolsc.h> +#else +#include <stdlib.h> +#include <string.h> +#endif +/* program files */ +#include "cylink.h" +#include "ctk_endian.h" +#include "toolkit.h" +#include "port_after.h" + +u_int16_t DataOrder = 0; + +/*Reset bytes in long*/ +/*extern void ByteSwap32_asm( uchar *X, u_int16_t X_len );*/ /*kz*/ + +/**************************************************************************** +* NAME: void ByteSwap32 (uchar *array, +* u_int16_t X_len ) +* +* DESCRIPTION: Perform byte reversal on an array of longword. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to array +* u_int16_t X_len Number of bytes +* OUTPUT: +* uchar *X Pointer to array +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + + +void ByteSwap32( uchar *X, u_int16_t X_len ) +{ + u_int16_t i; /*counter*/ + uchar a; /*temporary char*/ + for ( i = 0; i < X_len; i += 4) + { + a = X[i]; + X[i] = X[i+3]; + X[i+3] = a; + a = X[i+1]; + X[i+1] = X[i+2]; + X[i+2] = a; + } +/*#endif*/ /*kz*/ +} + + +/**************************************************************************** +* NAME: void ByteSwap (uchar *array, +* u_int16_t X_len ) +* +* DESCRIPTION: Perform byte reversal on an array of longword or shortword. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to array +* u_int16_t X_len Number of bytes +* OUTPUT: +* uchar *X Pointer to array +* +* REVISION HISTORY: +* +* 24 Sep 94 KPZ Initial release +* 14 Oct 94 GKL Second version (big endian support) +* +****************************************************************************/ + +void ByteSwap( uchar *X, + u_int16_t X_len ) +{ +#ifdef ORD_16 + u_int16_t i; /*counter*/ + uchar a; /*tempriory char for revers*/ + for ( i = 0; i < X_len; i += 2) + { + a = X[i]; + X[i] = X[i+1]; + X[i+1] = a; + } +#endif +#ifdef ORD_32 + ByteSwap32(X,X_len); +#endif +} + +/*kz longbyte deleted */ + +/**************************************************************************** +* NAME: void WordSwap (uchar *array, +* u_int16_t X_len ) +* +* DESCRIPTION: Perform short reversal on an array of longword. +* +* INPUTS: +* PARAMETERS: +* uchar *X Pointer to array +* u_int16_t X_len Number of bytes +* OUTPUT: +* uchar *X Pointer to array +* +* REVISION HISTORY: +* +* 14 Oct 94 GKL Initial release +* +****************************************************************************/ +void WordSwap( uchar *X, + u_int16_t X_len ) +{ + u_int16_t i; /*counter*/ + u_int16_t a; /*tempriory u_int16_t*/ + + for ( i = 0; i < X_len; i += 4) + { + a = *(u_int16_t*)(&X[i]); + *(u_int16_t*)(&X[i])=*(u_int16_t*)(&X[i+2]); + *(u_int16_t*)(&X[i+2])=a; + } +} + +void BigSwap( uchar *buffer, + u_int16_t bufferLength) +{ + uchar temp; + u_int16_t i; + + for (i = 0; i < (u_int16_t)(bufferLength/2); i++) + { + temp = buffer[i]; + buffer[i] = buffer[bufferLength - 1 - i]; + buffer[bufferLength - 1 - i] = temp; + } +} + +void SetDataOrder ( u_int16_t dataOrder) +{ + DataOrder = dataOrder; +} diff --git a/usr/src/lib/libresolv2/common/cylink/toolkit.h b/usr/src/lib/libresolv2/common/cylink/toolkit.h new file mode 100644 index 0000000000..b9ba25ad57 --- /dev/null +++ b/usr/src/lib/libresolv2/common/cylink/toolkit.h @@ -0,0 +1,399 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Cylink Corporation © 1998 + * + * This software is licensed by Cylink to the Internet Software Consortium to + * promote implementation of royalty free public key cryptography within IETF + * standards. Cylink wishes to expressly thank the contributions of Dr. + * Martin Hellman, Whitfield Diffie, Ralph Merkle and Stanford University for + * their contributions to Internet Security. In accordance with the terms of + * this license, ISC is authorized to distribute and sublicense this software + * for the practice of IETF standards. + * + * The software includes BigNum, written by Colin Plumb and licensed by Philip + * R. Zimmermann for royalty free use and distribution with Cylink's + * software. Use of BigNum as a stand alone product or component is + * specifically prohibited. + * + * Disclaimer of All Warranties. THIS SOFTWARE IS BEING PROVIDED "AS IS", + * WITHOUT ANY EXPRESSED OR IMPLIED WARRANTY OF ANY KIND WHATSOEVER. IN + * PARTICULAR, WITHOUT LIMITATION ON THE GENERALITY OF THE FOREGOING, CYLINK + * MAKES NO REPRESENTATION OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR + * PURPOSE. + * + * Cylink or its representatives shall not be liable for tort, indirect, + * special or consequential damages such as loss of profits or loss of + * goodwill from the use or inability to use the software for any purpose or + * for any reason whatsoever. + * + * EXPORT LAW: Export of the Foundations Suite may be subject to compliance + * with the rules and regulations promulgated from time to time by the Bureau + * of Export Administration, United States Department of Commerce, which + * restrict the export and re-export of certain products and technical data. + * If the export of the Foundations Suite is controlled under such rules and + * regulations, then the Foundations Suite shall not be exported or + * re-exported, directly or indirectly, (a) without all export or re-export + * licenses and governmental approvals required by any applicable laws, or (b) + * in violation of any applicable prohibition against the export or re-export + * of any part of the Foundations Suite. All export licenses for software + * containing the Foundations Suite are the sole responsibility of the licensee. + */ + +/**************************************************************************** +* FILENAME: toolkit.h PRODUCT NAME: CRYPTOGRAPHIC TOOLKIT +* +* FILE STATUS: +* +* DESCRIPTION: Cryptographic Toolkit Functions Header File +* +* USAGE: File should be included to use Toolkit Functions +* +* +* Copyright (c) Cylink Corporation 1994. All rights reserved. +* +* REVISION HISTORY: +* +* 23 Aug 94 KPZ Initial release +* 24 Sep 94 KPZ Added prototypes of Toolkit functions +* 14 Oct 94 GKL Second version (big endian support) +* 08 Dec 94 GKL Added YIELD_context to GenDSSParameters +* +****************************************************************************/ + +#ifndef TOOLKIT_H /* Prevent multiple inclusions of same header file */ +#define TOOLKIT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Error types */ + +#define SUCCESS 0 /* no errors */ +#define ERR_DATA -1 /* generic data error */ +#define ERR_ALLOC -2 /* insufficient memory */ +#define ERR_INPUT_LEN -3 /* invalid length for input data (zero bytes) */ +#define ERR_DSS_LEN -4 /* invalid length for dss_p */ +#define ERR_DH_LEN -5 /* invalid length for DH_modulus */ +#define ERR_BLOCK_LEN -7 /* invalid length for input block for ECB/CBC */ +#define ERR_HASH_LEN -8 /* invalid length for hash_result */ +#define ERR_MODE -9 /* invalid value of encryption mode */ +#define ERR_NUMBER -10 /* invalid number of testings (zero) */ +#define ERR_POSITION -11 /* invalid value of triplet_position */ +#define ERR_COUNT -12 /* invalid iteration count (zero) */ +#define ERR_SIGNATURE -21 /* signature is not valid */ +#define ERR_PRIME -22 /* number is not prime */ +#define ERR_WEAK -23 /* weak key */ +#define ERR_INPUT_VALUE -24 /* invalid input value */ +/* additional error types for CEPA */ +#define ERR_KEY_LENGTH -25 /* invalid value of key length */ +#define ERR_ROUNDS -26 /* invalid value of rounds number */ +#define ERR_CANCEL -30 /* canceled by user */ +#define ERR_MODULUS_ZERO -31 /* invalid modulo */ +#define ERR_UNSUPPORTED -40 /* unsupported crypto method */ +#define ERR_OP_CODE -41 /*invalid operation code*/ + + + +/* Lengths of variables */ +#define DH_LENGTH_MIN 64 /* 512-bit minimal length for DH functions */ +#define DSS_LENGTH_MIN 64 /* 512-bit minimal length for DSS functions */ +#define DSS_LENGTH_MAX 128 /* 1024-bit maximal length for DSS functions */ +#define SHA_LENGTH 20 /* 160-bit length for SHA hash result */ + +/* Number of random bases for Miller test */ +#define TEST_COUNT 40 + +#define LITTLE_ORDER 0 +#define BIG_ORDER 1 + +/* Key lengths */ /* add to toolkit.h */ +#define KEY_40BIT 40 /* 40-bit key */ +#define KEY_64BIT 64 /* 64-bit key */ +#define KEY_128BIT 128 /* 128-bit key */ +#define CEPA_MAX_ROUNDS 12 + +/* Operation codes for MultiPrecArithm() */ +#define EXPO 0x21 +#define MUL 0x22 +/*#define ADD 0x23*/ + +/**************************************************************************** +* INCLUDE FILES +****************************************************************************/ + +/* system files */ +#include "cylink.h" +#include "ctk_endian.h" +/* callback function */ +#ifdef VXD +typedef int (* YIELD_PROC)( void ); +#else +typedef int (* YIELD_PROC)(int ); /*TKL00601*/ +#endif + +typedef struct { /*TKL00601*/ + YIELD_PROC yield_proc; + void * handle; /* Application specific information */ +}YIELD_context; + + +/* Secure Hash Algorithm structure */ +typedef struct +{ + u_int32_t state[ 5 ]; /* state */ + u_int32_t count[ 2 ]; /* number of bits */ + uchar buffer[ 64 ]; /* input buffer */ +} SHA_context; + + +#ifdef __cplusplus +extern "C" { +#endif +/* Copy Cylink DSS Common Parameters */ /*TKL01201*/ + int GetDSSPQG(u_int16_t dss_p_bytes, + uchar *dss_p, + uchar *dss_q, + uchar *dss_g); + +/* Compute a Secure Hash Function */ + int SHA( uchar *message, u_int16_t message_bytes, + uchar *hash_result ); +/* Initialize Secure Hash Function */ + void SHAInit( SHA_context *hash_context ); + +/* Update Secure Hash Function */ + int SHAUpdate( SHA_context *hash_context, + const uchar *message, + u_int16_t message_bytes ); +/* Finalize Secure Hash Function */ + int SHAFinal( SHA_context *hash_context, + uchar *hash_result ); +/* Compute a DSS Signature */ + int GenDSSSignature( u_int16_t dss_p_bytes, uchar *dss_p, + uchar *dss_q, uchar *dss_g, + uchar *dss_x, uchar *dss_k, + uchar *r, uchar *s, + uchar *hash_result ); +/* Verify a DSS Signature */ + int VerDSSSignature( u_int16_t dss_p_bytes, uchar *dss_p, + uchar *dss_q, uchar *dss_g, + uchar *dss_y, uchar *r, + uchar *s, uchar *hash_result); +/* Initialize Random number Generator */ + int InitRand( u_int16_t SEED_bytes, uchar *SEED, + uchar *RVAL ); +/* Generate random number */ + int GenRand( u_int16_t A_bytes, uchar *A, + uchar *RVAL ); +/* Compute DSS public/secret number pair */ + int GenDSSKey( u_int16_t dss_p_bytes, uchar *dss_p, + uchar *dss_q, uchar *dss_g, + uchar *dss_x, uchar *dss_y, + uchar *XKEY ); +/* Generate secret number */ + int GenDSSNumber( uchar *dss_k, uchar *dss_q, + uchar *KKEY ); + +/* Compute a Diffie-Hellman Shared number */ + int GetDHSharedNumber( u_int16_t DH_modulus_bytes, uchar *DH_secret, + uchar *DH_public, uchar *DH_shared, + uchar *DH_modulus ); +/* Set Key by Diffie_Hellman shared number */ + int SetDESKAPPAKey( u_int16_t DH_modulus_bytes, uchar *DH_shared, + uchar *K ); +/* Expand DES key */ + void DESKeyExpand( uchar *key, uchar *K1 ); + +/* Encrypt a block of data with single DES */ + int DESEncrypt( uchar *des_iv, uchar *des_key, + u_int16_t des_mode, uchar *input_array, + uchar *output_array, u_int16_t input_array_bytes ); + +/* Decrypt a block of data with single DES */ + int DESDecrypt( uchar *des_iv, uchar *des_key, + u_int16_t des_mode, uchar *data_array, + u_int16_t data_array_bytes ); + +/* One-Time-Pad Signature with a Diffie-Hellman shared number */ + int DHOneTimePad( u_int16_t DH_modulus_bytes, uchar *DH_shared, + uchar *X, uchar *Y ); + +/* Compute a Diffie-Hellman pair */ + int GenDHPair( u_int16_t DH_modulus_bytes, uchar *DH_secret, + uchar *DH_public, uchar *DH_base, + uchar *DH_modulus, uchar *RVAL ); + + int GetPasswordKeySHA( u_int16_t Password_bytes, uchar *Password, + uchar *salt, u_int16_t Count, + uchar *K, uchar *IV ); + +/* Generate DSS Common Parameters */ + int GenDSSParameters( u_int16_t dss_p_bytes, uchar *dss_p, + uchar *dss_q, uchar *dss_g, + uchar *RVAL, YIELD_context *yield_cont ); /*TKL00701*/ + +/* Produce a Shamir Key-Sharing Triplet for Secret Number */ +int GenShamirTriplet( u_int16_t SecretNumber_bytes, uchar *SecretNumber, + uchar *first_value, uchar *second_value, + uchar *third_value, uchar *RVAL ); + +/* Reconstract a Secret Number from Shamir Key-Sharing Duplex */ +int GetNumberShamirDuplex( u_int16_t SecretNumber_bytes, + uchar *value_A, + u_int16_t A_position, uchar *value_B, + u_int16_t B_position, + uchar *SecretNumber ); +int SFDHEncrypt( u_int16_t DH_modulus_bytes, + uchar *DH_modulus, + uchar *DH_base, + uchar *DH_public, + uchar *DH_random_public, + uchar *DH_shared, + uchar *RVAL ); +int SFDHDecrypt( u_int16_t DH_modulus_bytes, + uchar *DH_modulus, + uchar *DH_secret, + uchar *DH_random_public, + uchar *DH_shared ); +/* Check DES key weakness */ +int CheckDESKeyWeakness( uchar *key ); + +int SetCipherKey( u_int16_t DH_shared_bytes, + uchar *DH_shared, + uchar *Key, + u_int16_t cryptoMethod ); +/* Non-Pipelined Triple DES encrypt*/ +int TDESEncrypt( uchar *des_iv, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + u_int16_t des_mode, + uchar *input_array, + uchar *output_array, + u_int16_t input_array_bytes ); +/* Non-Pipelined Triple DES decrypt*/ +int TDESDecrypt( uchar *des_iv, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + u_int16_t des_mode, + uchar *data_array, + u_int16_t data_array_bytes ); +/*Pipeline Triple DES encrypt*/ +int PTDESEncrypt( uchar *iv1, uchar *iv2, uchar *iv3, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + u_int16_t des_mode, + uchar *input_array, + uchar *output_array, + u_int16_t input_array_bytes ); +/*Pipeline Triple DES decrypt*/ +int PTDESDecrypt( uchar *iv1, uchar *iv2, uchar *iv3, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + u_int16_t des_mode, + uchar *data_array, + u_int16_t input_array_bytes ); + int PCBC1Encrypt( uchar *iv1, uchar *iv2, uchar *iv3, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + uchar *msg1,uchar *msg2, uchar *msg3, + uchar *out1,uchar *out2, uchar *out3, + u_int16_t input_array_bytes ); + int PCBC1Decrypt( uchar *iv1, uchar *iv2, uchar *iv3, + uchar *des_key1,uchar *des_key2, uchar *des_key3, + uchar *out1,uchar *out2, uchar *out3, + u_int16_t input_array_bytes ); + +/*CEPA enc/dec */ +int CepaKeyExpand( uchar *key, + u_int16_t key_length, + u_int16_t number_of_rounds, + uchar *expanded_key ); + +int CepaCsp( u_int16_t key_length, + uchar *csp); + +int CepaEncrypt( uchar *iv, + uchar *key, + u_int16_t mode, + uchar *csp, + u_int16_t r, + uchar *input_array, + uchar *output_array, + u_int16_t input_array_bytes ); + +int CepaDecrypt( uchar *iv, + uchar *key, + u_int16_t mode, + uchar *csp, + u_int16_t r, + uchar *data_array, + u_int16_t data_array_bytes ); +void BigNumInit(void); +void SetDataOrder ( u_int16_t dataOrder); + +int GetDHSecretShared( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, uchar *DH_secret, + uchar *DH_public, uchar *DH_shared, + uchar *DH_modulus); +int GenDHKey( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, uchar *DH_secret, + uchar *DH_public, uchar *DH_base, + uchar *DH_modulus, uchar *RVAL ); +int SFDHInitiate( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, + uchar *DH_modulus, uchar *DH_base, + uchar *DH_public, uchar *DH_random_public, + uchar *DH_shared, uchar *RVAL ); +int SFDHComplete( u_int16_t DH_modulus_bytes, u_int16_t DH_secret_bytes, + uchar *DH_modulus, + uchar *DH_secret, uchar *DH_random_public, + uchar *DH_shared ); + +int SplitKey( u_int16_t Secretnumber_bytes, uchar *SecretNumber, + uchar *first_value, uchar *second_value, + uchar *third_value, uchar *RVAL ); +int UnsplitKey( u_int16_t Secretnumber_bytes, uchar *value_A, + u_int16_t A_position, uchar *value_B, + u_int16_t B_position, uchar *SecretNumber ); +int SAFERKeyExpand( uchar *key, u_int16_t key_length, + uchar *expanded_key ); +int SAFEREncrypt( uchar *iv, uchar *key, u_int16_t mode, u_int16_t key_length, + uchar *input_array, uchar *output_array, u_int16_t input_array_bytes ); +int SAFERDecrypt( uchar *iv, uchar *key, u_int16_t mode, u_int16_t r_length, + uchar *data_array, u_int16_t data_array_bytes ); + + + void ByteSwap( uchar *X, u_int16_t X_len); + void ByteSwap32( uchar *X, u_int16_t X_len); + void WordSwap( uchar *X, u_int16_t X_len); + void BigSwap( uchar *buffer, u_int16_t bufferLength); + int Sum_big (ord *X, ord *Y, ord *Z, u_int16_t len_X); + int Sum_Q(ord *X, u_int16_t src, u_int16_t len_X); + void LShiftL_big( ord *X, u_int32_t len_X, u_int32_t n_bit ); + int Sub_big (ord *X, ord *Y, ord *Z, u_int16_t len_X); + int DivRem( u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P, + ord *Z, ord *D); + int SteinGCD (ord *m, ord *n, u_int16_t len); + int Add( ord *X, ord *Y, u_int16_t P_len, ord *P); + int Inverse(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P, + ord *Z); + int DoubleExpo(u_int16_t X1_bytes, ord *X1, u_int16_t Y1_bytes, + ord *Y1, u_int16_t X2_bytes, ord *X2, + u_int16_t Y2_bytes, ord *Y2, u_int16_t P_bytes, + ord *P, ord *Z); + int Sum (ord *X, ord *Y, u_int16_t len_X); + void Mul_big_1( ord X, ord *Y, ord *XY, u_int16_t ly); + int Mul( u_int16_t X_bytes, ord *X, u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, ord *Z ); + + int Square(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P, + ord *Z); + + int PartReduct(u_int16_t X_bytes, ord *X, u_int16_t P_bytes, ord *P, + ord *Z); + int Expo(u_int16_t X_bytes, ord *X, u_int16_t Y_bytes, ord *Y, + u_int16_t P_bytes, ord *P, ord *Z); + + +#ifdef __cplusplus +} +#endif + + +#endif /* TOOLKIT_H */ + diff --git a/usr/src/lib/libresolv2/common/dnssafe/README.copyright b/usr/src/lib/libresolv2/common/dnssafe/README.copyright new file mode 100644 index 0000000000..bfbd0a4d3b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/README.copyright @@ -0,0 +1,51 @@ +#pragma ident "%Z%%M% %I% %E% SMI" + +[The copyright in this file amends the "RSA Data Security, Inc." copyrights +in the source files in this directory, according to an email from David R. +Conrad, executive director at ISC, on 02/07/2000.] + + + + DNSSAFE LICENSE TERMS + +This BIND software includes the DNSsafe software from RSA Data +Security, Inc., which is copyrighted software that can only be +distributed under the terms of this license agreement. + +The DNSsafe software cannot be used or distributed separately from the +BIND software. You only have the right to use it or distribute it as +a bundled, integrated product. + +The DNSsafe software can ONLY be used to provide authentication for +resource records in the Domain Name System, as specified in RFC 2065 +and successors. You cannot modify the BIND software to use the +DNSsafe software for other purposes, or to make its cryptographic +functions available to end-users for other uses. + +If you modify the DNSsafe software itself, you cannot modify its +documented API, and you must grant RSA Data Security the right to use, +modify, and distribute your modifications, including the right to use +any patents or other intellectual property that your modifications +depend upon. + +You must not remove, alter, or destroy any of RSA's copyright notices +or license information. When distributing the software to the Federal +Government, it must be licensed to them as "commercial computer +software" protected under 48 CFR 12.212 of the FAR, or 48 CFR +227.7202.1 of the DFARS. + +You must not violate United States export control laws by distributing +the DNSsafe software or information about it, when such distribution +is prohibited by law. + +THE DNSSAFE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY +WHATSOEVER. RSA HAS NO OBLIGATION TO SUPPORT, CORRECT, UPDATE OR +MAINTAIN THE RSA SOFTWARE. RSA DISCLAIMS ALL WARRANTIES, EXPRESS, +IMPLIED OR STATUTORY, AS TO ANY MATTER WHATSOEVER, INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY RIGHTS. + +If you desire to use DNSsafe in ways that these terms do not permit, +please contact RSA Data Security, Inc., 100 Marine Parkway, Redwood +City, California 94065, USA, to discuss alternate licensing +arrangements. diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.c b/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.c new file mode 100644 index 0000000000..bfdfd048aa --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.c @@ -0,0 +1,183 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHSecretCBCPad; +#define THIS_ENCRYPT_DECRYPT struct AHSecretCBCPad + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahcbcpad.h" +#include "port_after.h" + +#define GENERATE_BREAK(type) { \ + status = type; \ + break; \ + } + +/* Inherit the base class destructor, block size, + and decrypt init and update routines. + */ +static AHEncryptDecryptVTable V_TABLE = { + AHChooseEncryptDestructor, AHChooseEncryptGetBlockLen, + AHSecretCBCPadEncryptInit, AHChooseEncryptDecryptInit, + AHSecretCBCPadEncryptUpdate, AHChooseEncryptDecryptUpdate, + AHSecretCBCPadEncryptFinal, AHSecretCBCPadDecryptFinal +}; + +AHSecretCBCPad *AHSecretCBCPadConstructor2 (handler, infoType, info) +AHSecretCBCPad *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHSecretCBCPad *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHSecretCBCPad *)T_malloc (sizeof (*handler))) + == (AHSecretCBCPad *)NULL_PTR) + return (handler); + } + + /* Construct base class with the infoType and info. */ + AHChooseEncryptConstructor2 + (&handler->chooseEncryptDecrypt, infoType, info); + + handler->chooseEncryptDecrypt.encryptDecrypt.vTable = &V_TABLE; + return (handler); +} + +int AHSecretCBCPadEncryptInit (handler, key, chooser, surrenderContext) +AHSecretCBCPad *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + /* For encryption, we need to track the input length */ + handler->_inputRemainder = 0; + + return (AHChooseEncryptEncryptInit + (handler, key, chooser, surrenderContext)); +} + +int AHSecretCBCPadEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +AHSecretCBCPad *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + /* For encryption, we need to track the input length */ + handler->_inputRemainder = (handler->_inputRemainder + partInLen) % 8; + + return (AHChooseEncryptEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext)); +} + +int AHSecretCBCPadEncryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AHSecretCBCPad *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned char finalBuffer[8]; + unsigned int padLen, dummyPartOutLen; + + padLen = 8 - handler->_inputRemainder; + T_memset ((POINTER)finalBuffer, padLen, padLen); + + /* Add the pad bytes. This should force the output of the final block. + */ + if ((status = AHChooseEncryptEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, finalBuffer, padLen, + randomAlgorithm, surrenderContext)) != 0) + return (status); + + /* The encrypt final operation should have no output. */ + if ((status = AHChooseEncryptEncryptFinal + (handler, (unsigned char *)NULL_PTR, &dummyPartOutLen, 0, + (B_Algorithm *)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR)) != 0) + return (status); + + /* Restart the context. */ + handler->_inputRemainder = 0; + + /* No need to zeroize the finalBuffer since it only contains pad bytes. */ + return (0); +} + +int AHSecretCBCPadDecryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AHSecretCBCPad *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned char finalBuffer[16], *padBuffer; + unsigned int padLen, localPartOutLen, i; + + do { + /* For now, the DecrypyFinal operations is set to output 16 bytes. + */ + if ((status = AHChooseEncryptDecryptFinal + (handler, finalBuffer, &localPartOutLen, sizeof (finalBuffer), + randomAlgorithm, surrenderContext)) != 0) + break; + + if (localPartOutLen == 8) + padBuffer = finalBuffer; + else if (localPartOutLen == 16) + padBuffer = finalBuffer + 8; + else + GENERATE_BREAK (BE_INPUT_LEN); + + /* Check that padding is one 1 to eight 8's. + */ + if ((padLen = (unsigned int)padBuffer[7]) == 0 || padLen > 8) + GENERATE_BREAK (BE_INPUT_DATA); + for (i = 8 - padLen; i < 8; i++) { + if ((unsigned int)padBuffer[i] != padLen) + GENERATE_BREAK (BE_INPUT_DATA); + } + + if ((*partOutLen = localPartOutLen - padLen) > maxPartOutLen) + GENERATE_BREAK (BE_OUTPUT_LEN); + + T_memcpy + ((POINTER)partOut, (POINTER)finalBuffer, *partOutLen); + } while (0); + + T_memset ((POINTER)finalBuffer, 0, sizeof (finalBuffer)); + return (status); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.h b/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.h new file mode 100644 index 0000000000..e72a5d770c --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahcbcpad.h @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCBCPAD_H_ +#define _AHCBCPAD_H_ + +#include "ahchencr.h" + +typedef struct AHSecretCBCPad { + AHChooseEncryptDecrypt chooseEncryptDecrypt; /* base class */ + + unsigned int _inputRemainder; /* Used for encrypt to compute pad length */ +} AHSecretCBCPad; + +AHSecretCBCPad *AHSecretCBCPadConstructor2 PROTO_LIST + ((AHSecretCBCPad *, struct B_AlgorithmInfoType *, POINTER)); + +int AHSecretCBCPadEncryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AHSecretCBCPadEncryptUpdate PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); +int AHSecretCBCPadEncryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int AHSecretCBCPadDecryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahchdig.c b/usr/src/lib/libresolv2/common/dnssafe/ahchdig.c new file mode 100644 index 0000000000..574bdb8154 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahchdig.c @@ -0,0 +1,139 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHChooseDigest; +#define THIS_DIGEST struct AHChooseDigest + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "balgmeth.h" +#include "ahchdig.h" +#include "amdigest.h" +#include "port_after.h" + +static int InitDigestAlga PROTO_LIST + ((AlgaChoice *, POINTER, B_ALGORITHM_METHOD *, A_SURRENDER_CTX *)); + +static AHDigestVTable V_TABLE = { + AHChooseDigestDestructor, AHChooseDigestInit, AHChooseDigestUpdate, + AHChooseDigestFinal +}; + +AHChooseDigest *AHChooseDigestConstructor2 (handler, infoType, info) +AHChooseDigest *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHChooseDigest *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHChooseDigest *)T_malloc (sizeof (*handler))) + == (AHChooseDigest *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AHDigestConstructor (&handler->digest); + + ALGA_CHOICE_Constructor (&handler->algaChoice, InitDigestAlga); + handler->algaChoice._algorithmInfoType = infoType; + handler->algaChoice._algorithmInfo = info; + + handler->digest.vTable = &V_TABLE; + + return (handler); +} + +void AHChooseDigestDestructor (handler) +AHChooseDigest *handler; +{ + ALGA_CHOICE_Destructor (&handler->algaChoice); + /* There is no desructor to call for the base class. */ +} + +int AHChooseDigestInit (handler, key, chooser, surrenderContext) +AHChooseDigest *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->algaChoice, 0, key, chooser, surrenderContext)); +} + +int AHChooseDigestUpdate (handler, partIn, partInLen, surrenderContext) +AHChooseDigest *handler; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = (*((A_DIGEST_ALGA *)handler->algaChoice._alga)->Update) + (handler->algaChoice.context.z.context, partIn, partInLen, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseDigestFinal + (handler, partOut, partOutLen, maxPartOutLen, surrenderContext) +AHChooseDigest *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = (*((A_DIGEST_ALGA *)handler->algaChoice._alga)->Final) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +static int InitDigestAlga + (algaChoice, keyInfo, algorithmMethod, surrenderContext) +AlgaChoice *algaChoice; +POINTER keyInfo; +B_ALGORITHM_METHOD *algorithmMethod; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int contextSize; + +UNUSED_ARG (keyInfo) + if ((status = (*((A_DIGEST_ALGA *)algorithmMethod->alga)->Query) + (&contextSize, algaChoice->_algorithmInfo)) != 0) + return (ConvertAlgaeError (status)); + + if ((status = ResizeContextMakeNewContext + (&algaChoice->context, contextSize)) != 0) + return (status); + + if ((status = (*((A_DIGEST_ALGA *)algorithmMethod->alga)->Init) + (algaChoice->context.z.context, algaChoice->_algorithmInfo, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahchdig.h b/usr/src/lib/libresolv2/common/dnssafe/ahchdig.h new file mode 100644 index 0000000000..a80c3d208e --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahchdig.h @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCHDIG_H_ +#define _AHCHDIG_H_ 1 + +#include "ahdigest.h" +#include "algchoic.h" + +typedef struct AHChooseDigest { + AHDigest digest; /* base class */ + AlgaChoice algaChoice; +} AHChooseDigest; + +AHChooseDigest *AHChooseDigestConstructor2 PROTO_LIST + ((AHChooseDigest *, struct B_AlgorithmInfoType *, POINTER)); +void AHChooseDigestDestructor PROTO_LIST ((THIS_DIGEST *)); + +int AHChooseDigestInit PROTO_LIST + ((THIS_DIGEST *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int AHChooseDigestUpdate PROTO_LIST + ((THIS_DIGEST *, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int AHChooseDigestFinal PROTO_LIST + ((THIS_DIGEST *, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahchencr.c b/usr/src/lib/libresolv2/common/dnssafe/ahchencr.c new file mode 100644 index 0000000000..6d339824fc --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahchencr.c @@ -0,0 +1,275 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHChooseEncryptDecrypt; +#define THIS_ENCRYPT_DECRYPT struct AHChooseEncryptDecrypt + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "balgmeth.h" +#include "ahchencr.h" +#include "amencdec.h" +#include "port_after.h" + +static int InitEncryptDecryptAlga PROTO_LIST + ((AlgaChoice *, POINTER, B_ALGORITHM_METHOD *, A_SURRENDER_CTX *)); + +static AHEncryptDecryptVTable V_TABLE = { + AHChooseEncryptDestructor, AHChooseEncryptGetBlockLen, + AHChooseEncryptEncryptInit, AHChooseEncryptDecryptInit, + AHChooseEncryptEncryptUpdate, AHChooseEncryptDecryptUpdate, + AHChooseEncryptEncryptFinal, AHChooseEncryptDecryptFinal +}; + +/* In C++: +AHChooseEncryptDecrypt::AHChooseEncryptDecrypt + (B_AlgorithmInfoType *infoType, POINTER info) + : algaChoice (InitEncryptDecryptAlga) +{ + algaChoice.setAlgorithmInfoType (infoType); + algaChoice.setAlgorithmInfo (info); +} + */ +AHChooseEncryptDecrypt *AHChooseEncryptConstructor2 (handler, infoType, info) +AHChooseEncryptDecrypt *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHChooseEncryptDecrypt *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHChooseEncryptDecrypt *)T_malloc (sizeof (*handler))) + == (AHChooseEncryptDecrypt *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AHEncryptDecryptConstructor (&handler->encryptDecrypt); + + ALGA_CHOICE_Constructor (&handler->algaChoice, InitEncryptDecryptAlga); + handler->algaChoice._algorithmInfoType = infoType; + handler->algaChoice._algorithmInfo = info; + + handler->encryptDecrypt.vTable = &V_TABLE; + + return (handler); +} + +void AHChooseEncryptDestructor (handler) +AHChooseEncryptDecrypt *handler; +{ + ALGA_CHOICE_Destructor (&handler->algaChoice); + /* There is no desructor to call for the base class. */ +} + +int AHChooseEncryptGetBlockLen (handler, blockLen) +AHChooseEncryptDecrypt *handler; +unsigned int *blockLen; +{ + int status; + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)-> + GetBlockLen) + (handler->algaChoice.context.z.context, blockLen)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +/* In C++: +int AHChooseEncryptDecrypt::encryptInit + (B_Key *key, B_ALGORITHM_CHOOSER chooser, A_SURRENDER_CTX *surrenderContext) +{ + return (algaChoice.choose (1, key, chooser, surrenderContext)); +} + */ +int AHChooseEncryptEncryptInit (handler, key, chooser, surrenderContext) +AHChooseEncryptDecrypt *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->algaChoice, 1, key, chooser, surrenderContext)); +} + +int AHChooseEncryptDecryptInit (handler, key, chooser, surrenderContext) +AHChooseEncryptDecrypt *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->algaChoice, 0, key, chooser, surrenderContext)); +} + +/* In C++: +int AHChooseEncryptDecrypt::encryptUpdate + (unsigned char *partOut, unsigned int *partOutLen, + unsigned int maxPartOutLen, unsigned char *partIn, unsigned int partInLen, + B_Algorithm *randomAlgorithm, A_SURRENDER_CTX *surrenderContext) +{ + int status; + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)algaChoice.alga ()) ->Update) + (algaChoice.context (), partOut, partOutLen, maxPartOutLen, + partIn, partInLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + */ +int AHChooseEncryptEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +AHChooseEncryptDecrypt *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + +UNUSED_ARG (randomAlgorithm) + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)-> + Update) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, partIn, partInLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseEncryptDecryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +AHChooseEncryptDecrypt *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + +UNUSED_ARG (randomAlgorithm) + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)-> + Update) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, partIn, partInLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseEncryptEncryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AHChooseEncryptDecrypt *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + +UNUSED_ARG (randomAlgorithm) + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)->Final) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseEncryptDecryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AHChooseEncryptDecrypt *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + +UNUSED_ARG (randomAlgorithm) + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)handler->algaChoice._alga)->Final) + (handler->algaChoice.context.z.context, partOut, partOutLen, + maxPartOutLen, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +/* In C++: +static int InitEncryptDecryptAlga + (AlgaChoice *algaChoice, POINTER keyInfo, POINTER alga, + A_SURRENDER_CTX *surrenderContext) +{ + int status; + unsigned int contextSize; + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)alga)->Query) + (&contextSize, keyInfo, algaChoice->algorithmInfo ())) != 0) + return (ConvertAlgaeError (status)); + + if ((status = algaChoice->makeNewContext (contextSize)) != 0) + return (status); + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)alga)->Init) + (algaChoice->context (), keyInfo, algaChoice->algorithmInfo (), + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} + */ +static int InitEncryptDecryptAlga + (algaChoice, keyInfo, algorithmMethod, surrenderContext) +AlgaChoice *algaChoice; +POINTER keyInfo; +B_ALGORITHM_METHOD *algorithmMethod; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int contextSize; + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)algorithmMethod->alga)->Query) + (&contextSize, keyInfo, algaChoice->_algorithmInfo)) != 0) + return (ConvertAlgaeError (status)); + + if ((status = ResizeContextMakeNewContext + (&algaChoice->context, contextSize)) != 0) + return (status); + + if ((status = (*((A_ENCRYPT_DECRYPT_ALGA *)algorithmMethod->alga)->Init) + (algaChoice->context.z.context, keyInfo, algaChoice->_algorithmInfo, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahchencr.h b/usr/src/lib/libresolv2/common/dnssafe/ahchencr.h new file mode 100644 index 0000000000..82e1a59244 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahchencr.h @@ -0,0 +1,81 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCHENCR_H_ +#define _AHCHENCR_H_ 1 + +#include "ahencryp.h" +#include "algchoic.h" + +/* In C++: +class AHChooseEncryptDecrypt : public AHEncryptDecrypt { +public: + AHChooseEncryptDecrypt (B_AlgorithmInfoType *, POINTER); + virtual ~AHChooseEncryptDecrypt () {}; + + virtual int getBlockLen (unsigned int *); + virtual int encryptInit (B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *); + virtual int decryptInit (B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *); + virtual int encryptUpdate + (unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *); + virtual int decryptUpdate + (unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *); + virtual int encryptFinal + (unsigned char *, unsigned int *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *); + virtual int decryptFinal + (unsigned char *, unsigned int *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *); + +private: + AlgaChoice algaChoice; +}; + */ + +typedef struct AHChooseEncryptDecrypt { + AHEncryptDecrypt encryptDecrypt; /* base class */ + AlgaChoice algaChoice; +} AHChooseEncryptDecrypt; + +AHChooseEncryptDecrypt *AHChooseEncryptConstructor2 PROTO_LIST + ((AHChooseEncryptDecrypt *, struct B_AlgorithmInfoType *, POINTER)); +void AHChooseEncryptDestructor PROTO_LIST ((THIS_ENCRYPT_DECRYPT *)); + +int AHChooseEncryptGetBlockLen PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned int *)); +int AHChooseEncryptEncryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AHChooseEncryptDecryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AHChooseEncryptEncryptUpdate PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); +int AHChooseEncryptDecryptUpdate PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); +int AHChooseEncryptEncryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int AHChooseEncryptDecryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahchgen.c b/usr/src/lib/libresolv2/common/dnssafe/ahchgen.c new file mode 100644 index 0000000000..c0e94a7c15 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahchgen.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHChooseGenerate; +#define THIS_GENERATE struct AHChooseGenerate + +/* Define this so that the type of the AlgaChoice pointer in the + INIT_ALGA functions will be correct for this derived class. + */ +struct GenerateAlgaChoice; +#define THIS_ALGA_CHOICE struct GenerateAlgaChoice + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "balgmeth.h" +#include "ahchgen.h" +#include "amgen.h" +#include "port_after.h" + +static int InitGenerateAlga PROTO_LIST + ((GenerateAlgaChoice *, POINTER, B_ALGORITHM_METHOD *, A_SURRENDER_CTX *)); +static int GenerateResult PROTO_LIST + ((GenerateAlgaChoice *, POINTER *, B_Algorithm *, A_SURRENDER_CTX *)); + +static AHGenerateVTable V_TABLE = { + AHChooseGenerateDestructor, AHChooseGenerateInit, AHChooseGenerateKeypair, + AHChooseGenerateParameters +}; + +AHChooseGenerate *AHChooseGenerateConstructor2 (handler, infoType, info) +AHChooseGenerate *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHChooseGenerate *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHChooseGenerate *)T_malloc (sizeof (*handler))) + == (AHChooseGenerate *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AHGenerateConstructor (&handler->generate); + + ALGA_CHOICE_Constructor + (&handler->generateAlgaChoice.algaChoice, InitGenerateAlga); + ResizeContextConstructor (&handler->generateAlgaChoice.secondContext); + ResizeContextConstructor (&handler->generateAlgaChoice.randomBlock); + + /* Set algaChoice. + */ + handler->generateAlgaChoice.algaChoice._algorithmInfoType = infoType; + handler->generateAlgaChoice.algaChoice._algorithmInfo = info; + + handler->generate.vTable = &V_TABLE; + + return (handler); +} + +void AHChooseGenerateDestructor (handler) +AHChooseGenerate *handler; +{ + ResizeContextDestructor (&handler->generateAlgaChoice.secondContext); + ResizeContextDestructor (&handler->generateAlgaChoice.randomBlock); + ALGA_CHOICE_Destructor (&handler->generateAlgaChoice.algaChoice); + /* There is no desructor to call for the base class. */ +} + +int AHChooseGenerateInit (handler, chooser, surrenderContext) +AHChooseGenerate *handler; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->generateAlgaChoice.algaChoice, 0, (B_Key *)NULL_PTR, + chooser, surrenderContext)); +} + +int AHChooseGenerateKeypair + (handler, publicKey, privateKey, randomAlgorithm, surrenderContext) +AHChooseGenerate *handler; +B_Key *publicKey; +B_Key *privateKey; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + POINTER result; + int status; + + if ((status = GenerateResult + (&handler->generateAlgaChoice, &result, randomAlgorithm, + surrenderContext)) != 0) + return (status); + if ((status = B_KeySetInfo + (publicKey, handler->generateAlgaChoice._resultInfoType, result)) != 0) + return (status); + return (B_KeySetInfo + (privateKey, handler->generateAlgaChoice._resultInfoType, result)); +} + +int AHChooseGenerateParameters + (handler, resultAlgorithm, randomAlgorithm, surrenderContext) +AHChooseGenerate *handler; +B_Algorithm *resultAlgorithm; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + POINTER result; + int status; + + if ((status = GenerateResult + (&handler->generateAlgaChoice, &result, randomAlgorithm, + surrenderContext)) != 0) + return (status); + + /* Force the resultInfoType into a B_AlgorithmInfoType since it is + supplied in the chooser as a B_KeyInfoType. */ + return (B_AlgorithmSetInfo + (resultAlgorithm, (struct B_AlgorithmInfoType *) + handler->generateAlgaChoice._resultInfoType, result)); +} + +static int InitGenerateAlga + (generateAlgaChoice, keyInfo, algorithmMethod, surrenderContext) +GenerateAlgaChoice *generateAlgaChoice; +POINTER keyInfo; +B_ALGORITHM_METHOD *algorithmMethod; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int contextSize, secondContextSize; + +UNUSED_ARG (keyInfo) + /* Note that this also gets the resultInfoType which will be used later + by GenerateResult. */ + if ((status = (*((A_GENERATE_ALGA *)algorithmMethod->alga)->Query) + (&contextSize, &secondContextSize, &generateAlgaChoice->_randomBlockLen, + &generateAlgaChoice->_resultInfoType, + generateAlgaChoice->algaChoice._algorithmInfo)) != 0) + return (ConvertAlgaeError (status)); + + /* Create the context. + */ + if ((status = ResizeContextMakeNewContext + (&generateAlgaChoice->algaChoice.context, contextSize)) != 0) + return (status); + + /* Create the second context which is only passed during Init, but + must persist for all operations. */ + if ((status = ResizeContextMakeNewContext + (&generateAlgaChoice->secondContext, secondContextSize)) != 0) + return (status); + + /* Create randomBlock which will be filled in during GenerateResult. */ + if ((status = ResizeContextMakeNewContext + (&generateAlgaChoice->randomBlock, generateAlgaChoice->_randomBlockLen)) + != 0) + return (status); + + if ((status = (*((A_GENERATE_ALGA *)algorithmMethod->alga)->Init) + (generateAlgaChoice->algaChoice.context.z.context, + generateAlgaChoice->secondContext.z.context, + generateAlgaChoice->algaChoice._algorithmInfo, surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} + +/* Call the generate procedure repeatedly with a new random block + until it succeeds. + */ +static int GenerateResult + (generateAlgaChoice, result, randomAlgorithm, surrenderContext) +GenerateAlgaChoice *generateAlgaChoice; +POINTER *result; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + /* Fill in the random block and try generating as long as the + the generate operation returns BE_NEED_RANDOM. + */ + while (1) { + if ((status = B_AlgorithmGenerateRandomBytes + (randomAlgorithm, + (unsigned char *)generateAlgaChoice->randomBlock.z.context, + generateAlgaChoice->_randomBlockLen, surrenderContext)) != 0) + return (status); + + if ((status = (*((A_GENERATE_ALGA *) + generateAlgaChoice->algaChoice._alga)->Generate) + (generateAlgaChoice->algaChoice.context.z.context, result, + (unsigned char *)generateAlgaChoice->randomBlock.z.context, + surrenderContext)) != 0) { + if (status != AE_NEED_RANDOM) + return (ConvertAlgaeError (status)); + + /* Else continue and try again */ + } + else + /* Success, so return */ + return (0); + } +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahchgen.h b/usr/src/lib/libresolv2/common/dnssafe/ahchgen.h new file mode 100644 index 0000000000..ec38f97714 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahchgen.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCHGEN_H_ +#define _AHCHGEN_H_ 1 + +#include "ahgen.h" +#include "algchoic.h" + +/* Make a new class derived from an AlgaChoice which records the + result algorithm info type and needed randomBlockLen. + */ +typedef struct GenerateAlgaChoice { + AlgaChoice algaChoice; /* base class */ + + struct B_KeyInfoType *_resultInfoType; + ResizeContext secondContext; /* used for scratch */ + ResizeContext randomBlock; + unsigned int _randomBlockLen; +} GenerateAlgaChoice; + +typedef struct AHChooseGenerate { + AHGenerate generate; /* base class */ + + GenerateAlgaChoice generateAlgaChoice; +} AHChooseGenerate; + +AHChooseGenerate *AHChooseGenerateConstructor2 PROTO_LIST + ((AHChooseGenerate *, struct B_AlgorithmInfoType *, POINTER)); +void AHChooseGenerateDestructor PROTO_LIST ((THIS_GENERATE *)); + +int AHChooseGenerateInit PROTO_LIST + ((THIS_GENERATE *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int AHChooseGenerateKeypair PROTO_LIST + ((THIS_GENERATE *, B_Key *, B_Key *, B_Algorithm *, A_SURRENDER_CTX *)); +int AHChooseGenerateParameters PROTO_LIST + ((THIS_GENERATE *, B_Algorithm *, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahchrand.c b/usr/src/lib/libresolv2/common/dnssafe/ahchrand.c new file mode 100644 index 0000000000..caecaf5dd2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahchrand.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AHChooseRandom; +#define THIS_RANDOM struct AHChooseRandom + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "balgmeth.h" +#include "ahchrand.h" +#include "amrandom.h" +#include "port_after.h" + +static int InitRandomAlga PROTO_LIST + ((AlgaChoice *, POINTER, B_ALGORITHM_METHOD *, A_SURRENDER_CTX *)); + +static AHRandomVTable V_TABLE = { + AHChooseRandomDestructor, AHChooseRandomInit, AHChooseRandomUpdate, + AHChooseRandomGenerateBytes +}; + +AHChooseRandom *AHChooseRandomConstructor2 (handler, infoType, info) +AHChooseRandom *handler; +struct B_AlgorithmInfoType *infoType; +POINTER info; +{ + if (handler == (AHChooseRandom *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AHChooseRandom *)T_malloc (sizeof (*handler))) + == (AHChooseRandom *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AHRandomConstructor (&handler->random); + + ALGA_CHOICE_Constructor (&handler->algaChoice, InitRandomAlga); + handler->algaChoice._algorithmInfoType = infoType; + handler->algaChoice._algorithmInfo = info; + + handler->random.vTable = &V_TABLE; + + return (handler); +} + +void AHChooseRandomDestructor (handler) +AHChooseRandom *handler; +{ + ALGA_CHOICE_Destructor (&handler->algaChoice); + /* There is no desructor to call for the base class. */ +} + +int AHChooseRandomInit (handler, chooser, surrenderContext) +AHChooseRandom *handler; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + return (AlgaChoiceChoose + (&handler->algaChoice, 0, (B_Key *)NULL_PTR, chooser, + surrenderContext)); +} + +int AHChooseRandomUpdate (handler, input, inputLen, surrenderContext) +AHChooseRandom *handler; +unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = (*((A_RANDOM_ALGA *)handler->algaChoice._alga)->Update) + (handler->algaChoice.context.z.context, input, inputLen, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +int AHChooseRandomGenerateBytes (handler, output, outputLen, surrenderContext) +AHChooseRandom *handler; +unsigned char *output; +unsigned int outputLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = (*((A_RANDOM_ALGA *)handler->algaChoice._alga)->Generate) + (handler->algaChoice.context.z.context, output, outputLen, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + return (0); +} + +static int InitRandomAlga + (algaChoice, keyInfo, algorithmMethod, surrenderContext) +AlgaChoice *algaChoice; +POINTER keyInfo; +B_ALGORITHM_METHOD *algorithmMethod; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int contextSize; + +UNUSED_ARG (keyInfo) + if ((status = (*((A_RANDOM_ALGA *)algorithmMethod->alga)->Query) + (&contextSize, algaChoice->_algorithmInfo)) != 0) + return (ConvertAlgaeError (status)); + + if ((status = ResizeContextMakeNewContext + (&algaChoice->context, contextSize)) != 0) + return (status); + + if ((status = (*((A_RANDOM_ALGA *)algorithmMethod->alga)->Init) + (algaChoice->context.z.context, algaChoice->_algorithmInfo, + surrenderContext)) != 0) + return (ConvertAlgaeError (status)); + + return (0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahchrand.h b/usr/src/lib/libresolv2/common/dnssafe/ahchrand.h new file mode 100644 index 0000000000..349a97fe25 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahchrand.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHCHRAND_H_ +#define _AHCHRAND_H_ 1 + +#include "ahrandom.h" +#include "algchoic.h" + +typedef struct AHChooseRandom { + AHRandom random; /* base class */ + AlgaChoice algaChoice; +} AHChooseRandom; + +AHChooseRandom *AHChooseRandomConstructor2 PROTO_LIST + ((AHChooseRandom *, struct B_AlgorithmInfoType *, POINTER)); +void AHChooseRandomDestructor PROTO_LIST ((THIS_RANDOM *)); + +int AHChooseRandomInit PROTO_LIST + ((THIS_RANDOM *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int AHChooseRandomUpdate PROTO_LIST + ((THIS_RANDOM *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int AHChooseRandomGenerateBytes PROTO_LIST + ((THIS_RANDOM *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahdigest.c b/usr/src/lib/libresolv2/common/dnssafe/ahdigest.c new file mode 100644 index 0000000000..a0fa71355f --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahdigest.c @@ -0,0 +1,100 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahdigest.h" +#include "port_after.h" + +static void TypedAHDigestDestructor PROTO_LIST ((B_TypeCheck *)); + +void AHDigestConstructor (handler) +AHDigest *handler; +{ + /* Construct base class, setting type tag. */ + B_TYPE_CHECK_Constructor + (&handler->typeCheck, TypedAHDigestDestructor); + + /* Don't set vTable since this is a pure virtual base class. */ +} + +int B_AlgorithmDigestInit + (algorithm, key, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_Key *key; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType + (algorithm, TypedAHDigestDestructor)) != 0) + return (status); + + if ((status = + (*((AHDigest *)algorithm->z.handler)->vTable->DigestInit) + ((AHDigest *)algorithm->z.handler, key, algorithmChooser, + surrenderContext)) != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmDigestUpdate (algorithm, partIn, partInLen, surrenderContext) +B_Algorithm *algorithm; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHDigestDestructor)) != 0) + return (status); + + return ((*((AHDigest *)algorithm->z.handler)->vTable->DigestUpdate) + ((AHDigest *)algorithm->z.handler, partIn, partInLen, + surrenderContext)); +} + +int B_AlgorithmDigestFinal + (algorithm, partOut, partOutLen, maxPartOutLen, surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHDigestDestructor)) != 0) + return (status); + + return ((*((AHDigest *)algorithm->z.handler)->vTable->DigestFinal) + ((AHDigest *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, surrenderContext)); +} + +static void TypedAHDigestDestructor (typeCheck) +B_TypeCheck *typeCheck; +{ + (*((AHDigest *)typeCheck)->vTable->Destructor) ((AHDigest *)typeCheck); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahdigest.h b/usr/src/lib/libresolv2/common/dnssafe/ahdigest.h new file mode 100644 index 0000000000..2abe53d76b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahdigest.h @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHDIGEST_H_ +#define _AHDIGEST_H_ 1 + +#include "btypechk.h" + +/* Use the THIS_DIGEST macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_DIGEST +#define THIS_DIGEST struct AHDigest +#endif + +struct AHDigest; + +typedef struct { + void (*Destructor) PROTO_LIST ((THIS_DIGEST *)); + int (*DigestInit) PROTO_LIST + ((THIS_DIGEST *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); + int (*DigestUpdate) PROTO_LIST + ((THIS_DIGEST *, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*DigestFinal) PROTO_LIST + ((THIS_DIGEST *, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); +} AHDigestVTable; + +typedef struct AHDigest { + B_TypeCheck typeCheck; /* inherited */ + AHDigestVTable *vTable; /* pure virtual */ +} AHDigest; + +/* The constructor does not set the vTable since this is a pure base class. + */ +void AHDigestConstructor PROTO_LIST ((AHDigest *)); +/* No destructor because it is pure virtual. Also, do not call destructor + for B_TypeCheck, since this will just re-invoke this virtual + destructor. */ + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahencryp.c b/usr/src/lib/libresolv2/common/dnssafe/ahencryp.c new file mode 100644 index 0000000000..a8874dccd6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahencryp.c @@ -0,0 +1,178 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahencryp.h" +#include "port_after.h" + +static void TypedAHEncryptDecryptDestructor PROTO_LIST ((B_TypeCheck *)); + +void AHEncryptDecryptConstructor (handler) +AHEncryptDecrypt *handler; +{ + /* Construct base class, setting type tag. */ + B_TYPE_CHECK_Constructor + (&handler->typeCheck, TypedAHEncryptDecryptDestructor); + + /* Don't set vTable since this is a pure virtual base class. */ +} + +int B_AlgorithmEncryptInit + (algorithm, key, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_Key *key; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + if ((status = + (*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->EncryptInit) + ((AHEncryptDecrypt *)algorithm->z.handler, key, algorithmChooser, + surrenderContext)) != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmDecryptInit + (algorithm, key, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_Key *key; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + if ((status = + (*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->DecryptInit) + ((AHEncryptDecrypt *)algorithm->z.handler, key, algorithmChooser, + surrenderContext)) != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmEncryptUpdate + (algorithm, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + return ((*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->EncryptUpdate) + ((AHEncryptDecrypt *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, partIn, partInLen, randomAlgorithm, + surrenderContext)); +} + +int B_AlgorithmDecryptUpdate + (algorithm, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + return ((*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->DecryptUpdate) + ((AHEncryptDecrypt *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, partIn, partInLen, randomAlgorithm, + surrenderContext)); +} + +int B_AlgorithmEncryptFinal + (algorithm, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + return ((*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->EncryptFinal) + ((AHEncryptDecrypt *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, randomAlgorithm, surrenderContext)); +} + +int B_AlgorithmDecryptFinal + (algorithm, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +B_Algorithm *algorithm; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHEncryptDecryptDestructor)) != 0) + return (status); + + return ((*((AHEncryptDecrypt *)algorithm->z.handler)->vTable->DecryptFinal) + ((AHEncryptDecrypt *)algorithm->z.handler, partOut, partOutLen, + maxPartOutLen, randomAlgorithm, surrenderContext)); +} + +static void TypedAHEncryptDecryptDestructor (typeCheck) +B_TypeCheck *typeCheck; +{ + (*((AHEncryptDecrypt *)typeCheck)->vTable->Destructor) + ((AHEncryptDecrypt *)typeCheck); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahencryp.h b/usr/src/lib/libresolv2/common/dnssafe/ahencryp.h new file mode 100644 index 0000000000..d57b7ca9b7 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahencryp.h @@ -0,0 +1,92 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHENCRYP_H_ +#define _AHENCRYP_H_ 1 + +#include "btypechk.h" + +/* In C++: +class AHEncryptDecrypt : public B_TypeCheck { + AHEncryptDecrypt (); + virtual ~AHEncryptDecrypt () = 0; + + virtual int getBlockLen (unsigned int *) = 0; + virtual int encryptInit + (B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *) = 0; + virtual int decryptInit + (B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *) = 0; + virtual int encryptUpdate + (unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *) = 0; + virtual int decryptUpdate + (unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *) = 0; + virtual int encryptFinal + (unsigned char *, unsigned int *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *) = 0; + virtual int decryptFinal + (unsigned char *, unsigned int *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *) = 0; +}; + */ + +/* Use the THIS_ENCRYPT_DECRYPT macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_ENCRYPT_DECRYPT +#define THIS_ENCRYPT_DECRYPT struct AHEncryptDecrypt +#endif + +struct AHEncryptDecrypt; + +typedef struct { + void (*Destructor) PROTO_LIST ((THIS_ENCRYPT_DECRYPT *)); + int (*GetBlockLen) PROTO_LIST ((THIS_ENCRYPT_DECRYPT *, unsigned int *)); + int (*EncryptInit) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); + int (*DecryptInit) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); + int (*EncryptUpdate) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + int (*DecryptUpdate) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + int (*EncryptFinal) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); + int (*DecryptFinal) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); +} AHEncryptDecryptVTable; + +typedef struct AHEncryptDecrypt { + B_TypeCheck typeCheck; /* inherited */ + AHEncryptDecryptVTable *vTable; /* pure virtual */ +} AHEncryptDecrypt; + +/* The constructor does not set the vTable since this is a pure base class. + */ +void AHEncryptDecryptConstructor PROTO_LIST ((AHEncryptDecrypt *)); +/* No destructor because it is pure virtual. Also, do not call destructor + for B_TypeCheck, since this will just re-invoke this virtual + destructor. */ + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahgen.c b/usr/src/lib/libresolv2/common/dnssafe/ahgen.c new file mode 100644 index 0000000000..a65763429b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahgen.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahgen.h" +#include "port_after.h" + +static void TypedAHGenerateDestructor PROTO_LIST ((B_TypeCheck *)); + +void AHGenerateConstructor (handler) +AHGenerate *handler; +{ + /* Construct base class, setting type tag. */ + B_TYPE_CHECK_Constructor + (&handler->typeCheck, TypedAHGenerateDestructor); + + /* Don't set vTable since this is a pure virtual base class. */ +} + +int B_AlgorithmGenerateInit (algorithm, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType + (algorithm, TypedAHGenerateDestructor)) != 0) + return (status); + + if ((status = + (*((AHGenerate *)algorithm->z.handler)->vTable->GenerateInit) + ((AHGenerate *)algorithm->z.handler, algorithmChooser, + surrenderContext)) != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmGenerateKeypair + (algorithm, publicKey, privateKey, randomAlgorithm, surrenderContext) +B_Algorithm *algorithm; +B_Key *publicKey; +B_Key *privateKey; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHGenerateDestructor)) != 0) + return (status); + + return ((*((AHGenerate *)algorithm->z.handler)->vTable->GenerateKeypair) + ((AHGenerate *)algorithm->z.handler, publicKey, privateKey, + randomAlgorithm, surrenderContext)); +} + +int B_AlgorithmGenerateParameters + (algorithm, resultAlgorithm, randomAlgorithm, surrenderContext) +B_Algorithm *algorithm; +B_Algorithm *resultAlgorithm; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHGenerateDestructor)) != 0) + return (status); + + return ((*((AHGenerate *)algorithm->z.handler)->vTable->GenerateParameters) + ((AHGenerate *)algorithm->z.handler, resultAlgorithm, + randomAlgorithm, surrenderContext)); +} + +static void TypedAHGenerateDestructor (typeCheck) +B_TypeCheck *typeCheck; +{ + (*((AHGenerate *)typeCheck)->vTable->Destructor) ((AHGenerate *)typeCheck); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahgen.h b/usr/src/lib/libresolv2/common/dnssafe/ahgen.h new file mode 100644 index 0000000000..afe0ef3bf9 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahgen.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHGEN_H_ +#define _AHGEN_H_ 1 + +#include "btypechk.h" + +/* Use the THIS_GENERATE macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_GENERATE +#define THIS_GENERATE struct AHGenerate +#endif + +struct AHGenerate; + +typedef struct { + void (*Destructor) PROTO_LIST ((THIS_GENERATE *)); + int (*GenerateInit) PROTO_LIST + ((THIS_GENERATE *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); + int (*GenerateKeypair) PROTO_LIST + ((THIS_GENERATE *, B_Key *, B_Key *, B_Algorithm *, A_SURRENDER_CTX *)); + int (*GenerateParameters) PROTO_LIST + ((THIS_GENERATE *, B_Algorithm *, B_Algorithm *, A_SURRENDER_CTX *)); +} AHGenerateVTable; + +typedef struct AHGenerate { + B_TypeCheck typeCheck; /* inherited */ + AHGenerateVTable *vTable; /* pure virtual */ +} AHGenerate; + +/* The constructor does not set the vTable since this is a pure base class. + */ +void AHGenerateConstructor PROTO_LIST ((AHGenerate *)); +/* No destructor because it is pure virtual. Also, do not call destructor + for B_TypeCheck, since this will just re-invoke this virtual + destructor. */ + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahrandom.c b/usr/src/lib/libresolv2/common/dnssafe/ahrandom.c new file mode 100644 index 0000000000..9a31e9b817 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahrandom.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahrandom.h" +#include "port_after.h" + +static void TypedAHRandomDestructor PROTO_LIST ((B_TypeCheck *)); + +void AHRandomConstructor (handler) +AHRandom *handler; +{ + /* Construct base class, setting type tag. */ + B_TYPE_CHECK_Constructor + (&handler->typeCheck, TypedAHRandomDestructor); + + /* Don't set vTable since this is a pure virtual base class. */ +} + +int B_AlgorithmRandomInit (algorithm, algorithmChooser, surrenderContext) +B_Algorithm *algorithm; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckType (algorithm, TypedAHRandomDestructor)) + != 0) + return (status); + + if ((status = + (*((AHRandom *)algorithm->z.handler)->vTable->RandomInit) + ((AHRandom *)algorithm->z.handler, algorithmChooser, surrenderContext)) + != 0) + return (status); + + algorithm->z.initFlag = 1; + return (0); +} + +int B_AlgorithmRandomUpdate (algorithm, input, inputLen, surrenderContext) +B_Algorithm *algorithm; +unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHRandomDestructor)) != 0) + return (status == BE_ALGORITHM_NOT_INITIALIZED ? + BE_RANDOM_NOT_INITIALIZED : status); + + return ((*((AHRandom *)algorithm->z.handler)->vTable->RandomUpdate) + ((AHRandom *)algorithm->z.handler, input, inputLen, + surrenderContext)); +} + +int B_AlgorithmGenerateRandomBytes + (algorithm, output, outputLen, surrenderContext) +B_Algorithm *algorithm; +unsigned char *output; +unsigned int outputLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + /* As a special case, check here for a null this pointer when the object + is actually being used since many routines take a "dummy" null + random algorithm. + */ + if (algorithm == (B_Algorithm *)NULL_PTR) + return (BE_RANDOM_OBJ); + + if ((status = B_AlgorithmCheckTypeAndInitFlag + (algorithm, TypedAHRandomDestructor)) != 0) + return (status == BE_ALGORITHM_NOT_INITIALIZED ? + BE_RANDOM_NOT_INITIALIZED : status); + + return ((*((AHRandom *)algorithm->z.handler)->vTable->GenerateBytes) + ((AHRandom *)algorithm->z.handler, output, outputLen, + surrenderContext)); +} + +static void TypedAHRandomDestructor (typeCheck) +B_TypeCheck *typeCheck; +{ + (*((AHRandom *)typeCheck)->vTable->Destructor) ((AHRandom *)typeCheck); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahrandom.h b/usr/src/lib/libresolv2/common/dnssafe/ahrandom.h new file mode 100644 index 0000000000..fd566879e6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahrandom.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHRANDOM_H_ +#define _AHRANDOM_H_ 1 + +#include "btypechk.h" + +/* Use the THIS_RANDOM macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_RANDOM +#define THIS_RANDOM struct AHRandom +#endif + +struct AHRandom; + +typedef struct { + void (*Destructor) PROTO_LIST ((THIS_RANDOM *)); + int (*RandomInit) PROTO_LIST + ((THIS_RANDOM *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); + int (*RandomUpdate) PROTO_LIST + ((THIS_RANDOM *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*GenerateBytes) PROTO_LIST + ((THIS_RANDOM *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +} AHRandomVTable; + +typedef struct AHRandom { + B_TypeCheck typeCheck; /* inherited */ + AHRandomVTable *vTable; /* pure virtual */ +} AHRandom; + +/* The constructor does not set the vTable since this is a pure base class. + */ +void AHRandomConstructor PROTO_LIST ((AHRandom *)); +/* No destructor because it is pure virtual. Also, do not call destructor + for B_TypeCheck, since this will just re-invoke this virtual + destructor. */ + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.c b/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.c new file mode 100644 index 0000000000..3a8894d2d4 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.c @@ -0,0 +1,251 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AH_RSAEncryption; +#define THIS_ENCRYPT_DECRYPT struct AH_RSAEncryption + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahrsaenc.h" +#include "port_after.h" + +static int AH_RSAEncryptionInitHelper PROTO_LIST ((AH_RSAEncryption *, int)); + +static AHEncryptDecryptVTable V_TABLE = { + AH_RSAEncryptionDestructor, AH_RSAEncryptionGetBlockLen, + AH_RSAEncryptionEncryptInit, AH_RSAEncryptionDecryptInit, + AH_RSAEncryptionUpdate, + AH_RSAEncryptionUpdate, + AH_RSAEncryptionEncryptFinal, AH_RSAEncryptionDecryptFinal +}; + +void AH_RSAEncryptionConstructor1 (handler, infoType) +AH_RSAEncryption *handler; +struct B_AlgorithmInfoType *infoType; +{ + /* Construct base class with the infoType. Assume info is NULL_PTR. */ + AHChooseEncryptConstructor2 + (&handler->chooseEncryptDecrypt, infoType, NULL_PTR); + + T_memset ((POINTER)&handler->z, 0, sizeof (handler->z)); + /* Set the AHEncryptDecrypt vTable, but don't set the RSAEncryption vTable + since it is pure virtual. */ + handler->chooseEncryptDecrypt.encryptDecrypt.vTable = &V_TABLE; +} + +void AH_RSAEncryptionDestructor (handler) +AH_RSAEncryption *handler; +{ + T_memset ((POINTER)handler->z.block, 0, handler->z.blockLen); + T_free ((POINTER)handler->z.block); + + /* Call base class destructor */ + AHChooseEncryptDestructor (handler); +} + +int AH_RSAEncryptionGetBlockLen (handler, blockLen) +AH_RSAEncryption *handler; +unsigned int *blockLen; +{ +UNUSED_ARG (handler) +UNUSED_ARG (blockLen) + return (BE_NOT_SUPPORTED); +} + +int AH_RSAEncryptionEncryptInit (handler, key, chooser, surrenderContext) +AH_RSAEncryption *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AHChooseEncryptEncryptInit + (handler, key, chooser, surrenderContext)) != 0) + return (status); + + return (AH_RSAEncryptionInitHelper (handler, 1)); +} + +int AH_RSAEncryptionDecryptInit (handler, key, chooser, surrenderContext) +AH_RSAEncryption *handler; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AHChooseEncryptDecryptInit + (handler, key, chooser, surrenderContext)) != 0) + return (status); + + return (AH_RSAEncryptionInitHelper (handler, 0)); +} + +/* Accumulate into the z.block. + */ +int AH_RSAEncryptionUpdate + (handler, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +AH_RSAEncryption *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (partOut) +UNUSED_ARG (maxPartOutLen) +UNUSED_ARG (randomAlgorithm) +UNUSED_ARG (surrenderContext) + *partOutLen = 0; + + if (handler->_inputLen + partInLen > handler->_maxInputLen) + return (BE_INPUT_LEN); + T_memcpy + ((POINTER)(handler->z.block + handler->_inputLen), (CPOINTER)partIn, + partInLen); + handler->_inputLen += partInLen; + return (0); +} + +int AH_RSAEncryptionEncryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AH_RSAEncryption *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int dummyPartOutLen; + + /* Encode methodContext in place. */ + if ((status = (*handler->vTable->EncodeBlock) + (handler, randomAlgorithm, surrenderContext)) != 0) + return (status); + + /* This should not return BE_INPUT_DATA since it is well-formatted. */ + if ((status = AHChooseEncryptEncryptUpdate + (handler, partOut, partOutLen, maxPartOutLen, handler->z.block, + handler->z.blockLen, (B_Algorithm *)NULL_PTR, surrenderContext)) != 0) + return (status); + + /* Expect final to return zero bytes. */ + if ((status = AHChooseEncryptEncryptFinal + (handler, (unsigned char *)NULL_PTR, &dummyPartOutLen, 0, + (B_Algorithm *)NULL_PTR, surrenderContext)) != 0) + return (status); + + /* Restart the handle for new input. */ + handler->_inputLen = 0; + return (0); +} + +int AH_RSAEncryptionDecryptFinal + (handler, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +AH_RSAEncryption *handler; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + ITEM output; + int status; + unsigned int decryptedLen, dummyPartOutLen; + +UNUSED_ARG (randomAlgorithm) + /* Decrypt block in place. The block lenghts are already within limits. + */ + if ((status = AHChooseEncryptDecryptUpdate + (handler, handler->z.block, &decryptedLen, handler->z.blockLen, + handler->z.block, handler->_inputLen, (B_Algorithm *)NULL_PTR, + surrenderContext)) != 0) + return (status); + /* Expect final to return zero bytes. */ + if ((status = AHChooseEncryptDecryptFinal + (handler, (unsigned char *)NULL_PTR, &dummyPartOutLen, 0, + (B_Algorithm *)NULL_PTR, surrenderContext)) != 0) + return (status); + + /* Restart the handle for new input. */ + handler->_inputLen = 0; + + /* Now decode the block and copy the result to the partOut. + */ + if ((status = (*handler->vTable->DecodeBlock) + (handler, &output, decryptedLen)) != 0) + return (status); + + if (output.len > handler->z.blockLen - 11) + /* This implies that the block was encrypted with less than + 8 bytes of padding */ + return (BE_INPUT_DATA); + + if ((*partOutLen = output.len) > maxPartOutLen) + return (BE_OUTPUT_LEN); + T_memcpy ((POINTER)partOut, (POINTER)output.data, output.len); + + return (0); +} + +static int AH_RSAEncryptionInitHelper (handler, encryptFlag) +AH_RSAEncryption *handler; +int encryptFlag; +{ + int status; + unsigned int newBlockLen; + + if ((status = AHChooseEncryptGetBlockLen (handler, &newBlockLen)) != 0) + return (status); + + if (newBlockLen < 12) + /* PKCS Requires at least 12 bytes of modulus */ + return (BE_NOT_SUPPORTED); + + /* During encrypt, this will ensure that there are 8 bytes of padding. + During decrypt, the DecodeBlock procedure must check that the block + was encrypted with 8 bytes of padding. + */ + handler->_maxInputLen = encryptFlag ? (newBlockLen - 11) : newBlockLen; + + handler->_inputLen = 0; + + /* Zeroize old block and realloc to new size. + */ + T_memset ((POINTER)handler->z.block, 0, handler->z.blockLen); + if ((handler->z.block = (unsigned char *)T_realloc + ((POINTER)handler->z.block, newBlockLen)) + == (unsigned char *)NULL_PTR) { + handler->z.blockLen = 0; + return (BE_ALLOC); + } + + handler->z.blockLen = newBlockLen; + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.h b/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.h new file mode 100644 index 0000000000..5fa5f9be08 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaenc.h @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHRSAENC_H_ +#define _AHRSAENC_H_ + +#include "ahchencr.h" + +struct AH_RSAEncryption; + +/* For EncodeBlock, the block to encode is left justified in the + z.block with length given by z._inputLen. EncodeBlock encodes the block + in place to fill it out to z.blockLen. + For DecodeBlock, return the contents in the given ITEM by decoding + the z.block value which has length given by decryptedLen. This + procedure must also ensure that the block was encrypted with 8 bytes + of padding. + */ +typedef struct { + int (*EncodeBlock) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Algorithm * /* randomAlgorithm */, + A_SURRENDER_CTX *)); + int (*DecodeBlock) PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, ITEM *, unsigned int /* decryptedLen */)); +} AH_RSAEncryptionVTable; + +typedef struct AH_RSAEncryption { + AHChooseEncryptDecrypt chooseEncryptDecrypt; /* base class */ + + struct { + unsigned char *block; + unsigned int blockLen; + } z; /* Zeroized by constructor */ + + unsigned int _inputLen; /* Length of data accumulated by Update */ + unsigned int _maxInputLen; /* used during update to check for overflow */ + AH_RSAEncryptionVTable *vTable; /* pure virtual */ +} AH_RSAEncryption; + +void AH_RSAEncryptionConstructor1 PROTO_LIST + ((AH_RSAEncryption *, struct B_AlgorithmInfoType *)); +void AH_RSAEncryptionDestructor PROTO_LIST ((AH_RSAEncryption *)); + +int AH_RSAEncryptionGetBlockLen PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned int *)); +int AH_RSAEncryptionEncryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AH_RSAEncryptionDecryptInit PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, B_Key *, B_ALGORITHM_CHOOSER, + A_SURRENDER_CTX *)); +int AH_RSAEncryptionUpdate PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, const unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); +int AH_RSAEncryptionEncryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int AH_RSAEncryptionDecryptFinal PROTO_LIST + ((THIS_ENCRYPT_DECRYPT *, unsigned char *, unsigned int *, + unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.c b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.c new file mode 100644 index 0000000000..e5d6dad1c6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AH_RSAEncryption; +#define THIS_ENCRYPT_DECRYPT struct AH_RSAEncryption + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahrsaepr.h" +#include "port_after.h" + +static int EncodeBlock1 PROTO_LIST + ((AH_RSAEncryptionPrivate *, B_Algorithm *, A_SURRENDER_CTX *)); +static int DecodeBlock2 PROTO_LIST + ((AH_RSAEncryptionPrivate *, ITEM *, unsigned int)); + +static AH_RSAEncryptionVTable ENCRYPTION_V_TABLE = + {EncodeBlock1, DecodeBlock2}; + +extern struct B_AlgorithmInfoType AIT_RSAPrivate; + +AH_RSAEncryptionPrivate *AH_RSAEncrypPrivateConstructor (handler) +AH_RSAEncryptionPrivate *handler; +{ + if (handler == (AH_RSAEncryptionPrivate *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AH_RSAEncryptionPrivate *)T_malloc (sizeof (*handler))) + == (AH_RSAEncryptionPrivate *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AH_RSAEncryptionConstructor1 (handler, &AIT_RSAPrivate); + + handler->vTable = &ENCRYPTION_V_TABLE; + return (handler); +} + +/* block1 starts out with the input bytes of length inputLen left-justified. + Returns 0, BE_INPUT_LEN. + */ +static int EncodeBlock1 (handler, randomAlgorithm, surrenderContext) +AH_RSAEncryptionPrivate *handler; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + unsigned int padLen; + +UNUSED_ARG (randomAlgorithm) +UNUSED_ARG (surrenderContext) + if ((handler->_inputLen + 3) > handler->z.blockLen) + /* input is too large to make a block 1 */ + return (BE_INPUT_LEN); + + padLen = handler->z.blockLen - (handler->_inputLen + 3); + T_memmove + ((POINTER)(handler->z.block + padLen + 3), (POINTER)handler->z.block, + handler->_inputLen); + + handler->z.block[0] = 0; + handler->z.block[1] = 1; + T_memset ((POINTER)(handler->z.block + 2), 0xff, padLen); + handler->z.block[2 + padLen] = 0; + return (0); +} + +static int DecodeBlock2 (handler, output, block2Len) +AH_RSAEncryptionPrivate *handler; +ITEM *output; +unsigned int block2Len; +{ + unsigned int i; + + if ((handler->z.block[0] != 0) || (handler->z.block[1] != 2)) + return (BE_INPUT_DATA); + + /* Should be able to find the data after the first zero byte following + the random bytes. */ + for (i = 2; i < block2Len && handler->z.block[i] != 0; i++); + i++; + + if (i > block2Len) + /* The data is not zero terminated. */ + return (BE_INPUT_DATA); + + output->len = block2Len - i; + output->data = handler->z.block + i; + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.h b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.h new file mode 100644 index 0000000000..9820017939 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepr.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHRSAEPR_H_ +#define _AHRSAEPR_H_ + +#include "ahrsaenc.h" + +/* structure is identical to base class, so just re-typedef. */ +typedef AH_RSAEncryption AH_RSAEncryptionPrivate; + +AH_RSAEncryptionPrivate *AH_RSAEncrypPrivateConstructor PROTO_LIST + ((AH_RSAEncryptionPrivate *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.c b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.c new file mode 100644 index 0000000000..40a6c8db35 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct AH_RSAEncryption; +#define THIS_ENCRYPT_DECRYPT struct AH_RSAEncryption + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahrsaepu.h" +#include "port_after.h" + +static int EncodeBlock2 PROTO_LIST + ((AH_RSAEncryptionPublic *, B_Algorithm *, A_SURRENDER_CTX *)); +static int DecodeBlock1 PROTO_LIST + ((AH_RSAEncryptionPublic *, ITEM *, unsigned int)); + +static AH_RSAEncryptionVTable ENCRYPTION_V_TABLE = + {EncodeBlock2, DecodeBlock1}; + +extern struct B_AlgorithmInfoType AIT_RSAPublic; + +AH_RSAEncryptionPublic *AH_RSAEncrypPublicConstructor (handler) +AH_RSAEncryptionPublic *handler; +{ + if (handler == (AH_RSAEncryptionPublic *)NULL_PTR) { + /* This constructor is being used to do a new */ + if ((handler = (AH_RSAEncryptionPublic *)T_malloc (sizeof (*handler))) + == (AH_RSAEncryptionPublic *)NULL_PTR) + return (handler); + } + + /* Construct base class */ + AH_RSAEncryptionConstructor1 (handler, &AIT_RSAPublic); + + handler->vTable = &ENCRYPTION_V_TABLE; + return (handler); +} + +/* block starts out with the input bytes of length inputLen left-justified. + */ +static int EncodeBlock2 (handler, randomAlgorithm, surrenderContext) +AH_RSAEncryptionPublic *handler; +B_Algorithm *randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned char randomByte; + unsigned int padLen, i; + + if ((handler->_inputLen + 3) > handler->z.blockLen) + /* input is too large to make a block 2 */ + return (BE_INPUT_LEN); + + padLen = handler->z.blockLen - (handler->_inputLen + 3); + T_memmove + ((POINTER)(handler->z.block + padLen + 3), (POINTER)handler->z.block, + handler->_inputLen); + + handler->z.block[0] = 0; + handler->z.block[1] = 2; + + /* Pad out with random bytes, making sure that none of the bytes is zero. + */ + for (i = 2; i < (padLen + 2); i++) { + do { + if ((status = B_AlgorithmGenerateRandomBytes + (randomAlgorithm, &randomByte, 1, surrenderContext)) != 0) + return (status); + } while (randomByte == 0); + + handler->z.block[i] = randomByte; + } + + handler->z.block[2 + padLen] = 0; + return (0); +} + +static int DecodeBlock1 (handler, output, block1Len) +AH_RSAEncryptionPublic *handler; +ITEM *output; +unsigned int block1Len; +{ + unsigned int i; + + /* Locate the digestInfo within the PKCS block 1. + */ + if (handler->z.block[0] != 0 || handler->z.block[1] != 1) + return (BE_INPUT_DATA); + + /* Should be able to find the data after the first zero byte following + the 0xff. */ + for (i = 2; i < block1Len && handler->z.block[i] == 0xff; i++); + i++; + + if (i > block1Len || handler->z.block[i - 1] != 0) + /* The data is not zero terminated, or a byte other than 0xff. */ + return (BE_INPUT_DATA); + + output->len = block1Len - i; + output->data = handler->z.block + i; + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.h b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.h new file mode 100644 index 0000000000..5f13415fdf --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ahrsaepu.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AHRSAEPU_H_ +#define _AHRSAEPU_H_ + +#include "ahrsaenc.h" + +/* structure is identical to base class, so just re-typedef. */ +typedef AH_RSAEncryption AH_RSAEncryptionPublic; + +AH_RSAEncryptionPublic *AH_RSAEncrypPublicConstructor PROTO_LIST + ((AH_RSAEncryptionPublic *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichdig.c b/usr/src/lib/libresolv2/common/dnssafe/aichdig.c new file mode 100644 index 0000000000..6aa7043b99 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichdig.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahchdig.h" +#include "aichdig.h" +#include "port_after.h" + +B_TypeCheck *AITChooseDigestNullNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +B_AlgorithmInfoTypeVTable AITChooseDigestNull_V_TABLE = + {AITNullAddInfo, AITChooseDigestNullNewHandler, + B_AlgorithmInfoTypeMakeError}; + +/* This always uses NULL_PTR for the info. + */ +B_TypeCheck *AITChooseDigestNullNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ +UNUSED_ARG (algorithm) + + /* Pass in NULL_PTR so that constructor will allocate. + */ + return ((B_TypeCheck *)AHChooseDigestConstructor2 + ((AHChooseDigest *)NULL_PTR, infoType, NULL_PTR)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichdig.h b/usr/src/lib/libresolv2/common/dnssafe/aichdig.h new file mode 100644 index 0000000000..a7366e40b5 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichdig.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHDIG_H_ +#define _AICHDIG_H_ 1 + +#include "ainfotyp.h" +#include "ainull.h" + +extern B_AlgorithmInfoTypeVTable AITChooseDigestNull_V_TABLE; + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichenc8.c b/usr/src/lib/libresolv2/common/dnssafe/aichenc8.c new file mode 100644 index 0000000000..42f869d8ee --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichenc8.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichenc8.h" +#include "port_after.h" + +B_AlgorithmInfoTypeVTable AITChooseEncrypt8_V_TABLE = + {AIT_8AddInfo, AITChooseEncryptNewHandler, B_AlgorithmInfoTypeMakeError}; + +int AIT_8AddInfo (infoType, algorithm, info) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +POINTER info; +{ + POINTER newInfo; + int status; + + if ((status = B_MemoryPoolAllocAndCopy + (&algorithm->infoCache.memoryPool, &newInfo, info, 8)) != 0) + return (status); + + return (B_InfoCacheAddInfo + (&algorithm->infoCache, (POINTER)infoType, newInfo)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichenc8.h b/usr/src/lib/libresolv2/common/dnssafe/aichenc8.h new file mode 100644 index 0000000000..59c6bf44d2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichenc8.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHENC8_H_ +#define _AICHENC8_H_ 1 + +#include "aichencr.h" + +extern B_AlgorithmInfoTypeVTable AITChooseEncrypt8_V_TABLE; + +int AIT_8AddInfo PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *, POINTER)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichencn.c b/usr/src/lib/libresolv2/common/dnssafe/aichencn.c new file mode 100644 index 0000000000..0dc2fb6650 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichencn.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichencn.h" +#include "port_after.h" + +B_AlgorithmInfoTypeVTable AITChooseEncryptNull_V_TABLE = + {AITNullAddInfo, AITChooseEncryptNewHandler, B_AlgorithmInfoTypeMakeError}; + diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichencn.h b/usr/src/lib/libresolv2/common/dnssafe/aichencn.h new file mode 100644 index 0000000000..99af4ff8c7 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichencn.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHENCN_H_ +#define _AICHENCN_H_ 1 + +#include "aichencr.h" +#include "ainull.h" + +extern B_AlgorithmInfoTypeVTable AITChooseEncryptNull_V_TABLE; + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichencr.c b/usr/src/lib/libresolv2/common/dnssafe/aichencr.c new file mode 100644 index 0000000000..4e50087014 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichencr.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahchencr.h" +#include "aichencr.h" +#include "port_after.h" + +B_TypeCheck *AITChooseEncryptNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ + POINTER info; + + if (B_InfoCacheFindInfo (&algorithm->infoCache, &info, (POINTER)infoType) + != 0) + /* This really shouldn't happen since the info was just added. */ + return ((B_TypeCheck *)NULL_PTR); + + /* Pass in NULL_PTR so that constructor will allocate. */ + return ((B_TypeCheck *)AHChooseEncryptConstructor2 + ((AHChooseEncryptDecrypt *)NULL_PTR, infoType, info)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichencr.h b/usr/src/lib/libresolv2/common/dnssafe/aichencr.h new file mode 100644 index 0000000000..7d67ab0e31 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichencr.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHENCR_H_ +#define _AICHENCR_H_ 1 + +#include "ainfotyp.h" + +struct B_TypeCheck *AITChooseEncryptNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichgen.c b/usr/src/lib/libresolv2/common/dnssafe/aichgen.c new file mode 100644 index 0000000000..f23a715026 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichgen.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahchgen.h" +#include "aichgen.h" +#include "port_after.h" + +B_TypeCheck *AITChooseGenerateNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ + POINTER info; + + if (B_InfoCacheFindInfo (&algorithm->infoCache, &info, (POINTER)infoType) + != 0) + /* This really shouldn't happen since the info was just added. */ + return ((B_TypeCheck *)NULL_PTR); + + /* Pass in NULL_PTR so that constructor will allocate. */ + return ((B_TypeCheck *)AHChooseGenerateConstructor2 + ((AHChooseGenerate *)NULL_PTR, infoType, info)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichgen.h b/usr/src/lib/libresolv2/common/dnssafe/aichgen.h new file mode 100644 index 0000000000..0b5e7086fa --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichgen.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHGEN_H_ +#define _AICHGEN_H_ 1 + +#include "ainfotyp.h" + +struct B_TypeCheck *AITChooseGenerateNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichrand.c b/usr/src/lib/libresolv2/common/dnssafe/aichrand.c new file mode 100644 index 0000000000..9c3ea6d9fd --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichrand.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ahchrand.h" +#include "aichrand.h" +#include "port_after.h" + +B_TypeCheck *AITChooseRandomNullNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +B_AlgorithmInfoTypeVTable AITChooseRandomNull_V_TABLE = + {AITNullAddInfo, AITChooseRandomNullNewHandler, + B_AlgorithmInfoTypeMakeError}; + +/* This always uses NULL_PTR for the info. + */ +B_TypeCheck *AITChooseRandomNullNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ +UNUSED_ARG (algorithm) + + /* Pass in NULL_PTR so that constructor will allocate. + */ + return ((B_TypeCheck *)AHChooseRandomConstructor2 + ((AHChooseRandom *)NULL_PTR, infoType, NULL_PTR)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/aichrand.h b/usr/src/lib/libresolv2/common/dnssafe/aichrand.h new file mode 100644 index 0000000000..f36d7bfe7c --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aichrand.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AICHRAND_H_ +#define _AICHRAND_H_ 1 + +#include "ainfotyp.h" +#include "ainull.h" + +extern B_AlgorithmInfoTypeVTable AITChooseRandomNull_V_TABLE; + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/aimd5.c b/usr/src/lib/libresolv2/common/dnssafe/aimd5.c new file mode 100644 index 0000000000..8ac7c4d3f7 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aimd5.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichdig.h" +#include "port_after.h" + +B_AlgorithmInfoType AIT_MD5 = {&AITChooseDigestNull_V_TABLE}; + +int AI_MD5 (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_MD5; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/aimd5ran.c b/usr/src/lib/libresolv2/common/dnssafe/aimd5ran.c new file mode 100644 index 0000000000..c4ee058b0f --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/aimd5ran.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichrand.h" +#include "port_after.h" + +B_AlgorithmInfoType AIT_MD5Random = {&AITChooseRandomNull_V_TABLE}; + +int AI_MD5Random (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_MD5Random; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.c b/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.c new file mode 100644 index 0000000000..2b4f21d67b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "port_after.h" + +/* This is the default routine which algorithm info types point MakeInfo to + if not redefined by a derived class. + */ +int B_AlgorithmInfoTypeMakeError (infoType, info, algorithm) +B_AlgorithmInfoType *infoType; +POINTER *info; +B_Algorithm *algorithm; +{ +UNUSED_ARG (infoType) +UNUSED_ARG (info) +UNUSED_ARG (algorithm) + + /* Should already have been found in the cache. */ + return (BE_WRONG_ALGORITHM_INFO); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.h b/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.h new file mode 100644 index 0000000000..5a6bc782f3 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ainfotyp.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _AINFOTYP_H_ +#define _AINFOTYP_H_ 1 + +/* Use the THIS_ALGORITHM_INFO_TYPE macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_ALGORITHM_INFO_TYPE +#define THIS_ALGORITHM_INFO_TYPE struct B_AlgorithmInfoType +#endif + +struct B_AlgorithmInfoType; + +typedef struct { + int (*AddInfo) PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *, POINTER)); + struct B_TypeCheck * (*NewHandler) PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *)); + int (*MakeInfo) PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, POINTER *, B_Algorithm *)); +} B_AlgorithmInfoTypeVTable; + +typedef struct B_AlgorithmInfoType { + B_AlgorithmInfoTypeVTable *vTable; +} B_AlgorithmInfoType; + +int B_AlgorithmInfoTypeMakeError PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, POINTER *, B_Algorithm *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/ainull.c b/usr/src/lib/libresolv2/common/dnssafe/ainull.c new file mode 100644 index 0000000000..2879369730 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ainull.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "ainull.h" +#include "port_after.h" + +int AITNullAddInfo (infoType, algorithm, info) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +POINTER info; +{ +UNUSED_ARG (info) + /* Cache null parameters. */ + return (B_InfoCacheAddInfo + (&algorithm->infoCache, (POINTER)infoType, NULL_PTR)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ainull.h b/usr/src/lib/libresolv2/common/dnssafe/ainull.h new file mode 100644 index 0000000000..c15b892f29 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ainull.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +int AITNullAddInfo PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *, POINTER)); diff --git a/usr/src/lib/libresolv2/common/dnssafe/airsaepr.c b/usr/src/lib/libresolv2/common/dnssafe/airsaepr.c new file mode 100644 index 0000000000..328366e90b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/airsaepr.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "ainull.h" +#include "ahrsaepr.h" +#include "port_after.h" + +B_TypeCheck *AIT_PKCS_RSAPrivateNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +static B_AlgorithmInfoTypeVTable V_TABLE = + {AITNullAddInfo, AIT_PKCS_RSAPrivateNewHandler, + B_AlgorithmInfoTypeMakeError}; + +B_AlgorithmInfoType AIT_PKCS_RSAPrivate = {&V_TABLE}; + +int AI_PKCS_RSAPrivate (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_PKCS_RSAPrivate; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + +B_TypeCheck *AIT_PKCS_RSAPrivateNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ +UNUSED_ARG (infoType) +UNUSED_ARG (algorithm) + /* Pass in NULL_PTR so that constructor will allocate. */ + return ((B_TypeCheck *)AH_RSAEncrypPrivateConstructor + ((AH_RSAEncryptionPrivate *)NULL_PTR)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/airsaepu.c b/usr/src/lib/libresolv2/common/dnssafe/airsaepu.c new file mode 100644 index 0000000000..1271220f7c --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/airsaepu.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "ainull.h" +#include "ahrsaepu.h" +#include "port_after.h" + +B_TypeCheck *AIT_PKCS_RSAPublicNewHandler PROTO_LIST + ((B_AlgorithmInfoType *, B_Algorithm *)); + +static B_AlgorithmInfoTypeVTable V_TABLE = + {AITNullAddInfo, AIT_PKCS_RSAPublicNewHandler, + B_AlgorithmInfoTypeMakeError}; + +B_AlgorithmInfoType AIT_PKCS_RSAPublic = {&V_TABLE}; + +int AI_PKCS_RSAPublic (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_PKCS_RSAPublic; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + +B_TypeCheck *AIT_PKCS_RSAPublicNewHandler (infoType, algorithm) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +{ +UNUSED_ARG (infoType) +UNUSED_ARG (algorithm) + /* Pass in NULL_PTR so that constructor will allocate. */ + return ((B_TypeCheck *)AH_RSAEncrypPublicConstructor + ((AH_RSAEncryptionPublic *)NULL_PTR)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/airsakgn.c b/usr/src/lib/libresolv2/common/dnssafe/airsakgn.c new file mode 100644 index 0000000000..dfe450fe37 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/airsakgn.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "intitem.h" +#include "aichgen.h" +#include "port_after.h" + +int AIT_RSAKeyGenAddInfo PROTO_LIST + ((THIS_ALGORITHM_INFO_TYPE *, B_Algorithm *, POINTER)); + +static A_RSA_KEY_GEN_PARAMS STATIC_KEY_GEN_PARAMS; +static ITEM *KEY_GEN_PARAMS_ITEMS[] = {&STATIC_KEY_GEN_PARAMS.publicExponent}; + +static B_AlgorithmInfoTypeVTable V_TABLE = + {AIT_RSAKeyGenAddInfo, AITChooseGenerateNewHandler, + B_AlgorithmInfoTypeMakeError}; + +B_AlgorithmInfoType AIT_RSAKeyGen = {&V_TABLE}; + +int AI_RSAKeyGen (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_RSAKeyGen; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + +int AIT_RSAKeyGenAddInfo (infoType, algorithm, info) +B_AlgorithmInfoType *infoType; +B_Algorithm *algorithm; +POINTER info; +{ + A_RSA_KEY_GEN_PARAMS *newInfo; + int status; + + if ((status = B_MemoryPoolAlloc + (&algorithm->infoCache.memoryPool, (POINTER *)&newInfo, + sizeof (A_RSA_KEY_GEN_PARAMS))) != 0) + return (status); + if ((status = AllocAndCopyIntegerItems + ((POINTER)newInfo, info, (POINTER)&STATIC_KEY_GEN_PARAMS, + KEY_GEN_PARAMS_ITEMS, + sizeof (KEY_GEN_PARAMS_ITEMS) / sizeof (KEY_GEN_PARAMS_ITEMS[0]), + &algorithm->infoCache.memoryPool)) != 0) + return (status); + + newInfo->modulusBits = ((A_RSA_KEY_GEN_PARAMS *)info)->modulusBits; + return (B_InfoCacheAddInfo + (&algorithm->infoCache, (POINTER)infoType, (POINTER)newInfo)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/airsaprv.c b/usr/src/lib/libresolv2/common/dnssafe/airsaprv.c new file mode 100644 index 0000000000..4aaa53b37b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/airsaprv.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichencn.h" +#include "port_after.h" + +B_AlgorithmInfoType AIT_RSAPrivate = {&AITChooseEncryptNull_V_TABLE}; + +int AI_RSAPrivate (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_RSAPrivate; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/airsapub.c b/usr/src/lib/libresolv2/common/dnssafe/airsapub.c new file mode 100644 index 0000000000..f0aef24046 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/airsapub.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "aichencn.h" +#include "port_after.h" + +B_AlgorithmInfoType AIT_RSAPublic = {&AITChooseEncryptNull_V_TABLE}; + +int AI_RSAPublic (infoType) +POINTER *infoType; +{ + *infoType = (POINTER)&AIT_RSAPublic; + + /* Return 0 to indicate a B_AlgorithmInfoType, not a B_KeyInfoType */ + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/algae.h b/usr/src/lib/libresolv2/common/dnssafe/algae.h new file mode 100644 index 0000000000..0f66f796f0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/algae.h @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _ALGAE_H_ +#define _ALGAE_H_ 1 + +#ifndef T_CALL +#define T_CALL +#endif + +/* Used to reduce the stack size in routines with big scratch buffers. + If set to 1, this will make ALGAE allocate these buffers on the heap. + */ +#ifndef USE_ALLOCED_FRAME +#define USE_ALLOCED_FRAME 1 +#endif + +#include "atypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define AE_CANCEL 0x0001 +#define AE_DATA 0x0002 +#define AE_EXPONENT_EVEN 0x0003 +#define AE_EXPONENT_LEN 0x0004 +#define AE_INPUT_DATA 0x0005 +#define AE_INPUT_LEN 0x0006 +#define AE_MODULUS_LEN 0x0007 +#define AE_NEED_RANDOM 0x0008 +#define AE_NOT_SUPPORTED 0x0009 +#define AE_OUTPUT_LEN 0x000a +#define AE_NOT_INITIALIZED 0x000b +#define AE_KEY_LEN 0x000c +#define AE_KEY_INFO 0x000d +#define AE_SEQUENCE 0x000e +#define AE_PARAMS 0x000f + +#if USE_ALLOCED_FRAME +/* Needed only for big number code heap allocation of scratch arrays. + */ +#define AE_ALLOC 0x0080 +POINTER T_malloc PROTO_LIST ((unsigned int)); +void T_free PROTO_LIST ((POINTER)); +#endif + +/* Routines supplied by the implementor. + */ +void T_memset PROTO_LIST ((POINTER, int, unsigned int)); +void T_memcpy PROTO_LIST ((POINTER, CPOINTER, unsigned int)); +void T_memmove PROTO_LIST ((POINTER, POINTER, unsigned int)); +int T_memcmp PROTO_LIST ((CPOINTER, CPOINTER, unsigned int)); + +unsigned int A_IntegerBits PROTO_LIST ((const unsigned char *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/algchoic.c b/usr/src/lib/libresolv2/common/dnssafe/algchoic.c new file mode 100644 index 0000000000..b444c41be6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/algchoic.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "algae.h" +#include "balgmeth.h" +#include "bkey.h" +#include "algchoic.h" +#include "port_after.h" + +/* In C++: +ResizeContext::ResizeContext () +{ + T_memset ((POINTER)&z, 0, sizeof (z)); +} + */ +void ResizeContextConstructor (resizeContext) +ResizeContext *resizeContext; +{ + T_memset ((POINTER)&resizeContext->z, 0, sizeof (resizeContext->z)); +} + +/* In C++: +ResizeContext::~ResizeContext () +{ + T_memset (z.context, 0, z.contextSize); + T_free (z.context); +} + */ +void ResizeContextDestructor (resizeContext) +ResizeContext *resizeContext; +{ + T_memset (resizeContext->z.context, 0, resizeContext->z.contextSize); + T_free (resizeContext->z.context); +} + +/* If the resizeContext's context is already the requested size, do nothing. + Otherwise, this memsets the existing context to zero, then allocates + the context as a buffer of the requested size. + If the allocate fails, the context size is set to + zero so that later calls will not zeroize non-existing buffers. + */ +int ResizeContextMakeNewContext (resizeContext, contextSize) +ResizeContext *resizeContext; +unsigned int contextSize; +{ + if (resizeContext->z.contextSize == contextSize) + return (0); + + /* Take care of zeroizing the previous context. + */ + T_memset (resizeContext->z.context, 0, resizeContext->z.contextSize); + + if ((resizeContext->z.context = T_realloc + (resizeContext->z.context, contextSize)) == NULL_PTR) { + resizeContext->z.contextSize = 0; + return (BE_ALLOC); + } + + resizeContext->z.contextSize = contextSize; + return (0); +} + +int AlgaChoiceChoose (algaChoice, encryptFlag, key, chooser, surrenderContext) +AlgaChoice *algaChoice; +int encryptFlag; +B_Key *key; +B_ALGORITHM_CHOOSER chooser; +A_SURRENDER_CTX *surrenderContext; +{ + POINTER keyInfo; + int status, overallStatus; + + /* Each alga init callback returns BE_NOT_SUPPORTED if the Query fails. + Each also may return a more specific error like BE_MODULUS_LEN if the + method is not supported, so return the more specific error if possible. + */ + overallStatus = BE_METHOD_NOT_IN_CHOOSER; + + for (; *chooser != (B_ALGORITHM_METHOD *)NULL_PTR; chooser++) { + if ((*chooser)->algorithmInfoType != algaChoice->_algorithmInfoType || + (*chooser)->encryptFlag != encryptFlag) + /* Wrong type of algorithm, or the encryptFlag is wrong */ + continue; + + if ((*chooser)->keyInfoType != (struct B_KeyInfoType *)NULL_PTR) { + if ((status = B_KeyGetInfo + (key, &keyInfo, (*chooser)->keyInfoType)) != 0) { + if (IS_FATAL_BSAFE_ERROR (status)) + return (status); + + /* Update the overall status with this more specific error. */ + overallStatus = status; + continue; + } + } + else + keyInfo = NULL_PTR; + + if ((status = (*algaChoice->_InitAlga) + (algaChoice, keyInfo, *chooser, surrenderContext)) != 0) { + if (IS_FATAL_BSAFE_ERROR (status)) + return (status); + + /* Update the overall status with this more specific error. */ + overallStatus = status; + continue; + } + + /* Succeeded */ + algaChoice->_alga = (*chooser)->alga; + return (0); + } + + return (overallStatus); +} + +/* Convert the ALGAE error to a BSAFE2 error. + This does not check for zero since BSAFE should not bother to call + this function if there is no error. + */ +int ConvertAlgaeError (type) +int type; +{ + switch (type) { + case AE_CANCEL: + return (BE_CANCEL); + case AE_DATA: + return (BE_DATA); + case AE_EXPONENT_EVEN: + return (BE_EXPONENT_EVEN); + case AE_EXPONENT_LEN: + return (BE_EXPONENT_LEN); + case AE_INPUT_DATA: + return (BE_INPUT_DATA); + case AE_INPUT_LEN: + return (BE_INPUT_LEN); + case AE_KEY_INFO: + return (BE_KEY_INFO); + case AE_KEY_LEN: + return (BE_KEY_LEN); + case AE_MODULUS_LEN: + return (BE_MODULUS_LEN); + case AE_NOT_INITIALIZED: + return (BE_NOT_INITIALIZED); + case AE_NOT_SUPPORTED: + return (BE_NOT_SUPPORTED); + case AE_OUTPUT_LEN: + return (BE_OUTPUT_LEN); + case AE_PARAMS: + return (BE_ALGORITHM_INFO); + +#if USE_ALLOCED_FRAME + case AE_ALLOC: + return (BE_ALLOC); +#endif + + default: + return (BE_DATA); + } +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/algchoic.h b/usr/src/lib/libresolv2/common/dnssafe/algchoic.h new file mode 100644 index 0000000000..699b5dbe7d --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/algchoic.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _ALGCHOICE_H_ +#define _ALGCHOICE_H_ 1 + +#define IS_FATAL_BSAFE_ERROR(status) \ + (status == BE_ALLOC || status == BE_HARDWARE || status == BE_CANCEL) + +/* Use the THIS_ALGA_CHOICE macro to define the type of object in the + INIT_ALGA prototype. It defaults to the AlgaChoice, but + derived modules may define the macro to a more derived class before + including this header file. + */ +struct AlgaChoice; +#ifndef THIS_ALGA_CHOICE +#define THIS_ALGA_CHOICE struct AlgaChoice +#endif + +/* In C++: +class ResizeContext { +public: + ResizeContext (); + ~ResizeContext (); + int makeNewContext (unsigned int contextSize); + POINTER context () {return z.context;} + +private: + struct { + POINTER context; + unsigned int contextSize; + } z; +}; + +class AlgaChoice; +typedef int (*INIT_ALGA) + (THIS_ALGA_CHOICE *algaChoice, POINTER keyInfo, + struct B_ALGORITHM_METHOD *algorithmMethod, + A_SURRENDER_CTX *surrenderContext); + +class AlgaChoice { +public: + AlgaChoice (INIT_ALGA InitAlga) : _InitAlga (InitAlga) {} + ~AlgaChoice () {} + int choose + (int encryptFlag, B_Key *key, B_ALGORITHM_CHOOSER chooser, + A_SURRENDER_CTX *surrenderContext); + int makeNewContext (unsigned int contextSize) { + context.makeNewContext (contextSize); } + POINTER alga () {return _alga;} + POINTER algorithmInfo () {return _algorithmInfo;} + POINTER context () {return context.context ();} + void setAlgorithmInfoType (B_AlgorithmInfoType *algorithmInfoType) { + _algorithmInfoType = algorithmInfoType; + } + void setAlgorithmInfo (POINTER algorithmInfo) { + _algorithmInfo = algorithmInfo; + } + +private: + POINTER _alga; + B_AlgorithmInfoType *_algorithmInfoType; + POINTER _algorithmInfo; + INIT_ALGA _InitAlga; + + ResizeContext context; +}; + */ +struct B_AlgorithmInfoType; + +typedef struct ResizeContext { + struct { + POINTER context; + unsigned int contextSize; + } z; /* zeriozed by constructor */ +} ResizeContext; + +typedef int (*INIT_ALGA) PROTO_LIST + ((THIS_ALGA_CHOICE *, POINTER, struct B_ALGORITHM_METHOD *, + A_SURRENDER_CTX *)); + +typedef struct AlgaChoice { + POINTER _alga; + struct B_AlgorithmInfoType *_algorithmInfoType; + POINTER _algorithmInfo; + INIT_ALGA _InitAlga; + + ResizeContext context; +} AlgaChoice; + +void ResizeContextConstructor PROTO_LIST ((ResizeContext *)); +void ResizeContextDestructor PROTO_LIST ((ResizeContext *)); +int ResizeContextMakeNewContext PROTO_LIST ((ResizeContext *, unsigned int)); + +#define ALGA_CHOICE_Constructor(algaChoice, InitAlga)\ + (ResizeContextConstructor (&(algaChoice)->context), \ + (algaChoice)->_InitAlga = (InitAlga)) +#define ALGA_CHOICE_Destructor(algaChoice)\ + (ResizeContextDestructor (&(algaChoice)->context)) + +int AlgaChoiceChoose PROTO_LIST + ((AlgaChoice *, int, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); + +int ConvertAlgaeError PROTO_LIST ((int)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/algobj.c b/usr/src/lib/libresolv2/common/dnssafe/algobj.c new file mode 100644 index 0000000000..6be38586f9 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/algobj.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "keyobj.h" +#include "algobj.h" +#include "port_after.h" + +static char ALGORITHM_TYPE_TAG = 0; + +int B_CreateAlgorithmObject (algorithmObject) +B_ALGORITHM_OBJ *algorithmObject; +{ + AlgorithmWrap *algorithmWrap; + + if ((*algorithmObject = T_malloc (sizeof (*algorithmWrap))) == NULL_PTR) + return (BE_ALLOC); + + algorithmWrap = (AlgorithmWrap *)*algorithmObject; + + /* First construct base class */ + B_AlgorithmConstructor (&algorithmWrap->algorithm); + + algorithmWrap->typeTag = &ALGORITHM_TYPE_TAG; + algorithmWrap->selfCheck = algorithmWrap; + return (0); +} + +void B_DestroyAlgorithmObject (algorithmObject) +B_ALGORITHM_OBJ *algorithmObject; +{ + AlgorithmWrap *algorithmWrap = (AlgorithmWrap *)*algorithmObject; + + if (AlgorithmWrapCheck (algorithmWrap) == 0) { + /* zeroize self check to invalidate memory. */ + algorithmWrap->selfCheck = (AlgorithmWrap *)NULL_PTR; + + /* Call base class descructor */ + B_AlgorithmDestructor (&algorithmWrap->algorithm); + + T_free ((POINTER)algorithmWrap); + } + + *algorithmObject = NULL_PTR; +} + +int B_SetAlgorithmInfo (algorithmObject, infoType, info) +B_ALGORITHM_OBJ algorithmObject; +B_INFO_TYPE infoType; +POINTER info; +{ + B_AlgorithmInfoType *algorithmInfoType; + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + /* Get the AlgorithmInfoType from the B_INFO_TYPE, which returns + zero for an AlgorithmInfoType, non-zero for KeyInfoType + */ + if ((*infoType) ((POINTER *)&algorithmInfoType) != 0) + return (BE_KEY_OPERATION_UNKNOWN); + + return (B_AlgorithmSetInfo + (&THE_ALG_WRAP->algorithm, algorithmInfoType, info)); +} + +int B_GetAlgorithmInfo (info, algorithmObject, infoType) +POINTER *info; +B_ALGORITHM_OBJ algorithmObject; +B_INFO_TYPE infoType; +{ + B_AlgorithmInfoType *algorithmInfoType; + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + /* Get the AlgorithmInfoType from the B_INFO_TYPE, which returns + zero for an AlgorithmInfoType, non-zero for KeyInfoType + */ + if ((*infoType) ((POINTER *)&algorithmInfoType) != 0) + return (BE_KEY_OPERATION_UNKNOWN); + + return (B_AlgorithmGetInfo + (&THE_ALG_WRAP->algorithm, info, algorithmInfoType)); +} + +/* Return 0 if this is a valid AlgorithmWrap object. Return BE_ALGORITHM_OBJ if + algorithmWrap is NULL_PTR or invalid. + */ +int AlgorithmWrapCheck (algorithmWrap) +AlgorithmWrap *algorithmWrap; +{ + return ((algorithmWrap != (AlgorithmWrap *)NULL_PTR && + algorithmWrap->selfCheck == algorithmWrap && + algorithmWrap->typeTag == &ALGORITHM_TYPE_TAG) ? + 0 : BE_ALGORITHM_OBJ); +} + +/* Like AlgorithmWrapCheck except returns BE_RANDOM_OBJ for error. + Also, return OK status if randomAlgorithm is NULL_PTR. + */ +int RandomAlgorithmCheck (randomAlgorithm) +B_ALGORITHM_OBJ randomAlgorithm; +{ + if (randomAlgorithm == NULL_PTR) + return (0); + + return (AlgorithmWrapCheck ((AlgorithmWrap *)randomAlgorithm) ? + BE_RANDOM_OBJ : 0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/algobj.h b/usr/src/lib/libresolv2/common/dnssafe/algobj.h new file mode 100644 index 0000000000..a101e8f719 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/algobj.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#define THE_ALG_WRAP ((AlgorithmWrap *)algorithmObject) + +typedef struct AlgorithmWrap { + B_Algorithm algorithm; + char *typeTag; + struct AlgorithmWrap *selfCheck; +} AlgorithmWrap; + +int AlgorithmWrapCheck PROTO_LIST ((AlgorithmWrap *)); +int RandomAlgorithmCheck PROTO_LIST ((B_ALGORITHM_OBJ)); + diff --git a/usr/src/lib/libresolv2/common/dnssafe/amcrte.c b/usr/src/lib/libresolv2/common/dnssafe/amcrte.c new file mode 100644 index 0000000000..beb2c4555b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/amcrte.c @@ -0,0 +1,126 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "balgmeth.h" +#include "crt2.h" +#include "amencdec.h" +#include "port_after.h" + +static int RSA_CRT2Query PROTO_LIST ((unsigned int *, POINTER, POINTER)); +static int RSA_CRT2Init PROTO_LIST + ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); +static int RSA_CRT2Update PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +static int RSA_CRT2Final PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); +static int RSA_CRT2GetMaxOutputLen PROTO_LIST + ((POINTER, unsigned int *, unsigned int)); +static int RSA_CRT2GetBlockLen PROTO_LIST ((POINTER, unsigned int *)); + +extern struct B_AlgorithmInfoType AIT_RSAPrivate; +extern struct B_KeyInfoType KIT_RSA_CRT; + +static A_ENCRYPT_DECRYPT_ALGA A_RSA_CRT2_CRYPT = { + RSA_CRT2Query, RSA_CRT2Init, RSA_CRT2Update, RSA_CRT2Final, + RSA_CRT2GetMaxOutputLen, RSA_CRT2GetBlockLen +}; + +B_ALGORITHM_METHOD AM_RSA_CRT_DECRYPT = + {&AIT_RSAPrivate, 0, &KIT_RSA_CRT, (POINTER)&A_RSA_CRT2_CRYPT}; +B_ALGORITHM_METHOD AM_RSA_CRT_ENCRYPT = + {&AIT_RSAPrivate, 1, &KIT_RSA_CRT, (POINTER)&A_RSA_CRT2_CRYPT}; + +static int RSA_CRT2Query (contextLen, key, params) +unsigned int *contextLen; +POINTER key; +POINTER params; +{ +UNUSED_ARG (params) + + if (A_IntegerBits + (((A_RSA_CRT_KEY *)key)->modulus.data, + ((A_RSA_CRT_KEY *)key)->modulus.len) > MAX_RSA_MODULUS_BITS) + /* Key size is too big to handle. */ + return (AE_MODULUS_LEN); + + *contextLen = sizeof (A_RSA_CRT2_CTX); + return (0); +} + +static int RSA_CRT2Init (context, key, params, surrenderContext) +POINTER context; +POINTER key; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (params) +UNUSED_ARG (surrenderContext) + + return (A_RSA_CRT2Init ((A_RSA_CRT2_CTX *)context, (A_RSA_CRT_KEY *)key)); +} + +static int RSA_CRT2Update + (context, output, outputLen, maxOutputLen, input, inputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +const unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + return (A_RSA_CRT2Update + ((A_RSA_CRT2_CTX *)context, output, outputLen, maxOutputLen, input, + inputLen, surrenderContext)); +} + +static int RSA_CRT2Final + (context, output, outputLen, maxOutputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +A_SURRENDER_CTX * surrenderContext; +{ +UNUSED_ARG (output) +UNUSED_ARG (maxOutputLen) +UNUSED_ARG (surrenderContext) + + *outputLen = 0; + return (A_RSA_CRT2Final ((A_RSA_CRT2_CTX *)context)); +} + +static int RSA_CRT2GetMaxOutputLen (context, outputLen, inputLen) +POINTER context; +unsigned int *outputLen; +unsigned int inputLen; +{ + *outputLen = A_RSA_CRT2_MAX_OUTPUT_LEN ((A_RSA_CRT2_CTX *)context, inputLen); + return (0); +} + +static int RSA_CRT2GetBlockLen (context, blockLen) +POINTER context; +unsigned int *blockLen; +{ + *blockLen = A_RSA_CRT2_BLOCK_LEN ((A_RSA_CRT2_CTX *)context); + return(0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/amdigest.h b/usr/src/lib/libresolv2/common/dnssafe/amdigest.h new file mode 100644 index 0000000000..f58f2e1fcf --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/amdigest.h @@ -0,0 +1,26 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef struct { + int (*Query) PROTO_LIST ((unsigned int *, POINTER)); + int (*Init) PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX *)); + int (*Update) PROTO_LIST + ((POINTER, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*Final) PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + int (*GetMaxOutputLen) PROTO_LIST ((POINTER, unsigned int *)); +} A_DIGEST_ALGA; + diff --git a/usr/src/lib/libresolv2/common/dnssafe/amencdec.h b/usr/src/lib/libresolv2/common/dnssafe/amencdec.h new file mode 100644 index 0000000000..0cacf5236c --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/amencdec.h @@ -0,0 +1,28 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef struct { + int (*Query) PROTO_LIST ((unsigned int *, POINTER, POINTER)); + int (*Init) PROTO_LIST ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); + int (*Update) PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*Final) PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + int (*GetMaxOutputLen) PROTO_LIST ((POINTER, unsigned int *, unsigned int)); + int (*GetBlockLen) PROTO_LIST ((POINTER, unsigned int *)); +} A_ENCRYPT_DECRYPT_ALGA; + diff --git a/usr/src/lib/libresolv2/common/dnssafe/amgen.h b/usr/src/lib/libresolv2/common/dnssafe/amgen.h new file mode 100644 index 0000000000..dfc56deba5 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/amgen.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +struct B_KeyInfoType; + +typedef struct { + int (*Query) PROTO_LIST + ((unsigned int *, unsigned int *, unsigned int *, struct B_KeyInfoType **, + POINTER)); + int (*Init) PROTO_LIST ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); + int (*Generate) PROTO_LIST + ((POINTER, POINTER *, unsigned char *, A_SURRENDER_CTX *)); +} A_GENERATE_ALGA; + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ammd5.c b/usr/src/lib/libresolv2/common/dnssafe/ammd5.c new file mode 100644 index 0000000000..26c7503952 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ammd5.c @@ -0,0 +1,109 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "balgmeth.h" +#include "md5.h" +#include "amdigest.h" +#include "port_after.h" + +static int amMD5Query PROTO_LIST ((unsigned int *, POINTER)); +static int amMD5Init PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX*)); +static int amMD5Update PROTO_LIST + ((POINTER, const unsigned char *, unsigned int, A_SURRENDER_CTX*)); +static int amMD5Final PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, A_SURRENDER_CTX*)); +static int amMD5GetMaxOutputLen PROTO_LIST ((POINTER, unsigned int *)); + +static A_DIGEST_ALGA A_MD5_DIGEST = { + amMD5Query, amMD5Init, amMD5Update, amMD5Final, amMD5GetMaxOutputLen +}; + +extern struct B_AlgorithmInfoType AIT_MD5; + +B_ALGORITHM_METHOD AM_MD5 = + {&AIT_MD5, 0, (struct B_KeyInfoType *)NULL_PTR, (POINTER)&A_MD5_DIGEST}; + +/* Returns 0. + */ +static int amMD5Query (contextLen, params) +unsigned int *contextLen; +POINTER params; +{ +UNUSED_ARG (params) + + *contextLen = sizeof (A_MD5_CTX); + return (0); +} + +/* Returns 0. + */ +static int amMD5Init (context, params, surrenderContext) +POINTER context; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (params) +UNUSED_ARG (surrenderContext) + + A_MD5Init ((A_MD5_CTX *)context); + return (0); +} + +/* Returns 0. + */ +static int amMD5Update (context, input, inputLen, surrenderContext) +POINTER context; +const unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (surrenderContext) + + A_MD5Update ((A_MD5_CTX *)context, input, inputLen); + return (0); +} + +/* Returns 0, AE_OUTPUT_LEN if maxDigestLen is too small. + */ +static int amMD5Final + (context, digest, digestLen, maxDigestLen, surrenderContext) +POINTER context; +unsigned char *digest; +unsigned int *digestLen; +unsigned int maxDigestLen; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (surrenderContext) + + if ((*digestLen = A_MD5_DIGEST_LEN) > maxDigestLen) + return (AE_OUTPUT_LEN); + + A_MD5Final ((A_MD5_CTX *)context, digest); + return (0); +} + +static int amMD5GetMaxOutputLen (context, outputLen) +POINTER context; +unsigned int *outputLen; +{ +UNUSED_ARG (context) + + *outputLen = A_MD5_DIGEST_LEN; + return(0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/ammd5r.c b/usr/src/lib/libresolv2/common/dnssafe/ammd5r.c new file mode 100644 index 0000000000..10ffb58635 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ammd5r.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "balgmeth.h" +#include "md5rand.h" +#include "amrandom.h" +#include "port_after.h" + +static int MD5RandomQuery PROTO_LIST ((unsigned int *, POINTER)); +static int MD5RandomInit PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX *)); +static int MD5RandomUpdate PROTO_LIST + ((POINTER, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +static int MD5RandomGenerateBytes PROTO_LIST + ((POINTER, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +extern struct B_AlgorithmInfoType AIT_MD5Random; + +static A_RANDOM_ALGA A_MD5_RANDOM = + {MD5RandomQuery, MD5RandomInit, MD5RandomUpdate, MD5RandomGenerateBytes}; + +B_ALGORITHM_METHOD AM_MD5_RANDOM = + {&AIT_MD5Random, 0, (struct B_KeyInfoType *)NULL_PTR, + (POINTER)&A_MD5_RANDOM}; + +static int MD5RandomQuery (contextLen, params) +unsigned int *contextLen; +POINTER params; +{ +UNUSED_ARG (params) + + *contextLen = sizeof (A_MD5_RANDOM_CTX); + return (0); +} + +static int MD5RandomInit (context, params, surrenderContext) +POINTER context; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (params) +UNUSED_ARG (surrenderContext) + + A_MD5RandomInit ((A_MD5_RANDOM_CTX *)context); + return (0); +} + +static int MD5RandomUpdate (context, input, inputLen, surrenderContext) +POINTER context; +unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (surrenderContext) + + A_MD5RandomUpdate ((A_MD5_RANDOM_CTX *)context, input, inputLen); + return (0); +} + +static int MD5RandomGenerateBytes + (context, output, outputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int outputLen; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (surrenderContext) + + A_MD5RandomGenerateBytes ((A_MD5_RANDOM_CTX *)context, output, outputLen); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/amrandom.h b/usr/src/lib/libresolv2/common/dnssafe/amrandom.h new file mode 100644 index 0000000000..2576e389c8 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/amrandom.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef struct { + int (*Query) PROTO_LIST ((unsigned int *, POINTER)); + int (*Init) PROTO_LIST ((POINTER, POINTER, A_SURRENDER_CTX *)); + int (*Update) PROTO_LIST + ((POINTER, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + int (*Generate) PROTO_LIST + ((POINTER, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +} A_RANDOM_ALGA; + diff --git a/usr/src/lib/libresolv2/common/dnssafe/amrkg.c b/usr/src/lib/libresolv2/common/dnssafe/amrkg.c new file mode 100644 index 0000000000..7fe6905899 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/amrkg.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "algae.h" +#include "rsakeygn.h" +#include "balgmeth.h" +#include "amgen.h" +#include "port_after.h" + +#define THE_GEN_PARAMS ((A_RSA_KEY_GEN_PARAMS *)params) + +extern struct B_AlgorithmInfoType AIT_RSAKeyGen; +extern struct B_KeyInfoType KIT_PKCS_RSAPrivate; + +static int RSAKeyGenQuery PROTO_LIST + ((unsigned int *, unsigned int *, unsigned int *, struct B_KeyInfoType **, + POINTER)); +static int RSAKeyGenInit PROTO_LIST + ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); +static int RSAKeyGen PROTO_LIST + ((POINTER, POINTER *, unsigned char *, A_SURRENDER_CTX *)); + +static A_GENERATE_ALGA A_RSA_KEY_GEN = + {RSAKeyGenQuery, RSAKeyGenInit, RSAKeyGen}; + +B_ALGORITHM_METHOD AM_RSA_KEY_GEN = + {&AIT_RSAKeyGen, 0, (struct B_KeyInfoType *)NULL_PTR, + (POINTER)&A_RSA_KEY_GEN}; + +static int RSAKeyGenQuery + (contextLen, secondContextLen, randomBlockLen, resultInfoType, params) +unsigned int *contextLen; +unsigned int *secondContextLen; +unsigned int *randomBlockLen; +struct B_KeyInfoType **resultInfoType; +POINTER params; +{ + if ((THE_GEN_PARAMS->modulusBits > MAX_RSA_MODULUS_BITS) || + (THE_GEN_PARAMS->modulusBits < MIN_RSA_MODULUS_BITS)) + /* Can't support a keypair of this size. */ + return (AE_MODULUS_LEN); + + *contextLen = sizeof (A_RSA_KEY_GEN_CTX); + *secondContextLen = 0; + *randomBlockLen = + A_RSA_KEY_GEN_RANDOM_BLOCK_LEN (THE_GEN_PARAMS->modulusBits); + *resultInfoType = &KIT_PKCS_RSAPrivate; + + return (0); +} + +static int RSAKeyGenInit (context, secondContext, params, surrenderContext) +POINTER context; +POINTER secondContext; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (secondContext) +UNUSED_ARG (surrenderContext) + + return (A_RSAKeyGenInit + ((A_RSA_KEY_GEN_CTX *)context, (A_RSA_KEY_GEN_PARAMS *)params)); +} + +static int RSAKeyGen (context, result, randomBlock, surrenderContext) +POINTER context; +POINTER *result; +unsigned char *randomBlock; +A_SURRENDER_CTX *surrenderContext; +{ + return (A_RSAKeyGen + ((A_RSA_KEY_GEN_CTX *)context, (A_PKCS_RSA_PRIVATE_KEY **)result, + randomBlock, surrenderContext)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/amrsae.c b/usr/src/lib/libresolv2/common/dnssafe/amrsae.c new file mode 100644 index 0000000000..01a26bef47 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/amrsae.c @@ -0,0 +1,124 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bsafe2.h" +#include "balgmeth.h" +#include "rsa.h" +#include "amencdec.h" +#include "port_after.h" + +static int RSAQuery PROTO_LIST ((unsigned int *, POINTER, POINTER)); +static int RSAInit PROTO_LIST ((POINTER, POINTER, POINTER, A_SURRENDER_CTX *)); +static int RSAUpdate PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +static int RSAFinal PROTO_LIST + ((POINTER, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); +static int RSAGetMaxOutputLen PROTO_LIST + ((POINTER, unsigned int *, unsigned int)); +static int RSAGetBlockLen PROTO_LIST ((POINTER, unsigned int *)); + +extern struct B_AlgorithmInfoType AIT_RSAPublic; +extern struct B_KeyInfoType KIT_RSAPublic; + +static A_ENCRYPT_DECRYPT_ALGA A_RSA_CRYPT = { + RSAQuery, RSAInit, RSAUpdate, RSAFinal, RSAGetMaxOutputLen, RSAGetBlockLen +}; + +B_ALGORITHM_METHOD AM_RSA_DECRYPT = + {&AIT_RSAPublic, 0, &KIT_RSAPublic, (POINTER)&A_RSA_CRYPT}; +B_ALGORITHM_METHOD AM_RSA_ENCRYPT = + {&AIT_RSAPublic, 1, &KIT_RSAPublic, (POINTER)&A_RSA_CRYPT}; + +static int RSAQuery (contextLen, key, params) +unsigned int *contextLen; +POINTER key; +POINTER params; +{ +UNUSED_ARG (params) + + if (A_IntegerBits + (((A_RSA_KEY *)key)->modulus.data, ((A_RSA_KEY *)key)->modulus.len) + > MAX_RSA_MODULUS_BITS) + /* Key size is too big to handle. */ + return (AE_MODULUS_LEN); + + *contextLen = sizeof (A_RSA_CTX); + return (0); +} + +static int RSAInit (context, key, params, surrenderContext) +POINTER context; +POINTER key; +POINTER params; +A_SURRENDER_CTX *surrenderContext; +{ +UNUSED_ARG (params) +UNUSED_ARG (surrenderContext) + + return (A_RSAInit ((A_RSA_CTX *)context, (A_RSA_KEY *)key)); +} + +static int RSAUpdate + (context, output, outputLen, maxOutputLen, input, inputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +const unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + return (A_RSAUpdate + ((A_RSA_CTX *)context, output, outputLen, maxOutputLen, input, + inputLen, surrenderContext)); +} + +static int RSAFinal + (context, output, outputLen, maxOutputLen, surrenderContext) +POINTER context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +A_SURRENDER_CTX * surrenderContext; +{ +UNUSED_ARG (output) +UNUSED_ARG (maxOutputLen) +UNUSED_ARG (surrenderContext) + + *outputLen = 0; + return (A_RSAFinal ((A_RSA_CTX *)context)); +} + +static int RSAGetMaxOutputLen (context, outputLen, inputLen) +POINTER context; +unsigned int *outputLen; +unsigned int inputLen; +{ + *outputLen = A_RSA_MAX_OUTPUT_LEN ((A_RSA_CTX *)context, inputLen); + return (0); +} + +static int RSAGetBlockLen (context, blockLen) +POINTER context; +unsigned int *blockLen; +{ + *blockLen = A_RSA_BLOCK_LEN ((A_RSA_CTX *)context); + return(0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/atypes.h b/usr/src/lib/libresolv2/common/dnssafe/atypes.h new file mode 100644 index 0000000000..8fbfeb6b27 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/atypes.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _ATYPES_H_ +#define _ATYPES_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ITEM_ +#define _ITEM_ 1 +typedef struct { + unsigned char *data; + unsigned int len; +} ITEM; +#endif + +typedef struct { + int (T_CALL *Surrender) PROTO_LIST ((POINTER)); + POINTER handle; + POINTER reserved; +} A_SURRENDER_CTX; + +typedef struct { + ITEM modulus; + ITEM publicExponent; + ITEM privateExponent; + ITEM prime[2]; /* prime factors */ + ITEM primeExponent[2]; /* exponents for prime factors */ + ITEM coefficient; /* CRT coefficient */ +} A_PKCS_RSA_PRIVATE_KEY; + +typedef struct { + ITEM modulus; + ITEM prime[2]; /* prime factors */ + ITEM primeExponent[2]; /* exponents for prime factors */ + ITEM coefficient; /* CRT coefficient */ +} A_RSA_CRT_KEY; + +typedef struct { + ITEM modulus; /* modulus */ + ITEM exponent; /* exponent */ +} A_RSA_KEY; + +typedef struct { + unsigned int modulusBits; + ITEM publicExponent; +} A_RSA_KEY_GEN_PARAMS; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/balg.c b/usr/src/lib/libresolv2/common/dnssafe/balg.c new file mode 100644 index 0000000000..0105aa2873 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/balg.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "btypechk.h" +#include "ainfotyp.h" +#include "port_after.h" + +void B_AlgorithmConstructor (algorithm) +B_Algorithm *algorithm; +{ + /* Construct immediate base class. */ + B_InfoCacheConstructor (&algorithm->infoCache); + + T_memset ((POINTER)&algorithm->z, 0, sizeof (algorithm->z)); +} + +void B_AlgorithmDestructor (algorithm) +B_Algorithm *algorithm; +{ + if (algorithm->z.handler != (B_TypeCheck *)NULL_PTR) { + B_TYPE_CHECK_Destructor (algorithm->z.handler); + T_free ((POINTER)algorithm->z.handler); + } + + /* Destroy base class */ + B_INFO_CACHE_Destructor (&algorithm->infoCache); +} + +int B_AlgorithmCheckType (algorithm, Destructor) +B_Algorithm *algorithm; +B_TYPE_CHECK_DESTRUCTOR Destructor; +{ + if (algorithm->z.handler == (B_TypeCheck *)NULL_PTR) + return (BE_ALGORITHM_NOT_SET); + + if (algorithm->z.handler->_Destructor != Destructor) + return (BE_ALG_OPERATION_UNKNOWN); + + return (0); +} + +int B_AlgorithmCheckTypeAndInitFlag (algorithm, Destructor) +B_Algorithm *algorithm; +B_TYPE_CHECK_DESTRUCTOR Destructor; +{ + int status; + + /* Check the type first. */ + if ((status = B_AlgorithmCheckType (algorithm, Destructor)) != 0) + return (status); + + if (!algorithm->z.initFlag) + return (BE_ALGORITHM_NOT_INITIALIZED); + + return (0); +} + +int B_AlgorithmSetInfo (algorithm, algorithmInfoType, info) +B_Algorithm *algorithm; +B_AlgorithmInfoType *algorithmInfoType; +POINTER info; +{ + int status; + + if (algorithm->infoCache.z.infoCount > 0) + return (BE_ALGORITHM_ALREADY_SET); + + /* This will cache the encoding. */ + if ((status = (*algorithmInfoType->vTable->AddInfo) + (algorithmInfoType, algorithm, info)) != 0) + return (status); + + /* Allocate the algorithm handler. NewHandler returns NULL_PTR for error. + */ + if ((algorithm->z.handler = (*algorithmInfoType->vTable->NewHandler) + (algorithmInfoType, algorithm)) == (B_TypeCheck *)NULL_PTR) + return (BE_ALLOC); + + return (0); +} + +int B_AlgorithmGetInfo (algorithm, info, algorithmInfoType) +B_Algorithm *algorithm; +POINTER *info; +B_AlgorithmInfoType *algorithmInfoType; +{ + int status; + + if (algorithm->infoCache.z.infoCount == 0) + return (BE_ALGORITHM_NOT_SET); + + /* First check if the encoding is already in the encoding cache. + */ + if (B_InfoCacheFindInfo + (&algorithm->infoCache, info, (POINTER)algorithmInfoType) == 0) + return (0); + + /* Info is not in the cache, go ahead and encode. + */ + if ((status = (*algorithmInfoType->vTable->MakeInfo) + (algorithmInfoType, info, algorithm)) != 0) + return (status); + + return (B_InfoCacheAddInfo + (&algorithm->infoCache, (POINTER)algorithmInfoType, *info)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/balg.h b/usr/src/lib/libresolv2/common/dnssafe/balg.h new file mode 100644 index 0000000000..8c2e2cfe26 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/balg.h @@ -0,0 +1,123 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BALG_H_ +#define _BALG_H_ 1 + +#include "binfocsh.h" +#include "btypechk.h" + +typedef struct { + B_InfoCache infoCache; /* inherited */ + + struct { + B_TypeCheck *handler; + int initFlag; + /* POINTER reserved; */ + } z; +} B_Algorithm; + +void B_AlgorithmConstructor PROTO_LIST ((B_Algorithm *)); +void B_AlgorithmDestructor PROTO_LIST ((B_Algorithm *)); + +int B_AlgorithmCheckType PROTO_LIST ((B_Algorithm *, B_TYPE_CHECK_DESTRUCTOR)); +int B_AlgorithmCheckTypeAndInitFlag PROTO_LIST + ((B_Algorithm *, B_TYPE_CHECK_DESTRUCTOR)); + +struct B_AlgorithmInfoType; +int B_AlgorithmSetInfo PROTO_LIST + ((B_Algorithm *, struct B_AlgorithmInfoType *, POINTER)); +int B_AlgorithmGetInfo PROTO_LIST + ((B_Algorithm *, POINTER *, struct B_AlgorithmInfoType *)); + +int B_AlgorithmRandomInit PROTO_LIST + ((B_Algorithm *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmRandomUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int B_AlgorithmGenerateRandomBytes PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +int B_AlgorithmDigestInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmDigestUpdate PROTO_LIST + ((B_Algorithm *, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int B_AlgorithmDigestFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + +int B_AlgorithmEncryptInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmDecryptInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmEncryptUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int B_AlgorithmDecryptUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, B_Algorithm *, A_SURRENDER_CTX *)); +int B_AlgorithmEncryptFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); +int B_AlgorithmDecryptFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); + +int B_AlgorithmEncodeInit PROTO_LIST ((B_Algorithm *)); +int B_AlgorithmDecodeInit PROTO_LIST ((B_Algorithm *)); +int B_AlgorithmEncodeUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int)); +int B_AlgorithmDecodeUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int)); +int B_AlgorithmEncodeFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int)); +int B_AlgorithmDecodeFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int)); + +int B_AlgorithmSignInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmSignUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int B_AlgorithmSignFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); + +int B_AlgorithmVerifyInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmVerifyUpdate PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int B_AlgorithmVerifyFinal PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int, B_Algorithm *, + A_SURRENDER_CTX *)); + +int B_AlgorithmKeyAgreeInit PROTO_LIST + ((B_Algorithm *, B_Key *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmKeyAgreePhase1 PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + B_Algorithm *, A_SURRENDER_CTX *)); +int B_AlgorithmKeyAgreePhase2 PROTO_LIST + ((B_Algorithm *, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +int B_AlgorithmGenerateInit PROTO_LIST + ((B_Algorithm *, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int B_AlgorithmGenerateKeypair PROTO_LIST + ((B_Algorithm *, B_Key *, B_Key *, B_Algorithm *, + A_SURRENDER_CTX *)); +int B_AlgorithmGenerateParameters PROTO_LIST + ((B_Algorithm *, B_Algorithm *, B_Algorithm *, A_SURRENDER_CTX *)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/balgmeth.h b/usr/src/lib/libresolv2/common/dnssafe/balgmeth.h new file mode 100644 index 0000000000..98ea56077c --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/balgmeth.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +struct B_AlgorithmInfoType; +struct B_KeyInfoType; + +struct B_ALGORITHM_METHOD { + struct B_AlgorithmInfoType *algorithmInfoType; + int encryptFlag; + struct B_KeyInfoType *keyInfoType; + POINTER alga; +}; + diff --git a/usr/src/lib/libresolv2/common/dnssafe/bgclrbit.c b/usr/src/lib/libresolv2/common/dnssafe/bgclrbit.c new file mode 100644 index 0000000000..717e985a7c --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bgclrbit.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigClrbit (a, v) -- clears v-th bit of a, where v is nonnegative. + */ +void BigClrbit (a, v) +UINT2 *a; +unsigned int v; +{ + a[v/16] &= ~ (1 << (v % 16)); +} + +/* BigSetbit (a, v) -- sets v-th bit of a, where v is nonnegative. + */ +void BigSetbit (a, v) +UINT2 *a; +unsigned int v; +{ + a[v/16] |= (1 << (v % 16)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bgmdmpyx.c b/usr/src/lib/libresolv2/common/dnssafe/bgmdmpyx.c new file mode 100644 index 0000000000..8c0bc71172 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bgmdmpyx.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigModMpyx (a, b, c, d, dInv, n) -- a = (b * c) mod d !! EXPRESS. + -- assumes a, b, c, d of length n, dInv of length n+2. + -- assumes dInv previously computed by BigInv. + */ +void BigModMpyx (a, b, c, d, dInv, n) +UINT2 *a, *b, *c, *d, *dInv; +unsigned int n; +{ + UINT2 prod[2 * MAX_RSA_MODULUS_WORDS]; + + BigPmpy (prod, b, c, n); + BigModx (a, prod, d, dInv, n); + + T_memset ((POINTER)prod, 0, sizeof (prod)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bgmdsqx.c b/usr/src/lib/libresolv2/common/dnssafe/bgmdsqx.c new file mode 100644 index 0000000000..f976aa7bbd --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bgmdsqx.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigModSqx (a, b, d, dInv, n) -- a = (b * b) mod d !! EXPRESS. + */ +void BigModSqx (a, b, d, dInv, n) +UINT2 *a, *b, *d, *dInv; +unsigned int n; +{ + UINT2 prod[2 * MAX_RSA_MODULUS_WORDS]; + + BigPsq (prod, b, n); + BigModx (a, prod, d, dInv, n); + + T_memset ((POINTER)prod, 0, sizeof (prod)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bgmodexp.c b/usr/src/lib/libresolv2/common/dnssafe/bgmodexp.c new file mode 100644 index 0000000000..9ae08ec962 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bgmodexp.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "surrendr.h" +#include "port_after.h" + +/* BigModExp (a, b, c, d, n): a = b**c (mod d) + Assumes a, b, c, d of length n. + Returns 0, AE_CANCEL. + */ +int BigModExp (a, b, c, d, n, surrenderContext) +UINT2 *a, *b, *c, *d; +unsigned int n; +A_SURRENDER_CTX *surrenderContext; +{ + struct BigModExpFrame { + UINT2 dInv[MAX_RSA_MODULUS_WORDS + 2], result[MAX_RSA_MODULUS_WORDS], + tab[16][MAX_RSA_MODULUS_WORDS]; + } *frame = (struct BigModExpFrame *)NULL_PTR; +#if !USE_ALLOCED_FRAME + struct BigModExpFrame stackFrame; +#endif + int i, didAMultiply, status; + unsigned int cLen, w, setup[64], power, mask; + + /* Initialize. + */ + do { +#if USE_ALLOCED_FRAME + if ((frame = (struct BigModExpFrame *)T_malloc (sizeof (*frame))) + == (struct BigModExpFrame *)NULL_PTR) { + status = AE_ALLOC; + break; + } +#else + /* Just use the buffers allocated on the stack. */ + frame = &stackFrame; +#endif + + /* precompute inverse of d to enable express mod-outs */ + BigInv (frame->dInv, d, n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* precompute small (size 2**w) table of powers of b */ + cLen = BigLen (c, n); + if (cLen < 4) + w = 1; + else if (cLen < 16) + w = 2; + else if (cLen < 64) + w = 3; + else + w = 4; + + /* zeroth power is one */ + BigConst (frame->tab[0], 1, n); + + /* first power is b */ + BigCopy (frame->tab[1], b, n); + setup[0] = 1; + setup[1] = 1; + for (i = 2; i < 64; i++) + setup[i] = 0; + + /* Loop over elements of exponent c in appropriate radix. + */ + power = 0; + didAMultiply = 0; + mask = 1 << ((cLen) % 16); + for (i = cLen; i >= 0; i--) { + if (didAMultiply) { + BigModSqx (frame->result, frame->result, d, frame->dInv, n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + } + + power = power << 1; + if (setup[power] == 0) { + BigModSqx (frame->tab[power], frame->tab[power/2], d, frame->dInv, n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + setup[power] = 1; + } + if (c[i/16] & mask) + power = power + 1; + if (mask == 1) + mask = 0x8000; + else + mask = (mask >> 1) & 0x7FFF; + if (setup[power] == 0) { + BigModMpyx + (frame->tab[power], frame->tab[power-1], b, d, frame->dInv, n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + setup[power] = 1; + } + if ((i == 0) || (power >= (unsigned int)(1 << (w-1)))) { + if (didAMultiply) { + BigModMpyx + (frame->result, frame->result, frame->tab[power], d, frame->dInv, + n); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + } + else + BigCopy (frame->result, frame->tab[power], n); + + power = 0; + didAMultiply = 1; + } + } + if (status) + break; + + BigCopy (a, frame->result, n); + } while (0); + + if (frame != (struct BigModExpFrame *)NULL_PTR) { + T_memset ((POINTER)frame, 0, sizeof (*frame)); +#if USE_ALLOCED_FRAME + T_free ((POINTER)frame); +#endif + } + return (status); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bgpegcd.c b/usr/src/lib/libresolv2/common/dnssafe/bgpegcd.c new file mode 100644 index 0000000000..ade4d386b6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bgpegcd.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigPegcd + input + u, v bignums + k int size of u, v regs + restriction u, v positive + output + u3=GCD (u, v) (pos) + u1=inv (u)modv (pos) + u2=inv (v)modu (pos) + if GCD (u, v)!=1 then u1, u2 st + u3=u * u1mod (v) & u3=v * u2mod (u) + (see KNUTH vol 2) + */ +void BigPegcd (u3, u1, u2, u, v, k) +UINT2 *u3, *u2, *u1, *u, *v; +unsigned int k; +{ + UINT2 v1[2 * MAX_RSA_PRIME_WORDS], v2[2 * MAX_RSA_PRIME_WORDS], + v3[2 * MAX_RSA_PRIME_WORDS], q[2 * MAX_RSA_PRIME_WORDS], + r[2 * MAX_RSA_PRIME_WORDS], t1[2 * MAX_RSA_PRIME_WORDS], + t2[2 * MAX_RSA_PRIME_WORDS], t3[2 * MAX_RSA_PRIME_WORDS]; + + BigConst (u1, 1, k); + BigConst (u2, 0, k); + BigCopy (u3, u, k); + BigConst (v1, 0, k); + BigConst (v2, 1, k); + BigCopy (v3, v, k); + + /* Begin calc. + */ + while (1) { + if (BigSign (v3, k) == 0) + break; + BigPdiv (q, r, u3, v3, k, k); + BigPmpyl (t1, v1, q, k); + BigPmpyl (t2, v2, q, k); + BigPmpyl (t3, v3, q, k); + BigSub (t1, u1, t1, k); + BigSub (t2, u2, t2, k); + BigSub (t3, u3, t3, k); + + BigCopy (u1, v1, k); + BigCopy (u2, v2, k); + BigCopy (u3, v3, k); + BigCopy (v1, t1, k); + BigCopy (v2, t2, k); + BigCopy (v3, t3, k); + } + + if (BigSign (u1, k) == -1) + /* make positive */ + BigAdd (u1, u1, v, k); + + if (BigSign (u2, k) == -1) + /* make positive */ + BigAdd (u2, u2, u, k); + + T_memset ((POINTER)v1, 0, sizeof (v1)); + T_memset ((POINTER)v2, 0, sizeof (v2)); + T_memset ((POINTER)v3, 0, sizeof (v3)); + T_memset ((POINTER)q, 0, sizeof (q)); + T_memset ((POINTER)r, 0, sizeof (r)); + T_memset ((POINTER)t1, 0, sizeof (t1)); + T_memset ((POINTER)t2, 0, sizeof (t2)); + T_memset ((POINTER)t3, 0, sizeof (t3)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/big2exp.c b/usr/src/lib/libresolv2/common/dnssafe/big2exp.c new file mode 100644 index 0000000000..b0422779d6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/big2exp.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Big2Exp (a, v, n) -- a = 2**v, where v is nonnegative int. + Sets a to be 2**v. + */ +void Big2Exp (a, v, n) +UINT2 *a; +unsigned v; +unsigned int n; +{ + register unsigned int i; + + for (i = 0; i < n; i++) + a[i] = 0; + a[v/16] = 1 << (v % 16); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigabs.c b/usr/src/lib/libresolv2/common/dnssafe/bigabs.c new file mode 100644 index 0000000000..f6a105988d --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigabs.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigAbs (a, b, n) -- a = ABS (b). + */ +void BigAbs (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + if (BigSign (b, n) >= 0) + BigCopy (a, b, n); + else + BigNeg (a, b, n); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigacc.c b/usr/src/lib/libresolv2/common/dnssafe/bigacc.c new file mode 100644 index 0000000000..06d68ab680 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigacc.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Returns carry: vector a = b * vector c. + */ +UINT2 BigAcc (a, b, c, n) +UINT2 *a; +unsigned int b; +UINT2 *c; +unsigned int n; +{ + UINT4 bTemp, result = (UINT4)0; + register unsigned int i; + + if (!b) + return (0); + + bTemp = b; + for (i = 0; i < n; i++) { + result += bTemp * ((UINT4) c[i]); + result += ((UINT4) a[i]); + a[i] = (UINT2) result; + result >>= 16; + } + return ((UINT2)result); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigarith.c b/usr/src/lib/libresolv2/common/dnssafe/bigarith.c new file mode 100644 index 0000000000..adc1b0b194 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigarith.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +void BigZero (a, n) +UINT2 *a; +unsigned int n; +{ + register unsigned int i; + + for (i = 0; i < n; i++) + a[i] = 0; +} + +void BigAdd (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + UINT4 result = (UINT4)0; + register unsigned int i; + + for (i = 0; i < n; i++) { + result += (UINT4) b[i]; + result += (UINT4) c[i]; + a[i] = (UINT2) result; + result >>= 16; + } +} + +void BigSub (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + UINT4 result = (UINT4)1; /* carry bit for negation of c */ + register unsigned int i; + + for (i = 0; i < n; i++) { + result += (UINT4) b[i]; + result += (((UINT4) ~c[i]) & 0x0000FFFFL); + a[i] = (UINT2)result; + result >>= 16; + } +} + +void BigNeg (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + register unsigned int i; + unsigned int carry = 1; + + for (i = 0; i < n-1; i++) { + a[i] = ~b[i] + carry; + if (a[i]) + carry = 0; + } + + a[i] = ~b[i] + carry; +} + +void BigInc (a, n) +UINT2 *a; +unsigned int n; +{ + register unsigned int i; + unsigned int carry = 1; /* carry to start */ + + for (i = 0; i < n-1 && carry; i++) { + a[i]++; + if (a[i]) + carry = 0; + } + + if (carry) + a[i]++; +} + +void BigDec (a, n) +UINT2 *a; +unsigned int n; +{ + register unsigned int i; + unsigned int borrow = 1; /* borrow to start */ + + for (i = 0; i < n-1 && borrow; i++) { + a[i]--; + if (a[i] != 0xFFFF) + borrow = 0; + } + + if (borrow) + a[i]--; +} + +int BigSign (a, n) +UINT2 *a; +unsigned int n; +{ + register int i; + + if (a[n-1] & 0x8000) + return (-1); + for (i = n-1; i >= 0; i--) + if (a[i]) + return (1); + return (0); +} + +void BigCopy (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + register unsigned int i; + + for (i = 0; i < n; i++) + a[i] = b[i]; +} + +/* Assumes a is nonnegative. + */ +unsigned int BigLenw (a, n) +UINT2 *a; +unsigned int n; +{ + register int i; + + for (i = n-1; i >= 0; i--) + if (a[i]) + return (i+1); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigcmp.c b/usr/src/lib/libresolv2/common/dnssafe/bigcmp.c new file mode 100644 index 0000000000..f4df4281f8 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigcmp.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Comparison operator. + BigCmp (a, b, n) -- returns sign of a-b. + */ +int BigCmp (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + register int i; + int aSign = BigSign (a, n), bSign = BigSign (b, n); + + if (aSign > bSign) + return (1); + if (aSign < bSign) + return (-1); + + for (i = n-1; i >= 0 && a[i] == b[i]; i--); + + if (i == -1) + return (0); + if (a[i] > b[i]) + return (1); + return (-1); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigconst.c b/usr/src/lib/libresolv2/common/dnssafe/bigconst.c new file mode 100644 index 0000000000..e4754cb60d --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigconst.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigConst (a, v, n) -- a = v, where v is an int. Initialize bignum a to + value v. + */ +void BigConst (a, v, n) +UINT2 *a; +unsigned int v; +unsigned int n; +{ + UINT2 signWord = (((UINT2)v & 0x8000) ? ~0 : 0); + register unsigned int i; + + a[0] = (UINT2)v; + for (i = 1; i < n; i++) + a[i] = signWord; +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/biginv.c b/usr/src/lib/libresolv2/common/dnssafe/biginv.c new file mode 100644 index 0000000000..92fee05ebf --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/biginv.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +static unsigned int Log2 PROTO_LIST ((unsigned int)); + +/* BigInv (a, b, n) -- compute a as an "inverse" to b, suitable for + modding out integers which are < b**2. + -- assumes a has n+2 words, b has n words. + -- assumes b is a positive integer. + */ +void BigInv (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + UINT2 p[2 * (MAX_RSA_MODULUS_WORDS + 2)], + q[2 * (MAX_RSA_MODULUS_WORDS + 3)], t1[MAX_RSA_MODULUS_WORDS + 3]; + register int i; + unsigned int bl, u, uw, sw; + + /* Do initializations. + */ + /* 2** (bl-1) <= b < 2 ** bl */ + bl = BigLen (b, n); + u = BigU (2 * bl); + + /* uw and sw are in words */ + uw = u/16; + sw = (bl - 2) / 16; + + /* since a = floor ((2**u)/b), 2**(u-bl) < a <= 2**(u-bl+1) */ + + /* Initialize a to 1+2**(u-bl) -- we will converge from below. + */ + Big2Exp (a, u - bl, n + 2); + BigInc (a, n + 2); + + /* Copy b to local register. + */ + BigZero (t1, n + 3); + BigCopy (t1, b, n); + + /* Convergence is quadratic, so iterate log (len (a)) times. + */ + for (i = 1 + Log2 (u - bl + 1); i > 0; i--) { + /* use fast squaring routine to compute p = a**2 + 2**(2 * (u-bl)) < p <= 2**(2 * (u-bl+1)) */ + BigPsq (p, a, n + 2); + + /* compute q = b * floor (p/ (2**s)) + 2**(2 * (u-bl)-s+bl-1) <= q <= 2**(2 * (u-bl+1)-s+bl + 2**(2 * u-bl-s-1) <= q <= 2**(2 * u-bl-s+2) */ + BigPmpy (q, t1, &p[sw], n + 3); + + /* double a + 2**(u-bl+1) < a <= 2**(u-bl+2) */ + BigAdd (a, a, a, n + 2); + /* a = a - floor (q/(2**(u-s))) + 2**(u-bl) < a <= 2**(u-bl+1) + epsilon */ + BigSub (a, a, &q[uw-sw], n + 2); + } + + /* now we are guaranteed that a is not too small */ + BigInc (a, n + 2); + + while (1) { + BigPmpy (p, a, t1, n + 2); + /* makes comparison to 2**u easier */ + BigDec (p, 2 * (n + 2)); + + /* a is desired result */ + if (BigLen (p, 2 * (n + 2)) <= u) + break; + + /* a was too big, reduce and try again */ + BigDec (a, n + 2); + } + + T_memset ((POINTER)p, 0, sizeof (p)); + T_memset ((POINTER)q, 0, sizeof (q)); + T_memset ((POINTER)t1, 0, sizeof (t1)); +} + +/* Log2 (x) -- ceiling of log base 2 of x > 0. Auxiliary function. + */ +static unsigned int Log2 (x) +unsigned int x; +{ + unsigned int i; + + x = x - 1; + /* now Log2 is equal to len in bits of x */ + for (i = 0; x > 0; i++, x >>= 1); + + return (i); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/biglen.c b/usr/src/lib/libresolv2/common/dnssafe/biglen.c new file mode 100644 index 0000000000..8f5ffb0a32 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/biglen.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +unsigned int BigLen (a, n) +UINT2 *a; +unsigned int n; +{ + UINT2 signWord = ((a[n-1] & 0x8000) ? ~0 : 0); + int i, j; + unsigned int k; + + for (i = n-1; i >= 0 && a[i] == signWord; i--); + if (i == -1) + return (1); /* len of 0 or -1 */ + + for (j = 16, k = 0x8000; + j >= 0 && 0 == (k & (signWord ^ a[i])); + j--, k >>= 1); + return (16 * i + j); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigmath.h b/usr/src/lib/libresolv2/common/dnssafe/bigmath.h new file mode 100644 index 0000000000..1675046bc7 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigmath.h @@ -0,0 +1,78 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BIGMATH_H_ +#define _BIGMATH_H_ 1 + +#include "algae.h" +#include "bigmaxes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void Big2Exp PROTO_LIST ((UINT2 *, unsigned int, unsigned int)); +void BigAbs PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +UINT2 BigAcc PROTO_LIST ((UINT2 *, unsigned int, UINT2 *, unsigned int)); +void BigZero PROTO_LIST ((UINT2 *, unsigned int)); +void BigAdd PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigSub PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigNeg PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +void BigInc PROTO_LIST ((UINT2 *, unsigned int)); +void BigDec PROTO_LIST ((UINT2 *, unsigned int)); +int BigSign PROTO_LIST ((UINT2 *, unsigned int)); +void BigCopy PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +unsigned int BigLenw PROTO_LIST ((UINT2 *, unsigned int)); +void BigClrbit PROTO_LIST ((UINT2 *, unsigned int)); +void BigSetbit PROTO_LIST ((UINT2 *, unsigned int)); +int BigCmp PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +void BigConst PROTO_LIST ((UINT2 *, unsigned int, unsigned int)); +void BigInv PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +unsigned int BigLen PROTO_LIST ((UINT2 *, unsigned int)); +void BigModMpyx PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigModSqx PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +int BigModExp PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int, A_SURRENDER_CTX *)); +void BigModx PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigMpy PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigPdiv PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int , unsigned int)); +void BigPegcd PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigPmpy PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigPmpyh PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, unsigned int, unsigned int)); +void BigPmpyl PROTO_LIST ((UINT2 *, UINT2 *, UINT2 *, unsigned int)); +void BigPsq PROTO_LIST ((UINT2 *, UINT2 *, unsigned int)); +void BigQrx PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, unsigned int)); +UINT2 BigSmod PROTO_LIST ((UINT2 *, unsigned int, unsigned int)); +int BigToCanonical PROTO_LIST + ((unsigned char *, unsigned int, UINT2 *, unsigned int)); +unsigned int BigU PROTO_LIST ((unsigned int)); +int BigUnexp PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, + unsigned int, A_SURRENDER_CTX *)); +int CanonicalToBig PROTO_LIST + ((UINT2 *, unsigned int, const unsigned char *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigmaxes.h b/usr/src/lib/libresolv2/common/dnssafe/bigmaxes.h new file mode 100644 index 0000000000..4f803e6025 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigmaxes.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BIGMAXES_H_ +#define _BIGMAXES_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_RSA_MODULUS_BITS 4096 + +#define BITS_TO_LEN(modulusBits) (((modulusBits) + 7) / 8) +#define RSA_PRIME_BITS(modulusBits) (((modulusBits) + 1) / 2) +#define RSA_PRIME_LEN(modulusBits) ((RSA_PRIME_BITS (modulusBits) + 7) / 8) +#define BITS_TO_WORDS(bits) ((bits >> 4) + 1) +#define LEN_TO_WORDS(len) ((len >> 1) + 1) + +/* MAX_RSA_PRIME_BITS -- length in bits of the maximum allowed RSA prime + MAX_RSA_MODULUS_LEN -- length in bytes of the maximum allowed RSA modulus, + in canonical format (no sign bit) + MAX_RSA_PRIME_LEN -- length in bytes of the maximum allowed RSA prime, in + canonical format (no sign bit) + */ +#define MAX_RSA_PRIME_BITS RSA_PRIME_BITS (MAX_RSA_MODULUS_BITS) +#define MAX_RSA_PRIME_LEN RSA_PRIME_LEN (MAX_RSA_MODULUS_BITS) +#define MAX_RSA_MODULUS_LEN BITS_TO_LEN (MAX_RSA_MODULUS_BITS) + +/* MAX_RSA_MODULUS_WORDS -- length in 16-bit words of the maximum allowed RSA + modulus, in bignum format (including sign bit) + MAX_RSA_PRIME_WORDS -- length in 16-bit words of the maximum allowed RSA + prime, in bignum format (including sign bit) + */ + +#define MAX_RSA_MODULUS_WORDS BITS_TO_WORDS (MAX_RSA_MODULUS_BITS) +#define MAX_RSA_PRIME_WORDS BITS_TO_WORDS (MAX_RSA_PRIME_BITS) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigmodx.c b/usr/src/lib/libresolv2/common/dnssafe/bigmodx.c new file mode 100644 index 0000000000..a58f6cdaab --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigmodx.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigModx (a, b, c, cInv, n) -- compute a as (b mod c). + -- assumes a and c of length n, cInv of length n + 2, b of length 2n. + -- assumes cInv computed with BigInv, and that b < c**2. + */ +void BigModx (a, b, c, cInv, n) +UINT2 *a, *b, *c, *cInv; +unsigned int n; +{ + UINT2 q[MAX_RSA_MODULUS_WORDS]; + + BigQrx (q, a, b, c, cInv, n); + + T_memset ((POINTER)q, 0, sizeof (q)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigmpy.c b/usr/src/lib/libresolv2/common/dnssafe/bigmpy.c new file mode 100644 index 0000000000..7ef2d16a85 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigmpy.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigMpy (a, b, c, n) -- a = b * c + -- assumes b and c have n words, a has 2*n words + -- inputs may be positive or negative. + */ +void BigMpy (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + UINT2 prod[2 * MAX_RSA_PRIME_WORDS], absb[MAX_RSA_PRIME_WORDS], + absc[MAX_RSA_PRIME_WORDS]; + int bSign = BigSign (b, n), cSign = BigSign (c, n); + + BigAbs (absb, b, n); + BigAbs (absc, c, n); + BigPmpy (prod, absb, absc, n); + + if (bSign * cSign >= 0) + BigCopy (a, prod, 2 * n); + else + BigNeg (a, prod, 2 * n); + + T_memset ((POINTER)prod, 0, sizeof (prod)); + T_memset ((POINTER)absb, 0, sizeof (absb)); + T_memset ((POINTER)absc, 0, sizeof (absc)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigpdiv.c b/usr/src/lib/libresolv2/common/dnssafe/bigpdiv.c new file mode 100644 index 0000000000..0609f469ef --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigpdiv.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigPdiv POSITIVE DIVIDE + uu=vv * qi+ri + uu in reg of ll cells + vv in reg of kk cells + qi assumed to be ll cells + ri assumed to be kk cells + restriction uu>=0, vv>0 + + input uu in reg of ll cells + input vv in reg of kk cells + output qi assumed to be ll cells + output ri assumed to be kk cells + restriction uu>=0, vv>0 + uu=vv * qi+ri + */ +#define UJN (u[(j+n)/2] & mk[(j+n)%2]) +#define VN (v[n/2] & mk[n%2]) +#define UT (u[t/2] & mk[t%2]) +void BigPdiv (qi, ri, uu, vv, ll, kk) +UINT2 *qi, *ri, *uu, *vv; +unsigned int ll, kk; +{ + UINT2 u[2 * MAX_RSA_PRIME_WORDS + 2], us[2 * MAX_RSA_PRIME_WORDS + 2], + v[2 * MAX_RSA_PRIME_WORDS + 2], vs[2 * MAX_RSA_PRIME_WORDS + 2], + q[2 * MAX_RSA_PRIME_WORDS + 2], r[2 * MAX_RSA_PRIME_WORDS + 2], + t1[2 * MAX_RSA_PRIME_WORDS + 2], t2[2 * MAX_RSA_PRIME_WORDS + 2], + t3[2 * MAX_RSA_PRIME_WORDS + 2], mk[2]; + int j, l, n, m, t, x; + unsigned int a, b, c, d, e, vh, qq; + + if (ll >= kk) + l = ll + 2; + else + l = kk + 2; + + mk[0] = 0x00FF; + mk[1] = 0xFF00; + b = 0x0100; + + BigConst (u, 0, l); + BigConst (v, 0, l); + BigCopy (u, uu, ll); + BigCopy (us, u, l); + BigCopy (v, vv, kk); + BigCopy (vs, v, l); + + /* zero q */ + BigConst (q, 0, l); + + /* Calculate len of v=n. + */ + for (n = (2 * l) - 1; n >= 0; n--) { + if (VN == 0) + continue; + break; + } + + /* Normalize. + */ + a = VN; + if (n % 2 == 1) + a = a >> 8; + d = b / (a+1); + BigConst (t1, d, l); + BigPmpyl (t2, t1, v, l); + BigCopy (v, t2, l); + + /* vh=high order digit of normalized v */ + vh = VN; + if (n % 2 == 1) + vh = vh >> 8; + BigPmpyl (t2, t1, u, l); + BigCopy (u, t2, l); + + /* Calculate len of u=t. + */ + for (t = (2 * l)-1; t >= 0; t--) { + if (UT == 0) + continue; + break; + } + + /* calc t = n + m */ + m = t - n; + + /* Divide u by v. + */ + for (j = m + 1 + n; j > n; j--) { + if (j % 2 == 1) + c = u[j / 2]; + else { + a = u[j/2]; + a = a << 8; + e = u[(j - 1) / 2]; + e = e >> 8; + c = a + e; + } + a = c >> 8; + if (vh == a) + qq = b - 1; + else + qq = c / vh; + + BigConst (t1, qq, l); + BigPmpyl (t2, v, t1, l); + Big2Exp (t3, (j - 1 - n) * 8, l); + BigPmpyl (t1, t3, t2, l); + BigSub (t2, u, t1, l); + + /* Adjust q. + */ + for (x = 0; ; qq --, x ++) { + if (BigSign (t2, l) != -1) + break; + BigPmpyl (t1, t3, v, l); + BigAdd (t2, t2, t1, l); + } + + BigCopy (u, t2, l); + BigConst (t3, qq, l); + Big2Exp (t2, 8, l); + BigPmpyl (t1, q, t2, l); + BigAdd (q, t3, t1, l); + } + + /* Check result. + */ + + BigPmpyl (t1, vs, q, l); + /* t2 has remainder */ + BigSub (t2, us, t1, l); + + BigSub (t3, vs, t2, l); + + /* transfer results to input registers */ + BigCopy (qi, q, ll); + BigCopy (ri, t2, kk); + + T_memset ((POINTER)u, 0, sizeof (u)); + T_memset ((POINTER)us, 0, sizeof (us)); + T_memset ((POINTER)v, 0, sizeof (v)); + T_memset ((POINTER)vs, 0, sizeof (vs)); + T_memset ((POINTER)q, 0, sizeof (q)); + T_memset ((POINTER)r, 0, sizeof (r)); + T_memset ((POINTER)t1, 0, sizeof (t1)); + T_memset ((POINTER)t2, 0, sizeof (t2)); + T_memset ((POINTER)t3, 0, sizeof (t3)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigpmpy.c b/usr/src/lib/libresolv2/common/dnssafe/bigpmpy.c new file mode 100644 index 0000000000..5baa3e5884 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigpmpy.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* a = b * c. + */ +void BigPmpy (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + register unsigned int i; + unsigned int cLen; + + BigZero (a, 2*n); + cLen = BigLenw (c, n); + for (i = 0; i < n; i++) + a[cLen+i] = BigAcc (&a[i], (unsigned int)b[i], c, cLen); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigpmpyh.c b/usr/src/lib/libresolv2/common/dnssafe/bigpmpyh.c new file mode 100644 index 0000000000..6e94d3cf11 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigpmpyh.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Returns high order t bytes of result. + */ +void BigPmpyh (a, b, c, t, n) +UINT2 *a, *b, *c; +unsigned int t, n; +{ + register unsigned int i; + unsigned int iStart, cLen, j; + + BigZero (a, 2*n); + cLen = BigLenw (c, n); + iStart = (t >= n-1) ? t - (n-1) : 0; + + for (i = iStart; i < n; i++) { + j = (t >= i) ? t - i : 0; + a[cLen+i] = BigAcc + (&a[i+j], (unsigned int)b[i], &c[j], (cLen >= j) ? cLen-j : 0); + } +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigpmpyl.c b/usr/src/lib/libresolv2/common/dnssafe/bigpmpyl.c new file mode 100644 index 0000000000..b6bd3d7617 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigpmpyl.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Single precision multiply, a is same len as b and c. + Returns low order n bytes of result. + */ +void BigPmpyl (a, b, c, n) +UINT2 *a, *b, *c; +unsigned int n; +{ + register unsigned int i; + unsigned int cLen; + + BigZero (a, n); + cLen = BigLenw (c, n); + for (i = 0; i < n; i++) { + if (cLen < n-i) + a[cLen+i] = BigAcc (&a[i], (unsigned int)b[i], c, cLen); + else + BigAcc (&a[i], (unsigned int)b[i], c, n-i); + } +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigpsq.c b/usr/src/lib/libresolv2/common/dnssafe/bigpsq.c new file mode 100644 index 0000000000..ee058e2c82 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigpsq.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* Similar to BigPmpy (a, b, b, n) but faster. + */ +void BigPsq (a, b, n) +UINT2 *a, *b; +unsigned int n; +{ + UINT4 result = (UINT4)0; + register unsigned int i; + unsigned int bLen; + + BigZero (a, 2*n); + bLen = BigLenw (b, n); + if (!bLen) + return; + + for (i = 0; i < bLen-1; i++) + a[bLen+i] = BigAcc (&a[2*i+1], (unsigned int)b[i], &b[i+1], bLen-i-1); + BigAdd (a, a, a, 2*n); + + /* add in trace b[i] * b[i] */ + for (i = 0; i < bLen; i++) { + result += ((UINT4)b[i]) * ((UINT4)b[i]); + result += (UINT4)a[2*i]; + a[2*i] = (UINT2)result; + result >>= 16; + result += (UINT4)a[2*i+1]; + a[2*i+1] = (UINT2)result; + result >>= 16; + } + a[2*i] = (UINT2)result; +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigqrx.c b/usr/src/lib/libresolv2/common/dnssafe/bigqrx.c new file mode 100644 index 0000000000..7614783715 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigqrx.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + + +/* BigQrx (q, r, b, c, cInv, n) -- compute quotient and remainder fast. + -- computes q and r s.t. b = q * c + r with 0 <= r < c. + -- assumes b and c are positive integers. + -- assumes q, r, c have n words, cInv has n+2 words, b has 2*n words. + -- assumes cInv previously computed with BigInv. + */ +void BigQrx (q, r, b, c, cInv, n) +UINT2 *q, *r, *b, *c, *cInv; +unsigned int n; +{ + UINT2 qc[2 * (MAX_RSA_MODULUS_WORDS + 2)], /* current product of q and c */ + qsc[2 * (MAX_RSA_MODULUS_WORDS + 2)], /* temporary q scaled by 2**(u-s) */ + t1[2 * MAX_RSA_MODULUS_WORDS + 2]; + int uwsw3; + register unsigned int i; + unsigned int u, uw, cl, sw; + + /* 2**(cl-1) <= c < 2**cl + 2**(u-cl) <= cInv <= 2**(u-cl+1) */ + cl = BigLen (c, n); + + /* u is in bits, uw is in words */ + u = BigU (2 * cl); + uw = u/16; + + /* sw is in words, s is is bits */ + sw = (cl - 2) / 16; + + uwsw3 = uw - sw - 3; + + if (uwsw3 < 0) + uwsw3 = 0; + + /* Copy b to local register. + */ + BigZero (t1, 2 * n + 2); + BigCopy (t1, b, 2 * n); + + /* Compute qsc = cInv * floor (b/ (2**s)). + qsc an approximation to (b/c) * (2**(u-s)) + 2**((u-cl)+ (bl-1-s)) <= qsc 2**((u-cl+1)+ (bl-s)) + 2**(u-cl+bl-s-1) <= qsc <= 2 ** (u-cl+bl-s+1) + (Actually, we only compute a "high-order" approximation + to qsc, by using BigPmpyh.) + */ + BigPmpyh (qsc, cInv, &t1[sw], uwsw3, n + 2); + + /* Divide by 2**(u-s) to get initial estimate for quotient q + 2**(bl-cl-1) <= q <= 2**(bl-cl+1) (unless q = 0). + */ + for (i = 0; i < n; i++) + q[i] = qsc[i+ (uw - sw)]; + + /* compute qc = low-order part of q * c + 2 ** (bl - 2) <= qc <= 2 ** (bl + 1) */ + BigPmpyl (qc, q, c, n); + + /* subtract qc from b to get initial estimate for remainder r */ + BigSub (r, b, qc, n); + + /* Adjust to be exactly right by repeated subtraction. + */ + while (BigCmp (r, c, n) >= 0) { + BigSub (r, r, c, n); + BigInc (q, n); + } + + T_memset ((POINTER)qc, 0, sizeof (qc)); + T_memset ((POINTER)qsc, 0, sizeof (qsc)); + T_memset ((POINTER)t1, 0, sizeof (t1)); +} + + diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigsmod.c b/usr/src/lib/libresolv2/common/dnssafe/bigsmod.c new file mode 100644 index 0000000000..8e44e84773 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigsmod.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1987, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +UINT2 BigSmod (a, v, n) +UINT2 *a; +unsigned int v; +unsigned int n; +{ + UINT4 r = (UINT4)0; + register int i; + unsigned int scale; + + scale = (unsigned int)((UINT4)65536 % (UINT4)v); + + for (i = n-1; i >= 0; i--) { + r = (r*scale) + (UINT4)a[i]; + r = r % (UINT4)v; + } + return ((UINT2)r); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigtocan.c b/usr/src/lib/libresolv2/common/dnssafe/bigtocan.c new file mode 100644 index 0000000000..c3722323ab --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigtocan.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bigmath.h" +#include "port_after.h" + + +/* BigToCanonical () copies a word vector to a byte vector while REVERSING the + order of significance. The word vector is input LSWord first and the + byte vector is written out MSByte first. It also removes a leading zero + sign bit. (The byte vector must represent a nonnegative number.) + Returns 0, AE_DATA. + */ +int BigToCanonical (bytePointer, numBytes, wordPointer, wordCount) +unsigned char *bytePointer; +unsigned int numBytes; +UINT2 *wordPointer; +unsigned int wordCount; +{ + unsigned int copyCount; + + if (BigSign (wordPointer, wordCount) < 0 || + (BigLen (wordPointer, wordCount) + 7) / 8 > numBytes) + return (AE_DATA); + + /* start at end of byte vector */ + bytePointer += numBytes-1; + + /* copy as much as possible */ + copyCount = (wordCount < numBytes / 2) ? wordCount : numBytes / 2; + wordCount -= copyCount; + numBytes -= 2 * copyCount; + while (copyCount--) { + /* Copy two bytes.*/ + *bytePointer-- = (unsigned char)*wordPointer; + *bytePointer-- = (unsigned char)(*wordPointer >> 8); + wordPointer++; + } + + if (wordCount && numBytes & 1) { + /* The number of output bytes was odd. Copy one last byte */ + *bytePointer-- = (unsigned char)*wordPointer++; + wordCount--; + numBytes--; + } + + /* zero fill remainder of byte vector */ + while (numBytes--) + *bytePointer-- = 0; + + return (0); +} + + diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigu.c b/usr/src/lib/libresolv2/common/dnssafe/bigu.c new file mode 100644 index 0000000000..d5cc036706 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigu.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "port_after.h" + +/* BigU (t) -- returns length u where floor (2**u/b) is used as scaled version + of (1/b) when modding out modulo b, and where (positive) integers to be + reduced are < 2**t; i.e. they are at most t bits in length. + Result is (t+1) rounded up if necessary to next multiple of 16. +*/ +unsigned int BigU (t) +unsigned int t; +{ + return (16 * (((t+1) + 15)/16)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/bigunexp.c b/usr/src/lib/libresolv2/common/dnssafe/bigunexp.c new file mode 100644 index 0000000000..14b5302740 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bigunexp.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1986, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bigmath.h" +#include "surrendr.h" +#include "port_after.h" + +/* BigUnexp - decrypt ciphertext c into message m using Chinese remainder. + Assumes m, c of length 2*pSize, pp, qq, dp, dq and cr of length pSize. + Returns 0, AE_CANCEL. + */ +int BigUnexp (m, c, pp, qq, dp, dq, cr, pSize, surrenderContext) +UINT2 *m; /* output message size 2*pSize words */ +UINT2 *c; /* input `ciphertext' size 2*pSize */ +UINT2 *pp; /* first prime size pSize */ +UINT2 *qq; /* second prime; size pSize */ +UINT2 *dp; /* decryption exponent mod p size pSize */ +UINT2 *dq; /* decryption exponent mod q size pSize */ +UINT2 *cr; /* CRT coef (inverse of q mod p) cr has len pSize */ +unsigned int pSize; /* length of p in words */ +A_SURRENDER_CTX *surrenderContext; +{ + struct BigUnexpFrame { + UINT2 t1[2 * MAX_RSA_PRIME_WORDS], t2[2 * MAX_RSA_PRIME_WORDS], + t3[2 * MAX_RSA_PRIME_WORDS], u1[2 * MAX_RSA_PRIME_WORDS], + u2[2 * MAX_RSA_PRIME_WORDS], u3[2 * MAX_RSA_PRIME_WORDS]; + } *frame = (struct BigUnexpFrame *)NULL_PTR; +#if !USE_ALLOCED_FRAME + struct BigUnexpFrame stackFrame; +#endif + int status; + + do { +#if USE_ALLOCED_FRAME + if ((frame = (struct BigUnexpFrame *)T_malloc (sizeof (*frame))) + == (struct BigUnexpFrame *)NULL_PTR) { + status = AE_ALLOC; + break; + } +#else + /* Just use the buffers allocated on the stack. */ + frame = &stackFrame; +#endif + + BigConst (frame->t1, 0, 2 * pSize); + BigConst (frame->t2, 0, 2 * pSize); + + /* u2=c mod p */ + BigPdiv (frame->u1, frame->u2, c, pp, 2 * pSize, pSize); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* t1=c**dp modP */ + if ((status = BigModExp + (frame->t1, frame->u2, dp, pp, pSize, surrenderContext)) != 0) + break; + + /* u3=CmodQ */ + BigPdiv (frame->u2, frame->u3, c, qq, 2 * pSize, pSize); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* t2=c**DQmodQ */ + if ((status = BigModExp + (frame->t2, frame->u3, dq, qq, pSize, surrenderContext)) != 0) + break; + + /* CRT. + */ + BigSub (frame->u1, frame->t1, frame->t2, pSize); + + while (-1 == BigSign (frame->u1, pSize)) + BigAdd (frame->u1, frame->u1, pp, pSize); + + BigMpy (frame->u2, frame->u1, cr, pSize); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + BigPdiv (frame->u3, frame->u1, frame->u2, pp, 2 * pSize, pSize); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + BigMpy (m, frame->u1, qq, pSize); + + BigAdd (m, m, frame->t2, 2 * pSize); + } while (0); + + if (frame != (struct BigUnexpFrame *)NULL_PTR) { + T_memset ((POINTER)frame, 0, sizeof (*frame)); +#if USE_ALLOCED_FRAME + T_free ((POINTER)frame); +#endif + } + return (status); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/binfocsh.c b/usr/src/lib/libresolv2/common/dnssafe/binfocsh.c new file mode 100644 index 0000000000..ffc04dd2f2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/binfocsh.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "binfocsh.h" +#include "port_after.h" + +void B_InfoCacheConstructor (infoCache) +B_InfoCache *infoCache; +{ + /* Construct immediate base class. */ + B_MemoryPoolConstructor (&infoCache->memoryPool); + + T_memset ((POINTER)&infoCache->z, 0, sizeof (infoCache->z)); +} + +/* Returns 0, BE_ALLOC. + */ +int B_InfoCacheAddInfo (infoCache, infoType, info) +B_InfoCache *infoCache; +POINTER infoType; +POINTER info; +{ + int status; + + if ((status = B_MemoryPoolRealloc + (&infoCache->memoryPool, (POINTER *)&infoCache->z.infos, + (infoCache->z.infoCount + 1) * sizeof (infoCache->z.infos[0]))) != 0) + return (status); + + infoCache->z.infos[infoCache->z.infoCount].infoType = infoType; + infoCache->z.infos[infoCache->z.infoCount].info = info; + infoCache->z.infoCount++; + + return (0); +} + +/* Set info to the entry in the cache for the given infoType. + Returns 0, or BE_NOT_SUPPORTED if infoType is not in the cache. + */ +int B_InfoCacheFindInfo (infoCache, info, infoType) +B_InfoCache *infoCache; +POINTER *info; +POINTER infoType; +{ + unsigned int i; + + for (i = 0; i < infoCache->z.infoCount; ++i) { + if (infoCache->z.infos[i].infoType == infoType) { + /* The info has already been constructed. */ + *info = infoCache->z.infos[i].info; + return (0); + } + } + + return (BE_NOT_SUPPORTED); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/binfocsh.h b/usr/src/lib/libresolv2/common/dnssafe/binfocsh.h new file mode 100644 index 0000000000..8600e4bcb1 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/binfocsh.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BINFOCSH_H_ +#define _BINFOCSH_H_ 1 + +#include "bmempool.h" + +typedef struct B_InfoCache { + B_MemoryPool memoryPool; /* inherited */ + struct { + unsigned int infoCount; + struct { + POINTER infoType; + POINTER info; + } *infos; + /* POINTER reserved; */ + } z; /* z gives the members that are zeroized by the constructor */ +} B_InfoCache; + +void B_InfoCacheConstructor PROTO_LIST ((B_InfoCache *)); +#define B_INFO_CACHE_Destructor(infoCache) \ + B_MemoryPoolDestructor (&(infoCache)->memoryPool) + +int B_InfoCacheAddInfo PROTO_LIST ((B_InfoCache *, POINTER, POINTER)); +int B_InfoCacheFindInfo PROTO_LIST ((B_InfoCache *, POINTER *, POINTER)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/bkey.c b/usr/src/lib/libresolv2/common/dnssafe/bkey.c new file mode 100644 index 0000000000..be9b547452 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bkey.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "kiitem.h" +#include "port_after.h" + +int B_KeySetInfo (key, keyInfoType, info) +B_Key *key; +B_KeyInfoType *keyInfoType; +POINTER info; +{ + if (key == (B_Key *)NULL_PTR) + return (BE_KEY_OBJ); + + if (key->infoCache.z.infoCount > 0) + return (BE_KEY_ALREADY_SET); + + /* This will cache the encoding. */ + return ((*keyInfoType->AddInfo) (key, info)); +} + +int B_KeyGetInfo (key, info, keyInfoType) +B_Key *key; +POINTER *info; +B_KeyInfoType *keyInfoType; +{ + int status; + + if (key == (B_Key *)NULL_PTR) + return (BE_KEY_OBJ); + + if (key->infoCache.z.infoCount == 0) + return (BE_KEY_NOT_SET); + + /* First check if the encoding is already in the encoding cache. + */ + if (B_InfoCacheFindInfo (&key->infoCache, info, (POINTER)keyInfoType) == 0) + return (0); + + /* Info is not in the cache, go ahead and encode. + */ + if ((status = (*keyInfoType->MakeInfo) (info, key)) != 0) + return (status); + + return (B_InfoCacheAddInfo (&key->infoCache, (POINTER)keyInfoType, *info)); +} + +/* Create an ITEM out of the data and len and cache it as KITItem. + The data is already alloced in the info cache. + Returns 0, BE_ALLOC. + */ +int B_KeyAddItemInfo (key, data, len) +B_Key *key; +unsigned char *data; +unsigned int len; +{ + ITEM *newInfo; + int status; + + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, (POINTER *)&newInfo, sizeof (*newInfo))) + != 0) + return (status); + + newInfo->data = data; + newInfo->len = len; + + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KITItem, (POINTER)newInfo)); +} + +/* Return the number of bits in the canonical, positive integer. + B_IntegerBits (0) = 0. + */ +unsigned int B_IntegerBits (integer, integerLen) +unsigned char *integer; +unsigned int integerLen; +{ + unsigned char mask, byte; + unsigned int bytes, bits; + + for (bytes = 0; bytes < integerLen && integer[bytes] == 0; bytes++); + if (bytes == integerLen) + return (0); + + /* Get byte to test and increment byte count for final calculation */ + byte = integer[bytes++]; + + /* Get number of bits in most significant byte */ + for (bits = 8, mask = 0x80; (byte & mask) == 0; bits--, mask >>= 1); + return (8 * (integerLen - bytes) + bits); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/bkey.h b/usr/src/lib/libresolv2/common/dnssafe/bkey.h new file mode 100644 index 0000000000..0d9d761068 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bkey.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BKEY_H_ +#define _BKEY_H_ 1 + +#include "binfocsh.h" + +typedef struct { + B_InfoCache infoCache; /* inherited */ + + /* For now we don't need to worry about a reserved field. + struct { + POINTER reserved; + } z; + */ +} B_Key; + +#define B_KEY_Constructor(key) (B_InfoCacheConstructor (&(key)->infoCache)) +#define B_KEY_Destructor(key) (B_INFO_CACHE_Destructor (&(key)->infoCache)) + +struct B_KeyInfoType; +int B_KeySetInfo PROTO_LIST ((B_Key *, struct B_KeyInfoType *, POINTER)); +int B_KeyGetInfo PROTO_LIST ((B_Key *, POINTER *, struct B_KeyInfoType *)); +int B_KeyAddItemInfo PROTO_LIST ((B_Key *, unsigned char *, unsigned int)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/bmempool.c b/usr/src/lib/libresolv2/common/dnssafe/bmempool.c new file mode 100644 index 0000000000..e5d9ae28e0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bmempool.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bmempool.h" +#include "port_after.h" + +#define ALLOCED_LIST_SLACK 10 + +void B_MemoryPoolConstructor (memoryPool) +B_MemoryPool *memoryPool; +{ + T_memset ((POINTER)&memoryPool->z, 0, sizeof (memoryPool->z)); +} + +void B_MemoryPoolDestructor (memoryPool) +B_MemoryPool *memoryPool; +{ + B_MemoryPoolReset (memoryPool); + T_free ((POINTER)memoryPool->z.allocedList); +} + +/* For each item on the alloced list, call the DeleteFuncion if + there is one, otherwise zerioze and free. + Leave the list itself allocated with all NULL entries. + */ +void B_MemoryPoolReset (memoryPool) +B_MemoryPool *memoryPool; +{ + B_ALLOCED_DATA *allocedData; + unsigned int i; + + for (i = memoryPool->z.allocedCount, + allocedData = memoryPool->z.allocedList; + i-- > 0; + ++allocedData) { + /* Only process this entry if the data is not NULL_PTR. + */ + if (allocedData->object != NULL_PTR) { + if (allocedData->DeleteFunction != NULL) + /* There is a destroy function, so call. */ + (*allocedData->DeleteFunction) (allocedData->object); + else { + T_memset (allocedData->object, 0, allocedData->size); + T_free (allocedData->object); + } + allocedData->object = NULL_PTR; + } + } + + memoryPool->z.allocedCount = 0; + /* Note that maxAllocedCount still indicates the size of the alloced list. */ +} + +/* On any error return, NULL_PTR is returned for the data. + Returns 0 if successful, or BE_ALLOC if cannot alloc the memory. + */ +int B_MemoryPoolAlloc (memoryPool, data, size) +B_MemoryPool *memoryPool; +POINTER *data; +unsigned int size; +{ + if ((*data = T_malloc (size)) == NULL_PTR) + return (BE_ALLOC); + return (B_MemoryPoolAdoptData (memoryPool, data, size)); +} + +/* Use alloc to allocate the newData of length size and T_memcpy data into it. + On any error return, NULL_PTR is returned for the newData. + Returns 0 if successful or BE_ALLOC if cannot alloc the memory. + */ +int B_MemoryPoolAllocAndCopy (memoryPool, newData, data, size) +B_MemoryPool *memoryPool; +POINTER *newData; +POINTER data; +unsigned int size; +{ + int status; + + if ((status = B_MemoryPoolAlloc (memoryPool, newData, size)) != 0) + return (status); + + T_memcpy (*newData, data, size); + return (0); +} + +/* Put the given data on the memory pool's alloced list. + The size of the alloced data buffer must be passed in so that it can + be zeroized when the object is reset (Pass in a size of zero if + the buffer does not need to be zeroized.) + The data is passed by reference, so that if there is an error, + the data is zeroized and freed, and the pointer to the data is set + to NULL_PTR. + This routine should be used with caution - it is meant be called + immediately after an alloc. + No check is made as to whether the data is already on the memory pool's + alloced list (which would be a problem since it will get freed twice). + Returns 0 if successful or BE_ALLOC if cannot expand the alloced list. + */ +int B_MemoryPoolAdoptData (memoryPool, data, size) +B_MemoryPool *memoryPool; +POINTER *data; +unsigned int size; +{ + int status; + + if ((status = B_MemoryPoolAdoptHelper(memoryPool, *data, size, NULL)) != 0) { + T_memset (*data, 0, size); + T_free (*data); + *data = NULL_PTR; + return (status); + } + + return (0); +} + +/* Put the given object on the memory pool's alloced list. + The size of the alloced object must be passed in so that it can + be zeroized when the object is reset (Pass in a size of zero if + the buffer does not need to be zeroized, especially if it + is an object and not a data buffer.) + The object is not passed by reference. If there is an error, + the calling routine should clean up the object, such as zeroizing + and freeing. + No check is made as to whether the object is already on the memory pool's + alloced list (which would be a problem since it will get freed twice). + Returns 0 if successful or BE_ALLOC if cannot expand the alloced list. + */ +int B_MemoryPoolAdoptHelper (memoryPool, object, size, DeleteFunction) +B_MemoryPool *memoryPool; +POINTER object; +unsigned int size; +B_MEMORY_POOL_DELETE_FUNCTION DeleteFunction; +{ + POINTER newList; + unsigned int newMaxCount; + + if (memoryPool->z.allocedCount + 1 > memoryPool->z.maxAllocedCount) { + /* Make extra room on the alloced list. + */ + newMaxCount = memoryPool->z.allocedCount + ALLOCED_LIST_SLACK; + if ((newList = T_malloc (newMaxCount * sizeof (B_ALLOCED_DATA))) + == NULL_PTR) + /* alloc errorm so caller should clean up the object it passed. */ + return (BE_ALLOC); + + /* move in new list and free old list */ + T_memcpy + (newList, (POINTER)memoryPool->z.allocedList, + memoryPool->z.allocedCount * sizeof (B_ALLOCED_DATA)); + T_free ((POINTER)memoryPool->z.allocedList); + memoryPool->z.allocedList = (B_ALLOCED_DATA *)newList; + memoryPool->z.maxAllocedCount = newMaxCount; + } + + /* Put object on alloced list and increment count. + */ + memoryPool->z.allocedList[memoryPool->z.allocedCount].object = object; + memoryPool->z.allocedList[memoryPool->z.allocedCount].size = size; + memoryPool->z.allocedList[memoryPool->z.allocedCount++].DeleteFunction = + DeleteFunction; + return (0); +} + +/* 'data' points to the pointer to realloc and also is used to + return the realloced memory. + If data points to NULL_PTR, behaves like B_MemoryPoolAlloc. + Find 'data' on the allocedList and realloc it to the given size, + replacing the entry on the alloced list with the new memory. + If it is not on the allocedList, the adopt the reallocated memory. + If the buffer must be moved during the realloc, the old buffer is not + zeroized (unless T_realloc does the zeroizing). + This assumes that the (POINTER *)data is not (POINTER *)NULL_PTR. + This assumes there is no DesroyFunction for this entry. That is, + you should not try to resize an object. + On any error return, NULL_PTR is returned for the data. + Returns 0 if successful or BE_ALLOC if cannot alloc the memory. + */ +int B_MemoryPoolRealloc (memoryPool, data, size) +B_MemoryPool *memoryPool; +POINTER *data; +unsigned int size; +{ + B_ALLOCED_DATA *allocedData; + + allocedData = B_MemoryPoolFindAllocedObject (memoryPool, *data); + + if ((*data = T_realloc (*data, size)) == NULL_PTR) { + if (allocedData != (B_ALLOCED_DATA *)NULL_PTR) + /* Could not reallocate, so nullify this entry. */ + allocedData->object = NULL_PTR; + + return (BE_ALLOC); + } + + /* Realloc was successful. + */ + if (allocedData == (B_ALLOCED_DATA *)NULL_PTR) + /* The data was not in the memory pool to start with, so adopt it. + Note that this also happens when the data is initially NULL_PTR. */ + return (B_MemoryPoolAdoptData (memoryPool, data, size)); + + /* Replace the entry on the alloced list with the new memory. + */ + allocedData->object = *data; + allocedData->size = size; + return (0); +} + +/* Find the object in the alloced list, call the DeleteFunction if + there is one, zeroize it and free it, nullifying that alloced list entry. + The object to be freed is passed by pointer and is set to NULL_PTR to + enforce the fact that the address no longer points to valid memory. + This assumes that the (POINTER *)data is not (POINTER *)NULL_PTR. + If the address is not found on the alloced list, only set the address + to NULL_PTR. + */ +void B_MemoryPoolFree (memoryPool, object) +B_MemoryPool *memoryPool; +POINTER *object; +{ + B_ALLOCED_DATA *allocedData; + + if ((allocedData = B_MemoryPoolFindAllocedObject (memoryPool, *object)) + != (B_ALLOCED_DATA *)NULL_PTR) { + if (allocedData->DeleteFunction != NULL) + /* There is a destroy function, so call. */ + (*allocedData->DeleteFunction) (allocedData->object); + else { + T_memset (*object, 0, allocedData->size); + T_free (*object); + } + + /* Set this entry to NULL_PTR so that reset will not process it. */ + allocedData->object = NULL_PTR; + } + + *object = NULL_PTR; +} + +/* Return a pointer to the alloced object entry in the memoryPool. + Return (ALLOCED_DATA *)NULL_PTR if object is NULL_PTR or object is not + in the memoryPool. + */ +B_ALLOCED_DATA *B_MemoryPoolFindAllocedObject (memoryPool, object) +B_MemoryPool *memoryPool; +POINTER object; +{ + B_ALLOCED_DATA *allocedData; + unsigned int i; + + if (object == NULL_PTR) + return ((B_ALLOCED_DATA *)NULL_PTR); + + for (i = memoryPool->z.allocedCount, + allocedData = memoryPool->z.allocedList; + i-- > 0; + ++allocedData) { + if (allocedData->object == object) + return (allocedData); + } + + /* data not found. */ + return ((B_ALLOCED_DATA *)NULL_PTR); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/bmempool.h b/usr/src/lib/libresolv2/common/dnssafe/bmempool.h new file mode 100644 index 0000000000..923a5f6967 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bmempool.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BMEMPOOL_H_ +#define _BMEMPOOL_H_ 1 + +typedef void (*B_MEMORY_POOL_DELETE_FUNCTION) PROTO_LIST ((POINTER)); + +typedef struct { + POINTER object; + unsigned int size; + B_MEMORY_POOL_DELETE_FUNCTION DeleteFunction; +} B_ALLOCED_DATA; + +typedef struct { + struct { + unsigned int allocedCount; + unsigned int maxAllocedCount; /* Size of the actuall allocated list */ + B_ALLOCED_DATA *allocedList; + /* POINTER reserved; */ + } z; /* z gives the members that are zeroized by the constructor */ +} B_MemoryPool; + +void B_MemoryPoolConstructor PROTO_LIST ((B_MemoryPool *)); +void B_MemoryPoolDestructor PROTO_LIST ((B_MemoryPool *)); + +void B_MemoryPoolReset PROTO_LIST ((B_MemoryPool *)); +int B_MemoryPoolAlloc PROTO_LIST ((B_MemoryPool *, POINTER *, unsigned int)); +int B_MemoryPoolAllocAndCopy PROTO_LIST + ((B_MemoryPool *, POINTER *, POINTER, unsigned int)); +int B_MemoryPoolAdoptData PROTO_LIST + ((B_MemoryPool *, POINTER *, unsigned int)); +int B_MemoryPoolAdoptObject PROTO_LIST + ((B_MemoryPool *, POINTER *, B_MEMORY_POOL_DELETE_FUNCTION)); +int B_MemoryPoolRealloc PROTO_LIST ((B_MemoryPool *, POINTER *, unsigned int)); +int B_MemoryPoolSafeRealloc PROTO_LIST + ((B_MemoryPool *, POINTER *, unsigned int)); +void B_MemoryPoolFree PROTO_LIST ((B_MemoryPool *, POINTER *)); +void B_MemoryPoolResetExceptObject PROTO_LIST ((B_MemoryPool *, POINTER)); + +/* These are "private member functions ". + */ +B_ALLOCED_DATA *B_MemoryPoolFindAllocedObject PROTO_LIST + ((B_MemoryPool *, POINTER)); +int B_MemoryPoolAdoptHelper PROTO_LIST + ((B_MemoryPool *, POINTER, unsigned int, B_MEMORY_POOL_DELETE_FUNCTION)); + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/bsafe2.h b/usr/src/lib/libresolv2/common/dnssafe/bsafe2.h new file mode 100644 index 0000000000..1bae822a8a --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/bsafe2.h @@ -0,0 +1,201 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BSAFE_H_ +#define _BSAFE_H_ 1 + +#ifndef T_CALL +#define T_CALL +#endif + +#include "atypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BE_ALGORITHM_ALREADY_SET 0x0200 +#define BE_ALGORITHM_INFO 0x0201 +#define BE_ALGORITHM_NOT_INITIALIZED 0x0202 +#define BE_ALGORITHM_NOT_SET 0x0203 +#define BE_ALGORITHM_OBJ 0x0204 +#define BE_ALG_OPERATION_UNKNOWN 0x0205 +#define BE_ALLOC 0x0206 +#define BE_CANCEL 0x0207 +#define BE_DATA 0x0208 +#define BE_EXPONENT_EVEN 0x0209 +#define BE_EXPONENT_LEN 0x020a +#define BE_HARDWARE 0x020b +#define BE_INPUT_DATA 0x020c +#define BE_INPUT_LEN 0x020d +#define BE_KEY_ALREADY_SET 0x020e +#define BE_KEY_INFO 0x020f +#define BE_KEY_LEN 0x0210 +#define BE_KEY_NOT_SET 0x0211 +#define BE_KEY_OBJ 0x0212 +#define BE_KEY_OPERATION_UNKNOWN 0x0213 +#define BE_MEMORY_OBJ 0x0214 +#define BE_MODULUS_LEN 0x0215 +#define BE_NOT_INITIALIZED 0x0216 +#define BE_NOT_SUPPORTED 0x0217 +#define BE_OUTPUT_LEN 0x0218 +#define BE_OVER_32K 0x0219 +#define BE_RANDOM_NOT_INITIALIZED 0x021a +#define BE_RANDOM_OBJ 0x021b +#define BE_SIGNATURE 0x021c +#define BE_WRONG_ALGORITHM_INFO 0x021d +#define BE_WRONG_KEY_INFO 0x021e +#define BE_INPUT_COUNT 0x021f +#define BE_OUTPUT_COUNT 0x0220 +#define BE_METHOD_NOT_IN_CHOOSER 0x221 + +typedef POINTER B_KEY_OBJ; +typedef POINTER B_ALGORITHM_OBJ; + +typedef int (T_CALL *B_INFO_TYPE) PROTO_LIST ((POINTER *)); + +typedef struct B_ALGORITHM_METHOD B_ALGORITHM_METHOD; +typedef B_ALGORITHM_METHOD **B_ALGORITHM_CHOOSER; + +/* Routines supplied by the implementor. + */ +void T_CALL T_memset PROTO_LIST ((POINTER, int, unsigned int)); +void T_CALL T_memcpy PROTO_LIST ((POINTER, CPOINTER, unsigned int)); +void T_CALL T_memmove PROTO_LIST ((POINTER, POINTER, unsigned int)); +int T_CALL T_memcmp PROTO_LIST ((CPOINTER, CPOINTER, unsigned int)); +POINTER T_CALL T_malloc PROTO_LIST ((unsigned int)); +POINTER T_CALL T_realloc PROTO_LIST ((POINTER, unsigned int)); +void T_CALL T_free PROTO_LIST ((POINTER)); + +/* The key object. + */ +int T_CALL B_CreateKeyObject PROTO_LIST ((B_KEY_OBJ *)); +void T_CALL B_DestroyKeyObject PROTO_LIST ((B_KEY_OBJ *)); +int T_CALL B_SetKeyInfo PROTO_LIST ((B_KEY_OBJ, B_INFO_TYPE, POINTER)); +int T_CALL B_GetKeyInfo PROTO_LIST ((POINTER *, B_KEY_OBJ, B_INFO_TYPE)); + +/* The algorithm object. + */ +int T_CALL B_CreateAlgorithmObject PROTO_LIST ((B_ALGORITHM_OBJ *)); +void T_CALL B_DestroyAlgorithmObject PROTO_LIST ((B_ALGORITHM_OBJ *)); +int T_CALL B_SetAlgorithmInfo PROTO_LIST + ((B_ALGORITHM_OBJ, B_INFO_TYPE, POINTER)); +int T_CALL B_GetAlgorithmInfo PROTO_LIST + ((POINTER *, B_ALGORITHM_OBJ, B_INFO_TYPE)); + +unsigned int B_IntegerBits PROTO_LIST ((unsigned char *, unsigned int)); + +/* Algorithm operations. + */ +int T_CALL B_RandomInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_RandomUpdate PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int T_CALL B_GenerateRandomBytes PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int, A_SURRENDER_CTX *)); + +int T_CALL B_DigestInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_KEY_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_DigestUpdate PROTO_LIST + ((B_ALGORITHM_OBJ, const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int T_CALL B_DigestFinal PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + A_SURRENDER_CTX *)); + +int T_CALL B_EncryptInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_KEY_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_EncryptUpdate PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + unsigned char *, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); +int T_CALL B_EncryptFinal PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); + +int T_CALL B_DecryptInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_KEY_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_DecryptUpdate PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); +int T_CALL B_DecryptFinal PROTO_LIST + ((B_ALGORITHM_OBJ, unsigned char *, unsigned int *, unsigned int, + B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); + + + +int T_CALL B_GenerateInit PROTO_LIST + ((B_ALGORITHM_OBJ, B_ALGORITHM_CHOOSER, A_SURRENDER_CTX *)); +int T_CALL B_GenerateKeypair PROTO_LIST + ((B_ALGORITHM_OBJ, B_KEY_OBJ, B_KEY_OBJ, B_ALGORITHM_OBJ, + A_SURRENDER_CTX *)); +int T_CALL B_GenerateParameters PROTO_LIST + ((B_ALGORITHM_OBJ, B_ALGORITHM_OBJ, B_ALGORITHM_OBJ, A_SURRENDER_CTX *)); + + +/* Information for password-based encryption (PBE) algorithms. + */ +typedef struct { + unsigned char *salt; /* salt value */ + unsigned int iterationCount; /* iteration count */ +} B_PBE_PARAMS; + +/* Information for MAC algorithm. + */ +typedef struct { + unsigned int macLen; /* length of MAC value */ +} B_MAC_PARAMS; + + +/* Information for BSAFE 1.x compatible encryption algorithms. + */ + + +typedef struct { + unsigned int threshold; /* share threshold */ +} B_SECRET_SHARING_PARAMS; + +/* Key Info Types. + */ +int T_CALL KI_8Byte PROTO_LIST ((POINTER *)); +int T_CALL KI_Item PROTO_LIST ((POINTER *)); +int T_CALL KI_PKCS_RSAPrivate PROTO_LIST ((POINTER *)); +int T_CALL KI_RSAPublic PROTO_LIST ((POINTER *)); +int T_CALL KI_RSA_CRT PROTO_LIST ((POINTER *)); + +/* Algorithm Info Types. + */ +int T_CALL AI_MD5 PROTO_LIST ((POINTER *)); +int T_CALL AI_MD5Random PROTO_LIST ((POINTER *)); +int T_CALL AI_PKCS_RSAPrivate PROTO_LIST ((POINTER *)); +int T_CALL AI_PKCS_RSAPublic PROTO_LIST ((POINTER *)); +int T_CALL AI_RSAKeyGen PROTO_LIST ((POINTER *)); +int T_CALL AI_RSAPrivate PROTO_LIST ((POINTER *)); +int T_CALL AI_RSAPublic PROTO_LIST ((POINTER *)); + + +/* Algorithm methods for use int the algorithm chooser. + */ +extern B_ALGORITHM_METHOD T_CALL AM_MD5; +extern B_ALGORITHM_METHOD T_CALL AM_MD5_RANDOM; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_CRT_DECRYPT; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_CRT_ENCRYPT; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_DECRYPT; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_ENCRYPT; +extern B_ALGORITHM_METHOD T_CALL AM_RSA_KEY_GEN; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/btypechk.h b/usr/src/lib/libresolv2/common/dnssafe/btypechk.h new file mode 100644 index 0000000000..328e5008e1 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/btypechk.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _BTYPECHK_H_ +#define _BTYPECHK_H_ 1 + +struct B_TypeCheck; + +typedef void (*B_TYPE_CHECK_DESTRUCTOR) PROTO_LIST ((struct B_TypeCheck *)); + +typedef struct B_TypeCheck { + B_TYPE_CHECK_DESTRUCTOR _Destructor; +} B_TypeCheck; + +#define B_TYPE_CHECK_Constructor(typeCheck, Destructor)\ + (typeCheck)->_Destructor = (Destructor) +#define B_TYPE_CHECK_Destructor(typeCheck)\ + (*(typeCheck)->_Destructor) (typeCheck) + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/cantobig.c b/usr/src/lib/libresolv2/common/dnssafe/cantobig.c new file mode 100644 index 0000000000..b41c3d758a --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/cantobig.c @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bigmath.h" +#include "port_after.h" + +/* CanonicalToBig () copies a byte vector into a word vector while REVERSING + the order of significance. The byte vector is input MSByte first while + the word vector is written out LSWord first. It also adds a leading zero + sign bit if necessary. + Returns 0, AE_DATA. + */ +int CanonicalToBig (wordPointer, wordCount, bytePointer, numBytes) +UINT2 *wordPointer; +unsigned int wordCount; +const unsigned char *bytePointer; +unsigned int numBytes; +{ + unsigned int copyCount; + + if (A_IntegerBits (bytePointer, numBytes) / 16 + 1 > wordCount) + return (AE_DATA); + + /* start at end of byte vector */ + bytePointer += numBytes-1; + + /* copy as much as possible */ + copyCount = (wordCount < numBytes / 2) ? wordCount : numBytes / 2; + wordCount -= copyCount; + numBytes -= 2 * copyCount; + while (copyCount--) { + /* Copy two bytes.*/ + *wordPointer++ = (UINT2)*bytePointer + (*(bytePointer - 1) << 8); + bytePointer -= 2; + } + + if (wordCount && numBytes & 1) { + /* If the number of input bytes was odd. Copy one last byte.*/ + *wordPointer++ = (UINT2)*bytePointer--; + wordCount--; + numBytes--; + } + + /* zero fill remainder of word vector */ + while (wordCount--) + *wordPointer++ = 0; + + return (0); +} + + diff --git a/usr/src/lib/libresolv2/common/dnssafe/crt2.c b/usr/src/lib/libresolv2/common/dnssafe/crt2.c new file mode 100644 index 0000000000..0428183591 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/crt2.c @@ -0,0 +1,237 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "crt2.h" +#include "bigmath.h" +#include "port_after.h" + +/* RSA encryption/decryption with Chinese Remainder Theorem. + */ + +#define GENERATE_BREAK(type) { \ + status = type; \ + break; \ + } + +static int RSA_CRT2 PROTO_LIST + ((A_RSA_CRT2_CTX *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, A_SURRENDER_CTX *)); + +int A_RSA_CRT2Init (context, key) +A_RSA_CRT2_CTX *context; +A_RSA_CRT_KEY *key; +{ + if (A_IntegerBits (key->modulus.data, key->modulus.len) + > MAX_RSA_MODULUS_BITS) + /* Key len is too big to handle. */ + return (AE_MODULUS_LEN); + + /* Set the block update blockLen to be big enough to hold the modulus. + */ + context->blockLen = + BITS_TO_LEN (A_IntegerBits (key->modulus.data, key->modulus.len)); + + context->inputLen = 0; + + /* convert first prime to bignum format */ + if (CanonicalToBig + (context->primeP, MAX_RSA_PRIME_WORDS, key->prime[0].data, + key->prime[0].len)) + return (AE_KEY_INFO); + + /* compute significant length of first prime */ + context->primeWords = BITS_TO_WORDS + (BigLen (context->primeP, MAX_RSA_PRIME_WORDS)); + + /* convert other private key parameters to bignum format */ + if (CanonicalToBig + (context->primeQ, context->primeWords, key->prime[1].data, + key->prime[1].len) || + CanonicalToBig + (context->exponentP, context->primeWords, + key->primeExponent[0].data, key->primeExponent[0].len) || + CanonicalToBig + (context->exponentQ, context->primeWords, + key->primeExponent[1].data, key->primeExponent[1].len) || + CanonicalToBig + (context->coefficient, context->primeWords, + key->coefficient.data, key->coefficient.len)) + return (AE_KEY_INFO); + + /* convert modulus to bignum format */ + if (CanonicalToBig + (context->modulus, 2 * context->primeWords, + key->modulus.data, key->modulus.len)) + return (AE_KEY_INFO); + + return (0); +} + +int A_RSA_CRT2Update + (context, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + surrenderContext) +A_RSA_CRT2_CTX *context; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int partialLen, localPartOutLen; + + /* Initialize partOutLen to zero. */ + *partOutLen = 0; + + if (context->inputLen + partInLen < context->blockLen) { + /* Not enough to encrypt - just accumulate. + */ + T_memcpy + ((POINTER)(context->input + context->inputLen), (CPOINTER)partIn, + partInLen); + context->inputLen += partInLen; + return (0); + } + + if (context->inputLen > 0) { + /* Need to accumulate the rest of the block bytes into the input and + encrypt from there (otherwise it's OK to encrypt straight from + the partIn). + */ + partialLen = context->blockLen - context->inputLen; + T_memcpy + ((POINTER)(context->input + context->inputLen), (CPOINTER)partIn, + partialLen); + partIn += partialLen; + partInLen -= partialLen; + + if ((status = RSA_CRT2 + (context, partOut, &localPartOutLen, maxPartOutLen, context->input, + surrenderContext)) != 0) + return (status); + (*partOutLen) += localPartOutLen; + partOut += localPartOutLen; + maxPartOutLen -= localPartOutLen; + } + + /* Encrypt as many blocks of input as provided. + */ + while (partInLen >= context->blockLen) { + if ((status = RSA_CRT2 + (context, partOut, &localPartOutLen, maxPartOutLen, partIn, + surrenderContext)) != 0) + return (status); + + partIn += context->blockLen; + partInLen -= context->blockLen; + (*partOutLen) += localPartOutLen; + partOut += localPartOutLen; + maxPartOutLen -= localPartOutLen; + } + + /* Copy remaining input bytes to the context's input buffer. + */ + T_memcpy + ((POINTER)context->input, partIn, partInLen); + context->inputLen = partInLen; + return (0); +} + +int A_RSA_CRT2Final (context) +A_RSA_CRT2_CTX *context; +{ + if (context->inputLen != 0) + return (AE_INPUT_LEN); + + /* Restart context to accumulate a new block. + */ + context->inputLen = 0; + return (0); +} + +/* Assume input length is context->blockLen. + */ +static int RSA_CRT2 + (context, output, outputLen, maxOutputLen, input, surrenderContext) +A_RSA_CRT2_CTX *context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +const unsigned char *input; +A_SURRENDER_CTX *surrenderContext; +{ + struct ModExpCRTFrame { + UINT2 bigInBuf[2 * MAX_RSA_PRIME_WORDS], + bigOutBuf[2 * MAX_RSA_PRIME_WORDS]; + } *frame = (struct ModExpCRTFrame *)NULL_PTR; +#if !USE_ALLOCED_FRAME + struct ModExpCRTFrame stackFrame; +#endif + int status; + + status = 0; + do { + if ((*outputLen = context->blockLen) > maxOutputLen) + return (AE_OUTPUT_LEN); + +#if USE_ALLOCED_FRAME + if ((frame = (struct ModExpCRTFrame *)T_malloc (sizeof (*frame))) + == (struct ModExpCRTFrame *)NULL_PTR) { + status = AE_ALLOC; + break; + } +#else + /* Just use the buffers allocated on the stack. */ + frame = &stackFrame; +#endif + + /* Convert input to bignum representation. + This won't return AE_DATA since input length was checked at Update. + */ + CanonicalToBig + (frame->bigInBuf, 2 * context->primeWords, input, context->blockLen); + + /* Check for overflow. */ + if (BigCmp + (frame->bigInBuf, context->modulus, 2 * context->primeWords) >= 0) + GENERATE_BREAK (AE_INPUT_DATA); + + /* Chinese remainder exponentiation. */ + if ((status = BigUnexp + (frame->bigOutBuf, frame->bigInBuf, context->primeP, context->primeQ, + context->exponentP, context->exponentQ, context->coefficient, + context->primeWords, surrenderContext)) != 0) + break; + + /* Convert output to canonical representation. + This won't return AE_DATA since outputLen was set above. + */ + BigToCanonical + (output, *outputLen, frame->bigOutBuf, 2 * context->primeWords); + } while (0); + + if (frame != (struct ModExpCRTFrame *)NULL_PTR) { + T_memset ((POINTER)frame, 0, sizeof (*frame)); +#if USE_ALLOCED_FRAME + T_free ((POINTER)frame); +#endif + } + return (status); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/crt2.h b/usr/src/lib/libresolv2/common/dnssafe/crt2.h new file mode 100644 index 0000000000..c26d7bdacb --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/crt2.h @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _RSA_H_ +#define _RSA_H_ 1 + +#include "bigmaxes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note, these are only valid after a call to A_RSA_CRT2Init. + */ +#define A_RSA_CRT2_BLOCK_LEN(context) ((context)->blockLen) +#define A_RSA_CRT2_MAX_OUTPUT_LEN(context, inputLen)\ + (inputLen) + (((inputLen) % (context)->blockLen) ?\ + (context)->blockLen - ((inputLen) % (context)->blockLen) : 0) + +typedef struct { + unsigned int blockLen; /* total size of the block to be computed */ + unsigned char input[MAX_RSA_MODULUS_LEN]; + unsigned int inputLen; + unsigned int primeWords; + UINT2 modulus[2 * MAX_RSA_PRIME_WORDS]; + UINT2 primeP[MAX_RSA_PRIME_WORDS]; + UINT2 primeQ[MAX_RSA_PRIME_WORDS]; + UINT2 exponentP[MAX_RSA_PRIME_WORDS]; + UINT2 exponentQ[MAX_RSA_PRIME_WORDS]; + UINT2 coefficient[MAX_RSA_PRIME_WORDS]; +} A_RSA_CRT2_CTX; + +int A_RSA_CRT2Init PROTO_LIST ((A_RSA_CRT2_CTX *, A_RSA_CRT_KEY *)); +int A_RSA_CRT2Update PROTO_LIST + ((A_RSA_CRT2_CTX *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int A_RSA_CRT2Final PROTO_LIST ((A_RSA_CRT2_CTX *)); +void A_RSA_CRT2GetMaxOutputLen PROTO_LIST + ((A_RSA_CRT2_CTX *, unsigned int *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/digest.c b/usr/src/lib/libresolv2/common/dnssafe/digest.c new file mode 100644 index 0000000000..4394f579ec --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/digest.c @@ -0,0 +1,76 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "keyobj.h" +#include "algobj.h" +#include "port_after.h" + +int B_DigestInit + (algorithmObject, keyObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_KEY_OBJ keyObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)keyObject)) != 0) + return (status); + + return (B_AlgorithmDigestInit + (&THE_ALG_WRAP->algorithm, &((KeyWrap *)keyObject)->key, + algorithmChooser, surrenderContext)); +} + +int B_DigestUpdate (algorithmObject, partIn, partInLen, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + return (B_AlgorithmDigestUpdate + (&THE_ALG_WRAP->algorithm, partIn, partInLen, surrenderContext)); +} + +int B_DigestFinal + (algorithmObject, digest, digestLen, maxDigestLen, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *digest; +unsigned int *digestLen; +unsigned int maxDigestLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + return (B_AlgorithmDigestFinal + (&THE_ALG_WRAP->algorithm, digest, digestLen, maxDigestLen, + surrenderContext)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/digrand.c b/usr/src/lib/libresolv2/common/dnssafe/digrand.c new file mode 100644 index 0000000000..62ba5ba337 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/digrand.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "digrand.h" +#include "port_after.h" + +/* Calling routine must initialize the digest algorithm and set + digestRandom->vTable. + digestLen is the length of the output of the digest algorithm (i.e. 16). + state must point to an unsigned char * array of 3 * digestLen. + */ +void A_DigestRandomInit (digestRandom, digestLen, state) +A_DigestRandom *digestRandom; +unsigned int digestLen; +unsigned char *state; +{ + digestRandom->_state = state; + digestRandom->_output = state + digestLen; + digestRandom->_digest = digestRandom->_output + digestLen; + + digestRandom->_outputAvailable = 0; + digestRandom->_digestLen = digestLen; + + T_memset ((POINTER)digestRandom->_state, 0, digestLen); +} + +void A_DigestRandomUpdate (digestRandom, input, inputLen) +A_DigestRandom *digestRandom; +unsigned char *input; +unsigned int inputLen; +{ + unsigned int i, j, x; + + (*digestRandom->vTable->DigestUpdate) (digestRandom, input, inputLen); + (*digestRandom->vTable->DigestFinal) (digestRandom, digestRandom->_digest); + + /* add digest to state */ + x = 0; + for (i = 0; i < digestRandom->_digestLen; i++) { + j = digestRandom->_digestLen-1-i; + x += digestRandom->_state[j] + digestRandom->_digest[j]; + digestRandom->_state[j] = (unsigned char)x; + x >>= 8; + } +} + +void A_DigestRandomGenerateBytes (digestRandom, output, outputLen) +A_DigestRandom *digestRandom; +unsigned char *output; +unsigned int outputLen; +{ + unsigned int available, i; + + available = digestRandom->_outputAvailable; + + while (outputLen > available) { + T_memcpy + ((POINTER)output, + (POINTER)&digestRandom->_output[digestRandom->_digestLen-available], + available); + output += available; + outputLen -= available; + + /* generate new output */ + (*digestRandom->vTable->DigestUpdate) + (digestRandom, digestRandom->_state, digestRandom->_digestLen); + (*digestRandom->vTable->DigestFinal) (digestRandom, digestRandom->_output); + available = digestRandom->_digestLen; + + /* increment state */ + for (i = 0; i < digestRandom->_digestLen; i++) + if (digestRandom->_state[digestRandom->_digestLen-1-i]++) + break; + } + + T_memcpy + ((POINTER)output, + (POINTER)&digestRandom->_output[digestRandom->_digestLen-available], + outputLen); + digestRandom->_outputAvailable = available - outputLen; +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/digrand.h b/usr/src/lib/libresolv2/common/dnssafe/digrand.h new file mode 100644 index 0000000000..f93ea1d63a --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/digrand.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _DIGRAND_H_ +#define _DIGRAND_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Use the THIS_DIGEST_RANDOM macro to define the type of object in the + virtual function prototype. It defaults to the most base class, but + derived modules may define the macro to a more derived class before + including this header file. + */ +#ifndef THIS_DIGEST_RANDOM +#define THIS_DIGEST_RANDOM struct A_DigestRandom +#endif + +struct A_DigestRandom; + +typedef struct { + void (*DigestUpdate) PROTO_LIST + ((THIS_DIGEST_RANDOM *, unsigned char *, unsigned int)); + void (*DigestFinal) PROTO_LIST ((THIS_DIGEST_RANDOM *, unsigned char *)); +} A_DigestRandomVTable; + +typedef struct A_DigestRandom { + unsigned char *_state; /* input to digest */ + unsigned char *_output; /* current output of digest */ + unsigned int _outputAvailable; + unsigned char *_digest; + unsigned int _digestLen; + A_DigestRandomVTable *vTable; +} A_DigestRandom; + +void A_DigestRandomInit PROTO_LIST + ((A_DigestRandom *, unsigned int, unsigned char *)); +void A_DigestRandomUpdate PROTO_LIST + ((A_DigestRandom *, unsigned char *, unsigned int)); +void A_DigestRandomGenerateBytes PROTO_LIST + ((A_DigestRandom *, unsigned char *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/encrypt.c b/usr/src/lib/libresolv2/common/dnssafe/encrypt.c new file mode 100644 index 0000000000..71e34ea714 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/encrypt.c @@ -0,0 +1,156 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "keyobj.h" +#include "algobj.h" +#include "port_after.h" + +int B_EncryptInit + (algorithmObject, keyObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_KEY_OBJ keyObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)keyObject)) != 0) + return (status); + + return (B_AlgorithmEncryptInit + (&THE_ALG_WRAP->algorithm, &((KeyWrap *)keyObject)->key, + algorithmChooser, surrenderContext)); +} + +int B_EncryptUpdate + (algorithmObject, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +unsigned char *partIn; +unsigned int partInLen; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmEncryptUpdate + (&THE_ALG_WRAP->algorithm, partOut, partOutLen, maxPartOutLen, + partIn, partInLen, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + +int B_EncryptFinal + (algorithmObject, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmEncryptFinal + (&THE_ALG_WRAP->algorithm, partOut, partOutLen, maxPartOutLen, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + +int B_DecryptInit + (algorithmObject, keyObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_KEY_OBJ keyObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)keyObject)) != 0) + return (status); + + return (B_AlgorithmDecryptInit + (&THE_ALG_WRAP->algorithm, &((KeyWrap *)keyObject)->key, + algorithmChooser, surrenderContext)); +} + +int B_DecryptUpdate + (algorithmObject, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + randomAlgorithm, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmDecryptUpdate + (&THE_ALG_WRAP->algorithm, partOut, partOutLen, maxPartOutLen, + partIn, partInLen, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + +int B_DecryptFinal + (algorithmObject, partOut, partOutLen, maxPartOutLen, randomAlgorithm, + surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmDecryptFinal + (&THE_ALG_WRAP->algorithm, partOut, partOutLen, maxPartOutLen, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/generate.c b/usr/src/lib/libresolv2/common/dnssafe/generate.c new file mode 100644 index 0000000000..f892ad60e9 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/generate.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "keyobj.h" +#include "algobj.h" +#include "port_after.h" + +int B_GenerateInit (algorithmObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + + return (B_AlgorithmGenerateInit + (&THE_ALG_WRAP->algorithm, algorithmChooser, surrenderContext)); +} + +int B_GenerateKeypair + (algorithmObject, publicKey, privateKey, randomAlgorithm, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_KEY_OBJ publicKey; +B_KEY_OBJ privateKey; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)publicKey)) != 0) + return (status); + if ((status = KeyWrapCheck ((KeyWrap *)privateKey)) != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmGenerateKeypair + (&THE_ALG_WRAP->algorithm, &((KeyWrap *)publicKey)->key, + &((KeyWrap *)privateKey)->key, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + +int B_GenerateParameters + (algorithmObject, resultAlgorithmObject, randomAlgorithm, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_ALGORITHM_OBJ resultAlgorithmObject; +B_ALGORITHM_OBJ randomAlgorithm; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + + if ((status = AlgorithmWrapCheck (THE_ALG_WRAP)) != 0) + return (status); + if ((status = AlgorithmWrapCheck ((AlgorithmWrap *)resultAlgorithmObject)) + != 0) + return (status); + if ((status = RandomAlgorithmCheck (randomAlgorithm)) != 0) + return (status); + + return (B_AlgorithmGenerateParameters + (&THE_ALG_WRAP->algorithm, + &((AlgorithmWrap *)resultAlgorithmObject)->algorithm, + &((AlgorithmWrap *)randomAlgorithm)->algorithm, surrenderContext)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/global.h b/usr/src/lib/libresolv2/common/dnssafe/global.h new file mode 100644 index 0000000000..811ba42cc4 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/global.h @@ -0,0 +1,70 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _GLOBAL_H_ +#define _GLOBAL_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. + The following makes PROTOTYPES default to 1 if it has not already been + defined as 0 with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 1 +#endif + +#include <sys/types.h> +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +# include <sys/bitypes.h> +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; +typedef const unsigned char *CPOINTER; + +/* UINT2 defines a two byte word */ +typedef u_int16_t UINT2; + +/* UINT4 defines a four byte word */ +typedef u_int32_t UINT4; + +#ifndef NULL_PTR +#define NULL_PTR ((POINTER)0) +#endif + +#ifndef UNUSED_ARG +#define UNUSED_ARG(x) x = *(&x); +#endif + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. + If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end _GLOBAL_H_ */ diff --git a/usr/src/lib/libresolv2/common/dnssafe/intbits.c b/usr/src/lib/libresolv2/common/dnssafe/intbits.c new file mode 100644 index 0000000000..6a213d30ee --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/intbits.c @@ -0,0 +1,41 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "port_after.h" + +/* Return the number of bits in the canonical, positive integer. + IntgerBits (0) = 0. + */ +unsigned int A_IntegerBits (integer, integerLen) +const unsigned char *integer; +unsigned int integerLen; +{ + unsigned char mask, byte; + unsigned int bytes, bits; + + for (bytes = 0; bytes < integerLen && integer[bytes] == 0; bytes++); + if (bytes == integerLen) + return (0); + + /* Get byte to test and increment byte count for final calculation */ + byte = integer[bytes++]; + + /* Get number of bits in most significant byte */ + for (bits = 8, mask = 0x80; (byte & mask) == 0; bits--, mask >>= 1); + return (8 * (integerLen - bytes) + bits); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/intitem.c b/usr/src/lib/libresolv2/common/dnssafe/intitem.c new file mode 100644 index 0000000000..8c8d0ce4aa --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/intitem.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bmempool.h" +#include "intitem.h" +#include "port_after.h" + +/* Copy itemCount ITEMs from source to destination, allocating new + memory in the memoryPool. + Each ITEM is a canonical integer, and is stripped of leading zeros. + Use the list of staticItems as a template. Each of the staticItems + points to the ITEM within the staticStruct, which is a structure + of the same format as destination and source. + Returns 0, BE_ALLOC. + */ +int AllocAndCopyIntegerItems + (destination, source, staticStruct, staticItems, itemCount, memoryPool) +POINTER destination; +POINTER source; +POINTER staticStruct; +ITEM **staticItems; +unsigned int itemCount; +B_MemoryPool *memoryPool; +{ + ITEM sourceItem, *destinationItem; + int status; + unsigned int i, offset; + + for (i = 0; i < itemCount; i++) { + offset = (unsigned int)((char *)staticItems[i] - (char *)staticStruct); + sourceItem = *(ITEM *)((char *)source + offset); + destinationItem = (ITEM *)((char *)destination + offset); + + while (sourceItem.len > 0 && *sourceItem.data == 0) { + sourceItem.len--; + sourceItem.data++; + } + + if ((status = B_MemoryPoolAllocAndCopy + (memoryPool, (POINTER *)&destinationItem->data, + (POINTER)sourceItem.data, destinationItem->len = sourceItem.len)) + != 0) + return (status); + } + + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/intitem.h b/usr/src/lib/libresolv2/common/dnssafe/intitem.h new file mode 100644 index 0000000000..6da83ce8e8 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/intitem.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +int AllocAndCopyIntegerItems PROTO_LIST + ((POINTER, POINTER, POINTER, ITEM **, unsigned int, B_MemoryPool *)); + diff --git a/usr/src/lib/libresolv2/common/dnssafe/keyobj.c b/usr/src/lib/libresolv2/common/dnssafe/keyobj.c new file mode 100644 index 0000000000..9ac577d6de --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/keyobj.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "keyobj.h" +#include "port_after.h" + +#define THE_KEY_WRAP ((KeyWrap *)keyObject) + +static char KEY_TYPE_TAG = 0; + +int B_CreateKeyObject (keyObject) +B_KEY_OBJ *keyObject; +{ + KeyWrap *keyWrap; + + if ((*keyObject = T_malloc (sizeof (*keyWrap))) == NULL_PTR) + return (BE_ALLOC); + + keyWrap = (KeyWrap *)*keyObject; + + /* First construct base class */ + B_KEY_Constructor (&keyWrap->key); + + keyWrap->typeTag = &KEY_TYPE_TAG; + keyWrap->selfCheck = keyWrap; + return (0); +} + +void B_DestroyKeyObject (keyObject) +B_KEY_OBJ *keyObject; +{ + KeyWrap *keyWrap = (KeyWrap *)*keyObject; + + /* Need to explicitly check for NULL_PTR since KeyWrapCheck does not. + */ + if (*keyObject == NULL_PTR) + return; + + if (KeyWrapCheck (keyWrap) == 0) { + /* zeroize self check to invalidate memory. */ + keyWrap->selfCheck = (KeyWrap *)NULL_PTR; + + /* Call base class descructor */ + B_KEY_Destructor (&keyWrap->key); + + T_free ((POINTER)keyWrap); + } + + *keyObject = NULL_PTR; +} + +int B_SetKeyInfo (keyObject, infoType, info) +B_KEY_OBJ keyObject; +B_INFO_TYPE infoType; +POINTER info; +{ + B_KeyInfoType *keyInfoType; + int status; + + if ((status = KeyWrapCheck (THE_KEY_WRAP)) != 0) + return (status); + + /* Get the KeyInfoType from the B_INFO_TYPE, which returns + zero for an AlgorithmInfoType, non-zero for KeyInfoType + */ + if ((*infoType) ((POINTER *)&keyInfoType) == 0) + return (BE_ALG_OPERATION_UNKNOWN); + + return (B_KeySetInfo (&THE_KEY_WRAP->key, keyInfoType, info)); +} + +int B_GetKeyInfo (info, keyObject, infoType) +POINTER *info; +B_KEY_OBJ keyObject; +B_INFO_TYPE infoType; +{ + B_KeyInfoType *keyInfoType; + int status; + + if ((status = KeyWrapCheck (THE_KEY_WRAP)) != 0) + return (status); + + /* Get the KeyInfoType from the B_INFO_TYPE, which returns + zero for an AlgorithmInfoType, non-zero for KeyInfoType + */ + if ((*infoType) ((POINTER *)&keyInfoType) == 0) + return (BE_ALG_OPERATION_UNKNOWN); + + return (B_KeyGetInfo (&THE_KEY_WRAP->key, info, keyInfoType)); +} + +/* Return 0 if this is a valid KeyWrap object, else BE_KEY_OBJ. + If keyWrap is NULL_PTR, return 0 and expect the lower routines + to check for NULL. + */ +int KeyWrapCheck (keyWrap) +KeyWrap *keyWrap; +{ + if (keyWrap == (KeyWrap *)NULL_PTR) + return (0); + + return ((keyWrap->selfCheck == keyWrap && keyWrap->typeTag == &KEY_TYPE_TAG) + ? 0 : BE_KEY_OBJ); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/keyobj.h b/usr/src/lib/libresolv2/common/dnssafe/keyobj.h new file mode 100644 index 0000000000..41ad52e7eb --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/keyobj.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef struct KeyWrap { + B_Key key; + char *typeTag; + struct KeyWrap *selfCheck; +} KeyWrap; + +int KeyWrapCheck PROTO_LIST ((KeyWrap *)); + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ki8byte.c b/usr/src/lib/libresolv2/common/dnssafe/ki8byte.c new file mode 100644 index 0000000000..8e6a069cfc --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ki8byte.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "kiitem.h" +#include "ki8byte.h" +#include "port_after.h" + +int KIT_8ByteAddInfo PROTO_LIST ((B_Key *, POINTER)); +int KIT_8ByteMakeInfo PROTO_LIST ((POINTER *, B_Key *)); + +B_KeyInfoType KIT_8Byte = {KIT_8ByteAddInfo, KIT_8ByteMakeInfo}; + +int KI_8Byte (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KIT_8Byte; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +/* info points to 8 byte key. + Cache as a KITItem and a KIT_8Byte. + */ +int KIT_8ByteAddInfo (key, info) +B_Key *key; +POINTER info; +{ + POINTER newData; + int status; + + /* Copy the 8 byte key. */ + if ((status = B_MemoryPoolAllocAndCopy + (&key->infoCache.memoryPool, &newData, info, 8)) != 0) + return (status); + + /* Cache as a KITItem as well as KIT_8Byte. + */ + if ((status = B_KeyAddItemInfo (key, (unsigned char *)newData, 8)) != 0) + return (status); + return (B_InfoCacheAddInfo (&key->infoCache, (POINTER)&KIT_8Byte, newData)); +} + +int KIT_8ByteMakeInfo (info, key) +POINTER *info; +B_Key *key; +{ + ITEM *item; + int status; + + /* Try to make one from a KI_Item. Since KI_Item doesn't + call KI_8Byte, this should not cause an endless loop. + */ + if ((status = B_KeyGetInfo (key, (POINTER *)&item, &KITItem)) != 0) + return (status); + if (item->len != 8) + return (BE_WRONG_KEY_INFO); + + *(unsigned char **)info = item->data; + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/ki8byte.h b/usr/src/lib/libresolv2/common/dnssafe/ki8byte.h new file mode 100644 index 0000000000..197d3dcbe3 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/ki8byte.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +extern B_KeyInfoType KIT_8Byte; diff --git a/usr/src/lib/libresolv2/common/dnssafe/kifulprv.c b/usr/src/lib/libresolv2/common/dnssafe/kifulprv.c new file mode 100644 index 0000000000..050f115e4a --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kifulprv.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "kifulprv.h" +#include "port_after.h" + +typedef struct { + ITEM modulus; /* modulus */ + ITEM publicExponent; /* exponent for the public key */ + ITEM privateExponent; /* exponent for the private key */ + ITEM prime[2]; /* prime factors */ + ITEM primeExponent[2]; /* exponents for prime factors */ + ITEM coefficient; /* CRT coefficient */ +} FULL_PRIVATE_KEY; + +static int KITFullPrivateKeyAddInfo PROTO_LIST ((B_Key *, POINTER)); + +static B_KeyInfoType KITFullPrivate = + {KITFullPrivateKeyAddInfo, B_KeyInfoTypeMakeError}; + +/* Create a FULL_PRIVATE_KEY value and only copy inthe entries + that are not (ITEM *)NULL_PTR. + primes and primeExponents point to a 2 entry ITEM array. + */ +int CacheFullPrivateKey + (key, modulus, publicExponent, privateExponent, primes, + primeExponents, coefficient) +B_Key *key; +ITEM *modulus; +ITEM *publicExponent; +ITEM *privateExponent; +ITEM *primes; +ITEM *primeExponents; +ITEM *coefficient; +{ + FULL_PRIVATE_KEY *fullKey; + int status; + + /* Allocate memory for FULL_PRIVATE_KEY value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, (POINTER *)&fullKey, + sizeof (FULL_PRIVATE_KEY))) != 0) + return (status); + + /* Pre-zeroize and only copy in values that are not NULL. + */ + T_memset ((POINTER)fullKey, 0, sizeof (*fullKey)); + if (modulus != (ITEM *)NULL_PTR) + fullKey->modulus = *modulus; + if (publicExponent != (ITEM *)NULL_PTR) + fullKey->publicExponent = *publicExponent; + if (privateExponent != (ITEM *)NULL_PTR) + fullKey->privateExponent = *privateExponent; + if (primes != (ITEM *)NULL_PTR) { + fullKey->prime[0] = primes[0]; + fullKey->prime[1] = primes[1]; + } + if (primeExponents != (ITEM *)NULL_PTR) { + fullKey->primeExponent[0] = primeExponents[0]; + fullKey->primeExponent[1] = primeExponents[1]; + } + if (coefficient != (ITEM *)NULL_PTR) + fullKey->coefficient = *coefficient; + + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KITFullPrivate, (POINTER)fullKey)); +} + +/* Select the key object's full private key and set all of the supplied + fields which are not (ITEM *)NULL_PTR. + primes and primeExponents point to a 2 entry ITEM array. + If one of the fields is not (ITEM *)NULL_PTR, but the full key's + field is null, return BE_WRONG_KEY_INFO. + */ +int GetFullPrivateKeyInfo + (modulus, publicExponent, privateExponent, primes, primeExponents, + coefficient, key) +ITEM *modulus; +ITEM *publicExponent; +ITEM *privateExponent; +ITEM *primes; +ITEM *primeExponents; +ITEM *coefficient; +B_Key *key; +{ + FULL_PRIVATE_KEY *fullKey; + int status; + + if ((status = B_KeyGetInfo + (key, (POINTER *)&fullKey, &KITFullPrivate)) != 0) + return (status); + + if (modulus != (ITEM *)NULL_PTR) { + if (fullKey->modulus.data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + *modulus = fullKey->modulus; + } + if (publicExponent != (ITEM *)NULL_PTR) { + if (fullKey->publicExponent.data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + *publicExponent = fullKey->publicExponent; + } + if (privateExponent != (ITEM *)NULL_PTR) { + if (fullKey->privateExponent.data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + *privateExponent = fullKey->privateExponent; + } + if (primes != (ITEM *)NULL_PTR) { + if (fullKey->prime[0].data == (unsigned char *)NULL_PTR || + fullKey->prime[1].data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + primes[0] = fullKey->prime[0]; + primes[1] = fullKey->prime[1]; + } + if (primeExponents != (ITEM *)NULL_PTR) { + if (fullKey->primeExponent[0].data == (unsigned char *)NULL_PTR || + fullKey->primeExponent[1].data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + primeExponents[0] = fullKey->primeExponent[0]; + primeExponents[1] = fullKey->primeExponent[1]; + } + if (coefficient != (ITEM *)NULL_PTR) { + if (fullKey->coefficient.data == (unsigned char *)NULL_PTR) + return (BE_WRONG_KEY_INFO); + *coefficient = fullKey->coefficient; + } + + return (0); +} + +/* This is not intended to be called from B_SetKeyInfo. + Get returns BE_WRONG_KEY_INFO. + */ +static int KITFullPrivateKeyAddInfo (key, info) +B_Key *key; +POINTER info; +{ +UNUSED_ARG (key) +UNUSED_ARG (info) + return (BE_ALG_OPERATION_UNKNOWN); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/kifulprv.h b/usr/src/lib/libresolv2/common/dnssafe/kifulprv.h new file mode 100644 index 0000000000..55cdd8c666 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kifulprv.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +int CacheFullPrivateKey PROTO_LIST + ((B_Key *, ITEM *, ITEM *, ITEM *, ITEM *, ITEM *, ITEM *)); +int GetFullPrivateKeyInfo PROTO_LIST + ((ITEM *, ITEM *, ITEM *, ITEM *, ITEM *, ITEM *, B_Key *)); diff --git a/usr/src/lib/libresolv2/common/dnssafe/kiitem.c b/usr/src/lib/libresolv2/common/dnssafe/kiitem.c new file mode 100644 index 0000000000..3aaa80f358 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kiitem.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "kiitem.h" +#include "port_after.h" + +int KITItemAddInfo PROTO_LIST ((B_Key *, POINTER)); + +B_KeyInfoType KITItem = {KITItemAddInfo, B_KeyInfoTypeMakeError}; + +int KI_Item (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KITItem; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +/* info is an ITEM. The ITEM's data is copied into the object. + */ +int KITItemAddInfo (key, info) +B_Key *key; +POINTER info; +{ + unsigned char *newData; + int status; + + if ((status = B_MemoryPoolAllocAndCopy + (&key->infoCache.memoryPool, (POINTER *)&newData, + (POINTER)((ITEM *)info)->data, ((ITEM *)info)->len)) != 0) + return (status); + + return (B_KeyAddItemInfo (key, newData, ((ITEM *)info)->len)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/kiitem.h b/usr/src/lib/libresolv2/common/dnssafe/kiitem.h new file mode 100644 index 0000000000..ad0863722f --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kiitem.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +extern B_KeyInfoType KITItem; diff --git a/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.c b/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.c new file mode 100644 index 0000000000..fba31dc2ba --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "port_after.h" + +/* This is the default routine which key info types can point MakeInfo to. + */ +int B_KeyInfoTypeMakeError (info, key) +POINTER *info; +B_Key *key; +{ +UNUSED_ARG (info) +UNUSED_ARG (key) + + /* Should already have been found in the cache. */ + return (BE_WRONG_KEY_INFO); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.h b/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.h new file mode 100644 index 0000000000..8de4f5e883 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kinfotyp.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +typedef int (*KIT_ADD_INFO) PROTO_LIST ((B_Key *, POINTER)); +typedef int (*KIT_MAKE_INFO) PROTO_LIST ((POINTER *, B_Key *)); + +/* The definition in C++ is: + class B_KeyInfoType { + public: + B_KeyInfoType (KIT_ADD_INFO AddInfo) { + _AddInfo = AddInfo; + _MakeInfo = KeyInfoType::makeError;} + B_KeyInfoType (KIT_ADD_INFO AddInfo, KIT_MAKE_INFO MakeInfo) { + _AddInfo = AddInfo; + _MakeInfo = MakeInfo;} + + int addInfo (B_Key *key, POINTER info) {return (*_AddInfo) (key, info);} + int makeInfo (POINTER *info, B_Key *key) {return (*_MakeInfo) (info, key);} + + static int makeError (POINTER *info, B_Key *key); + + private: + KIT_ADD_INFO _AddInfo; + KIT_MAKE_INFO _MakeInfo; + }; + + Note that a derived class simply calls one of the B_KeyInfoType constructors + which set the addInfo or both the addInfo and makeInfo callbacks. + There is no need for an extra level involving virtual functions because + each key class only has one instance, making a V table a waste of space. + An example of a derived class is: + + class KITItem : public B_KeyInfoType { + public: + // Set addInfo and leave makeInfo as B_KeyInfoType::makeError + KITItem () : B_KeyInfoType (KITItem::addInfo) {}; + + static int addInfo (B_Key *key, POINTER info); + }; + + + There is one global instance which is used by B_Key::setInfo, etc.: + + KITItem KITItem; + */ + +typedef struct B_KeyInfoType { + KIT_ADD_INFO AddInfo; + KIT_MAKE_INFO MakeInfo; +} B_KeyInfoType; + +int B_KeyInfoTypeMakeError PROTO_LIST ((POINTER *, B_Key *)); diff --git a/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.c b/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.c new file mode 100644 index 0000000000..e0d3ff523e --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "intitem.h" +#include "kifulprv.h" +#include "kipkcrpr.h" +#include "port_after.h" + +B_KeyInfoType KIT_PKCS_RSAPrivate = + {KIT_PKCS_RSAPrivateAddInfo, KIT_PKCS_RSAPrivateMakeInfo}; + +static A_PKCS_RSA_PRIVATE_KEY STATIC_PKCS_RSA_PRIVATE_KEY; +static ITEM *PKCS_RSA_PRIVATE_KEY_ITEMS[] = { + &STATIC_PKCS_RSA_PRIVATE_KEY.modulus, + &STATIC_PKCS_RSA_PRIVATE_KEY.publicExponent, + &STATIC_PKCS_RSA_PRIVATE_KEY.privateExponent, + &STATIC_PKCS_RSA_PRIVATE_KEY.prime[0], + &STATIC_PKCS_RSA_PRIVATE_KEY.prime[1], + &STATIC_PKCS_RSA_PRIVATE_KEY.primeExponent[0], + &STATIC_PKCS_RSA_PRIVATE_KEY.primeExponent[1], + &STATIC_PKCS_RSA_PRIVATE_KEY.coefficient +}; + +int KI_PKCS_RSAPrivate (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KIT_PKCS_RSAPrivate; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +int KIT_PKCS_RSAPrivateAddInfo (key, info) +B_Key *key; +POINTER info; +{ + A_PKCS_RSA_PRIVATE_KEY *newValue; + int status; + + /* Allocate memory for A_PKCS_RSA_PRIVATE_KEY struct and copy integers + from supplied value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, (POINTER *)&newValue, + sizeof (A_PKCS_RSA_PRIVATE_KEY))) != 0) + return (status); + if ((status = AllocAndCopyIntegerItems + ((POINTER)newValue, info, (POINTER)&STATIC_PKCS_RSA_PRIVATE_KEY, + PKCS_RSA_PRIVATE_KEY_ITEMS, sizeof (PKCS_RSA_PRIVATE_KEY_ITEMS) / + sizeof (PKCS_RSA_PRIVATE_KEY_ITEMS[0]), &key->infoCache.memoryPool)) + != 0) + return (status); + + /* Cache the full private key info. + */ + if ((status = CacheFullPrivateKey + (key, &newValue->modulus, &newValue->publicExponent, + &newValue->privateExponent, newValue->prime, newValue->primeExponent, + &newValue->coefficient)) != 0) + return (status); + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KIT_PKCS_RSAPrivate, (POINTER)newValue)); +} + +int KIT_PKCS_RSAPrivateMakeInfo (info, key) +POINTER *info; +B_Key *key; +{ + A_PKCS_RSA_PRIVATE_KEY keyValue; + int status; + + /* If not already found in the cache, try to get values from + a full private key info. + */ + if ((status = GetFullPrivateKeyInfo + (&keyValue.modulus, &keyValue.publicExponent, + &keyValue.privateExponent, keyValue.prime, keyValue.primeExponent, + &keyValue.coefficient, key)) != 0) + return (status); + + /* Got all the needed fields, so allocate memory for a new + A_PKCS_RSA_PRIVATE_KEY struct and copy the key value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, info, sizeof (A_PKCS_RSA_PRIVATE_KEY))) + != 0) + return (status); + + **(A_PKCS_RSA_PRIVATE_KEY **)info = keyValue; + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.h b/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.h new file mode 100644 index 0000000000..f61de3ce97 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kipkcrpr.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +extern B_KeyInfoType KIT_PKCS_RSAPrivate; + +int KIT_PKCS_RSAPrivateAddInfo PROTO_LIST ((B_Key *, POINTER)); +int KIT_PKCS_RSAPrivateMakeInfo PROTO_LIST ((POINTER *, B_Key *)); + diff --git a/usr/src/lib/libresolv2/common/dnssafe/kirsacrt.c b/usr/src/lib/libresolv2/common/dnssafe/kirsacrt.c new file mode 100644 index 0000000000..269724d7e8 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kirsacrt.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "intitem.h" +#include "kifulprv.h" +#include "port_after.h" + +#define NULL_UCHAR_PTR ((unsigned char *)NULL_PTR) + +int KIT_RSA_CRTAddInfo PROTO_LIST ((B_Key *, POINTER)); +int KIT_RSA_CRTMakeInfo PROTO_LIST ((POINTER *, B_Key *)); + +B_KeyInfoType KIT_RSA_CRT = {KIT_RSA_CRTAddInfo, KIT_RSA_CRTMakeInfo}; + +static A_RSA_CRT_KEY STATIC_RSA_CRT_KEY; +static ITEM *RSA_CRT_KEY_ITEMS[] = { + &STATIC_RSA_CRT_KEY.modulus, &STATIC_RSA_CRT_KEY.prime[0], + &STATIC_RSA_CRT_KEY.prime[1], + &STATIC_RSA_CRT_KEY.primeExponent[0], + &STATIC_RSA_CRT_KEY.primeExponent[1], + &STATIC_RSA_CRT_KEY.coefficient +}; + +/* args points to A_RSA_CRT_KEY. + */ +int KI_RSA_CRT (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KIT_RSA_CRT; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +int KIT_RSA_CRTAddInfo (key, info) +B_Key *key; +POINTER info; +{ + A_RSA_CRT_KEY *newValue; + int status; + + /* Allocate memory for A_RSA_CRT_KEY struct and copy integers + from supplied value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, (POINTER *)&newValue, + sizeof (A_RSA_CRT_KEY))) != 0) + return (status); + if ((status = AllocAndCopyIntegerItems + ((POINTER)newValue, info, (POINTER)&STATIC_RSA_CRT_KEY, + RSA_CRT_KEY_ITEMS, + sizeof (RSA_CRT_KEY_ITEMS) / sizeof (RSA_CRT_KEY_ITEMS[0]), + &key->infoCache.memoryPool)) != 0) + return (status); + + /* Cache the full private key info, setting unused fields to NULL. + */ + if ((status = CacheFullPrivateKey + (key, &newValue->modulus, (ITEM *)NULL_PTR, (ITEM *)NULL_PTR, + newValue->prime, newValue->primeExponent, &newValue->coefficient)) + != 0) + return (status); + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KIT_RSA_CRT, (POINTER)newValue)); +} + +int KIT_RSA_CRTMakeInfo (info, key) +POINTER *info; +B_Key *key; +{ + A_RSA_CRT_KEY keyValue; + int status; + + /* If not already found in the cache, try to get values from + a full private key info, setting unneeded entries to NULL. + */ + if ((status = GetFullPrivateKeyInfo + (&keyValue.modulus, (ITEM *)NULL_PTR, (ITEM *)NULL_PTR, + keyValue.prime, keyValue.primeExponent, &keyValue.coefficient, + key)) != 0) + return (status); + + /* Got all the needed fields, so allocate memory for a new + A_RSA_CRT_KEY struct and copy the key value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, info, sizeof (A_RSA_CRT_KEY))) != 0) + return (status); + + **(A_RSA_CRT_KEY **)info = keyValue; + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/kirsapub.c b/usr/src/lib/libresolv2/common/dnssafe/kirsapub.c new file mode 100644 index 0000000000..22baff948b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kirsapub.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "kinfotyp.h" +#include "intitem.h" +#include "kifulprv.h" +#include "kirsapub.h" +#include "port_after.h" + +B_KeyInfoType KIT_RSAPublic = + {KIT_RSAPublicAddInfo, KIT_RSAPublicMakeInfo}; + +static A_RSA_KEY STATIC_RSA_KEY; +static ITEM *RSA_KEY_ITEMS[] = + {&STATIC_RSA_KEY.modulus, &STATIC_RSA_KEY.exponent}; + +int KI_RSAPublic (keyInfoType) +POINTER *keyInfoType; +{ + *keyInfoType = (POINTER)&KIT_RSAPublic; + + /* Return 1 to indicate a KeyInfoType, not an AlgorithmInfoType */ + return (1); +} + +int KIT_RSAPublicAddInfo (key, info) +B_Key *key; +POINTER info; +{ + POINTER newValue; + int status; + + /* Allocate memory for A_RSA_KEY struct and copy integers + from supplied value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, &newValue, sizeof (A_RSA_KEY))) != 0) + return (status); + if ((status = AllocAndCopyIntegerItems + (newValue, info, (POINTER)&STATIC_RSA_KEY, RSA_KEY_ITEMS, + sizeof (RSA_KEY_ITEMS) / sizeof (RSA_KEY_ITEMS[0]), + &key->infoCache.memoryPool)) != 0) + return (status); + + return (B_InfoCacheAddInfo + (&key->infoCache, (POINTER)&KIT_RSAPublic, newValue)); +} + +int KIT_RSAPublicMakeInfo (info, key) +POINTER *info; +B_Key *key; +{ + A_RSA_KEY keyValue; + int status; + + /* If not already found in the cache, try to get values from + a full private key info, setting unneeded entries to NULL. + */ + if ((status = GetFullPrivateKeyInfo + (&keyValue.modulus, &keyValue.exponent, (ITEM *)NULL_PTR, + (ITEM *)NULL_PTR, (ITEM *)NULL_PTR, (ITEM *)NULL_PTR, key)) != 0) + return (status); + + /* Got all the needed fields, so allocate memory for a new + A_RSA_KEY struct and copy the key value. + */ + if ((status = B_MemoryPoolAlloc + (&key->infoCache.memoryPool, info, sizeof (A_RSA_KEY))) != 0) + return (status); + + **(A_RSA_KEY **)info = keyValue; + return (0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/kirsapub.h b/usr/src/lib/libresolv2/common/dnssafe/kirsapub.h new file mode 100644 index 0000000000..0e26eb3666 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/kirsapub.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1993, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +extern B_KeyInfoType KIT_RSAPublic; + +int KIT_RSAPublicAddInfo PROTO_LIST ((B_Key *, POINTER)); +int KIT_RSAPublicMakeInfo PROTO_LIST ((POINTER *, B_Key *)); + diff --git a/usr/src/lib/libresolv2/common/dnssafe/md5.h b/usr/src/lib/libresolv2/common/dnssafe/md5.h new file mode 100644 index 0000000000..1a1c963a61 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/md5.h @@ -0,0 +1,51 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _MD5_H_ +#define _MD5_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define A_MD5_DIGEST_LEN 16 + +#ifndef SUNW_LIBMD5 + +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} A_MD5_CTX; + +void A_MD5Init PROTO_LIST ((A_MD5_CTX *)); +void A_MD5Update PROTO_LIST ((A_MD5_CTX *, const unsigned char *, unsigned int)); +void A_MD5Final PROTO_LIST ((A_MD5_CTX *, unsigned char *)); + +#else + +#include <sys/md5.h> +#define A_MD5_CTX MD5_CTX +#define A_MD5Init(c) MD5Init((c)) +#define A_MD5Update(c, d, l) MD5Update((c), (d), (l)) +#define A_MD5Final(c, d) MD5Final((d), (c)) + +#endif /* SUNW_LIBMD5 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/md5rand.c b/usr/src/lib/libresolv2/common/dnssafe/md5rand.c new file mode 100644 index 0000000000..d8e910ec15 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/md5rand.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +/* Define this so that the type of the 'this' pointer in the + virtual functions will be correct for this derived class. + */ +struct A_MD5_RANDOM_CTX; +#define THIS_DIGEST_RANDOM struct A_MD5_RANDOM_CTX + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "md5rand.h" +#include "port_after.h" + +static void A_MD5RandomDigestUpdate PROTO_LIST + ((A_MD5_RANDOM_CTX *, unsigned char *, unsigned int)); +static void A_MD5RandomDigestFinal PROTO_LIST + ((A_MD5_RANDOM_CTX *, unsigned char *)); + +static A_DigestRandomVTable V_TABLE = + {A_MD5RandomDigestUpdate, A_MD5RandomDigestFinal}; + +void A_MD5RandomInit (context) +A_MD5_RANDOM_CTX *context; +{ + /* Initialize "base class" */ + A_DigestRandomInit + (&context->digestRandom, A_MD5_DIGEST_LEN, context->state); + + /* Initialize digest algorithm and set vTable. + */ + A_MD5Init (&context->md5Context); + context->digestRandom.vTable = &V_TABLE; +} + +void A_MD5RandomUpdate (context, input, inputLen) +A_MD5_RANDOM_CTX *context; +unsigned char *input; +unsigned int inputLen; +{ + A_DigestRandomUpdate (&context->digestRandom, input, inputLen); +} + +void A_MD5RandomGenerateBytes (context, output, outputLen) +A_MD5_RANDOM_CTX *context; +unsigned char *output; +unsigned int outputLen; +{ + A_DigestRandomGenerateBytes (&context->digestRandom, output, outputLen); +} + +static void A_MD5RandomDigestUpdate (context, input, inputLen) +A_MD5_RANDOM_CTX *context; +unsigned char *input; +unsigned int inputLen; +{ + A_MD5Update (&context->md5Context, input, inputLen); +} + +static void A_MD5RandomDigestFinal (context, digest) +A_MD5_RANDOM_CTX *context; +unsigned char *digest; +{ + A_MD5Final (&context->md5Context, digest); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/md5rand.h b/usr/src/lib/libresolv2/common/dnssafe/md5rand.h new file mode 100644 index 0000000000..a181e147d7 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/md5rand.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _MD5RAND_H_ +#define _MD5RAND_H_ 1 + +#include "digrand.h" +#include "md5.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct A_MD5_RANDOM_CTX { + A_DigestRandom digestRandom; /* "base class" */ + + unsigned char state[3 * A_MD5_DIGEST_LEN]; + A_MD5_CTX md5Context; +} A_MD5_RANDOM_CTX; + +void A_MD5RandomInit PROTO_LIST ((A_MD5_RANDOM_CTX *)); +void A_MD5RandomUpdate PROTO_LIST + ((A_MD5_RANDOM_CTX *, unsigned char *, unsigned int)); +void A_MD5RandomGenerateBytes PROTO_LIST + ((A_MD5_RANDOM_CTX *, unsigned char *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/prime.c b/usr/src/lib/libresolv2/common/dnssafe/prime.c new file mode 100644 index 0000000000..a1819813f7 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/prime.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bigmath.h" +#include "prime.h" +#include "port_after.h" + +static unsigned char SMALL_PRIME[]= {3, 5, 7, 11, 13, 17, 19, 23, 29, 31}; + +/* Prime finding routine. + Returns 0, AE_CANCEL, AE_NEED_RANDOM. + */ +int PrimeFind + (prime, primeSizeBits, primeWords, ee, modulusWords, randomBlock, + surrenderContext) +UINT2 *prime; +unsigned int primeSizeBits; +unsigned int primeWords; +UINT2 *ee; +unsigned int modulusWords; +unsigned char *randomBlock; +A_SURRENDER_CTX *surrenderContext; +{ + UINT2 t1[MAX_RSA_MODULUS_WORDS], u1[MAX_RSA_MODULUS_WORDS], + u2[MAX_RSA_MODULUS_WORDS], u3[MAX_RSA_MODULUS_WORDS], + u4[MAX_RSA_MODULUS_WORDS]; + char sieve[1000]; + int status = 0; + unsigned int i, r, s, testResult; + + do { + /* Create a starting point for the prime from the random block */ + for (i = 0; i < primeWords; i++) { + prime[i] = (UINT2)((UINT2)randomBlock[0] << 8) + randomBlock[1]; + randomBlock += 2; + } + + /* set high order two bits */ + BigSetbit (prime, primeSizeBits-2); + BigSetbit (prime, primeSizeBits-1); + for (i = primeSizeBits; i < (unsigned int)(16 * primeWords); i++) + BigClrbit (prime, i); + + /* force p to be even */ + BigClrbit (prime, 0); + + /* clear sieve and mark even positions */ + for (i = 0; i < 1000; i += 2) { + sieve[i] = 1; + sieve[i+1] = 0; + } + + /* sieve by all odd numbers (don't bother with primality checking) */ + for (s = 3; s < 9000; s += 2) { + /* increase likelihood that s is prime */ + for (i = 0; i < 5; i++) + if (s > SMALL_PRIME[i] && !(s % SMALL_PRIME[i])) + continue; + + /* sieve based on s */ + r = BigSmod (prime, s, primeWords); + + /* returns prime modulo s */ + if (r == 0) + r = s; + + for (i = s - r; i < 1000; i += s) + sieve[i] = 1; + } + + /* t1 = 1 */ + BigConst (t1, 1, modulusWords); + + /* now check for primality of values with unmarked sieve */ + testResult = 0; + for (i = 0; i < 1000; i++, BigInc (prime, primeWords)) { + if (sieve[i]) + continue; + + /* copy prime into big variable */ + BigZero (u4, modulusWords); + BigCopy (u4, prime, primeWords); + + /* set u4 = p - 1 */ + BigDec (u4, modulusWords); + BigPegcd (u1, u2, u3, ee, u4, modulusWords); + + /* Now u1 = gcd (E, t1). + Test (E, t1)==1 */ + if (BigCmp (t1, u1, modulusWords)) + continue; + + /* check for pseudo primality */ + if ((status = PseudoPrime + (&testResult, prime, primeWords, surrenderContext)) != 0) + break; + if (testResult) + /* testResult is set and will cause a break out of while (1) loop */ + break; + } + if (status) + break; + + if (!testResult) + /* Couldn't find a prime with the supplied random block, so ask + caller to generate another random block and try again. */ + status = AE_NEED_RANDOM; + } while (0); + + T_memset ((POINTER)u1, 0, sizeof (u1)); + T_memset ((POINTER)u2, 0, sizeof (u2)); + T_memset ((POINTER)u3, 0, sizeof (u3)); + T_memset ((POINTER)u4, 0, sizeof (u4)); + return (status); +} + +/* Pseudo-primality test. + If pseudo prime, *testResult = 1, else *testResult = 0. + Returns 0, AE_CANCEL. + */ +int PseudoPrime (testResult, prime, primeWords, surrenderContext) +unsigned int *testResult; +UINT2 *prime; +unsigned int primeWords; +A_SURRENDER_CTX *surrenderContext; +{ + UINT2 base[MAX_RSA_MODULUS_WORDS], remainder[MAX_RSA_MODULUS_WORDS]; + int status; + unsigned int i; + + /* Default testResult to false. */ + *testResult = 0; + + /* Prepare for setting base vector to the small prime. */ + T_memset ((POINTER)base, 0, sizeof (base)); + + for (i = 0; i < 4; i++) { + /* check to see if target is multiple of SMALL_PRIME */ + if (BigSmod (prime, (unsigned int)SMALL_PRIME[i], primeWords) == 0) + /* fail... */ + return (0); + + /* Fermat test. Compute remainder = base ^ prime mod prime + and compare the base to the remainder. + */ + base[0] = (UINT2)SMALL_PRIME[i]; + if ((status = BigModExp + (remainder, base, prime, prime, primeWords, surrenderContext)) != 0) + return (status); + if (BigCmp (remainder, base, primeWords) != 0) + /* fail... */ + return (0); + } + + *testResult = 1; + return (0); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/prime.h b/usr/src/lib/libresolv2/common/dnssafe/prime.h new file mode 100644 index 0000000000..4d94667a3e --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/prime.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _PRIME_H_ +#define _PRIME_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +int PrimeFind PROTO_LIST + ((UINT2 *, unsigned int, unsigned int, UINT2 *, unsigned int, + unsigned char *, A_SURRENDER_CTX *)); +int PseudoPrime PROTO_LIST + ((unsigned int *, UINT2 *, unsigned int, A_SURRENDER_CTX *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/random.c b/usr/src/lib/libresolv2/common/dnssafe/random.c new file mode 100644 index 0000000000..8126b76926 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/random.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "bsafe2.h" +#include "bkey.h" +#include "balg.h" +#include "ainfotyp.h" +#include "algobj.h" +#include "port_after.h" + +int B_RandomInit + (algorithmObject, algorithmChooser, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +B_ALGORITHM_CHOOSER algorithmChooser; +A_SURRENDER_CTX *surrenderContext; +{ + if (AlgorithmWrapCheck (THE_ALG_WRAP) != 0) + /* Assume error is B_ALGORITHM_OBJ */ + return (BE_RANDOM_OBJ); + + return (B_AlgorithmRandomInit + (&THE_ALG_WRAP->algorithm, algorithmChooser, surrenderContext)); +} + +int B_RandomUpdate (algorithmObject, input, inputLen, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *input; +unsigned int inputLen; +A_SURRENDER_CTX *surrenderContext; +{ + if (AlgorithmWrapCheck (THE_ALG_WRAP) != 0) + /* Assume error is B_ALGORITHM_OBJ */ + return (BE_RANDOM_OBJ); + + return (B_AlgorithmRandomUpdate + (&THE_ALG_WRAP->algorithm, input, inputLen, surrenderContext)); +} + +int B_GenerateRandomBytes + (algorithmObject, output, outputLen, surrenderContext) +B_ALGORITHM_OBJ algorithmObject; +unsigned char *output; +unsigned int outputLen; +A_SURRENDER_CTX *surrenderContext; +{ + if (AlgorithmWrapCheck (THE_ALG_WRAP) != 0) + /* Assume error is B_ALGORITHM_OBJ */ + return (BE_RANDOM_OBJ); + + return (B_AlgorithmGenerateRandomBytes + (&THE_ALG_WRAP->algorithm, output, outputLen, surrenderContext)); +} + diff --git a/usr/src/lib/libresolv2/common/dnssafe/rsa.c b/usr/src/lib/libresolv2/common/dnssafe/rsa.c new file mode 100644 index 0000000000..5aeea63ccb --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/rsa.c @@ -0,0 +1,218 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "rsa.h" +#include "bigmath.h" +#include "port_after.h" + +/* RSA encryption/decryption with full exponent. + */ + +#define GENERATE_BREAK(type) { \ + status = type; \ + break; \ + } + +static int RSA PROTO_LIST + ((A_RSA_CTX *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, A_SURRENDER_CTX *)); + +/* Returns 0, AE_MODULUS_LEN, AE_KEY_INFO. + */ +int A_RSAInit (context, key) +A_RSA_CTX *context; +A_RSA_KEY *key; +{ + if (A_IntegerBits (key->modulus.data, key->modulus.len) + > MAX_RSA_MODULUS_BITS) + /* Key size is too big to handle. */ + return (AE_MODULUS_LEN); + + /* Set the block update blockLen to be big enough to hold the modulus. */ + context->blockLen = + (A_IntegerBits (key->modulus.data, key->modulus.len) + 7) / 8; + + context->inputLen = 0; + + /* convert modulus to bignum representation */ + if (CanonicalToBig + (context->modulus, MAX_RSA_MODULUS_WORDS, key->modulus.data, + key->modulus.len)) + return (AE_KEY_INFO); + + /* compute significant length of modulus */ + context->modulusWords = BigLen + (context->modulus, MAX_RSA_MODULUS_WORDS) / 16 + 1; + + /* convert exponent to bignum representation */ + if (CanonicalToBig + (context->exponent, context->modulusWords, + key->exponent.data, key->exponent.len)) + return (AE_KEY_INFO); + + return (0); +} + +int A_RSAUpdate + (context, partOut, partOutLen, maxPartOutLen, partIn, partInLen, + surrenderContext) +A_RSA_CTX *context; +unsigned char *partOut; +unsigned int *partOutLen; +unsigned int maxPartOutLen; +const unsigned char *partIn; +unsigned int partInLen; +A_SURRENDER_CTX *surrenderContext; +{ + int status; + unsigned int partialLen, localPartOutLen; + + /* Initialize partOutLen to zero. */ + *partOutLen = 0; + + if (context->inputLen + partInLen < context->blockLen) { + /* Not enough to encrypt - just accumulate. + */ + T_memcpy + ((POINTER)(context->input + context->inputLen), (CPOINTER)partIn, + partInLen); + context->inputLen += partInLen; + return (0); + } + + if (context->inputLen > 0) { + /* Need to accumulate the rest of the block bytes into the input and + encrypt from there (otherwise it's OK to encrypt straight from + the partIn). + */ + partialLen = context->blockLen - context->inputLen; + T_memcpy + ((POINTER)(context->input + context->inputLen), (CPOINTER)partIn, + partialLen); + partIn += partialLen; + partInLen -= partialLen; + + if ((status = RSA + (context, partOut, &localPartOutLen, maxPartOutLen, context->input, + surrenderContext)) != 0) + return (status); + (*partOutLen) += localPartOutLen; + partOut += localPartOutLen; + maxPartOutLen -= localPartOutLen; + } + + /* Encrypt as many blocks of input as provided. + */ + while (partInLen >= context->blockLen) { + if ((status = RSA + (context, partOut, &localPartOutLen, maxPartOutLen, partIn, + surrenderContext)) != 0) + return (status); + + partIn += context->blockLen; + partInLen -= context->blockLen; + (*partOutLen) += localPartOutLen; + partOut += localPartOutLen; + maxPartOutLen -= localPartOutLen; + } + + /* Copy remaining input bytes to the context's input buffer. + */ + T_memcpy + ((POINTER)context->input, partIn, context->inputLen = partInLen); + return (0); +} + +int A_RSAFinal (context) +A_RSA_CTX *context; +{ + if (context->inputLen != 0) + return (AE_INPUT_LEN); + + /* Restart context to accumulate a new block. */ + context->inputLen = 0; + return (0); +} + +/* Assume input length is context->blockLen. + */ +static int RSA + (context, output, outputLen, maxOutputLen, input, surrenderContext) +A_RSA_CTX *context; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +const unsigned char *input; +A_SURRENDER_CTX *surrenderContext; +{ + struct ModExpFrame { + UINT2 bigInBuf[MAX_RSA_MODULUS_WORDS], bigOutBuf[MAX_RSA_MODULUS_WORDS]; + } *frame = (struct ModExpFrame *)NULL_PTR; +#if !USE_ALLOCED_FRAME + struct ModExpFrame stackFrame; +#endif + int status; + + status = 0; + do { + if ((*outputLen = context->blockLen) > maxOutputLen) + return (AE_OUTPUT_LEN); + +#if USE_ALLOCED_FRAME + if ((frame = (struct ModExpFrame *)T_malloc (sizeof (*frame))) + == (struct ModExpFrame *)NULL_PTR) { + status = AE_ALLOC; + break; + } +#else + /* Just use the buffers allocated on the stack. */ + frame = &stackFrame; +#endif + + /* Convert input to bignum representation. + This won't return AE_DATA since input length was checked at Update. + */ + CanonicalToBig + (frame->bigInBuf, context->modulusWords, input, context->blockLen); + + /* Check for overflow. */ + if (BigCmp (frame->bigInBuf, context->modulus, context->modulusWords) >= 0) + GENERATE_BREAK (AE_INPUT_DATA); + + /* Exponentiate. */ + if ((status = BigModExp + (frame->bigOutBuf, frame->bigInBuf, context->exponent, + context->modulus, context->modulusWords, surrenderContext)) != 0) + break; + + /* Convert output to canonical representation. + This won't return AE_DATA since outputLen was set above. + */ + BigToCanonical + (output, *outputLen, frame->bigOutBuf, context->modulusWords); + } while (0); + + if (frame != (struct ModExpFrame *)NULL_PTR) { + T_memset ((POINTER)frame, 0, sizeof (*frame)); +#if USE_ALLOCED_FRAME + T_free ((POINTER)frame); +#endif + } + + return (status); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/rsa.h b/usr/src/lib/libresolv2/common/dnssafe/rsa.h new file mode 100644 index 0000000000..986af82afb --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/rsa.h @@ -0,0 +1,51 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _RSA_H_ +#define _RSA_H_ 1 + +#include "bigmaxes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note, these are only valid after a call to A_RSAInit. + */ +#define A_RSA_BLOCK_LEN(context) ((context)->blockLen) +#define A_RSA_MAX_OUTPUT_LEN(context, inputLen)\ + (inputLen) + (((inputLen) % (context)->blockLen) ?\ + (context)->blockLen - ((inputLen) % (context)->blockLen) : 0) + +typedef struct { + unsigned int blockLen; /* total size for the block to be computed */ + unsigned char input[MAX_RSA_MODULUS_LEN]; + unsigned int inputLen; + unsigned int modulusWords; + UINT2 modulus[MAX_RSA_MODULUS_WORDS]; + UINT2 exponent[MAX_RSA_MODULUS_WORDS]; +} A_RSA_CTX; + +int A_RSAInit PROTO_LIST ((A_RSA_CTX *, A_RSA_KEY *)); +int A_RSAUpdate PROTO_LIST + ((A_RSA_CTX *, unsigned char *, unsigned int *, unsigned int, + const unsigned char *, unsigned int, A_SURRENDER_CTX *)); +int A_RSAFinal PROTO_LIST ((A_RSA_CTX *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.c b/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.c new file mode 100644 index 0000000000..010c1e2414 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "bigmath.h" +#include "surrendr.h" +#include "prime.h" +#include "rsakeygn.h" +#include "port_after.h" + +#define GENERATE_BREAK(type) { \ + status = type; \ + break; \ + } + +static int RSAParameters PROTO_LIST + ((UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, UINT2 *, + unsigned int, unsigned int, A_SURRENDER_CTX *)); +static void SetRSAKeyGenResult PROTO_LIST + ((A_PKCS_RSA_PRIVATE_KEY *, A_RSA_KEY_GEN_CTX *, UINT2 *, UINT2 *)); + +int A_RSAKeyGenInit (context, params) +A_RSA_KEY_GEN_CTX *context; +A_RSA_KEY_GEN_PARAMS *params; +{ + context->modulusBits = params->modulusBits; + + /* Prezeroize big public exponent vector. */ + T_memset + ((POINTER)context->bigPublicExponent, 0, + sizeof (context->bigPublicExponent)); + + /* Copy public exponent into big vector */ + if (CanonicalToBig + (context->bigPublicExponent, MAX_RSA_MODULUS_WORDS, + params->publicExponent.data, params->publicExponent.len) != 0) + /* could not copy exponent into MAX_RSA_MODULUS_WORDS */ + return (AE_EXPONENT_LEN); + + /* Check that public exponent is in bounds and odd. + */ + if (BigLen (context->bigPublicExponent, MAX_RSA_MODULUS_WORDS) >= + context->modulusBits) + return (AE_EXPONENT_LEN); + if (!(context->bigPublicExponent[0] & 1)) + return (AE_EXPONENT_EVEN); + + return (0); +} + +/* This generates an RSA keypair of size modulusBits with the fixed + publicExponent, pointing result to the resulting integers. The + resulting integer data is in the context, so that the values must be + copied before the context is zeroized. + All integers are unsigned canonical bytes arrays with the most significant + byte first. + The randomBlock is of length randomBlockLen returned by RSAKeyGenQuery. + This assumes that the modulusBits size was checked by RSAKeyGenQuery. + */ +int A_RSAKeyGen (context, result, randomBlock, surrenderContext) +A_RSA_KEY_GEN_CTX *context; +A_PKCS_RSA_PRIVATE_KEY **result; +unsigned char *randomBlock; +A_SURRENDER_CTX *surrenderContext; +{ + UINT2 *bigPrimeP, *bigPrimeQ; + int status; + unsigned int modulusWords, primeSizeBits, primeWords; + + /* Prezeroize all big word vectors. */ + T_memset ((POINTER)context->bigModulus, 0, sizeof (context->bigModulus)); + T_memset + ((POINTER)context->bigPrivateExponent, 0, + sizeof (context->bigPrivateExponent)); + T_memset ((POINTER)context->bigPrime1, 0, sizeof (context->bigPrime1)); + T_memset ((POINTER)context->bigPrime2, 0, sizeof (context->bigPrime2)); + T_memset ((POINTER)context->bigExponentP, 0, sizeof (context->bigExponentP)); + T_memset ((POINTER)context->bigExponentQ, 0, sizeof (context->bigExponentQ)); + T_memset + ((POINTER)context->bigCoefficient, 0, sizeof (context->bigCoefficient)); + + /* prime size is half modulus size */ + modulusWords = BITS_TO_WORDS (context->modulusBits); + primeSizeBits = RSA_PRIME_BITS (context->modulusBits); + primeWords = BITS_TO_WORDS (RSA_PRIME_BITS (context->modulusBits)); + + /* Fish for bigPrime1 and bigPrime2 that are compatible with supplied + publicExponent. + The randomBlock holds random bytes for two primes. + */ + if ((status = PrimeFind + (context->bigPrime1, primeSizeBits, primeWords, + context->bigPublicExponent, modulusWords, randomBlock, + surrenderContext)) != 0) + return (status); + if ((status = PrimeFind + (context->bigPrime2, context->modulusBits - primeSizeBits, + primeWords, context->bigPublicExponent, modulusWords, + randomBlock + (2 * primeWords), surrenderContext)) != 0) + return (status); + + /* Set bigPrimeP to the larger of bigPrime1 and bigPrime2 and set + bigPrimeQ to the smaller. + */ + if (BigCmp (context->bigPrime1, context->bigPrime2, primeWords) == 1) { + bigPrimeP = context->bigPrime1; + bigPrimeQ = context->bigPrime2; + } + else { + bigPrimeP = context->bigPrime2; + bigPrimeQ = context->bigPrime1; + } + + /* Calculate the rest of the key components */ + if ((status = RSAParameters + (context->bigModulus, context->bigCoefficient, + context->bigExponentP, context->bigExponentQ, + context->bigPrivateExponent, context->bigPublicExponent, + bigPrimeP, bigPrimeQ, primeWords, modulusWords, surrenderContext)) != 0) + return (status); + + /* Copy key components into canonical buffers which are at the + end of the context. */ + *result = &context->result; + SetRSAKeyGenResult (*result, context, bigPrimeP, bigPrimeQ); + + return (0); +} + +/* Assumes ee, pp, qq are given, calculates other parameters. + Returns 0, AE_CANCEL. + */ +static int RSAParameters + (nn, cr, dp, dq, dd, ee, pp, qq, primeWords, modulusWords, surrenderContext) +UINT2 *nn, *cr, *dp, *dq, *dd, *ee, *pp, *qq; +unsigned int primeWords, modulusWords; +A_SURRENDER_CTX *surrenderContext; +{ + UINT2 t1[2 * MAX_RSA_PRIME_WORDS], t2[MAX_RSA_PRIME_WORDS], + t3[MAX_RSA_MODULUS_WORDS], u1[MAX_RSA_MODULUS_WORDS], + u3[MAX_RSA_MODULUS_WORDS], pm1[MAX_RSA_PRIME_WORDS], + qm1[MAX_RSA_PRIME_WORDS]; + int status; + + do { + /* N=P*Q */ + BigMpy (t1, pp, qq, primeWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + BigCopy (nn, t1, modulusWords); + + /* qm1=q-1 & pm1=p-1 */ + BigConst (t1, 1, primeWords); + BigSub (qm1, qq, t1, primeWords); + BigSub (pm1, pp, t1, primeWords); + + /* t3=1 */ + BigConst (t3, 1, modulusWords); + + /*t1=phi (N) */ + BigMpy (t1, pm1, qm1, primeWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* compute decryption exponent */ + BigPegcd (u1, dd, u3, ee, t1, modulusWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* calc DP=inv (E)[mod (P-1)] & DQ=inv (e)[mod (Q-1)] */ + BigPdiv (t1, dp, dd, pm1, modulusWords, primeWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + BigPdiv (t1, dq, dd, qm1, modulusWords, primeWords); + if ((status = CheckSurrender (surrenderContext)) != 0) + break; + + /* calc CR = (inv (Q)[modP]) */ + BigPegcd (t1, t2, cr, pp, qq, primeWords); + } while (0); + + T_memset ((POINTER)t1, 0, sizeof (t1)); + T_memset ((POINTER)t2, 0, sizeof (t2)); + T_memset ((POINTER)t3, 0, sizeof (t3)); + T_memset ((POINTER)u1, 0, sizeof (u1)); + T_memset ((POINTER)u3, 0, sizeof (u3)); + T_memset ((POINTER)pm1, 0, sizeof (pm1)); + T_memset ((POINTER)qm1, 0, sizeof (qm1)); + return (status); +} + +static void SetRSAKeyGenResult (result, context, bigPrimeP, bigPrimeQ) +A_PKCS_RSA_PRIVATE_KEY *result; +A_RSA_KEY_GEN_CTX *context; +UINT2 *bigPrimeP; +UINT2 *bigPrimeQ; +{ + unsigned int primeLen, modulusLen; + + modulusLen = result->modulus.len = result->publicExponent.len = + result->privateExponent.len = BITS_TO_LEN (context->modulusBits); + primeLen = result->prime[0].len = result->prime[1].len = + result->primeExponent[0].len = result->primeExponent[1].len = + result->coefficient.len = RSA_PRIME_LEN (context->modulusBits); + + result->modulus.data = context->resultBuffer; + result->publicExponent.data = result->modulus.data + modulusLen; + result->privateExponent.data = result->publicExponent.data + modulusLen; + result->prime[0].data = result->privateExponent.data + modulusLen; + result->prime[1].data = result->prime[0].data + primeLen; + result->primeExponent[0].data = result->prime[1].data + primeLen; + result->primeExponent[1].data = result->primeExponent[0].data + primeLen; + result->coefficient.data = result->primeExponent[1].data + primeLen; + + BigToCanonical + (result->modulus.data, modulusLen, context->bigModulus, + MAX_RSA_MODULUS_WORDS); + BigToCanonical + (result->publicExponent.data, modulusLen, + context->bigPublicExponent, MAX_RSA_MODULUS_WORDS); + BigToCanonical + (result->privateExponent.data, modulusLen, + context->bigPrivateExponent, MAX_RSA_MODULUS_WORDS); + BigToCanonical + (result->prime[0].data, primeLen, bigPrimeP, MAX_RSA_PRIME_WORDS); + BigToCanonical + (result->prime[1].data, primeLen, bigPrimeQ, MAX_RSA_PRIME_WORDS); + BigToCanonical + (result->primeExponent[0].data, primeLen, context->bigExponentP, + MAX_RSA_PRIME_WORDS); + BigToCanonical + (result->primeExponent[1].data, primeLen, context->bigExponentQ, + MAX_RSA_PRIME_WORDS); + BigToCanonical + (result->coefficient.data, primeLen, context->bigCoefficient, + MAX_RSA_PRIME_WORDS); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.h b/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.h new file mode 100644 index 0000000000..714bcea412 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/rsakeygn.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _RSAKEYGN_H_ +#define _RSAKEYGN_H_ 1 + +#include "bigmaxes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MIN_RSA_MODULUS_BITS 256 + +/* Need randomBlock to hold bytes for two UINT2 prime number arrays each, + of length primeWords = BITS_TO_WORDS (RSA_PRIME_BITS (modulusBits)). */ +#define A_RSA_KEY_GEN_RANDOM_BLOCK_LEN(modulusBits) \ + (4 * BITS_TO_WORDS (RSA_PRIME_BITS (modulusBits))) + +/* Note that the scratch area for the output integers is allocated + in the context after the RSA_KEY_GEN_CTX. + */ +typedef struct { + unsigned int modulusBits; + UINT2 bigModulus[MAX_RSA_MODULUS_WORDS]; + UINT2 bigPublicExponent[MAX_RSA_MODULUS_WORDS]; + UINT2 bigPrivateExponent[MAX_RSA_MODULUS_WORDS]; + UINT2 bigPrime1[MAX_RSA_PRIME_WORDS]; + UINT2 bigPrime2[MAX_RSA_PRIME_WORDS]; + UINT2 bigExponentP[MAX_RSA_PRIME_WORDS]; + UINT2 bigExponentQ[MAX_RSA_PRIME_WORDS]; + UINT2 bigCoefficient[MAX_RSA_PRIME_WORDS]; + A_PKCS_RSA_PRIVATE_KEY result; + unsigned char resultBuffer + [3 * BITS_TO_LEN (MAX_RSA_MODULUS_BITS) + + 5 * RSA_PRIME_LEN (MAX_RSA_MODULUS_BITS)]; +} A_RSA_KEY_GEN_CTX; + +int A_RSAKeyGenInit PROTO_LIST ((A_RSA_KEY_GEN_CTX *, A_RSA_KEY_GEN_PARAMS *)); +int A_RSAKeyGen PROTO_LIST + ((A_RSA_KEY_GEN_CTX *, A_PKCS_RSA_PRIVATE_KEY **, unsigned char *, + A_SURRENDER_CTX *)); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/usr/src/lib/libresolv2/common/dnssafe/seccbcd.c b/usr/src/lib/libresolv2/common/dnssafe/seccbcd.c new file mode 100644 index 0000000000..b88d6f9438 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/seccbcd.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "secrcbc.h" +#include "port_after.h" + +static void SecretCBCDecryptBlock PROTO_LIST + ((POINTER, unsigned char *, SECRET_CRYPT, unsigned char *, + unsigned char *)); + +/* On first call, it is assumed that *remainderLen is zero. + This assumes remainder buffer is at least 16 bytes is size. + Returns AE_OUTPUT_LEN, 0. + */ +int SecretCBCDecryptUpdate + (context, xorBlock, remainder, remainderLen, SecretDecrypt, output, + outputLen, maxOutputLen, input, inputLen) +POINTER context; +unsigned char *xorBlock; +unsigned char *remainder; +unsigned int *remainderLen; +SECRET_CRYPT SecretDecrypt; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +unsigned char *input; +unsigned int inputLen; +{ + unsigned int partialLen; + + if (*remainderLen + inputLen <= 16) { + /* Not enough to decrypt, just accumulate into remainder. + */ + *outputLen = 0; + T_memcpy ((POINTER)remainder + *remainderLen, (POINTER)input, inputLen); + *remainderLen += inputLen; + return (0); + } + + /* Fill up the rest of the remainder with bytes from input. + */ + T_memcpy + ((POINTER)remainder + *remainderLen, (POINTER)input, + partialLen = 16 - *remainderLen); + input += partialLen; + inputLen -= partialLen; + + /* remainder is full and inputLen is at least 1. Compute outputLen + as the size needed to keep remainder as full as possible. + */ + if ((*outputLen = 8 * ((inputLen + 7) / 8)) > maxOutputLen) + return (AE_OUTPUT_LEN); + + SecretCBCDecryptBlock + (context, xorBlock, SecretDecrypt, output, remainder); + output += 8; + + if (inputLen <= 8) { + /* Shift remaining input bytes into remainder */ + T_memmove ((POINTER)remainder, (POINTER)(remainder + 8), 8); + T_memcpy ((POINTER)(remainder + 8), (POINTER)input, inputLen); + *remainderLen = 8 + inputLen; + return (0); + } + + /* Decrypt the rest of the remainder. + */ + SecretCBCDecryptBlock + (context, xorBlock, SecretDecrypt, output, remainder + 8); + output += 8; + + /* Now decrypt the bulk of the input. + */ + while (inputLen > 16) { + SecretCBCDecryptBlock (context, xorBlock, SecretDecrypt, output, input); + output += 8; + input += 8; + inputLen -= 8; + } + + /* inputLen is now <= 16, so copy input to remainder. + */ + T_memcpy ((POINTER)remainder, (POINTER)input, inputLen); + *remainderLen = inputLen; + return (0); +} + +/* The caller must restart the context (setting remainderLen to zero). + Returns AE_INPUT_LEN, AE_OUTPUT_LEN, 0. + */ +int SecretCBCDecryptFinal + (context, xorBlock, remainder, remainderLen, SecretDecrypt, output, + outputLen, maxOutputLen) +POINTER context; +unsigned char *xorBlock; +unsigned char *remainder; +unsigned int remainderLen; +SECRET_CRYPT SecretDecrypt; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +{ + if ((*outputLen = remainderLen) == 0) + /* There was never any data. */ + return (0); + + if (remainderLen != 8 && remainderLen != 16) + return (AE_INPUT_LEN); + + if (*outputLen > maxOutputLen) + return (AE_OUTPUT_LEN); + + SecretCBCDecryptBlock + (context, xorBlock, SecretDecrypt, output, remainder); + output += 8; + if (remainderLen == 16) + SecretCBCDecryptBlock + (context, xorBlock, SecretDecrypt, output, remainder + 8); + return (0); +} + +static void SecretCBCDecryptBlock (context, xorBlock, SecretDecrypt, out, in) +POINTER context; +unsigned char *xorBlock; +SECRET_CRYPT SecretDecrypt; +unsigned char *out; +unsigned char *in; +{ + unsigned char tempBuffer[8]; + unsigned int i; + + /* Save input to be copied to the xor block. */ + T_memcpy ((POINTER)tempBuffer, (POINTER)in, 8); + (*SecretDecrypt) (context, out, in); + for (i = 0; i < 8; i++) + out[i] ^= xorBlock[i]; + T_memcpy ((POINTER)xorBlock, (POINTER)tempBuffer, 8); + + T_memset ((POINTER)tempBuffer, 0, sizeof (tempBuffer)); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/seccbce.c b/usr/src/lib/libresolv2/common/dnssafe/seccbce.c new file mode 100644 index 0000000000..e388bd9c4b --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/seccbce.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "secrcbc.h" +#include "port_after.h" + +/* On first call, it is assumed that *remainderLen is zero. + Returns AE_OUTPUT_LEN, 0. + */ +int SecretCBCEncryptUpdate + (context, xorBlock, remainder, remainderLen, SecretEncrypt, output, + outputLen, maxOutputLen, input, inputLen) +POINTER context; +unsigned char *xorBlock; +unsigned char *remainder; +unsigned int *remainderLen; +SECRET_CRYPT SecretEncrypt; +unsigned char *output; +unsigned int *outputLen; +unsigned int maxOutputLen; +unsigned char *input; +unsigned int inputLen; +{ + unsigned int partialLen, totalLen, i; + + totalLen = *remainderLen + inputLen; + + /* Output length will be all available 8-byte blocks. + */ + if ((*outputLen = 8 * (totalLen / 8)) > maxOutputLen) + return (AE_OUTPUT_LEN); + + if (totalLen < 8) { + /* Not enough to encrypt, just accumulate into remainder. + */ + T_memcpy + ((POINTER)remainder + *remainderLen, (POINTER)input, inputLen); + *remainderLen = totalLen; + + return (0); + } + + /* Accumulate enough bytes from input into remainder to encrypt the + remainder. + */ + T_memcpy + ((POINTER)remainder + *remainderLen, (POINTER)input, + partialLen = 8 - *remainderLen); + + for (i = 0; i < 8; i++) + output[i] = remainder[i] ^ xorBlock[i]; + /* Encrypt in place */ + (*SecretEncrypt) (context, output, output); + + T_memcpy ((POINTER)xorBlock, (POINTER)output, 8); + input += partialLen; + inputLen -= partialLen; + output += 8; + + /* Now encrypt the bulk of the input. + */ + while (inputLen >= 8) { + for (i = 0; i < 8; i++) + output[i] = *(input++) ^ xorBlock[i]; + /* Encrypt in place */ + (*SecretEncrypt) (context, output, output); + T_memcpy ((POINTER)xorBlock, (POINTER)output, 8); + output += 8; + inputLen -= 8; + } + + /* inputLen is now < 8, so copy input to remainder. + */ + T_memcpy ((POINTER)remainder, (POINTER)input, inputLen); + *remainderLen = inputLen; + + return (0); +} + +/* This just ensures that *remainderLen is zero. + The caller must restart the context (setting remainderLen to zero). + Returns AE_INPUT_LEN, 0. + */ +int SecretCBCEncryptFinal (remainderLen) +unsigned int remainderLen; +{ + if (remainderLen != 0) + return (AE_INPUT_LEN); + + return (0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/secrcbc.h b/usr/src/lib/libresolv2/common/dnssafe/secrcbc.h new file mode 100644 index 0000000000..3eab2d5fe6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/secrcbc.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1990, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _SECRCBC_H_ +#define _SECRCBC_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*SECRET_CRYPT) PROTO_LIST + ((POINTER, unsigned char *, unsigned char *)); + +int SecretCBCEncryptUpdate PROTO_LIST + ((POINTER, unsigned char *, unsigned char *, unsigned int *, SECRET_CRYPT, + unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int)); +int SecretCBCEncryptFinal PROTO_LIST ((unsigned int)); +int SecretCBCDecryptUpdate PROTO_LIST + ((POINTER, unsigned char *, unsigned char *, unsigned int *, SECRET_CRYPT, + unsigned char *, unsigned int *, unsigned int, unsigned char *, + unsigned int)); +int SecretCBCDecryptFinal PROTO_LIST + ((POINTER, unsigned char *, unsigned char *, unsigned int, SECRET_CRYPT, + unsigned char *, unsigned int *, unsigned int)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dnssafe/surrendr.c b/usr/src/lib/libresolv2/common/dnssafe/surrendr.c new file mode 100644 index 0000000000..d353ee8de6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/surrendr.c @@ -0,0 +1,33 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#include "port_before.h" +#include "global.h" +#include "algae.h" +#include "surrendr.h" +#include "port_after.h" + +/* Returns 0, AE_CANCEL. + */ +int CheckSurrender (surrenderContext) +A_SURRENDER_CTX *surrenderContext; +{ + if (surrenderContext == (A_SURRENDER_CTX *)NULL_PTR) + return (0); + + if ((*surrenderContext->Surrender) (surrenderContext->handle)) + return (AE_CANCEL); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/dnssafe/surrendr.h b/usr/src/lib/libresolv2/common/dnssafe/surrendr.h new file mode 100644 index 0000000000..4c18f1c543 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dnssafe/surrendr.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Copyright (C) RSA Data Security, Inc. created 1992, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + +#ifndef _SURRENDR_H_ +#define _SURRENDR_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +int CheckSurrender PROTO_LIST ((A_SURRENDER_CTX *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/usr/src/lib/libresolv2/common/dst/bsafe_link.c b/usr/src/lib/libresolv2/common/dst/bsafe_link.c new file mode 100644 index 0000000000..8a9fbdf312 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/bsafe_link.c @@ -0,0 +1,1128 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(BSAFE) || defined(DNSSAFE) +static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/bsafe_link.c,v 1.15 2001/09/25 04:50:28 marka Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +/* + * This file contains two components + * 1. Interface to the BSAFE library to allow compilation of Bind + * with TIS/DNSSEC when BSAFE is not available + * all calls to BSAFE are contained inside this file. + * 2. The glue to connvert RSA KEYS to and from external formats + */ +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <sys/param.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include "dst_internal.h" + +# ifdef __STDC__ +# define PROTOTYPES 1 +# else +# define PROTOTYPES 0 +# endif + +# ifdef BSAFE +# include <aglobal.h> +# include <bsafe.h> +# else +# include <global.h> +# include <bsafe2.h> +# include <bigmaxes.h> +# endif + +#include "port_after.h" + +typedef struct bsafekey { + char *rk_signer; + B_KEY_OBJ rk_Private_Key; + B_KEY_OBJ rk_Public_Key; +} RSA_Key; + +#ifndef MAX_RSA_MODULUS_BITS +#define MAX_RSA_MODULUS_BITS 4096 +#define MAX_RSA_MODULUS_LEN (MAX_RSA_MODULUS_BITS/8) +#define MAX_RSA_PRIME_LEN (MAX_RSA_MODULUS_LEN/2) +#endif + +#define NULL_SURRENDER (A_SURRENDER_CTX *)NULL_PTR +#define NULL_RANDOM (B_ALGORITHM_OBJ)NULL_PTR + +B_ALGORITHM_METHOD *CHOOSER[] = +{ + &AM_MD5, + &AM_MD5_RANDOM, + &AM_RSA_KEY_GEN, + &AM_RSA_ENCRYPT, + &AM_RSA_DECRYPT, + &AM_RSA_CRT_ENCRYPT, + &AM_RSA_CRT_DECRYPT, + (B_ALGORITHM_METHOD *) NULL_PTR +}; + +static u_char pkcs1[] = +{ + 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, + 0x04, 0x10 +}; + +static int dst_bsafe_md5digest(const int mode, B_ALGORITHM_OBJ *digest_obj, + const u_char *data, const int len, + u_char *digest, const int digest_len); + +static int dst_bsafe_key_size(RSA_Key *r_key); + +static int dst_bsafe_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); +static int dst_bsafe_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); +static int dst_bsafe_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_bsafe_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_bsafe_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len); +static int dst_bsafe_key_from_file_format(DST_KEY *d_key, + const char *buff, + const int buff_len); +static int dst_bsafe_generate_keypair(DST_KEY *key, int exp); +static int dst_bsafe_compare_keys(const DST_KEY *key1, const DST_KEY *key2); +static void *dst_bsafe_free_key_structure(void *key); + +/* + * dst_bsafe_init() Function to answer set up function pointers for + * BSAFE/DNSSAFE related functions + */ +int +dst_bsafe_init(void) +{ + if (dst_t_func[KEY_RSA] != NULL) + return (1); + dst_t_func[KEY_RSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_RSA] == NULL) + return (0); + memset(dst_t_func[KEY_RSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_RSA]->sign = dst_bsafe_sign; + dst_t_func[KEY_RSA]->verify = dst_bsafe_verify; + dst_t_func[KEY_RSA]->compare = dst_bsafe_compare_keys; + dst_t_func[KEY_RSA]->generate = dst_bsafe_generate_keypair; + dst_t_func[KEY_RSA]->destroy = dst_bsafe_free_key_structure; + dst_t_func[KEY_RSA]->from_dns_key = dst_bsafe_from_dns_key; + dst_t_func[KEY_RSA]->to_dns_key = dst_bsafe_to_dns_key; + dst_t_func[KEY_RSA]->from_file_fmt = dst_bsafe_key_from_file_format; + dst_t_func[KEY_RSA]->to_file_fmt = dst_bsafe_key_to_file_format; + return (1); +} + +/* + * dst_bsafe_sign + * Call BSAFE signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey structure holds context for a sign done in multiple calls. + * context the context to use for this computation + * data data to be signed. + * len length in bytes of data. + * priv_key key to use for signing. + * signature location to store signature. + * sig_len size in bytes of signature field. + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_bsafe_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + u_int sign_len = 0; + int status = 0; + B_ALGORITHM_OBJ *md5_ctx = NULL; + int w_bytes = 0; + u_int u_bytes = 0; + u_char work_area[NS_MD5RSA_MAX_SIZE]; + + if (mode & SIG_MODE_INIT) { + md5_ctx = (B_ALGORITHM_OBJ *) malloc(sizeof(B_ALGORITHM_OBJ)); + if ((status = B_CreateAlgorithmObject(md5_ctx))) + return (-1); + if ((status = B_SetAlgorithmInfo(*md5_ctx, AI_MD5, NULL))) + return (-1); + } + else if (context) + md5_ctx = (B_ALGORITHM_OBJ *) *context; + if (md5_ctx == NULL) + return (-1); + + w_bytes = dst_bsafe_md5digest(mode, md5_ctx, + data, len,work_area, sizeof(work_area)); + if (w_bytes < 0 || (mode & SIG_MODE_FINAL)) { + B_DestroyAlgorithmObject(md5_ctx); + SAFE_FREE(md5_ctx); + if (w_bytes < 0) + return (w_bytes); + } + + if (mode & SIG_MODE_FINAL) { + RSA_Key *key; + int ret = 0; + B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ) NULL_PTR; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (RSA_Key *) dkey->dk_KEY_struct; + if (key == NULL || key->rk_Private_Key == NULL) + return (-1); + + if ((status = B_CreateAlgorithmObject(&rsaEncryptor))) + return (SIGN_FINAL_FAILURE); + if ((status = B_SetAlgorithmInfo(rsaEncryptor, + AI_PKCS_RSAPrivate, + NULL_PTR))) + + ret = SIGN_FINAL_FAILURE; + if (ret == 0 && + (status = B_EncryptInit(rsaEncryptor, + key->rk_Private_Key, + CHOOSER, NULL_SURRENDER))) + ret = SIGN_FINAL_FAILURE; + if (ret == 0 && + (status = B_EncryptUpdate(rsaEncryptor, signature, + &u_bytes, sig_len, pkcs1, + sizeof(pkcs1), NULL_PTR, + NULL_SURRENDER))) + ret = SIGN_FINAL_FAILURE; + if (ret == 0 && + (status = B_EncryptUpdate(rsaEncryptor, signature, + &u_bytes, sig_len, work_area, + w_bytes, NULL_PTR, + NULL_SURRENDER))) + ret = SIGN_FINAL_FAILURE; + + if (ret == 0 && + (status = B_EncryptFinal(rsaEncryptor, signature + u_bytes, + &sign_len, sig_len - u_bytes, + NULL_PTR, NULL_SURRENDER))) + ret = SIGN_FINAL_FAILURE; + B_DestroyAlgorithmObject(&rsaEncryptor); + if (ret != 0) + return (ret); + + } + else { + if (context == NULL) + return (-1); + *context = (void *) md5_ctx; + } + return (sign_len); +} + + +/* + * Dst_bsafe_verify + * Calls BSAFE verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey structure holds context for a verify done in multiple calls. + * context the context to use for this computation + * data data signed. + * len length in bytes of data. + * pub_key key to use for verify. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_bsafe_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + B_ALGORITHM_OBJ *md5_ctx = NULL; + u_char digest[DST_HASH_SIZE]; + u_char work_area[DST_HASH_SIZE + sizeof(pkcs1)]; + int status = 0, w_bytes = 0; + u_int u_bytes = 0; + + if (mode & SIG_MODE_INIT) { + md5_ctx = (B_ALGORITHM_OBJ *) malloc(sizeof(B_ALGORITHM_OBJ)); + if ((status = B_CreateAlgorithmObject(md5_ctx))) + return (-1); + if ((status = B_SetAlgorithmInfo(*md5_ctx, AI_MD5, NULL))) + return (-1); + } + else if (context) + md5_ctx = (B_ALGORITHM_OBJ *) *context; + if (md5_ctx == NULL) + return (-1); + + w_bytes = dst_bsafe_md5digest(mode, md5_ctx, data, len, + digest, sizeof(digest)); + + if (w_bytes < 0 || (mode & SIG_MODE_FINAL)) { + B_DestroyAlgorithmObject(md5_ctx); + SAFE_FREE(md5_ctx); + if (w_bytes < 0) + return (-1); + } + + if (mode & SIG_MODE_FINAL) { + RSA_Key *key; + int ret = 0; + B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ) NULL_PTR; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (RSA_Key *) dkey->dk_KEY_struct; + if (key->rk_Public_Key == NULL) + return (-2); + if (rsaEncryptor == NULL_PTR) { + if ((status = B_CreateAlgorithmObject(&rsaEncryptor))) + ret = SIGN_FINAL_FAILURE; + if (ret == 0 && + (status = B_SetAlgorithmInfo(rsaEncryptor, + AI_PKCS_RSAPublic, + NULL_PTR))) + ret = VERIFY_FINAL_FAILURE; + } + if (ret == 0 && + (status = B_DecryptInit(rsaEncryptor, key->rk_Public_Key, + CHOOSER, NULL_SURRENDER))) + ret = VERIFY_FINAL_FAILURE; + + if (ret == 0 && + (status = B_DecryptUpdate(rsaEncryptor, work_area, + &u_bytes, 0, + (const u_char *) signature, + sig_len, + NULL_PTR, NULL_SURRENDER))) + ret = VERIFY_FINAL_FAILURE; + + if (ret == 0 && + (status = B_DecryptFinal(rsaEncryptor, work_area + u_bytes, + &u_bytes, + sizeof(work_area) - u_bytes, + NULL_PTR, NULL_SURRENDER))) + ret = VERIFY_FINAL_FAILURE; + B_DestroyAlgorithmObject(&rsaEncryptor); + /* skip PKCS#1 header in output from Decrypt function */ + if (ret) + return (ret); + ret = memcmp(digest, &work_area[sizeof(pkcs1)], w_bytes); + if (ret == 0) + return(0); + else + return(VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) md5_ctx; + } + return (0); +} + + +/* + * dst_bsafe_to_dns_key + * Converts key from RSA to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_bsafe_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + B_KEY_OBJ public; + A_RSA_KEY *pub = NULL; + u_char *op = out_str; + int n = 0; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + public = (B_KEY_OBJ)((RSA_Key *) in_key->dk_KEY_struct)->rk_Public_Key; + + n = B_GetKeyInfo((POINTER *) &pub, public, KI_RSAPublic); + if (n != 0) + return (-1); + + if (pub->exponent.len < 256) { /* key exponent is <= 2040 bits */ + if ((unsigned int)out_len < pub->exponent.len + 1) + return (-1); + *op++ = (u_int8_t) pub->exponent.len; + } else { /* key exponent is > 2040 bits */ + u_int16_t e = (u_int16_t) pub->exponent.len; + if ((unsigned int)out_len < pub->exponent.len + 3) + return (-1); + *op++ = 0; /* 3 byte length field */ + dst_s_put_int16(op, e); + op += sizeof(e); + n = 2; + } + n++; + memcpy(op, pub->exponent.data, pub->exponent.len); + op += pub->exponent.len; + n += pub->exponent.len; + + if ((unsigned int)(out_len - n) >= pub->modulus.len) { + /*copy exponent */ + memcpy(op, pub->modulus.data, pub->modulus.len); + n += pub->modulus.len; + } + else + n = -1; + return (n); +} + + +/* + * dst_bsafe_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_bsafe_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int bytes; + const u_char *key_ptr; + RSA_Key *r_key; + A_RSA_KEY *public; + + if (s_key == NULL || len < 0 || key == NULL) + return (0); + + r_key = (RSA_Key *) s_key->dk_KEY_struct; + if (r_key != NULL) /* do not reuse */ + s_key->dk_func->destroy(r_key); + + if (len == 0) + return (1); + + if ((r_key = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_bsafe_from_dns_key(): Memory allocation error 1")); + return (0); + } + memset(r_key, 0, sizeof(RSA_Key)); + s_key->dk_KEY_struct = (void *) r_key; + r_key->rk_signer = strdup(s_key->dk_key_name); + + if (B_CreateKeyObject(&r_key->rk_Public_Key) != 0) { + EREPORT(("dst_bsafe_from_dns_key(): Memory allocation error 3")); + s_key->dk_func->destroy(r_key); + return (0); + } + key_ptr = key; + bytes = (int) *key_ptr++; /* length of exponent in bytes */ + if (bytes == 0) { /* special case for long exponents */ + bytes = (int) dst_s_get_int16(key_ptr); + key_ptr += sizeof(u_int16_t); + } + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_bsafe_free_key_structure(r_key); + return (-1); + } + if ((public = (A_RSA_KEY *) malloc(sizeof(A_RSA_KEY))) == NULL) + return (0); + memset(public, 0, sizeof(*public)); + public->exponent.len = bytes; + if ((public->exponent.data = (u_char *) malloc(bytes)) == NULL) + return (0); + memcpy(public->exponent.data, key_ptr, bytes); + + key_ptr += bytes; /* beginning of modulus */ + bytes = len - bytes - 1; /* length of modulus */ + + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_bsafe_free_key_structure(r_key); + return (-1); + } + public->modulus.len = bytes; + if ((public->modulus.data = (u_char *) malloc(bytes)) == NULL) + return (0); + memcpy(public->modulus.data, key_ptr, bytes); + + B_SetKeyInfo(r_key->rk_Public_Key, KI_RSAPublic, (POINTER) public); + + s_key->dk_key_size = dst_bsafe_key_size(r_key); + SAFE_FREE(public->modulus.data); + SAFE_FREE(public->exponent.data); + SAFE_FREE(public); + return (1); +} + + +/* + * dst_bsafe_key_to_file_format + * Encodes an RSA Key into the portable file format. + * Parameters + * rkey RSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_bsafe_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len) +{ + char *bp; + int len, b_len; + B_KEY_OBJ rkey; + A_PKCS_RSA_PRIVATE_KEY *private = NULL; + + if (key == NULL || key->dk_KEY_struct == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + rkey = (B_KEY_OBJ)((RSA_Key *) key->dk_KEY_struct)->rk_Private_Key; + + B_GetKeyInfo((POINTER *) &private, rkey, KI_PKCS_RSAPrivate); + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_RSA, "RSA"); + + bp = strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Modulus: ", + private->modulus.data, + private->modulus.len)) <= 0) + return (-1); + + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PublicExponent: ", + private->publicExponent.data, + private->publicExponent.len)) <= 0) + return (-2); + + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PrivateExponent: ", + private->privateExponent.data, + private->privateExponent.len)) <= 0) + return (-3); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime1: ", + private->prime[0].data, + private->prime[0].len)) < 0) + return (-4); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime2: ", + private->prime[1].data, + private->prime[1].len)) < 0) + return (-5); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent1: ", + private->primeExponent[0].data, + private->primeExponent[0].len)) < 0) + return (-6); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent2: ", + private->primeExponent[1].data, + private->primeExponent[1].len)) < 0) + return (-7); + bp += len; + b_len -= len; + + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Coefficient: ", + private->coefficient.data, + private->coefficient.len)) < 0) + return (-8); + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/* + * dst_bsafe_key_from_file_format + * Converts contents of a private key file into a private RSA key. + * Parameters + * RSA_Key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_bsafe_key_from_file_format(DST_KEY *d_key, const char *buff, + const int buff_len) +{ + int status; + char s[RAW_KEY_SIZE]; + int len, s_len = sizeof(s); + const char *p = buff; + RSA_Key *b_key; + A_RSA_KEY *public; + A_PKCS_RSA_PRIVATE_KEY *private; + + if (d_key == NULL || buff == NULL || buff_len <= 0) + return (-1); + + b_key = (RSA_Key *) malloc(sizeof(RSA_Key)); + public = (A_RSA_KEY *) malloc(sizeof(A_RSA_KEY)); + private = (A_PKCS_RSA_PRIVATE_KEY *) + malloc(sizeof(A_PKCS_RSA_PRIVATE_KEY)); + if (b_key == NULL || private == NULL || public == NULL) { + SAFE_FREE(b_key); + SAFE_FREE(public); + SAFE_FREE(private); + return (-2); + } + memset(b_key, 0, sizeof(*b_key)); + memset(public, 0, sizeof(A_RSA_KEY)); + memset(private, 0, sizeof(A_PKCS_RSA_PRIVATE_KEY)); + d_key->dk_KEY_struct = (void *) b_key; + if (!dst_s_verify_str(&p, "Modulus: ")) + return (-3); + memset(s, 0, s_len); + if ((len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len)) == 0) + return (-4); + + private->modulus.len = len; + if ((private->modulus.data = malloc(len)) == NULL) + return (-5); + memcpy(private->modulus.data, s + s_len - len, len); + + while (*(++p) && p < (const char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "PublicExponent: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len))) + return (-5); + private->publicExponent.len = len; + if ((private->publicExponent.data = malloc(len)) + == NULL) + return (-6); + memcpy(private->publicExponent.data, + s + s_len - len, len); + } else if (dst_s_verify_str(&p, "PrivateExponent: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, s_len))) + return (-6); + private->privateExponent.len = len; + if ((private->privateExponent.data = malloc(len)) + == NULL) + return (-7); + memcpy(private->privateExponent.data, s + s_len - len, + len); + } else if (dst_s_verify_str(&p, "Prime1: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-7); + private->prime[0].len = len; + if ((private->prime[0].data = malloc(len)) == NULL) + return (-8); + memcpy(private->prime[0].data, + s + MAX_RSA_PRIME_LEN - len, len); + } else if (dst_s_verify_str(&p, "Prime2: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-8); + private->prime[1].len = len; + if ((private->prime[1].data = malloc(len)) == NULL) + return (-9); + memcpy(private->prime[1].data, + s + MAX_RSA_PRIME_LEN - len, len); + } else if (dst_s_verify_str(&p, "Exponent1: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-9); + private->primeExponent[0].len = len; + if ((private->primeExponent[0].data = malloc(len)) + == NULL) + return (-10); + memcpy(private->primeExponent[0].data, + s + MAX_RSA_PRIME_LEN - len, len); + } else if (dst_s_verify_str(&p, "Exponent2: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-10); + private->primeExponent[1].len = len; + if ((private->primeExponent[1].data = malloc(len)) + == NULL) + return (-11); + memcpy(private->primeExponent[1].data, + s + MAX_RSA_PRIME_LEN - len, len); + } else if (dst_s_verify_str(&p, "Coefficient: ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, (u_char *)s, + MAX_RSA_PRIME_LEN))) + return (-11); + private->coefficient.len = len; + if ((private->coefficient.data = malloc(len)) == NULL) + return (-12); + memcpy(private->coefficient.data, + s + MAX_RSA_PRIME_LEN - len, len); + } else { + EREPORT(("Decode_RSAKey(): Bad keyword %s\n", p)); + return (-12); + } + } /* while p */ + + public->modulus.len = private->modulus.len; + if ((public->modulus.data = (u_char *) malloc(public->modulus.len)) == + NULL) + return (-13); + memcpy(public->modulus.data, private->modulus.data, + private->modulus.len); + + public->exponent.len = private->publicExponent.len; + if ((public->exponent.data = (u_char *) malloc(public->exponent.len)) + == NULL) + return (-14); + memcpy(public->exponent.data, private->publicExponent.data, + private->publicExponent.len); + + status = B_CreateKeyObject(&(b_key->rk_Public_Key)); + if (status) + return (-1); + status = B_SetKeyInfo(b_key->rk_Public_Key, KI_RSAPublic, + (POINTER) public); + if (status) + return (-1); + + status = B_CreateKeyObject(&b_key->rk_Private_Key); + if (status) + return (-1); + status = B_SetKeyInfo(b_key->rk_Private_Key, KI_PKCS_RSAPrivate, + (POINTER) private); + if (status) + return (-1); + + d_key->dk_key_size = dst_bsafe_key_size(b_key); + + SAFE_FREE(private->modulus.data); + SAFE_FREE(private->publicExponent.data); + SAFE_FREE(private->privateExponent.data); + SAFE_FREE(private->prime[0].data); + SAFE_FREE(private->prime[1].data); + SAFE_FREE(private->primeExponent[0].data); + SAFE_FREE(private->primeExponent[1].data); + SAFE_FREE(private->coefficient.data); + SAFE_FREE(private); /* is this the right thing to do ??? XXXX */ + SAFE_FREE(public->modulus.data); + SAFE_FREE(public->exponent.data); + SAFE_FREE(public); + return (0); +} + + +/* + * dst_bsafe_free_key_structure + * Frees all dynamicly allocated structures in RSA_Key. + */ + +static void * +dst_bsafe_free_key_structure(void *key) +{ + RSA_Key *r_key = (RSA_Key *) key; + if (r_key != NULL) { + if (r_key->rk_Private_Key) + B_DestroyKeyObject(&r_key->rk_Private_Key); + if (r_key->rk_Public_Key) + B_DestroyKeyObject(&r_key->rk_Public_Key); + SAFE_FREE2(r_key->rk_signer, strlen(r_key->rk_signer)); + SAFE_FREE(r_key); + } + return (NULL); +} + + +/* + * dst_bsafe_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_bsafe_generate_keypair(DST_KEY *key, int exp) +{ + int i, status; + B_KEY_OBJ private; + B_KEY_OBJ public; + B_ALGORITHM_OBJ keypairGenerator; + B_ALGORITHM_OBJ randomAlgorithm; + A_RSA_KEY_GEN_PARAMS keygenParams; + char exponent[4]; + int exponent_len; + RSA_Key *rsa; + POINTER randomSeed = NULL_PTR; + int randomSeedLen; + A_RSA_KEY *pk_access = NULL; + + if (key == NULL || key->dk_alg != KEY_RSA) + return (0); + + if ((rsa = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_bsafe_generate_keypair: Memory allocation error 3")); + return (0); + } + memset(rsa, 0, sizeof(*rsa)); + + if ((status = B_CreateAlgorithmObject(&keypairGenerator)) != 0) + return (0); + + keygenParams.modulusBits = key->dk_key_size; + + /* exp = 0 or 1 are special (mean 3 or F4) */ + if (exp == 0) + exp = 3; + else if (exp == 1) + exp = 65537; + + /* Now encode the exponent and its length */ + if (exp < 256) { + exponent_len = 1; + exponent[0] = exp; + } else if (exp < (1 << 16)) { + exponent_len = 2; + exponent[0] = exp >> 8; + exponent[1] = exp; + } else if (exp < (1 << 24)) { + exponent_len = 3; + exponent[0] = exp >> 16; + exponent[1] = exp >> 8; + exponent[2] = exp; + } else { + exponent_len = 4; + exponent[0] = exp >> 24; + exponent[1] = exp >> 16; + exponent[2] = exp >> 8; + exponent[3] = exp; + } + + if ((keygenParams.publicExponent.data = (u_char *) malloc(exponent_len)) + == NULL) + return (0); + memcpy(keygenParams.publicExponent.data, exponent, exponent_len); + keygenParams.publicExponent.len = exponent_len; + if ((status = B_SetAlgorithmInfo + (keypairGenerator, AI_RSAKeyGen, (POINTER) &keygenParams)) != 0) + return (0); + + if ((status = B_GenerateInit(keypairGenerator, CHOOSER, + NULL_SURRENDER)) != 0) + return (0); + + if ((status = B_CreateKeyObject(&public)) != 0) + return (0); + + if ((status = B_CreateKeyObject(&private)) != 0) + return (0); + + if ((status = B_CreateAlgorithmObject(&randomAlgorithm)) != 0) + return (0); + + if ((status = B_SetAlgorithmInfo(randomAlgorithm, AI_MD5Random, + NULL_PTR)) + != 0) + return (0); + + if ((status = B_RandomInit(randomAlgorithm, CHOOSER, + NULL_SURRENDER)) != 0) + return (0); + + randomSeedLen = 256; + if ((randomSeed = malloc(randomSeedLen)) == NULL) + return (0); + if ((status = (randomSeed == NULL_PTR)) != 0) + return (0); + + /* gets random seed from /dev/random if present, generates random + * values if it is not present. + * first fill the buffer with semi random data + * then fill as much as possible with good random data + */ + i = dst_random(DST_RAND_SEMI, randomSeedLen, randomSeed); + i += dst_random(DST_RAND_KEY, randomSeedLen, randomSeed); + + if (i <= randomSeedLen) { + SAFE_FREE(rsa); + return(0); + } + if ((status = B_RandomUpdate(randomAlgorithm, randomSeed, + randomSeedLen, NULL_SURRENDER)) != 0) { + SAFE_FREE(rsa); + return (0); + } + SAFE_FREE2(randomSeed, randomSeedLen); + if ((status = B_GenerateKeypair(keypairGenerator, public, private, + randomAlgorithm, NULL_SURRENDER)) + != 0) { + SAFE_FREE(rsa); + return (0); + } + rsa->rk_signer = strdup(key->dk_key_name); + rsa->rk_Private_Key = private; + rsa->rk_Public_Key = public; + key->dk_KEY_struct = (void *) rsa; + + B_GetKeyInfo((POINTER *) &pk_access, public, KI_RSAPublic); + return (1); +} + + +/************************************************************************** + * dst_bsafe_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_s_bsafe_itemcmp(ITEM i1, ITEM i2) +{ + if (i1.len != i2.len || memcmp (i1.data, i2.data, i1.len)) + return (1); + else + return (0); +} + +static int +dst_bsafe_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + int status, s1 = 0, s2 = 0; + RSA_Key *rkey1 = (RSA_Key *) key1->dk_KEY_struct; + RSA_Key *rkey2 = (RSA_Key *) key2->dk_KEY_struct; + A_RSA_KEY *public1 = NULL, *public2 = NULL; + A_PKCS_RSA_PRIVATE_KEY *p1 = NULL, *p2 = NULL; + + if (rkey1 == NULL && rkey2 == NULL) + return(0); + else if (rkey1 == NULL) + return (1); + else if (rkey2 == NULL) + return (2); + + if (rkey1->rk_Public_Key) + B_GetKeyInfo((POINTER *) &public1, rkey1->rk_Public_Key, + KI_RSAPublic); + if (rkey2->rk_Public_Key) + B_GetKeyInfo((POINTER *) &public2, rkey2->rk_Public_Key, + KI_RSAPublic); + if (public1 == NULL && public2 == NULL) + return (0); + else if (public1 == NULL || public2 == NULL) + return (1); + + status = dst_s_bsafe_itemcmp(public1->modulus, public2->modulus) || + dst_s_bsafe_itemcmp(public1->exponent, public2->exponent); + + if (status) + return (status); + + if (rkey1->rk_Private_Key == NULL || rkey2->rk_Private_Key == NULL) + /* if neither or only one is private key consider identical */ + return (status); + if (rkey1->rk_Private_Key) + s1 = B_GetKeyInfo((POINTER *) &p1, rkey1->rk_Private_Key, + KI_PKCS_RSAPrivate); + if (rkey2->rk_Private_Key) + s2 = B_GetKeyInfo((POINTER *) &p2, rkey2->rk_Private_Key, + KI_PKCS_RSAPrivate); + if (p1 == NULL || p2 == NULL) + return (0); + + status = dst_s_bsafe_itemcmp(p1->modulus, p2->modulus) || + dst_s_bsafe_itemcmp (p1->publicExponent, + p2->publicExponent) || + dst_s_bsafe_itemcmp (p1->privateExponent, + p2->privateExponent) || + dst_s_bsafe_itemcmp (p1->prime[0], p2->prime[0]) || + dst_s_bsafe_itemcmp (p1->prime[1], p2->prime[1]) || + dst_s_bsafe_itemcmp (p1->primeExponent[0], + p2->primeExponent[0])|| + dst_s_bsafe_itemcmp (p1->primeExponent[1], + p2->primeExponent[1])|| + dst_s_bsafe_itemcmp (p1->coefficient, p2->coefficient); + return (status); +} + + +/* + * dst_bsafe_key_size() + * Function to calculate how the size of the key in bits + */ +static int +dst_bsafe_key_size(RSA_Key *r_key) +{ + int size; + A_PKCS_RSA_PRIVATE_KEY *private = NULL; + + if (r_key == NULL) + return (-1); + if (r_key->rk_Private_Key) + B_GetKeyInfo((POINTER *) &private, r_key->rk_Private_Key, + KI_PKCS_RSAPrivate); + else if (r_key->rk_Public_Key) + B_GetKeyInfo((POINTER *) &private, r_key->rk_Public_Key, + KI_RSAPublic); + size = dst_s_calculate_bits(private->modulus.data, + private->modulus.len * 8); + return (size); +} + +/* + * dst_bsafe_md5digest(): function to digest data using MD5 digest function + * if needed + */ +static int +dst_bsafe_md5digest(const int mode, B_ALGORITHM_OBJ *digest_obj, + const u_char *data, const int len, + u_char *digest, const int digest_len) +{ + int status = 0; + u_int work_size = 0; + + if (digest_obj == NULL || *digest_obj == NULL) { + printf("NO digest obj\n"); + exit(33); + } + + if ((mode & SIG_MODE_INIT) && + (status = B_DigestInit(*digest_obj, (B_KEY_OBJ) NULL, + CHOOSER, NULL_SURRENDER))) + return (SIGN_INIT_FAILURE); + + if ((mode & SIG_MODE_UPDATE) && data && (len > 0) && + (status = B_DigestUpdate(*digest_obj, data, len, NULL_SURRENDER))) + return (SIGN_UPDATE_FAILURE); + + if (mode & SIG_MODE_FINAL) { + if (digest == NULL || + (status = B_DigestFinal(*digest_obj, digest, &work_size, + digest_len, NULL_SURRENDER))) + return (SIGN_FINAL_FAILURE); + return (work_size); + } + return (0); +} + +/* + * just use the standard memory functions for bsafe + */ +void +T_free(POINTER block) +{ + free(block); +} + +POINTER +T_malloc(unsigned int len) +{ + return (malloc(len)); +} + +int +T_memcmp(CPOINTER firstBlock, CPOINTER secondBlock, unsigned int len) +{ + return (memcmp(firstBlock, secondBlock, len)); +} + +void +T_memcpy(POINTER output, CPOINTER input, unsigned int len) +{ + memcpy(output, input, len); +} + +void +T_memmove(POINTER output, POINTER input, unsigned int len) +{ + memmove(output, input, len); +} + +void +T_memset(POINTER output, int value, unsigned int len) +{ + memset(output, value, len); +} + +POINTER +T_realloc(POINTER block, unsigned int len) +{ + return (realloc(block, len)); +} + +#else /* BSAFE NOT available */ +int +dst_bsafe_init() +{ + return (0); +} +#endif /* BSAFE */ diff --git a/usr/src/lib/libresolv2/common/dst/cylink_link.c b/usr/src/lib/libresolv2/common/dst/cylink_link.c new file mode 100644 index 0000000000..d7ee3a8af4 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/cylink_link.c @@ -0,0 +1,677 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef CYLINK_DSS +static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/cylink_link.c,v 1.9 2001/05/29 05:48:05 marka Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +/* + * This file contains two components + * 1. Interface to the CYLINK library to allow compilation of Bind + * with TIS/DNSSEC when CYLINK is not available + * all calls to CYLINK are contained inside this file. + * 2. The glue to connvert DSA KEYS to and from external formats + */ +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <sys/param.h> +#include <sys/time.h> +#include <netinet/in.h> + +#include "dst_internal.h" +#include <toolkit.h> + +#include "port_after.h" + +typedef struct cylinkkey { + char *dk_signer; + uchar *dk_p; + uchar *dk_q; + uchar *dk_g; + uchar *dk_x; + uchar *dk_y; + ushort dk_p_bytes; +} DSA_Key; + +#define NULL_PRIV_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \ + k->dk_g == NULL || k->dk_x == NULL) +#define NULL_PUB_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \ + k->dk_g == NULL || k->dk_y == NULL) + +static int dst_cylink_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); + +static int dst_cylink_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_cylink_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len); +static int dst_cylink_key_from_file_format(DST_KEY *d_key, + const char *buff, + const int buff_len); +static void *dst_cylink_free_key_structure(void *key); + +static int dst_cylink_generate_keypair(DST_KEY *key, int exp); +static int dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2); + +static void *memcpyend(void *dest, const void *src, size_t n, size_t size); + +/* + * dst_cylink_init() Function to answer set up function pointers for + * CYLINK related functions + */ +int +dst_cylink_init() +{ + if (dst_t_func[KEY_DSA] != NULL) + return (1); + dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_DSA] == NULL) + return (0); + memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_DSA]->sign = dst_cylink_sign; + dst_t_func[KEY_DSA]->verify = dst_cylink_verify; + dst_t_func[KEY_DSA]->compare = dst_cylink_compare_keys; + dst_t_func[KEY_DSA]->generate = dst_cylink_generate_keypair; + dst_t_func[KEY_DSA]->destroy = dst_cylink_free_key_structure; + dst_t_func[KEY_DSA]->from_dns_key = dst_cylink_from_dns_key; + dst_t_func[KEY_DSA]->to_dns_key = dst_cylink_to_dns_key; + dst_t_func[KEY_DSA]->from_file_fmt = dst_cylink_key_from_file_format; + dst_t_func[KEY_DSA]->to_file_fmt = dst_cylink_key_to_file_format; + SetDataOrder(1); + return (1); +} + +/* + * dst_cylink_sign + * Call CYLINK signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * algobj structure holds context for a sign done in multiple calls. + * context the context to use for this computation + * data data to be signed. + * len length in bytes of data. + * priv_key key to use for signing. + * signature location to store signature. + * sig_len size in bytes of signature field. + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * N is 41 for DNS + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_cylink_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + int sign_len = 0; + int status; + SHA_context *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_context *) malloc(sizeof(SHA_context)); + else if (context) + ctx = (SHA_context *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHAInit(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + status = SHAUpdate(ctx, data, len); + if (status != SUCCESS) + return (SIGN_UPDATE_FAILURE); + } + if (mode & SIG_MODE_FINAL) { + DSA_Key *key; + uchar digest[SHA_LENGTH]; + uchar rand[SHA_LENGTH]; + uchar r[SHA_LENGTH], s[SHA_LENGTH]; + + if (signature == NULL || sig_len < 2 * SHA_LENGTH) + return (SIGN_FINAL_FAILURE); + if ((status = SHAFinal(ctx, digest)) != SUCCESS) + return (SIGN_FINAL_FAILURE); + SAFE_FREE(ctx); + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (DSA_Key *) dkey->dk_KEY_struct; + if (NULL_PRIV_KEY(key)) + return (-2); + dst_random(DST_RAND_STD, sizeof(rand), rand); + status = GenDSSSignature(key->dk_p_bytes, key->dk_p, + key->dk_q, key->dk_g, key->dk_x, + rand, r, s, digest); + if (status != SUCCESS) + return (SIGN_FINAL_FAILURE); + *signature = (dkey->dk_key_size - 512)/64; + sign_len = 1; + memcpy(signature + sign_len, r, SHA_LENGTH); + sign_len += SHA_LENGTH; + memcpy(signature + sign_len, s, SHA_LENGTH); + sign_len += SHA_LENGTH; + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/* + * Dst_cylink_verify + * Calls CYLINK verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey structure holds context for a verify done in multiple calls. + * context algorithm specific context for the current context processing + * data data signed. + * len length in bytes of data. + * pub_key key to use for verify. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_cylink_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + int status; + SHA_context *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_context *) malloc(sizeof(SHA_context)); + else if (context) + ctx = (SHA_context *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHAInit(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + status = SHAUpdate(ctx, data, len); + if (status != SUCCESS) + return (VERIFY_UPDATE_FAILURE); + } + if (mode & SIG_MODE_FINAL) { + DSA_Key *key; + uchar digest[SHA_LENGTH]; + uchar r[SHA_LENGTH], s[SHA_LENGTH]; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (DSA_Key *) dkey->dk_KEY_struct; + if (NULL_PUB_KEY(key)) + return (-2); + if (signature == NULL || sig_len != (2 * SHA_LENGTH +1)) + return (SIGN_FINAL_FAILURE); + status = SHAFinal(ctx, digest); + SAFE_FREE(ctx); + if (status != SUCCESS) + return (SIGN_FINAL_FAILURE); + if (((int)*signature) != ((key->dk_p_bytes -64)/8)) + return(VERIFY_FINAL_FAILURE); + + memcpy(r, signature +1, SHA_LENGTH); + memcpy(s, signature + SHA_LENGTH +1, SHA_LENGTH); + status = VerDSSSignature(key->dk_p_bytes, key->dk_p, + key->dk_q, key->dk_g, key->dk_y, + r, s, digest); + if (status != SUCCESS) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (0); +} + + +/* + * dst_cylink_to_dns_key + * Converts key from DSA to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + u_char *op = out_str; + int t; + DSA_Key *key; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + key = (DSA_Key *) in_key->dk_KEY_struct; + + t = (key->dk_p_bytes - 64) / 8; + + *op++ = t; + memcpy(op, key->dk_q, SHA_LENGTH); + op += SHA_LENGTH; + memcpy(op, key->dk_p, key->dk_p_bytes); + op += key->dk_p_bytes; + memcpy(op, key->dk_g, key->dk_p_bytes); + op += key->dk_p_bytes; + memcpy(op, key->dk_y, key->dk_p_bytes); + op += key->dk_p_bytes; + + return (op - out_str); +} + + +/* + * dst_cylink_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int t; + const u_char *key_ptr = key; + DSA_Key *d_key; + + if (s_key == NULL || len < 0 || key == NULL) + return (0); + + if (len == 0) /* process null key */ + return (1); + + if (key_ptr == NULL) + return (0); + t = (int) *key_ptr++; /* length of exponent in bytes */ + + if ((3 * (t * 8 + 64) + SHA_LENGTH + 1) != len) + return (0); + + if ((d_key = (DSA_Key *) malloc(sizeof(DSA_Key))) == NULL) { + EREPORT(("dst_cylink_from_dns_key(): Memory allocation error 1")); + return (0); + } + memset(d_key, 0, sizeof(DSA_Key)); + s_key->dk_KEY_struct = (void *) d_key; + d_key->dk_signer = strdup(s_key->dk_key_name); + d_key->dk_p_bytes = 64 + 8 * t; + + if ((d_key->dk_q = (uchar *) malloc(SHA_LENGTH)) == NULL) + return (0); + memcpy(d_key->dk_q, key_ptr, SHA_LENGTH); + key_ptr += SHA_LENGTH; + + if ((d_key->dk_p = (uchar *) malloc(d_key->dk_p_bytes)) == NULL) + return (0); + memcpy(d_key->dk_p, key_ptr, d_key->dk_p_bytes); + key_ptr += d_key->dk_p_bytes; + + if ((d_key->dk_g = (uchar *) malloc(d_key->dk_p_bytes)) == NULL) + return (0); + memcpy(d_key->dk_g, key_ptr, d_key->dk_p_bytes); + key_ptr += d_key->dk_p_bytes; + + if ((d_key->dk_y = (uchar *) malloc(d_key->dk_p_bytes)) == NULL) + return (0); + memcpy(d_key->dk_y, key_ptr, d_key->dk_p_bytes); + key_ptr += d_key->dk_p_bytes; + + s_key->dk_key_size = d_key->dk_p_bytes * 8; + return (1); +} + + +/************************************************************************** + * dst_cylink_key_to_file_format + * Encodes an DSA Key into the portable file format. + * Parameters + * key DSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_cylink_key_to_file_format(const DST_KEY *key, char *buff, + const int buff_len) +{ + char *bp; + int len, b_len; + DSA_Key *dkey; + u_char num[256]; /* More than long enough for DSA keys */ + + if (key == NULL || key->dk_KEY_struct == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + dkey = (DSA_Key *) key->dk_KEY_struct; + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_DSA, "DSA"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_p, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime(p): ", + num, dkey->dk_p_bytes)) <= 0) + return (-1); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_q, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Subprime(q): ", + num, SHA_LENGTH)) <= 0) + return (-2); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_g, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Base(g): ", + num, dkey->dk_p_bytes)) <= 0) + return (-3); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_x, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Private_value(x): ", + num, SHA_LENGTH)) <= 0) + return (-4); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->dk_y, dkey->dk_p_bytes); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Public_value(y): ", + num, dkey->dk_p_bytes)) <= 0) + return (-4); + + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/************************************************************************** + * dst_cylink_key_from_file_format + * Converts contents of a private key file into a private DSA key. + * Parameters + * DSA_Key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_cylink_key_from_file_format(DST_KEY *d_key, const char *buff, + const int buff_len) +{ + u_char s[DSS_LENGTH_MAX]; + int len, s_len = sizeof(s); + const char *p = buff; + DSA_Key *dsa_key; + + if (d_key == NULL || buff == NULL || buff_len <= 0) + return (-1); + + dsa_key = (DSA_Key *) malloc(sizeof(DSA_Key)); + if (dsa_key == NULL) { + return (-2); + } + memset(dsa_key, 0, sizeof(*dsa_key)); + d_key->dk_KEY_struct = (void *) dsa_key; + + if (!dst_s_verify_str(&p, "Prime(p): ")) + return (-3); + memset(s, 0, s_len); + if ((len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)) == 0) + return (-4); + dsa_key->dk_p_bytes = len; + if ((dsa_key->dk_p = malloc(len)) == NULL) + return (-5); + memcpy(dsa_key->dk_p, s + s_len - len, len); + + while (*++p && p < (const char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "Subprime(q): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-6); + if ((dsa_key->dk_q = malloc(SHA_LENGTH)) == NULL) + return (-7); + memcpyend(dsa_key->dk_q, s + s_len - len, len, + SHA_LENGTH); + } else if (dst_s_verify_str(&p, "Base(g): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-8); + if ((dsa_key->dk_g = malloc(dsa_key->dk_p_bytes)) + == NULL) + return (-9); + memcpyend(dsa_key->dk_g, s + s_len - len, len, + dsa_key->dk_p_bytes); + } else if (dst_s_verify_str(&p, "Private_value(x): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-10); + if ((dsa_key->dk_x = malloc(SHA_LENGTH)) == NULL) + return (-11); + memcpyend(dsa_key->dk_x, s + s_len - len, len, + SHA_LENGTH); + } else if (dst_s_verify_str(&p, "Public_value(y): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-10); + if ((dsa_key->dk_y = malloc(dsa_key->dk_p_bytes)) + == NULL) + return (-11); + memcpyend(dsa_key->dk_y, s + s_len - len, len, + dsa_key->dk_p_bytes); + } else { + EREPORT(("Decode_DSAKey(): Bad keyword %s\n", p)); + return (-12); + } + } /* while p */ + + d_key->dk_key_size = dsa_key->dk_p_bytes * 8; + + return (0); +} + + +/************************************************************************** + * dst_cylink_free_key_structure + * Frees all dynamicly allocated structures in DSA_Key. + */ + +static void * +dst_cylink_free_key_structure(void *key) +{ + DSA_Key *d_key = (DSA_Key *) key; + if (d_key != NULL) { + SAFE_FREE(d_key->dk_signer); + SAFE_FREE(d_key->dk_p); + SAFE_FREE(d_key->dk_q); + SAFE_FREE(d_key->dk_g); + SAFE_FREE(d_key->dk_x); + SAFE_FREE(d_key->dk_y); + SAFE_FREE(d_key); + } + return (NULL); +} + + +/************************************************************************** + * dst_cylink_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_cylink_generate_keypair(DST_KEY *key, int nothing) +{ + int status, n; + DSA_Key *dsa; + u_char rand[SHA_LENGTH]; + + UNUSED(nothing); + + if (key == NULL || key->dk_alg != KEY_DSA) + return (0); + + if ((dsa = (DSA_Key *) malloc(sizeof(DSA_Key))) == NULL) { + EREPORT(("dst_cylink_generate_keypair: Memory allocation error 3")); + return (0); + } + memset(dsa, 0, sizeof(*dsa)); + + dsa->dk_p_bytes = key->dk_key_size / 8; + dsa->dk_p = (uchar *) malloc(dsa->dk_p_bytes); + dsa->dk_q = (uchar *) malloc(SHA_LENGTH); + dsa->dk_g = (uchar *) malloc(dsa->dk_p_bytes); + dsa->dk_x = (uchar *) malloc(SHA_LENGTH); + dsa->dk_y = (uchar *) malloc(dsa->dk_p_bytes); + if (!dsa->dk_p || !dsa->dk_q || !dsa->dk_g || !dsa->dk_x || !dsa->dk_y) { + EREPORT(("dst_cylink_generate_keypair: Memory allocation error 4")); + return (0); + } + n = dst_random(DST_RAND_KEY, sizeof(rand), rand); + if (n != sizeof(rand)) + return (0); + status = GenDSSParameters(dsa->dk_p_bytes, dsa->dk_p, dsa->dk_q, + dsa->dk_g, rand, NULL); + if (status != SUCCESS) + return (0); + + status = GenDSSKey(dsa->dk_p_bytes, dsa->dk_p, dsa->dk_q, dsa->dk_g, + dsa->dk_x, dsa->dk_y, rand); + if (status != SUCCESS) + return (0); + memset(rand, 0, sizeof(rand)); + key->dk_KEY_struct = (void *) dsa; + return (1); +} + + +/* + * dst_cylink_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + int status; + DSA_Key *dkey1 = (DSA_Key *) key1->dk_KEY_struct; + DSA_Key *dkey2 = (DSA_Key *) key2->dk_KEY_struct; + + if (dkey1 == NULL && dkey2 == NULL) + return (0); + else if (dkey1 == NULL) + return (2); + else if (dkey2 == NULL) + return(1); + + if (dkey1->dk_p_bytes != dkey2->dk_p_bytes) + return (201); + status = memcmp(dkey1->dk_p, dkey2->dk_p, dkey1->dk_p_bytes) || + memcmp(dkey1->dk_q, dkey2->dk_q, SHA_LENGTH) || + memcmp(dkey1->dk_g, dkey2->dk_g, dkey1->dk_p_bytes) || + memcmp(dkey1->dk_y, dkey2->dk_y, dkey1->dk_p_bytes); + if (status) + return (status); + if (dkey1->dk_x || dkey2->dk_x) { + if (dkey1->dk_x == NULL || dkey2->dk_x == NULL) + return (202); + return (memcmp(dkey1->dk_x, dkey2->dk_x, dkey1->dk_p_bytes)); + } else + return (0); +} + +static void * +memcpyend(void *dest, const void *src, size_t n, size_t size) { + if (n < size) + memset(dest, 0, size - n); + memcpy((char *)dest + size - n, src, n); + return dest; +} + +#else +int +dst_cylink_init() +{ + return (0); +} +#endif /* CYLINK */ diff --git a/usr/src/lib/libresolv2/common/dst/dst_api.c b/usr/src/lib/libresolv2/common/dst/dst_api.c new file mode 100644 index 0000000000..f074b4a2a0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/dst_api.c @@ -0,0 +1,1100 @@ +#ifndef LINT +static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/dst_api.c,v 1.21 2002/06/28 06:58:19 marka Exp $"; +#endif + +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +/* + * This file contains the interface between the DST API and the crypto API. + * This is the only file that needs to be changed if the crypto system is + * changed. Exported functions are: + * void dst_init() Initialize the toolkit + * int dst_check_algorithm() Function to determines if alg is suppored. + * int dst_compare_keys() Function to compare two keys for equality. + * int dst_sign_data() Incremental signing routine. + * int dst_verify_data() Incremental verify routine. + * int dst_generate_key() Function to generate new KEY + * DST_KEY *dst_read_key() Function to retrieve private/public KEY. + * void dst_write_key() Function to write out a key. + * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST + * KEY structure. + * int dst_key_to_dnskey() Function to return a public key in DNS + * format binary + * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY + * int *dst_key_to_buffer() Writes out DST_KEY key matterial in buffer + * void dst_free_key() Releases all memory referenced by key structure + */ + +#include "port_before.h" +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <memory.h> +#include <ctype.h> +#include <time.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include "dst_internal.h" +#include "port_after.h" + +/* static variables */ +static int done_init = 0; +dst_func *dst_t_func[DST_MAX_ALGS]; +const char *key_file_fmt_str = "Private-key-format: v%s\nAlgorithm: %d (%s)\n"; +const char *dst_path = ""; + +/* internal I/O functions */ +static DST_KEY *dst_s_read_public_key(const char *in_name, + const u_int16_t in_id, int in_alg); +static int dst_s_read_private_key_file(char *name, DST_KEY *pk_key, + u_int16_t in_id, int in_alg); +static int dst_s_write_public_key(const DST_KEY *key); +static int dst_s_write_private_key(const DST_KEY *key); + +/* internal function to set up data structure */ +static DST_KEY *dst_s_get_key_struct(const char *name, const int alg, + const int flags, const int protocol, + const int bits); + +/* + * dst_init + * This function initializes the Digital Signature Toolkit. + * Right now, it just checks the DSTKEYPATH environment variable. + * Parameters + * none + * Returns + * none + */ +void +dst_init() +{ + char *s; + int len; + + if (done_init != 0) + return; + done_init = 1; + + s = getenv("DSTKEYPATH"); + len = 0; + if (s) { + struct stat statbuf; + + len = strlen(s); + if (len > PATH_MAX) { + EREPORT(("%s is longer than %d characters, ignoring\n", + s, PATH_MAX)); + } else if (stat(s, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) { + EREPORT(("%s is not a valid directory\n", s)); + } else { + char *tmp; + tmp = (char *) malloc(len + 2); + memcpy(tmp, s, len + 1); + if (tmp[strlen(tmp) - 1] != '/') { + tmp[strlen(tmp) + 1] = 0; + tmp[strlen(tmp)] = '/'; + } + dst_path = tmp; + } + } + memset(dst_t_func, 0, sizeof(dst_t_func)); + /* first one is selected */ + dst_bsafe_init(); + dst_rsaref_init(); + dst_hmac_md5_init(); + dst_eay_dss_init(); + dst_cylink_init(); +} + +/* + * dst_check_algorithm + * This function determines if the crypto system for the specified + * algorithm is present. + * Parameters + * alg 1 KEY_RSA + * 3 KEY_DSA + * 157 KEY_HMAC_MD5 + * future algorithms TBD and registered with IANA. + * Returns + * 1 - The algorithm is available. + * 0 - The algorithm is not available. + */ +int +dst_check_algorithm(const int alg) +{ + return (dst_t_func[alg] != NULL); +} + +/* + * dst_s_get_key_struct + * This function allocates key structure and fills in some of the + * fields of the structure. + * Parameters: + * name: the name of the key + * alg: the algorithm number + * flags: the dns flags of the key + * protocol: the dns protocol of the key + * bits: the size of the key + * Returns: + * NULL if error + * valid pointer otherwise + */ +static DST_KEY * +dst_s_get_key_struct(const char *name, const int alg, const int flags, + const int protocol, const int bits) +{ + DST_KEY *new_key = NULL; + + if (dst_check_algorithm(alg)) /* make sure alg is available */ + new_key = (DST_KEY *) malloc(sizeof(*new_key)); + if (new_key == NULL) + return (NULL); + + memset(new_key, 0, sizeof(*new_key)); + new_key->dk_key_name = strdup(name); + new_key->dk_alg = alg; + new_key->dk_flags = flags; + new_key->dk_proto = protocol; + new_key->dk_KEY_struct = NULL; + new_key->dk_key_size = bits; + new_key->dk_func = dst_t_func[alg]; + return (new_key); +} + +/* + * dst_compare_keys + * Compares two keys for equality. + * Parameters + * key1, key2 Two keys to be compared. + * Returns + * 0 The keys are equal. + * non-zero The keys are not equal. + */ + +int +dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + if (key1 == key2) + return (0); + if (key1 == NULL || key2 == NULL) + return (4); + if (key1->dk_alg != key2->dk_alg) + return (1); + if (key1->dk_key_size != key2->dk_key_size) + return (2); + if (key1->dk_id != key2->dk_id) + return (3); + return (key1->dk_func->compare(key1, key2)); +} + + +/* + * dst_sign_data + * An incremental signing function. Data is signed in steps. + * First the context must be initialized (SIG_MODE_INIT). + * Then data is hashed (SIG_MODE_UPDATE). Finally the signature + * itself is created (SIG_MODE_FINAL). This function can be called + * once with INIT, UPDATE and FINAL modes all set, or it can be + + * called separately with a different mode set for each step. The + * UPDATE step can be repeated. + * Parameters + * mode A bit mask used to specify operation(s) to be performed. + * SIG_MODE_INIT 1 Initialize digest + * SIG_MODE_UPDATE 2 Add data to digest + * SIG_MODE_FINAL 4 Generate signature + * from signature + * SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL + * data Data to be signed. + * len The length in bytes of data to be signed. + * in_key Contains a private key to sign with. + * KEY structures should be handled (created, converted, + * compared, stored, freed) by the DST. + * signature + * The location to which the signature will be written. + * sig_len Length of the signature field in bytes. + * Return + * 0 Successfull INIT or Update operation + * >0 success FINAL (sign) operation + * <0 failure + */ + +int +dst_sign_data(const int mode, DST_KEY *in_key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + DUMP(data, mode, len, "dst_sign_data()"); + + if (mode & SIG_MODE_FINAL && + (in_key->dk_KEY_struct == NULL || signature == NULL)) + return (MISSING_KEY_OR_SIGNATURE); + + if (in_key->dk_func && in_key->dk_func->sign) + return (in_key->dk_func->sign(mode, in_key, context, data, len, + signature, sig_len)); + return (UNKNOWN_KEYALG); +} + + +/* + * dst_verify_data + * An incremental verify function. Data is verified in steps. + * First the context must be initialized (SIG_MODE_INIT). + * Then data is hashed (SIG_MODE_UPDATE). Finally the signature + * is verified (SIG_MODE_FINAL). This function can be called + * once with INIT, UPDATE and FINAL modes all set, or it can be + * called separately with a different mode set for each step. The + * UPDATE step can be repeated. + * Parameters + * mode Operations to perform this time. + * SIG_MODE_INIT 1 Initialize digest + * SIG_MODE_UPDATE 2 add data to digest + * SIG_MODE_FINAL 4 verify signature + * SIG_MODE_ALL + * (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL) + * data Data to pass through the hash function. + * len Length of the data in bytes. + * in_key Key for verification. + * signature Location of signature. + * sig_len Length of the signature in bytes. + * Returns + * 0 Verify success + * Non-Zero Verify Failure + */ + +int +dst_verify_data(const int mode, DST_KEY *in_key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + DUMP(data, mode, len, "dst_verify_data()"); + if (mode & SIG_MODE_FINAL && + (in_key->dk_KEY_struct == NULL || signature == NULL)) + return (MISSING_KEY_OR_SIGNATURE); + + if (in_key->dk_func == NULL || in_key->dk_func->verify == NULL) + return (UNSUPPORTED_KEYALG); + return (in_key->dk_func->verify(mode, in_key, context, data, len, + signature, sig_len)); +} + + +/* + * dst_read_private_key + * Access a private key. First the list of private keys that have + * already been read in is searched, then the key accessed on disk. + * If the private key can be found, it is returned. If the key cannot + * be found, a null pointer is returned. The options specify required + * key characteristics. If the private key requested does not have + * these characteristics, it will not be read. + * Parameters + * in_keyname The private key name. + * in_id The id of the private key. + * options DST_FORCE_READ Read from disk - don't use a previously + * read key. + * DST_CAN_SIGN The key must be useable for signing. + * DST_NO_AUTHEN The key must be useable for authentication. + * DST_STANDARD Return any key + * Returns + * NULL If there is no key found in the current directory or + * this key has not been loaded before. + * !NULL Success - KEY structure returned. + */ + +DST_KEY * +dst_read_key(const char *in_keyname, const u_int16_t in_id, + const int in_alg, const int type) +{ + char keyname[PATH_MAX]; + DST_KEY *dg_key = NULL, *pubkey = NULL; + + if (!dst_check_algorithm(in_alg)) { /* make sure alg is available */ + EREPORT(("dst_read_private_key(): Algorithm %d not suppored\n", + in_alg)); + return (NULL); + } + if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0) + return (NULL); + if (in_keyname == NULL) { + EREPORT(("dst_read_private_key(): Null key name passed in\n")); + return (NULL); + } else + strcpy(keyname, in_keyname); + + /* before I read in the public key, check if it is allowed to sign */ + if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL) + return (NULL); + + if (type == DST_PUBLIC) + return pubkey; + + if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg, + pubkey->dk_flags, pubkey->dk_proto, + 0))) + return (dg_key); + /* Fill in private key and some fields in the general key structure */ + if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id, + pubkey->dk_alg) == 0) + dg_key = dst_free_key(dg_key); + + pubkey = dst_free_key(pubkey); + return (dg_key); +} + +int +dst_write_key(const DST_KEY *key, const int type) +{ + int pub = 0, priv = 0; + + if (key == NULL) + return (0); + if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */ + EREPORT(("dst_write_key(): Algorithm %d not suppored\n", + key->dk_alg)); + return (UNSUPPORTED_KEYALG); + } + if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0) + return (0); + + if (type & DST_PUBLIC) + if ((pub = dst_s_write_public_key(key)) < 0) + return (pub); + if (type & DST_PRIVATE) + if ((priv = dst_s_write_private_key(key)) < 0) + return (priv); + return (priv+pub); +} + +/* + * dst_write_private_key + * Write a private key to disk. The filename will be of the form: + * K<key->dk_name>+<key->dk_alg>+<key->dk_id>.<private key suffix>. + * If there is already a file with this name, an error is returned. + * + * Parameters + * key A DST managed key structure that contains + * all information needed about a key. + * Return + * >= 0 Correct behavior. Returns length of encoded key value + * written to disk. + * < 0 error. + */ + +static int +dst_s_write_private_key(const DST_KEY *key) +{ + u_char encoded_block[RAW_KEY_SIZE]; + char file[PATH_MAX]; + int len; + FILE *fp; + + /* First encode the key into the portable key format */ + if (key == NULL) + return (-1); + if (key->dk_KEY_struct == NULL) + return (0); /* null key has no private key */ + + if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) { + EREPORT(("dst_write_private_key(): Unsupported operation %d\n", + key->dk_alg)); + return (-5); + } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block, + sizeof(encoded_block))) <= 0) { + EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len)); + return (-8); + } + /* Now I can create the file I want to use */ + dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg, + PRIVATE_KEY, PATH_MAX); + + /* Do not overwrite an existing file */ + if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) { + int nn; + if ((nn = fwrite(encoded_block, 1, len, fp)) != len) { + EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n", + file, len, nn, errno)); + return (-5); + } + fclose(fp); + } else { + EREPORT(("dst_write_private_key(): Can not create file %s\n" + ,file)); + return (-6); + } + memset(encoded_block, 0, len); + return (len); +} + +/* +* + * dst_read_public_key + * Read a public key from disk and store in a DST key structure. + * Parameters + * in_name K<in_name><in_id>.<public key suffix> is the + * filename of the key file to be read. + * Returns + * NULL If the key does not exist or no name is supplied. + * NON-NULL Initialized key structure if the key exists. + */ + +static DST_KEY * +dst_s_read_public_key(const char *in_name, const u_int16_t in_id, int in_alg) +{ + int flags, proto, alg, len, dlen; + int c; + char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace; + u_char deckey[RAW_KEY_SIZE]; + FILE *fp; + + if (in_name == NULL) { + EREPORT(("dst_read_public_key(): No key name given\n")); + return (NULL); + } + if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY, + PATH_MAX) == -1) { + EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n", + in_name, in_id, PUBLIC_KEY)); + return (NULL); + } + /* + * Open the file and read it's formatted contents up to key + * File format: + * domain.name [ttl] [IN] KEY <flags> <protocol> <algorithm> <key> + * flags, proto, alg stored as decimal (or hex numbers FIXME). + * (FIXME: handle parentheses for line continuation.) + */ + if ((fp = dst_s_fopen(name, "r", 0)) == NULL) { + EREPORT(("dst_read_public_key(): Public Key not found %s\n", + name)); + return (NULL); + } + /* Skip domain name, which ends at first blank */ + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + /* Skip blank to get to next field */ + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + + /* Skip optional TTL -- if initial digit, skip whole word. */ + if (isdigit(c)) { + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + } + /* Skip optional "IN" */ + if (c == 'I' || c == 'i') { + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + } + /* Locate and skip "KEY" */ + if (c != 'K' && c != 'k') { + EREPORT(("\"KEY\" doesn't appear in file: %s", name)); + return NULL; + } + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + ungetc(c, fp); /* return the charcter to the input field */ + /* Handle hex!! FIXME. */ + + if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) { + EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n" + ,name)); + return (NULL); + } + /* read in the key string */ + fgets(enckey, sizeof(enckey), fp); + + /* If we aren't at end-of-file, something is wrong. */ + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + if (!feof(fp)) { + EREPORT(("Key too long in file: %s", name)); + return NULL; + } + fclose(fp); + + if ((len = strlen(enckey)) <= 0) + return (NULL); + + /* discard \n */ + enckey[--len] = '\0'; + + /* remove leading spaces */ + for (notspace = (char *) enckey; isspace((*notspace)&0xff); len--) + notspace++; + + dlen = b64_pton(notspace, deckey, sizeof(deckey)); + if (dlen < 0) { + EREPORT(("dst_read_public_key: bad return from b64_pton = %d", + dlen)); + return (NULL); + } + /* store key and info in a key structure that is returned */ +/* return dst_store_public_key(in_name, alg, proto, 666, flags, deckey, + dlen);*/ + return dst_buffer_to_key(in_name, alg, flags, proto, deckey, dlen); +} + + +/* + * dst_write_public_key + * Write a key to disk in DNS format. + * Parameters + * key Pointer to a DST key structure. + * Returns + * 0 Failure + * 1 Success + */ + +static int +dst_s_write_public_key(const DST_KEY *key) +{ + FILE *fp; + char filename[PATH_MAX]; + u_char out_key[RAW_KEY_SIZE]; + char enc_key[RAW_KEY_SIZE]; + int len = 0; + int mode; + + memset(out_key, 0, sizeof(out_key)); + if (key == NULL) { + EREPORT(("dst_write_public_key(): No key specified \n")); + return (0); + } else if ((len = dst_key_to_dnskey(key, out_key, sizeof(out_key)))< 0) + return (0); + + /* Make the filename */ + if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id, + key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) { + EREPORT(("dst_write_public_key(): Cannot make filename from %s, %d, and %s\n", + key->dk_key_name, key->dk_id, PUBLIC_KEY)); + return (0); + } + /* XXX in general this should be a check for symmetric keys */ + mode = (key->dk_alg == KEY_HMAC_MD5) ? 0600 : 0644; + /* create public key file */ + if ((fp = dst_s_fopen(filename, "w+", mode)) == NULL) { + EREPORT(("DST_write_public_key: open of file:%s failed (errno=%d)\n", + filename, errno)); + return (0); + } + /*write out key first base64 the key data */ + if (key->dk_flags & DST_EXTEND_FLAG) + b64_ntop(&out_key[6], len - 6, enc_key, sizeof(enc_key)); + else + b64_ntop(&out_key[4], len - 4, enc_key, sizeof(enc_key)); + fprintf(fp, "%s IN KEY %d %d %d %s\n", + key->dk_key_name, + key->dk_flags, key->dk_proto, key->dk_alg, enc_key); + fclose(fp); + return (1); +} + + +/* + * dst_dnskey_to_public_key + * This function converts the contents of a DNS KEY RR into a DST + * key structure. + * Paramters + * len Length of the RDATA of the KEY RR RDATA + * rdata A pointer to the the KEY RR RDATA. + * in_name Key name to be stored in key structure. + * Returns + * NULL Failure + * NON-NULL Success. Pointer to key structure. + * Caller's responsibility to free() it. + */ + +DST_KEY * +dst_dnskey_to_key(const char *in_name, const u_char *rdata, const int len) +{ + DST_KEY *key_st; + int alg ; + int start = DST_KEY_START; + + if (rdata == NULL || len <= DST_KEY_ALG) /* no data */ + return (NULL); + alg = (u_int8_t) rdata[DST_KEY_ALG]; + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_dnskey_to_key(): Algorithm %d not suppored\n", + alg)); + return (NULL); + } + if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL) + return (NULL); + + if (in_name == NULL) + return (NULL); + key_st->dk_id = dst_s_dns_key_id(rdata, len); + key_st->dk_flags = dst_s_get_int16(rdata); + key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT]; + if (key_st->dk_flags & DST_EXTEND_FLAG) { + u_int32_t ext_flags; + ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]); + key_st->dk_flags = key_st->dk_flags | (ext_flags << 16); + start += 2; + } + /* + * now point to the begining of the data representing the encoding + * of the key + */ + if (key_st->dk_func && key_st->dk_func->from_dns_key) { + if (key_st->dk_func->from_dns_key(key_st, &rdata[start], + len - start) > 0) + return (key_st); + } else + EREPORT(("dst_dnskey_to_public_key(): unsuppored alg %d\n", + alg)); + + SAFE_FREE(key_st); + return (key_st); +} + + +/* + * dst_public_key_to_dnskey + * Function to encode a public key into DNS KEY wire format + * Parameters + * key Key structure to encode. + * out_storage Location to write the encoded key to. + * out_len Size of the output array. + * Returns + * <0 Failure + * >=0 Number of bytes written to out_storage + */ + +int +dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, + const int out_len) +{ + u_int16_t val; + int loc = 0; + int enc_len = 0; + if (key == NULL) + return (-1); + + if (!dst_check_algorithm(key->dk_alg)) { /* make sure alg is available */ + EREPORT(("dst_key_to_dnskey(): Algorithm %d not suppored\n", + key->dk_alg)); + return (UNSUPPORTED_KEYALG); + } + memset(out_storage, 0, out_len); + val = (u_int16_t)(key->dk_flags & 0xffff); + dst_s_put_int16(out_storage, val); + loc += 2; + + out_storage[loc++] = (u_char) key->dk_proto; + out_storage[loc++] = (u_char) key->dk_alg; + + if (key->dk_flags > 0xffff) { /* Extended flags */ + val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); + dst_s_put_int16(&out_storage[loc], val); + loc += 2; + } + if (key->dk_KEY_struct == NULL) + return (loc); + if (key->dk_func && key->dk_func->to_dns_key) { + enc_len = key->dk_func->to_dns_key(key, + (u_char *) &out_storage[loc], + out_len - loc); + if (enc_len > 0) + return (enc_len + loc); + else + return (-1); + } else + EREPORT(("dst_key_to_dnskey(): Unsupported ALG %d\n", + key->dk_alg)); + return (-1); +} + + +/* + * dst_buffer_to_key + * Function to encode a string of raw data into a DST key + * Parameters + * alg The algorithm (HMAC only) + * key A pointer to the data + * keylen The length of the data + * Returns + * NULL an error occurred + * NON-NULL the DST key + */ +DST_KEY * +dst_buffer_to_key(const char *key_name, /* name of the key */ + const int alg, /* algorithm */ + const int flags, /* dns flags */ + const int protocol, /* dns protocol */ + const u_char *key_buf, /* key in dns wire fmt */ + const int key_len) /* size of key */ +{ + + DST_KEY *dkey = NULL; + int dnslen; + u_char dns[2048]; + + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_buffer_to_key(): Algorithm %d not suppored\n", alg)); + return (NULL); + } + + dkey = dst_s_get_key_struct(key_name, alg, flags, + protocol, -1); + + if (dkey == NULL) + return (NULL); + if (dkey->dk_func == NULL || dkey->dk_func->from_dns_key == NULL) + return NULL; + + if (dkey->dk_func->from_dns_key(dkey, key_buf, key_len) < 0) { + EREPORT(("dst_buffer_to_key(): dst_buffer_to_hmac failed\n")); + return (dst_free_key(dkey)); + } + + dnslen = dst_key_to_dnskey(dkey, dns, sizeof(dns)); + dkey->dk_id = dst_s_dns_key_id(dns, dnslen); + return (dkey); +} + +int +dst_key_to_buffer(DST_KEY *key, u_char *out_buff, int buf_len) +{ + int len; + /* this function will extrac the secret of HMAC into a buffer */ + if (key == NULL) + return (0); + if (key->dk_func != NULL && key->dk_func->to_dns_key != NULL) { + len = key->dk_func->to_dns_key(key, out_buff, buf_len); + if (len < 0) + return (0); + return (len); + } + return (0); +} + + +/* + * dst_s_read_private_key_file + * Function reads in private key from a file. + * Fills out the KEY structure. + * Parameters + * name Name of the key to be read. + * pk_key Structure that the key is returned in. + * in_id Key identifier (tag) + * Return + * 1 if everthing works + * 0 if there is any problem + */ + +static int +dst_s_read_private_key_file(char *name, DST_KEY *pk_key, u_int16_t in_id, + int in_alg) +{ + int cnt, alg, len, major, minor, file_major, file_minor; + int ret, id; + char filename[PATH_MAX]; + u_char in_buff[RAW_KEY_SIZE], *p; + FILE *fp; + int dnslen; + u_char dns[2048]; + + if (name == NULL || pk_key == NULL) { + EREPORT(("dst_read_private_key_file(): No key name given\n")); + return (0); + } + /* Make the filename */ + if (dst_s_build_filename(filename, name, in_id, in_alg, PRIVATE_KEY, + PATH_MAX) == -1) { + EREPORT(("dst_read_private_key(): Cannot make filename from %s, %d, and %s\n", + name, in_id, PRIVATE_KEY)); + return (0); + } + /* first check if we can find the key file */ + if ((fp = dst_s_fopen(filename, "r", 0)) == NULL) { + EREPORT(("dst_s_read_private_key_file: Could not open file %s in directory %s\n", + filename, dst_path[0] ? dst_path : + (char *) getcwd(NULL, PATH_MAX - 1))); + return (0); + } + /* now read the header info from the file */ + if ((cnt = fread(in_buff, 1, sizeof(in_buff), fp)) < 5) { + fclose(fp); + EREPORT(("dst_s_read_private_key_file: error reading file %s (empty file)\n", + filename)); + return (0); + } + /* decrypt key */ + fclose(fp); + if (memcmp(in_buff, "Private-key-format: v", 20) != 0) + goto fail; + len = cnt; + p = in_buff; + + if (!dst_s_verify_str((const char **) &p, "Private-key-format: v")) { + EREPORT(("dst_s_read_private_key_file(): Not a Key file/Decrypt failed %s\n", name)); + goto fail; + } + /* read in file format */ + sscanf((char *)p, "%d.%d", &file_major, &file_minor); + sscanf(KEY_FILE_FORMAT, "%d.%d", &major, &minor); + if (file_major < 1) { + EREPORT(("dst_s_read_private_key_file(): Unknown keyfile %d.%d version for %s\n", + file_major, file_minor, name)); + goto fail; + } else if (file_major > major || file_minor > minor) + EREPORT(( + "dst_s_read_private_key_file(): Keyfile %s version higher than mine %d.%d MAY FAIL\n", + name, file_major, file_minor)); + + while (*p++ != '\n') ; /* skip to end of line */ + + if (!dst_s_verify_str((const char **) &p, "Algorithm: ")) + goto fail; + + if (sscanf((char *)p, "%d", &alg) != 1) + goto fail; + while (*p++ != '\n') ; /* skip to end of line */ + + if (pk_key->dk_key_name && !strcmp(pk_key->dk_key_name, name)) + SAFE_FREE2(pk_key->dk_key_name, strlen(pk_key->dk_key_name)); + pk_key->dk_key_name = (char *) strdup(name); + + /* allocate and fill in key structure */ + if (pk_key->dk_func == NULL || pk_key->dk_func->from_file_fmt == NULL) + goto fail; + + ret = pk_key->dk_func->from_file_fmt(pk_key, (char *)p, &in_buff[len] - p); + if (ret < 0) + goto fail; + + dnslen = dst_key_to_dnskey(pk_key, dns, sizeof(dns)); + id = dst_s_dns_key_id(dns, dnslen); + + /* Make sure the actual key tag matches the input tag used in the filename + */ + if (id != in_id) { + EREPORT(("dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n", id, in_id)); + goto fail; + } + pk_key->dk_id = (u_int16_t) id; + pk_key->dk_alg = alg; + memset(in_buff, 0, cnt); + return (1); + + fail: + memset(in_buff, 0, cnt); + return (0); +} + + +/* + * dst_generate_key + * Generate and store a public/private keypair. + * Keys will be stored in formatted files. + * Parameters + * name Name of the new key. Used to create key files + * K<name>+<alg>+<id>.public and K<name>+<alg>+<id>.private. + * bits Size of the new key in bits. + * exp What exponent to use: + * 0 use exponent 3 + * non-zero use Fermant4 + * flags The default value of the DNS Key flags. + * The DNS Key RR Flag field is defined in RFC 2065, + * section 3.3. The field has 16 bits. + * protocol + * Default value of the DNS Key protocol field. + * The DNS Key protocol field is defined in RFC 2065, + * section 3.4. The field has 8 bits. + * alg What algorithm to use. Currently defined: + * KEY_RSA 1 + * KEY_DSA 3 + * KEY_HMAC 157 + * out_id The key tag is returned. + * + * Return + * NULL Failure + * non-NULL the generated key pair + * Caller frees the result, and its dk_name pointer. + */ +DST_KEY * +dst_generate_key(const char *name, const int bits, const int exp, + const int flags, const int protocol, const int alg) +{ + DST_KEY *new_key = NULL; + int res; + int dnslen; + u_char dns[2048]; + + if (name == NULL) + return (NULL); + + if (!dst_check_algorithm(alg)) { /* make sure alg is available */ + EREPORT(("dst_generate_key(): Algorithm %d not suppored\n", alg)); + return (NULL); + } + + new_key = dst_s_get_key_struct(name, alg, flags, protocol, bits); + if (new_key == NULL) + return (NULL); + if (bits == 0) /* null key we are done */ + return (new_key); + if (new_key->dk_func == NULL || new_key->dk_func->generate == NULL) { + EREPORT(("dst_generate_key_pair():Unsupported algorithm %d\n", + alg)); + return (dst_free_key(new_key)); + } + if ((res = new_key->dk_func->generate(new_key, exp)) <= 0) { + EREPORT(("dst_generate_key_pair(): Key generation failure %s %d %d %d\n", + new_key->dk_key_name, new_key->dk_alg, + new_key->dk_key_size, exp)); + return (dst_free_key(new_key)); + } + + dnslen = dst_key_to_dnskey(new_key, dns, sizeof(dns)); + if (dnslen != UNSUPPORTED_KEYALG) + new_key->dk_id = dst_s_dns_key_id(dns, dnslen); + else + new_key->dk_id = 0; + + return (new_key); +} + + +/* + * dst_free_key + * Release all data structures pointed to by a key structure. + * Parameters + * f_key Key structure to be freed. + */ + +DST_KEY * +dst_free_key(DST_KEY *f_key) +{ + + if (f_key == NULL) + return (f_key); + if (f_key->dk_func && f_key->dk_func->destroy) + f_key->dk_KEY_struct = + f_key->dk_func->destroy(f_key->dk_KEY_struct); + else { + EREPORT(("dst_free_key(): Unknown key alg %d\n", + f_key->dk_alg)); + free(f_key->dk_KEY_struct); /* SHOULD NOT happen */ + } + if (f_key->dk_KEY_struct) { + free(f_key->dk_KEY_struct); + f_key->dk_KEY_struct = NULL; + } + if (f_key->dk_key_name) + SAFE_FREE(f_key->dk_key_name); + SAFE_FREE(f_key); + return (NULL); +} + +/* + * dst_sig_size + * Return the maximim size of signature from the key specified in bytes + * Parameters + * key + * Returns + * bytes + */ +int +dst_sig_size(DST_KEY *key) { + switch (key->dk_alg) { + case KEY_HMAC_MD5: + return (16); + case KEY_HMAC_SHA1: + return (20); + case KEY_RSA: + return (key->dk_key_size + 7) / 8; + case KEY_DSA: + return (40); + default: + EREPORT(("dst_sig_size(): Unknown key alg %d\n", key->dk_alg)); + return -1; + } +} + +/* + * dst_random + * function that multiplexes number of random number generators + * Parameters + * mode: select the random number generator + * wanted is how many bytes of random data are requested + * outran is a buffer of size at least wanted for the output data + * + * Returns + * number of bytes written to outran + */ +int +dst_random(const int mode, int wanted, u_char *outran) +{ + u_int32_t *buff = NULL, *bp = NULL; + int i; + if (wanted <= 0 || outran == NULL) + return (0); + + switch (mode) { + case DST_RAND_SEMI: + bp = buff = (u_int32_t *) malloc(wanted+sizeof(u_int32_t)); + for (i = 0; i < wanted; i+= sizeof(u_int32_t), bp++) { + *bp = dst_s_quick_random(i); + } + memcpy(outran, buff, wanted); + SAFE_FREE(buff); + return (wanted); + case DST_RAND_STD: + return (dst_s_semi_random(outran, wanted)); + case DST_RAND_KEY: + return (dst_s_random(outran, wanted)); + case DST_RAND_DSS: + default: + /* need error case here XXX OG */ + return (0); + } +} + diff --git a/usr/src/lib/libresolv2/common/dst/dst_internal.h b/usr/src/lib/libresolv2/common/dst/dst_internal.h new file mode 100644 index 0000000000..05f2c48bbc --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/dst_internal.h @@ -0,0 +1,175 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef DST_INTERNAL_H +#define DST_INTERNAL_H + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +#include <limits.h> +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +# include <sys/bitypes.h> +#else +# include <sys/types.h> +#endif + +#ifndef PATH_MAX +# ifdef POSIX_PATH_MAX +# define PATH_MAX POSIX_PATH_MAX +# else +# define PATH_MAX 255 /* this is the value of POSIX_PATH_MAX */ +# endif +#endif + +typedef struct dst_key { + char *dk_key_name; /* name of the key */ + int dk_key_size; /* this is the size of the key in bits */ + int dk_proto; /* what protocols this key can be used for */ + int dk_alg; /* algorithm number from key record */ + u_int32_t dk_flags; /* and the flags of the public key */ + u_int16_t dk_id; /* identifier of the key */ + void *dk_KEY_struct; /* pointer to key in crypto pkg fmt */ + struct dst_func *dk_func; /* point to cryptto pgk specific function table */ +} DST_KEY; +#define HAS_DST_KEY + +#include <isc/dst.h> +/* + * define what crypto systems are supported for RSA, + * BSAFE is prefered over RSAREF; only one can be set at any time + */ +#if defined(BSAFE) && defined(RSAREF) +# error "Cannot have both BSAFE and RSAREF defined" +#endif + +/* Declare dst_lib specific constants */ +#define KEY_FILE_FORMAT "1.2" + +/* suffixes for key file names */ +#define PRIVATE_KEY "private" +#define PUBLIC_KEY "key" + +/* error handling */ +#ifdef REPORT_ERRORS +#define EREPORT(str) printf str +#else +#define EREPORT(str) (void)0 +#endif + +/* use our own special macro to FRRE memory */ + +#ifndef SAFE_FREE +#define SAFE_FREE(a) \ +do{if(a != NULL){memset(a,0, sizeof(*a)); free(a); a=NULL;}} while (0) +#define SAFE_FREE2(a,s) if (a != NULL && s > 0){memset(a,0, s);free(a); a=NULL;} +#endif + +typedef struct dst_func { + int (*sign)(const int mode, DST_KEY *key, void **context, + const u_int8_t *data, const int len, + u_int8_t *signature, const int sig_len); + int (*verify)(const int mode, DST_KEY *key, void **context, + const u_int8_t *data, const int len, + const u_int8_t *signature, const int sig_len); + int (*compare)(const DST_KEY *key1, const DST_KEY *key2); + int (*generate)(DST_KEY *key, int parms); + void *(*destroy)(void *key); + /* conversion functions */ + int (*to_dns_key)(const DST_KEY *key, u_int8_t *out, + const int out_len); + int (*from_dns_key)(DST_KEY *key, const u_int8_t *str, + const int str_len); + int (*to_file_fmt)(const DST_KEY *key, char *out, + const int out_len); + int (*from_file_fmt)(DST_KEY *key, const char *out, + const int out_len); + +} dst_func; + +extern dst_func *dst_t_func[DST_MAX_ALGS]; +extern const char *key_file_fmt_str; +extern const char *dst_path; + +#ifndef DST_HASH_SIZE +#define DST_HASH_SIZE 20 /* RIPEMD160 and SHA-1 are 20 bytes MD5 is 16 */ +#endif + +int dst_bsafe_init(void); + +int dst_rsaref_init(void); + +int dst_hmac_md5_init(void); + +int dst_cylink_init(void); + +int dst_eay_dss_init(void); + +/* support functions */ +/* base64 to bignum conversion routines */ +int dst_s_conv_bignum_u8_to_b64( char *out_buf, const int out_len, + const char *header, + const u_int8_t *bin_data, + const int bin_len); +int dst_s_conv_bignum_b64_to_u8( const char **buf, u_int8_t *loc, + const int loclen) ; +/* from higher level support routines */ +int dst_s_calculate_bits( const u_int8_t *str, const int max_bits); +int dst_s_verify_str( const char **buf, const char *str); + + +/* conversion between dns names and key file names */ +size_t dst_s_filename_length( const char *name, const char *suffix); +int dst_s_build_filename( char *filename, const char *name, + u_int16_t id, int alg, const char *suffix, + size_t filename_length); + +FILE *dst_s_fopen (const char *filename, const char *mode, int perm); + +/* from file prandom.c */ +int dst_s_random( u_int8_t *output, int size); +int dst_s_semi_random( u_int8_t *output, int size); +u_int32_t dst_s_quick_random( int inc); +void dst_s_quick_random_set( u_int32_t val, u_int32_t cnt); + +/* + * read and write network byte order into u_int?_t + * all of these should be retired + */ +u_int16_t dst_s_get_int16( const u_int8_t *buf); +void dst_s_put_int16( u_int8_t *buf, const u_int16_t val); + +u_int32_t dst_s_get_int32( const u_int8_t *buf); +void dst_s_put_int32( u_int8_t *buf, const u_int32_t val); + +#ifdef DUMP +# undef DUMP +# define DUMP(a,b,c,d) dst_s_dump(a,b,c,d) +#else +# define DUMP(a,b,c,d) +#endif +void +dst_s_dump(const int mode, const u_char *data, const int size, + const char *msg); + + + +#endif /* DST_INTERNAL_H */ diff --git a/usr/src/lib/libresolv2/common/dst/eay_dss_link.c b/usr/src/lib/libresolv2/common/dst/eay_dss_link.c new file mode 100644 index 0000000000..5216010cd2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/eay_dss_link.c @@ -0,0 +1,637 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef EAY_DSS +static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/eay_dss_link.c,v 1.6 2001/05/29 05:48:09 marka Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ +/* + * This file contains two components + * 1. Interface to the EAY libcrypto library to allow compilation of Bind + * with TIS/DNSSEC when EAY libcrypto is not available + * all calls to libcrypto are contained inside this file. + * 2. The glue to connvert DSA KEYS to and from external formats + */ +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <sys/param.h> +#include <sys/time.h> +#include <netinet/in.h> + +#include "dst_internal.h" + +#include "crypto.h" +#include "bn.h" +#include "dsa.h" +#include "sha.h" + +#include "port_after.h" + + +static int dst_eay_dss_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); + +static int dst_eay_dss_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_eay_dss_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len); +static int dst_eay_dss_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); +static int dst_eay_dss_key_to_file_format(const DST_KEY *key, u_char *buff, + const int buff_len); +static int dst_eay_dss_key_from_file_format(DST_KEY *d_key, + const u_char *buff, + const int buff_len); +static void *dst_eay_dss_free_key_structure(void *key); + +static int dst_eay_dss_generate_keypair(DST_KEY *key, int exp); +static int dst_eay_dss_compare_keys(const DST_KEY *key1, const DST_KEY *key2); + +/* + * dst_eay_dss_init() Function to answer set up function pointers for + * EAY DSS related functions + */ +int +dst_eay_dss_init(void) +{ + if (dst_t_func[KEY_DSA] != NULL) + return (1); + dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_DSA] == NULL) + return (0); + memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_DSA]->sign = dst_eay_dss_sign; + dst_t_func[KEY_DSA]->verify = dst_eay_dss_verify; + dst_t_func[KEY_DSA]->compare = dst_eay_dss_compare_keys; + dst_t_func[KEY_DSA]->generate = dst_eay_dss_generate_keypair; + dst_t_func[KEY_DSA]->destroy = dst_eay_dss_free_key_structure; + dst_t_func[KEY_DSA]->from_dns_key = dst_eay_dss_from_dns_key; + dst_t_func[KEY_DSA]->to_dns_key = dst_eay_dss_to_dns_key; + dst_t_func[KEY_DSA]->from_file_fmt = dst_eay_dss_key_from_file_format; + dst_t_func[KEY_DSA]->to_file_fmt = dst_eay_dss_key_to_file_format; + return (1); +} + +/* + * dst_eay_dss_sign + * Call EAY DSS signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * algobj structure holds context for a sign done in multiple calls. + * context the context to use for this computation + * data data to be signed. + * len length in bytes of data. + * priv_key key to use for signing. + * signature location to store signature. + * sig_len size in bytes of signature field. + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * N is 41 for DNS + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_eay_dss_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + int sign_len = 0; + int status; + SHA_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_CTX *) malloc(sizeof(SHA_CTX)); + else if (context) + ctx = (SHA_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHA1_Init(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + SHA1_Update(ctx, (u_char *) data, len); + } + if (mode & SIG_MODE_FINAL) { + DSA *key; + u_char digest[SHA_DIGEST_LENGTH]; + u_char rand[SHA_DIGEST_LENGTH]; + u_char r[SHA_DIGEST_LENGTH], s[SHA_DIGEST_LENGTH]; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = dkey->dk_KEY_struct; + if (key == NULL) + return(-2); + SHA1_Final(digest, ctx); + status = DSA_sign(0, digest, SHA_DIGEST_LENGTH, + signature, &sign_len, key); + if (status != 0) + return (SIGN_FINAL_FAILURE); + + *signature = (dkey->dk_key_size - 512)/64; + sign_len = 1; + memcpy(signature + sign_len, r, SHA_DIGEST_LENGTH); + sign_len += SHA_DIGEST_LENGTH; + memcpy(signature + sign_len, s, SHA_DIGEST_LENGTH); + sign_len += SHA_DIGEST_LENGTH; + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/* + * dst_eay_dss_verify + * Calls EAY DSS verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey structure holds context for a verify done in multiple calls. + * context algorithm specific context for the current context processing + * data data signed. + * len length in bytes of data. + * pub_key key to use for verify. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_eay_dss_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + int status; + SHA_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (SHA_CTX *) malloc(sizeof(SHA_CTX)); + else if (context) + ctx = (SHA_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + SHA1_Init(ctx); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) { + SHA1_Update(ctx, (u_char *) data, len); + } + if (mode & SIG_MODE_FINAL) { + DSA *key; + u_char digest[SHA_DIGEST_LENGTH]; + u_char r[SHA_DIGEST_LENGTH], s[SHA_DIGEST_LENGTH]; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (-1); + key = (DSA *) dkey->dk_KEY_struct; + if (key = NULL) + return (-2); + if (signature == NULL || sig_len != (2 * SHA_DIGEST_LENGTH +1)) + return (SIGN_FINAL_FAILURE); + SHA1_Final(digest, ctx); + SAFE_FREE(ctx); + if (status != 0) + return (SIGN_FINAL_FAILURE); + if (((int)*signature) != ((BN_num_bytes(key->p) -64)/8)) + return(VERIFY_FINAL_FAILURE); + + memcpy(r, signature +1, SHA_DIGEST_LENGTH); + memcpy(s, signature + SHA_DIGEST_LENGTH +1, SHA_DIGEST_LENGTH); + status = DSA_verify(0, digest, SHA_DIGEST_LENGTH, + (u_char *)signature, sig_len, key); + if (status != 0) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (0); +} + + +/* + * dst_eay_dss_to_dns_key + * Converts key from DSA to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_eay_dss_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + u_char *op = out_str; + int t; + DSA *key; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + key = (DSA *) in_key->dk_KEY_struct; + + t = (BN_num_bytes(key->p) - 64) / 8; + + *op++ = t; + BN_bn2bin(key->q, op); + op += BN_num_bytes(key->q); + BN_bn2bin(key->p, op); + op += BN_num_bytes(key->p); + BN_bn2bin(key->g, op); + op += BN_num_bytes(key->g); + BN_bn2bin(key->pub_key, op); + op += BN_num_bytes(key->pub_key); + + return (op - out_str); +} + + +/* + * dst_eay_dss_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_eay_dss_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int t; + u_char *key_ptr = (u_char *)key; + DSA *d_key; + int p_bytes; + + if (s_key == NULL || len < 0 || key == NULL) + return (0); + + if (len == 0) /* process null key */ + return (1); + + if (key_ptr == NULL) + return (0); + t = (int) *key_ptr++; /* length of exponent in bytes */ + p_bytes = 64 + 8 * t; + + if ((3 * (t * 8 + 64) + SHA_DIGEST_LENGTH + 1) != len) + return (0); + + if ((d_key = (DSA *) malloc(sizeof(DSA))) == NULL) { + EREPORT(("dst_eay_dss_from_dns_key(): Memory allocation error 1")); + return (0); + } + memset(d_key, 0, sizeof(DSA)); + s_key->dk_KEY_struct = (void *) d_key; + + d_key->q = BN_bin2bn(key_ptr, SHA_DIGEST_LENGTH, NULL); + key_ptr += SHA_DIGEST_LENGTH; + + d_key->p = BN_bin2bn(key_ptr, p_bytes, NULL); + key_ptr += p_bytes; + + d_key->g = BN_bin2bn(key_ptr, p_bytes, NULL); + key_ptr += p_bytes; + + d_key->pub_key = BN_bin2bn(key_ptr, p_bytes, NULL); + key_ptr += p_bytes; + + s_key->dk_key_size = p_bytes * 8; + return (1); +} + + +/************************************************************************** + * dst_eay_dss_key_to_file_format + * Encodes an DSA Key into the portable file format. + * Parameters + * key DSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_eay_dss_key_to_file_format(const DST_KEY *key, u_char *buff, + const int buff_len) +{ + u_char *bp; + int len, b_len; + DSA *dkey; + char num[256]; /* More than long enough for DSA keys */ + + if (key == NULL || key->dk_KEY_struct == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + dkey = (DSA *) key->dk_KEY_struct; + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_DSA, "DSA"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->p, BN_num_bytes(dkey->p)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime(p): ", num, + BN_num_bytes(dkey->p))) <= 0) + return (-1); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->q, BN_num_bytes(dkey->q)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Subprime(q): ", num, + BN_num_bytes(dkey->q))) <= 0) + return (-2); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->g, BN_num_bytes(dkey->g)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Base(g): ", num, + BN_num_bytes(dkey->g))) <= 0) + return (-3); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->priv_key, BN_num_bytes(dkey->priv_key)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Private_value(x): ", + num, + BN_num_bytes(dkey->priv_key))) + <= 0) + return (-4); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + memcpy(num, dkey->pub_key, BN_num_bytes(dkey->pub_key)); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Public_value(y): ", + num, + BN_num_bytes(dkey->pub_key))) + <= 0) + return (-5); + + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/************************************************************************** + * dst_eay_dss_key_from_file_format + * Converts contents of a private key file into a private DSA key. + * Parameters + * d_key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_eay_dss_key_from_file_format(DST_KEY *d_key, const u_char *buff, + const int buff_len) +{ + char s[128]; + int len, s_len = sizeof(s); + const char *p = buff; + DSA *dsa_key; + + if (d_key == NULL || buff == NULL || buff_len <= 0) + return (-1); + + dsa_key = (DSA *) malloc(sizeof(DSA)); + if (dsa_key == NULL) { + return (-2); + } + memset(dsa_key, 0, sizeof(*dsa_key)); + d_key->dk_KEY_struct = (void *) dsa_key; + + if (!dst_s_verify_str(&p, "Prime(p): ")) + return (-3); + memset(s, 0, s_len); + if ((len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)) == 0) + return (-4); + dsa_key->p = BN_bin2bn (s, len, NULL); + if (dsa_key->p == NULL) + return(-5); + + while (*++p && p < (const char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "Subprime(q): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-6); + dsa_key->q = BN_bin2bn (s, len, NULL); + if (dsa_key->q == NULL) + return (-7); + } else if (dst_s_verify_str(&p, "Base(g): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-8); + dsa_key->g = BN_bin2bn (s, len, NULL); + if (dsa_key->g == NULL) + return (-9); + } else if (dst_s_verify_str(&p, "Private_value(x): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-10); + dsa_key->priv_key = BN_bin2bn (s, len, NULL); + if (dsa_key->priv_key == NULL) + return (-11); + } else if (dst_s_verify_str(&p, "Public_value(y): ")) { + if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len))) + return (-12); + dsa_key->pub_key = BN_bin2bn (s, len, NULL); + if (dsa_key->pub_key == NULL) + return (-13); + } else { + EREPORT(("Decode_DSAKey(): Bad keyword %s\n", p)); + return (-14); + } + } /* while p */ + + d_key->dk_key_size = BN_num_bytes(dsa_key->p); + + return (0); +} + + +/************************************************************************** + * dst_eay_dss_free_key_structure + * Frees all dynamicly allocated structures in DSA. + */ + +static void * +dst_eay_dss_free_key_structure(void *key) +{ + DSA *d_key = (DSA *) key; + if (d_key != NULL) { + BN_free(d_key->p); + BN_free(d_key->q); + BN_free(d_key->g); + if (d_key->pub_key) + BN_free(d_key->pub_key); + if (d_key->priv_key) + BN_free(d_key->priv_key); + SAFE_FREE(d_key); + } + return (NULL); +} + + +/************************************************************************** + * dst_eay_dss_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_eay_dss_generate_keypair(DST_KEY *key, int nothing) +{ + int status, n; + DSA *dsa; + u_char rand[SHA_DIGEST_LENGTH]; + + if (key == NULL || key->dk_alg != KEY_DSA) + return (0); + + if ((dsa = (DSA *) malloc(sizeof(DSA))) == NULL) { + EREPORT(("dst_eay_dss_generate_keypair: Memory allocation error 3")); + return (0); + } + memset(dsa, 0, sizeof(*dsa)); + + n = dst_random(DST_RAND_KEY, sizeof(rand), rand); + if (n != sizeof(rand)) + return (0); + dsa = DSA_generate_parameters(key->dk_key_size, rand, 20, NULL, NULL, + NULL, NULL); + + if (!dsa) { + EREPORT(("dst_eay_dss_generate_keypair: Generate Parameters failed")); + return (0); + } + if (DSA_generate_key(dsa) == 0) { + EREPORT(("dst_eay_dss_generate_keypair: Generate Key failed")); + return(0); + } + key->dk_KEY_struct = (void *) dsa; + return (1); +} + + +/* + * dst_eay_dss_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_eay_dss_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + int status; + DSA *dkey1 = (DSA *) key1->dk_KEY_struct; + DSA *dkey2 = (DSA *) key2->dk_KEY_struct; + + if (dkey1 == NULL && dkey2 == NULL) + return (0); + else if (dkey1 == NULL) + return (2); + else if (dkey2 == NULL) + return(1); + + status = BN_cmp(dkey1->p, dkey2->p) || + BN_cmp(dkey1->q, dkey2->q) || + BN_cmp(dkey1->g, dkey2->g) || + BN_cmp(dkey1->pub_key, dkey2->pub_key); + + if (status) + return (status); + + if (dkey1->priv_key || dkey2->priv_key) { + if (dkey1->priv_key == NULL || dkey2->priv_key == NULL) + return (202); + return (BN_cmp(dkey1->priv_key, dkey2->priv_key)); + } else + return (0); +} +#else +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <sys/param.h> +#include <sys/time.h> +#include <netinet/in.h> + +#include "dst_internal.h" +#include "port_after.h" +int +dst_eay_dss_init(void) +{ + return (0); +} +#endif /* EAY_DSS */ diff --git a/usr/src/lib/libresolv2/common/dst/hmac_link.c b/usr/src/lib/libresolv2/common/dst/hmac_link.c new file mode 100644 index 0000000000..77269667c2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/hmac_link.c @@ -0,0 +1,510 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef HMAC_MD5 +#ifndef LINT +static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/hmac_link.c,v 1.9 2001/05/29 05:48:10 marka Exp $"; +#endif +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ + +/* + * This file contains an implementation of the HMAC-MD5 algorithm. + */ +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <sys/param.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include "dst_internal.h" +#ifdef USE_MD5 +#ifndef SUNW_LIBMD5 +# include "md5.h" +#else +#include <sys/md5.h> +#endif +# ifndef _MD5_H_ +# define _MD5_H_ 1 /* make sure we do not include rsaref md5.h file */ +# endif +#endif + +#include "port_after.h" + + +#define HMAC_LEN 64 +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5c +#define MD5_LEN 16 + + +typedef struct hmackey { + u_char hk_ipad[64], hk_opad[64]; +} HMAC_Key; + + +/************************************************************************** + * dst_hmac_md5_sign + * Call HMAC signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * priv_key key to use for signing. + * context the context to be used in this digest + * data data to be signed. + * len length in bytes of data. + * signature location to store signature. + * sig_len size of the signature location + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + HMAC_Key *key; + int sign_len = 0; + MD5_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (MD5_CTX *) malloc(sizeof(*ctx)); + else if (context) + ctx = (MD5_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (d_key == NULL || d_key->dk_KEY_struct == NULL) + return (-1); + key = (HMAC_Key *) d_key->dk_KEY_struct; + + if (mode & SIG_MODE_INIT) { + MD5Init(ctx); + MD5Update(ctx, key->hk_ipad, HMAC_LEN); + } + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) + MD5Update(ctx, data, len); + + if (mode & SIG_MODE_FINAL) { + if (signature == NULL || sig_len < MD5_LEN) + return (SIGN_FINAL_FAILURE); + MD5Final(signature, ctx); + + /* perform outer MD5 */ + MD5Init(ctx); + MD5Update(ctx, key->hk_opad, HMAC_LEN); + MD5Update(ctx, signature, MD5_LEN); + MD5Final(signature, ctx); + sign_len = MD5_LEN; + SAFE_FREE(ctx); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/************************************************************************** + * dst_hmac_md5_verify() + * Calls HMAC verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey key to use for verify. + * data data signed. + * len length in bytes of data. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + HMAC_Key *key; + MD5_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = (MD5_CTX *) malloc(sizeof(*ctx)); + else if (context) + ctx = (MD5_CTX *) *context; + if (ctx == NULL) + return (-1); + + if (d_key == NULL || d_key->dk_KEY_struct == NULL) + return (-1); + + key = (HMAC_Key *) d_key->dk_KEY_struct; + if (mode & SIG_MODE_INIT) { + MD5Init(ctx); + MD5Update(ctx, key->hk_ipad, HMAC_LEN); + } + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) + MD5Update(ctx, data, len); + + if (mode & SIG_MODE_FINAL) { + u_char digest[MD5_LEN]; + if (signature == NULL || key == NULL || sig_len != MD5_LEN) + return (VERIFY_FINAL_FAILURE); + MD5Final(digest, ctx); + + /* perform outer MD5 */ + MD5Init(ctx); + MD5Update(ctx, key->hk_opad, HMAC_LEN); + MD5Update(ctx, digest, MD5_LEN); + MD5Final(digest, ctx); + + SAFE_FREE(ctx); + if (memcmp(digest, signature, MD5_LEN) != 0) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (0); +} + + +/************************************************************************** + * dst_buffer_to_hmac_md5 + * Converts key from raw data to an HMAC Key + * This function gets in a pointer to the data + * Parameters + * hkey the HMAC key to be filled in + * key the key in raw format + * keylen the length of the key + * Return + * 0 Success + * <0 Failure + */ +static int +dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const int keylen) +{ + int i; + HMAC_Key *hkey = NULL; + MD5_CTX ctx; + int local_keylen = keylen; + + if (dkey == NULL || key == NULL || keylen < 0) + return (-1); + + if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL) + return (-2); + + memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad)); + memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad)); + + /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */ + if (keylen > HMAC_LEN) { + u_char tk[MD5_LEN]; + MD5Init(&ctx); + MD5Update(&ctx, key, keylen); + MD5Final(tk, &ctx); + memset((void *) &ctx, 0, sizeof(ctx)); + key = tk; + local_keylen = MD5_LEN; + } + /* start out by storing key in pads */ + memcpy(hkey->hk_ipad, key, local_keylen); + memcpy(hkey->hk_opad, key, local_keylen); + + /* XOR key with hk_ipad and opad values */ + for (i = 0; i < HMAC_LEN; i++) { + hkey->hk_ipad[i] ^= HMAC_IPAD; + hkey->hk_opad[i] ^= HMAC_OPAD; + } + dkey->dk_key_size = local_keylen; + dkey->dk_KEY_struct = (void *) hkey; + return (1); +} + + +/************************************************************************** + * dst_hmac_md5_key_to_file_format + * Encodes an HMAC Key into the portable file format. + * Parameters + * hkey HMAC KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input hkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff, + const int buff_len) +{ + char *bp; + int len, b_len, i, key_len; + u_char key[HMAC_LEN]; + HMAC_Key *hkey; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + hkey = (HMAC_Key *) dkey->dk_KEY_struct; + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + + memset(key, 0, HMAC_LEN); + for (i = 0; i < HMAC_LEN; i++) + key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; + for (i = HMAC_LEN - 1; i >= 0; i--) + if (key[i] != 0) + break; + key_len = i + 1; + + strcat(bp, "Key: "); + bp += strlen("Key: "); + b_len = buff_len - (bp - buff); + + len = b64_ntop(key, key_len, bp, b_len); + if (len < 0) + return (-1); + bp += len; + *(bp++) = '\n'; + *bp = '\0'; + b_len = buff_len - (bp - buff); + + return (buff_len - b_len); +} + + +/************************************************************************** + * dst_hmac_md5_key_from_file_format + * Converts contents of a key file into an HMAC key. + * Parameters + * hkey structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff, + const int buff_len) +{ + const char *p = buff, *eol; + u_char key[HMAC_LEN+1]; /* b64_pton needs more than 64 bytes do decode + * it should probably be fixed rather than doing + * this + */ + u_char *tmp; + int key_len, len; + + if (dkey == NULL) + return (-2); + if (buff == NULL || buff_len < 0) + return (-1); + + memset(key, 0, sizeof(key)); + + if (!dst_s_verify_str(&p, "Key: ")) + return (-3); + + eol = strchr(p, '\n'); + if (eol == NULL) + return (-4); + len = eol - p; + tmp = malloc(len + 2); + memcpy(tmp, p, len); + *(tmp + len) = 0x0; + key_len = b64_pton((char *)tmp, key, HMAC_LEN+1); /* see above */ + SAFE_FREE2(tmp, len + 2); + + if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) { + return (-6); + } + return (0); +} + +/* + * dst_hmac_md5_to_dns_key() + * function to extract hmac key from DST_KEY structure + * intput: + * in_key: HMAC-MD5 key + * output: + * out_str: buffer to write ot + * out_len: size of output buffer + * returns: + * number of bytes written to output buffer + */ +static int +dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + + HMAC_Key *hkey; + int i; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= in_key->dk_key_size || out_str == NULL) + return (-1); + + hkey = (HMAC_Key *) in_key->dk_KEY_struct; + for (i = 0; i < in_key->dk_key_size; i++) + out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; + return (i); +} + +/************************************************************************** + * dst_hmac_md5_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct; + HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct; + return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN); +} + +/************************************************************************** + * dst_hmac_md5_free_key_structure + * Frees all (none) dynamically allocated structures in hkey + */ + +static void * +dst_hmac_md5_free_key_structure(void *key) +{ + HMAC_Key *hkey = key; + SAFE_FREE(hkey); + return (NULL); +} + + +/*************************************************************************** + * dst_hmac_md5_generate_key + * Creates a HMAC key of size size with a maximum size of 63 bytes + * generating a HMAC key larger than 63 bytes makes no sense as that key + * is digested before use. + */ + +static int +dst_hmac_md5_generate_key(DST_KEY *key, const int nothing) +{ + u_char *buff; + int i, n, size; + + i = nothing; + + if (key == NULL || key->dk_alg != KEY_HMAC_MD5) + return (0); + size = (key->dk_key_size + 7) / 8; /* convert to bytes */ + if (size <= 0) + return(0); + + i = size > 64 ? 64 : size; + buff = malloc(i+8); + + n = dst_random(DST_RAND_SEMI, i, buff); + n += dst_random(DST_RAND_KEY, i, buff); + if (n <= i) { /* failed getting anything */ + SAFE_FREE2(buff, i); + return (-1); + } + n = dst_buffer_to_hmac_md5(key, buff, i); + SAFE_FREE2(buff, i); + if (n <= 0) + return (n); + return (1); +} + +/* + * dst_hmac_md5_init() Function to answer set up function pointers for HMAC + * related functions + */ +int +#ifdef ORIGINAL_ISC_CODE +dst_hmac_md5_init() +#else +dst_md5_hmac_init() +#endif +{ + if (dst_t_func[KEY_HMAC_MD5] != NULL) + return (1); + dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_HMAC_MD5] == NULL) + return (0); + memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func)); + dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign; + dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify; + dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys; + dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key; + dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure; + dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key; + dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5; + dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format; + dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format; + return (1); +} + +#else +int +dst_hmac_md5_init(){ + return (0); +} +#endif + + + + + + + diff --git a/usr/src/lib/libresolv2/common/dst/prandom.c b/usr/src/lib/libresolv2/common/dst/prandom.c new file mode 100644 index 0000000000..0a4fd7d79e --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/prandom.c @@ -0,0 +1,860 @@ +#ifndef LINT +static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/prandom.c,v 1.12 2001/07/26 01:20:09 marka Exp $"; +#endif +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ + +#include "port_before.h" + +#include <assert.h> +#include <stdio.h> +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <dirent.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include "dst_internal.h" +#include "prand_conf.h" + +#include "port_after.h" + +#ifndef DST_NUM_HASHES +#define DST_NUM_HASHES 4 +#endif +#ifndef DST_NUMBER_OF_COUNTERS +#define DST_NUMBER_OF_COUNTERS 5 /* 32 * 5 == 160 == SHA(1) > MD5 */ +#endif + +/* + * the constant below is a prime number to make fixed data structues like + * stat and time wrap over blocks. This adds certain uncertanty to what is + * in each digested block. + * The prime number 2879 has the special property that when + * divided by 2,4 and 6 the result is also a prime numbers + */ + +#ifndef DST_RANDOM_BLOCK_SIZE +#define DST_RANDOM_BLOCK_SIZE 2879 +#endif + +/* + * This constant dictatates how many bits we shift to the right before using a + */ +#ifndef DST_SHIFT +#define DST_SHIFT 9 +#endif + +/* + * An initalizer that is as bad as any other with half the bits set + */ +#ifndef DST_RANDOM_PATTERN +#define DST_RANDOM_PATTERN 0x8765CA93 +#endif +/* + * things must have changed in the last 3600 seconds to be used + */ +#define MAX_OLD 3600 + + +/* + * these two data structure are used to process input data into digests, + * + * The first structure is containts a pointer to a DST HMAC key + * the variables accompanying are used for + * step : select every step byte from input data for the hash + * block: number of data elements going into each hash + * digested: number of data elements digested so far + * curr: offset into the next input data for the first byte. + */ +typedef struct hash { + DST_KEY *key; + void *ctx; + int digested, block, step, curr; +} prand_hash; + +/* + * This data structure controlls number of hashes and keeps track of + * overall progress in generating correct number of bytes of output. + * output : array to store the output data in + * needed : how many bytes of output are needed + * filled : number of bytes in output so far. + * bytes : total number of bytes processed by this structure + * file_digest : the HMAC key used to digest files. + */ +typedef struct work { + int needed, filled, bytes; + u_char *output; + prand_hash *hash[DST_NUM_HASHES]; + DST_KEY *file_digest; +} dst_work; + + +/* + * forward function declarations + */ +static int get_dev_random(u_char *output, int size); +static int do_time(dst_work *work); +static int do_ls(dst_work *work); +static int unix_cmd(dst_work *work); +static int digest_file(dst_work *work); + +static void force_hash(dst_work *work, prand_hash *hash); +static int do_hash(dst_work *work, prand_hash *hash, const u_char *input, + int size); +static int my_digest(dst_work *tmp, const u_char *input, int size); +static prand_hash *get_hmac_key(int step, int block); + +static int own_random(dst_work *work); + + +/* + * variables used in the quick random number generator + */ +static u_int32_t ran_val = DST_RANDOM_PATTERN; +static u_int32_t ran_cnt = (DST_RANDOM_PATTERN >> 10); + +/* + * setting the quick_random generator to particular values or if both + * input parameters are 0 then set it to initial vlaues + */ + +void +dst_s_quick_random_set(u_int32_t val, u_int32_t cnt) +{ + ran_val = (val == 0) ? DST_RANDOM_PATTERN : val; + ran_cnt = (cnt == 0) ? (DST_RANDOM_PATTERN >> 10) : cnt; +} + +/* + * this is a quick and random number generator that seems to generate quite + * good distribution of data + */ +u_int32_t +dst_s_quick_random(int inc) +{ + ran_val = ((ran_val >> 13) ^ (ran_val << 19)) ^ + ((ran_val >> 7) ^ (ran_val << 25)); + if (inc > 0) /* only increasing values accepted */ + ran_cnt += inc; + ran_val += ran_cnt++; + return (ran_val); +} + +/* + * get_dev_random: Function to read /dev/random reliably + * this function returns how many bytes where read from the device. + * port_after.h should set the control variable HAVE_DEV_RANDOM + */ +static int +get_dev_random(u_char *output, int size) +{ +#ifdef HAVE_DEV_RANDOM + struct stat st; + int n = 0, fd = -1, s; + + s = stat("/dev/random", &st); + if (s == 0 && S_ISCHR(st.st_mode)) { + if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) != -1) { + if ((n = read(fd, output, size)) < 0) + n = 0; + close(fd); + } + return (n); + } +#endif + return (0); +} + +/* + * Portable way of getting the time values if gettimeofday is missing + * then compile with -DMISSING_GETTIMEOFDAY time() is POSIX compliant but + * gettimeofday() is not. + * Time of day is predictable, we are looking for the randomness that comes + * the last few bits in the microseconds in the timer are hard to predict when + * this is invoked at the end of other operations + */ +struct timeval *mtime; +static int +do_time(dst_work *work) +{ + int cnt = 0; + static u_char tmp[sizeof(struct timeval) + sizeof(struct timezone)]; + struct timezone *zone; + + zone = (struct timezone *) tmp; + mtime = (struct timeval *)(tmp + sizeof(struct timezone)); + gettimeofday(mtime, zone); + cnt = sizeof(tmp); + my_digest(work, tmp, sizeof(tmp)); + + return (cnt); +} + +/* + * this function simulates the ls command, but it uses stat which gives more + * information and is harder to guess + * Each call to this function will visit the next directory on the list of + * directories, in a circular manner. + * return value is the number of bytes added to the temp buffer + * + * do_ls() does not visit subdirectories + * if attacker has access to machine it can guess most of the values seen + * thus it is important to only visit directories that are freqently updated + * Attacker that has access to the network can see network traffic + * when NFS mounted directories are accessed and know exactly the data used + * but may not know exactly in what order data is used. + * Returns the number of bytes that where returned in stat structures + */ +static int +do_ls(dst_work *work) +{ + struct dir_info { + uid_t uid; + gid_t gid; + off_t size; + time_t atime, mtime, ctime; + }; + static struct dir_info dir_info; + struct stat buf; + struct dirent *entry; + static int i = 0; + static unsigned long d_round = 0; + struct timeval tv; + int n = 0, dir_len, tb_i = 0, out = 0; + + char file_name[1024]; + u_char tmp_buff[1024]; + DIR *dir = NULL; + + if (dirs[i] == NULL) /* if at the end of the list start over */ + i = 0; + if (stat(dirs[i++], &buf)) /* directory does not exist */ + return (0); + + gettimeofday(&tv, NULL); + if (d_round == 0) + d_round = tv.tv_sec - MAX_OLD; + else if (i==1) /* if starting a new round cut what we accept */ + d_round += (tv.tv_sec - d_round)/2; + + if (buf.st_atime < (time_t)d_round) + return (0); + + EREPORT(("do_ls i %d filled %4d\n", i-1, work->filled)); + memcpy(tmp_buff, &buf, sizeof(buf)); + tb_i += sizeof(buf); + + + if ((dir = opendir(dirs[i-1])) == NULL)/* open it for read */ + return (0); + strcpy(file_name, dirs[i-1]); + dir_len = strlen(file_name); + file_name[dir_len++] = '/'; + while ((entry = readdir(dir))) { + int len = strlen(entry->d_name); + out += len; + if (my_digest(work, (u_char *)entry->d_name, len)) + break; + + memcpy(&file_name[dir_len], entry->d_name, len); + file_name[dir_len + len] = 0x0; + /* for all entries in dir get the stats */ + if (stat(file_name, &buf) == 0) { + n++; /* count successfull stat calls */ + /* copy non static fields */ + dir_info.uid += buf.st_uid; + dir_info.gid += buf.st_gid; + dir_info.size += buf.st_size; + dir_info.atime += buf.st_atime; + dir_info.mtime += buf.st_mtime; + dir_info.ctime += buf.st_ctime; + out += sizeof(dir_info); + if(my_digest(work, (u_char *)&dir_info, + sizeof(dir_info))) + break; + } + } + closedir(dir); /* done */ + out += do_time(work); /* add a time stamp */ + return (out); +} + + +/* + * unix_cmd() + * this function executes the a command from the cmds[] list of unix commands + * configured in the prand_conf.h file + * return value is the number of bytes added to the randomness temp buffer + * + * it returns the number of bytes that where read in + * if more data is needed at the end time is added to the data. + * This function maintains a state to selects the next command to run + * returns the number of bytes read in from the command + */ +static int +unix_cmd(dst_work *work) +{ + static int cmd_index = 0; + int cnt = 0, n; + FILE *pipe; + u_char buffer[4096]; + + if (cmds[cmd_index] == NULL) + cmd_index = 0; + EREPORT(("unix_cmd() i %d filled %4d\n", cmd_index, work->filled)); + pipe = popen(cmds[cmd_index++], "r"); /* execute the command */ + + while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) { + cnt += n; /* process the output */ + if (my_digest(work, buffer, n)) + break; + /* this adds some randomness to the output */ + cnt += do_time(work); + } + while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) + (void)NULL; /* drain the pipe */ + pclose(pipe); + return (cnt); /* read how many bytes where read in */ +} + +/* + * digest_file() This function will read a file and run hash over it + * input is a file name + */ +static int +digest_file(dst_work *work) +{ + static int f_cnt = 0; + static unsigned long f_round = 0; + FILE *fp; + void *ctx; + const char *name; + int no, i; + struct stat st; + struct timeval tv; + u_char buf[1024]; + + if (f_round == 0 || files[f_cnt] == NULL || work->file_digest == NULL) + if (gettimeofday(&tv, NULL)) /* only do this if needed */ + return (0); + if (f_round == 0) /* first time called set to one hour ago */ + f_round = (tv.tv_sec - MAX_OLD); + name = files[f_cnt++]; + if (files[f_cnt] == NULL) { /* end of list of files */ + if(f_cnt <= 1) /* list is too short */ + return (0); + f_cnt = 0; /* start again on list */ + f_round += (tv.tv_sec - f_round)/2; /* set new cutoff */ + work->file_digest = dst_free_key(work->file_digest); + } + if (work->file_digest == NULL) { + work->file_digest = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, + (u_char *)&tv, sizeof(tv)); + if (work->file_digest == NULL) + return (0); + } + if (access(name, R_OK) || stat(name, &st)) + return (0); /* no such file or not allowed to read it */ + if (strncmp(name, "/proc/", 6) && st.st_mtime < (time_t)f_round) + return(0); /* file has not changed recently enough */ + if (dst_sign_data(SIG_MODE_INIT, work->file_digest, &ctx, + NULL, 0, NULL, 0)) { + work->file_digest = dst_free_key(work->file_digest); + return (0); + } + if ((fp = fopen(name, "r")) == NULL) + return (0); + for (no = 0; (i = fread(buf, sizeof(*buf), sizeof(buf), fp)) > 0; + no += i) + dst_sign_data(SIG_MODE_UPDATE, work->file_digest, &ctx, + buf, i, NULL, 0); + + fclose(fp); + if (no >= 64) { + i = dst_sign_data(SIG_MODE_FINAL, work->file_digest, &ctx, + NULL, 0, &work->output[work->filled], + DST_HASH_SIZE); + if (i > 0) + work->filled += i; + } + else if (i > 0) + my_digest(work, buf, i); + my_digest(work, (const u_char *)name, strlen(name)); + return (no + strlen(name)); +} + +/* + * function to perform the FINAL and INIT operation on a hash if allowed + */ +static void +force_hash(dst_work *work, prand_hash *hash) +{ + int i = 0; + + /* + * if more than half a block then add data to output + * otherwise adde the digest to the next hash + */ + if ((hash->digested * 2) > hash->block) { + i = dst_sign_data(SIG_MODE_FINAL, hash->key, &hash->ctx, + NULL, 0, &work->output[work->filled], + DST_HASH_SIZE); + + hash->digested = 0; + dst_sign_data(SIG_MODE_INIT, hash->key, &hash->ctx, + NULL, 0, NULL, 0); + if (i > 0) + work->filled += i; + } + return; +} + +/* + * This function takes the input data does the selection of data specified + * by the hash control block. + * The step varialbe in the work sturcture determines which 1/step bytes + * are used, + * + */ +static int +do_hash(dst_work *work, prand_hash *hash, const u_char *input, int size) +{ + const u_char *tmp = input; + u_char *save = NULL, *tp; + int i, cnt = size, n, needed, avail, dig, tmp_size = 0; + + if (cnt <= 0 || input == NULL) + return (0); + + if (hash->step > 1) { /* if using subset of input data */ + tmp_size = size / hash->step + 2; + tmp = tp = save = malloc(tmp_size); + for (cnt = 0, i = hash->curr; i < size; i += hash->step, cnt++) + *(tp++) = input[i]; + /* calcutate the starting point in the next input set */ + hash->curr = (hash->step - (i - size)) % hash->step; + } + /* digest the data in block sizes */ + for (n = 0; n < cnt; n += needed) { + avail = (cnt - n); + needed = hash->block - hash->digested; + dig = (avail < needed) ? avail : needed; + dst_sign_data(SIG_MODE_UPDATE, hash->key, &hash->ctx, + &tmp[n], dig, NULL, 0); + hash->digested += dig; + if (hash->digested >= hash->block) + force_hash(work, hash); + if (work->needed < work->filled) { + if (tmp_size > 0) + SAFE_FREE2(save, tmp_size); + return (1); + } + } + if (tmp_size > 0) + SAFE_FREE2(save, tmp_size); + return (0); +} + +/* + * Copy data from INPUT for length SIZE into the work-block TMP. + * If we fill the work-block, digest it; then, + * if work-block needs more data, keep filling with the rest of the input. + */ +static int +my_digest(dst_work *work, const u_char *input, int size) +{ + + int i, full = 0; + static unsigned counter; + + counter += size; + /* first do each one of the hashes */ + for (i = 0; i < DST_NUM_HASHES && full == 0; i++) + full = do_hash(work, work->hash[i], input, size) + + do_hash(work, work->hash[i], (u_char *) &counter, + sizeof(counter)); +/* + * if enough data has be generated do final operation on all hashes + * that have enough date for that + */ + for (i = 0; full && (i < DST_NUM_HASHES); i++) + force_hash(work, work->hash[i]); + + return (full); +} + +/* + * this function gets some semi random data and sets that as an HMAC key + * If we get a valid key this function returns that key initalized + * otherwise it returns NULL; + */ +static prand_hash * +get_hmac_key(int step, int block) +{ + + u_char *buff; + int temp = 0, n = 0, size = 70; + DST_KEY *new_key = NULL; + prand_hash *new = NULL; + + /* use key that is larger than digest algorithms (64) for key size */ + buff = malloc(size); + if (buff == NULL) + return (NULL); + /* do not memset the allocated memory to get random bytes there */ + /* time of day is somewhat random expecialy in the last bytes */ + gettimeofday((struct timeval *) &buff[n], NULL); + n += sizeof(struct timeval); + +/* get some semi random stuff in here stir it with micro seconds */ + if (n < size) { + temp = dst_s_quick_random((int) buff[n - 1]); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* get the pid of this process and its parent */ + if (n < size) { + temp = (int) getpid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } + if (n < size) { + temp = (int) getppid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* get the user ID */ + if (n < size) { + temp = (int) getuid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +#ifndef GET_HOST_ID_MISSING + if (n < size) { + temp = (int) gethostid(); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +#endif +/* get some more random data */ + if (n < size) { + temp = dst_s_quick_random((int) buff[n - 1]); + memcpy(&buff[n], &temp, sizeof(temp)); + n += sizeof(temp); + } +/* covert this into a HMAC key */ + new_key = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, buff, size); + SAFE_FREE(buff); + +/* get the control structure */ + if ((new = malloc(sizeof(prand_hash))) == NULL) + return (NULL); + new->digested = new->curr = 0; + new->step = step; + new->block = block; + new->key = new_key; + if (dst_sign_data(SIG_MODE_INIT, new_key, &new->ctx, NULL, 0, NULL, 0)) + return (NULL); + + return (new); +} + +/* + * own_random() + * This function goes out and from various sources tries to generate enough + * semi random data that a hash function can generate a random data. + * This function will iterate between the two main random source sources, + * information from programs and directores in random order. + * This function return the number of bytes added to the random output buffer. + */ +static int +own_random(dst_work *work) +{ + int dir = 0, b; + int bytes, n, cmd = 0, dig = 0; + int start =0; +/* + * now get the initial seed to put into the quick random function from + * the address of the work structure + */ + bytes = (int) getpid(); +/* + * proceed while needed + */ + while (work->filled < work->needed) { + EREPORT(("own_random r %08x b %6d f %6d\n", + ran_val, bytes, work->filled)); +/* pick a random number in the range of 0..7 based on that random number + * perform some operations that yield random data + */ + start = work->filled; + n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07; + switch (n) { + case 0: + case 3: + if (sizeof(cmds) > 2 *sizeof(*cmds)) { + b = unix_cmd(work); + cmd += b; + } + break; + + case 1: + case 7: + if (sizeof(dirs) > 2 *sizeof(*dirs)) { + b = do_ls(work); + dir += b; + } + break; + + case 4: + case 5: + /* retry getting data from /dev/random */ + b = get_dev_random(&work->output[work->filled], + work->needed - work->filled); + if (b > 0) + work->filled += b; + break; + + case 6: + if (sizeof(files) > 2 * sizeof(*files)) { + b = digest_file(work); + dig += b; + } + break; + + case 2: + default: /* to make sure we make some progress */ + work->output[work->filled++] = 0xff & + dst_s_quick_random(bytes); + b = 1; + break; + } + if (b > 0) + bytes += b; + } + return (work->filled); +} + + +/* + * dst_s_random() This function will return the requested number of bytes + * of randomness to the caller it will use the best available sources of + * randomness. + * The current order is to use /dev/random, precalculated randomness, and + * finaly use some system calls and programs to generate semi random data that + * is then digested to generate randomness. + * This function is thread safe as each thread uses its own context, but + * concurrent treads will affect each other as they update shared state + * information. + * It is strongly recommended that this function be called requesting a size + * that is not a multiple of the output of the hash function used. + * + * If /dev/random is not available this function is not suitable to generate + * large ammounts of data, rather it is suitable to seed a pseudo-random + * generator + * Returns the number of bytes put in the output buffer + */ +int +dst_s_random(u_char *output, int size) +{ + int n = 0, s, i; + static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES]; + static int unused = 0; + + if (size <= 0 || output == NULL) + return (0); + + if (size >= 2048) + return (-1); + /* + * Read from /dev/random + */ + n = get_dev_random(output, size); + /* + * If old data is available and needed use it + */ + if (n < size && unused > 0) { + int need = size - n; + if (unused <= need) { + memcpy(output, old_unused, unused); + n += unused; + unused = 0; + } else { + memcpy(output, old_unused, need); + n += need; + unused -= need; + memcpy(old_unused, &old_unused[need], unused); + } + } + /* + * If we need more use the simulated randomness here. + */ + if (n < size) { + dst_work *my_work = (dst_work *) malloc(sizeof(dst_work)); + if (my_work == NULL) + return (n); + my_work->needed = size - n; + my_work->filled = 0; + my_work->output = (u_char *) malloc(my_work->needed + + DST_HASH_SIZE * + DST_NUM_HASHES); + my_work->file_digest = NULL; + if (my_work->output == NULL) + return (n); + memset(my_work->output, 0x0, my_work->needed); +/* allocate upto 4 different HMAC hash functions out of order */ +#if DST_NUM_HASHES >= 3 + my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2); +#endif +#if DST_NUM_HASHES >= 2 + my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6); +#endif +#if DST_NUM_HASHES >= 4 + my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4); +#endif + my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE); + if (my_work->hash[0] == NULL) /* if failure bail out */ + return (n); + s = own_random(my_work); +/* if more generated than needed store it for future use */ + if (s >= my_work->needed) { + EREPORT(("dst_s_random(): More than needed %d >= %d\n", + s, my_work->needed)); + memcpy(&output[n], my_work->output, my_work->needed); + n += my_work->needed; + /* saving unused data for next time */ + unused = s - my_work->needed; + memcpy(old_unused, &my_work->output[my_work->needed], + unused); + } else { + /* XXXX This should not happen */ + EREPORT(("Not enough %d >= %d\n", s, my_work->needed)); + memcpy(&output[n], my_work->output, s); + n += my_work->needed; + } + +/* delete the allocated work area */ + for (i = 0; i < DST_NUM_HASHES; i++) { + dst_free_key(my_work->hash[i]->key); + SAFE_FREE(my_work->hash[i]); + } + SAFE_FREE(my_work->output); + SAFE_FREE(my_work); + } + return (n); +} + +/* + * A random number generator that is fast and strong + * this random number generator is based on HASHing data, + * the input to the digest function is a collection of <NUMBER_OF_COUNTERS> + * counters that is incremented between digest operations + * each increment operation amortizes to 2 bits changed in that value + * for 5 counters thus the input will amortize to have 10 bits changed + * The counters are initaly set using the strong random function above + * the HMAC key is selected by the same methold as the HMAC keys for the + * strong random function. + * Each set of counters is used for 2^25 operations + * + * returns the number of bytes written to the output buffer + * or negative number in case of error + */ +int +dst_s_semi_random(u_char *output, int size) +{ + static u_int32_t counter[DST_NUMBER_OF_COUNTERS]; + static u_char semi_old[DST_HASH_SIZE]; + static int semi_loc = 0, cnt = 0, hb_size = 0; + static DST_KEY *my_key = NULL; + prand_hash *hash; + int out = 0, i, n; + + if (output == NULL || size <= 0) + return (-2); + +/* check if we need a new key */ + if (my_key == NULL || cnt > (1 << 25)) { /* get HMAC KEY */ + if (my_key) + my_key->dk_func->destroy(my_key); + if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL) + return (0); + my_key = hash->key; +/* check if the key works stir the new key using some old random data */ + hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL, + (u_char *) counter, sizeof(counter), + semi_old, sizeof(semi_old)); + if (hb_size <= 0) { + EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n", + my_key->dk_alg, hb_size)); + return (-1); + } +/* new set the counters to random values */ + dst_s_random((u_char *) counter, sizeof(counter)); + cnt = 0; + } +/* if old data around use it first */ + if (semi_loc < hb_size) { + if (size <= hb_size - semi_loc) { /* need less */ + memcpy(output, &semi_old[semi_loc], size); + semi_loc += size; + return (size); /* DONE */ + } else { + out = hb_size - semi_loc; + memcpy(output, &semi_old[semi_loc], out); + semi_loc += out; + } + } +/* generate more randome stuff */ + while (out < size) { + /* + * modify at least one bit by incrementing at least one counter + * based on the last bit of the last counter updated update + * the next one. + * minimaly this operation will modify at least 1 bit, + * amortized 2 bits + */ + for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++) + i = (int) counter[n]++; + + i = dst_sign_data(SIG_MODE_ALL, my_key, NULL, + (u_char *) counter, hb_size, + semi_old, sizeof(semi_old)); +#ifdef REPORT_ERRORS + if (i != hb_size) + EREPORT(("HMAC SIGNATURE FAILURE %d\n", i)); +#endif + cnt++; + if (size - out < i) /* Not all data is needed */ + semi_loc = i = size - out; + memcpy(&output[out], semi_old, i); + out += i; + } + return (out); +} diff --git a/usr/src/lib/libresolv2/common/dst/rsaref_link.c b/usr/src/lib/libresolv2/common/dst/rsaref_link.c new file mode 100644 index 0000000000..b18d694825 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/rsaref_link.c @@ -0,0 +1,768 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef RSAREF +static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/rsaref_link.c,v 1.10 2001/05/29 05:48:15 marka Exp $"; + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ + +/* + * This file contains two components + * 1. Interface to the rsaref library to allow compilation when RSAREF is + * not available all calls to RSAREF are contained inside this file. + * 2. The glue to connvert RSA{REF} KEYS to and from external formats + */ +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <sys/param.h> +#include <sys/time.h> +#include <netinet/in.h> + +#include "dst_internal.h" + +# ifdef __STDC__ +# define PROTOTYPES 1 +# else +# define PROTOTYPES 0 +# endif + +# include <global.h> +# include <rsaref.h> + +#include "port_after.h" + + +typedef struct rsakey { + char *rk_signer; + R_RSA_PRIVATE_KEY *rk_Private_Key; + R_RSA_PUBLIC_KEY *rk_Public_Key; +} RSA_Key; + + +static int dst_rsaref_sign(const int mode, DST_KEY *key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len); +static int dst_rsaref_verify(const int mode, DST_KEY *key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len); + +static int dst_rsaref_to_dns_key(const DST_KEY *public, u_char *out_str, + const int out_len); +static int dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key, + const int len); + +static int dst_rsaref_key_to_file_format(const DST_KEY *dkey, + u_char *buff, + const int buff_len); +static int dst_rsaref_key_from_file_format(DST_KEY *dkey, + const u_char *buff, + const int buff_len); + +static int dst_rsaref_compare_keys(const DST_KEY *rkey1, + const DST_KEY *rkey2); +static void *dst_rsaref_free_key_structure(void *d_key); + +static int dst_rsaref_generate_keypair(DST_KEY *key, const int exp); + +static void dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct); + +/* + * dst_rsaref_init() Function to answer set up function pointers for RSAREF + * related functions + */ +int +dst_rsaref_init() +{ + if (dst_t_func[KEY_RSA] != NULL) + return (1); + dst_t_func[KEY_RSA] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_RSA] == NULL) + return (0); + memset(dst_t_func[KEY_RSA], 0, sizeof(struct dst_func)); + dst_t_func[KEY_RSA]->sign = dst_rsaref_sign; + dst_t_func[KEY_RSA]->verify = dst_rsaref_verify; + dst_t_func[KEY_RSA]->compare = dst_rsaref_compare_keys; + dst_t_func[KEY_RSA]->generate = dst_rsaref_generate_keypair; + dst_t_func[KEY_RSA]->destroy = dst_rsaref_free_key_structure; + dst_t_func[KEY_RSA]->to_dns_key = dst_rsaref_to_dns_key; + dst_t_func[KEY_RSA]->from_dns_key = dst_rsaref_from_dns_key; + dst_t_func[KEY_RSA]->to_file_fmt = dst_rsaref_key_to_file_format; + dst_t_func[KEY_RSA]->from_file_fmt = dst_rsaref_key_from_file_format; + return (1); +} + +/* + * dst_rsa_sign + * Call RSAREF signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * key pointer to a RSA key structure that points to public key + * and context to use. + * data data to be signed. + * len length in bytes of data. + * signature location to store signature. + * sig_len size of the signature storage area + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + + +static int +dst_rsaref_sign(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + int sign_len = 0; + R_SIGNATURE_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = malloc(sizeof(*ctx)); + else if (context) + ctx = (R_SIGNATURE_CTX *) *context; + if (ctx == NULL) + return (-1); + + if ((mode & SIG_MODE_INIT) && R_SignInit(ctx, DA_MD5)) + return (SIGN_INIT_FAILURE); + + /* equivalent of SIG_MODE_UPDATE */ + if ((mode & SIG_MODE_UPDATE) && (data && len > 0) && + R_SignUpdate(ctx, (u_char *) data, len)) + return (SIGN_UPDATE_FAILURE); + + if (mode & SIG_MODE_FINAL) { + RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct; + if (signature == NULL || + sig_len < (int)(key->rk_Public_Key->bits + 7) / 8) + return (SIGN_FINAL_FAILURE); + if(key == NULL || key->rk_Private_Key == NULL) + return (-1); + if (R_SignFinal(ctx, signature, &sign_len, + key->rk_Private_Key)) + return (SIGN_FINAL_FAILURE); + SAFE_FREE(ctx); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/* + * dst_rsaref_verify() + * Calls RSAREF verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * key pointer to a RSA key structure that points to public key + * and context to use. + * data data signed. + * len length in bytes of data. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_rsaref_verify(const int mode, DST_KEY *dkey, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + R_SIGNATURE_CTX *ctx = NULL; + + if (mode & SIG_MODE_INIT) + ctx = malloc(sizeof(*ctx)); + else if (context) + ctx = (R_SIGNATURE_CTX *) *context; + if (ctx == NULL) + return (-1); + + if ((mode & SIG_MODE_INIT) && R_VerifyInit(ctx, DA_MD5)) + return (VERIFY_INIT_FAILURE); + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0) && + R_VerifyUpdate(ctx, (u_char *) data, len)) + return (VERIFY_UPDATE_FAILURE); + + if ((mode & SIG_MODE_FINAL)) { + RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct; + + if (key == NULL || key->rk_Public_Key == NULL) + return (-1); + if (signature == NULL || sig_len <= 0) + return (VERIFY_FINAL_FAILURE); + if (R_VerifyFinal(ctx, (u_char *) signature, sig_len, + key->rk_Public_Key)) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + + return (0); +} + + +/* + * dst_rsaref_to_dns_key + * Converts key in RSAREF to DNS distribution format + * This function gets in a pointer to the public key and a work area + * to write the key into. + * Parameters + * public KEY structure + * out_str buffer to write encoded key into + * out_len size of out_str + * Return + * N >= 0 length of encoded key + * n < 0 error + */ + +static int +dst_rsaref_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + int n, loc; + R_RSA_PUBLIC_KEY *public; + u_char *op = (u_char *) out_str; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= 0 || out_str == NULL) + return (-1); + public = (R_RSA_PUBLIC_KEY *) + ((RSA_Key *) in_key->dk_KEY_struct)->rk_Public_Key; + if (public == NULL) + return (-1); + + memset(op, 0, out_len); + + /* find first non zero */ + for (n = 0; public->exponent[n] == 0x0; n++) ; + + n = (MAX_RSA_MODULUS_LEN - n); /* find lenght of exponent */ + *op++ = (u_int8_t) n; + + if (n > (out_len - (op-out_str))) + return (-1); + memcpy(op, &public->exponent[MAX_RSA_MODULUS_LEN - n], n); + op += n; + n++; /* include the lenght field in this count */ + + /* find first non zero */ + for (loc = 0; public->modulus[loc] == 0x0; loc++) ; + + /*copy exponent */ + if ((MAX_RSA_MODULUS_LEN - loc) > (out_len - (op-out_str))) + return (-1); + memcpy(op, &public->modulus[loc], MAX_RSA_MODULUS_LEN - loc); + n += (MAX_RSA_MODULUS_LEN - loc); + return (n); +} + + +/* + * dst_rsaref_from_dns_key + * Converts from a DNS KEY RR format to an RSA KEY. + * Parameters + * len Length in bytes of DNS key + * key DNS key + * name Key name + * s_key DST structure that will point to the RSA key this routine + * will build. + * Return + * -1 The input key has fields that are larger than this package supports + * 0 The input key, s_key or name was null. + * 1 Success + */ +static int +dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key, const int len) +{ + int bytes; + u_char *key_ptr; + RSA_Key *r_key; + + if (key == NULL || s_key == NULL || len < 0) + return (0); + + if (s_key->dk_KEY_struct) { /* do not reuse */ + dst_rsaref_free_key_structure(s_key->dk_KEY_struct); + s_key->dk_KEY_struct = NULL; + } + if (len == 0) /* null key no conversion needed */ + return (1); + + if ((r_key = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 1\n")); + return (0); + } + memset(r_key, 0, sizeof(RSA_Key)); + s_key->dk_KEY_struct = (void *) r_key; + r_key->rk_signer = strdup(s_key->dk_key_name); + r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *) + malloc(sizeof(R_RSA_PUBLIC_KEY)); + if (r_key->rk_Public_Key == NULL) { + EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 3\n")); + return (0); + } + memset(r_key->rk_Public_Key, 0, sizeof(R_RSA_PUBLIC_KEY)); + key_ptr = (u_char *) key; + bytes = (int) *key_ptr++; /* length of exponent in bytes */ + if (bytes == 0) { /* special case for long exponents */ + bytes = (int) dst_s_get_int16(key_ptr); + key_ptr += sizeof(u_int16_t); + } + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_rsaref_free_key_structure(r_key); + return (-1); + } + memcpy(&r_key->rk_Public_Key->exponent[MAX_RSA_MODULUS_LEN - bytes], + key_ptr, bytes); + + key_ptr += bytes; /* beginning of modulus */ + bytes = len - bytes - 1; /* length of modulus */ + if (bytes > MAX_RSA_MODULUS_LEN) { + dst_rsaref_free_key_structure(r_key); + return (-1); + } + memcpy(&r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - bytes], + key_ptr, bytes); + r_key->rk_Public_Key->bits = bytes * 8; + s_key->dk_key_size = r_key->rk_Public_Key->bits; + + return (1); +} + + +/* + * dst_rsaref_key_to_file_format + * Encodes an RSA Key into the portable file format. + * Parameters + * rkey RSA KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input rkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_rsaref_key_to_file_format(const DST_KEY *in_key, u_char *buff, + const int buff_len) +{ + u_char *bp; + int len, b_len; + R_RSA_PRIVATE_KEY *rkey; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL) + return (-1); + rkey = (R_RSA_PRIVATE_KEY *) + ((RSA_Key *) in_key->dk_KEY_struct)->rk_Private_Key; + if (rkey == NULL) /* no output */ + return (0); + if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str)) + return (-1); /* no OR not enough space in output area */ + + memset(buff, 0, buff_len); /* just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_RSA, "RSA"); + + bp = (char *) strchr(buff, '\0'); + b_len = buff_len - (bp - buff); + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Modulus: ", + rkey->modulus, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-1); + + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PublicExponent: ", + rkey->publicExponent, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-2); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PrivateExponent: ", + rkey->exponent, + MAX_RSA_MODULUS_LEN)) <= 0) + return (-3); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime1: ", + rkey->prime[0], + MAX_RSA_PRIME_LEN)) < 0) + return (-4); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime2: ", + rkey->prime[1], + MAX_RSA_PRIME_LEN)) < 0) + return (-5); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent1: ", + rkey->primeExponent[0], + MAX_RSA_PRIME_LEN)) < 0) + return (-6); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent2: ", + rkey->primeExponent[1], + MAX_RSA_PRIME_LEN)) < 0) + return (-7); + bp += len; + b_len -= len; + if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Coefficient: ", + rkey->coefficient, + MAX_RSA_PRIME_LEN)) < 0) + return (-8); + bp += len; + b_len -= len; + return (buff_len - b_len); +} + + +/* + * dst_rsaref_key_from_file_format + * Converts contents of a private key file into a private RSA key. + * Parameters + * r_key structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_rsaref_key_from_file_format(DST_KEY *d_key, const u_char *buff, + const int buff_len) +{ + const char *p = (char *) buff; + R_RSA_PRIVATE_KEY key; + int foot = -1; + RSA_Key *r_key; + + if (d_key == NULL || buff == NULL || buff_len < 0) + return (-1); + + memset(&key, 0, sizeof(key)); + + if (!dst_s_verify_str(&p, "Modulus: ")) + return (-3); + + if (!dst_s_conv_bignum_b64_to_u8(&p, key.modulus, MAX_RSA_MODULUS_LEN)) + return (-4); + + key.bits = dst_s_calculate_bits(key.modulus, MAX_RSA_MODULUS_BITS); + + while (*++p && p < (char *) &buff[buff_len]) { + if (dst_s_verify_str(&p, "PublicExponent: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.publicExponent, + MAX_RSA_MODULUS_LEN)) + return (-5); + } else if (dst_s_verify_str(&p, "PrivateExponent: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.exponent, + MAX_RSA_MODULUS_LEN)) + return (-6); + } else if (dst_s_verify_str(&p, "Prime1: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.prime[0], + MAX_RSA_PRIME_LEN)) + return (-7); + } else if (dst_s_verify_str(&p, "Prime2: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.prime[1], + MAX_RSA_PRIME_LEN)) + return (-8); + } else if (dst_s_verify_str(&p, "Exponent1: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.primeExponent[0], + MAX_RSA_PRIME_LEN)) + return (-9); + } else if (dst_s_verify_str(&p, "Exponent2: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, + key.primeExponent[1], + MAX_RSA_PRIME_LEN)) + return (-10); + } else if (dst_s_verify_str(&p, "Coefficient: ")) { + if (!dst_s_conv_bignum_b64_to_u8(&p, key.coefficient, + MAX_RSA_PRIME_LEN)) + return (-11); + } else { + EREPORT(("dst_rsaref_key_from_file_format: Bad keyword %s\n", p)); + return (-12); + } + } /* while p */ + + r_key = (RSA_Key *) malloc(sizeof(RSA_Key)); + if (r_key == NULL) { + return (-2); + } + memset(r_key, 0, sizeof(*r_key)); + + r_key->rk_Private_Key = + (R_RSA_PRIVATE_KEY *) malloc(sizeof(R_RSA_PRIVATE_KEY)); + if (r_key->rk_Private_Key == NULL) { + EREPORT(("dst_rsaref_key_from_file_format: Memory allocation error\n")); + return (-13); + } + r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *) r_key->rk_Private_Key; + memcpy(r_key->rk_Private_Key, &key, sizeof(R_RSA_PRIVATE_KEY)); + + r_key->rk_signer = strdup(d_key->dk_key_name); + d_key->dk_KEY_struct = (void *) r_key; + d_key->dk_key_size = r_key->rk_Private_Key->bits; + + return (0); +} + + + +/* + * dst_rsaref_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_rsaref_compare_keys(const DST_KEY *dkey1, const DST_KEY *dkey2) +{ + RSA_Key *rkey1 = (RSA_Key *) dkey1->dk_KEY_struct; + RSA_Key *rkey2 = (RSA_Key *) dkey2->dk_KEY_struct; + + if (rkey1 == NULL && rkey2 == NULL) + return (0); /* same */ + else if (rkey1 == NULL) + return (1); + else if (rkey2 == NULL) + return (2); + return (memcmp(rkey1->rk_Public_Key, rkey2->rk_Public_Key, + sizeof(R_RSA_PUBLIC_KEY))); +} + +/* + * dst_rsaref_generate_keypair + * Generates unique keys that are hard to predict. + * Parameters + * key generic Key structure + * exp the public exponent + * Return + * 0 Failure + * 1 Success + */ + +static int +dst_rsaref_generate_keypair(DST_KEY *key, const int exp) +{ + R_RSA_PUBLIC_KEY *public; + R_RSA_PRIVATE_KEY *private; + R_RSA_PROTO_KEY proto; + R_RANDOM_STRUCT randomStruct; + RSA_Key *rsa; + int status; + + if (key == NULL || key->dk_alg != KEY_RSA) + return (0); + if (key->dk_key_size < MIN_RSA_MODULUS_BITS || + key->dk_key_size > MAX_RSA_MODULUS_BITS) { + EREPORT(("dst_rsaref_generate_keypair: Invalid key size\n")); + return (0); /* these are the limits on key size in RSAREF */ + } + /* allocate space */ + if ((public = (R_RSA_PUBLIC_KEY *) malloc(sizeof(R_RSA_PUBLIC_KEY))) + == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 1\n")); + return (0); + } + if ((private = (R_RSA_PRIVATE_KEY *) malloc(sizeof(R_RSA_PRIVATE_KEY))) + == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 2\n")); + return (0); + } + if ((rsa = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) { + EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 3\n")); + return (0); + } + memset(public, 0, sizeof(*public)); + memset(private, 0, sizeof(*private)); + + proto.bits = key->dk_key_size; + proto.useFermat4 = exp ? 0x1 : 0x0; /* 1 for f4=65537, 0 for f0=3 */ + EREPORT(("\ndst_rsaref_generate_keypair: Generating KEY for %s Please wait\n", + key->dk_key_name)); + + /* set up random seed */ + dst_rsaref_init_random_struct(&randomStruct); + + /* generate keys */ + status = R_GeneratePEMKeys(public, private, &proto, &randomStruct); + if (status) { + EREPORT(("dst_rsaref_generate_keypair: No Key Pair generated %d\n", + status)); + SAFE_FREE(public); + SAFE_FREE(private); + SAFE_FREE(rsa); + return (0); + } + memset(rsa, 0, sizeof(*rsa)); + rsa->rk_signer = key->dk_key_name; + rsa->rk_Private_Key = private; + rsa->rk_Public_Key = public; + key->dk_KEY_struct = (void *) rsa; + + return (1); +} + + +/* + * dst_rsaref_free_key_structure + * Frees all dynamicly allocated structures in r_key + */ + +static void * +dst_rsaref_free_key_structure(void *v_key) +{ + RSA_Key *r_key = (RSA_Key *) v_key; + + if (r_key != NULL) { + if ((void *) r_key->rk_Private_Key == (void *) r_key->rk_Public_Key) + r_key->rk_Public_Key = NULL; + SAFE_FREE(r_key->rk_Private_Key); + SAFE_FREE(r_key->rk_Public_Key); + SAFE_FREE(r_key->rk_signer); + SAFE_FREE(r_key); + } + return (NULL); +} + + +/* + * dst_rsaref_init_random_struct + * A random seed value is used in key generation. + * This routine gets a bunch of system values to randomize the + * randomstruct. A number of system calls are used to get somewhat + * unpredicable values, then a special function dst_s_prandom() is called + * that will do some magic depending on the system used. + * If this function is executed on reasonably busy machine then the values + * that prandom uses are hard to + * 1. Predict + * 2. Regenerate + * 3. Hard to spy on as nothing is stored to disk and data is consumed + * as fast as it is generated. + */ + +static void +dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct) +{ + unsigned bytesNeeded; + struct timeval tv; + u_char *array; + int n; + + R_RandomInit(randomstruct); + + /* The runtime of the script is unpredictable within some range + * thus I'm getting the time of day again as this is an hard to guess + * value and the number of characters of the output from the script is + * hard to guess. + * This must be the FIRST CALL + */ + gettimeofday(&tv, 0); + R_RandomUpdate(randomstruct, (u_char *) &tv, + sizeof(struct timeval)); + + /* + * first find out how many bytes I need + */ + R_GetRandomBytesNeeded(&bytesNeeded, randomstruct); + + /* + * get a storage area for it addjust the area for the possible + * side effects of digest functions writing out in blocks + */ + array = (u_char *) malloc(bytesNeeded); + + /* extract the random data from /dev/random if present, generate + * it if not present + * first fill the buffer with semi random data + * then fill as much as possible with good random data + */ + n = dst_random(DST_RAND_SEMI, bytesNeeded, array); + n += dst_random(DST_RAND_KEY, bytesNeeded, array); + if (n <= bytesNeeded) { + SAFE_FREE(array); + return(0); + } + + /* supply the random data (even if it is larger than requested) */ + R_RandomUpdate(randomstruct, array, bytesNeeded); + + SAFE_FREE(array); + + R_GetRandomBytesNeeded(&bytesNeeded, randomstruct); + if (bytesNeeded) { + EREPORT(("InitRandomStruct() didn't initialize enough randomness\n")); + exit(33); + } +} + + +#else +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <sys/param.h> +#include <sys/time.h> +#include <netinet/in.h> + +#include "dst_internal.h" +#include "port_after.h" +int /* rsaref is not available */ +dst_rsaref_init() +{ + return (0); +} +#endif /* RSAREF */ diff --git a/usr/src/lib/libresolv2/common/dst/support.c b/usr/src/lib/libresolv2/common/dst/support.c new file mode 100644 index 0000000000..4b3438f604 --- /dev/null +++ b/usr/src/lib/libresolv2/common/dst/support.c @@ -0,0 +1,465 @@ +static const char rcsid[] = "$Header: /proj/cvs/isc/bind8/src/lib/dst/support.c,v 1.11 2001/05/29 05:48:16 marka Exp $"; + +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * Permission to use, copy modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. + */ + +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <memory.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include "dst_internal.h" + +#include "port_after.h" +/* + * dst_s_conv_bignum_u8_to_b64 + * This function converts binary data stored as a u_char[] to a + * base-64 string. Leading zeroes are discarded. If a header is + * supplied, it is prefixed to the input prior to encoding. The + * output is \n\0 terminated (the \0 is not included in output length). + * Parameters + * out_buf binary data to convert + * header character string to prefix to the output (label) + * bin_data binary data + * bin_len size of binary data + * Return + * -1 not enough space in output work area + * 0 no output + * >0 number of bytes written to output work area + */ + +int +dst_s_conv_bignum_u8_to_b64(char *out_buf, const int out_len, + const char *header, const u_char *bin_data, + const int bin_len) +{ + const u_char *bp = bin_data; + char *op = out_buf; + int lenh = 0, len64 = 0; + int local_in_len = bin_len; + int local_out_len = out_len; + + if (bin_data == NULL || bin_len <= 0) /* no data no */ + return (0); + + if (out_buf == NULL || out_len <= 0) /* no output_work area */ + return (-1); + + /* suppress leading \0 */ + for (; (*bp == 0x0) && (local_in_len > 0); local_in_len--) + bp++; + + if (header) { /* add header to output string */ + lenh = strlen(header); + if (lenh < out_len) + memcpy(op, header, lenh); + else + return (-1); + local_out_len -= lenh; + op += lenh; + } + len64 = b64_ntop(bp, local_in_len, op, local_out_len - 2); + if (len64 < 0) + return (-1); + op += len64++; + *(op++) = '\n'; /* put CR in the output */ + *op = '\0'; /* make sure output is 0 terminated */ + return (lenh + len64); +} + + +/* + * dst_s_verify_str() + * Validate that the input string(*str) is at the head of the input + * buffer(**buf). If so, move the buffer head pointer (*buf) to + * the first byte of data following the string(*str). + * Parameters + * buf Input buffer. + * str Input string. + * Return + * 0 *str is not the head of **buff + * 1 *str is the head of **buff, *buf is is advanced to + * the tail of **buf. + */ + +int +dst_s_verify_str(const char **buf, const char *str) +{ + int b, s; + if (*buf == NULL) /* error checks */ + return (0); + if (str == NULL || *str == '\0') + return (1); + + b = strlen(*buf); /* get length of strings */ + s = strlen(str); + if (s > b || strncmp(*buf, str, s)) /* check if same */ + return (0); /* not a match */ + (*buf) += s; /* advance pointer */ + return (1); +} + + +/* + * dst_s_conv_bignum_b64_to_u8 + * Read a line of base-64 encoded string from the input buffer, + * convert it to binary, and store it in an output area. The + * input buffer is read until reaching a newline marker or the + * end of the buffer. The binary data is stored in the last X + * number of bytes of the output area where X is the size of the + * binary output. If the operation is successful, the input buffer + * pointer is advanced. This procedure does not do network to host + * byte order conversion. + * Parameters + * buf Pointer to encoded input string. Pointer is updated if + * function is successfull. + * loc Output area. + * loclen Size in bytes of output area. + * Return + * >0 Return = number of bytes of binary data stored in loc. + * 0 Failure. + */ + +int +dst_s_conv_bignum_b64_to_u8(const char **buf, u_char *loc, const int loclen) +{ + int blen; + char *bp; + u_char bstr[RAW_KEY_SIZE]; + + if (buf == NULL || *buf == NULL) { /* error checks */ + EREPORT(("dst_s_conv_bignum_b64_to_u8: null input buffer.\n")); + return (0); + } + bp = strchr(*buf, '\n'); /* find length of input line */ + if (bp != NULL) + *bp = (u_char) NULL; + + blen = b64_pton(*buf, bstr, sizeof(bstr)); + if (blen <= 0) { + EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is null.\n")); + return (0); + } + else if (loclen < blen) { + EREPORT(("dst_s_conv_bignum_b64_to_u8: decoded value is longer than output buffer.\n")); + return (0); + } + if (bp) + *buf = bp; /* advancing buffer past \n */ + memset(loc, 0, loclen - blen); /* clearing unused output area */ + memcpy(loc + loclen - blen, bstr, blen); /* write last blen bytes */ + return (blen); +} + + +/* + * dst_s_calculate_bits + * Given a binary number represented in a u_char[], determine + * the number of significant bits used. + * Parameters + * str An input character string containing a binary number. + * max_bits The maximum possible significant bits. + * Return + * N The number of significant bits in str. + */ + +int +dst_s_calculate_bits(const u_char *str, const int max_bits) +{ + const u_char *p = str; + u_char i, j = 0x80; + int bits; + for (bits = max_bits; *p == 0x00 && bits > 0; p++) + bits -= 8; + for (i = *p; (i & j) != j; j >>= 1) + bits--; + return (bits); +} + + +/* + * calculates a checksum used in dst for an id. + * takes an array of bytes and a length. + * returns a 16 bit checksum. + */ +u_int16_t +dst_s_id_calc(const u_char *key, const int keysize) +{ + u_int32_t ac; + const u_char *kp = key; + int size = keysize; + + if (!key || (keysize <= 0)) + return (-1); + + for (ac = 0; size > 1; size -= 2, kp += 2) + ac += ((*kp) << 8) + *(kp + 1); + + if (size > 0) + ac += ((*kp) << 8); + ac += (ac >> 16) & 0xffff; + + return (ac & 0xffff); +} + +/* + * dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record + * rdata + * Input: + * dns_key_rdata: the raw data in wire format + * rdata_len: the size of the input data + * Output: + * the key footprint/id calculated from the key data + */ +u_int16_t +dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len) +{ + if (!dns_key_rdata) + return 0; + + /* compute id */ + if (dns_key_rdata[3] == KEY_RSA) /* Algorithm RSA */ + return dst_s_get_int16((const u_char *) + &dns_key_rdata[rdata_len - 3]); + else if (dns_key_rdata[3] == KEY_HMAC_MD5) + /* compatibility */ + return 0; + else + /* compute a checksum on the key part of the key rr */ + return dst_s_id_calc(dns_key_rdata, rdata_len); +} + +/* + * dst_s_get_int16 + * This routine extracts a 16 bit integer from a two byte character + * string. The character string is assumed to be in network byte + * order and may be unaligned. The number returned is in host order. + * Parameter + * buf A two byte character string. + * Return + * The converted integer value. + */ + +u_int16_t +dst_s_get_int16(const u_char *buf) +{ + register u_int16_t a = 0; + a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1])); + return (a); +} + + +/* + * dst_s_get_int32 + * This routine extracts a 32 bit integer from a four byte character + * string. The character string is assumed to be in network byte + * order and may be unaligned. The number returned is in host order. + * Parameter + * buf A four byte character string. + * Return + * The converted integer value. + */ + +u_int32_t +dst_s_get_int32(const u_char *buf) +{ + register u_int32_t a = 0; + a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) | + ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3])); + return (a); +} + + +/* + * dst_s_put_int16 + * Take a 16 bit integer and store the value in a two byte + * character string. The integer is assumed to be in network + * order and the string is returned in host order. + * + * Parameters + * buf Storage for a two byte character string. + * val 16 bit integer. + */ + +void +dst_s_put_int16(u_int8_t *buf, const u_int16_t val) +{ + buf[0] = (u_int8_t)(val >> 8); + buf[1] = (u_int8_t)(val); +} + + +/* + * dst_s_put_int32 + * Take a 32 bit integer and store the value in a four byte + * character string. The integer is assumed to be in network + * order and the string is returned in host order. + * + * Parameters + * buf Storage for a four byte character string. + * val 32 bit integer. + */ + +void +dst_s_put_int32(u_int8_t *buf, const u_int32_t val) +{ + buf[0] = (u_int8_t)(val >> 24); + buf[1] = (u_int8_t)(val >> 16); + buf[2] = (u_int8_t)(val >> 8); + buf[3] = (u_int8_t)(val); +} + + +/* + * dst_s_filename_length + * + * This function returns the number of bytes needed to hold the + * filename for a key file. '/', '\' and ':' are not allowed. + * form: K<keyname>+<alg>+<id>.<suffix> + * + * Returns 0 if the filename would contain either '\', '/' or ':' + */ +size_t +dst_s_filename_length(const char *name, const char *suffix) +{ + if (name == NULL) + return (0); + if (strrchr(name, '\\')) + return (0); + if (strrchr(name, '/')) + return (0); + if (strrchr(name, ':')) + return (0); + if (suffix == NULL) + return (0); + if (strrchr(suffix, '\\')) + return (0); + if (strrchr(suffix, '/')) + return (0); + if (strrchr(suffix, ':')) + return (0); + return (1 + strlen(name) + 6 + strlen(suffix)); +} + + +/* + * dst_s_build_filename () + * Builds a key filename from the key name, it's id, and a + * suffix. '\', '/' and ':' are not allowed. fA filename is of the + * form: K<keyname><id>.<suffix> + * form: K<keyname>+<alg>+<id>.<suffix> + * + * Returns -1 if the conversion fails: + * if the filename would be too long for space allotted + * if the filename would contain a '\', '/' or ':' + * Returns 0 on success + */ + +int +dst_s_build_filename(char *filename, const char *name, u_int16_t id, + int alg, const char *suffix, size_t filename_length) +{ + u_int32_t my_id; + if (filename == NULL) + return (-1); + memset(filename, 0, filename_length); + if (name == NULL) + return (-1); + if (suffix == NULL) + return (-1); + if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix)) + return (-1); + my_id = id; + sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id, + (const char *) suffix); + if (strrchr(filename, '/')) + return (-1); + if (strrchr(filename, '\\')) + return (-1); + if (strrchr(filename, ':')) + return (-1); + return (0); +} + +/* + * dst_s_fopen () + * Open a file in the dst_path directory. If perm is specified, the + * file is checked for existence first, and not opened if it exists. + * Parameters + * filename File to open + * mode Mode to open the file (passed directly to fopen) + * perm File permission, if creating a new file. + * Returns + * NULL Failure + * NON-NULL (FILE *) of opened file. + */ +FILE * +dst_s_fopen(const char *filename, const char *mode, int perm) +{ + FILE *fp; + char pathname[PATH_MAX]; + size_t plen = sizeof(pathname); + + if (*dst_path != '\0') { + strcpy(pathname, dst_path); + plen -= strlen(pathname); + } + else + pathname[0] = '\0'; + + if (plen > strlen(filename)) + strncpy(&pathname[PATH_MAX - plen], filename, plen-1); + else + return (NULL); + + fp = fopen(pathname, mode); + if (perm) + chmod(pathname, perm); + return (fp); +} + +void +dst_s_dump(const int mode, const u_char *data, const int size, + const char *msg) +{ + UNUSED(data); + + if (size > 0) { +#ifdef LONG_TEST + static u_char scratch[1000]; + int n ; + n = b64_ntop(data, scratch, size, sizeof(scratch)); + printf("%s: %x %d %s\n", msg, mode, n, scratch); +#else + printf("%s,%x %d\n", msg, mode, size); +#endif + } +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_addr.c b/usr/src/lib/libresolv2/common/inet/inet_addr.c new file mode 100644 index 0000000000..06fe73bd4e --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_addr.c @@ -0,0 +1,79 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1983, 1990, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * inet_aton() has been moved to usr/src/lib/libnsl/rpc/inet_ntoa.c + */ +#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/lib/libresolv2/common/inet/inet_cidr_ntop.c b/usr/src/lib/libresolv2/common/inet/inet_cidr_ntop.c new file mode 100644 index 0000000000..738d82d3dd --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_cidr_ntop.c @@ -0,0 +1,266 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 8.7 2001/09/28 05:19:36 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_cidr_ntop_ipv4 __P((const u_char *src, int bits, + char *dst, size_t size)); +static char * inet_cidr_ntop_ipv6 __P((const u_char *src, int bits, + char *dst, size_t size)); + +/* + * char * + * inet_cidr_ntop(af, src, bits, dst, size) + * convert network address from network to presentation format. + * "src"'s size is determined from its "af". + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * 192.5.5.1/28 has a nonzero host part, which means it isn't a network + * as called for by inet_net_ntop() but it can be a host address with + * an included netmask. + * author: + * Paul Vixie (ISC), October 1998 + */ +char * +inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) { + switch (af) { + case AF_INET: + return (inet_cidr_ntop_ipv4(src, bits, dst, size)); + case AF_INET6: + return (inet_cidr_ntop_ipv6(src, bits, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +static int +decoct(const u_char *src, int bytes, char *dst, size_t size) { + char *odst = dst; + char *t; + int b; + + for (b = 1; b <= bytes; b++) { + if (size < sizeof "255.") + return (0); + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b != bytes) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + return (dst - odst); +} + +/* + * static char * + * inet_cidr_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network address from network to presentation format. + * "src"'s size is determined from its "af". + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), October 1998 + */ +static char * +inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) { + char *odst = dst; + size_t len = 4; + size_t b; + size_t bytes; + + if ((bits < -1) || (bits > 32)) { + errno = EINVAL; + return (NULL); + } + + /* Find number of significant bytes in address. */ + if (bits == -1) + len = 4; + else + for (len = 1, b = 1 ; b < 4; b++) + if (*(src + b)) + len = b + 1; + + /* Format whole octets plus nonzero trailing octets. */ + bytes = (((bits <= 0) ? 1 : bits) + 7) / 8; + if (len > bytes) + bytes = len; + b = decoct(src, bytes, dst, size); + if (b == 0) + goto emsgsize; + dst += b; + size -= b; + + if (bits != -1) { + /* Format CIDR /width. */ + if (size < sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + } + + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} + +static char * +inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"]; + char *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + if ((bits < -1) || (bits > 128)) { + errno = EINVAL; + return (NULL); + } + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff))) { + int n; + + if (src[15] || bits == -1 || bits > 120) + n = 4; + else if (src[14] || bits > 112) + n = 3; + else + n = 2; + n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp)); + if (n == 0) { + errno = EMSGSIZE; + return (NULL); + } + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp = '\0'; + + if (bits != -1) + tp += SPRINTF((tp, "/%u", bits)); + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = EMSGSIZE; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_cidr_pton.c b/usr/src/lib/libresolv2/common/inet/inet_cidr_pton.c new file mode 100644 index 0000000000..26fe2e926a --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_cidr_pton.c @@ -0,0 +1,282 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_cidr_pton.c,v 8.7 2001/09/28 04:21:28 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <isc/assertions.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst, + int *bits, int ipv6)); +static int inet_cidr_pton_ipv6 __P((const char *src, u_char *dst, + int *bits)); + +static int getbits(const char *, int ipv6); + +/* + * int + * inet_cidr_pton(af, src, dst, *bits) + * convert network address from presentation to network format. + * accepts inet_pton()'s input for this "af" plus trailing "/CIDR". + * "dst" is assumed large enough for its "af". "bits" is set to the + * /CIDR prefix length, which can have defaults (like /32 for IPv4). + * return: + * -1 if an error occurred (inspect errno; ENOENT means bad format). + * 0 if successful conversion occurred. + * note: + * 192.5.5.1/28 has a nonzero host part, which means it isn't a network + * as called for by inet_net_pton() but it can be a host address with + * an included netmask. + * author: + * Paul Vixie (ISC), October 1998 + */ +int +inet_cidr_pton(int af, const char *src, void *dst, int *bits) { + switch (af) { + case AF_INET: + return (inet_cidr_pton_ipv4(src, dst, bits, 0)); + case AF_INET6: + return (inet_cidr_pton_ipv6(src, dst, bits)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +static const char digits[] = "0123456789"; + +static int +inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) { + const u_char *odst = dst; + int n, ch, tmp, bits; + size_t size = 4; + + /* Get the mantissa. */ + while (ch = *src++, (isascii(ch) && isdigit(ch))) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (size-- == 0) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + } + + /* Get the prefix length if any. */ + bits = -1; + if (ch == '/' && dst > odst) { + bits = getbits(src, ipv6); + if (bits == -2) + goto enoent; + } else if (ch != '\0') + goto enoent; + + /* Prefix length can default to /32 only if all four octets spec'd. */ + if (bits == -1) { + if (dst - odst == 4) + bits = ipv6 ? 128 : 32; + else + goto enoent; + } + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + + /* If prefix length overspecifies mantissa, life is bad. */ + if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst)) + goto enoent; + + /* Extend address to four octets. */ + while (size-- > 0) + *dst++ = 0; + + *pbits = bits; + return (0); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static int +inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + int bits; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + bits = -1; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') { + return (0); + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + if (ch == '/') { + bits = getbits(src, 1); + if (bits == -2) + goto enoent; + break; + } + goto enoent; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + goto emsgsize; + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + goto enoent; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + + memcpy(dst, tmp, NS_IN6ADDRSZ); + + *pbits = bits; + return (0); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +int +getbits(const char *src, int ipv6) { + int bits = 0; + char *cp, ch; + + if (*src == '\0') /* syntax */ + return (-2); + do { + ch = *src++; + cp = strchr(digits, ch); + if (cp == NULL) /* syntax */ + return (-2); + bits *= 10; + bits += cp - digits; + if (bits == 0 && *src != '\0') /* no leading zeros */ + return (-2); + if (bits > (ipv6 ? 128 : 32)) /* range error */ + return (-2); + } while (*src != '\0'); + + return (bits); +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_data.c b/usr/src/lib/libresolv2/common/inet/inet_data.c new file mode 100644 index 0000000000..80a87e5660 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_data.c @@ -0,0 +1,51 @@ +/* + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_data.c,v 1.2 2001/06/20 22:06:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +const struct in6_addr isc_in6addr_any = IN6ADDR_ANY_INIT; +const struct in6_addr isc_in6addr_loopback = IN6ADDR_LOOPBACK_INIT; diff --git a/usr/src/lib/libresolv2/common/inet/inet_lnaof.c b/usr/src/lib/libresolv2/common/inet/inet_lnaof.c new file mode 100644 index 0000000000..0212d18f51 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_lnaof.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1983, 1993 + * The 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. + */ +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/* + * Return the local network address portion of an + * internet address; handles class a/b/c network + * number formats. + */ +#ifdef ORIGINAL_ISC_CODE +u_long +#else +in_addr_t +#endif +inet_lnaof(in) + struct in_addr in; +{ +#ifdef ORIGINAL_ISC_CODE + u_long i = ntohl(in.s_addr); +#else + in_addr_t i = ntohl(in.s_addr); +#endif + + if (IN_CLASSA(i)) + return ((i)&IN_CLASSA_HOST); + else if (IN_CLASSB(i)) + return ((i)&IN_CLASSB_HOST); + else + return ((i)&IN_CLASSC_HOST); +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_makeaddr.c b/usr/src/lib/libresolv2/common/inet/inet_makeaddr.c new file mode 100644 index 0000000000..59dc91d218 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_makeaddr.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1997-2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1983, 1993 + * The 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/* + * Formulate an Internet address from network + host. Used in + * building addresses stored in the ifnet structure. + */ +struct in_addr +inet_makeaddr(net, host) +#ifdef ORIGINAL_ISC_CODE + u_long net, host; +#else + in_addr_t net, host; +#endif +{ +#ifdef ORIGINAL_ISC_CODE + u_long addr; +#else + in_addr_t addr; + struct in_addr inaddr; +#endif + + if (net < 128) + addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + else if (net < 65536) + addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + else if (net < 16777216L) + addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + else + addr = net | host; +#ifdef ORIGINAL_ISC_CODE + addr = htonl(addr); + return (*(struct in_addr *)&addr); +#else + inaddr.s_addr = htonl(addr); + return (inaddr); +#endif +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_net_ntop.c b/usr/src/lib/libresolv2/common/inet/inet_net_ntop.c new file mode 100644 index 0000000000..0c77c1614a --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_net_ntop.c @@ -0,0 +1,284 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.8 2001/09/27 15:08:36 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits, + char *dst, size_t size)); +static char * inet_net_ntop_ipv6 __P((const u_char *src, int bits, + char *dst, size_t size)); + +/* + * char * + * inet_net_ntop(af, src, bits, dst, size) + * convert network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_net_ntop(af, src, bits, dst, size) + int af; + const void *src; + int bits; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_net_ntop_ipv4(src, bits, dst, size)); + case AF_INET6: + return (inet_net_ntop_ipv6(src, bits, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +/* + * static char * + * inet_net_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), July 1996 + */ +static char * +inet_net_ntop_ipv4(src, bits, dst, size) + const u_char *src; + int bits; + char *dst; + size_t size; +{ + char *odst = dst; + char *t; + u_int m; + int b; + + if (bits < 0 || bits > 32) { + errno = EINVAL; + return (NULL); + } + + if (bits == 0) { + if (size < sizeof "0") + goto emsgsize; + *dst++ = '0'; + size--; + *dst = '\0'; + } + + /* Format whole octets. */ + for (b = bits / 8; b > 0; b--) { + if (size <= sizeof "255.") + goto emsgsize; + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b > 1) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + + /* Format partial octet. */ + b = bits % 8; + if (b > 0) { + if (size <= sizeof ".255") + goto emsgsize; + t = dst; + if (dst != odst) + *dst++ = '.'; + m = ((1 << b) - 1) << (8 - b); + dst += SPRINTF((dst, "%u", *src & m)); + size -= (size_t)(dst - t); + } + + /* Format CIDR /width. */ + if (size <= sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} + +/* + * static char * + * inet_net_ntop_ipv6(src, bits, fakebits, dst, size) + * convert IPv6 network number from network to presentation format. + * generates CIDR style result always. Picks the shortest representation + * unless the IP is really IPv4. + * always prints specified number of bits (bits). + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Vadim Kogan (UCB), June 2001 + * Original version (IPv4) by Paul Vixie (ISC), July 1996 + */ + +static char * +inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { + u_int m; + int b; + int p; + int zero_s, zero_l, tmp_zero_s, tmp_zero_l; + int i; + int is_ipv4 = 0; + unsigned char inbuf[16]; + char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")]; + char *cp; + int words; + u_char *s; + + if (bits < 0 || bits > 128) { + errno = EINVAL; + return (NULL); + } + + cp = outbuf; + + if (bits == 0) { + *cp++ = ':'; + *cp++ = ':'; + *cp = '\0'; + } else { + /* Copy src to private buffer. Zero host part. */ + p = (bits + 7) / 8; + memcpy(inbuf, src, p); + memset(inbuf + p, 0, 16 - p); + b = bits % 8; + if (b != 0) { + m = ~0 << (8 - b); + inbuf[p-1] &= m; + } + + s = inbuf; + + /* how many words need to be displayed in output */ + words = (bits + 15) / 16; + if (words == 1) + words = 2; + + /* Find the longest substring of zero's */ + zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0; + for (i = 0; i < (words * 2); i += 2) { + if ((s[i] | s[i+1]) == 0) { + if (tmp_zero_l == 0) + tmp_zero_s = i / 2; + tmp_zero_l++; + } else { + if (tmp_zero_l && zero_l < tmp_zero_l) { + zero_s = tmp_zero_s; + zero_l = tmp_zero_l; + tmp_zero_l = 0; + } + } + } + + if (tmp_zero_l && zero_l < tmp_zero_l) { + zero_s = tmp_zero_s; + zero_l = tmp_zero_l; + } + + if (zero_l != words && zero_s == 0 && ((zero_l == 6) || + ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) || + ((zero_l == 7 && s[14] != 0 && s[15] != 1))))) + is_ipv4 = 1; + + /* Format whole words. */ + for (p = 0; p < words; p++) { + if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) { + /* Time to skip some zeros */ + if (p == zero_s) + *cp++ = ':'; + if (p == words - 1) + *cp++ = ':'; + s++; + s++; + continue; + } + + if (is_ipv4 && p > 5 ) { + *cp++ = (p == 6) ? ':' : '.'; + cp += SPRINTF((cp, "%u", *s++)); + /* we can potentially drop the last octet */ + if (p != 7 || bits > 120) { + *cp++ = '.'; + cp += SPRINTF((cp, "%u", *s++)); + } + } else { + if (cp != outbuf) + *cp++ = ':'; + cp += SPRINTF((cp, "%x", *s * 256 + s[1])); + s += 2; + } + } + } + /* Format CIDR /width. */ + SPRINTF((cp, "/%u", bits)); + if (strlen(outbuf) + 1 > size) + goto emsgsize; + strcpy(dst, outbuf); + + return (dst); + +emsgsize: + errno = EMSGSIZE; + return (NULL); +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_net_pton.c b/usr/src/lib/libresolv2/common/inet/inet_net_pton.c new file mode 100644 index 0000000000..18a89be9ae --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_net_pton.c @@ -0,0 +1,406 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_pton.c,v 1.13 2001/09/27 15:08:38 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <isc/assertions.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * static int + * inet_net_pton_ipv4(src, dst, size) + * convert IPv4 network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not an IPv4 network specification. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +static int +inet_net_pton_ipv4( const char *src, u_char *dst, size_t size) { + static const char xdigits[] = "0123456789abcdef"; + static const char digits[] = "0123456789"; + int n, ch, tmp = 0, dirty, bits; + const u_char *odst = dst; + + ch = *src++; + if (ch == '0' && (src[0] == 'x' || src[0] == 'X') + && isascii((unsigned char)(src[1])) + && isxdigit((unsigned char)(src[1]))) { + /* Hexadecimal: Eat nybble string. */ + if (size <= 0) + goto emsgsize; + dirty = 0; + src++; /* skip x or X. */ + while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) { + if (isupper(ch)) + ch = tolower(ch); + n = strchr(xdigits, ch) - xdigits; + INSIST(n >= 0 && n <= 15); + if (dirty == 0) + tmp = n; + else + tmp = (tmp << 4) | n; + if (++dirty == 2) { + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + dirty = 0; + } + } + if (dirty) { /* Odd trailing nybble? */ + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) (tmp << 4); + } + } else if (isascii(ch) && isdigit(ch)) { + /* Decimal: eat dotted digit string. */ + for (;;) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && + isascii(ch) && isdigit(ch)); + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + ch = *src++; + if (!isascii(ch) || !isdigit(ch)) + goto enoent; + } + } else + goto enoent; + + bits = -1; + if (ch == '/' && isascii((unsigned char)(src[0])) && + isdigit((unsigned char)(src[0])) && dst > odst) { + /* CIDR width specifier. Nothing can follow it. */ + ch = *src++; /* Skip over the /. */ + bits = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + bits *= 10; + bits += n; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (ch != '\0') + goto enoent; + if (bits > 32) + goto emsgsize; + } + + /* Firey death and destruction unless we prefetched EOS. */ + if (ch != '\0') + goto enoent; + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + /* If no CIDR spec was given, infer width from net class. */ + if (bits == -1) { + if (*odst >= 240) /* Class E */ + bits = 32; + else if (*odst >= 224) /* Class D */ + bits = 4; + else if (*odst >= 192) /* Class C */ + bits = 24; + else if (*odst >= 128) /* Class B */ + bits = 16; + else /* Class A */ + bits = 8; + /* If imputed mask is narrower than specified octets, widen. */ + if (bits >= 8 && bits < ((dst - odst) * 8)) + bits = (dst - odst) * 8; + } + /* Extend network to cover the actual mask. */ + while (bits > ((dst - odst) * 8)) { + if (size-- <= 0) + goto emsgsize; + *dst++ = '\0'; + } + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static int +getbits(const char *src, int *bitsp) { + static const char digits[] = "0123456789"; + int n; + int val; + char ch; + + val = 0; + n = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + if (n++ != 0 && val == 0) /* no leading zeros */ + return (0); + val *= 10; + val += (pch - digits); + if (val > 128) /* range */ + return (0); + continue; + } + return (0); + } + if (n == 0) + return (0); + *bitsp = val; + return (1); +} + +static int +getv4(const char *src, u_char *dst, int *bitsp) { + static const char digits[] = "0123456789"; + u_char *odst = dst; + int n; + u_int val; + char ch; + + val = 0; + n = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + if (n++ != 0 && val == 0) /* no leading zeros */ + return (0); + val *= 10; + val += (pch - digits); + if (val > 255) /* range */ + return (0); + continue; + } + if (ch == '.' || ch == '/') { + if (dst - odst > 3) /* too many octets? */ + return (0); + *dst++ = val; + if (ch == '/') + return (getbits(src, bitsp)); + val = 0; + n = 0; + continue; + } + return (0); + } + if (n == 0) + return (0); + if (dst - odst > 3) /* too many octets? */ + return (0); + *dst++ = val; + return (1); +} + +static int +inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + int digits; + int bits; + size_t bytes; + int words; + int ipv4; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + goto enoent; + curtok = src; + saw_xdigit = 0; + val = 0; + digits = 0; + bits = -1; + ipv4 = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (++digits > 4) + goto enoent; + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + goto enoent; + colonp = tp; + continue; + } else if (*src == '\0') + goto enoent; + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + digits = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + getv4(curtok, tp, &bits) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + ipv4 = 1; + break; /* '\0' was seen by inet_pton4(). */ + } + if (ch == '/' && getbits(src, &bits) > 0) + break; + goto enoent; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + goto enoent; + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (bits == -1) + bits = 128; + + words = (bits + 15) / 16; + if (words < 2) + words = 2; + if (ipv4) + words = 8; + endp = tmp + 2 * words; + + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + goto enoent; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + goto enoent; + + bytes = (bits + 7) / 8; + if (bytes > size) + goto emsgsize; + memcpy(dst, tmp, bytes); + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +/* + * int + * inet_net_pton(af, src, dst, size) + * convert network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not a valid network specification. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +inet_net_pton(int af, const char *src, void *dst, size_t size) { + switch (af) { + case AF_INET: + return (inet_net_pton_ipv4(src, dst, size)); + case AF_INET6: + return (inet_net_pton_ipv6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_neta.c b/usr/src/lib/libresolv2/common/inet/inet_neta.c new file mode 100644 index 0000000000..1a71b11906 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_neta.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_neta.c,v 1.6 1999/01/08 19:23:45 vixie Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * char * + * inet_neta(src, dst, size) + * format a u_long network number into presentation format. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * format of ``src'' is as for inet_network(). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_neta(src, dst, size) + u_long src; + char *dst; + size_t size; +{ + char *odst = dst; + char *tp; + + while (src & 0xffffffff) { + u_char b = (src & 0xff000000) >> 24; + + src <<= 8; + if (b) { + if (size < sizeof "255.") + goto emsgsize; + tp = dst; + dst += SPRINTF((dst, "%u", b)); + if (src != 0L) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - tp); + } + } + if (dst == odst) { + if (size < sizeof "0.0.0.0") + goto emsgsize; + strcpy(dst, "0.0.0.0"); + } + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_netof.c b/usr/src/lib/libresolv2/common/inet/inet_netof.c new file mode 100644 index 0000000000..a5395af2d4 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_netof.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1983, 1993 + * The 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/* + * Return the network number from an internet + * address; handles class a/b/c network #'s. + */ +#ifdef ORIGINAL_ISC_CODE +u_long +#else +in_addr_t +#endif +inet_netof(in) + struct in_addr in; +{ +#ifdef ORIGINAL_ISC_CODE + register u_long i = ntohl(in.s_addr); +#else + register in_addr_t i = ntohl(in.s_addr); +#endif + + if (IN_CLASSA(i)) + return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_network.c b/usr/src/lib/libresolv2/common/inet/inet_network.c new file mode 100644 index 0000000000..e1f6f6d96a --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_network.c @@ -0,0 +1,129 @@ +/* + * Copyright 1997-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1983, 1993 + * The 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> + +#include "port_after.h" + +/* + * Internet network address interpretation routine. + * The library routines call this routine to interpret + * network numbers. + */ +#ifdef ORIGINAL_ISC_CODE +u_long +#else +in_addr_t +#endif +inet_network(cp) + register const char *cp; +{ +#ifdef ORIGINAL_ISC_CODE + register u_long val, base, n, i; +#else + register in_addr_t val, base, n, i; +#endif + register char c; +#ifdef ORIGINAL_ISC_CODE + u_long parts[4], *pp = parts; +#else + in_addr_t parts[4], *pp = parts; +#endif + int digit; + +again: + val = 0; base = 10; digit = 0; + if (*cp == '0') + digit = 1, base = 8, cp++; + if (*cp == 'x' || *cp == 'X') + base = 16, cp++; + while ((c = *cp) != 0) { + if (isdigit((unsigned char)c)) { + if (base == 8 && (c == '8' || c == '9')) + return (INADDR_NONE); + val = (val * base) + (c - '0'); + cp++; + digit = 1; + continue; + } + if (base == 16 && isxdigit((unsigned char)c)) { + val = (val << 4) + + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); + cp++; + digit = 1; + continue; + } + break; + } + if (!digit) + return (INADDR_NONE); +#ifdef ORIGINAL_ISC_CODE + if (*cp == '.') { + if (pp >= parts + 4 || val > 0xff) + return (INADDR_NONE); +#else + if (pp >= parts + 4 || val > 0xff) + return (INADDR_NONE); + if (*cp == '.') { +#endif + *pp++ = val, cp++; + goto again; + } + if (*cp && !isspace(*cp&0xff)) + return (INADDR_NONE); + *pp++ = val; + n = pp - parts; + if (n > 4) + return (INADDR_NONE); + for (val = 0, i = 0; i < n; i++) { + val <<= 8; + val |= parts[i] & 0xff; + } + return (val); +} diff --git a/usr/src/lib/libresolv2/common/inet/inet_ntoa.c b/usr/src/lib/libresolv2/common/inet/inet_ntoa.c new file mode 100644 index 0000000000..7c838ac458 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_ntoa.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1983, 1993 + * The 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: inet_ntoa.c,v 1.7 1999/05/14 18:16:55 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +/* + * Convert network-format internet address + * to base 256 d.d.d.d representation. + */ +#ifndef SUNW_LIBNSL /* We don't need this if linked with libnsl */ +/*const*/ char * +inet_ntoa(struct in_addr in) { + static char ret[18]; + + strcpy(ret, "[inet_ntoa error]"); + (void) inet_ntop(AF_INET, &in, ret, sizeof ret); + return (ret); +} +#endif /* SUNW_LIBNSL */ diff --git a/usr/src/lib/libresolv2/common/inet/inet_ntop.c b/usr/src/lib/libresolv2/common/inet/inet_ntop.c new file mode 100644 index 0000000000..c13d5e3fc6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_ntop.c @@ -0,0 +1,212 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_ntop.c,v 1.11 2001/09/27 15:12:57 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); +static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); + +#ifndef SUNW_LIBNSL /* We don't need this if linked with libnsl */ + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} +#endif /* SUNW_LIBNSL */ diff --git a/usr/src/lib/libresolv2/common/inet/inet_pton.c b/usr/src/lib/libresolv2/common/inet/inet_pton.c new file mode 100644 index 0000000000..465d1ded01 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/inet_pton.c @@ -0,0 +1,231 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_pton.c,v 1.8 2001/07/16 03:22:24 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <string.h> +#include <errno.h> +#include "port_after.h" + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 __P((const char *src, u_char *dst)); +static int inet_pton6 __P((const char *src, u_char *dst)); + +#ifndef SUNW_LIBNSL /* We don't need this if linked with libnsl */ + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(af, src, dst) + int af; + const char *src; + void *dst; +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); + case AF_INET6: + return (inet_pton6(src, dst)); + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + u_char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + u_char tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + u_int new = *tp * 10 + (pch - digits); + + if (saw_digit && *tp == 0) + return (0); + if (new > 255) + return (0); + *tp = new; + if (!saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + memcpy(dst, tmp, NS_INADDRSZ); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(src, dst) + const char *src; + u_char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') { + return (0); + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return (0); + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return (1); +} +#endif /* SUNW_LIBNSL */ diff --git a/usr/src/lib/libresolv2/common/inet/nsap_addr.c b/usr/src/lib/libresolv2/common/inet/nsap_addr.c new file mode 100644 index 0000000000..cab8508187 --- /dev/null +++ b/usr/src/lib/libresolv2/common/inet/nsap_addr.c @@ -0,0 +1,119 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAI! + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANT! + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF TH! + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nsap_addr.c,v 8.12 2001/05/28 07:37:46 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <resolv.h> + +#include "port_after.h" + +static char +xtob(int c) { + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) { + u_char c, nib; + u_int len = 0; + + if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X')) + return (0); + ascii += 2; + + while ((c = *ascii++) != '\0' && len < (u_int)maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + if (islower(c)) + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + c = *ascii++; + if (c != '\0') { + c = toupper(c); + if (isxdigit(c)) { + *binary++ = (nib << 4) | xtob(c); + len++; + } else + return (0); + } + else + return (0); + } + else + return (0); + } + return (len); +} + +char * +inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { + int nib; + int i; +#ifdef SUNW_MT_RESOLVER + char *tmpbuf = inet_nsap_ntoa_tmpbuf; +#else + static char tmpbuf[2+255*3]; +#endif /* SUNW_MT_RESOLVER */ + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + *ascii++ = '0'; + *ascii++ = 'x'; + + if (binlen > 255) + binlen = 255; + + for (i = 0; i < binlen; i++) { + nib = *binary >> 4; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} diff --git a/usr/src/lib/libresolv2/common/irs/dns.c b/usr/src/lib/libresolv2/common/irs/dns.c new file mode 100644 index 0000000000..30feb1b882 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/dns.c @@ -0,0 +1,160 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns.c,v 1.16 2001/05/29 05:48:26 marka Exp $"; +#endif + +/* + * dns.c --- this is the top-level accessor function for the dns + */ + +#include "port_before.h" + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <resolv.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* forward */ + +static void dns_close(struct irs_acc *); +static struct __res_state * dns_res_get(struct irs_acc *); +static void dns_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* public */ + +struct irs_acc * +irs_dns_acc(const char *options) { + struct irs_acc *acc; + struct dns_p *dns; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(dns = memget(sizeof *dns))) { + errno = ENOMEM; + memput(acc, sizeof *acc); + return (NULL); + } + memset(dns, 0x5e, sizeof *dns); + dns->res = NULL; + dns->free_res = NULL; + if (hesiod_init(&dns->hes_ctx) < 0) { + /* + * We allow the dns accessor class to initialize + * despite hesiod failing to initialize correctly, + * since dns host queries don't depend on hesiod. + */ + dns->hes_ctx = NULL; + } + acc->private = dns; +#ifdef WANT_IRS_GR + acc->gr_map = irs_dns_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_dns_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_dns_sv; + acc->pr_map = irs_dns_pr; + acc->ho_map = irs_dns_ho; + acc->nw_map = irs_dns_nw; + acc->ng_map = irs_nul_ng; + acc->res_get = dns_res_get; + acc->res_set = dns_res_set; + acc->close = dns_close; + return (acc); +} + +/* methods */ +static struct __res_state * +dns_res_get(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + + if (dns->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(dns->res, 0, sizeof *dns->res); + dns_res_set(this, res, free); + } + + if ((dns->res->options & RES_INIT) == 0 && + res_ninit(dns->res) < 0) + return (NULL); + + return (dns->res); +} + +static void +dns_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct dns_p *dns = (struct dns_p *)this->private; + + if (dns->res && dns->free_res) { + res_nclose(dns->res); + (*dns->free_res)(dns->res); + } + dns->res = res; + dns->free_res = free_res; +} + +static void +dns_close(struct irs_acc *this) { + struct dns_p *dns; + + dns = (struct dns_p *)this->private; + if (dns->res && dns->free_res) + (*dns->free_res)(dns->res); + if (dns->hes_ctx) + hesiod_end(dns->hes_ctx); + memput(dns, sizeof *dns); + memput(this, sizeof *this); +} + diff --git a/usr/src/lib/libresolv2/common/irs/dns_gr.c b/usr/src/lib/libresolv2/common/irs/dns_gr.c new file mode 100644 index 0000000000..92da69b8c5 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/dns_gr.c @@ -0,0 +1,301 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_gr.c,v 1.21 2002/07/08 06:26:09 marka Exp $"; +#endif + +/* + * dns_gr.c --- this file contains the functions for accessing + * group information from Hesiod. + */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include <sys/param.h> +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <isc/memcluster.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + /* + * This is our private accessor data. It has a shared hesiod context. + */ + struct dns_p * dns; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward. */ + +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_close(struct irs_gr *); +static int gr_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +static void gr_minimize(struct irs_gr *); +static struct __res_state * gr_res_get(struct irs_gr *); +static void gr_res_set(struct irs_gr *, + struct __res_state *, + void (*)(void *)); + +static struct group * get_hes_group(struct irs_gr *this, + const char *name, + const char *type); + +/* Public. */ + +struct irs_gr * +irs_dns_gr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_gr *gr; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(gr = memget(sizeof *gr))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + gr->private = pvt; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->close = gr_close; + gr->list = gr_list; + gr->minimize = gr_minimize; + gr->res_get = gr_res_get; + gr->res_set = gr_res_set; + return (gr); +} + +/* methods */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + + UNUSED(this); + + return (NULL); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + return (get_hes_group(this, name, "group")); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + char name[32]; + + sprintf(name, "%ld", (long)gid); + return (get_hes_group(this, name, "gid")); +} + +static void +gr_rewind(struct irs_gr *this) { + + UNUSED(this); + + /* NOOP */ +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + UNUSED(this); + UNUSED(name); + UNUSED(basegid); + UNUSED(groups); + + *ngroups = 0; + /* There's some way to do this in Hesiod. */ + return (-1); +} + +static void +gr_minimize(struct irs_gr *this) { + + UNUSED(this); + /* NOOP */ +} + +/* Private. */ + +static struct group * +get_hes_group(struct irs_gr *this, const char *name, const char *type) { + struct pvt *pvt = (struct pvt *)this->private; + char **hes_list, *cp, **new; + size_t num_members = 0; + u_long t; + + hes_list = hesiod_resolve(pvt->dns->hes_ctx, name, type); + if (!hes_list) + return (NULL); + + /* + * Copy the returned hesiod string into storage space. + */ + if (pvt->membuf) + free(pvt->membuf); + pvt->membuf = strdup(*hes_list); + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + + cp = pvt->membuf; + pvt->group.gr_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->group.gr_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + errno = 0; + t = strtoul(cp, NULL, 10); + if (errno == ERANGE) + goto cleanup; + pvt->group.gr_gid = (gid_t) t; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + cp++; + + /* + * Parse the members out. + */ + while (*cp) { + if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { + pvt->nmemb += 10; + new = realloc(pvt->group.gr_mem, + pvt->nmemb * sizeof(char *)); + if (new == NULL) + goto cleanup; + pvt->group.gr_mem = new; + } + pvt->group.gr_mem[num_members++] = cp; + if (!(cp = strchr(cp, ','))) + break; + *cp++ = '\0'; + } + if (!pvt->group.gr_mem) { + pvt->group.gr_mem = malloc(sizeof(char*)); + if (!pvt->group.gr_mem) + goto cleanup; + } + pvt->group.gr_mem[num_members] = NULL; + + return (&pvt->group); + + cleanup: + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + } + if (pvt->membuf) { + free(pvt->membuf); + pvt->membuf = NULL; + } + return (NULL); +} + +static struct __res_state * +gr_res_get(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +gr_res_set(struct irs_gr *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +#endif /* WANT_IRS_GR */ diff --git a/usr/src/lib/libresolv2/common/irs/dns_ho.c b/usr/src/lib/libresolv2/common/irs/dns_ho.c new file mode 100644 index 0000000000..4d4b830dfe --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/dns_ho.c @@ -0,0 +1,1163 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1985, 1988, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_ho.c,v 1.43 2003/05/27 23:36:52 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#define MAXPACKET (65535) /* Maximum TCP message size */ + +#define BOUNDS_CHECK(ptr, count) \ + if ((ptr) + (count) > eom) { \ + had_error++; \ + continue; \ + } else (void)0 + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +struct dns_res_target { + struct dns_res_target *next; + querybuf qbuf; /* query buffer */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer buffer */ + int qclass, qtype; /* class and type of query */ + int action; /* condition whether query is really issued */ + char qname[MAXDNAME +1]; /* domain name */ +#if 0 + int n; /* result length */ +#endif +}; +enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE}; +enum {RESQRY_SUCCESS, RESQRY_FAIL}; + +struct pvt { + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +typedef union { + int32_t al; + char ac; +} align; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; +/* Note: the IPv6 loopback address is in the "tunnel" space */ +static const u_char v6local[] = { 0,0, 0,1 }; /* last 4 bytes of IPv6 addr */ + +/* Forwards. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static void map_v4v6_hostent(struct hostent *hp, char **bp, + char *ep); +static void addrsort(res_state, char **, int); +static struct hostent * gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, + const char *qname, int qtype, + int af, int size, + struct addrinfo **ret_aip, + const struct addrinfo *pai); +static int add_hostent(struct pvt *pvt, char *bp, char **hap, + struct addrinfo *ai); +static int init(struct irs_ho *this); + +/* Exports. */ + +struct irs_ho * +irs_dns_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt) + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp = NULL; + int n, size; + char tmp[NS_MAXDNAME]; + const char *cp; + struct addrinfo ai; + struct dns_res_target *q, *p; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + q = memget(sizeof(*q)); + if (q == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(q)); + + switch (af) { + case AF_INET: + size = INADDRSZ; + q->qclass = C_IN; + q->qtype = T_A; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + size = IN6ADDRSZ; + q->qclass = C_IN; + q->qtype = T_AAAA; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + default: + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + hp = NULL; + goto cleanup; + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + if ((hp = gethostans(this, p->answer, n, name, p->qtype, + af, size, NULL, + (const struct addrinfo *)&ai)) != NULL) + goto cleanup; /* no more loop is necessary */ + + querystate = RESQRY_FAIL; + continue; + } + + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + return(hp); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) +{ + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + char *qp; + struct hostent *hp = NULL; + struct addrinfo ai; + struct dns_res_target *q, *q2, *p; + int n, size, i; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + q = memget(sizeof(*q)); + q2 = memget(sizeof(*q2)); + if (q == NULL || q2 == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(q)); + memset(q2, 0, sizeof(q2)); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + (!memcmp(uaddr, tunnelled, sizeof tunnelled) && + memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) { + /* Unmap. */ + addr = (const char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + q->qclass = C_IN; + q->qtype = T_PTR; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + size = IN6ADDRSZ; + q->qclass = C_IN; + q->qtype = T_PTR; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->next = q2; + q->action = RESTGT_DOALWAYS; + q2->qclass = C_IN; + q2->qtype = T_PTR; + q2->answer = q2->qbuf.buf; + q2->anslen = sizeof(q2->qbuf); + if ((pvt->res->options & RES_NO_NIBBLE2) != 0) + q2->action = RESTGT_IGNORE; + else + q2->action = RESTGT_AFTERFAILURE; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + hp = NULL; + goto cleanup; + } + if (size > len) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + hp = NULL; + goto cleanup; + } + switch (af) { + case AF_INET: + qp = q->qname; + (void) sprintf(qp, "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + if (q->action != RESTGT_IGNORE) { + qp = q->qname; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + i = SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + if (i < 0) + abort(); + qp += i; + } +#ifdef HAVE_STRLCAT + strlcat(q->qname, res_get_nibblesuffix(pvt->res), + sizeof(q->qname)); +#else + strcpy(qp, res_get_nibblesuffix(pvt->res)); +#endif + } + if (q2->action != RESTGT_IGNORE) { + qp = q2->qname; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + i = SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + if (i < 0) + abort(); + qp += i; + } +#ifdef HAVE_STRLCAT + strlcat(q->qname, res_get_nibblesuffix2(pvt->res), + sizeof(q->qname)); +#else + strcpy(qp, res_get_nibblesuffix2(pvt->res)); +#endif + } + break; + default: + abort(); + } + + for (p = q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nquery(pvt->res, p->qname, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + hp = gethostans(this, p->answer, n, p->qname, T_PTR, af, size, + NULL, (const struct addrinfo *)&ai); + if (!hp) { + querystate = RESQRY_FAIL; + continue; + } + + memcpy(pvt->host_addr, addr, len); + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + pvt->host.h_addrtype = AF_INET6; + pvt->host.h_length = IN6ADDRSZ; + } + + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + goto cleanup; /* no more loop is necessary. */ + } + hp = NULL; /* H_ERRNO was set by subroutines */ + + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + if (q2 != NULL) + memput(q2, sizeof(*q2)); + return(hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + + UNUSED(this); + + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + + UNUSED(this); + + /* NOOP */ +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +/* XXX */ +extern struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int n; + char tmp[NS_MAXDNAME]; + const char *cp; + struct dns_res_target *q, *q2, *p; + struct addrinfo sentinel, *cur; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + q = memget(sizeof(*q)); + q2 = memget(sizeof(*q2)); + if (q == NULL || q2 == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(q2)); + memset(q2, 0, sizeof(q2)); + + switch (pai->ai_family) { + case AF_UNSPEC: + /* prefer IPv6 */ + q->qclass = C_IN; + q->qtype = T_AAAA; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->next = q2; + q->action = RESTGT_DOALWAYS; + q2->qclass = C_IN; + q2->qtype = T_A; + q2->answer = q2->qbuf.buf; + q2->anslen = sizeof(q2->qbuf); + q2->action = RESTGT_DOALWAYS; + break; + case AF_INET: + q->qclass = C_IN; + q->qtype = T_A; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + q->qclass = C_IN; + q->qtype = T_AAAA; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* better error? */ + goto cleanup; + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = q; p; p = p->next) { + struct addrinfo *ai; + + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + (void)gethostans(this, p->answer, n, name, p->qtype, + pai->ai_family, /* XXX: meaningless */ + 0, &ai, pai); + if (ai) { + querystate = RESQRY_SUCCESS; + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + else + querystate = RESQRY_FAIL; + } + + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + if (q2 != NULL) + memput(q2, sizeof(*q2)); + return(sentinel.ai_next); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private. */ + +static struct hostent * +gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, const char *qname, int qtype, + int af, int size, /* meaningless for addrinfo cases */ + struct addrinfo **ret_aip, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, ancount, qdcount, n, haveanswer, had_error; + int error = NETDB_SUCCESS, arcount; + int (*name_ok)(const char *); + const HEADER *hp; + const u_char *eom; + const u_char *eor; + const u_char *cp; + const char *tname; + const char *hname; + char *bp, *ep, **ap, **hap; + char tbuf[MAXDNAME+1]; + struct addrinfo sentinel, *cur, ai; + + if (pai == NULL) abort(); + if (ret_aip != NULL) + *ret_aip = NULL; + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + tname = qname; + eom = ansbuf + anslen; + switch (qtype) { + case T_A: + case T_AAAA: + case T_ANY: /* use T_ANY only for T_A/T_AAAA lookup */ + name_ok = res_hnok; + break; + case T_PTR: + name_ok = res_dnok; + break; + default: + abort(); + } + + pvt->host.h_addrtype = af; + pvt->host.h_length = size; + hname = pvt->host.h_name = NULL; + + /* + * Find first satisfactory answer. + */ + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (const HEADER *)ansbuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + arcount = ntohs(hp->arcount); + bp = pvt->hostbuf; + ep = pvt->hostbuf + sizeof(pvt->hostbuf); + cp = ansbuf + HFIXEDSZ; + if (qdcount != 1) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { + /* res_nsend() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen(bp) + 1; /* for the \0 */ + if (n > MAXHOSTNAMELEN) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->host.h_name = bp; + hname = bp; + bp += n; + /* The qname can be abbreviated, but hname is now absolute. */ + qname = pvt->host.h_name; + } + ap = pvt->host_aliases; + *ap = NULL; + pvt->host.h_aliases = pvt->host_aliases; + hap = pvt->h_addr_ptrs; + *hap = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + haveanswer = 0; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { + had_error++; + continue; + } + cp += n; /* name */ + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + type = ns_get16(cp); + cp += INT16SZ; /* type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /* len */ + BOUNDS_CHECK(cp, n); + if (class != C_IN) { + cp += n; + continue; + } + eor = cp + n; + if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && + type == T_CNAME) { + if (haveanswer) { + int level = LOG_CRIT; +#ifdef LOG_SECURITY + level |= LOG_SECURITY; +#endif + syslog(level, + "gethostans: possible attempt to exploit buffer overflow while looking up %s", + *qname ? qname : "."); + } + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { + had_error++; + continue; + } + cp += n; + /* Store alias. */ + if (ap >= &pvt->host_aliases[MAXALIASES-1]) + continue; + *ap++ = bp; + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > (ep - bp) || n > MAXHOSTNAMELEN) { + had_error++; + continue; + } +#ifdef HAVE_STRLCPY + strlcpy(bp, tbuf, ep - bp); +#else + strcpy(bp, tbuf); +#endif + pvt->host.h_name = bp; + hname = bp; + bp += n; + continue; + } + if (qtype == T_PTR && type == T_CNAME) { + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { + had_error++; + continue; + } + cp += n; +#ifdef RES_USE_DNAME + if ((pvt->res->options & RES_USE_DNAME) != 0) +#endif + { + /* + * We may be able to check this regardless + * of the USE_DNAME bit, but we add the check + * for now since the DNAME support is + * experimental. + */ + if (ns_samename(tname, bp) != 1) + continue; + } + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > (ep - bp)) { + had_error++; + continue; + } +#ifdef HAVE_STRLCPY + strlcpy(bp, tbuf, ep - bp); +#else + strcpy(bp, tbuf); +#endif + tname = bp; + bp += n; + continue; + } + if (qtype == T_ANY) { + if (!(type == T_A || type == T_AAAA)) { + cp += n; + continue; + } + } else if (type != qtype) { + cp += n; + continue; + } + switch (type) { + case T_PTR: + if (ret_aip != NULL) { + /* addrinfo never needs T_PTR */ + cp += n; + continue; + } + if (ns_samename(tname, bp) != 1) { + cp += n; + continue; + } + n = dn_expand(ansbuf, eor, cp, bp, ep - bp); + if (n < 0 || !maybe_hnok(pvt->res, bp) || + n >= MAXHOSTNAMELEN) { + had_error++; + break; + } + cp += n; + if (!haveanswer) { + pvt->host.h_name = bp; + hname = bp; + } + else if (ap < &pvt->host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + } + break; + case T_A: + case T_AAAA: + if (ns_samename(hname, bp) != 1) { + cp += n; + continue; + } + if (type == T_A && n != INADDRSZ) { + cp += n; + continue; + } + if (type == T_AAAA && n != IN6ADDRSZ) { + cp += n; + continue; + } + + /* make addrinfo. don't overwrite constant PAI */ + ai = *pai; + ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET; + cur->ai_next = addr2addrinfo( + (const struct addrinfo *)&ai, + (const char *)cp); + if (cur->ai_next == NULL) + had_error++; + + if (!haveanswer) { + int nn; + + nn = strlen(bp) + 1; /* for the \0 */ + if (nn >= MAXHOSTNAMELEN) { + cp += n; + had_error++; + continue; + } + pvt->host.h_name = bp; + hname = bp; + bp += nn; + } + /* Ensure alignment. */ + bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & + ~(sizeof(align) - 1)); + /* Avoid overflows. */ + if (bp + n >= &pvt->hostbuf[sizeof pvt->hostbuf]) { + had_error++; + continue; + } + if (ret_aip) { /* need addrinfo. keep it. */ + while (cur && cur->ai_next) + cur = cur->ai_next; + } else if (cur->ai_next) { /* need hostent */ + struct addrinfo *aip = cur->ai_next; + + for (aip = cur->ai_next; aip; + aip = aip->ai_next) { + int m; + + m = add_hostent(pvt, bp, hap, aip); + if (m < 0) { + had_error++; + break; + } + if (m == 0) + continue; + if (hap < &pvt->h_addr_ptrs[MAXADDRS-1]) + hap++; + *hap = NULL; + bp += m; + } + + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + } + cp += n; + break; + default: + abort(); + } + if (!had_error) + haveanswer++; + } + if (haveanswer) { + if (ret_aip == NULL) { + *ap = NULL; + *hap = NULL; + + if (pvt->res->nsort && haveanswer > 1 && qtype == T_A) + addrsort(pvt->res, pvt->h_addr_ptrs, + haveanswer); + if (pvt->host.h_name == NULL) { + n = strlen(qname) + 1; /* for the \0 */ + if (n > (ep - bp) || n >= MAXHOSTNAMELEN) + goto no_recovery; +#ifdef HAVE_STRLCPY + strlcpy(bp, qname, ep - bp); +#else + strcpy(bp, qname); +#endif + pvt->host.h_name = bp; + bp += n; + } + if (pvt->res->options & RES_USE_INET6) + map_v4v6_hostent(&pvt->host, &bp, ep); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); + } else { + if ((pai->ai_flags & AI_CANONNAME) != 0) { + if (pvt->host.h_name == NULL) { + sentinel.ai_next->ai_canonname = + strdup(qname); + } + else { + sentinel.ai_next->ai_canonname = + strdup(pvt->host.h_name); + } + } + *ret_aip = sentinel.ai_next; + return(NULL); + } + } + no_recovery: + if (sentinel.ai_next) { + /* this should be impossible, but check it for safety */ + freeaddrinfo(sentinel.ai_next); + } + if (error == NETDB_SUCCESS) + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + else + RES_SET_H_ERRNO(pvt->res, error); + return(NULL); +} + +static int +add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai) +{ + int addrlen; + char *addrp; + const char **tap; + char *obp = bp; + + switch(ai->ai_addr->sa_family) { + case AF_INET6: + addrlen = IN6ADDRSZ; + addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; + break; + case AF_INET: + addrlen = INADDRSZ; + addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr; + break; + default: + return(-1); /* abort? */ + } + + /* Ensure alignment. */ + bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & + ~(sizeof(align) - 1)); + /* Avoid overflows. */ + if (bp + addrlen >= &pvt->hostbuf[sizeof pvt->hostbuf]) + return(-1); + if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1]) + return(0); /* fail, but not treat it as an error. */ + + /* Suppress duplicates. */ + for (tap = (const char **)pvt->h_addr_ptrs; + *tap != NULL; + tap++) + if (memcmp(*tap, addrp, addrlen) == 0) + break; + if (*tap != NULL) + return (0); + + memcpy(*hap = bp, addrp, addrlen); + return((bp + addrlen) - obp); +} + +static void +map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) { + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) { + int i = (u_long)*bpp % sizeof(align); + + if (i != 0) + i = sizeof(align) - i; + + if ((ep - *bpp) < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. */ + *ap = NULL; + return; + } + *bpp += i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + } +} + +static void +addrsort(res_state statp, char **ap, int num) { + int i, j, needsort = 0, aval[MAXADDRS]; + char **p; + + p = ap; + for (i = 0; i < num; i++, p++) { + for (j = 0 ; (unsigned)j < statp->nsort; j++) + if (statp->sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & + statp->sort_list[j].mask)) + break; + aval[i] = j; + if (needsort == 0 && i > 0 && j < aval[i-1]) + needsort = i; + } + if (!needsort) + return; + + while (needsort < num) { + for (j = needsort - 1; j >= 0; j--) { + if (aval[j] > aval[j+1]) { + char *hp; + + i = aval[j]; + aval[j] = aval[j+1]; + aval[j+1] = i; + + hp = ap[j]; + ap[j] = ap[j+1]; + ap[j+1] = hp; + + } else + break; + } + needsort++; + } +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/irs/dns_nw.c b/usr/src/lib/libresolv2/common/irs/dns_nw.c new file mode 100644 index 0000000000..bcae67480d --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/dns_nw.c @@ -0,0 +1,601 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_nw.c,v 1.25 2002/07/18 02:07:43 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 + +#define MAXPACKET (64*1024) + +struct pvt { + struct nwent net; + char * ali[MAXALIASES]; + char buf[BUFSIZ+1]; + struct __res_state * res; + void (*free_res)(void *); +}; + +typedef union { + long al; + char ac; +} align; + +enum by_what { by_addr, by_name }; + +/* Forwards. */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int); +static struct nwent * get1101byname(struct irs_nw *, const char *); +static struct nwent * get1101answer(struct irs_nw *, + u_char *ansbuf, int anslen, + enum by_what by_what, + int af, const char *name, + const u_char *addr, int addrlen); +static struct nwent * get1101mask(struct irs_nw *this, struct nwent *); +static int make1101inaddr(const u_char *, int, char *, int); +static void normalize_name(char *name); +static int init(struct irs_nw *this); + +/* Exports. */ + +struct irs_nw * +irs_dns_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods. */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + return (get1101byname(this, name)); + default: + (void)NULL; + } + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + return (get1101byaddr(this, net, len)); + default: + (void)NULL; + } + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + + UNUSED(this); + + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + UNUSED(this); + /* NOOP */ +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private. */ + +static struct nwent * +get1101byname(struct irs_nw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + u_char *ansbuf; + int anslen; + struct nwent *result; + + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, ansbuf, MAXPACKET); + if (anslen < 0) { + memput(ansbuf, MAXPACKET); + return (NULL); + } + result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_name, + AF_INET, name, NULL, 0)); + memput(ansbuf, MAXPACKET); + return (result); +} + +static struct nwent * +get1101byaddr(struct irs_nw *this, u_char *net, int len) { + struct pvt *pvt = (struct pvt *)this->private; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"]; + struct nwent *result; + u_char *ansbuf; + int anslen; + + if (len < 1 || len > 32) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0) + return (NULL); + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, ansbuf, MAXPACKET); + if (anslen < 0) { + memput(ansbuf, MAXPACKET); + return (NULL); + } + result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr, + AF_INET, NULL, net, len)); + memput(ansbuf, MAXPACKET); + return (result); +} + +static struct nwent * +get1101answer(struct irs_nw *this, + u_char *ansbuf, int anslen, enum by_what by_what, + int af, const char *name, const u_char *addr, int addrlen) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, ancount, qdcount, haveanswer; + char *bp, *ep, **ap; + u_char *cp, *eom; + HEADER *hp; + + /* Initialize, and parse header. */ + eom = ansbuf + anslen; + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + } + ancount = ntohs(hp->ancount); + if (!ancount) { + if (hp->aa) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + else + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); + return (NULL); + } + + /* Prepare a return structure. */ + bp = pvt->buf; + ep = pvt->buf + sizeof (pvt->buf); + pvt->net.n_name = NULL; + pvt->net.n_aliases = pvt->ali; + pvt->net.n_addrtype = af; + pvt->net.n_addr = NULL; + pvt->net.n_length = addrlen; + + /* Save input key if given. */ + switch (by_what) { + case by_name: + if (name != NULL) { + int n = strlen(name) + 1; + + if (n > (ep - bp)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } +#ifdef HAVE_STRLCPY + strlcpy(bp, name, ep - bp); + pvt->net.n_name = bp; +#else + pvt->net.n_name = strcpy(bp, name); +#endif + bp += n; + } + break; + case by_addr: + if (addr != NULL && addrlen != 0) { + int n = addrlen / 8 + ((addrlen % 8) != 0); + + if (INADDRSZ > (ep - bp)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + memset(bp, 0, INADDRSZ); + memcpy(bp, addr, n); + pvt->net.n_addr = bp; + bp += INADDRSZ; + } + break; + default: + abort(); + } + + /* Parse the answer, collect aliases. */ + ap = pvt->ali; + haveanswer = 0; + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + + cp += n; /* Owner */ + if (n < 0 || !maybe_dnok(pvt->res, bp) || + cp + 3 * INT16SZ + INT32SZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + GETSHORT(type, cp); /* Type */ + GETSHORT(class, cp); /* Class */ + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); /* RDLENGTH */ + if (class == C_IN && type == T_PTR) { + int nn; + + nn = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + normalize_name(bp); + switch (by_what) { + case by_addr: { + if (pvt->net.n_name == NULL) + pvt->net.n_name = bp; + else if (ns_samename(pvt->net.n_name, bp) == 1) + break; + else + *ap++ = bp; + nn = strlen(bp) + 1; + bp += nn; + haveanswer++; + break; + } + case by_name: { + u_int b1, b2, b3, b4; + + if (pvt->net.n_addr != NULL || + sscanf(bp, "%u.%u.%u.%u.in-addr.arpa", + &b1, &b2, &b3, &b4) != 4) + break; + if ((ep - bp) < INADDRSZ) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_addr = bp; + *bp++ = b4; + *bp++ = b3; + *bp++ = b2; + *bp++ = b1; + pvt->net.n_length = INADDRSZ * 8; + haveanswer++; + } + } + } + cp += n; /* RDATA */ + } + if (!haveanswer) { + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); + return (NULL); + } + *ap = NULL; + + return (&pvt->net); +} + +static struct nwent * +get1101mask(struct irs_nw *this, struct nwent *nwent) { + struct pvt *pvt = (struct pvt *)this->private; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME]; + int anslen, type, class, ancount, qdcount; + u_char *ansbuf, *cp, *eom; + HEADER *hp; + + if (!nwent) + return (NULL); + if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf) + < 0) { + /* "First, do no harm." */ + return (nwent); + } + + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + /* Query for the A RR that would hold this network's mask. */ + anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, MAXPACKET); + if (anslen < HFIXEDSZ) { + memput(ansbuf, MAXPACKET); + return (nwent); + } + + /* Initialize, and parse header. */ + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + eom = ansbuf + anslen; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) { + memput(ansbuf, MAXPACKET); + return (nwent); + } + } + ancount = ntohs(hp->ancount); + + /* Parse the answer, collect aliases. */ + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner); + + if (n < 0 || !maybe_dnok(pvt->res, owner)) + break; + cp += n; /* Owner */ + if (cp + 3 * INT16SZ + INT32SZ > eom) + break; + GETSHORT(type, cp); /* Type */ + GETSHORT(class, cp); /* Class */ + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); /* RDLENGTH */ + if (cp + n > eom) + break; + if (n == INADDRSZ && class == C_IN && type == T_A && + ns_samename(qbuf, owner) == 1) { + /* This A RR indicates the actual netmask. */ + int nn, mm; + + nwent->n_length = 0; + for (nn = 0; nn < INADDRSZ; nn++) + for (mm = 7; mm >= 0; mm--) + if (cp[nn] & (1 << mm)) + nwent->n_length++; + else + break; + } + cp += n; /* RDATA */ + } + memput(ansbuf, MAXPACKET); + return (nwent); +} + +static int +make1101inaddr(const u_char *net, int bits, char *name, int size) { + int n, m; + char *ep; + + ep = name + size; + + /* Zero fill any whole bytes left out of the prefix. */ + for (n = (32 - bits) / 8; n > 0; n--) { + if (ep - name < (int)(sizeof "0.")) + goto emsgsize; + m = SPRINTF((name, "0.")); + name += m; + } + + /* Format the partial byte, if any, within the prefix. */ + if ((n = bits % 8) != 0) { + if (ep - name < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", + net[bits / 8] & ~((1 << (8 - n)) - 1))); + name += m; + } + + /* Format the whole bytes within the prefix. */ + for (n = bits / 8; n > 0; n--) { + if (ep - name < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", net[n - 1])); + name += m; + } + + /* Add the static text. */ + if (ep - name < (int)(sizeof "in-addr.arpa")) + goto emsgsize; + (void) SPRINTF((name, "in-addr.arpa")); + return (0); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static void +normalize_name(char *name) { + char *t; + + /* Make lower case. */ + for (t = name; *t; t++) + if (isascii((unsigned char)*t) && isupper((unsigned char)*t)) + *t = tolower(*t); + + /* Remove trailing dots. */ + while (t > name && t[-1] == '.') + *--t = '\0'; +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/irs/dns_p.h b/usr/src/lib/libresolv2/common/irs/dns_p.h new file mode 100644 index 0000000000..cc45a8e3fc --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/dns_p.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: dns_p.h,v 1.11 1999/06/03 20:50:36 vixie Exp $ + */ + +#ifndef _DNS_P_H_INCLUDED +#define _DNS_P_H_INCLUDED + +#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0 || \ + (ok)(nm) != 0) +#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) +#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) + +/* + * Object state. + */ +struct dns_p { + void *hes_ctx; + struct __res_state *res; + void (*free_res) __P((void *)); +}; + +/* + * Methods. + */ + +extern struct irs_gr * irs_dns_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_dns_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_dns_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_dns_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_dns_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_dns_nw __P((struct irs_acc *)); + +#endif /*_DNS_P_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2/common/irs/dns_pr.c b/usr/src/lib/libresolv2/common/irs/dns_pr.c new file mode 100644 index 0000000000..10a574e0ea --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/dns_pr.c @@ -0,0 +1,273 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pr.c,v 1.15 2001/05/29 05:48:31 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p * dns; + struct protoent proto; + char * prbuf; +}; + +/* Forward. */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); +static struct __res_state * pr_res_get(struct irs_pr *); +static void pr_res_set(struct irs_pr *, + struct __res_state *, + void (*)(void *)); + +static struct protoent * parse_hes_list(struct irs_pr *, char **); + +/* Public. */ + +struct irs_pr * +irs_dns_pr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct pvt *pvt; + struct irs_pr *pr; + + if (!dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(pr = memget(sizeof *pr))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + pvt->dns = dns; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + pr->res_get = pr_res_get; + pr->res_set = pr_res_set; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "protocol"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char numstr[16]; + char **hes_list; + + sprintf(numstr, "%d", num); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, numstr, "protonum"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +pr_rewind(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +static void +pr_minimize(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +static struct __res_state * +pr_res_get(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +pr_res_set(struct irs_pr *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +/* Private. */ + +static struct protoent * +parse_hes_list(struct irs_pr *this, char **hes_list) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Skip blank lines. */ + p = cp; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = strdup(cp); + + p = pvt->prbuf; + pvt->proto.p_name = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->proto.p_proto = atoi(p); + while (*p && !isspace((unsigned char)*p)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->proto.p_aliases) { + max += 10; + new = realloc(pvt->proto.p_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = new; + } + pvt->proto.p_aliases[num++] = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[num] = NULL; + return (&pvt->proto); + } + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} diff --git a/usr/src/lib/libresolv2/common/irs/dns_pw.c b/usr/src/lib/libresolv2/common/irs/dns_pw.c new file mode 100644 index 0000000000..c40ef80e15 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/dns_pw.c @@ -0,0 +1,238 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pw.c,v 1.19 2001/05/29 05:48:32 marka Exp $"; +#endif + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <isc/memcluster.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p * dns; + struct passwd passwd; + char * pwbuf; +}; + +/* Forward. */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static struct passwd * pw_next(struct irs_pw *); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); +static struct __res_state * pw_res_get(struct irs_pw *); +static void pw_res_set(struct irs_pw *, + struct __res_state *, + void (*)(void *)); + +static struct passwd * getpwcommon(struct irs_pw *, const char *, + const char *); + +/* Public. */ + +struct irs_pw * +irs_dns_pw(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_pw *pw; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(pw = memget(sizeof *pw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + pw->private = pvt; + pw->close = pw_close; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->next = pw_next; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = pw_res_get; + pw->res_set = pw_res_set; + return (pw); +} + +/* Methods. */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pwbuf) + free(pvt->pwbuf); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *nam) { + return (getpwcommon(this, nam, "passwd")); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + char uidstr[16]; + + sprintf(uidstr, "%lu", (u_long)uid); + return (getpwcommon(this, uidstr, "uid")); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +static void +pw_minimize(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +static struct __res_state * +pw_res_get(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +pw_res_set(struct irs_pw *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +/* Private. */ + +static struct passwd * +getpwcommon(struct irs_pw *this, const char *arg, const char *type) { + struct pvt *pvt = (struct pvt *)this->private; + char **hes_list, *cp; + + if (!(hes_list = hesiod_resolve(pvt->dns->hes_ctx, arg, type))) + return (NULL); + if (!*hes_list) { + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + errno = ENOENT; + return (NULL); + } + + memset(&pvt->passwd, 0, sizeof pvt->passwd); + if (pvt->pwbuf) + free(pvt->pwbuf); + pvt->pwbuf = strdup(*hes_list); + hesiod_free_list(pvt->dns->hes_ctx, hes_list); + + cp = pvt->pwbuf; + pvt->passwd.pw_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_uid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gecos = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_dir = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_shell = cp; + return (&pvt->passwd); + + cleanup: + free(pvt->pwbuf); + pvt->pwbuf = NULL; + return (NULL); +} + +#endif /* WANT_IRS_PW */ diff --git a/usr/src/lib/libresolv2/common/irs/dns_sv.c b/usr/src/lib/libresolv2/common/irs/dns_sv.c new file mode 100644 index 0000000000..6afeb5a56e --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/dns_sv.c @@ -0,0 +1,305 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_sv.c,v 1.20 2001/05/29 05:48:33 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Definitions */ + +struct pvt { + struct dns_p * dns; + struct servent serv; + char * svbuf; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward. */ + +static void sv_close(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, + const char *, const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static struct servent * sv_next(struct irs_sv *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +#ifdef SV_RES_SETGET +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); +#endif + +static struct servent * parse_hes_list(struct irs_sv *, + char **, const char *); + +/* Public */ + +struct irs_sv * +irs_dns_sv(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(sv = memget(sizeof *sv))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + sv->private = pvt; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->next = sv_next; + sv->rewind = sv_rewind; + sv->close = sv_close; + sv->minimize = sv_minimize; +#ifdef SV_RES_SETGET + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; +#else + sv->res_get = NULL; /* sv_res_get; */ + sv->res_set = NULL; /* sv_res_set; */ +#endif + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "service"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char portstr[16]; + char **hes_list; + + sprintf(portstr, "%d", ntohs(port)); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, portstr, "port"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_next(struct irs_sv *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +sv_rewind(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct servent * +parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int proto_len; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Check to make sure the protocol matches. */ + p = cp; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + if (proto) { + proto_len = strlen(proto); + if (strncasecmp(++p, proto, proto_len) != 0) + continue; + if (p[proto_len] && !isspace(p[proto_len]&0xff)) + continue; + } + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = strdup(cp); + + p = pvt->svbuf; + pvt->serv.s_name = p; + while (*p && !isspace(*p&0xff)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_proto = p; + while (*p && !isspace(*p&0xff)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_port = htons((u_short) atoi(p)); + while (*p && !isspace(*p&0xff)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->serv.s_aliases) { + max += 10; + new = realloc(pvt->serv.s_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = new; + } + pvt->serv.s_aliases[num++] = p; + while (*p && !isspace(*p&0xff)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[num] = NULL; + return (&pvt->serv); + } + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +sv_minimize(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +#ifdef SV_RES_SETGET +static struct __res_state * +sv_res_get(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +sv_res_set(struct irs_sv *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} +#endif diff --git a/usr/src/lib/libresolv2/common/irs/gai_strerror.c b/usr/src/lib/libresolv2/common/irs/gai_strerror.c new file mode 100644 index 0000000000..652d51debd --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gai_strerror.c @@ -0,0 +1,93 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 2001 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <port_before.h> +#include <netdb.h> +#include <port_after.h> + +#ifdef DO_PTHREADS +#include <pthread.h> +#include <stdlib.h> +#endif + +static const char *gai_errlist[] = { + "no error", + "address family not supported for name",/* EAI_ADDRFAMILY */ + "temporary failure", /* EAI_AGAIN */ + "invalid flags", /* EAI_BADFLAGS */ + "permanent failure", /* EAI_FAIL */ + "address family not supported", /* EAI_FAMILY */ + "memory failure", /* EAI_MEMORY */ + "no address", /* EAI_NODATA */ + "unknown name or service", /* EAI_NONAME */ + "service not supported for socktype", /* EAI_SERVICE */ + "socktype not supported", /* EAI_SOCKTYPE */ + "system failure", /* EAI_SYSTEM */ + "bad hints", /* EAI_BADHINTS */ + "bad protocol", /* EAI_PROTOCOL */ + + "unknown error" /* Must be last. */ +}; + +static const int gai_nerr = (sizeof(gai_errlist)/sizeof(*gai_errlist)); + +#define EAI_BUFSIZE 128 + +const char * +gai_strerror(int ecode) { +#ifndef DO_PTHREADS + static char buf[EAI_BUFSIZE]; +#else /* DO_PTHREADS */ + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + static pthread_key_t key; + static int once = 0; + char *buf; +#endif + + if (ecode >= 0 && ecode < (gai_nerr - 1)) + return (gai_errlist[ecode]); + +#ifdef DO_PTHREADS + if (!once) { + pthread_mutex_lock(&lock); + if (!once++) + pthread_key_create(&key, free); + pthread_mutex_unlock(&lock); + } + + buf = pthread_getspecific(key); + if (buf == NULL) { + buf = malloc(EAI_BUFSIZE); + if (buf == NULL) + return ("unknown error"); + pthread_setspecific(key, buf); + } +#endif + /* + * XXX This really should be snprintf(buf, EAI_BUFSIZE, ...). + * It is safe until message catalogs are used. + */ + sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode); + return (buf); +} diff --git a/usr/src/lib/libresolv2/common/irs/gen.c b/usr/src/lib/libresolv2/common/irs/gen.c new file mode 100644 index 0000000000..10acc388f1 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen.c @@ -0,0 +1,457 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen.c,v 1.26 2001/05/29 05:48:35 marka Exp $"; +#endif + +/* + * this is the top level dispatcher + * + * The dispatcher is implemented as an accessor class; it is an + * accessor class that calls other accessor classes, as controlled by a + * configuration file. + * + * A big difference between this accessor class and others is that the + * map class initializers are NULL, and the map classes are already + * filled in with method functions that will do the right thing. + */ + +/* Imports */ + +#include "port_before.h" + +#include <isc/assertions.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +#ifdef SUNW_HOSTS_FALLBACK +extern int __res_no_hosts_fallback(void); +#endif /* SUNW_HOSTS_FALLBACK */ + +/* Definitions */ + +struct nameval { + const char * name; + int val; +}; + +static const struct nameval acc_names[irs_nacc+1] = { + { "local", irs_lcl }, + { "dns", irs_dns }, + { "nis", irs_nis }, + { "irp", irs_irp }, + { NULL, irs_nacc } +}; + +typedef struct irs_acc *(*accinit) __P((const char *options)); + +static const accinit accs[irs_nacc+1] = { + irs_lcl_acc, + irs_dns_acc, +#ifdef WANT_IRS_NIS + irs_nis_acc, +#else + NULL, +#endif + irs_irp_acc, + NULL +}; + +static const struct nameval map_names[irs_nmap+1] = { + { "group", irs_gr }, + { "passwd", irs_pw }, + { "services", irs_sv }, + { "protocols", irs_pr }, + { "hosts", irs_ho }, + { "networks", irs_nw }, + { "netgroup", irs_ng }, + { NULL, irs_nmap } +}; + +static const struct nameval option_names[] = { + { "merge", IRS_MERGE }, + { "continue", IRS_CONTINUE }, + { NULL, 0 } +}; + +/* Forward */ + +static void gen_close(struct irs_acc *); +static struct __res_state * gen_res_get(struct irs_acc *); +static void gen_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); +static int find_name(const char *, const struct nameval nv[]); +static void init_map_rules(struct gen_p *, const char *conf_file); +static struct irs_rule *release_rule(struct irs_rule *); +static int add_rule(struct gen_p *, + enum irs_map_id, enum irs_acc_id, + const char *); + +/* Public */ + +struct irs_acc * +irs_gen_acc(const char *options, const char *conf_file) { + struct irs_acc *acc; + struct gen_p *irs; + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irs = memget(sizeof *irs))) { + errno = ENOMEM; + memput(acc, sizeof *acc); + return (NULL); + } + memset(irs, 0x5e, sizeof *irs); + irs->options = strdup(options); + irs->res = NULL; + irs->free_res = NULL; + memset(irs->accessors, 0, sizeof irs->accessors); + memset(irs->map_rules, 0, sizeof irs->map_rules); + init_map_rules(irs, conf_file); + acc->private = irs; +#ifdef WANT_IRS_GR + acc->gr_map = irs_gen_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_gen_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_gen_sv; + acc->pr_map = irs_gen_pr; + acc->ho_map = irs_gen_ho; + acc->nw_map = irs_gen_nw; + acc->ng_map = irs_gen_ng; + acc->res_get = gen_res_get; + acc->res_set = gen_res_set; + acc->close = gen_close; + return (acc); +} + +/* Methods */ + +static struct __res_state * +gen_res_get(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + + if (irs->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + gen_res_set(this, res, free); + } + + if (((irs->res->options & RES_INIT) == 0) && res_ninit(irs->res) < 0) + return (NULL); + + return (irs->res); +} + +static void +gen_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct gen_p *irs = (struct gen_p *)this->private; +#if 0 + struct irs_rule *rule; + struct irs_ho *ho; + struct irs_nw *nw; +#endif + + if (irs->res && irs->free_res) { + res_nclose(irs->res); + (*irs->free_res)(irs->res); + } + + irs->res = res; + irs->free_res = free_res; + +#if 0 + for (rule = irs->map_rules[irs_ho]; rule; rule = rule->next) { + ho = rule->inst->ho; + + (*ho->res_set)(ho, res, NULL); + } + for (rule = irs->map_rules[irs_nw]; rule; rule = rule->next) { + nw = rule->inst->nw; + + (*nw->res_set)(nw, res, NULL); + } +#endif +} + +static void +gen_close(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + int n; + + /* Search rules. */ + for (n = 0; n < irs_nmap; n++) + while (irs->map_rules[n] != NULL) + irs->map_rules[n] = release_rule(irs->map_rules[n]); + + /* Access methods. */ + for (n = 0; n < irs_nacc; n++) { + /* Map objects. */ + if (irs->accessors[n].gr != NULL) + (*irs->accessors[n].gr->close)(irs->accessors[n].gr); + if (irs->accessors[n].pw != NULL) + (*irs->accessors[n].pw->close)(irs->accessors[n].pw); + if (irs->accessors[n].sv != NULL) + (*irs->accessors[n].sv->close)(irs->accessors[n].sv); + if (irs->accessors[n].pr != NULL) + (*irs->accessors[n].pr->close)(irs->accessors[n].pr); + if (irs->accessors[n].ho != NULL) + (*irs->accessors[n].ho->close)(irs->accessors[n].ho); + if (irs->accessors[n].nw != NULL) + (*irs->accessors[n].nw->close)(irs->accessors[n].nw); + if (irs->accessors[n].ng != NULL) + (*irs->accessors[n].ng->close)(irs->accessors[n].ng); + /* Enclosing accessor. */ + if (irs->accessors[n].acc != NULL) + (*irs->accessors[n].acc->close)(irs->accessors[n].acc); + } + + /* The options string was strdup'd. */ + free((void*)irs->options); + + if (irs->res && irs->free_res) + (*irs->free_res)(irs->res); + + /* The private data container. */ + memput(irs, sizeof *irs); + + /* The object. */ + memput(this, sizeof *this); +} + +/* Private */ + +static int +find_name(const char *name, const struct nameval names[]) { + int n; + + for (n = 0; names[n].name != NULL; n++) + if (strcmp(name, names[n].name) == 0) + return (names[n].val); + return (-1); +} + +static struct irs_rule * +release_rule(struct irs_rule *rule) { + struct irs_rule *next = rule->next; + + memput(rule, sizeof *rule); + return (next); +} + +static int +add_rule(struct gen_p *irs, + enum irs_map_id map, enum irs_acc_id acc, + const char *options) +{ + struct irs_rule **rules, *last, *tmp, *new; + struct irs_inst *inst; + const char *cp; + int n; + +#ifndef WANT_IRS_GR + if (map == irs_gr) + return (-1); +#endif +#ifndef WANT_IRS_PW + if (map == irs_pw) + return (-1); +#endif +#ifndef WANT_IRS_NIS + if (acc == irs_nis) + return (-1); +#endif + new = memget(sizeof *new); + if (new == NULL) + return (-1); + memset(new, 0x5e, sizeof *new); + new->next = NULL; + + new->inst = &irs->accessors[acc]; + + new->flags = 0; + cp = options; + while (cp && *cp) { + char option[50], *next; + + next = strchr(cp, ','); + if (next) + n = next++ - cp; + else + n = strlen(cp); + if ((size_t)n > sizeof option - 1) + n = sizeof option - 1; + strncpy(option, cp, n); + option[n] = '\0'; + + n = find_name(option, option_names); + if (n >= 0) + new->flags |= n; + + cp = next; + } + + rules = &irs->map_rules[map]; + for (last = NULL, tmp = *rules; + tmp != NULL; + last = tmp, tmp = tmp->next) + (void)NULL; + if (last == NULL) + *rules = new; + else + last->next = new; + + /* Try to instantiate map accessors for this if necessary & approp. */ + inst = &irs->accessors[acc]; + if (inst->acc == NULL && accs[acc] != NULL) + inst->acc = (*accs[acc])(irs->options); + if (inst->acc != NULL) { + if (inst->gr == NULL && inst->acc->gr_map != NULL) + inst->gr = (*inst->acc->gr_map)(inst->acc); + if (inst->pw == NULL && inst->acc->pw_map != NULL) + inst->pw = (*inst->acc->pw_map)(inst->acc); + if (inst->sv == NULL && inst->acc->sv_map != NULL) + inst->sv = (*inst->acc->sv_map)(inst->acc); + if (inst->pr == NULL && inst->acc->pr_map != NULL) + inst->pr = (*inst->acc->pr_map)(inst->acc); + if (inst->ho == NULL && inst->acc->ho_map != NULL) + inst->ho = (*inst->acc->ho_map)(inst->acc); + if (inst->nw == NULL && inst->acc->nw_map != NULL) + inst->nw = (*inst->acc->nw_map)(inst->acc); + if (inst->ng == NULL && inst->acc->ng_map != NULL) + inst->ng = (*inst->acc->ng_map)(inst->acc); + } + + return (0); +} + +static void +default_map_rules(struct gen_p *irs) { + /* Install time honoured and proved BSD style rules as default. */ + add_rule(irs, irs_gr, irs_lcl, ""); + add_rule(irs, irs_pw, irs_lcl, ""); + add_rule(irs, irs_sv, irs_lcl, ""); + add_rule(irs, irs_pr, irs_lcl, ""); +#ifdef SUNW_HOSTS_FALLBACK + if (__res_no_hosts_fallback()) + add_rule(irs, irs_ho, irs_dns, ""); + else { + add_rule(irs, irs_ho, irs_dns, "continue"); + add_rule(irs, irs_ho, irs_lcl, ""); + } +#else /* SUNW_HOSTS_FALLBACK */ + add_rule(irs, irs_ho, irs_dns, "continue"); + add_rule(irs, irs_ho, irs_lcl, ""); +#endif /* SUNW_HOSTS_FALLBACK */ + add_rule(irs, irs_nw, irs_dns, "continue"); + add_rule(irs, irs_nw, irs_lcl, ""); + add_rule(irs, irs_ng, irs_lcl, ""); +} + +static void +init_map_rules(struct gen_p *irs, const char *conf_file) { + char line[1024], pattern[40], mapname[20], accname[20], options[100]; + FILE *conf; + +#ifdef SUNW_HOSTS_FALLBACK + if (__res_no_hosts_fallback()) { + default_map_rules(irs); + return; + } +#endif /* SUNW_HOSTS_FALLBACK */ + + if (conf_file == NULL) + conf_file = _PATH_IRS_CONF ; + + /* A conf file of "" means compiled in defaults. Irpd wants this */ + if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) { + default_map_rules(irs); + return; + } + (void) sprintf(pattern, "%%%ds %%%ds %%%ds\n", + sizeof mapname, sizeof accname, sizeof options); + while (fgets(line, sizeof line, conf)) { + enum irs_map_id map; + enum irs_acc_id acc; + char *tmp; + int n; + + for (tmp = line; + isascii((unsigned char)*tmp) && + isspace((unsigned char)*tmp); + tmp++) + (void)NULL; + if (*tmp == '#' || *tmp == '\n' || *tmp == '\0') + continue; + n = sscanf(tmp, pattern, mapname, accname, options); + if (n < 2) + continue; + if (n < 3) + options[0] = '\0'; + + n = find_name(mapname, map_names); + INSIST(n < irs_nmap); + if (n < 0) + continue; + map = (enum irs_map_id) n; + + n = find_name(accname, acc_names); + INSIST(n < irs_nacc); + if (n < 0) + continue; + acc = (enum irs_acc_id) n; + + add_rule(irs, map, acc, options); + } + fclose(conf); +} diff --git a/usr/src/lib/libresolv2/common/irs/gen_gr.c b/usr/src/lib/libresolv2/common/irs/gen_gr.c new file mode 100644 index 0000000000..1caf7a22c5 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen_gr.c @@ -0,0 +1,489 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_gr.c,v 1.26 2002/07/18 02:07:44 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_GR +static int __bind_irs_gr_unneeded; +#else + +#include <sys/types.h> + +#include <isc/assertions.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_gr * gr; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static int gr_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +static void gr_minimize(struct irs_gr *); +static struct __res_state * gr_res_get(struct irs_gr *); +static void gr_res_set(struct irs_gr *, + struct __res_state *, + void (*)(void *)); + +static void grmerge(struct irs_gr *gr, const struct group *src, + int preserve); + +static int countvec(char **vec); +static int isnew(char **old, char *new); +static int countnew(char **old, char **new); +static size_t sizenew(char **old, char **new); +static int newgid(int, gid_t *, gid_t); + +/* Public */ + +struct irs_gr * +irs_gen_gr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_gr]; + pvt->rule = pvt->rules; + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = gr_list; + gr->minimize = gr_minimize; + gr->res_get = gr_res_get; + gr->res_set = gr_res_set; + return (gr); +} + +/* Methods. */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *rval; + struct irs_gr *gr; + + while (pvt->rule) { + gr = pvt->rule->inst->gr; + rval = (*gr->next)(gr); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + gr = pvt->rule->inst->gr; + (*gr->rewind)(gr); + } + } + return (NULL); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct group *tval; + struct irs_gr *gr; + int dirty; + + dirty = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + gr = rule->inst->gr; + tval = (*gr->byname)(gr, name); + if (tval) { + grmerge(this, tval, dirty++); + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + if (dirty) + return (&pvt->group); + return (NULL); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct group *tval; + struct irs_gr *gr; + int dirty; + + dirty = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + gr = rule->inst->gr; + tval = (*gr->bygid)(gr, gid); + if (tval) { + grmerge(this, tval, dirty++); + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + if (dirty) + return (&pvt->group); + return (NULL); +} + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_gr *gr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + gr = pvt->rule->inst->gr; + (*gr->rewind)(gr); + } +} + +static int +gr_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_gr *gr; + int t_ngroups, maxgroups; + gid_t *t_groups; + int n, t, rval = 0; + + maxgroups = *ngroups; + *ngroups = 0; + t_groups = (gid_t *)malloc(maxgroups * sizeof(gid_t)); + if (!t_groups) { + errno = ENOMEM; + return (-1); + } + + for (rule = pvt->rules; rule; rule = rule->next) { + t_ngroups = maxgroups; + gr = rule->inst->gr; + t = (*gr->list)(gr, name, basegid, t_groups, &t_ngroups); + for (n = 0; n < t_ngroups; n++) { + if (newgid(*ngroups, groups, t_groups[n])) { + if (*ngroups == maxgroups) { + rval = -1; + goto done; + } + groups[(*ngroups)++] = t_groups[n]; + } + } + if (t == 0) { + if (!(rule->flags & IRS_MERGE)) + break; + } else { + if (!(rule->flags & IRS_CONTINUE)) + break; + } + } + done: + free(t_groups); + return (rval); +} + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_gr *gr = rule->inst->gr; + + (*gr->minimize)(gr); + } +} + +static struct __res_state * +gr_res_get(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + gr_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +gr_res_set(struct irs_gr *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_gr *gr = rule->inst->gr; + + if (gr->res_set) + (*gr->res_set)(gr, pvt->res, NULL); + } +} + +/* Private. */ + +static void +grmerge(struct irs_gr *this, const struct group *src, int preserve) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **m, **p, *oldmembuf, *ep; + int n, ndst, nnew; + size_t used; + + if (!preserve) { + pvt->group.gr_gid = src->gr_gid; + if (pvt->nmemb < 1) { + m = malloc(sizeof *m); + if (!m) { + /* No harm done, no work done. */ + return; + } + pvt->group.gr_mem = m; + pvt->nmemb = 1; + } + pvt->group.gr_mem[0] = NULL; + } + ndst = countvec(pvt->group.gr_mem); + nnew = countnew(pvt->group.gr_mem, src->gr_mem); + + /* + * Make sure destination member array is large enough. + * p points to new portion. + */ + n = ndst + nnew + 1; + if ((size_t)n > pvt->nmemb) { + m = realloc(pvt->group.gr_mem, n * sizeof *m); + if (!m) { + /* No harm done, no work done. */ + return; + } + pvt->group.gr_mem = m; + pvt->nmemb = n; + } + p = pvt->group.gr_mem + ndst; + + /* + * Enlarge destination membuf; cp points at new portion. + */ + n = sizenew(pvt->group.gr_mem, src->gr_mem); + INSIST((nnew == 0) == (n == 0)); + if (!preserve) { + n += strlen(src->gr_name) + 1; + n += strlen(src->gr_passwd) + 1; + } + if (n == 0) { + /* No work to do. */ + return; + } + used = preserve ? pvt->membufsize : 0; + cp = malloc(used + n); + if (!cp) { + /* No harm done, no work done. */ + return; + } + ep = cp + used + n; + if (used != 0) + memcpy(cp, pvt->membuf, used); + oldmembuf = pvt->membuf; + pvt->membuf = cp; + pvt->membufsize = used + n; + cp += used; + + /* + * Adjust group.gr_mem. + */ + if (pvt->membuf != oldmembuf) + for (m = pvt->group.gr_mem; *m; m++) + *m = pvt->membuf + (*m - oldmembuf); + + /* + * Add new elements. + */ + for (m = src->gr_mem; *m; m++) + if (isnew(pvt->group.gr_mem, *m)) { + *p++ = cp; + *p = NULL; +#ifdef HAVE_STRLCPY + strlcpy(cp, *m, ep - cp); +#else + strcpy(cp, *m); +#endif + cp += strlen(cp) + 1; + } + if (preserve) { + pvt->group.gr_name = pvt->membuf + + (pvt->group.gr_name - oldmembuf); + pvt->group.gr_passwd = pvt->membuf + + (pvt->group.gr_passwd - oldmembuf); + } else { + pvt->group.gr_name = cp; +#ifdef HAVE_STRLCPY + strlcpy(cp, src->gr_name, ep - cp); +#else + strcpy(cp, src->gr_name); +#endif + cp += strlen(src->gr_name) + 1; + pvt->group.gr_passwd = cp; +#ifdef HAVE_STRLCPY + strlcpy(cp, src->gr_passwd, ep - cp); +#else + strcpy(cp, src->gr_passwd); +#endif + cp += strlen(src->gr_passwd) + 1; + } + if (oldmembuf != NULL) + free(oldmembuf); + INSIST(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]); +} + +static int +countvec(char **vec) { + int n = 0; + + while (*vec++) + n++; + return (n); +} + +static int +isnew(char **old, char *new) { + for (; *old; old++) + if (strcmp(*old, new) == 0) + return (0); + return (1); +} + +static int +countnew(char **old, char **new) { + int n = 0; + + for (; *new; new++) + n += isnew(old, *new); + return (n); +} + +static size_t +sizenew(char **old, char **new) { + size_t n = 0; + + for (; *new; new++) + if (isnew(old, *new)) + n += strlen(*new) + 1; + return (n); +} + +static int +newgid(int ngroups, gid_t *groups, gid_t group) { + ngroups--, groups++; + for (; ngroups-- > 0; groups++) + if (*groups == group) + return (0); + return (1); +} + +#endif /* WANT_IRS_GR */ diff --git a/usr/src/lib/libresolv2/common/irs/gen_ho.c b/usr/src/lib/libresolv2/common/irs/gen_ho.c new file mode 100644 index 0000000000..529738d8be --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen_ho.c @@ -0,0 +1,398 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: gen_ho.c,v 1.16 2001/05/29 05:48:36 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_ho * ho; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static int init(struct irs_ho *this); + +/* Exports */ + +struct irs_ho * +irs_gen_ho(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + pvt->rules = accpvt->map_rules[irs_ho]; + pvt->rule = pvt->rules; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byname)(ho, name); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * The value TRY_AGAIN can mean that the service + * is not available, or just that this particular name + * cannot be resolved now. We use the errno ECONNREFUSED + * to distinguish. If a lookup sets that errno when + * H_ERRNO is TRY_AGAIN, we continue to try other lookup + * functions, otherwise we return the TRY_AGAIN error. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byname2)(ho, name, af); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byaddr)(ho, addr, len, af); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + struct irs_ho *ho; + + while (pvt->rule) { + ho = pvt->rule->inst->ho; + rval = (*ho->next)(ho); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } + } + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ho *ho; + + pvt->rule = pvt->rules; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res) + res_nclose(pvt->res); + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->minimize)(ho); + } +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->res_set)(ho, pvt->res, NULL); + } +} + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct addrinfo *rval = NULL; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + if (ho->addrinfo == NULL) /* for safety */ + continue; + rval = (*ho->addrinfo)(ho, name, pai); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || + errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + if (rval) + freeaddrinfo(rval); + return (NULL); +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + + if (((pvt->res->options & RES_INIT) == 0) && + (res_ninit(pvt->res) == -1)) + return (-1); + + return (0); +} diff --git a/usr/src/lib/libresolv2/common/irs/gen_ng.c b/usr/src/lib/libresolv2/common/irs/gen_ng.c new file mode 100644 index 0000000000..c628193868 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen_ng.c @@ -0,0 +1,179 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_ng.c,v 1.15 2001/05/29 05:48:38 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + char * curgroup; +}; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_gen_ng(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_ng]; + pvt->rule = pvt->rules; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ng_minimize(this); + if (pvt->curgroup) + free(pvt->curgroup); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + while (pvt->rule) { + ng = pvt->rule->inst->ng; + if ((*ng->next)(ng, host, user, domain) == 1) + return (1); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } + } + return (0); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_ng *ng; + int rval; + + rval = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + ng = rule->inst->ng; + rval = (*ng->test)(ng, name, user, host, domain); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + pvt->rule = pvt->rules; + if (pvt->rule) { + if (pvt->curgroup) + free(pvt->curgroup); + pvt->curgroup = strdup(group); + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ng *ng = rule->inst->ng; + + (*ng->minimize)(ng); + } +} diff --git a/usr/src/lib/libresolv2/common/irs/gen_nw.c b/usr/src/lib/libresolv2/common/irs/gen_nw.c new file mode 100644 index 0000000000..9fbb91a7bd --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen_nw.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_nw.c,v 1.13 1999/10/13 16:39:29 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void nw_close(struct irs_nw*); +static struct nwent * nw_next(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static int init(struct irs_nw *this); + +/* Public */ + +struct irs_nw * +irs_gen_nw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + pvt->rules = accpvt->map_rules[irs_nw]; + pvt->rule = pvt->rules; + nw->private = pvt; + nw->close = nw_close; + nw->next = nw_next; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + while (pvt->rule) { + nw = pvt->rule->inst->nw; + rval = (*nw->next)(nw); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } + } + return (NULL); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + rval = (*nw->byname)(nw, name, type); + if (rval != NULL) + return (rval); + if (pvt->res->res_h_errno != TRY_AGAIN && + !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + rval = (*nw->byaddr)(nw, net, length, type); + if (rval != NULL) + return (rval); + if (pvt->res->res_h_errno != TRY_AGAIN && + !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_nw *nw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res) + res_nclose(pvt->res); + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->minimize)(nw); + } +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->res_set)(nw, pvt->res, NULL); + } +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/irs/gen_p.h b/usr/src/lib/libresolv2/common/irs/gen_p.h new file mode 100644 index 0000000000..f07d02b8fc --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen_p.h @@ -0,0 +1,120 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: gen_p.h,v 1.11 2001/05/29 05:48:39 marka Exp $ + */ + +/* Notes: + * We hope to create a complete set of thread-safe entry points someday, + * which will mean a set of getXbyY() functions that take as an argument + * a pointer to the map class, which will have a pointer to the private + * data, which will be used preferentially to the static variables that + * are necessary to support the "classic" interface. This "classic" + * interface will then be reimplemented as stubs on top of the thread + * safe modules, and will keep the map class pointers as their only + * static data. HOWEVER, we are not there yet. So while we will call + * the just-barely-converted map class methods with map class pointers, + * right now they probably all still use statics. We're not fooling + * anybody, and we're not trying to (yet). + */ + +#ifndef _GEN_P_H_INCLUDED +#define _GEN_P_H_INCLUDED + +/* + * These are the access methods. + */ +enum irs_acc_id { + irs_lcl, /* Local. */ + irs_dns, /* DNS or Hesiod. */ + irs_nis, /* Sun NIS ("YP"). */ + irs_irp, /* IR protocol. */ + irs_nacc +}; + +/* + * These are the map types. + */ +enum irs_map_id { + irs_gr, /* "group" */ + irs_pw, /* "passwd" */ + irs_sv, /* "services" */ + irs_pr, /* "protocols" */ + irs_ho, /* "hosts" */ + irs_nw, /* "networks" */ + irs_ng, /* "netgroup" */ + irs_nmap +}; + +/* + * This is an accessor instance. + */ +struct irs_inst { + struct irs_acc *acc; + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; +}; + +/* + * This is a search rule for some map type. + */ +struct irs_rule { + struct irs_rule * next; + struct irs_inst * inst; + int flags; +}; +#define IRS_MERGE 0x0001 /* Don't stop if acc. has data? */ +#define IRS_CONTINUE 0x0002 /* Don't stop if acc. has no data? */ + +/* + * This is the private data for a search access class. + */ +struct gen_p { + char * options; + struct irs_rule * map_rules[(int)irs_nmap]; + struct irs_inst accessors[(int)irs_nacc]; + struct __res_state * res; + void (*free_res) __P((void *)); +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_gen_acc __P((const char *, const char *conf_file)); +extern struct irs_gr * irs_gen_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_gen_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_gen_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_gen_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_gen_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_gen_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_gen_ng __P((struct irs_acc *)); + +#endif /*_IRS_P_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2/common/irs/gen_pr.c b/usr/src/lib/libresolv2/common/irs/gen_pr.c new file mode 100644 index 0000000000..eefffa75bf --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen_pr.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_pr.c,v 1.12 1999/10/13 16:39:30 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void pr_close(struct irs_pr*); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); +static struct __res_state * pr_res_get(struct irs_pr *); +static void pr_res_set(struct irs_pr *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_pr * +irs_gen_pr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pr]; + pvt->rule = pvt->rules; + pr->private = pvt; + pr->close = pr_close; + pr->next = pr_next; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + pr->res_get = pr_res_get; + pr->res_set = pr_res_set; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + struct irs_pr *pr; + + while (pvt->rule) { + pr = pvt->rule->inst->pr; + rval = (*pr->next)(pr); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } + } + return (NULL); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->byname)(pr, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->bynumber)(pr, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pr *pr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + (*pr->minimize)(pr); + } +} + +static struct __res_state * +pr_res_get(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + pr_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +pr_res_set(struct irs_pr *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + if (pr->res_set) + (*pr->res_set)(pr, pvt->res, NULL); + } +} diff --git a/usr/src/lib/libresolv2/common/irs/gen_pw.c b/usr/src/lib/libresolv2/common/irs/gen_pw.c new file mode 100644 index 0000000000..82d0452a12 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen_pw.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_pw.c,v 1.14 1999/10/13 16:39:30 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <errno.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); +static struct __res_state * pw_res_get(struct irs_pw *); +static void pw_res_set(struct irs_pw *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_pw * +irs_gen_pw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pw]; + pvt->rule = pvt->rules; + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = pw_res_get; + pw->res_set = pw_res_set; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *rval; + struct irs_pw *pw; + + while (pvt->rule) { + pw = pvt->rule->inst->pw; + rval = (*pw->next)(pw); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pw = pvt->rule->inst->pw; + (*pw->rewind)(pw); + } + } + return (NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pw *pw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pw = pvt->rule->inst->pw; + (*pw->rewind)(pw); + } +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct passwd *rval; + struct irs_pw *pw; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pw = rule->inst->pw; + rval = (*pw->byname)(pw, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct passwd *rval; + struct irs_pw *pw; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pw = rule->inst->pw; + rval = (*pw->byuid)(pw, uid); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pw *pw = rule->inst->pw; + + (*pw->minimize)(pw); + } +} + +static struct __res_state * +pw_res_get(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + pw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +pw_res_set(struct irs_pw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pw *pw = rule->inst->pw; + + if (pw->res_set) + (*pw->res_set)(pw, pvt->res, NULL); + } +} + +#endif /* WANT_IRS_PW */ diff --git a/usr/src/lib/libresolv2/common/irs/gen_sv.c b/usr/src/lib/libresolv2/common/irs/gen_sv.c new file mode 100644 index 0000000000..db3c58b02b --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gen_sv.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_sv.c,v 1.12 1999/10/13 16:39:30 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_sv * +irs_gen_sv(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = memget(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = memget(sizeof *pvt))) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_sv]; + pvt->rule = pvt->rules; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + struct irs_sv *sv; + + while (pvt->rule) { + sv = pvt->rule->inst->sv; + rval = (*sv->next)(sv); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } + } + return (NULL); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byname)(sv, name, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byport)(sv, port, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_sv *sv; + + pvt->rule = pvt->rules; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + (*sv->minimize)(sv); + } +} + +static struct __res_state * +sv_res_get(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + sv_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +sv_res_set(struct irs_sv *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + if (sv->res_set) + (*sv->res_set)(sv, pvt->res, NULL); + } +} diff --git a/usr/src/lib/libresolv2/common/irs/getaddrinfo.c b/usr/src/lib/libresolv2/common/irs/getaddrinfo.c new file mode 100644 index 0000000000..a84716a1ce --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getaddrinfo.c @@ -0,0 +1,1307 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * 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. Neither the name of the project 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 PROJECT 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 PROJECT 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. + */ + +/* + * Issues to be discussed: + * - Thread safe-ness must be checked. + * - Return values. There are nonstandard return values defined and used + * in the source code. This is because RFC2553 is silent about which error + * code must be returned for which situation. + * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 + * says to use inet_aton() to convert IPv4 numeric to binary (allows + * classful form as a result). + * current code - disallow classful form for IPv4 (due to use of inet_pton). + * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is + * invalid. + * current code - SEGV on freeaddrinfo(NULL) + * Note: + * - We use getipnodebyname() just for thread-safeness. There's no intent + * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to + * getipnodebyname(). + * - The code filters out AFs that are not supported by the kernel, + * when globbing NULL hostname (to loopback, or wildcard). Is it the right + * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG + * in ai_flags? + * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. + * (1) what should we do against numeric hostname (2) what should we do + * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? + * non-loopback address configured? global address configured? + * - To avoid search order issue, we have a big amount of code duplicate + * from gethnamaddr.c and some other places. The issues that there's no + * lower layer function to lookup "IPv4 or IPv6" record. Calling + * gethostbyname2 from getaddrinfo will end up in wrong search order, as + * follows: + * - The code makes use of following calls when asked to resolver with + * ai_family = PF_UNSPEC: + * getipnodebyname(host, AF_INET6); + * getipnodebyname(host, AF_INET); + * This will result in the following queries if the node is configure to + * prefer /etc/hosts than DNS: + * lookup /etc/hosts for IPv6 address + * lookup DNS for IPv6 address + * lookup /etc/hosts for IPv4 address + * lookup DNS for IPv4 address + * which may not meet people's requirement. + * The right thing to happen is to have underlying layer which does + * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. + * This would result in a bit of code duplicate with _dns_ghbyname() and + * friends. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> + +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <netdb.h> +#include <resolv.h> +#include <string.h> +#include <stdlib.h> +#include <stddef.h> +#include <ctype.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> + +#include <stdarg.h> + +#include <irs.h> +#include <isc/assertions.h> + +#include "port_after.h" + +#include "irs_data.h" + +#define SUCCESS 0 +#define ANY 0 +#define YES 1 +#define NO 0 + +static const char in_addrany[] = { 0, 0, 0, 0 }; +static const char in6_addrany[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +static const char in_loopback[] = { 127, 0, 0, 1 }; +static const char in6_loopback[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +}; + +static const struct afd { + int a_af; + int a_addrlen; + int a_socklen; + int a_off; + const char *a_addrany; + const char *a_loopback; + int a_scoped; +} afdl [] = { + {PF_INET6, sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr), + in6_addrany, in6_loopback, 1}, + {PF_INET, sizeof(struct in_addr), + sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr), + in_addrany, in_loopback, 0}, + {0, 0, 0, 0, NULL, NULL, 0}, +}; + +struct explore { + int e_af; + int e_socktype; + int e_protocol; + const char *e_protostr; + int e_wild; +#define WILD_AF(ex) ((ex)->e_wild & 0x01) +#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) +#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) +}; + +static const struct explore explore[] = { +#if 0 + { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, +#endif + { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, + { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, + { -1, 0, 0, NULL, 0 }, +}; + +#define PTON_MAX 16 + +static int str_isnumber __P((const char *)); +static int explore_fqdn __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_copy __P((const struct addrinfo *, const struct addrinfo *, + struct addrinfo **)); +static int explore_null __P((const struct addrinfo *, + const char *, struct addrinfo **)); +static int explore_numeric __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_numeric_scope __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int get_canonname __P((const struct addrinfo *, + struct addrinfo *, const char *)); +static struct addrinfo *get_ai __P((const struct addrinfo *, + const struct afd *, const char *)); +static struct addrinfo *copy_ai __P((const struct addrinfo *)); +static int get_portmatch __P((const struct addrinfo *, const char *)); +static int get_port __P((const struct addrinfo *, const char *, int)); +static const struct afd *find_afd __P((int)); +static int addrconfig __P((int)); +static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *, + u_int32_t *scopeidp)); +static struct net_data *init __P((void)); + +struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *)); +struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +#if 0 +static const char *ai_errlist[] = { + "Success", + "Address family for hostname not supported", /* EAI_ADDRFAMILY */ + "Temporary failure in name resolution", /* EAI_AGAIN */ + "Invalid value for ai_flags", /* EAI_BADFLAGS */ + "Non-recoverable failure in name resolution", /* EAI_FAIL */ + "ai_family not supported", /* EAI_FAMILY */ + "Memory allocation failure", /* EAI_MEMORY */ + "No address associated with hostname", /* EAI_NODATA */ + "hostname nor servname provided, or not known", /* EAI_NONAME */ + "servname not supported for ai_socktype", /* EAI_SERVICE */ + "ai_socktype not supported", /* EAI_SOCKTYPE */ + "System error returned in errno", /* EAI_SYSTEM */ + "Invalid value for hints", /* EAI_BADHINTS */ + "Resolved protocol is unknown", /* EAI_PROTOCOL */ + "Unknown error", /* EAI_MAX */ +}; +#endif + +/* XXX macros that make external reference is BAD. */ + +#define GET_AI(ai, afd, addr) \ +do { \ + /* external reference: pai, error, and label free */ \ + (ai) = get_ai(pai, (afd), (addr)); \ + if ((ai) == NULL) { \ + error = EAI_MEMORY; \ + goto free; \ + } \ +} while (/*CONSTCOND*/0) + +#define GET_PORT(ai, serv) \ +do { \ + /* external reference: error and label free */ \ + error = get_port((ai), (serv), 0); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define GET_CANONNAME(ai, str) \ +do { \ + /* external reference: pai, error and label free */ \ + error = get_canonname(pai, (ai), (str)); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +/* + * Our compiler does not like an unconditional branch out of a loop, + * especially one defined in a macro! + */ +#ifdef ORIGINAL_ISC_CODE +#define ERR(err) \ +do { \ + /* external reference: error, and label bad */ \ + error = (err); \ + goto bad; \ + /*NOTREACHED*/ \ +} while (/*CONSTCOND*/0) +#else +#define ERR(err) \ +do { \ + /* external reference: error */ \ + error = (err); \ + /*NOTREACHED*/ \ +} while (/*CONSTCOND*/0) +#endif + +#define MATCH_FAMILY(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) +#define MATCH(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) + +#if 0 /* bind8 has its own version */ +char * +gai_strerror(ecode) + int ecode; +{ + if (ecode < 0 || ecode > EAI_MAX) + ecode = EAI_MAX; + return ai_errlist[ecode]; +} +#endif + +void +freeaddrinfo(ai) + struct addrinfo *ai; +{ + struct addrinfo *next; + + do { + next = ai->ai_next; + if (ai->ai_canonname) + free(ai->ai_canonname); + /* no need to free(ai->ai_addr) */ + free(ai); + ai = next; + } while (ai); +} + +static int +str_isnumber(p) + const char *p; +{ + char *ep; + + if (*p == '\0') + return NO; + ep = NULL; + errno = 0; + (void)strtoul(p, &ep, 10); + if (errno == 0 && ep && *ep == '\0') + return YES; + else + return NO; +} + +int +getaddrinfo(hostname, servname, hints, res) + const char *hostname, *servname; + const struct addrinfo *hints; + struct addrinfo **res; +{ + struct addrinfo sentinel; + struct addrinfo *cur; + int error = 0; + struct addrinfo ai, ai0, *afai = NULL; + struct addrinfo *pai; + const struct explore *ex; + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + pai = &ai; + pai->ai_flags = 0; + pai->ai_family = PF_UNSPEC; + pai->ai_socktype = ANY; + pai->ai_protocol = ANY; +#ifndef ORIGINAL_ISC_CODE +#ifdef __sparcv9 + /* + * We need to clear _ai_pad to preserve binary + * compatibility with previously compiled 64-bit + * applications in a pre-SUSv3 environment by + * guaranteeing the upper 32-bits are empty. + */ + pai->_ai_pad = 0; +#endif /* __sparcv9 */ +#endif /* ORIGINAL_ISC_CODE */ + pai->ai_addrlen = 0; + pai->ai_canonname = NULL; + pai->ai_addr = NULL; + pai->ai_next = NULL; + + if (hostname == NULL && servname == NULL) + return EAI_NONAME; + if (hints) { + /* error check for hints */ + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) { + ERR(EAI_BADHINTS); /* xxx */ +#if !defined(ORIGINAL_ISC_CODE) + goto bad; +#endif + } +/* + * The AI_ macros defined by ISC are different than those defined by Solaris. + * AI_MASK is defined by ISC to check the range of their flags and doesn't work + * with Solaris. + */ +#ifdef ORIGINAL_ISC_CODE + if (hints->ai_flags & ~AI_MASK) { + ERR(EAI_BADFLAGS); + } +#endif + switch (hints->ai_family) { + case PF_UNSPEC: + case PF_INET: + case PF_INET6: + break; + default: + ERR(EAI_FAMILY); +#if !defined(ORIGINAL_ISC_CODE) + goto bad; +#endif + } + memcpy(pai, hints, sizeof(*pai)); + +#ifndef ORIGINAL_ISC_CODE +#ifdef __sparcv9 + /* + * We need to clear _ai_pad to preserve binary + * compatibility. See prior comment. + */ + pai->_ai_pad = 0; +#endif /* __sparcv9 */ +#endif /* ORIGINAL_ISC_CODE */ + /* + * if both socktype/protocol are specified, check if they + * are meaningful combination. + */ + if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { + for (ex = explore; ex->e_af >= 0; ex++) { + if (pai->ai_family != ex->e_af) + continue; + if (ex->e_socktype == ANY) + continue; + if (ex->e_protocol == ANY) + continue; + if (pai->ai_socktype == ex->e_socktype && + pai->ai_protocol != ex->e_protocol) { + ERR(EAI_BADHINTS); +#if !defined(ORIGINAL_ISC_CODE) + goto bad; +#endif + } + } + } + } + + /* + * post-2553: AI_ALL and AI_V4MAPPED are effective only against + * AF_INET6 query. They needs to be ignored if specified in other + * occassions. + */ + switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { + case AI_V4MAPPED: + case AI_ALL | AI_V4MAPPED: + if (pai->ai_family != AF_INET6) + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; + case AI_ALL: +#if 1 + /* illegal */ + ERR(EAI_BADFLAGS); +#if !defined(ORIGINAL_ISC_CODE) + goto bad; +#endif +#else + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; +#endif + } + + /* + * check for special cases. (1) numeric servname is disallowed if + * socktype/protocol are left unspecified. (2) servname is disallowed + * for raw and other inet{,6} sockets. + */ + if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) +#ifdef PF_INET6 + || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) +#endif + ) { + ai0 = *pai; /* backup *pai */ + + if (pai->ai_family == PF_UNSPEC) { +#ifdef PF_INET6 + pai->ai_family = PF_INET6; +#else + pai->ai_family = PF_INET; +#endif + } + error = get_portmatch(pai, servname); + if (error) { + ERR(error); +#if !defined(ORIGINAL_ISC_CODE) + goto bad; +#endif + } + + *pai = ai0; + } + + ai0 = *pai; + + /* NULL hostname, or numeric hostname */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) + continue; + if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) + continue; + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + if (pai->ai_socktype == ANY && ex->e_socktype != ANY) + pai->ai_socktype = ex->e_socktype; + if (pai->ai_protocol == ANY && ex->e_protocol != ANY) + pai->ai_protocol = ex->e_protocol; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if (hostname == NULL) { + /* + * filter out AFs that are not supported by the kernel + * XXX errno? + */ + if (!addrconfig(pai->ai_family)) + continue; + error = explore_null(pai, servname, &cur->ai_next); + } else + error = explore_numeric_scope(pai, hostname, servname, + &cur->ai_next); + + if (error) + goto free; + + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + /* + * XXX + * If numreic representation of AF1 can be interpreted as FQDN + * representation of AF2, we need to think again about the code below. + */ + if (sentinel.ai_next) + goto good; + + if (pai->ai_flags & AI_NUMERICHOST) { + ERR(EAI_NONAME); +#if !defined(ORIGINAL_ISC_CODE) + goto bad; +#endif + } + if (hostname == NULL) { + ERR(EAI_NONAME); +#if !defined(ORIGINAL_ISC_CODE) + goto bad; +#endif + } + + /* + * hostname as alphabetical name. + * We'll make sure that + * - if returning addrinfo list is empty, return non-zero error + * value (already known one or EAI_NONAME). + * - otherwise, + * + if we haven't had any errors, return 0 (i.e. success). + * + if we've had an error, free the list and return the error. + * without any assumption on the behavior of explore_fqdn(). + */ + + /* first, try to query DNS for all possible address families. */ + *pai = ai0; + error = explore_fqdn(pai, hostname, servname, &afai); + if (error) { + if (afai != NULL) + freeaddrinfo(afai); + goto free; + } + if (afai == NULL) { + error = EAI_NONAME; /* we've had no errors. */ + goto free; + } + + /* + * we would like to prefer AF_INET6 than AF_INET, so we'll make an + * outer loop by AFs. + */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, + WILD_SOCKTYPE(ex))) { + continue; + } + if (!MATCH(pai->ai_protocol, ex->e_protocol, + WILD_PROTOCOL(ex))) { + continue; + } + +#ifdef AI_ADDRCONFIG + /* + * If AI_ADDRCONFIG is specified, check if we are + * expected to return the address family or not. + */ + if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && + !addrconfig(pai->ai_family)) + continue; +#endif + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + if (pai->ai_socktype == ANY && ex->e_socktype != ANY) + pai->ai_socktype = ex->e_socktype; + if (pai->ai_protocol == ANY && ex->e_protocol != ANY) + pai->ai_protocol = ex->e_protocol; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) { + freeaddrinfo(afai); + goto free; + } + + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + freeaddrinfo(afai); /* afai must not be NULL at this point. */ + + /* we must not have got any errors. */ + if (error != 0) /* just for diagnosis */ + abort(); + + if (sentinel.ai_next) { +good: + *res = sentinel.ai_next; + return(SUCCESS); + } else { + /* + * All the process succeeded, but we've had an empty list. + * This can happen if the given hints do not match our + * candidates. + */ + error = EAI_NONAME; + } + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + *res = NULL; + return(error); +} + +/* + * FQDN hostname, DNS lookup + */ +static int +explore_fqdn(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ + struct addrinfo *result; + struct addrinfo *cur; + struct net_data *net_data = init(); + struct irs_ho *ho; + int error = 0; + char tmp[NS_MAXDNAME]; + const char *cp; + + INSIST(res != NULL && *res == NULL); + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return(0); + + if (!net_data || !(ho = net_data->ho)) + return(0); +#if 0 /* XXX (notyet) */ + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); + } +#endif + if (!strchr(hostname, '.') && + (cp = res_hostalias(net_data->res, hostname, + tmp, sizeof(tmp)))) + hostname = cp; + result = (*ho->addrinfo)(ho, hostname, pai); + if (!net_data->ho_stayopen) { + (*ho->minimize)(ho); + } + if (result == NULL) { + int e = h_errno; + + switch(e) { + case NETDB_INTERNAL: + error = EAI_SYSTEM; + break; + case TRY_AGAIN: + error = EAI_AGAIN; + break; + case NO_RECOVERY: + error = EAI_FAIL; + break; + case HOST_NOT_FOUND: + case NO_DATA: + error = EAI_NONAME; + break; + default: + case NETDB_SUCCESS: /* should be impossible... */ + error = EAI_NONAME; + break; + } + goto free; + } + + for (cur = result; cur; cur = cur->ai_next) { + GET_PORT(cur, servname); /* XXX: redundant lookups... */ + /* canonname should already be filled. */ + } + + *res = result; + + return(0); + +free: + if (result) + freeaddrinfo(result); + return error; +} + +static int +explore_copy(pai, src0, res) + const struct addrinfo *pai; /* seed */ + const struct addrinfo *src0; /* source */ + struct addrinfo **res; +{ + int error; + struct addrinfo sentinel, *cur; + const struct addrinfo *src; + + error = 0; + sentinel.ai_next = NULL; + cur = &sentinel; + + for (src = src0; src != NULL; src = src->ai_next) { + if (src->ai_family != pai->ai_family) + continue; + + cur->ai_next = copy_ai(src); + if (!cur->ai_next) { + error = EAI_MEMORY; + goto fail; + } + + cur->ai_next->ai_socktype = pai->ai_socktype; + cur->ai_next->ai_protocol = pai->ai_protocol; + cur = cur->ai_next; + } + + *res = sentinel.ai_next; + return 0; + +fail: + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * hostname == NULL. + * passive socket -> anyaddr (0.0.0.0 or ::) + * non-passive socket -> localhost (127.0.0.1 or ::1) + */ +static int +explore_null(pai, servname, res) + const struct addrinfo *pai; + const char *servname; + struct addrinfo **res; +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (pai->ai_flags & AI_PASSIVE) { + GET_AI(cur->ai_next, afd, afd->a_addrany); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "anyaddr"); + */ + GET_PORT(cur->ai_next, servname); + } else { + GET_AI(cur->ai_next, afd, afd->a_loopback); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "localhost"); + */ + GET_PORT(cur->ai_next, servname); + } + cur = cur->ai_next; + + *res = sentinel.ai_next; + return 0; + +free: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname + */ +static int +explore_numeric(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + char pton[PTON_MAX]; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + switch (afd->a_af) { +#if 0 /*X/Open spec*/ + case AF_INET: + if (inet_aton(hostname, (struct in_addr *)pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + while (cur && cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + break; +#endif + default: + if (inet_pton(afd->a_af, hostname, pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + while (cur && cur->ai_next) + cur = cur->ai_next; + } else { + ERR(EAI_FAMILY); /*xxx*/ +#if !defined(ORIGINAL_ISC_CODE) + goto bad; +#endif + } + } + break; + } + + *res = sentinel.ai_next; + return 0; + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname with scope + */ +static int +explore_numeric_scope(pai, hostname, servname, res) + const struct addrinfo *pai; + const char *hostname; + const char *servname; + struct addrinfo **res; +{ +#ifndef SCOPE_DELIMITER + return explore_numeric(pai, hostname, servname, res); +#else + const struct afd *afd; + struct addrinfo *cur; + int error; + char *cp, *hostname2 = NULL, *scope, *addr; + struct sockaddr_in6 *sin6; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (!afd->a_scoped) + return explore_numeric(pai, hostname, servname, res); + + cp = strchr(hostname, SCOPE_DELIMITER); + if (cp == NULL) + return explore_numeric(pai, hostname, servname, res); + + /* + * Handle special case of <scoped_address><delimiter><scope id> + */ + hostname2 = strdup(hostname); + if (hostname2 == NULL) + return EAI_MEMORY; + /* terminate at the delimiter */ + hostname2[cp - hostname] = '\0'; + addr = hostname2; + scope = cp + 1; + + error = explore_numeric(pai, addr, servname, res); + if (error == 0) { + u_int32_t scopeid = 0; + + for (cur = *res; cur; cur = cur->ai_next) { + if (cur->ai_family != AF_INET6) + continue; + sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; + if (!ip6_str2scopeid(scope, sin6, &scopeid)) { + free(hostname2); + return(EAI_NONAME); /* XXX: is return OK? */ + } +#ifdef HAVE_SIN6_SCOPE_ID + sin6->sin6_scope_id = scopeid; +#endif + } + } + + free(hostname2); + + return error; +#endif +} + +static int +get_canonname(pai, ai, str) + const struct addrinfo *pai; + struct addrinfo *ai; + const char *str; +{ + if ((pai->ai_flags & AI_CANONNAME) != 0) { + ai->ai_canonname = (char *)malloc(strlen(str) + 1); + if (ai->ai_canonname == NULL) + return EAI_MEMORY; + strcpy(ai->ai_canonname, str); + } + return 0; +} + +static struct addrinfo * +get_ai(pai, afd, addr) + const struct addrinfo *pai; + const struct afd *afd; + const char *addr; +{ + char *p; + struct addrinfo *ai; + + ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + + (afd->a_socklen)); + if (ai == NULL) + return NULL; + + memcpy(ai, pai, sizeof(struct addrinfo)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memset(ai->ai_addr, 0, (size_t)afd->a_socklen); +#ifdef HAVE_SA_LEN + ai->ai_addr->sa_len = afd->a_socklen; +#endif + ai->ai_addrlen = afd->a_socklen; + ai->ai_addr->sa_family = ai->ai_family = afd->a_af; + p = (char *)(void *)(ai->ai_addr); + memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); + return ai; +} + +/* XXX need to malloc() the same way we do from other functions! */ +static struct addrinfo * +copy_ai(pai) + const struct addrinfo *pai; +{ + struct addrinfo *ai; + size_t l; + + l = sizeof(*ai) + pai->ai_addrlen; + if ((ai = (struct addrinfo *)malloc(l)) == NULL) + return NULL; + memset(ai, 0, l); + memcpy(ai, pai, sizeof(*ai)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen); + + if (pai->ai_canonname) { + l = strlen(pai->ai_canonname) + 1; + if ((ai->ai_canonname = malloc(l)) == NULL) { + free(ai); + return NULL; + } +#ifdef HAVE_STRLCPY + strlcpy(ai->ai_canonname, pai->ai_canonname, l); +#else + strncpy(ai->ai_canonname, pai->ai_canonname, l); +#endif + } else { + /* just to make sure */ + ai->ai_canonname = NULL; + } + + ai->ai_next = NULL; + + return ai; +} + +static int +get_portmatch(const struct addrinfo *ai, const char *servname) { + + /* get_port does not touch first argument. when matchonly == 1. */ + /* LINTED const cast */ + return get_port((const struct addrinfo *)ai, servname, 1); +} + +static int +get_port(const struct addrinfo *ai, const char *servname, int matchonly) { + const char *proto; + struct servent *sp; + int port; + int allownumeric; + + if (servname == NULL) + return 0; + switch (ai->ai_family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif + break; + default: + return 0; + } + + switch (ai->ai_socktype) { + case SOCK_RAW: + return EAI_SERVICE; + case SOCK_DGRAM: + case SOCK_STREAM: + allownumeric = 1; + break; + case ANY: + switch (ai->ai_family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif + allownumeric = 1; + break; + default: + allownumeric = 0; + break; + } + break; + default: + return EAI_SOCKTYPE; + } + + if (str_isnumber(servname)) { + if (!allownumeric) + return EAI_SERVICE; + port = atoi(servname); + if (port < 0 || port > 65535) + return EAI_SERVICE; + port = htons(port); + } else { + switch (ai->ai_socktype) { + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_STREAM: + proto = "tcp"; + break; + default: + proto = NULL; + break; + } + + if ((sp = getservbyname(servname, proto)) == NULL) + return EAI_SERVICE; + port = sp->s_port; + } + + if (!matchonly) { + switch (ai->ai_family) { + case AF_INET: + ((struct sockaddr_in *)(void *) + ai->ai_addr)->sin_port = port; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(void *) + ai->ai_addr)->sin6_port = port; + break; + } + } + + return 0; +} + +static const struct afd * +find_afd(af) + int af; +{ + const struct afd *afd; + + if (af == PF_UNSPEC) + return NULL; + for (afd = afdl; afd->a_af; afd++) { + if (afd->a_af == af) + return afd; + } + return NULL; +} + +/* + * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend + * will take care of it. + * the semantics of AI_ADDRCONFIG is not defined well. we are not sure + * if the code is right or not. + */ +static int +addrconfig(af) + int af; +{ + int s; + + /* XXX errno */ + s = socket(af, SOCK_DGRAM, 0); + if (s < 0) { + if (errno != EMFILE) + return 0; + } else + close(s); + return 1; +} + +/* convert a string to a scope identifier. XXX: IPv6 specific */ +static int +ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, + u_int32_t *scopeidp) +{ + u_int32_t scopeid; + u_long lscopeid; + struct in6_addr *a6 = &sin6->sin6_addr; + char *ep; + + /* empty scopeid portion is invalid */ + if (*scope == '\0') + return (0); + +#ifdef USE_IFNAMELINKID + if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { + /* + * Using interface names as link indices can be allowed + * only when we can assume a one-to-one mappings between + * links and interfaces. See comments in getnameinfo.c. + */ + scopeid = if_nametoindex(scope); + if (scopeid == 0) + goto trynumeric; + *scopeidp = scopeid; + return (1); + } +#endif + + /* still unclear about literal, allow numeric only - placeholder */ + if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) + goto trynumeric; + if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) + goto trynumeric; + else + goto trynumeric; /* global */ + + /* try to convert to a numeric id as a last resort */ +trynumeric: + errno = 0; + lscopeid = strtoul(scope, &ep, 10); + scopeid = lscopeid & 0xffffffff; + if (errno == 0 && ep && *ep == '\0' && scopeid == lscopeid) { + *scopeidp = scopeid; + return (1); + } else + return (0); +} + +struct addrinfo * +hostent2addrinfo(hp, pai) + struct hostent *hp; + const struct addrinfo *pai; +{ + int i, af, error = 0; + char **aplist = NULL, *ap; + struct addrinfo sentinel, *cur; + const struct afd *afd; + + af = hp->h_addrtype; + if (pai->ai_family != AF_UNSPEC && af != pai->ai_family) + return(NULL); + + afd = find_afd(af); + if (afd == NULL) + return(NULL); + + aplist = hp->h_addr_list; + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + for (i = 0; (ap = aplist[i]) != NULL; i++) { +#if 0 /* the trick seems too much */ + af = hp->h_addr_list; + if (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { + af = AF_INET; + ap = ap + sizeof(struct in6_addr) + - sizeof(struct in_addr); + } + afd = find_afd(af); + if (afd == NULL) + continue; +#endif /* 0 */ + + GET_AI(cur->ai_next, afd, ap); + + /* GET_PORT(cur->ai_next, servname); */ + if ((pai->ai_flags & AI_CANONNAME) != 0) { + /* + * RFC2553 says that ai_canonname will be set only for + * the first element. we do it for all the elements, + * just for convenience. + */ + GET_CANONNAME(cur->ai_next, hp->h_name); + } + while (cur && cur->ai_next) /* no need to loop, actually. */ + cur = cur->ai_next; + continue; + + free: + if (cur->ai_next) + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + /* continue, without tht pointer CUR advanced. */ + } + + return(sentinel.ai_next); +} + +struct addrinfo * +addr2addrinfo(pai, cp) + const struct addrinfo *pai; + const char *cp; +{ + const struct afd *afd; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return(NULL); + + return(get_ai(pai, afd, cp)); +} + +static struct net_data * +init() +{ + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { +error: + errno = EIO; + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); + } + + return (net_data); +} diff --git a/usr/src/lib/libresolv2/common/irs/getgrent.c b/usr/src/lib/libresolv2/common/irs/getgrent.c new file mode 100644 index 0000000000..5ac15a1c87 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getgrent.c @@ -0,0 +1,230 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getgrent.c,v 1.20 2001/05/29 05:48:41 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_GR) || defined(__BIND_NOSTATIC) +static int __bind_irs_gr_unneeded; +#else + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <grp.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); +void endgrent(void); + +/* Public */ + +struct group * +getgrent() { + struct net_data *net_data = init(); + + return (getgrent_p(net_data)); +} + +struct group * +getgrnam(const char *name) { + struct net_data *net_data = init(); + + return (getgrnam_p(name, net_data)); +} + +struct group * +getgrgid(gid_t gid) { + struct net_data *net_data = init(); + + return (getgrgid_p(gid, net_data)); +} + +int +setgroupent(int stayopen) { + struct net_data *net_data = init(); + + return (setgroupent_p(stayopen, net_data)); +} + +#ifdef SETGRENT_VOID +void +setgrent(void) { + struct net_data *net_data = init(); + + setgrent_p(net_data); +} +#else +int +setgrent(void) { + struct net_data *net_data = init(); + + return (setgrent_p(net_data)); +} +#endif /* SETGRENT_VOID */ + +void +endgrent() { + struct net_data *net_data = init(); + + endgrent_p(net_data); +} + +int +getgrouplist(GETGROUPLIST_ARGS) { + struct net_data *net_data = init(); + + return (getgrouplist_p(name, basegid, groups, ngroups, net_data)); +} + +/* Shared private. */ + +struct group * +getgrent_p(struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + net_data->gr_last = (*gr->next)(gr); + return (net_data->gr_last); +} + +struct group * +getgrnam_p(const char *name, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + if (net_data->gr_stayopen && net_data->gr_last && + !strcmp(net_data->gr_last->gr_name, name)) + return (net_data->gr_last); + net_data->gr_last = (*gr->byname)(gr, name); + if (!net_data->gr_stayopen) + endgrent(); + return (net_data->gr_last); +} + +struct group * +getgrgid_p(gid_t gid, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (NULL); + if (net_data->gr_stayopen && net_data->gr_last && + (gid_t)net_data->gr_last->gr_gid == gid) + return (net_data->gr_last); + net_data->gr_last = (*gr->bygid)(gr, gid); + if (!net_data->gr_stayopen) + endgrent(); + return (net_data->gr_last); +} + +int +setgroupent_p(int stayopen, struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) + return (0); + (*gr->rewind)(gr); + net_data->gr_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); + return (1); +} + +#ifdef SETGRENT_VOID +void +setgrent_p(struct net_data *net_data) { + (void)setgroupent_p(0, net_data); +} +#else +int +setgrent_p(struct net_data *net_data) { + return (setgroupent_p(0, net_data)); +} +#endif /* SETGRENT_VOID */ + +void +endgrent_p(struct net_data *net_data) { + struct irs_gr *gr; + + if ((net_data != NULL) && ((gr = net_data->gr) != NULL)) + (*gr->minimize)(gr); +} + +int +getgrouplist_p(const char *name, gid_t basegid, gid_t *groups, int *ngroups, + struct net_data *net_data) { + struct irs_gr *gr; + + if (!net_data || !(gr = net_data->gr)) { + *ngroups = 0; + return (-1); + } + return ((*gr->list)(gr, name, basegid, groups, ngroups)); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->gr) { + net_data->gr = (*net_data->irs->gr_map)(net_data->irs); + + if (!net_data->gr || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->gr->res_set)(net_data->gr, net_data->res, + NULL); + } + + return (net_data); +} + +#endif /* WANT_IRS_GR */ diff --git a/usr/src/lib/libresolv2/common/irs/getgrent_r.c b/usr/src/lib/libresolv2/common/irs/getgrent_r.c new file mode 100644 index 0000000000..01c0a936ed --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getgrent_r.c @@ -0,0 +1,237 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = + "$Id: getgrent_r.c,v 8.7 2001/11/01 08:02:08 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW) + static int getgrent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#if (defined(POSIX_GETGRNAM_R) || defined(POSIX_GETGRGID_R)) && \ + defined(_POSIX_PTHREAD_SEMANTICS) + /* turn off solaris remapping in <grp.h> */ +#define _UNIX95 +#undef _POSIX_PTHREAD_SEMANTICS +#include <grp.h> +#define _POSIX_PTHREAD_SEMANTICS 1 +#else +#include <grp.h> +#endif +#include <sys/param.h> +#include <port_after.h> + +#ifdef GROUP_R_RETURN + +static int +copy_group(struct group *, struct group *, char *buf, int buflen); + +/* POSIX 1003.1c */ +#ifdef POSIX_GETGRNAM_R +int +__posix_getgrnam_r(const char *name, struct group *gptr, + char *buf, size_t buflen, struct group **result) { +#else +int +getgrnam_r(const char *name, struct group *gptr, + char *buf, size_t buflen, struct group **result) { +#endif + struct group *ge = getgrnam(name); + int res; + + if (ge == NULL) { + *result = NULL; + return (0); + } + + res = copy_group(ge, gptr, buf, buflen); + *result = res ? NULL : gptr; + return (res); +} + +#ifdef POSIX_GETGRNAM_R +struct group * +getgrnam_r(const char *name, struct group *gptr, + char *buf, int buflen) { + struct group *ge = getgrnam(name); + int res; + + if (ge == NULL) + return (NULL); + res = copy_group(ge, gptr, buf, buflen); + return (res ? NULL : gptr); +} +#endif /* POSIX_GETGRNAM_R */ + +/* POSIX 1003.1c */ +#ifdef POSIX_GETGRGID_R +int +__posix_getgrgid_r(gid_t gid, struct group *gptr, + char *buf, size_t buflen, struct group **result) { +#else /* POSIX_GETGRGID_R */ +int +getgrgid_r(gid_t gid, struct group *gptr, + char *buf, size_t buflen, struct group **result) { +#endif /* POSIX_GETGRGID_R */ + struct group *ge = getgrgid(gid); + int res; + + if (ge == NULL) { + *result = NULL; + return (0); + } + + res = copy_group(ge, gptr, buf, buflen); + *result = res ? NULL : gptr; + return (res); +} + +#ifdef POSIX_GETGRGID_R +struct group * +getgrgid_r(gid_t gid, struct group *gptr, + char *buf, int buflen) { + struct group *ge = getgrgid(gid); + int res; + + if (ge == NULL) + return (NULL); + + res = copy_group(ge, gptr, buf, buflen); + return (res ? NULL : gptr); +} +#endif + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +GROUP_R_RETURN +getgrent_r(struct group *gptr, GROUP_R_ARGS) { + struct group *ge = getgrent(); + int res; + + if (ge == NULL) { + return (GROUP_R_BAD); + } + + res = copy_group(ge, gptr, buf, buflen); + return (res ? GROUP_R_BAD : GROUP_R_OK); +} + +GROUP_R_SET_RETURN +setgrent_r(GROUP_R_ENT_ARGS) { + + setgrent(); +#ifdef GROUP_R_SET_RESULT + return (GROUP_R_SET_RESULT); +#endif +} + +GROUP_R_END_RETURN +endgrent_r(GROUP_R_ENT_ARGS) { + + endgrent(); + GROUP_R_END_RESULT(GROUP_R_OK); +} + + +#if 0 + /* XXX irs does not have a fgetgrent() */ +GROUP_R_RETURN +fgetgrent_r(FILE *f, struct group *gptr, GROUP_R_ARGS) { + struct group *ge = fgetgrent(f); + int res; + + if (ge == NULL) + return (GROUP_R_BAD); + + res = copy_group(ge, gptr, buf, buflen); + return (res ? GROUP_R_BAD : GROUP_R_OK); +} +#endif + +/* Private */ + +static int +copy_group(struct group *ge, struct group *gptr, char *buf, int buflen) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; ge->gr_mem[i]; i++, numptr++) { + len += strlen(ge->gr_mem[i]) + 1; + } + len += strlen(ge->gr_name) + 1; + len += strlen(ge->gr_passwd) + 1; + len += numptr * sizeof (char *); + + if (len > buflen) { + errno = ERANGE; + return (ERANGE); + } + + /* copy group id */ + gptr->gr_gid = ge->gr_gid; + + cp = (char *)ALIGN(buf) + numptr * sizeof (char *); + + /* copy official name */ + n = strlen(ge->gr_name) + 1; + strcpy(cp, ge->gr_name); + gptr->gr_name = cp; + cp += n; + + /* copy member list */ + gptr->gr_mem = (char **)ALIGN(buf); + for (i = 0; ge->gr_mem[i]; i++) { + n = strlen(ge->gr_mem[i]) + 1; + strcpy(cp, ge->gr_mem[i]); + gptr->gr_mem[i] = cp; + cp += n; + } + gptr->gr_mem[i] = NULL; + + /* copy password */ + n = strlen(ge->gr_passwd) + 1; + strcpy(cp, ge->gr_passwd); + gptr->gr_passwd = cp; + cp += n; + + return (0); +} +#else /* GROUP_R_RETURN */ + static int getgrent_r_unknown_system = 0; +#endif /* GROUP_R_RETURN */ +#endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */ diff --git a/usr/src/lib/libresolv2/common/irs/gethostent.c b/usr/src/lib/libresolv2/common/irs/gethostent.c new file mode 100644 index 0000000000..db88d06b20 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gethostent.c @@ -0,0 +1,1091 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gethostent.c,v 1.34 2003/05/29 00:05:18 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <net/if.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + char * aliases[1]; + char * addrs[2]; + char addr[NS_IN6ADDRSZ]; + char name[NS_MAXDNAME + 1]; + struct hostent host; +}; + +/* Forward */ + +static struct net_data *init(void); +static void freepvt(struct net_data *); +static struct hostent *fakeaddr(const char *, int, struct net_data *); + +#ifdef SUNW_OVERRIDE_RETRY +extern int __res_retry(int); +extern int __res_retry_reset(void); +#endif /* SUNW_OVERRIDE_RETRY */ + +/* Public */ + +struct hostent * +gethostbyname(const char *name) { + struct net_data *net_data = init(); + + return (gethostbyname_p(name, net_data)); +} + +struct hostent * +gethostbyname2(const char *name, int af) { + struct net_data *net_data = init(); + + return (gethostbyname2_p(name, af, net_data)); +} + +struct hostent * +#ifdef ORIGINAL_ISC_CODE +gethostbyaddr(const char *addr, int len, int af) { +#else +gethostbyaddr(const void *addr, socklen_t len, int af) { +#endif /* ORIGINAL_ISC_CODE */ + struct net_data *net_data = init(); + + return (gethostbyaddr_p(addr, len, af, net_data)); +} + +struct hostent * +gethostent() { + struct net_data *net_data = init(); + + return (gethostent_p(net_data)); +} + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +sethostent(int stayopen) { + struct net_data *net_data = init(); + sethostent_p(stayopen, net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +endhostent() { + struct net_data *net_data = init(); + endhostent_p(net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + +/* Shared private. */ + +struct hostent * +gethostbyname_p(const char *name, struct net_data *net_data) { + struct hostent *hp; + + if (!net_data) +#ifdef SUNW_SETHERRNO + { + /* + * Should set the context h_errno, but since net_data + * is NULL, we don't have a context. + */ + h_errno = NETDB_INTERNAL; + return (NULL); + } +#else + return (NULL); +#endif /* SUNW_SETHERRNO */ + + if (net_data->res->options & RES_USE_INET6) { + hp = gethostbyname2_p(name, AF_INET6, net_data); + if (hp) + return (hp); + } + return (gethostbyname2_p(name, AF_INET, net_data)); +} + +struct hostent * +gethostbyname2_p(const char *name, int af, struct net_data *net_data) { + struct irs_ho *ho; + char tmp[NS_MAXDNAME]; + struct hostent *hp; + const char *cp; + char **hap; + + if (!net_data || !(ho = net_data->ho)) +#ifdef SUNW_SETHERRNO + { + h_errno = NETDB_INTERNAL; + return (NULL); + } +#else + return (NULL); +#endif /* SUNW_SETHERRNO */ + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); + } + if (!strchr(name, '.') && (cp = res_hostalias(net_data->res, name, + tmp, sizeof tmp))) + name = cp; + if ((hp = fakeaddr(name, af, net_data)) != NULL) + return (hp); +#ifdef SUNW_OVERRIDE_RETRY + net_data->res->retry = __res_retry(net_data->res->retry); +#endif /* SUNW_OVERRIDE_RETRY */ + net_data->ho_last = (*ho->byname2)(ho, name, af); +#ifdef SUNW_OVERRIDE_RETRY + net_data->res->retry = __res_retry_reset(); +#endif /* SUNW_OVERRIDE_RETRY */ + if (!net_data->ho_stayopen) + endhostent(); + return (net_data->ho_last); +} + +struct hostent * +gethostbyaddr_p(const char *addr, int len, int af, struct net_data *net_data) { + struct irs_ho *ho; + char **hap; + + if (!net_data || !(ho = net_data->ho)) +#ifdef SUNW_SETHERRNO + { + h_errno = NETDB_INTERNAL; + return (NULL); + } +#else + return (NULL); +#endif /* SUNW_SETHERRNO */ + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_length == len) + for (hap = net_data->ho_last->h_addr_list; + hap && *hap; + hap++) + if (!memcmp(addr, *hap, len)) + return (net_data->ho_last); + net_data->ho_last = (*ho->byaddr)(ho, addr, len, af); + if (!net_data->ho_stayopen) + endhostent(); + return (net_data->ho_last); +} + + +struct hostent * +gethostent_p(struct net_data *net_data) { + struct irs_ho *ho; + struct hostent *hp; + + if (!net_data || !(ho = net_data->ho)) +#ifdef SUNW_SETHERRNO + { + h_errno = NETDB_INTERNAL; + return (NULL); + } +#else + return (NULL); +#endif /* SUNW_SETHERRNO */ + while ((hp = (*ho->next)(ho)) != NULL && + hp->h_addrtype == AF_INET6 && + (net_data->res->options & RES_USE_INET6) == 0) + continue; + net_data->ho_last = hp; + return (net_data->ho_last); +} + + +void +sethostent_p(int stayopen, struct net_data *net_data) { + struct irs_ho *ho; + + if (!net_data || !(ho = net_data->ho)) + return; + freepvt(net_data); + (*ho->rewind)(ho); + net_data->ho_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endhostent_p(struct net_data *net_data) { + struct irs_ho *ho; + + if ((net_data != NULL) && ((ho = net_data->ho) != NULL)) + (*ho->minimize)(ho); +} + +#ifndef IN6_IS_ADDR_V4COMPAT +static const unsigned char in6addr_compat[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \ + ((x)->s6_addr[12] != 0 || \ + (x)->s6_addr[13] != 0 || \ + (x)->s6_addr[14] != 0 || \ + ((x)->s6_addr[15] != 0 && \ + (x)->s6_addr[15] != 1))) +#endif +#ifndef IN6_IS_ADDR_V4MAPPED +#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12)) +#endif + +static const unsigned char in6addr_mapped[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; + +static int scan_interfaces(int *, int *); +static struct hostent *copyandmerge(struct hostent *, struct hostent *, int, int *); + +/* + * Public functions + */ + +/* + * AI_V4MAPPED + AF_INET6 + * If no IPv6 address then a query for IPv4 and map returned values. + * + * AI_ALL + AI_V4MAPPED + AF_INET6 + * Return IPv6 and IPv4 mapped. + * + * AI_ADDRCONFIG + * Only return IPv6 / IPv4 address if there is an interface of that + * type active. + */ + +struct hostent * +getipnodebyname(const char *name, int af, int flags, int *error_num) { + int have_v4 = 1, have_v6 = 1; + struct in_addr in4; + struct in6_addr in6; + struct hostent he, *he1 = NULL, *he2 = NULL, *he3; + int v4 = 0, v6 = 0; + struct net_data *net_data = init(); + u_long options; + int tmp_err; + + if (net_data == NULL) { + *error_num = NO_RECOVERY; + return (NULL); + } + + /* If we care about active interfaces then check. */ + if ((flags & AI_ADDRCONFIG) != 0) + if (scan_interfaces(&have_v4, &have_v6) == -1) { + *error_num = NO_RECOVERY; + return (NULL); + } + + /* Check for literal address. */ + if ((v4 = inet_pton(AF_INET, name, &in4)) != 1) + v6 = inet_pton(AF_INET6, name, &in6); + + /* Impossible combination? */ + + if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) || + (af == AF_INET && v6 == 1) || + (have_v4 == 0 && v4 == 1) || + (have_v6 == 0 && v6 == 1) || + (have_v4 == 0 && af == AF_INET) || + (have_v6 == 0 && af == AF_INET6)) { + *error_num = HOST_NOT_FOUND; + return (NULL); + } + + /* Literal address? */ + if (v4 == 1 || v6 == 1) { + char *addr_list[2]; + char *aliases[1]; + + DE_CONST(name, he.h_name); + he.h_addr_list = addr_list; + he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6; + he.h_addr_list[1] = NULL; + he.h_aliases = aliases; + he.h_aliases[0] = NULL; + he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ; + he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6; + return (copyandmerge(&he, NULL, af, error_num)); + } + + options = net_data->res->options; + net_data->res->options &= ~RES_USE_INET6; + + tmp_err = NO_RECOVERY; + if (have_v6 && af == AF_INET6) { + he2 = gethostbyname2_p(name, AF_INET6, net_data); + if (he2 != NULL) { + he1 = copyandmerge(he2, NULL, af, error_num); + if (he1 == NULL) + return (NULL); + he2 = NULL; + } else { + tmp_err = net_data->res->res_h_errno; + } + } + + if (have_v4 && + ((af == AF_INET) || + (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 && + (he1 == NULL || (flags & AI_ALL) != 0)))) { + he2 = gethostbyname2_p(name, AF_INET, net_data); + if (he1 == NULL && he2 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + } else + *error_num = tmp_err; + + net_data->res->options = options; + + he3 = copyandmerge(he1, he2, af, error_num); + + if (he1 != NULL) + freehostent(he1); + return (he3); +} + +struct hostent * +getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { + struct hostent *he1, *he2; + struct net_data *net_data = init(); + + /* Sanity Checks. */ + if (src == NULL) { + *error_num = NO_RECOVERY; + return (NULL); + } + + switch (af) { + case AF_INET: + if (len != INADDRSZ) { + *error_num = NO_RECOVERY; + return (NULL); + } + break; + case AF_INET6: + if (len != IN6ADDRSZ) { + *error_num = NO_RECOVERY; + return (NULL); + } + break; + default: + *error_num = NO_RECOVERY; + return (NULL); + } + + /* + * Lookup IPv4 and IPv4 mapped/compatible addresses + */ + if ((af == AF_INET6 && + IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) || + (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) || + (af == AF_INET)) { + const char *cp = src; + + if (af == AF_INET6) + cp += 12; + he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data); + if (he1 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + he2 = copyandmerge(he1, NULL, af, error_num); + if (he2 == NULL) + return (NULL); + /* + * Restore original address if mapped/compatible. + */ + if (af == AF_INET6) + memcpy(he1->h_addr, src, len); + return (he2); + } + + /* + * Lookup IPv6 address. + */ + if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) { + *error_num = HOST_NOT_FOUND; + return (NULL); + } + + he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data); + if (he1 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + return (copyandmerge(he1, NULL, af, error_num)); +} + +void +freehostent(struct hostent *he) { + char **cpp; + int names = 1; + int addresses = 1; + + memput(he->h_name, strlen(he->h_name) + 1); + + cpp = he->h_addr_list; + while (*cpp != NULL) { + memput(*cpp, (he->h_addrtype == AF_INET) ? + INADDRSZ : IN6ADDRSZ); + *cpp = NULL; + cpp++; + addresses++; + } + + cpp = he->h_aliases; + while (*cpp != NULL) { + memput(*cpp, strlen(*cpp) + 1); + cpp++; + names++; + } + + memput(he->h_aliases, sizeof(char *) * (names)); + memput(he->h_addr_list, sizeof(char *) * (addresses)); + memput(he, sizeof *he); +} + +/* + * Private + */ + +/* + * Scan the interface table and set have_v4 and have_v6 depending + * upon whether there are IPv4 and IPv6 interface addresses. + * + * Returns: + * 0 on success + * -1 on failure. + */ + +#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \ + !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF) + +#define SETFAMILYFLAGS +#define LIFCONF lifconf +#define LIFREQ lifreq + +static void +scan_interfaces6(int *have_v4, int *have_v6) { + struct LIFCONF lifc; + struct LIFREQ lifreq; + struct in_addr in4; + struct in6_addr in6; + char *buf = NULL, *cp, *cplim; + static unsigned int bufsiz = 4095; + int s, cpsize, n; + + /* Get interface list from system. */ + if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) + goto cleanup; + + /* + * Grow buffer until large enough to contain all interface + * descriptions. + */ + for (;;) { + buf = memget(bufsiz); + if (buf == NULL) + goto cleanup; +#ifdef SETFAMILYFLAGS + lifc.lifc_family = AF_UNSPEC; /* request all families */ + lifc.lifc_flags = 0; +#endif + lifc.lifc_len = bufsiz; + lifc.lifc_buf = buf; + if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) { + /* + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * lifc.lifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz) + break; + } + if ((n == -1) && errno != EINVAL) + goto cleanup; + + if (bufsiz > 1000000) + goto cleanup; + + memput(buf, bufsiz); + bufsiz += 4096; + } + + /* Parse system's interface list. */ + cplim = buf + lifc.lifc_len; /* skip over if's with big ifr_addr's */ + for (cp = buf; + (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; + cp += cpsize) { + memcpy(&lifreq, cp, sizeof lifreq); +#ifdef HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (lifreq.lifr_addr.sa_len == 0) + lifreq.lifr_addr.sa_len = 16; +#endif +#ifdef HAVE_MINIMUM_IFREQ + cpsize = sizeof lifreq; + if (lifreq.lifr_addr.sa_len > sizeof (struct sockaddr)) + cpsize += (int)lifreq.lifr_addr.sa_len - + (int)(sizeof (struct sockaddr)); +#else + cpsize = sizeof lifreq.lifr_name + lifreq.lifr_addr.sa_len; +#endif /* HAVE_MINIMUM_IFREQ */ +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof lifreq; +#else + cpsize = sizeof lifreq.lifr_name; + /* XXX maybe this should be a hard error? */ + if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0) + continue; +#endif + switch (lifreq.lifr_addr.ss_family) { + case AF_INET: + if (*have_v4 == 0) { + memcpy(&in4, + &((struct sockaddr_in *) + &lifreq.lifr_addr)->sin_addr, + sizeof in4); + if (in4.s_addr == INADDR_ANY) + break; + n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); + if (n < 0) + break; + if ((lifreq.lifr_flags & IFF_UP) == 0) + break; + *have_v4 = 1; + } + break; + case AF_INET6: + if (*have_v6 == 0) { + memcpy(&in6, + &((struct sockaddr_in6 *) + &lifreq.lifr_addr)->sin6_addr, sizeof in6); + if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) + break; + n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); + if (n < 0) + break; + if ((lifreq.lifr_flags & IFF_UP) == 0) + break; + *have_v6 = 1; + } + break; + } + } + if (buf != NULL) + memput(buf, bufsiz); + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return; + cleanup: + if (buf != NULL) + memput(buf, bufsiz); + if (s != -1) + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return; +} +#endif + +static int +scan_interfaces(int *have_v4, int *have_v6) { + struct ifconf ifc; + union { + char _pad[256]; /* leave space for IPv6 addresses */ + struct ifreq ifreq; + } u; + struct in_addr in4; + struct in6_addr in6; + char *buf = NULL, *cp, *cplim; + static unsigned int bufsiz = 4095; + int s, n; + size_t cpsize; + + /* Set to zero. Used as loop terminators below. */ + *have_v4 = *have_v6 = 0; + +#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \ + !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF) + /* + * Try to scan the interfaces using IPv6 ioctls(). + */ + scan_interfaces6(have_v4, have_v6); + if (*have_v4 != 0 && *have_v6 != 0) + return (0); +#endif + + /* Get interface list from system. */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + goto err_ret; + + /* + * Grow buffer until large enough to contain all interface + * descriptions. + */ + for (;;) { + buf = memget(bufsiz); + if (buf == NULL) + goto err_ret; + ifc.ifc_len = bufsiz; + ifc.ifc_buf = buf; +#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF + /* + * This is a fix for IRIX OS in which the call to ioctl with + * the flag SIOCGIFCONF may not return an entry for all the + * interfaces like most flavors of Unix. + */ + if (emul_ioctl(&ifc) >= 0) + break; +#else + if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) { + /* + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * ifc.ifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz) + break; + } +#endif + if ((n == -1) && errno != EINVAL) + goto err_ret; + + if (bufsiz > 1000000) + goto err_ret; + + memput(buf, bufsiz); + bufsiz += 4096; + } + + /* Parse system's interface list. */ + cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */ + for (cp = buf; + (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; + cp += cpsize) { + memcpy(&u.ifreq, cp, sizeof u.ifreq); +#ifdef HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (u.ifreq.ifr_addr.sa_len == 0) + u.ifreq.ifr_addr.sa_len = 16; +#endif +#ifdef HAVE_MINIMUM_IFREQ + cpsize = sizeof u.ifreq; + if (u.ifreq.ifr_addr.sa_len > sizeof (struct sockaddr)) + cpsize += (int)u.ifreq.ifr_addr.sa_len - + (int)(sizeof (struct sockaddr)); +#else + cpsize = sizeof u.ifreq.ifr_name + u.ifreq.ifr_addr.sa_len; +#endif /* HAVE_MINIMUM_IFREQ */ + if (cpsize > sizeof u.ifreq && cpsize <= sizeof u) + memcpy(&u.ifreq, cp, cpsize); +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof u.ifreq; +#else + cpsize = sizeof u.ifreq.ifr_name; + /* XXX maybe this should be a hard error? */ + if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0) + continue; +#endif + switch (u.ifreq.ifr_addr.sa_family) { + case AF_INET: + if (*have_v4 == 0) { + memcpy(&in4, + &((struct sockaddr_in *) + &u.ifreq.ifr_addr)->sin_addr, + sizeof in4); + if (in4.s_addr == INADDR_ANY) + break; + n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq); + if (n < 0) + break; + if ((u.ifreq.ifr_flags & IFF_UP) == 0) + break; + *have_v4 = 1; + } + break; + case AF_INET6: + if (*have_v6 == 0) { + memcpy(&in6, + &((struct sockaddr_in6 *) + &u.ifreq.ifr_addr)->sin6_addr, + sizeof in6); + if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) + break; + n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq); + if (n < 0) + break; + if ((u.ifreq.ifr_flags & IFF_UP) == 0) + break; + *have_v6 = 1; + } + break; + } + } + if (buf != NULL) + memput(buf, bufsiz); + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (0); + err_ret: + if (buf != NULL) + memput(buf, bufsiz); + if (s != -1) + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (-1); +} + +static struct hostent * +copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) { + struct hostent *he = NULL; + int addresses = 1; /* NULL terminator */ + int names = 1; /* NULL terminator */ + int len = 0; + char **cpp, **npp; + + /* + * Work out array sizes; + */ + if (he1 != NULL) { + cpp = he1->h_addr_list; + while (*cpp != NULL) { + addresses++; + cpp++; + } + cpp = he1->h_aliases; + while (*cpp != NULL) { + names++; + cpp++; + } + } + + if (he2 != NULL) { + cpp = he2->h_addr_list; + while (*cpp != NULL) { + addresses++; + cpp++; + } + if (he1 == NULL) { + cpp = he2->h_aliases; + while (*cpp != NULL) { + names++; + cpp++; + } + } + } + + if (addresses == 1) { + *error_num = NO_ADDRESS; + return (NULL); + } + + he = memget(sizeof *he); + if (he == NULL) + goto no_recovery; + + he->h_addr_list = memget(sizeof(char *) * (addresses)); + if (he->h_addr_list == NULL) + goto cleanup0; + memset(he->h_addr_list, 0, sizeof(char *) * (addresses)); + + /* copy addresses */ + npp = he->h_addr_list; + if (he1 != NULL) { + cpp = he1->h_addr_list; + while (*cpp != NULL) { + *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + if (*npp == NULL) + goto cleanup1; + /* convert to mapped if required */ + if (af == AF_INET6 && he1->h_addrtype == AF_INET) { + memcpy(*npp, in6addr_mapped, + sizeof in6addr_mapped); + memcpy(*npp + sizeof in6addr_mapped, *cpp, + INADDRSZ); + } else { + memcpy(*npp, *cpp, + (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + } + cpp++; + npp++; + } + } + + if (he2 != NULL) { + cpp = he2->h_addr_list; + while (*cpp != NULL) { + *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + if (*npp == NULL) + goto cleanup1; + /* convert to mapped if required */ + if (af == AF_INET6 && he2->h_addrtype == AF_INET) { + memcpy(*npp, in6addr_mapped, + sizeof in6addr_mapped); + memcpy(*npp + sizeof in6addr_mapped, *cpp, + INADDRSZ); + } else { + memcpy(*npp, *cpp, + (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + } + cpp++; + npp++; + } + } + + he->h_aliases = memget(sizeof(char *) * (names)); + if (he->h_aliases == NULL) + goto cleanup1; + memset(he->h_aliases, 0, sizeof(char *) * (names)); + + /* copy aliases */ + npp = he->h_aliases; + cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases; + while (*cpp != NULL) { + len = strlen (*cpp) + 1; + *npp = memget(len); + if (*npp == NULL) + goto cleanup2; + strcpy(*npp, *cpp); + npp++; + cpp++; + } + + /* copy hostname */ + he->h_name = memget(strlen((he1 != NULL) ? + he1->h_name : he2->h_name) + 1); + if (he->h_name == NULL) + goto cleanup2; + strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name); + + /* set address type and length */ + he->h_addrtype = af; + he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ; + return(he); + + cleanup2: + cpp = he->h_aliases; + while (*cpp != NULL) { + memput(*cpp, strlen(*cpp) + 1); + cpp++; + } + memput(he->h_aliases, sizeof(char *) * (names)); + + cleanup1: + cpp = he->h_addr_list; + while (*cpp != NULL) { + memput(*cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + *cpp = NULL; + cpp++; + } + memput(he->h_addr_list, sizeof(char *) * (addresses)); + + cleanup0: + memput(he, sizeof *he); + + no_recovery: + *error_num = NO_RECOVERY; + return (NULL); +} + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { + error: + errno = EIO; + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); + } + + return (net_data); +} + +static void +freepvt(struct net_data *net_data) { + if (net_data->ho_data) { + free(net_data->ho_data); + net_data->ho_data = NULL; + } +} + +static struct hostent * +fakeaddr(const char *name, int af, struct net_data *net_data) { + struct pvt *pvt; + + freepvt(net_data); + net_data->ho_data = malloc(sizeof (struct pvt)); + if (!net_data->ho_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->ho_data; +#ifndef __bsdi__ + /* + * Unlike its forebear(inet_aton), our friendly inet_pton() is strict + * in its interpretation of its input, and it will only return "1" if + * the input string is a formally valid(and thus unambiguous with + * respect to host names) internet address specification for this AF. + * + * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now. + */ + if (inet_pton(af, name, pvt->addr) != 1) { +#else + /* BSDI XXX + * We put this back to inet_aton -- we really want the old behavior + * Long live 127.1... + */ + if ((af != AF_INET || + inet_aton(name, (struct in_addr *)pvt->addr) != 1) && + inet_pton(af, name, pvt->addr) != 1) { +#endif + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + strncpy(pvt->name, name, NS_MAXDNAME); + pvt->name[NS_MAXDNAME] = '\0'; + if (af == AF_INET && (net_data->res->options & RES_USE_INET6) != 0) { + map_v4v6_address(pvt->addr, pvt->addr); + af = AF_INET6; + } + pvt->host.h_addrtype = af; + switch(af) { + case AF_INET: + pvt->host.h_length = NS_INADDRSZ; + break; + case AF_INET6: + pvt->host.h_length = NS_IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt->host.h_name = pvt->name; + pvt->host.h_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->addrs[0] = (char *)pvt->addr; + pvt->addrs[1] = NULL; + pvt->host.h_addr_list = pvt->addrs; + RES_SET_H_ERRNO(net_data->res, NETDB_SUCCESS); + return (&pvt->host); +} + +#ifdef grot /* for future use in gethostbyaddr(), for "SUNSECURITY" */ + struct hostent *rhp; + char **haddr; + u_long old_options; + char hname2[MAXDNAME+1]; + + if (af == AF_INET) { + /* + * turn off search as the name should be absolute, + * 'localhost' should be matched by defnames + */ + strncpy(hname2, hp->h_name, MAXDNAME); + hname2[MAXDNAME] = '\0'; + old_options = net_data->res->options; + net_data->res->options &= ~RES_DNSRCH; + net_data->res->options |= RES_DEFNAMES; + if (!(rhp = gethostbyname(hname2))) { + net_data->res->options = old_options; + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + net_data->res->options = old_options; + for (haddr = rhp->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, INADDRSZ)) + break; + if (!*haddr) { + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + } +#endif /* grot */ + +#endif /*__BIND_NOSTATIC*/ diff --git a/usr/src/lib/libresolv2/common/irs/gethostent_r.c b/usr/src/lib/libresolv2/common/irs/gethostent_r.c new file mode 100644 index 0000000000..f6f77b7735 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/gethostent_r.c @@ -0,0 +1,271 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: gethostent_r.c,v 8.7 2001/11/01 08:02:09 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int gethostent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/param.h> +#include <port_after.h> + +#ifdef HOST_R_RETURN + +static HOST_R_RETURN +copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS); + +HOST_R_RETURN +gethostbyname_r(const char *name, struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostbyname(name); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + + HOST_R_ERRNO; + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +HOST_R_RETURN +gethostbyaddr_r(const char *addr, int len, int type, + struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostbyaddr(addr, len, type); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + + HOST_R_ERRNO; + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +HOST_R_RETURN +gethostent_r(struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostent(); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + + HOST_R_ERRNO; + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) == 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +HOST_R_SET_RETURN +#ifdef HOST_R_ENT_ARGS +sethostent_r(int stay_open, HOST_R_ENT_ARGS) +#else +sethostent_r(int stay_open) +#endif +{ + sethostent(stay_open); +#ifdef HOST_R_SET_RESULT + return (HOST_R_SET_RESULT); +#endif +} + +HOST_R_END_RETURN +#ifdef HOST_R_ENT_ARGS +endhostent_r(HOST_R_ENT_ARGS) +#else +endhostent_r(void) +#endif +{ + endhostent(); + HOST_R_END_RESULT(HOST_R_OK); +} + +/* Private */ + +#ifndef HOSTENT_DATA +static HOST_R_RETURN +copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) { + char *cp; + char **ptr; + int i, n; + int nptr, len; + + /* Find out the amount of space required to store the answer. */ + nptr = 2; /* NULL ptrs */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; he->h_addr_list[i]; i++, nptr++) { + len += he->h_length; + } + for (i = 0; he->h_aliases[i]; i++, nptr++) { + len += strlen(he->h_aliases[i]) + 1; + } + len += strlen(he->h_name) + 1; + len += nptr * sizeof(char*); + + if (len > buflen) { + errno = ERANGE; + return (HOST_R_BAD); + } + + /* copy address size and type */ + hptr->h_addrtype = he->h_addrtype; + n = hptr->h_length = he->h_length; + + ptr = (char **)ALIGN(buf); + cp = (char *)ALIGN(buf) + nptr * sizeof(char *); + + /* copy address list */ + hptr->h_addr_list = ptr; + for (i = 0; he->h_addr_list[i]; i++ , ptr++) { + memcpy(cp, he->h_addr_list[i], n); + hptr->h_addr_list[i] = cp; + cp += n; + } + hptr->h_addr_list[i] = NULL; + ptr++; + + /* copy official name */ + n = strlen(he->h_name) + 1; + strcpy(cp, he->h_name); + hptr->h_name = cp; + cp += n; + + /* copy aliases */ + hptr->h_aliases = ptr; + for (i = 0 ; he->h_aliases[i]; i++) { + n = strlen(he->h_aliases[i]) + 1; + strcpy(cp, he->h_aliases[i]); + hptr->h_aliases[i] = cp; + cp += n; + } + hptr->h_aliases[i] = NULL; + + return (HOST_R_OK); +} +#else /* !HOSTENT_DATA */ +static int +copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy address size and type */ + hptr->h_addrtype = he->h_addrtype; + n = hptr->h_length = he->h_length; + + /* copy up to first 35 addresses */ + i = 0; + cp = hdptr->hostaddr; + eob = hdptr->hostaddr + sizeof(hdptr->hostaddr); + hptr->h_addr_list = hdptr->h_addr_ptrs; + while (he->h_addr_list[i] && i < (_MAXADDRS)) { + if (n < (eob - cp)) { + memcpy(cp, he->h_addr_list[i], n); + hptr->h_addr_list[i] = cp; + cp += n; + } else { + break; + } + i++; + } + hptr->h_addr_list[i] = NULL; + + /* copy official name */ + cp = hdptr->hostbuf; + eob = hdptr->hostbuf + sizeof(hdptr->hostbuf); + if ((n = strlen(he->h_name) + 1) < (eob - cp)) { + strcpy(cp, he->h_name); + hptr->h_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + hptr->h_aliases = hdptr->host_aliases; + while (he->h_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(he->h_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, he->h_aliases[i]); + hptr->h_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + hptr->h_aliases[i] = NULL; + + return (HOST_R_OK); +} +#endif /* !HOSTENT_DATA */ +#else /* HOST_R_RETURN */ + static int gethostent_r_unknown_system = 0; +#endif /* HOST_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/usr/src/lib/libresolv2/common/irs/getnameinfo.c b/usr/src/lib/libresolv2/common/irs/getnameinfo.c new file mode 100644 index 0000000000..e645196a80 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getnameinfo.c @@ -0,0 +1,341 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Issues to be discussed: + * - Thread safe-ness must be checked + */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * 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 WIDE Project and + * its contributors. + * 4. Neither the name of the project 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 PROJECT 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 PROJECT 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. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <port_before.h> + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> +#include <net/if.h> + +#include <netdb.h> +#include <resolv.h> +#include <string.h> +#include <stddef.h> + +#include <port_after.h> + +/* + * Note that a_off will be dynamically adjusted so that to be consistent + * with the definition of sockaddr_in{,6}. + * The value presented below is just a guess. + */ +static struct afd { + int a_af; + int a_addrlen; + size_t a_socklen; + int a_off; +} afdl [] = { + /* first entry is linked last... */ + {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr)}, + {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr)}, + {0, 0, 0, 0}, +}; + +struct sockinet { +#ifdef HAVE_SA_LEN + u_char si_len; +#endif + u_char si_family; + u_short si_port; +}; + +static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *, + size_t, int)); +#ifdef HAVE_SIN6_SCOPE_ID +static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, int)); +#endif + +int +getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) + const struct sockaddr *sa; +#ifdef ORIGINAL_ISC_CODE + size_t salen; +#else + socklen_t salen; +#endif + char *host; +#ifdef ORIGINAL_ISC_CODE + size_t hostlen; +#else + socklen_t hostlen; +#endif + char *serv; +#ifdef ORIGINAL_ISC_CODE + size_t servlen; +#else + socklen_t servlen; +#endif + int flags; +{ + struct afd *afd; + struct servent *sp; + struct hostent *hp; + u_short port; +#ifdef HAVE_SA_LEN + size_t len; +#endif + int family, i; + const char *addr; + char *p; + char numserv[512]; + char numaddr[512]; + const struct sockaddr_in6 *sin6; + + if (sa == NULL) + return EAI_FAIL; + +#ifdef HAVE_SA_LEN + len = sa->sa_len; + if (len != salen) return EAI_FAIL; +#endif + + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + return EAI_FAMILY; + + found: + if (salen != afd->a_socklen) return EAI_FAIL; + + port = ((const struct sockinet *)sa)->si_port; /* network byte order */ + addr = (const char *)sa + afd->a_off; + + if (serv == NULL || servlen == 0) { + /* + * rfc2553bis says that serv == NULL or servlen == 0 means that + * the caller does not want the result. + */ + } else if (flags & NI_NUMERICSERV) { + sprintf(numserv, "%d", ntohs(port)); + if (strlen(numserv) > servlen) + return EAI_MEMORY; + strcpy(serv, numserv); + } else { + sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp"); + if (sp) { + if (strlen(sp->s_name) + 1 > servlen) + return EAI_MEMORY; + strcpy(serv, sp->s_name); + } else + return EAI_NONAME; + } + + switch (sa->sa_family) { + case AF_INET: + if (ntohl(*(const u_long *)addr) >> IN_CLASSA_NSHIFT == 0) + flags |= NI_NUMERICHOST; + break; + case AF_INET6: + sin6 = (const struct sockaddr_in6 *)sa; + switch (sin6->sin6_addr.s6_addr[0]) { + case 0x00: + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + ; + else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) + ; + else + flags |= NI_NUMERICHOST; + break; + default: + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) + flags |= NI_NUMERICHOST; + else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + flags |= NI_NUMERICHOST; + break; + } + break; + } + if (host == NULL || hostlen == 0) { + /* + * rfc2553bis says that host == NULL or hostlen == 0 means that + * the caller does not want the result. + */ + } else if (flags & NI_NUMERICHOST) { + goto numeric; + } else { + hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); + + if (hp) { + if (flags & NI_NOFQDN) { + p = strchr(hp->h_name, '.'); + if (p) *p = '\0'; + } + if (strlen(hp->h_name) + 1 > hostlen) + return EAI_MEMORY; + strcpy(host, hp->h_name); + } else { + if (flags & NI_NAMEREQD) + return EAI_NONAME; + numeric: + switch(afd->a_af) { + case AF_INET6: + { + int error; + + if ((error = ip6_parsenumeric(sa, addr, host, + hostlen, + flags)) != 0) + return(error); + break; + } + + default: + if (inet_ntop(afd->a_af, addr, numaddr, + sizeof(numaddr)) == NULL) + return EAI_NONAME; + if (strlen(numaddr) + 1 > hostlen) + return EAI_MEMORY; + strcpy(host, numaddr); + } + } + } + return(0); +} + +static int +ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host, + size_t hostlen, int flags) +{ + size_t numaddrlen; + char numaddr[512]; + +#ifndef HAVE_SIN6_SCOPE_ID + UNUSED(sa); + UNUSED(flags); +#endif + + if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) + == NULL) + return EAI_SYSTEM; + + numaddrlen = strlen(numaddr); + if (numaddrlen + 1 > hostlen) /* don't forget terminator */ + return EAI_MEMORY; + strcpy(host, numaddr); + +#ifdef HAVE_SIN6_SCOPE_ID + if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) { + char scopebuf[MAXHOSTNAMELEN]; /* XXX */ + int scopelen; + + /* ip6_sa2str never fails */ + scopelen = ip6_sa2str((const struct sockaddr_in6 *)sa, + scopebuf, sizeof(scopebuf), flags); + + if (scopelen + 1 + numaddrlen + 1 > hostlen) + return EAI_MEMORY; + + /* construct <numeric-addr><delim><scopeid> */ + memcpy(host + numaddrlen + 1, scopebuf, + scopelen); + host[numaddrlen] = SCOPE_DELIMITER; + host[numaddrlen + 1 + scopelen] = '\0'; + } +#endif + + return 0; +} + +#ifdef HAVE_SIN6_SCOPE_ID +/* ARGSUSED */ +static int +ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, + size_t bufsiz, int flags) +{ +#ifdef USE_IFNAMELINKID + unsigned int ifindex = (unsigned int)sa6->sin6_scope_id; + const struct in6_addr *a6 = &sa6->sin6_addr; +#endif + char tmp[64]; + +#ifdef NI_NUMERICSCOPE + if (flags & NI_NUMERICSCOPE) { + sprintf(tmp, "%u", sa6->sin6_scope_id); + if (bufsiz != 0) { + strncpy(buf, tmp, bufsiz - 1); + buf[bufsiz - 1] = '\0'; + } + return(strlen(tmp)); + } +#endif + +#ifdef USE_IFNAMELINKID + /* + * For a link-local address, convert the index to an interface + * name, assuming a one-to-one mapping between links and interfaces. + * Note, however, that this assumption is stronger than the + * specification of the scoped address architecture; the + * specficication says that more than one interfaces can belong to + * a single link. + */ + + /* if_indextoname() does not take buffer size. not a good api... */ + if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) && + bufsiz >= IF_NAMESIZE) { + char *p = if_indextoname(ifindex, buf); + if (p) { + return(strlen(p)); + } + } +#endif + + /* last resort */ + sprintf(tmp, "%u", sa6->sin6_scope_id); + if (bufsiz != 0) { + strncpy(buf, tmp, bufsiz - 1); + buf[bufsiz - 1] = '\0'; + } + return(strlen(tmp)); +} +#endif diff --git a/usr/src/lib/libresolv2/common/irs/getnetent.c b/usr/src/lib/libresolv2/common/irs/getnetent.c new file mode 100644 index 0000000000..8cf81d4699 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getnetent.c @@ -0,0 +1,370 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getnetent.c,v 1.19 2001/05/29 05:48:47 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + struct netent netent; + char * aliases[1]; + char name[MAXDNAME + 1]; +}; + +/* Forward */ + +static struct net_data *init(void); +static struct netent *nw_to_net(struct nwent *, struct net_data *); +static void freepvt(struct net_data *); +static struct netent *fakeaddr(const char *, int af, struct net_data *); + +/* Portability */ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffff +#endif + +/* Public */ + +struct netent * +getnetent() { + struct net_data *net_data = init(); + + return (getnetent_p(net_data)); +} + +struct netent * +getnetbyname(const char *name) { + struct net_data *net_data = init(); + + return (getnetbyname_p(name, net_data)); +} + +struct netent * +#ifdef ORIGINAL_ISC_CODE +getnetbyaddr(unsigned long net, int type) { +#else +getnetbyaddr(in_addr_t net, int type) { +#endif + struct net_data *net_data = init(); + + return (getnetbyaddr_p(net, type, net_data)); +} + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +setnetent(int stayopen) { + struct net_data *net_data = init(); + + setnetent_p(stayopen, net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +endnetent() { + struct net_data *net_data = init(); + + endnetent_p(net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + +/* Shared private. */ + +struct netent * +getnetent_p(struct net_data *net_data) { + struct irs_nw *nw; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + net_data->nww_last = (*nw->next)(nw); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + return (net_data->nw_last); +} + +struct netent * +getnetbyname_p(const char *name, struct net_data *net_data) { + struct irs_nw *nw; + struct netent *np; + char **nap; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + if (net_data->nw_stayopen && net_data->nw_last) { + if (!strcmp(net_data->nw_last->n_name, name)) + return (net_data->nw_last); + for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++) + if (!strcmp(name, *nap)) + return (net_data->nw_last); + } + if ((np = fakeaddr(name, AF_INET, net_data)) != NULL) + return (np); + net_data->nww_last = (*nw->byname)(nw, name, AF_INET); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + if (!net_data->nw_stayopen) + endnetent(); + return (net_data->nw_last); +} + +struct netent * +getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) { + struct irs_nw *nw; + u_char addr[4]; + int bits; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + if (net_data->nw_stayopen && net_data->nw_last) + if (type == net_data->nw_last->n_addrtype && + net == net_data->nw_last->n_net) + return (net_data->nw_last); + + /* cannonize net(host order) */ + if (net < 256) { + net <<= 24; + bits = 8; + } else if (net < 65536) { + net <<= 16; + bits = 16; + } else if (net < 16777216) { + net <<= 8; + bits = 24; + } else + bits = 32; + + /* convert to net order */ + addr[0] = (0xFF000000 & net) >> 24; + addr[1] = (0x00FF0000 & net) >> 16; + addr[2] = (0x0000FF00 & net) >> 8; + addr[3] = (0x000000FF & net); + + /* reduce bits to as close to natural number as possible */ + if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) { + if ((addr[0] < 192) && (addr[2] == 0)) { + if ((addr[0] < 128) && (addr[1] == 0)) + bits = 8; + else + bits = 16; + } else { + bits = 24; + } + } + + net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + if (!net_data->nw_stayopen) + endnetent(); + return (net_data->nw_last); +} + + + + +void +setnetent_p(int stayopen, struct net_data *net_data) { + struct irs_nw *nw; + + if (!net_data || !(nw = net_data->nw)) + return; + freepvt(net_data); + (*nw->rewind)(nw); + net_data->nw_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endnetent_p(struct net_data *net_data) { + struct irs_nw *nw; + + if ((net_data != NULL) && ((nw = net_data->nw) != NULL)) + (*nw->minimize)(nw); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->nw) { + net_data->nw = (*net_data->irs->nw_map)(net_data->irs); + + if (!net_data->nw || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->nw->res_set)(net_data->nw, net_data->res, NULL); + } + + return (net_data); +} + +static void +freepvt(struct net_data *net_data) { + if (net_data->nw_data) { + free(net_data->nw_data); + net_data->nw_data = NULL; + } +} + +static struct netent * +fakeaddr(const char *name, int af, struct net_data *net_data) { + struct pvt *pvt; + const char *cp; + u_long tmp; + + if (af != AF_INET) { + /* XXX should support IPv6 some day */ + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + if (!isascii((unsigned char)(name[0])) || + !isdigit((unsigned char)(name[0]))) + return (NULL); + for (cp = name; *cp; ++cp) + if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.')) + return (NULL); + if (*--cp == '.') + return (NULL); + + /* All-numeric, no dot at the end. */ + + tmp = inet_network(name); + if (tmp == INADDR_NONE) { + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + + /* Valid network number specified. + * Fake up a netent as if we'd actually + * done a lookup. + */ + freepvt(net_data); + net_data->nw_data = malloc(sizeof (struct pvt)); + if (!net_data->nw_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->nw_data; + + strncpy(pvt->name, name, MAXDNAME); + pvt->name[MAXDNAME] = '\0'; + pvt->netent.n_name = pvt->name; + pvt->netent.n_addrtype = AF_INET; + pvt->netent.n_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->netent.n_net = tmp; + + return (&pvt->netent); +} + +static struct netent * +nw_to_net(struct nwent *nwent, struct net_data *net_data) { + struct pvt *pvt; + u_long addr = 0; + int i; + int msbyte; + + if (!nwent || nwent->n_addrtype != AF_INET) + return (NULL); + freepvt(net_data); + net_data->nw_data = malloc(sizeof (struct pvt)); + if (!net_data->nw_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->nw_data; + pvt->netent.n_name = nwent->n_name; + pvt->netent.n_aliases = nwent->n_aliases; + pvt->netent.n_addrtype = nwent->n_addrtype; + +/* + * What this code does: Converts net addresses from network to host form. + * + * msbyte: the index of the most significant byte in the n_addr array. + * + * Shift bytes in significant order into addr. When all signicant + * bytes are in, zero out bits in the LSB that are not part of the network. + */ + msbyte = nwent->n_length / 8 + + ((nwent->n_length % 8) != 0 ? 1 : 0) - 1; + for (i = 0; i <= msbyte; i++) + addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i]; + i = (32 - nwent->n_length) % 8; + if (i != 0) + addr &= ~((1 << (i + 1)) - 1); + pvt->netent.n_net = addr; + return (&pvt->netent); +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/usr/src/lib/libresolv2/common/irs/getnetent_r.c b/usr/src/lib/libresolv2/common/irs/getnetent_r.c new file mode 100644 index 0000000000..1f8f9686c9 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getnetent_r.c @@ -0,0 +1,234 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetent_r.c,v 8.6 2001/11/01 08:02:11 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getnetent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/param.h> +#include <port_after.h> + +#ifdef NET_R_RETURN + +static NET_R_RETURN +copy_netent(struct netent *, struct netent *, NET_R_COPY_ARGS); + +NET_R_RETURN +getnetbyname_r(const char *name, struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetbyname(name); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +#ifndef GETNETBYADDR_ADDR_T +#define GETNETBYADDR_ADDR_T long +#endif +NET_R_RETURN +getnetbyaddr_r(GETNETBYADDR_ADDR_T addr, int type, struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetbyaddr(addr, type); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +NET_R_RETURN +getnetent_r(struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetent(); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +NET_R_SET_RETURN +#ifdef NET_R_ENT_ARGS +setnetent_r(int stay_open, NET_R_ENT_ARGS) +#else +setnetent_r(int stay_open) +#endif +{ + setnetent(stay_open); +#ifdef NET_R_SET_RESULT + return (NET_R_SET_RESULT); +#endif +} + +NET_R_END_RETURN +#ifdef NET_R_ENT_ARGS +endnetent_r(NET_R_ENT_ARGS) +#else +endnetent_r() +#endif +{ + endnetent(); + NET_R_END_RESULT(NET_R_OK); +} + +/* Private */ + +#ifndef NETENT_DATA +static NET_R_RETURN +copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; ne->n_aliases[i]; i++, numptr++) { + len += strlen(ne->n_aliases[i]) + 1; + } + len += strlen(ne->n_name) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (NET_R_BAD); + } + + /* copy net value and type */ + nptr->n_addrtype = ne->n_addrtype; + nptr->n_net = ne->n_net; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(ne->n_name) + 1; + strcpy(cp, ne->n_name); + nptr->n_name = cp; + cp += n; + + /* copy aliases */ + nptr->n_aliases = (char **)ALIGN(buf); + for (i = 0 ; ne->n_aliases[i]; i++) { + n = strlen(ne->n_aliases[i]) + 1; + strcpy(cp, ne->n_aliases[i]); + nptr->n_aliases[i] = cp; + cp += n; + } + nptr->n_aliases[i] = NULL; + + return (NET_R_OK); +} +#else /* !NETENT_DATA */ +static int +copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy net value and type */ + nptr->n_addrtype = ne->n_addrtype; + nptr->n_net = ne->n_net; + + /* copy official name */ + cp = ndptr->line; + eob = ndptr->line + sizeof(ndptr->line); + if ((n = strlen(ne->n_name) + 1) < (eob - cp)) { + strcpy(cp, ne->n_name); + nptr->n_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + nptr->n_aliases = ndptr->net_aliases; + while (ne->n_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(ne->n_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, ne->n_aliases[i]); + nptr->n_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + nptr->n_aliases[i] = NULL; + + return (NET_R_OK); +} +#endif /* !NETENT_DATA */ +#else /* NET_R_RETURN */ + static int getnetent_r_unknown_system = 0; +#endif /* NET_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/usr/src/lib/libresolv2/common/irs/getnetgrent.c b/usr/src/lib/libresolv2/common/irs/getnetgrent.c new file mode 100644 index 0000000000..69e322d647 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getnetgrent.c @@ -0,0 +1,191 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Portions Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetgrent.c,v 1.17 2003/04/29 05:51:14 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + + +/* Public */ + +#ifndef SETNETGRENT_ARGS +#define SETNETGRENT_ARGS const char *netgroup +#endif + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +setnetgrent(SETNETGRENT_ARGS) { + struct net_data *net_data = init(); + + setnetgrent_p(netgroup, net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +endnetgrent(void) { + struct net_data *net_data = init(); + + endnetgrent_p(net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + +#ifndef INNETGR_ARGS +#define INNETGR_ARGS const char *netgroup, const char *host, \ + const char *user, const char *domain +#endif +int +innetgr(INNETGR_ARGS) { + struct net_data *net_data = init(); + + return (innetgr_p(netgroup, host, user, domain, net_data)); +} + +#ifdef ORIGINAL_ISC_CODE +int +getnetgrent(const char **host, const char **user, const char **domain) { + struct net_data *net_data = init(); + const char *ch, *cu, *cd; + int ret; + + ret = getnetgrent_p(&ch, &cu, &cd, net_data); + if (ret != 1) + return (ret); + + DE_CONST(ch, *host); + DE_CONST(cu, *user); + DE_CONST(cd, *domain); + return (ret); +} +#else +int +getnetgrent(char **host, char **user, char **domain) { + struct net_data *net_data = init(); + + return (getnetgrent_p((const char **)host, (const char **)user, + (const char **)domain, net_data)); + +} +#endif /* ORIGINAL_ISC_CODE */ + +/* Shared private. */ + +void +setnetgrent_p(const char *netgroup, struct net_data *net_data) { + struct irs_ng *ng; + + if ((net_data != NULL) && ((ng = net_data->ng) != NULL)) + (*ng->rewind)(ng, netgroup); +} + +void +endnetgrent_p(struct net_data *net_data) { + struct irs_ng *ng; + + if (!net_data) + return; + if ((ng = net_data->ng) != NULL) + (*ng->close)(ng); + net_data->ng = NULL; +} + +int +innetgr_p(const char *netgroup, const char *host, + const char *user, const char *domain, + struct net_data *net_data) { + struct irs_ng *ng; + + if (!net_data || !(ng = net_data->ng)) + return (0); + return ((*ng->test)(ng, netgroup, host, user, domain)); +} + +int +getnetgrent_p(const char **host, const char **user, const char **domain, + struct net_data *net_data ) { + struct irs_ng *ng; + + if (!net_data || !(ng = net_data->ng)) + return (0); + return ((*ng->next)(ng, host, user, domain)); +} + +/* Private */ + +static struct net_data * +init(void) { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ng) { + net_data->ng = (*net_data->irs->ng_map)(net_data->irs); + if (!net_data->ng) { + error: + errno = EIO; + return (NULL); + } + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/usr/src/lib/libresolv2/common/irs/getnetgrent_r.c b/usr/src/lib/libresolv2/common/irs/getnetgrent_r.c new file mode 100644 index 0000000000..a53ebd2cee --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getnetgrent_r.c @@ -0,0 +1,172 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetgrent_r.c,v 8.7 2003/04/29 05:51:14 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getnetgrent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <netgroup.h> +#include <stdlib.h> +#include <port_after.h> + +#ifdef NGR_R_RETURN + +static NGR_R_RETURN +copy_protoent(char **, char **, char **, const char *, const char *, + const char *, NGR_R_COPY_ARGS); + +NGR_R_RETURN +innetgr_r(const char *netgroup, const char *host, const char *user, + const char *domain) { + char *ng, *ho, *us, *dom; + + DE_CONST(netgroup, ng); + DE_CONST(host, ho); + DE_CONST(user, us); + DE_CONST(domain, dom); + + return (innetgr(ng, ho, us, dom)); +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +NGR_R_RETURN +getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS) { + char *mp, *up, *dp; + int res = getnetgrent(&mp, &up, &dp); + + if (res != 1) + return (res); + + return (copy_protoent(machinep, userp, domainp, + mp, up, dp, NGR_R_COPY)); +} + +NGR_R_SET_RETURN +#ifdef NGR_R_ENT_ARGS +setnetgrent_r(const char *netgroup, NGR_R_ENT_ARGS) +#else +setnetgrent_r(const char *netgroup) +#endif +{ + setnetgrent(netgroup); +#ifdef NGR_R_PRIVATE + *buf = NULL; +#endif +#ifdef NGR_R_SET_RESULT + return (NGR_R_SET_RESULT); +#endif +} + +NGR_R_END_RETURN +#ifdef NGR_R_ENT_ARGS +endnetgrent_r(NGR_R_ENT_ARGS) +#else +endnetgrent_r(void) +#endif +{ + endnetgrent(); +#ifdef NGR_R_PRIVATE + if (*buf != NULL) + free(*buf); + *buf = NULL; +#endif + NGR_R_END_RESULT(NGR_R_OK); +} + +/* Private */ + +static int +copy_protoent(char **machinep, char **userp, char **domainp, + const char *mp, const char *up, const char *dp, + NGR_R_COPY_ARGS) { + char *cp; + int n; + int len; + + /* Find out the amount of space required to store the answer. */ + len = 0; + if (mp != NULL) len += strlen(mp) + 1; + if (up != NULL) len += strlen(up) + 1; + if (dp != NULL) len += strlen(dp) + 1; + +#ifdef NGR_R_PRIVATE + free(*buf); + *buf = malloc(len); + if (*buf == NULL) + return(NGR_R_BAD); + cp = *buf; +#else + if (len > (int)buflen) { + errno = ERANGE; + return (NGR_R_BAD); + } + cp = buf; +#endif + + + if (mp != NULL) { + n = strlen(mp) + 1; + strcpy(cp, mp); + *machinep = cp; + cp += n; + } else + *machinep = NULL; + + if (up != NULL) { + n = strlen(up) + 1; + strcpy(cp, up); + *userp = cp; + cp += n; + } else + *userp = NULL; + + if (dp != NULL) { + n = strlen(dp) + 1; + strcpy(cp, dp); + *domainp = cp; + cp += n; + } else + *domainp = NULL; + + return (NGR_R_OK); +} +#else /* NGR_R_RETURN */ + static int getnetgrent_r_unknown_system = 0; +#endif /* NGR_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/usr/src/lib/libresolv2/common/irs/getprotoent.c b/usr/src/lib/libresolv2/common/irs/getprotoent.c new file mode 100644 index 0000000000..9a2b7332e3 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getprotoent.c @@ -0,0 +1,197 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getprotoent.c,v 1.16 2001/11/01 07:34:33 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + +/* Public */ + +struct protoent * +getprotoent() { + struct net_data *net_data = init(); + + return (getprotoent_p(net_data)); +} + +struct protoent * +getprotobyname(const char *name) { + struct net_data *net_data = init(); + + return (getprotobyname_p(name, net_data)); +} + +struct protoent * +getprotobynumber(int proto) { + struct net_data *net_data = init(); + + return (getprotobynumber_p(proto, net_data)); +} + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +setprotoent(int stayopen) { + struct net_data *net_data = init(); + + setprotoent_p(stayopen, net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +endprotoent() { + struct net_data *net_data = init(); + + endprotoent_p(net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + +/* Shared private. */ + +struct protoent * +getprotoent_p(struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + net_data->pr_last = (*pr->next)(pr); + return (net_data->pr_last); +} + +struct protoent * +getprotobyname_p(const char *name, struct net_data *net_data) { + struct irs_pr *pr; + char **pap; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + if (net_data->pr_stayopen && net_data->pr_last) { + if (!strcmp(net_data->pr_last->p_name, name)) + return (net_data->pr_last); + for (pap = net_data->pr_last->p_aliases; pap && *pap; pap++) + if (!strcmp(name, *pap)) + return (net_data->pr_last); + } + net_data->pr_last = (*pr->byname)(pr, name); + if (!net_data->pr_stayopen) + endprotoent(); + return (net_data->pr_last); +} + +struct protoent * +getprotobynumber_p(int proto, struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + if (net_data->pr_stayopen && net_data->pr_last) + if (net_data->pr_last->p_proto == proto) + return (net_data->pr_last); + net_data->pr_last = (*pr->bynumber)(pr, proto); + if (!net_data->pr_stayopen) + endprotoent(); + return (net_data->pr_last); +} + +void +setprotoent_p(int stayopen, struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return; + (*pr->rewind)(pr); + net_data->pr_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endprotoent_p(struct net_data *net_data) { + struct irs_pr *pr; + + if ((net_data != NULL) && ((pr = net_data->pr) != NULL)) + (*pr->minimize)(pr); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->pr) { + net_data->pr = (*net_data->irs->pr_map)(net_data->irs); + + if (!net_data->pr || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->pr->res_set)(net_data->pr, net_data->res, NULL); + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/usr/src/lib/libresolv2/common/irs/getprotoent_r.c b/usr/src/lib/libresolv2/common/irs/getprotoent_r.c new file mode 100644 index 0000000000..c8f540d5c1 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getprotoent_r.c @@ -0,0 +1,223 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getprotoent_r.c,v 8.6 2001/11/01 08:02:14 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getprotoent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <port_after.h> + +#ifdef PROTO_R_RETURN + +static PROTO_R_RETURN +copy_protoent(struct protoent *, struct protoent *, PROTO_R_COPY_ARGS); + +PROTO_R_RETURN +getprotobyname_r(const char *name, struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotobyname(name); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +PROTO_R_RETURN +getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotobynumber(proto); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +PROTO_R_RETURN +getprotoent_r(struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotoent(); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +PROTO_R_SET_RETURN +#ifdef PROTO_R_ENT_ARGS +setprotoent_r(int stay_open, PROTO_R_ENT_ARGS) +#else +setprotoent_r(int stay_open) +#endif +{ + setprotoent(stay_open); +#ifdef PROTO_R_SET_RESULT + return (PROTO_R_SET_RESULT); +#endif +} + +PROTO_R_END_RETURN +#ifdef PROTO_R_ENT_ARGS +endprotoent_r(PROTO_R_ENT_ARGS) +#else +endprotoent_r() +#endif +{ + endprotoent(); + PROTO_R_END_RESULT(PROTO_R_OK); +} + +/* Private */ + +#ifndef PROTOENT_DATA +static PROTO_R_RETURN +copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; pe->p_aliases[i]; i++, numptr++) { + len += strlen(pe->p_aliases[i]) + 1; + } + len += strlen(pe->p_name) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (PROTO_R_BAD); + } + + /* copy protocol value*/ + pptr->p_proto = pe->p_proto; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(pe->p_name) + 1; + strcpy(cp, pe->p_name); + pptr->p_name = cp; + cp += n; + + /* copy aliases */ + pptr->p_aliases = (char **)ALIGN(buf); + for (i = 0 ; pe->p_aliases[i]; i++) { + n = strlen(pe->p_aliases[i]) + 1; + strcpy(cp, pe->p_aliases[i]); + pptr->p_aliases[i] = cp; + cp += n; + } + pptr->p_aliases[i] = NULL; + + return (PROTO_R_OK); +} +#else /* !PROTOENT_DATA */ +static int +copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy protocol value */ + pptr->p_proto = pe->p_proto; + + /* copy official name */ + cp = pdptr->line; + eob = pdptr->line + sizeof(pdptr->line); + if ((n = strlen(pe->p_name) + 1) < (eob - cp)) { + strcpy(cp, pe->p_name); + pptr->p_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + pptr->p_aliases = pdptr->proto_aliases; + while (pe->p_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(pe->p_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, pe->p_aliases[i]); + pptr->p_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + pptr->p_aliases[i] = NULL; + + return (PROTO_R_OK); +} +#endif /* PROTOENT_DATA */ +#else /* PROTO_R_RETURN */ + static int getprotoent_r_unknown_system = 0; +#endif /* PROTO_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/usr/src/lib/libresolv2/common/irs/getpwent.c b/usr/src/lib/libresolv2/common/irs/getpwent.c new file mode 100644 index 0000000000..8b4667c716 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getpwent.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1997-2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getpwent.c,v 1.21 2000/02/21 21:40:56 vixie Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_PW) || defined(__BIND_NOSTATIC) +static int __bind_irs_pw_unneeded; +#else + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <pwd.h> +#include <resolv.h> +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data * init(void); + +/* Public */ + +struct passwd * +getpwent(void) { + struct net_data *net_data = init(); + + return (getpwent_p(net_data)); +} + +struct passwd * +getpwnam(const char *name) { + struct net_data *net_data = init(); + + return (getpwnam_p(name, net_data)); +} + +struct passwd * +getpwuid(uid_t uid) { + struct net_data *net_data = init(); + + return (getpwuid_p(uid, net_data)); +} + +int +setpassent(int stayopen) { + struct net_data *net_data = init(); + + return (setpassent_p(stayopen, net_data)); +} + +#ifdef SETPWENT_VOID +void +setpwent() { + struct net_data *net_data = init(); + + setpwent_p(net_data); +} +#else +int +setpwent() { + struct net_data *net_data = init(); + + return (setpwent_p(net_data)); +} +#endif + +void +endpwent() { + struct net_data *net_data = init(); + + endpwent_p(net_data); +} + +/* Shared private. */ + +struct passwd * +getpwent_p(struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + net_data->pw_last = (*pw->next)(pw); + return (net_data->pw_last); +} + +struct passwd * +getpwnam_p(const char *name, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + if (net_data->pw_stayopen && net_data->pw_last && + !strcmp(net_data->pw_last->pw_name, name)) + return (net_data->pw_last); + net_data->pw_last = (*pw->byname)(pw, name); + if (!net_data->pw_stayopen) + endpwent(); + return (net_data->pw_last); +} + +struct passwd * +getpwuid_p(uid_t uid, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (NULL); + if (net_data->pw_stayopen && net_data->pw_last && + net_data->pw_last->pw_uid == uid) + return (net_data->pw_last); + net_data->pw_last = (*pw->byuid)(pw, uid); + if (!net_data->pw_stayopen) + endpwent(); + return (net_data->pw_last); +} + +int +setpassent_p(int stayopen, struct net_data *net_data) { + struct irs_pw *pw; + + if (!net_data || !(pw = net_data->pw)) + return (0); + (*pw->rewind)(pw); + net_data->pw_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); + return (1); +} + +#ifdef SETPWENT_VOID +void +setpwent_p(struct net_data *net_data) { + (void) setpassent_p(0, net_data); +} +#else +int +setpwent_p(struct net_data *net_data) { + return (setpassent_p(0, net_data)); +} +#endif + +void +endpwent_p(struct net_data *net_data) { + struct irs_pw *pw; + + if ((net_data != NULL) && ((pw = net_data->pw) != NULL)) + (*pw->minimize)(pw); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->pw) { + net_data->pw = (*net_data->irs->pw_map)(net_data->irs); + + if (!net_data->pw || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->pw->res_set)(net_data->pw, net_data->res, NULL); + } + + return (net_data); +} + +#endif /* WANT_IRS_PW */ diff --git a/usr/src/lib/libresolv2/common/irs/getpwent_r.c b/usr/src/lib/libresolv2/common/irs/getpwent_r.c new file mode 100644 index 0000000000..4e3b8a2578 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getpwent_r.c @@ -0,0 +1,283 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = + "$Id: getpwent_r.c,v 8.6 2001/11/01 08:02:15 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) || !defined(WANT_IRS_PW) + static int getpwent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#if (defined(POSIX_GETPWNAM_R) || defined(POSIX_GETPWUID_R)) +#if defined(_POSIX_PTHREAD_SEMANTICS) + /* turn off solaris remapping in <grp.h> */ +#undef _POSIX_PTHREAD_SEMANTICS +#include <pwd.h> +#define _POSIX_PTHREAD_SEMANTICS 1 +#else +#define _UNIX95 1 +#include <pwd.h> +#endif +#else +#include <pwd.h> +#endif +#include <port_after.h> + +#ifdef PASS_R_RETURN + +static int +copy_passwd(struct passwd *, struct passwd *, char *buf, int buflen); + +/* POSIX 1003.1c */ +#ifdef POSIX_GETPWNAM_R +int +__posix_getpwnam_r(const char *login, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#else +int +getpwnam_r(const char *login, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#endif + struct passwd *pw = getpwnam(login); + int res; + + if (pw == NULL) { + *result = NULL; + return (0); + } + + res = copy_passwd(pw, pwptr, buf, buflen); + *result = res ? NULL : pwptr; + return (res); +} + +#ifdef POSIX_GETPWNAM_R +struct passwd * +getpwnam_r(const char *login, struct passwd *pwptr, char *buf, int buflen) { + struct passwd *pw = getpwnam(login); + int res; + + if (pw == NULL) + return (NULL); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? NULL : pwptr); +} +#endif + +/* POSIX 1003.1c */ +#ifdef POSIX_GETPWUID_R +int +__posix_getpwuid_r(uid_t uid, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#else +int +getpwuid_r(uid_t uid, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result) { +#endif + struct passwd *pw = getpwuid(uid); + int res; + + if (pw == NULL) { + *result = NULL; + return (0); + } + + res = copy_passwd(pw, pwptr, buf, buflen); + *result = res ? NULL : pwptr; + return (res); +} + +#ifdef POSIX_GETPWUID_R +struct passwd * +getpwuid_r(uid_t uid, struct passwd *pwptr, char *buf, int buflen) { + struct passwd *pw = getpwuid(uid); + int res; + + if (pw == NULL) + return (NULL); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? NULL : pwptr); +} +#endif + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +PASS_R_RETURN +getpwent_r(struct passwd *pwptr, PASS_R_ARGS) { + struct passwd *pw = getpwent(); + int res; + + if (pw == NULL) + return (PASS_R_BAD); + + res = copy_passwd(pw, pwptr, buf, buflen); + return (res ? PASS_R_BAD : PASS_R_OK); +} + +PASS_R_SET_RETURN +#ifdef PASS_R_ENT_ARGS +setpassent_r(int stayopen, PASS_R_ENT_ARGS) +#else +setpassent_r(int stayopen) +#endif +{ + + setpassent(stayopen); +#ifdef PASS_R_SET_RESULT + return (PASS_R_SET_RESULT); +#endif +} + +PASS_R_SET_RETURN +#ifdef PASS_R_ENT_ARGS +setpwent_r(PASS_R_ENT_ARGS) +#else +setpwent_r(void) +#endif +{ + + setpwent(); +#ifdef PASS_R_SET_RESULT + return (PASS_R_SET_RESULT); +#endif +} + +PASS_R_END_RETURN +#ifdef PASS_R_ENT_ARGS +endpwent_r(PASS_R_ENT_ARGS) +#else +endpwent_r(void) +#endif +{ + + endpwent(); + PASS_R_END_RESULT(PASS_R_OK); +} + + +#ifdef HAS_FGETPWENT +PASS_R_RETURN +fgetpwent_r(FILE *f, struct passwd *pwptr, PASS_R_COPY_ARGS) { + struct passwd *pw = fgetpwent(f); + int res; + + if (pw == NULL) + return (PASS_R_BAD); + + res = copy_passwd(pw, pwptr, PASS_R_COPY); + return (res ? PASS_R_BAD : PASS_R_OK); +} +#endif + +/* Private */ + +static int +copy_passwd(struct passwd *pw, struct passwd *pwptr, char *buf, int buflen) { + char *cp; + int n; + int len; + + /* Find out the amount of space required to store the answer. */ + len = strlen(pw->pw_name) + 1; + len += strlen(pw->pw_passwd) + 1; +#ifdef HAVE_PW_CLASS + len += strlen(pw->pw_class) + 1; +#endif + len += strlen(pw->pw_gecos) + 1; + len += strlen(pw->pw_dir) + 1; + len += strlen(pw->pw_shell) + 1; + + if (len > buflen) { + errno = ERANGE; + return (ERANGE); + } + + /* copy fixed atomic values */ + pwptr->pw_uid = pw->pw_uid; + pwptr->pw_gid = pw->pw_gid; +#ifdef HAVE_PW_CHANGE + pwptr->pw_change = pw->pw_change; +#endif +#ifdef HAVE_PW_EXPIRE + pwptr->pw_expire = pw->pw_expire; +#endif + + cp = buf; + + /* copy official name */ + n = strlen(pw->pw_name) + 1; + strcpy(cp, pw->pw_name); + pwptr->pw_name = cp; + cp += n; + + /* copy password */ + n = strlen(pw->pw_passwd) + 1; + strcpy(cp, pw->pw_passwd); + pwptr->pw_passwd = cp; + cp += n; + +#ifdef HAVE_PW_CLASS + /* copy class */ + n = strlen(pw->pw_class) + 1; + strcpy(cp, pw->pw_class); + pwptr->pw_class = cp; + cp += n; +#endif + + /* copy gecos */ + n = strlen(pw->pw_gecos) + 1; + strcpy(cp, pw->pw_gecos); + pwptr->pw_gecos = cp; + cp += n; + + /* copy directory */ + n = strlen(pw->pw_dir) + 1; + strcpy(cp, pw->pw_dir); + pwptr->pw_dir = cp; + cp += n; + + /* copy login shell */ + n = strlen(pw->pw_shell) + 1; + strcpy(cp, pw->pw_shell); + pwptr->pw_shell = cp; + cp += n; + + return (0); +} +#else /* PASS_R_RETURN */ + static int getpwent_r_unknown_system = 0; +#endif /* PASS_R_RETURN */ +#endif /* !def(_REENTRANT) || !def(DO_PTHREADS) || !def(WANT_IRS_PW) */ diff --git a/usr/src/lib/libresolv2/common/irs/getservent.c b/usr/src/lib/libresolv2/common/irs/getservent.c new file mode 100644 index 0000000000..395aa2aba6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getservent.c @@ -0,0 +1,200 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getservent.c,v 1.17 2001/11/01 07:33:16 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + +/* Public */ + +struct servent * +getservent(void) { + struct net_data *net_data = init(); + + return (getservent_p(net_data)); +} + +struct servent * +getservbyname(const char *name, const char *proto) { + struct net_data *net_data = init(); + + return (getservbyname_p(name, proto, net_data)); +} + +struct servent * +getservbyport(int port, const char *proto) { + struct net_data *net_data = init(); + + return (getservbyport_p(port, proto, net_data)); +} + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +setservent(int stayopen) { + struct net_data *net_data = init(); + + setservent_p(stayopen, net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + +#ifdef ORIGINAL_ISC_CODE +void +#else +int +#endif +endservent() { + struct net_data *net_data = init(); + + endservent_p(net_data); +#ifdef ORIGINAL_ISC_CODE +#else + return (0); +#endif +} + +/* Shared private. */ + +struct servent * +getservent_p(struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + net_data->sv_last = (*sv->next)(sv); + return (net_data->sv_last); +} + +struct servent * +getservbyname_p(const char *name, const char *proto, + struct net_data *net_data) { + struct irs_sv *sv; + char **sap; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + if (net_data->sv_stayopen && net_data->sv_last) + if (!proto || !strcmp(net_data->sv_last->s_proto, proto)) { + if (!strcmp(net_data->sv_last->s_name, name)) + return (net_data->sv_last); + for (sap = net_data->sv_last->s_aliases; + sap && *sap; sap++) + if (!strcmp(name, *sap)) + return (net_data->sv_last); + } + net_data->sv_last = (*sv->byname)(sv, name, proto); + if (!net_data->sv_stayopen) + endservent(); + return (net_data->sv_last); +} + +struct servent * +getservbyport_p(int port, const char *proto, struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + if (net_data->sv_stayopen && net_data->sv_last) + if (port == net_data->sv_last->s_port && + ( !proto || + !strcmp(net_data->sv_last->s_proto, proto))) + return (net_data->sv_last); + net_data->sv_last = (*sv->byport)(sv, port, proto); + return (net_data->sv_last); +} + +void +setservent_p(int stayopen, struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return; + (*sv->rewind)(sv); + net_data->sv_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endservent_p(struct net_data *net_data) { + struct irs_sv *sv; + + if ((net_data != NULL) && ((sv = net_data->sv) != NULL)) + (*sv->minimize)(sv); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->sv) { + net_data->sv = (*net_data->irs->sv_map)(net_data->irs); + + if (!net_data->sv || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->sv->res_set)(net_data->sv, net_data->res, NULL); + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/usr/src/lib/libresolv2/common/irs/getservent_r.c b/usr/src/lib/libresolv2/common/irs/getservent_r.c new file mode 100644 index 0000000000..8548a85bba --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/getservent_r.c @@ -0,0 +1,244 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1998-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getservent_r.c,v 8.5 2001/11/01 08:02:16 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getservent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/param.h> +#include <port_after.h> + +#ifdef SERV_R_RETURN + +static SERV_R_RETURN +copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS); + +SERV_R_RETURN +getservbyname_r(const char *name, const char *proto, + struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservbyname(name, proto); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +SERV_R_RETURN +getservbyport_r(int port, const char *proto, + struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservbyport(port, proto); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +/* + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +SERV_R_RETURN +getservent_r(struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservent(); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +SERV_R_SET_RETURN +#ifdef SERV_R_ENT_ARGS +setservent_r(int stay_open, SERV_R_ENT_ARGS) +#else +setservent_r(int stay_open) +#endif +{ + + setservent(stay_open); +#ifdef SERV_R_SET_RESULT + return (SERV_R_SET_RESULT); +#endif +} + +SERV_R_END_RETURN +#ifdef SERV_R_ENT_ARGS +endservent_r(SERV_R_ENT_ARGS) +#else +endservent_r() +#endif +{ + + endservent(); + SERV_R_END_RESULT(SERV_R_OK); +} + +/* Private */ + +#ifndef SERVENT_DATA +static SERV_R_RETURN +copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; se->s_aliases[i]; i++, numptr++) { + len += strlen(se->s_aliases[i]) + 1; + } + len += strlen(se->s_name) + 1; + len += strlen(se->s_proto) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (SERV_R_BAD); + } + + /* copy port value */ + sptr->s_port = se->s_port; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(se->s_name) + 1; + strcpy(cp, se->s_name); + sptr->s_name = cp; + cp += n; + + /* copy aliases */ + sptr->s_aliases = (char **)ALIGN(buf); + for (i = 0 ; se->s_aliases[i]; i++) { + n = strlen(se->s_aliases[i]) + 1; + strcpy(cp, se->s_aliases[i]); + sptr->s_aliases[i] = cp; + cp += n; + } + sptr->s_aliases[i] = NULL; + + /* copy proto */ + n = strlen(se->s_proto) + 1; + strcpy(cp, se->s_proto); + sptr->s_proto = cp; + cp += n; + + return (SERV_R_OK); +} +#else /* !SERVENT_DATA */ +static int +copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy port value */ + sptr->s_port = se->s_port; + + /* copy official name */ + cp = ndptr->line; + eob = ndptr->line + sizeof(ndptr->line); + if ((n = strlen(se->s_name) + 1) < (eob - cp)) { + strcpy(cp, se->s_name); + sptr->s_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + sptr->s_aliases = ndptr->serv_aliases; + while (se->s_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(se->s_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, se->s_aliases[i]); + sptr->s_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + sptr->s_aliases[i] = NULL; + + /* copy proto */ + if ((n = strlen(se->s_proto) + 1) < (eob - cp)) { + strcpy(cp, se->s_proto); + sptr->s_proto = cp; + cp += n; + } else { + return (-1); + } + + return (SERV_R_OK); +} +#endif /* !SERVENT_DATA */ +#else /*SERV_R_RETURN */ + static int getservent_r_unknown_system = 0; +#endif /*SERV_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ diff --git a/usr/src/lib/libresolv2/common/irs/hesiod.c b/usr/src/lib/libresolv2/common/irs/hesiod.c new file mode 100644 index 0000000000..74c76bb879 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/hesiod.c @@ -0,0 +1,535 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: hesiod.c,v 1.23 2002/07/18 02:07:45 marka Exp $"; +#endif + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. + */ + +/* + * hesiod.c --- the core portion of the hesiod resolver. + * + * This file is derived from the hesiod library from Project Athena; + * It has been extensively rewritten by Theodore Ts'o to have a more + * thread-safe interface. + */ + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#include "pathnames.h" +#include "hesiod.h" +#include "hesiod_p.h" + +/* Forward */ + +int hesiod_init(void **context); +void hesiod_end(void *context); +char * hesiod_to_bind(void *context, const char *name, + const char *type); +char ** hesiod_resolve(void *context, const char *name, + const char *type); +void hesiod_free_list(void *context, char **list); + +static int parse_config_file(struct hesiod_p *ctx, const char *filename); +static char ** get_txt_records(struct hesiod_p *ctx, int class, + const char *name); +static int init(struct hesiod_p *ctx); + +/* Public */ + +/* + * This function is called to initialize a hesiod_p. + */ +int +hesiod_init(void **context) { + struct hesiod_p *ctx; + char *cp; + + ctx = malloc(sizeof(struct hesiod_p)); + if (ctx == 0) { + errno = ENOMEM; + return (-1); + } + +#ifdef ORIGINAL_ISC_CODE + ctx->LHS = NULL; + ctx->RHS = NULL; + ctx->res = NULL; +#else + memset(ctx, 0, sizeof (*ctx)); +#endif /* ORIGINAL_ISC_CODE */ + + if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) { +#ifdef DEF_RHS + /* + * Use compiled in defaults. + */ + ctx->LHS = malloc(strlen(DEF_LHS)+1); + ctx->RHS = malloc(strlen(DEF_RHS)+1); + if (ctx->LHS == 0 || ctx->RHS == 0) { + errno = ENOMEM; + goto cleanup; + } +#ifdef HAVE_STRLCPY + strlcpy(ctx->LHS, DEF_LHS, strlen(DEF_LHS) + 1); + strlcpy(ctx->RHS, DEF_RHS, strlen(DEF_RHS) + 1); +#else + strcpy(ctx->LHS, DEF_LHS); + strcpy(ctx->RHS, DEF_RHS); +#endif +#else + goto cleanup; +#endif + } + /* + * The default RHS can be overridden by an environment + * variable. + */ + if ((cp = getenv("HES_DOMAIN")) != NULL) { + size_t RHSlen = strlen(cp) + 2; + if (ctx->RHS) + free(ctx->RHS); + ctx->RHS = malloc(RHSlen); + if (!ctx->RHS) { + errno = ENOMEM; + goto cleanup; + } + if (cp[0] == '.') { +#ifdef HAVE_STRLCPY + strlcpy(ctx->RHS, cp, RHSlen); +#else + strcpy(ctx->RHS, cp); +#endif + } else { +#ifdef HAVE_STRLCPY + strlcpy(ctx->RHS, ".", RHSlen); +#else + strcpy(ctx->RHS, "."); +#endif +#ifdef HAVE_STRLCAT + strlcat(ctx->RHS, cp, RHSlen); +#else + strcat(ctx->RHS, cp); +#endif + } + } + + /* + * If there is no default hesiod realm set, we return an + * error. + */ + if (!ctx->RHS) { + errno = ENOEXEC; + goto cleanup; + } + +#if 0 + if (res_ninit(ctx->res) < 0) + goto cleanup; +#endif + + *context = ctx; + return (0); + + cleanup: + hesiod_end(ctx); + return (-1); +} + +/* + * This function deallocates the hesiod_p + */ +void +hesiod_end(void *context) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + int save_errno = errno; + + if (ctx->res) + res_nclose(ctx->res); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + if (ctx->res && ctx->free_res) + (*ctx->free_res)(ctx->res); + free(ctx); + errno = save_errno; +} + +/* + * This function takes a hesiod (name, type) and returns a DNS + * name which is to be resolved. + */ +char * +hesiod_to_bind(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname; + char **rhs_list = NULL; + const char *RHS, *cp; + + /* Decide what our RHS is, and set cp to the end of the actual name. */ + if ((cp = strchr(name, '@')) != NULL) { + if (strchr(cp + 1, '.')) + RHS = cp + 1; + else if ((rhs_list = hesiod_resolve(context, cp + 1, + "rhs-extension")) != NULL) + RHS = *rhs_list; + else { + errno = ENOENT; + return (NULL); + } + } else { + RHS = ctx->RHS; + cp = name + strlen(name); + } + + /* + * Allocate the space we need, including up to three periods and + * the terminating NUL. + */ + if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) + + (ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) { + errno = ENOMEM; + if (rhs_list) + hesiod_free_list(context, rhs_list); + return NULL; + } + + /* Now put together the DNS name. */ + memcpy(bindname, name, cp - name); + bindname[cp - name] = '\0'; + strcat(bindname, "."); + strcat(bindname, type); + if (ctx->LHS) { + if (ctx->LHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, ctx->LHS); + } + if (RHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, RHS); + + if (rhs_list) + hesiod_free_list(context, rhs_list); + + return (bindname); +} + +/* + * This is the core function. Given a hesiod (name, type), it + * returns an array of strings returned by the resolver. + */ +char ** +hesiod_resolve(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname = hesiod_to_bind(context, name, type); + char **retvec; + + if (bindname == NULL) + return (NULL); + if (init(ctx) == -1) { + free(bindname); + return (NULL); + } + + if ((retvec = get_txt_records(ctx, C_IN, bindname))) { + free(bindname); + return (retvec); + } + + if (errno != ENOENT) + return (NULL); + + retvec = get_txt_records(ctx, C_HS, bindname); + free(bindname); + return (retvec); +} + +void +hesiod_free_list(void *context, char **list) { + char **p; + + UNUSED(context); + + for (p = list; *p; p++) + free(*p); + free(list); +} + +/* + * This function parses the /etc/hesiod.conf file + */ +static int +parse_config_file(struct hesiod_p *ctx, const char *filename) { + char *key, *data, *cp, **cpp; + char buf[MAXDNAME+7]; + FILE *fp; + + /* + * Clear the existing configuration variable, just in case + * they're set. + */ + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + + /* + * Now open and parse the file... + */ + if (!(fp = fopen(filename, "r"))) + return (-1); + + while (fgets(buf, sizeof(buf), fp) != NULL) { + cp = buf; + if (*cp == '#' || *cp == '\n' || *cp == '\r') + continue; + while(*cp == ' ' || *cp == '\t') + cp++; + key = cp; + while(*cp != ' ' && *cp != '\t' && *cp != '=') + cp++; + *cp++ = '\0'; + + while(*cp == ' ' || *cp == '\t' || *cp == '=') + cp++; + data = cp; + while(*cp != ' ' && *cp != '\n' && *cp != '\r') + cp++; + *cp++ = '\0'; + + if (strcmp(key, "lhs") == 0) + cpp = &ctx->LHS; + else if (strcmp(key, "rhs") == 0) + cpp = &ctx->RHS; + else + continue; + + *cpp = malloc(strlen(data) + 1); + if (!*cpp) { + errno = ENOMEM; + goto cleanup; + } + strcpy(*cpp, data); + } + fclose(fp); + return (0); + + cleanup: + fclose(fp); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + return (-1); +} + +/* + * Given a DNS class and a DNS name, do a lookup for TXT records, and + * return a list of them. + */ +static char ** +get_txt_records(struct hesiod_p *ctx, int class, const char *name) { + struct { + int type; /* RR type */ + int class; /* RR class */ + int dlen; /* len of data section */ + u_char *data; /* pointer to data */ + } rr; + HEADER *hp; + u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; + u_char *cp, *erdata, *eom; + char *dst, *edst, **list; + int ancount, qdcount; + int i, j, n, skip; + + /* + * Construct the query and send it. + */ + n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0, + NULL, qbuf, MAX_HESRESP); + if (n < 0) { + errno = EMSGSIZE; + return (NULL); + } + n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP); + if (n < 0) { + errno = ECONNREFUSED; + return (NULL); + } + if (n < HFIXEDSZ) { + errno = EMSGSIZE; + return (NULL); + } + + /* + * OK, parse the result. + */ + hp = (HEADER *) abuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + cp = abuf + sizeof(HEADER); + eom = abuf + n; + + /* Skip query, trying to get to the answer section which follows. */ + for (i = 0; i < qdcount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0 || cp + skip + QFIXEDSZ > eom) { + errno = EMSGSIZE; + return (NULL); + } + cp += skip + QFIXEDSZ; + } + + list = malloc((ancount + 1) * sizeof(char *)); + if (!list) { + errno = ENOMEM; + return (NULL); + } + j = 0; + for (i = 0; i < ancount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0) { + errno = EMSGSIZE; + goto cleanup; + } + cp += skip; + if (cp + 3 * INT16SZ + INT32SZ > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.type = ns_get16(cp); + cp += INT16SZ; + rr.class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* skip the ttl, too */ + rr.dlen = ns_get16(cp); + cp += INT16SZ; + if (cp + rr.dlen > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.data = cp; + cp += rr.dlen; + if (rr.class != class || rr.type != T_TXT) + continue; + if (!(list[j] = malloc(rr.dlen))) + goto cleanup; + dst = list[j++]; + edst = dst + rr.dlen; + erdata = rr.data + rr.dlen; + cp = rr.data; + while (cp < erdata) { + n = (unsigned char) *cp++; + if (cp + n > eom || dst + n > edst) { + errno = EMSGSIZE; + goto cleanup; + } + memcpy(dst, cp, n); + cp += n; + dst += n; + } + if (cp != erdata) { + errno = EMSGSIZE; + goto cleanup; + } + *dst = '\0'; + } + list[j] = NULL; + if (j == 0) { + errno = ENOENT; + goto cleanup; + } + return (list); + + cleanup: + for (i = 0; i < j; i++) + free(list[i]); + free(list); + return (NULL); +} + +struct __res_state * +__hesiod_res_get(void *context) { + struct hesiod_p *ctx = context; + + if (!ctx->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + __hesiod_res_set(ctx, res, free); + } + + return (ctx->res); +} + +void +__hesiod_res_set(void *context, struct __res_state *res, + void (*free_res)(void *)) { + struct hesiod_p *ctx = context; + + if (ctx->res && ctx->free_res) { + res_nclose(ctx->res); + (*ctx->free_res)(ctx->res); + } + + ctx->res = res; + ctx->free_res = free_res; +} + +static int +init(struct hesiod_p *ctx) { + + if (!ctx->res && !__hesiod_res_get(ctx)) + return (-1); + + if (((ctx->res->options & RES_INIT) == 0) && + (res_ninit(ctx->res) == -1)) + return (-1); + + return (0); +} diff --git a/usr/src/lib/libresolv2/common/irs/hesiod_p.h b/usr/src/lib/libresolv2/common/irs/hesiod_p.h new file mode 100644 index 0000000000..7a9b68bc35 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/hesiod_p.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. + */ + +/* + * $Id: hesiod_p.h,v 1.9 1999/01/08 19:24:39 vixie Exp $ + */ + +/* + * hesiod_p.h -- private definitions for the hesiod library + */ + +#ifndef _HESIOD_P_H_INCLUDED +#define _HESIOD_P_H_INCLUDED + +#define DEF_RHS ".Athena.MIT.EDU" /* Defaults if HESIOD_CONF */ +#define DEF_LHS ".ns" /* file is not */ + /* present. */ +struct hesiod_p { + char * LHS; /* normally ".ns" */ + char * RHS; /* AKA the default hesiod domain */ + struct __res_state * res; /* resolver context */ + void (*free_res)(void *); + void (*res_set)(struct hesiod_p *, struct __res_state *, + void (*)(void *)); + struct __res_state * (*res_get)(struct hesiod_p *); +}; + +#define MAX_HESRESP 1024 + +#endif /*_HESIOD_P_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2/common/irs/irp.c b/usr/src/lib/libresolv2/common/irs/irp.c new file mode 100644 index 0000000000..ceb17b735c --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp.c @@ -0,0 +1,599 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irp.c,v 8.8 2001/09/25 04:50:29 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <stdarg.h> +#include <fcntl.h> +#include <syslog.h> +#include <ctype.h> +#include <unistd.h> + +#include <isc/memcluster.h> + +#include <irs.h> +#include <irp.h> + +#include "irs_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void irp_close(struct irs_acc *); + +#define LINEINCR 128 + +#if !defined(SUN_LEN) +#define SUN_LEN(su) \ + (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path)) +#endif + + +/* Public */ + + +/* send errors to syslog if true. */ +int irp_log_errors = 1; + +/* + * This module handles the irp module connection to irpd. + * + * The client expects a synchronous interface to functions like + * getpwnam(3), so we can't use the ctl_* i/o library on this end of + * the wire (it's used in the server). + */ + +/* + * irs_acc *irs_irp_acc(const char *options); + * + * Initialize the irp module. + */ +struct irs_acc * +irs_irp_acc(const char *options) { + struct irs_acc *acc; + struct irp_p *irp; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irp = memget(sizeof *irp))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + irp->inlast = 0; + irp->incurr = 0; + irp->fdCxn = -1; + acc->private = irp; + +#ifdef WANT_IRS_GR + acc->gr_map = irs_irp_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_irp_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_irp_sv; + acc->pr_map = irs_irp_pr; + acc->ho_map = irs_irp_ho; + acc->nw_map = irs_irp_nw; + acc->ng_map = irs_irp_ng; + acc->close = irp_close; + return (acc); +} + + +int +irs_irp_connection_setup(struct irp_p *cxndata, int *warned) { + if (irs_irp_is_connected(cxndata)) { + return (0); + } else if (irs_irp_connect(cxndata) != 0) { + if (warned != NULL && !*warned) { + syslog(LOG_ERR, "irpd connection failed: %m\n"); + (*warned)++; + } + + return (-1); + } + + return (0); +} + + +/* + * int irs_irp_connect(void); + * + * Sets up the connection to the remote irpd server. + * + * Returns: + * + * 0 on success, -1 on failure. + * + */ +int +irs_irp_connect(struct irp_p *pvt) { + int flags; + struct sockaddr *addr; + struct sockaddr_in iaddr; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un uaddr; +#endif + long ipaddr; + const char *irphost; + int code; + char text[256]; + int socklen = 0; + + if (pvt->fdCxn != -1) { + perror("fd != 1"); + return (-1); + } + +#ifndef NO_SOCKADDR_UN + memset(&uaddr, 0, sizeof uaddr); +#endif + memset(&iaddr, 0, sizeof iaddr); + + irphost = getenv(IRPD_HOST_ENV); + if (irphost == NULL) { + irphost = "127.0.0.1"; + } + +#ifndef NO_SOCKADDR_UN + if (irphost[0] == '/') { + addr = (struct sockaddr *)&uaddr; + strncpy(uaddr.sun_path, irphost, sizeof uaddr.sun_path); + uaddr.sun_family = AF_UNIX; + socklen = SUN_LEN(&uaddr); +#ifdef HAVE_SA_LEN + uaddr.sun_len = socklen; +#endif + } else +#endif + { + if (inet_pton(AF_INET, irphost, &ipaddr) != 1) { + errno = EADDRNOTAVAIL; + perror("inet_pton"); + return (-1); + } + + addr = (struct sockaddr *)&iaddr; + socklen = sizeof iaddr; +#ifdef HAVE_SA_LEN + iaddr.sin_len = socklen; +#endif + iaddr.sin_family = AF_INET; + iaddr.sin_port = htons(IRPD_PORT); + iaddr.sin_addr.s_addr = ipaddr; + } + + + pvt->fdCxn = socket(addr->sa_family, SOCK_STREAM, PF_UNSPEC); + if (pvt->fdCxn < 0) { + perror("socket"); + return (-1); + } + + if (connect(pvt->fdCxn, addr, socklen) != 0) { + perror("connect"); + return (-1); + } + + flags = fcntl(pvt->fdCxn, F_GETFL, 0); + if (flags < 0) { + close(pvt->fdCxn); + perror("close"); + return (-1); + } + +#if 0 + flags |= O_NONBLOCK; + if (fcntl(pvt->fdCxn, F_SETFL, flags) < 0) { + close(pvt->fdCxn); + perror("fcntl"); + return (-1); + } +#endif + + code = irs_irp_read_response(pvt, text, sizeof text); + if (code != IRPD_WELCOME_CODE) { + if (irp_log_errors) { + syslog(LOG_WARNING, "Connection failed: %s", text); + } + irs_irp_disconnect(pvt); + return (-1); + } + + return (0); +} + + + +/* + * int irs_irp_is_connected(struct irp_p *pvt); + * + * Returns: + * + * Non-zero if streams are setup to remote. + * + */ + +int +irs_irp_is_connected(struct irp_p *pvt) { + return (pvt->fdCxn >= 0); +} + + + +/* + * void + * irs_irp_disconnect(struct irp_p *pvt); + * + * Closes streams to remote. + */ + +void +irs_irp_disconnect(struct irp_p *pvt) { + if (pvt->fdCxn != -1) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + } +} + + + +int +irs_irp_read_line(struct irp_p *pvt, char *buffer, int len) { + char *realstart = &pvt->inbuffer[0]; + char *p, *start, *end; + int spare; + int i; + int buffpos = 0; + int left = len - 1; + + while (left > 0) { + start = p = &pvt->inbuffer[pvt->incurr]; + end = &pvt->inbuffer[pvt->inlast]; + + while (p != end && *p != '\n') + p++; + + if (p == end) { + /* Found no newline so shift data down if necessary + * and append new data to buffer + */ + if (start > realstart) { + memmove(realstart, start, end - start); + pvt->inlast = end - start; + start = realstart; + pvt->incurr = 0; + end = &pvt->inbuffer[pvt->inlast]; + } + + spare = sizeof (pvt->inbuffer) - pvt->inlast; + + p = end; + i = read(pvt->fdCxn, end, spare); + if (i < 0) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + return (buffpos > 0 ? buffpos : -1); + } else if (i == 0) { + return (buffpos); + } + + end += i; + pvt->inlast += i; + + while (p != end && *p != '\n') + p++; + } + + if (p == end) { + /* full buffer and still no newline */ + i = sizeof pvt->inbuffer; + } else { + /* include newline */ + i = p - start + 1; + } + + if (i > left) + i = left; + memcpy(buffer + buffpos, start, i); + pvt->incurr += i; + buffpos += i; + buffer[buffpos] = '\0'; + + if (p != end) { + left = 0; + } else { + left -= i; + } + } + +#if 0 + fprintf(stderr, "read line: %s\n", buffer); +#endif + return (buffpos); +} + + + + + +/* + * int irp_read_response(struct irp_p *pvt); + * + * Returns: + * + * The number found at the beginning of the line read from + * FP. 0 on failure(0 is not a legal response code). The + * rest of the line is discarded. + * + */ + +int +irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen) { + char line[1024]; + int code; + char *p; + + if (irs_irp_read_line(pvt, line, sizeof line) <= 0) { + return (0); + } + + p = strchr(line, '\n'); + if (p == NULL) { + return (0); + } + + if (sscanf(line, "%d", &code) != 1) { + code = 0; + } else if (text != NULL && textlen > 0) { + p = line; + while (isspace((unsigned char)*p)) p++; + while (isdigit((unsigned char)*p)) p++; + while (isspace((unsigned char)*p)) p++; + strncpy(text, p, textlen - 1); + p[textlen - 1] = '\0'; + } + + return (code); +} + + + +/* + * char *irp_read_body(struct irp_p *pvt, size_t *size); + * + * Read in the body of a response. Terminated by a line with + * just a dot on it. Lines should be terminated with a CR-LF + * sequence, but we're nt piccky if the CR is missing. + * No leading dot escaping is done as the protcol doesn't + * use leading dots anywhere. + * + * Returns: + * + * Pointer to null-terminated buffer allocated by memget. + * *SIZE is set to the length of the buffer. + * + */ + +char * +irs_irp_read_body(struct irp_p *pvt, size_t *size) { + char line[1024]; + u_int linelen; + size_t len = LINEINCR; + char *buffer = memget(len); + int idx = 0; + + for (;;) { + if (irs_irp_read_line(pvt, line, sizeof line) <= 0 || + strchr(line, '\n') == NULL) + goto death; + + linelen = strlen(line); + + if (line[linelen - 1] != '\n') + goto death; + + /* We're not strict about missing \r. Should we be?? */ + if (linelen > 2 && line[linelen - 2] == '\r') { + line[linelen - 2] = '\n'; + line[linelen - 1] = '\0'; + linelen--; + } + + if (linelen == 2 && line[0] == '.') { + *size = len; + buffer[idx] = '\0'; + + return (buffer); + } + + if (linelen > (len - (idx + 1))) { + char *p = memget(len + LINEINCR); + + if (p == NULL) + goto death; + memcpy(p, buffer, len); + memput(buffer, len); + buffer = p; + len += LINEINCR; + } + + memcpy(buffer + idx, line, linelen); + idx += linelen; + } + death: + memput(buffer, len); + return (NULL); +} + + +/* + * int irs_irp_get_full_response(struct irp_p *pvt, int *code, + * char **body, size_t *bodylen); + * + * Gets the response to a command. If the response indicates + * there's a body to follow(code % 10 == 1), then the + * body buffer is allcoated with memget and stored in + * *BODY. The length of the allocated body buffer is stored + * in *BODY. The caller must give the body buffer back to + * memput when done. The results code is stored in *CODE. + * + * Returns: + * + * 0 if a result was read. -1 on some sort of failure. + * + */ + +int +irs_irp_get_full_response(struct irp_p *pvt, int *code, char *text, + size_t textlen, char **body, size_t *bodylen) { + int result = irs_irp_read_response(pvt, text, textlen); + + *body = NULL; + + if (result == 0) { + return (-1); + } + + *code = result; + + /* Code that matches 2xx is a good result code. + * Code that matches xx1 means there's a response body coming. + */ + if ((result / 100) == 2 && (result % 10) == 1) { + *body = irs_irp_read_body(pvt, bodylen); + if (*body == NULL) { + return (-1); + } + } + + return (0); +} + + +/* + * int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...); + * + * Sends command to remote connected via the PVT + * struture. FMT and args after it are fprintf-like + * arguments for formatting. + * + * Returns: + * + * 0 on success, -1 on failure. + */ + +int +irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) { + va_list ap; + char buffer[1024]; + int pos = 0; + int i, todo; + + + if (pvt->fdCxn < 0) { + return (-1); + } + + va_start(ap, fmt); + todo = vsprintf(buffer, fmt, ap); + va_end(ap); + if (todo > (int)sizeof(buffer) - 3) { + syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()"); + exit(1); + } + strcat(buffer, "\r\n"); + todo = strlen(buffer); + + while (todo > 0) { + i = write(pvt->fdCxn, buffer + pos, todo); +#if 0 + /* XXX brister */ + fprintf(stderr, "Wrote: \""); + fwrite(buffer + pos, sizeof (char), todo, stderr); + fprintf(stderr, "\"\n"); +#endif + if (i < 0) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + return (-1); + } + todo -= i; + } + + return (0); +} + + +/* Methods */ + + + +/* + * void irp_close(struct irs_acc *this) + * + */ + +static void +irp_close(struct irs_acc *this) { + struct irp_p *irp = (struct irp_p *)this->private; + + if (irp != NULL) { + irs_irp_disconnect(irp); + memput(irp, sizeof *irp); + } + + memput(this, sizeof *this); +} + + + diff --git a/usr/src/lib/libresolv2/common/irs/irp_gr.c b/usr/src/lib/libresolv2/common/irs/irp_gr.c new file mode 100644 index 0000000000..e77468af7e --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp_gr.c @@ -0,0 +1,415 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Portions Copyright(c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_gr.c,v 8.3 2001/05/29 05:48:57 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_gr_unneeded; +#else + +#include <syslog.h> +#include <sys/param.h> +#include <sys/types.h> + +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/memcluster.h> +#include <isc/irpmarshall.h> + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +/* Types. */ + +/* + * Module for the getnetgrent(3) family to use when connected to a + * remote irp daemon. + * + * See irpd.c for justification of caching done here. + * + */ + +struct pvt { + struct irp_p *girpdata; /* global IRP data */ + int warned; + struct group group; +}; + +/* Forward. */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +/* Private */ +static void free_group(struct group *gr); + + +/* Public. */ + + + + + +/* + * struct irs_gr * irs_irp_gr(struct irs_acc *this) + * + * Notes: + * + * Initialize the group sub-module. + * + * Notes: + * + * Module data. + * + */ + +struct irs_gr * +irs_irp_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x0, sizeof *gr); + + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0x0, sizeof *pvt); + pvt->girpdata = this->private; + + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + return (gr); +} + +/* Methods. */ + + + +/* + * void gr_close(struct irs_gr *this) + * + * Notes: + * + * Close the sub-module. + * + */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + gr_minimize(this); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct group * gr_next(struct irs_gr *this) + * + * Notes: + * + * Gets the next group out of the cached data and returns it. + * + */ + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + if (irp_log_errors) { + syslog(LOG_WARNING, "getgrent failed: %s", text); + } + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + + +/* + * struct group * gr_byname(struct irs_gr *this, const char *name) + * + * Notes: + * + * Gets a group by name from irpd and returns it. + * + */ + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + + if (gr->gr_name != NULL && strcmp(name, gr->gr_name) == 0) { + return (gr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrnam %s", name) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + + +/* + * struct group * gr_bygid(struct irs_gr *this, gid_t gid) + * + * Notes: + * + * Gets a group by gid from irpd and returns it. + * + */ + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *gr = &pvt->group; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (gr->gr_name != NULL && (gid_t)gr->gr_gid == gid) { + return (gr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getgrgid %d", gid) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETGROUP_OK) { + free_group(gr); + if (irp_unmarshall_gr(gr, body) != 0) { + gr = NULL; + } + } else { + gr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (gr); +} + + + + +/* + * void gr_rewind(struct irs_gr *this) + * + */ + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setgrent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETGROUP_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setgrent failed: %s", text); + } + } + + return; +} + + + + +/* + * void gr_minimize(struct irs_gr *this) + * + * Notes: + * + * Frees up cached data and disconnects(if necessary) from the remote. + * + */ + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free_group(&pvt->group); + irs_irp_disconnect(pvt->girpdata); +} + +/* Private. */ + + + +/* + * static void free_group(struct group *gr); + * + * Deallocate all the memory irp_unmarshall_gr allocated. + * + */ + +static void +free_group(struct group *gr) { + char **p; + + if (gr == NULL) + return; + + if (gr->gr_name != NULL) + free(gr->gr_name); + + if (gr->gr_passwd != NULL) + free(gr->gr_passwd); + + for (p = gr->gr_mem ; p != NULL && *p != NULL ; p++) + free(*p); + + if (gr->gr_mem) + free(gr->gr_mem); + + if (p != NULL) + free(p); +} + + +#endif /* WANT_IRS_GR */ diff --git a/usr/src/lib/libresolv2/common/irs/irp_ho.c b/usr/src/lib/libresolv2/common/irs/irp_ho.c new file mode 100644 index 0000000000..12a03edd1b --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp_ho.c @@ -0,0 +1,436 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Portions Copyright (c) 1996,1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_ho.c,v 8.3 2001/05/29 05:48:59 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/irpmarshall.h> +#include <isc/memcluster.h> + +#include "irs_p.h" +#include "dns_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + + +struct pvt { + struct irp_p *girpdata; + int warned; + struct hostent host; +}; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); + +static void free_host(struct hostent *ho); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +/* Public. */ + + + +/* + * struct irs_ho * irs_irp_ho(struct irs_acc *this) + * + * Notes: + * + * Initializes the irp_ho module. + * + */ + +struct irs_ho * +irs_irp_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(ho = memget(sizeof *ho))) { + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x0, sizeof *ho); + + if (!(pvt = memget(sizeof *pvt))) { + memput(ho, sizeof *ho); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->addrinfo = ho_addrinfo; + + return (ho); +} + +/* Methods. */ + + + +/* + * void ho_close(struct irs_ho *this) + * + * Notes: + * + * Closes down the module. + * + */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + + free_host(&pvt->host); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + +/* + * struct hostent * ho_byname(struct irs_ho *this, const char *name) + * + */ + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + return (ho_byname2(this, name, AF_INET)); +} + + + + + +/* + * struct hostent * ho_byname2(struct irs_ho *this, const char *name, int af) + * + */ + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body = NULL; + size_t bodylen; + int code; + char text[256]; + + if (ho->h_name != NULL && + strcmp(name, ho->h_name) == 0 && + af == ho->h_addrtype) { + return (ho); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostbyname2 %s %s", + name, ADDR_T_STR(af)) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + +/* + * struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + * int len, int af) + * + */ + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body = NULL; + size_t bodylen; + int code; + char **p; + char paddr[MAXPADDRSIZE]; + char text[256]; + + if (ho->h_name != NULL && + af == ho->h_addrtype && + len == ho->h_length) { + for (p = ho->h_addr_list ; *p != NULL ; p++) { + if (memcmp(*p, addr, len) == 0) + return (ho); + } + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (inet_ntop(af, addr, paddr, sizeof paddr) == NULL) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostbyaddr %s %s", + paddr, ADDR_T_STR(af)) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + + + +/* + * struct hostent * ho_next(struct irs_ho *this) + * + * Notes: + * + * The implementation for gethostent(3). The first time it's + * called all the data is pulled from the remote(i.e. what + * the maximum number of gethostent(3) calls would return) + * and that data is cached. + * + */ + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + + + +/* + * void ho_rewind(struct irs_ho *this) + * + */ + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "sethostent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETHOST_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "sethostent failed: %s", text); + } + } + + return; +} + + + + +/* + * void ho_minimize(struct irs_ho *this) + * + */ + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free_host(&pvt->host); + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* + * void free_host(struct hostent *ho) + * + */ + +static void +free_host(struct hostent *ho) { + char **p; + + if (ho == NULL) { + return; + } + + if (ho->h_name != NULL) + free(ho->h_name); + + if (ho->h_aliases != NULL) { + for (p = ho->h_aliases ; *p != NULL ; p++) + free(*p); + free(ho->h_aliases); + } + + if (ho->h_addr_list != NULL) { + for (p = ho->h_addr_list ; *p != NULL ; p++) + free(*p); + free(ho->h_addr_list); + } +} + +/* dummy */ +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + UNUSED(this); + UNUSED(name); + UNUSED(pai); + return(NULL); +} diff --git a/usr/src/lib/libresolv2/common/irs/irp_ng.c b/usr/src/lib/libresolv2/common/irs/irp_ng.c new file mode 100644 index 0000000000..d585e636a0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp_ng.c @@ -0,0 +1,279 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irp_ng.c,v 8.3 2001/05/29 05:49:00 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/memcluster.h> +#include <isc/irpmarshall.h> + +#include "irs_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Definitions */ + +struct pvt { + struct irp_p *girpdata; + int warned; +}; + + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, const char **, + const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + + +/* Public */ + + + +/* + * struct irs_ng * irs_irp_ng(struct irs_acc *this) + * + * Notes: + * + * Intialize the irp netgroup module. + * + */ + +struct irs_ng * +irs_irp_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + + + +/* + * void ng_close(struct irs_ng *this) + * + */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ng_minimize(this); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * void ng_rewind(struct irs_ng *this, const char *group) + * + * + */ + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, + "setnetgrent %s", group) != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETNETGR_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setnetgrent(%s) failed: %s", + group, text); + } + } + + return; +} + + + + +/* + * int ng_next(struct irs_ng *this, const char **host, const char **user, + * const char **domain) + * + * Notes: + * + * Get the next netgroup item from the cache. + * + */ + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + int code; + char *body = NULL; + size_t bodylen; + int rval = 0; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (0); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetgrent") != 0) + return (0); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (0); + } + + if (code == IRPD_GETNETGR_OK) { + if (irp_unmarshall_ng(host, user, domain, body) == 0) { + rval = 1; + } + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (rval); +} + + + +/* + * int ng_test(struct irs_ng *this, const char *name, const char *host, + * const char *user, const char *domain) + * + * Notes: + * + * Search for a match in a netgroup. + * + */ + +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + char *body = NULL; + size_t bodylen = 0; + int code; + char text[256]; + int rval = 0; + + UNUSED(name); + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (0); + } + + if (irp_marshall_ng(host, user, domain, &body, &bodylen) != 0) { + return (0); + } + + if (irs_irp_send_command(pvt->girpdata, "innetgr %s", body) == 0) { + memput(body, bodylen); + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code == IRPD_GETNETGR_MATCHES) { + rval = 1; + } + } + + return (rval); +} + + + + +/* + * void ng_minimize(struct irs_ng *this) + * + */ + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* Private */ + diff --git a/usr/src/lib/libresolv2/common/irs/irp_nw.c b/usr/src/lib/libresolv2/common/irs/irp_nw.c new file mode 100644 index 0000000000..7c18f4cbac --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp_nw.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Portions Copyright (c) 1996,1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_nw.c,v 8.1 1999/01/18 07:46:54 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#if 0 + +#endif + +/* Imports */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <fcntl.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/irpmarshall.h> + +#include <isc/memcluster.h> +#include <isc/misc.h> + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + struct irp_p *girpdata; + int warned; + struct nwent net; +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); + +static void free_nw(struct nwent *nw); + + +/* Public */ + + + +/* + * struct irs_nw * irs_irp_nw(struct irs_acc *this) + * + */ + +struct irs_nw * +irs_irp_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x0, sizeof *nw); + pvt->girpdata = this->private; + + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + return (nw); +} + +/* Methods */ + + + +/* + * void nw_close(struct irs_nw *this) + * + */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + free_nw(&pvt->net); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct nwent * nw_byaddr(struct irs_nw *this, void *net, + * int length, int type) + * + */ + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body = NULL; + size_t bodylen; + int code; + char paddr[24]; /* bigenough for ip4 w/ cidr spec. */ + char text[256]; + + if (inet_net_ntop(type, net, length, paddr, sizeof paddr) == NULL) { + return (NULL); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetbyaddr %s %s", + paddr, ADDR_T_STR(type)) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (nw); +} + + + + +/* + * struct nwent * nw_byname(struct irs_nw *this, const char *name, int type) + * + */ + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body = NULL; + size_t bodylen; + int code; + char text[256]; + + if (nw->n_name != NULL && + strcmp(name, nw->n_name) == 0 && + nw->n_addrtype == type) { + return (nw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetbyname %s", name) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (nw); +} + + + + +/* + * void nw_rewind(struct irs_nw *this) + * + */ + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setnetent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETNET_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setnetent failed: %s", text); + } + } + + return; +} + + + + + + +/* + * struct nwent * nw_next(struct irs_nw *this) + * + * Notes: + * + * Prepares the cache if necessary and returns the first, or + * next item from it. + */ + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + return (nw); +} + + + + + + +/* + * void nw_minimize(struct irs_nw *this) + * + */ + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* private. */ + + + +/* + * static void free_passwd(struct passwd *pw); + * + * deallocate all the memory irp_unmarshall_pw allocated. + * + */ + +static void +free_nw(struct nwent *nw) { + char **p; + + if (nw == NULL) + return; + + if (nw->n_name != NULL) + free(nw->n_name); + + if (nw->n_aliases != NULL) { + for (p = nw->n_aliases ; *p != NULL ; p++) { + free(*p); + } + free(nw->n_aliases); + } + + if (nw->n_addr != NULL) + free(nw->n_addr); +} diff --git a/usr/src/lib/libresolv2/common/irs/irp_p.h b/usr/src/lib/libresolv2/common/irs/irp_p.h new file mode 100644 index 0000000000..0527d85d8e --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp_p.h @@ -0,0 +1,66 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irp_p.h,v 8.3 2003/04/29 01:26:06 marka Exp $ + */ + +#ifndef _IRP_P_H_INCLUDED +#define _IRP_P_H_INCLUDED + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> + +struct irp_p { + char inbuffer[1024]; + int inlast; /* index of one past the last char in buffer */ + int incurr; /* index of the next char to be read from buffer */ + + int fdCxn; +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_irp_acc __P((const char *)); +extern struct irs_gr * irs_irp_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_irp_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_irp_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_irp_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_irp_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_irp_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_irp_ng __P((struct irs_acc *)); + +int irs_irp_connect(struct irp_p *pvt); +int irs_irp_is_connected(struct irp_p *pvt); +void irs_irp_disconnect(struct irp_p *pvt); +int irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen); +char *irs_irp_read_body(struct irp_p *pvt, size_t *size); +int irs_irp_get_full_response(struct irp_p *pvt, int *code, + char *text, size_t textlen, + char **body, size_t *bodylen); + +extern int irp_log_errors; + +#endif diff --git a/usr/src/lib/libresolv2/common/irs/irp_pr.c b/usr/src/lib/libresolv2/common/irs/irp_pr.c new file mode 100644 index 0000000000..e72f6c2fe4 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp_pr.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_pr.c,v 8.1 1999/01/18 07:46:54 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <netdb.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/memcluster.h> +#include <isc/irpmarshall.h> + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + struct irp_p *girpdata; + int warned; + struct protoent proto; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static void free_proto(struct protoent *pr); + +/* Public */ + + + +/* + * struct irs_pr * irs_irp_pr(struct irs_acc *this) + * + */ + +struct irs_pr * +irs_irp_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x0, sizeof *pr); + + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + return (pr); +} + +/* Methods */ + + + +/* + * void pr_close(struct irs_pr *this) + * + */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pr_minimize(this); + + free_proto(&pvt->proto); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + +/* + * struct protoent * pr_byname(struct irs_pr *this, const char *name) + * + */ + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body = NULL; + size_t bodylen; + int code; + int i; + char text[256]; + + if (pr->p_name != NULL && strcmp(name, pr->p_name) == 0) { + return (pr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + i = irs_irp_send_command(pvt->girpdata, "getprotobyname %s", name); + if (i != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + +/* + * struct protoent * pr_bynumber(struct irs_pr *this, int proto) + * + */ + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body = NULL; + size_t bodylen; + int code; + int i; + char text[256]; + + if (pr->p_name != NULL && proto == pr->p_proto) { + return (pr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + i = irs_irp_send_command(pvt->girpdata, "getprotobynumber %d", proto); + if (i != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + + +/* + * void pr_rewind(struct irs_pr *this) + * + */ + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setprotoent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETPROTO_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setprotoent failed: %s", text); + } + } + + return; +} + + + + +/* + * struct protoent * pr_next(struct irs_pr *this) + * + * Notes: + * + * Prepares the cache if necessary and returns the next item in it. + * + */ + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getprotoent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + + + + +/* + * void pr_minimize(struct irs_pr *this) + * + */ + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + + + +/* + * static void free_proto(struct protoent *pw); + * + * Deallocate all the memory irp_unmarshall_pr allocated. + * + */ + +static void +free_proto(struct protoent *pr) { + char **p; + + if (pr == NULL) + return; + + if (pr->p_name != NULL) + free(pr->p_name); + + for (p = pr->p_aliases ; p != NULL && *p != NULL ; p++) + free(*p); +} diff --git a/usr/src/lib/libresolv2/common/irs/irp_pw.c b/usr/src/lib/libresolv2/common/irs/irp_pw.c new file mode 100644 index 0000000000..aa6fcbcbce --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp_pw.c @@ -0,0 +1,365 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_pw.c,v 8.2 2001/11/01 07:29:26 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include <syslog.h> +#include <sys/param.h> + +#include <db.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <utmp.h> +#include <unistd.h> + +#include <irs.h> +#include <irp.h> +#include <isc/memcluster.h> +#include <isc/irpmarshall.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "irp_p.h" + + +/* Types */ + +struct pvt { + struct irp_p *girpdata; /* global IRP data */ + int warned; + struct passwd passwd; /* password structure */ +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static void free_passwd(struct passwd *pw); + +/* Public */ +struct irs_pw * +irs_irp_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0, sizeof *pw); + + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + + return (pw); +} + +/* Methods */ + + + +/* + * void pw_close(struct irs_pw *this) + * + */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pw_minimize(this); + + free_passwd(&pvt->passwd); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct passwd * pw_next(struct irs_pw *this) + * + */ + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *pw = &pvt->passwd; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * struct passwd * pw_byname(struct irs_pw *this, const char *name) + * + */ + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *pw = &pvt->passwd; + char *body = NULL; + char text[256]; + size_t bodylen; + int code; + + if (pw->pw_name != NULL && strcmp(name, pw->pw_name) == 0) { + return (pw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwnam %s", name) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * struct passwd * pw_byuid(struct irs_pw *this, uid_t uid) + * + */ + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + char *body; + char text[256]; + size_t bodylen; + int code; + struct passwd *pw = &pvt->passwd; + + if (pw->pw_name != NULL && pw->pw_uid == uid) { + return (pw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getpwuid %d", uid) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETUSER_OK) { + free_passwd(pw); + if (irp_unmarshall_pw(pw, body) != 0) { + pw = NULL; + } + } else { + pw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pw); +} + + + + +/* + * void pw_rewind(struct irs_pw *this) + * + */ + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setpwent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETUSER_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setpwent failed: %s", text); + } + } + + return; +} + + +/* + * void pw_minimize(struct irs_pw *this) + * + */ + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + +/* Private. */ + + + +/* + * static void free_passwd(struct passwd *pw); + * + * Deallocate all the memory irp_unmarshall_pw allocated. + * + */ + +static void +free_passwd(struct passwd *pw) { + if (pw == NULL) + return; + + if (pw->pw_name != NULL) + free(pw->pw_name); + + if (pw->pw_passwd != NULL) + free(pw->pw_passwd); + +#ifdef HAVE_PW_CLASS + if (pw->pw_class != NULL) + free(pw->pw_class); +#endif + + if (pw->pw_gecos != NULL) + free(pw->pw_gecos); + + if (pw->pw_dir != NULL) + free(pw->pw_dir); + + if (pw->pw_shell != NULL) + free(pw->pw_shell); +} + +#endif /* WANT_IRS_PW */ diff --git a/usr/src/lib/libresolv2/common/irs/irp_sv.c b/usr/src/lib/libresolv2/common/irs/irp_sv.c new file mode 100644 index 0000000000..144ae5a7fc --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irp_sv.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Portions Copyright (c) 1996,1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_sv.c,v 8.1 1999/01/18 07:46:54 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> + +#ifdef IRS_LCL_SV_DB +#include <db.h> +#endif +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/irpmarshall.h> +#include <isc/memcluster.h> + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Types */ + +struct pvt { + struct irp_p *girpdata; + int warned; + struct servent service; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static void free_service(struct servent *sv); + + + +/* Public */ + + + +/* + * struct irs_sv * irs_irp_sv(struct irs_acc *this) + * + */ + +struct irs_sv * +irs_irp_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if ((sv = memget(sizeof *sv)) == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x0, sizeof *sv); + + if ((pvt = memget(sizeof *pvt)) == NULL) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + + return (sv); +} + +/* Methods */ + + + +/* + * void sv_close(struct irs_sv *this) + * + */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + sv_minimize(this); + + free_service(&pvt->service); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * struct servent * sv_next(struct irs_sv *this) + * + * Notes: + * + * Fills the cache if necessary and returns the next item from it. + * + */ + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + +/* + * struct servent * sv_byname(struct irs_sv *this, const char *name, + * const char *proto) + * + */ + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + char text[256]; + size_t bodylen; + int code; + + if (sv->s_name != NULL && + strcmp(name, sv->s_name) == 0 && + strcasecmp(proto, sv->s_proto) == 0) { + return (sv); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s", + name, proto) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + +/* + * struct servent * sv_byport(struct irs_sv *this, int port, + * const char *proto) + * + */ + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + size_t bodylen; + char text[256]; + int code; + + if (sv->s_name != NULL && + port == sv->s_port && + strcasecmp(proto, sv->s_proto) == 0) { + return (sv); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s", + ntohs((short)port), proto) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + + + + + +/* + * void sv_rewind(struct irs_sv *this) + * + */ + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETSERVICE_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setservent failed: %s", text); + } + } + + return; +} + + + + + +/* + * void sv_minimize(struct irs_sv *this) + * + */ + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + + + +static void +free_service(struct servent *sv) { + char **p; + + if (sv == NULL) { + return; + } + + if (sv->s_name != NULL) { + free(sv->s_name); + } + + for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) { + free(*p); + } + + if (sv->s_proto != NULL) { + free(sv->s_proto); + } +} + + diff --git a/usr/src/lib/libresolv2/common/irs/irpmarshall.c b/usr/src/lib/libresolv2/common/irs/irpmarshall.c new file mode 100644 index 0000000000..dfeb984262 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irpmarshall.c @@ -0,0 +1,2351 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright(c) 1989, 1993, 1995 + * The 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. + */ + +/* + * Portions Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irpmarshall.c,v 8.7 2001/05/29 05:49:01 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#if 0 + +Check values are in approrpriate endian order. + +Double check memory allocations on unmarhsalling + +#endif + + +/* Extern */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <stdio.h> +#include <ctype.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <utmp.h> +#include <unistd.h> +#include <assert.h> +#include <errno.h> + +#include <irs.h> +#include <isc/memcluster.h> +#include <isc/irpmarshall.h> + +#include "port_after.h" + + +#ifndef HAVE_STRNDUP +static char *strndup(const char *str, size_t len); +#endif + +static char **splitarray(const char *buffer, const char *buffend, char delim); +static int joinarray(char * const * argv, char *buffer, char delim); +static char *getfield(char **res, size_t reslen, char **buffer, char delim); +static size_t joinlength(char * const *argv); +static void free_array(char **argv, size_t entries); + +#define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ + (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) + +#define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) + +static char COMMA = ','; + +static const char *COMMASTR = ","; +static const char *COLONSTR = ":"; + + + +/* See big comment at bottom of irpmarshall.h for description. */ + + +#ifdef WANT_IRS_PW +/* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) + * + * notes: + * + * See above + * + * return: + * + * 0 on sucess, -1 on failure. + * + */ + +int +irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) { + size_t need = 1 ; /* for null byte */ + char pwUid[24]; + char pwGid[24]; + char pwChange[24]; + char pwExpire[24]; + const char *pwClass; + const char *fieldsep = COLONSTR; + + if (pw == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(pwUid, "%ld", (long)pw->pw_uid); + sprintf(pwGid, "%ld", (long)pw->pw_gid); + +#ifdef HAVE_PW_CHANGE + sprintf(pwChange, "%ld", (long)pw->pw_change); +#else + pwChange[0] = '0'; + pwChange[1] = '\0'; +#endif + +#ifdef HAVE_PW_EXPIRE + sprintf(pwExpire, "%ld", (long)pw->pw_expire); +#else + pwExpire[0] = '0'; + pwExpire[1] = '\0'; +#endif + +#ifdef HAVE_PW_CLASS + pwClass = pw->pw_class; +#else + pwClass = ""; +#endif + + need += strlen(pw->pw_name) + 1; /* one for fieldsep */ + need += strlen(pw->pw_passwd) + 1; + need += strlen(pwUid) + 1; + need += strlen(pwGid) + 1; + need += strlen(pwClass) + 1; + need += strlen(pwChange) + 1; + need += strlen(pwExpire) + 1; + need += strlen(pw->pw_gecos) + 1; + need += strlen(pw->pw_dir) + 1; + need += strlen(pw->pw_shell) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, pw->pw_name); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_passwd); strcat(*buffer, fieldsep); + strcat(*buffer, pwUid); strcat(*buffer, fieldsep); + strcat(*buffer, pwGid); strcat(*buffer, fieldsep); + strcat(*buffer, pwClass); strcat(*buffer, fieldsep); + strcat(*buffer, pwChange); strcat(*buffer, fieldsep); + strcat(*buffer, pwExpire); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_gecos); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_dir); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_shell); strcat(*buffer, fieldsep); + + return (0); +} + + + + + +/* + * int irp_unmarshall_pw(struct passwd *pw, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure + * + */ + +int +irp_unmarshall_pw(struct passwd *pw, char *buffer) { + char *name, *pass, *class, *gecos, *dir, *shell; + uid_t pwuid; + gid_t pwgid; + time_t pwchange; + time_t pwexpire; + char *p; + long t; + char tmpbuf[24]; + char *tb = &tmpbuf[0]; + char fieldsep = ':'; + int myerrno = EINVAL; + + name = pass = class = gecos = dir = shell = NULL; + p = buffer; + + /* pw_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + /* pw_passwd field */ + pass = NULL; + if (getfield(&pass, 0, &p, fieldsep) == NULL) { /* field can be empty */ + goto error; + } + + + /* pw_uid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwuid = (uid_t)t; + if ((long) pwuid != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_gid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwgid = (gid_t)t; + if ((long)pwgid != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_class field */ + class = NULL; + if (getfield(&class, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_change field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwchange = (time_t)t; + if ((long)pwchange != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_expire field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + pwexpire = (time_t)t; + if ((long) pwexpire != t) { /* value must have been too big. */ + goto error; + } + + + + /* pw_gecos field */ + gecos = NULL; + if (getfield(&gecos, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_dir field */ + dir = NULL; + if (getfield(&dir, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_shell field */ + shell = NULL; + if (getfield(&shell, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + pw->pw_name = name; + pw->pw_passwd = pass; + pw->pw_uid = pwuid; + pw->pw_gid = pwgid; + pw->pw_gecos = gecos; + pw->pw_dir = dir; + pw->pw_shell = shell; + +#ifdef HAVE_PW_CHANGE + pw->pw_change = pwchange; +#endif +#ifdef HAVE_PW_CLASS + pw->pw_class = class; +#endif +#ifdef HAVE_PW_EXPIRE + pw->pw_expire = pwexpire; +#endif + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (pass != NULL) free(pass); + if (gecos != NULL) free(gecos); + if (dir != NULL) free(dir); + if (shell != NULL) free(shell); + + return (-1); +} + +/* ------------------------- struct passwd ------------------------- */ +#endif /* WANT_IRS_PW */ + + + +/* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) + * + * notes: + * + * see above. + * + * return: + * + * 0 on success, -1 on failure + */ + +int +irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char grGid[24]; + const char *fieldsep = COLONSTR; + + if (gr == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(grGid, "%ld", (long)gr->gr_gid); + + need += strlen(gr->gr_name) + 1; +#ifndef MISSING_GR_PASSWD + need += strlen(gr->gr_passwd) + 1; +#else + need++; +#endif + need += strlen(grGid) + 1; + need += joinlength(gr->gr_mem) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, gr->gr_name); strcat(*buffer, fieldsep); +#ifndef MISSING_GR_PASSWD + strcat(*buffer, gr->gr_passwd); +#endif + strcat(*buffer, fieldsep); + strcat(*buffer, grGid); strcat(*buffer, fieldsep); + joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep); + + return (0); +} + + + + +/* + * int irp_unmarshall_gr(struct group *gr, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_gr(struct group *gr, char *buffer) { + char *p, *q; + gid_t grgid; + long t; + char *name = NULL; + char *pass = NULL; + char **members = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (gr == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* gr_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* gr_passwd field */ + pass = NULL; + if (getfield(&pass, 0, &p, fieldsep) == NULL) { + goto error; + } + + + /* gr_gid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + grgid = (gid_t)t; + if ((long) grgid != t) { /* value must have been too big. */ + goto error; + } + + + /* gr_mem field. Member names are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + members = splitarray(p, q, COMMA); + if (members == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + gr->gr_name = name; +#ifndef MISSING_GR_PASSWD + gr->gr_passwd = pass; +#endif + gr->gr_gid = grgid; + gr->gr_mem = members; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (pass != NULL) free(pass); + + return (-1); +} + + +/* ------------------------- struct group ------------------------- */ + + + + +/* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char svPort[24]; + const char *fieldsep = COLONSTR; + short realport; + + if (sv == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + /* the int s_port field is actually a short in network order. We + want host order to make the marshalled data look correct */ + realport = ntohs((short)sv->s_port); + sprintf(svPort, "%d", realport); + + need += strlen(sv->s_name) + 1; + need += joinlength(sv->s_aliases) + 1; + need += strlen(svPort) + 1; + need += strlen(sv->s_proto) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, sv->s_name); strcat(*buffer, fieldsep); + joinarray(sv->s_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, svPort); strcat(*buffer, fieldsep); + strcat(*buffer, sv->s_proto); strcat(*buffer, fieldsep); + + return (0); +} + + + + + +/* + * int irp_unmarshall_sv(struct servent *sv, char *buffer) + * + * notes: + * + * see above + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_unmarshall_sv(struct servent *sv, char *buffer) { + char *p, *q; + short svport; + long t; + char *name = NULL; + char *proto = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (sv == NULL || buffer == NULL) + return (-1); + + p = buffer; + + + /* s_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* s_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* s_port field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + svport = (short)t; + if ((long) svport != t) { /* value must have been too big. */ + goto error; + } + svport = htons(svport); + + /* s_proto field */ + proto = NULL; + if (getfield(&proto, 0, &p, fieldsep) == NULL) { + goto error; + } + + sv->s_name = name; + sv->s_aliases = aliases; + sv->s_port = svport; + sv->s_proto = proto; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (proto != NULL) free(proto); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct servent ------------------------- */ + +/* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */ + + + +/* + * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) + * + * notes: + * + * see above + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char prProto[24]; + const char *fieldsep = COLONSTR; + + if (pr == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(prProto, "%d", (int)pr->p_proto); + + need += strlen(pr->p_name) + 1; + need += joinlength(pr->p_aliases) + 1; + need += strlen(prProto) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, pr->p_name); strcat(*buffer, fieldsep); + joinarray(pr->p_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, prProto); strcat(*buffer, fieldsep); + + return (0); + +} + + + +/* + * int irp_unmarshall_pr(struct protoent *pr, char *buffer) + * + * notes: + * + * See above + * + * return: + * + * 0 on success, -1 on failure + * + */ + +int irp_unmarshall_pr(struct protoent *pr, char *buffer) { + char *p, *q; + int prproto; + long t; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (pr == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* p_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* p_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* p_proto field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + prproto = (int)t; + if ((long) prproto != t) { /* value must have been too big. */ + goto error; + } + + pr->p_name = name; + pr->p_aliases = aliases; + pr->p_proto = prproto; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + +/* ------------------------- struct protoent ------------------------- */ + + + +/* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) + * + * notes: + * + * see above. + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char hoaddrtype[24]; + char holength[24]; + char **av; + char *p; + int addrlen; + int malloced = 0; + size_t remlen; + const char *fieldsep = "@"; + + if (ho == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + switch(ho->h_addrtype) { + case AF_INET: + strcpy(hoaddrtype, "AF_INET"); + break; + + case AF_INET6: + strcpy(hoaddrtype, "AF_INET6"); + break; + + default: + errno = EINVAL; + return (-1); + } + + sprintf(holength, "%d", ho->h_length); + + need += strlen(ho->h_name) + 1; + need += joinlength(ho->h_aliases) + 1; + need += strlen(hoaddrtype) + 1; + need += strlen(holength) + 1; + + /* we determine an upper bound on the string length needed, not an + exact length. */ + addrlen = (ho->h_addrtype == AF_INET ? 16 : 46) ; /* XX other AF's?? */ + for (av = ho->h_addr_list; av != NULL && *av != NULL ; av++) + need += addrlen; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + malloced = 1; + } + + strcpy(*buffer, ho->h_name); strcat(*buffer, fieldsep); + joinarray(ho->h_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, hoaddrtype); strcat(*buffer, fieldsep); + strcat(*buffer, holength); strcat(*buffer, fieldsep); + + p = *buffer + strlen(*buffer); + remlen = need - strlen(*buffer); + for (av = ho->h_addr_list ; av != NULL && *av != NULL ; av++) { + if (inet_ntop(ho->h_addrtype, *av, p, remlen) == NULL) { + goto error; + } + if (*(av + 1) != NULL) + strcat(p, COMMASTR); + remlen -= strlen(p); + p += strlen(p); + } + strcat(*buffer, fieldsep); + + return (0); + + error: + if (malloced) { + memput(*buffer, need); + } + + return (-1); +} + + + +/* + * int irp_unmarshall_ho(struct hostent *ho, char *buffer) + * + * notes: + * + * See above. + * + * return: + * + * 0 on success, -1 on failure. + * + */ + +int +irp_unmarshall_ho(struct hostent *ho, char *buffer) { + char *p, *q, *r; + int hoaddrtype; + int holength; + long t; + char *name = NULL; + char **aliases = NULL; + char **hohaddrlist = NULL; + size_t hoaddrsize; + char tmpbuf[24]; + char *tb; + char **alist; + int addrcount; + char fieldsep = '@'; + int myerrno = EINVAL; + + if (ho == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* h_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* h_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + hoaddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + hoaddrtype = AF_INET6; + else + goto error; + + + /* h_length field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /* junk in value */ + } + holength = (int)t; + if ((long) holength != t) { /* value must have been too big. */ + goto error; + } + + + /* h_addr_list field */ + q = strchr(p, fieldsep); + if (q == NULL) + goto error; + + /* count how many addresss are in there */ + if (q > p + 1) { + for (addrcount = 1, r = p ; r != q ; r++) { + if (*r == COMMA) + addrcount++; + } + } else { + addrcount = 0; + } + + hoaddrsize = (addrcount + 1) * sizeof (char *); + hohaddrlist = malloc(hoaddrsize); + if (hohaddrlist == NULL) { + myerrno = ENOMEM; + goto error; + } + + memset(hohaddrlist, 0x0, hoaddrsize); + + alist = hohaddrlist; + for (t = 0, r = p ; r != q ; p = r + 1, t++) { + char saved; + while (r != q && *r != COMMA) r++; + saved = *r; + *r = 0x0; + + alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16); + if (alist[t] == NULL) { + myerrno = ENOMEM; + goto error; + } + + if (inet_pton(hoaddrtype, p, alist[t]) == -1) + goto error; + *r = saved; + } + alist[t] = NULL; + + ho->h_name = name; + ho->h_aliases = aliases; + ho->h_addrtype = hoaddrtype; + ho->h_length = holength; + ho->h_addr_list = hohaddrlist; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + +/* ------------------------- struct hostent------------------------- */ + + + +/* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ng(const char *host, const char *user, + * const char *domain, char *buffer, size_t *len) + * + * notes: + * + * See note for irp_marshall_ng_start + * + * return: + * + * 0 on success, 0 on failure. + * + */ + +int +irp_marshall_ng(const char *host, const char *user, const char *domain, + char **buffer, size_t *len) { + size_t need = 1; /* for nul byte */ + const char *fieldsep = ","; + + if (len == NULL) { + errno = EINVAL; + return (-1); + } + + need += 4; /* two parens and two commas */ + need += (host == NULL ? 0 : strlen(host)); + need += (user == NULL ? 0 : strlen(user)); + need += (domain == NULL ? 0 : strlen(domain)); + + if (buffer == NULL) { + *len = need; + return (0); + } else if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + (*buffer)[0] = '('; + (*buffer)[1] = '\0'; + + if (host != NULL) + strcat(*buffer, host); + strcat(*buffer, fieldsep); + + if (user != NULL) + strcat(*buffer, user); + strcat(*buffer, fieldsep); + + if (domain != NULL) + strcat(*buffer, domain); + strcat(*buffer, ")"); + + return (0); +} + + + +/* ---------- */ + + +/* + * int irp_unmarshall_ng(const char **host, const char **user, + * const char **domain, char *buffer) + * + * notes: + * + * Unpacks the BUFFER into 3 character arrays it allocates and assigns + * to *HOST, *USER and *DOMAIN. If any field of the value is empty, + * then the corresponding paramater value will be set to NULL. + * + * return: + * + * 0 on success and -1 on failure. + */ + +int +irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp, + char *buffer) +{ + char *p, *q; + char fieldsep = ','; + int myerrno = EINVAL; + char *host, *user, *domain; + + if (userp == NULL || hostp == NULL || + domainp == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + host = user = domain = NULL; + + p = buffer; + while (isspace((unsigned char)*p)) { + p++; + } + if (*p != '(') { + goto error; + } + + q = p + 1; + while (*q && *q != fieldsep) + q++; + if (!*q) { + goto error; + } else if (q > p + 1) { + host = strndup(p, q - p); + } + + p = q + 1; + if (!*p) { + goto error; + } else if (*p != fieldsep) { + q = p + 1; + while (*q && *q != fieldsep) + q++; + if (!*q) { + goto error; + } + user = strndup(p, q - p); + } else { + p++; + } + + if (!*p) { + goto error; + } else if (*p != ')') { + q = p + 1; + while (*q && *q != ')') + q++; + if (!*q) { + goto error; + } + domain = strndup(p, q - p); + } + *hostp = host; + *userp = user; + *domainp = domain; + + return (0); + + error: + errno = myerrno; + + if (host != NULL) free(host); + if (user != NULL) free(user); + if (domain != NULL) free(domain); + + return (-1); +} + +/* ------------------------- struct netgrp ------------------------- */ + + + + +/* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) + * + * notes: + * + * See at top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char nAddrType[24]; + char nNet[MAXPADDRSIZE]; + const char *fieldsep = COLONSTR; + + if (ne == NULL || len == NULL) { + return (-1); + } + + strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); + + if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length, + nNet, sizeof nNet) == NULL) { + return (-1); + } + + + need += strlen(ne->n_name) + 1; + need += joinlength(ne->n_aliases) + 1; + need += strlen(nAddrType) + 1; + need += strlen(nNet) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); + joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); + strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); + strcat(*buffer, nNet); strcat(*buffer, fieldsep); + + return (0); +} + + + +/* + * int irp_unmarshall_nw(struct nwent *ne, char *buffer) + * + * notes: + * + * See note up top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_nw(struct nwent *ne, char *buffer) { + char *p, *q; + int naddrtype; + long nnet; + int bits; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (ne == NULL || buffer == NULL) { + goto error; + } + + p = buffer; + + /* n_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* n_aliases field. Aliases are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + naddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + naddrtype = AF_INET6; + else + goto error; + + + /* n_net field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + nnet = 0; + bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); + if (bits < 0) { + goto error; + } + + /* nnet = ntohl(nnet); */ /* keep in network order for nwent */ + + ne->n_name = name; + ne->n_aliases = aliases; + ne->n_addrtype = naddrtype; + ne->n_length = bits; + ne->n_addr = malloc(sizeof nnet); + if (ne->n_addr == NULL) { + goto error; + } + + memcpy(ne->n_addr, &nnet, sizeof nnet); + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct nwent ------------------------- */ + + +/* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */ + + +/* + * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) + * + * notes: + * + * See at top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) { + size_t need = 1; /* for null byte */ + char nAddrType[24]; + char nNet[MAXPADDRSIZE]; + const char *fieldsep = COLONSTR; + long nval; + + if (ne == NULL || len == NULL) { + return (-1); + } + + strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); + + nval = htonl(ne->n_net); + if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) { + return (-1); + } + + need += strlen(ne->n_name) + 1; + need += joinlength(ne->n_aliases) + 1; + need += strlen(nAddrType) + 1; + need += strlen(nNet) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /* for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); + joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); + strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); + strcat(*buffer, nNet); strcat(*buffer, fieldsep); + + return (0); +} + + + +/* + * int irp_unmarshall_ne(struct netent *ne, char *buffer) + * + * notes: + * + * See note up top. + * + * return: + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_ne(struct netent *ne, char *buffer) { + char *p, *q; + int naddrtype; + long nnet; + int bits; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (ne == NULL || buffer == NULL) { + goto error; + } + + p = buffer; + + /* n_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + + /* n_aliases field. Aliases are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + naddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + naddrtype = AF_INET6; + else + goto error; + + + /* n_net field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); + if (bits < 0) { + goto error; + } + nnet = ntohl(nnet); + + ne->n_name = name; + ne->n_aliases = aliases; + ne->n_addrtype = naddrtype; + ne->n_net = nnet; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct netent ------------------------- */ + + +/* =========================================================================== */ + + +/* + * static char ** splitarray(const char *buffer, const char *buffend, char delim) + * + * notes: + * + * Split a delim separated astring. Not allowed + * to have two delims next to each other. BUFFER points to begining of + * string, BUFFEND points to one past the end of the string + * (i.e. points at where the null byte would be if null + * terminated). + * + * return: + * + * Returns a malloced array of pointers, each pointer pointing to a + * malloced string. If BUFEER is an empty string, then return values is + * array of 1 pointer that is NULL. Returns NULL on failure. + * + */ + +static char ** +splitarray(const char *buffer, const char *buffend, char delim) { + const char *p, *q; + int count = 0; + char **arr = NULL; + char **aptr; + + if (buffend < buffer) + return (NULL); + else if (buffend > buffer && *buffer == delim) + return (NULL); + else if (buffend > buffer && *(buffend - 1) == delim) + return (NULL); + + /* count the number of field and make sure none are empty */ + if (buffend > buffer + 1) { + for (count = 1, q = buffer ; q != buffend ; q++) { + if (*q == delim) { + if (q > buffer && (*(q - 1) == delim)) { + errno = EINVAL; + return (NULL); + } + count++; + } + } + } + + if (count > 0) { + count++ ; /* for NULL at end */ + aptr = arr = malloc(count * sizeof (char *)); + if (aptr == NULL) { + errno = ENOMEM; + return (NULL); + } + + memset(arr, 0x0, count * sizeof (char *)); + for (p = buffer ; p < buffend ; p++) { + for (q = p ; *q != delim && q != buffend ; q++) + /* nothing */; + *aptr = strndup(p, q - p); + + p = q; + aptr++; + } + *aptr = NULL; + } else { + arr = malloc(sizeof (char *)); + if (arr == NULL) { + errno = ENOMEM; + return (NULL); + } + + *arr = NULL; + } + + return (arr); +} + + + + +/* + * static size_t joinlength(char * const *argv) + * + * return: + * + * the number of bytes in all the arrays pointed at + * by argv, including their null bytes(which will usually be turned + * into commas). + * + * + */ + +static size_t +joinlength(char * const *argv) { + int len = 0; + + while (argv && *argv) { + len += (strlen(*argv) + 1); + argv++; + } + + return (len); +} + + + +/* + * int joinarray(char * const *argv, char *buffer, char delim) + * + * notes: + * + * Copy all the ARGV strings into the end of BUFFER + * separating them with DELIM. BUFFER is assumed to have + * enough space to hold everything and to be already null-terminated. + * + * return: + * + * 0 unless argv or buffer is NULL. + * + * + */ + +static int +joinarray(char * const *argv, char *buffer, char delim) { + char * const *p; + char sep[2]; + + if (argv == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + sep[0] = delim; + sep[1] = 0x0; + + for (p = argv ; *p != NULL ; p++) { + strcat(buffer, *p); + if (*(p + 1) != NULL) { + strcat(buffer, sep); + } + } + + return (0); +} + + +/* + * static char * getfield(char **res, size_t reslen, char **ptr, char delim) + * + * notes: + * + * Stores in *RES, which is a buffer of length RESLEN, a + * copy of the bytes from *PTR up to and including the first + * instance of DELIM. If *RES is NULL, then it will be + * assigned a malloced buffer to hold the copy. *PTR is + * modified to point at the found delimiter. + * + * return: + * + * If there was no delimiter, then NULL is returned, + * otherewise *RES is returned. + * + */ + +static char * +getfield(char **res, size_t reslen, char **ptr, char delim) { + char *q; + + if (res == NULL || ptr == NULL || *ptr == NULL) { + errno = EINVAL; + return (NULL); + } + + q = strchr(*ptr, delim); + + if (q == NULL) { + errno = EINVAL; + return (NULL); + } else { + if (*res == NULL) { + *res = strndup(*ptr, q - *ptr); + } else { + if ((size_t)(q - *ptr + 1) > reslen) { /* to big for res */ + errno = EINVAL; + return (NULL); + } else { + strncpy(*res, *ptr, q - *ptr); + (*res)[q - *ptr] = 0x0; + } + } + *ptr = q + 1; + } + + return (*res); +} + + + + + + +/* + * static char * strndup(const char *str, size_t len) + * + * notes: + * + * like strdup, except do len bytes instead of the whole string. Always + * null-terminates. + * + * return: + * + * The newly malloced string. + * + */ + +static char * +strndup(const char *str, size_t len) { + char *p = malloc(len + 1); + + if (p == NULL) + return (NULL); + strncpy(p, str, len); + p[len] = 0x0; + return (p); +} + + +#if WANT_MAIN + +/* + * static int strcmp_nws(const char *a, const char *b) + * + * notes: + * + * do a strcmp, except uneven lengths of whitespace compare the same + * + * return: + * + */ + +static int +strcmp_nws(const char *a, const char *b) { + while (*a && *b) { + if (isspace(*a) && isspace(*b)) { + do { + a++; + } while (isspace(*a)); + do { + b++; + } while (isspace(*b)); + } + if (*a < *b) + return (-1); + else if (*a > *b) + return (1); + + a++; + b++;; + } + + if (*a == *b) + return (0); + else if (*a > *b) + return (1); + else + return (-1); +} + +#endif + + + + + +/* + * static void free_array(char **argv, size_t entries) + * + * notes: + * + * Free argv and each of the pointers inside it. The end of + * the array is when a NULL pointer is found inside. If + * entries is > 0, then NULL pointers inside the array do + * not indicate the end of the array. + * + */ + +static void +free_array(char **argv, size_t entries) { + char **p = argv; + int useEntries = (entries > 0); + + if (argv == NULL) + return; + + while ((useEntries && entries > 0) || *p) { + if (*p) + free(*p); + p++; + if (useEntries) + entries--; + } + free(argv); +} + + + + + +/* ************************************************** */ + +#if WANT_MAIN + +/* takes an option to indicate what sort of marshalling(read the code) and + an argument. If the argument looks like a marshalled buffer(has a ':' + embedded) then it's unmarshalled and the remarshalled and the new string + is compared to the old one. +*/ + +int +main(int argc, char **argv) { + char buffer[1024]; + char *b = &buffer[0]; + size_t len = sizeof buffer; + char option; + + if (argc < 2 || argv[1][0] != '-') + exit(1); + + option = argv[1][1]; + argv++; + argc--; + + +#if 0 + { + char buff[10]; + char *p = argv[1], *q = &buff[0]; + + while (getfield(&q, sizeof buff, &p, ':') != NULL) { + printf("field: \"%s\"\n", q); + p++; + } + printf("p is now \"%s\"\n", p); + } +#endif + +#if 0 + { + char **x = splitarray(argv[1], argv[1] + strlen(argv[1]), + argv[2][0]); + char **p; + + if (x == NULL) + printf("split failed\n"); + + for (p = x ; p != NULL && *p != NULL ; p++) { + printf("\"%s\"\n", *p); + } + } +#endif + +#if 1 + switch(option) { + case 'n': { + struct nwent ne; + int i; + + if (strchr(argv[1], ':') != NULL) { + if (irp_unmarshall_nw(&ne, argv[1]) != 0) { + printf("Unmarhsalling failed\n"); + exit(1); + } + + printf("Name: \"%s\"\n", ne.n_name); + printf("Aliases:"); + for (i = 0 ; ne.n_aliases[i] != NULL ; i++) + printf("\n\t\"%s\"", ne.n_aliases[i]); + printf("\nAddrtype: %s\n", ADDR_T_STR(ne.n_addrtype)); + inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, + buffer, sizeof buffer); + printf("Net: \"%s\"\n", buffer); + *((long*)ne.n_addr) = htonl(*((long*)ne.n_addr)); + inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, + buffer, sizeof buffer); + printf("Corrected Net: \"%s\"\n", buffer); + } else { + struct netent *np1 = getnetbyname(argv[1]); + ne.n_name = np1->n_name; + ne.n_aliases = np1->n_aliases; + ne.n_addrtype = np1->n_addrtype; + ne.n_addr = &np1->n_net; + ne.n_length = (IN_CLASSA(np1->n_net) ? + 8 : + (IN_CLASSB(np1->n_net) ? + 16 : + (IN_CLASSC(np1->n_net) ? + 24 : -1))); + np1->n_net = htonl(np1->n_net); + if (irp_marshall_nw(&ne, &b, &len) != 0) { + printf("Marshalling failed\n"); + } + printf("%s\n", b); + } + break; + } + + + case 'r': { + char **hosts, **users, **domains; + size_t entries; + int i; + char *buff; + size_t size; + char *ngname; + + if (strchr(argv[1], '(') != NULL) { + if (irp_unmarshall_ng(&ngname, &entries, + &hosts, &users, &domains, + argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + +#define STRVAL(x) (x == NULL ? "*" : x) + + printf("%s {\n", ngname); + for (i = 0 ; i < entries ; i++) + printf("\t\"%s\" : \"%s\" : \"%s\"\n", + STRVAL(hosts[i]), + STRVAL(users[i]), + STRVAL(domains[i])); + printf("}\n\n\n"); + + + irp_marshall_ng_start(ngname, NULL, &size); + for (i = 0 ; i < entries ; i++) + irp_marshall_ng_next(hosts[i], users[i], + domains[i], NULL, &size); + irp_marshall_ng_end(NULL, &size); + + buff = malloc(size); + + irp_marshall_ng_start(ngname, buff, &size); + for (i = 0 ; i < entries ; i++) { + if (irp_marshall_ng_next(hosts[i], users[i], + domains[i], buff, + &size) != 0) + printf("next marshalling failed.\n"); + } + irp_marshall_ng_end(buff, &size); + + if (strcmp_nws(argv[1], buff) != 0) { + printf("compare failed:\n\t%s\n\t%s\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + char *h, *u, *d, *buff; + size_t size; + + /* run through two times. First to figure out how + much of a buffer we need. Second to do the + actual marshalling */ + + setnetgrent(argv[1]); + irp_marshall_ng_start(argv[1], NULL, &size); + while (getnetgrent(&h, &u, &d) == 1) + irp_marshall_ng_next(h, u, d, NULL, &size); + irp_marshall_ng_end(NULL, &size); + endnetgrent(argv[1]); + + buff = malloc(size); + + setnetgrent(argv[1]); + if (irp_marshall_ng_start(argv[1], buff, &size) != 0) + printf("Marshalling start failed\n"); + + while (getnetgrent(&h, &u, &d) == 1) { + if (irp_marshall_ng_next(h, u, d, buff, &size) + != 0) { + printf("Marshalling failed\n"); + } + } + + irp_marshall_ng_end(buff, &size); + endnetgrent(); + + printf("success: %s\n", buff); + } + break; + } + + + + case 'h': { + struct hostent he, *hp; + int i; + + + if (strchr(argv[1], '@') != NULL) { + if (irp_unmarshall_ho(&he, argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + + printf("Host: \"%s\"\nAliases:", he.h_name); + for (i = 0 ; he.h_aliases[i] != NULL ; i++) + printf("\n\t\t\"%s\"", he.h_aliases[i]); + printf("\nAddr Type: \"%s\"\n", + ADDR_T_STR(he.h_addrtype)); + printf("Length: %d\nAddresses:", he.h_length); + for (i = 0 ; he.h_addr_list[i] != 0 ; i++) { + inet_ntop(he.h_addrtype, he.h_addr_list[i], + buffer, sizeof buffer); + printf("\n\t\"%s\"\n", buffer); + } + printf("\n\n"); + + irp_marshall_ho(&he, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((hp = gethostbyname(argv[1])) == NULL) { + perror("gethostbyname"); + printf("\"%s\"\n", argv[1]); + exit(1); + } + + if (irp_marshall_ho(hp, &b, &len) != 0) { + printf("irp_marshall_ho failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + + case 's': { + struct servent *sv; + struct servent sv1; + + if (strchr(argv[1], ':') != NULL) { + sv = &sv1; + memset(sv, 0xef, sizeof (struct servent)); + if (irp_unmarshall_sv(sv, argv[1]) != 0) { + printf("unmarshall failed\n"); + + } + + irp_marshall_sv(sv, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((sv = getservbyname(argv[1], argv[2])) == NULL) { + perror("getservent"); + exit(1); + } + + if (irp_marshall_sv(sv, &b, &len) != 0) { + printf("irp_marshall_sv failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + case 'g': { + struct group *gr; + struct group gr1; + + if (strchr(argv[1], ':') != NULL) { + gr = &gr1; + memset(gr, 0xef, sizeof (struct group)); + if (irp_unmarshall_gr(gr, argv[1]) != 0) { + printf("unmarshall failed\n"); + + } + + irp_marshall_gr(gr, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((gr = getgrnam(argv[1])) == NULL) { + perror("getgrnam"); + exit(1); + } + + if (irp_marshall_gr(gr, &b, &len) != 0) { + printf("irp_marshall_gr failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + + case 'p': { + struct passwd *pw; + struct passwd pw1; + + if (strchr(argv[1], ':') != NULL) { + pw = &pw1; + memset(pw, 0xef, sizeof (*pw)); + if (irp_unmarshall_pw(pw, argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + + printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n", + pw->pw_name, pw->pw_passwd, (long)pw->pw_uid, + (long)pw->pw_gid); + printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n", + pw->pw_class, (long)pw->pw_change, pw->pw_gecos); + printf("Shell: \"%s\"\nDirectory: \"%s\"\n", + pw->pw_shell, pw->pw_dir); + + pw = getpwnam(pw->pw_name); + irp_marshall_pw(pw, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((pw = getpwnam(argv[1])) == NULL) { + perror("getpwnam"); + exit(1); + } + + if (irp_marshall_pw(pw, &b, &len) != 0) { + printf("irp_marshall_pw failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + default: + printf("Wrong option: %c\n", option); + break; + } + +#endif + + return (0); +} + +#endif diff --git a/usr/src/lib/libresolv2/common/irs/irs_data.c b/usr/src/lib/libresolv2/common/irs/irs_data.c new file mode 100644 index 0000000000..14d965bf0c --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irs_data.c @@ -0,0 +1,221 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irs_data.c,v 1.22 2003/06/20 07:09:33 marka Exp $"; +#endif + +#include "port_before.h" + +#ifndef __BIND_NOSTATIC + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <isc/memcluster.h> +#include <stdlib.h> + +#ifdef DO_PTHREADS +#include <pthread.h> +#endif + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" +#undef _res +#undef h_errno + +extern struct __res_state _res; +extern int h_errno; + +#ifdef DO_PTHREADS +static pthread_key_t key; +static int once = 0; +#else +static struct net_data *net_data; +#endif + +void +irs_destroy(void) { +#ifndef DO_PTHREADS + if (net_data != NULL) + net_data_destroy(net_data); + net_data = NULL; +#endif +} + +void +net_data_destroy(void *p) { + struct net_data *net_data = p; + + res_ndestroy(net_data->res); + if (net_data->gr != NULL) { + (*net_data->gr->close)(net_data->gr); + net_data->gr = NULL; + } + if (net_data->pw != NULL) { + (*net_data->pw->close)(net_data->pw); + net_data->pw = NULL; + } + if (net_data->sv != NULL) { + (*net_data->sv->close)(net_data->sv); + net_data->sv = NULL; + } + if (net_data->pr != NULL) { + (*net_data->pr->close)(net_data->pr); + net_data->pr = NULL; + } + if (net_data->ho != NULL) { + (*net_data->ho->close)(net_data->ho); + net_data->ho = NULL; + } + if (net_data->nw != NULL) { + (*net_data->nw->close)(net_data->nw); + net_data->nw = NULL; + } + if (net_data->ng != NULL) { + (*net_data->ng->close)(net_data->ng); + net_data->ng = NULL; + } + if (net_data->ho_data != NULL) { + free(net_data->ho_data); + net_data->ho_data = NULL; + } + if (net_data->nw_data != NULL) { + free(net_data->nw_data); + net_data->nw_data = NULL; + } + + (*net_data->irs->close)(net_data->irs); + memput(net_data, sizeof *net_data); +} + +/* applications that need a specific config file other than + * _PATH_IRS_CONF should call net_data_init directly rather than letting + * the various wrapper functions make the first call. - brister + */ + +struct net_data * +net_data_init(const char *conf_file) { +#ifdef DO_PTHREADS + static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; + struct net_data *net_data; + + if (!once) { + pthread_mutex_lock(&keylock); + if (!once++) + pthread_key_create(&key, net_data_destroy); + pthread_mutex_unlock(&keylock); + } + net_data = pthread_getspecific(key); +#endif + + if (net_data == NULL) { + net_data = net_data_create(conf_file); + if (net_data == NULL) + return (NULL); +#ifdef DO_PTHREADS + pthread_setspecific(key, net_data); +#endif + } + + return (net_data); +} + +struct net_data * +net_data_create(const char *conf_file) { + struct net_data *net_data; + + net_data = memget(sizeof (struct net_data)); + if (net_data == NULL) + return (NULL); + memset(net_data, 0, sizeof (struct net_data)); + + if ((net_data->irs = irs_gen_acc("", conf_file)) == NULL) { + memput(net_data, sizeof (struct net_data)); + return (NULL); + } +#ifndef DO_PTHREADS + (*net_data->irs->res_set)(net_data->irs, &_res, NULL); +#endif + + net_data->res = (*net_data->irs->res_get)(net_data->irs); + if (net_data->res == NULL) { + (*net_data->irs->close)(net_data->irs); + memput(net_data, sizeof (struct net_data)); + return (NULL); + } + + if ((net_data->res->options & RES_INIT) == 0 && + res_ninit(net_data->res) == -1) { + (*net_data->irs->close)(net_data->irs); + memput(net_data, sizeof (struct net_data)); + return (NULL); + } + + return (net_data); +} + + + +void +net_data_minimize(struct net_data *net_data) { + res_nclose(net_data->res); +} + +#ifdef _REENTRANT +struct __res_state * +__res_state(void) { + /* NULL param here means use the default config file. */ + struct net_data *net_data = net_data_init(NULL); + if (net_data && net_data->res) + return (net_data->res); + + return (&_res); +} +#endif + +int * +__h_errno(void) { + /* NULL param here means use the default config file. */ + struct net_data *net_data = net_data_init(NULL); + if (net_data && net_data->res) + return (&net_data->res->res_h_errno); + return (&h_errno); +} + +void +__h_errno_set(struct __res_state *res, int err) { + + h_errno = res->res_h_errno = err; +} + +#endif /*__BIND_NOSTATIC*/ diff --git a/usr/src/lib/libresolv2/common/irs/irs_data.h b/usr/src/lib/libresolv2/common/irs/irs_data.h new file mode 100644 index 0000000000..4c5fdf3c64 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irs_data.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: irs_data.h,v 1.12 1999/01/18 07:46:55 vixie Exp $ + */ + +#ifndef __BIND_NOSTATIC + +#ifndef _IRS_DATA_H +#define _IRS_DATA_H + +#define net_data_init __net_data_init + +struct net_data { + struct irs_acc * irs; + + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; + + struct group * gr_last; + struct passwd * pw_last; + struct servent * sv_last; + struct protoent * pr_last; + struct netent * nw_last; /* should have been ne_last */ + struct nwent * nww_last; + struct hostent * ho_last; + + unsigned int gr_stayopen :1; + unsigned int pw_stayopen :1; + unsigned int sv_stayopen :1; + unsigned int pr_stayopen :1; + unsigned int ho_stayopen :1; + unsigned int nw_stayopen :1; + + void * nw_data; + void * ho_data; + + struct __res_state * res; /* for gethostent.c */ + +}; + +extern struct net_data * net_data_init(const char *conf_file); +extern void net_data_minimize(struct net_data *); + +#endif /* _IR_DATA_H */ + +#endif /*__BIND_NOSTATIC*/ diff --git a/usr/src/lib/libresolv2/common/irs/irs_p.h b/usr/src/lib/libresolv2/common/irs/irs_p.h new file mode 100644 index 0000000000..64043b90aa --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/irs_p.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: irs_p.h,v 1.8 1999/01/08 19:24:42 vixie Exp $ + */ + +#ifndef _IRS_P_H_INCLUDED +#define _IRS_P_H_INCLUDED + +#include <stdio.h> + +#include "pathnames.h" + +#define IRS_SV_MAXALIASES 35 + +struct lcl_sv { + FILE * fp; + char line[BUFSIZ+1]; + struct servent serv; + char * serv_aliases[IRS_SV_MAXALIASES]; +}; + +#define irs_nul_ng __irs_nul_ng +#define map_v4v6_address __map_v4v6_address +#define make_group_list __make_group_list +#define irs_lclsv_fnxt __irs_lclsv_fnxt + +extern void map_v4v6_address(const char *src, char *dst); +extern int make_group_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +extern struct irs_ng * irs_nul_ng(struct irs_acc *); +extern struct servent * irs_lclsv_fnxt(struct lcl_sv *); + +#endif diff --git a/usr/src/lib/libresolv2/common/irs/lcl.c b/usr/src/lib/libresolv2/common/irs/lcl.c new file mode 100644 index 0000000000..3d86033209 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl.c @@ -0,0 +1,147 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: lcl.c,v 1.17 2001/05/29 05:49:02 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <isc/memcluster.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Forward. */ + +static void lcl_close(struct irs_acc *); +static struct __res_state * lcl_res_get(struct irs_acc *); +static void lcl_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_acc * +irs_lcl_acc(const char *options) { + struct irs_acc *acc; + struct lcl_p *lcl; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(lcl = memget(sizeof *lcl))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + memset(lcl, 0x5e, sizeof *lcl); + lcl->res = NULL; + lcl->free_res = NULL; + acc->private = lcl; +#ifdef WANT_IRS_GR + acc->gr_map = irs_lcl_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_lcl_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_lcl_sv; + acc->pr_map = irs_lcl_pr; + acc->ho_map = irs_lcl_ho; + acc->nw_map = irs_lcl_nw; + acc->ng_map = irs_lcl_ng; + acc->res_get = lcl_res_get; + acc->res_set = lcl_res_set; + acc->close = lcl_close; + return (acc); +} + +/* Methods */ +static struct __res_state * +lcl_res_get(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + lcl_res_set(this, res, free); + } + + if ((lcl->res->options & RES_INIT) == 0 && + res_ninit(lcl->res) < 0) + return (NULL); + + return (lcl->res); +} + +static void +lcl_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl->res && lcl->free_res) { + res_nclose(lcl->res); + (*lcl->free_res)(lcl->res); + } + + lcl->res = res; + lcl->free_res = free_res; +} + +static void +lcl_close(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl) { + if (lcl->free_res) + (*lcl->free_res)(lcl->res); + memput(lcl, sizeof *lcl); + } + memput(this, sizeof *this); +} diff --git a/usr/src/lib/libresolv2/common/irs/lcl_gr.c b/usr/src/lib/libresolv2/common/irs/lcl_gr.c new file mode 100644 index 0000000000..0a655f0d8f --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl_gr.c @@ -0,0 +1,361 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1989, 1993, 1995 + * The 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. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_gr.c,v 1.26 2001/05/29 05:49:03 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_gr_unneeded; +#else + +#include <sys/param.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +/* Types. */ + +struct pvt { + FILE * fp; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +/* Forward. */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +static int grstart(struct pvt *); +static char * grnext(struct pvt *); +static struct group * grscan(struct irs_gr *, int, gid_t, const char *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_gr * +irs_lcl_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + UNUSED(this); + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + gr->res_get = NULL; + gr->res_set = NULL; + return (gr); +} + +/* Methods. */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void)fclose(pvt->fp); + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->fp && !grstart(pvt)) + return (NULL); + return (grscan(this, 0, 0, NULL)); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + if (!grstart((struct pvt *)this->private)) + return (NULL); + return (grscan(this, 1, 0, name)); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + if (!grstart((struct pvt *)this->private)) + return (NULL); + return (grscan(this, 1, gid, NULL)); +} + +static void +gr_rewind(struct irs_gr *this) { + (void) grstart((struct pvt *)this->private); +} + +static void +gr_minimize(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private. */ + +static int +grstart(struct pvt *pvt) { + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return (1); + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_GROUP, "r"))) + return (0); + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + fclose(pvt->fp); + return (0); + } + return (1); +} + +#define INITIAL_NMEMB 30 /* about 120 bytes */ +#define INITIAL_BUFSIZ (INITIAL_NMEMB * 8) /* about 240 bytes */ + +static char * +grnext(struct pvt *pvt) { + char *w, *e; + int ch; + + /* Make sure we have a buffer. */ + if (pvt->membuf == NULL) { + pvt->membuf = malloc(INITIAL_BUFSIZ); + if (pvt->membuf == NULL) { + enomem: + errno = ENOMEM; + return (NULL); + } + pvt->membufsize = INITIAL_BUFSIZ; + } + + /* Read until EOF or EOL. */ + w = pvt->membuf; + e = pvt->membuf + pvt->membufsize; + while ((ch = fgetc(pvt->fp)) != EOF && ch != '\n') { + /* Make sure we have room for this character and a \0. */ + if (w + 1 == e) { + size_t o = w - pvt->membuf; + size_t n = pvt->membufsize * 2; + char *t = realloc(pvt->membuf, n); + + if (t == NULL) + goto enomem; + pvt->membuf = t; + pvt->membufsize = n; + w = pvt->membuf + o; + e = pvt->membuf + pvt->membufsize; + } + /* Store it. */ + *w++ = (char)ch; + } + + /* Hitting EOF on the first character really does mean EOF. */ + if (w == pvt->membuf && ch == EOF) { + errno = ENOENT; + return (NULL); + } + + /* Last line of /etc/group need not end with \n; we don't care. */ + *w = '\0'; + return (pvt->membuf); +} + +static struct group * +grscan(struct irs_gr *this, int search, gid_t gid, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + size_t n; + char *bp, **m, *p; + + /* Read lines until we find one that matches our search criteria. */ + for (;;) { + if ((bp = grnext(pvt)) == NULL) + return (NULL); + + /* Optimize the usual case of searching for a name. */ + pvt->group.gr_name = strsep(&bp, ":"); + if (search && name != NULL && + strcmp(pvt->group.gr_name, name) != 0) + continue; + if (bp == NULL || *bp == '\0') + goto corrupt; + + /* Skip past the password field. */ + pvt->group.gr_passwd = strsep(&bp, ":"); + if (bp == NULL || *bp == '\0') + goto corrupt; + + /* Checking for a gid. */ + if ((p = strsep(&bp, ":")) == NULL) + continue; + /* + * Unlike the tests above, the test below is supposed to be + * testing 'p' and not 'bp', in case you think it's a typo. + */ + if (p == NULL || *p == '\0') { + corrupt: + /* warning: corrupted %s file!", _PATH_GROUP */ + continue; + } + pvt->group.gr_gid = atoi(p); + if (search && name == NULL && (gid_t)pvt->group.gr_gid != gid) + continue; + + /* We want this record. */ + break; + } + + /* + * Count commas to find out how many members there might be. + * Note that commas separate, so if there is one comma there + * can be two members (group:*:id:user1,user2). Add another + * to account for the NULL terminator. As above, allocate + * largest of INITIAL_NMEMB, or 2*n. + */ + n = 1; + if (bp != NULL) + for (n = 2, p = bp; (p = strpbrk(p, ", ")) != NULL; ++n) + p += strspn(p, ", "); + if (n > pvt->nmemb || pvt->group.gr_mem == NULL) { + if ((n *= 2) < INITIAL_NMEMB) + n = INITIAL_NMEMB; + if ((m = realloc(pvt->group.gr_mem, n * sizeof *m)) == NULL) + return (NULL); + pvt->group.gr_mem = m; + pvt->nmemb = n; + } + + /* Set the name pointers. */ + for (m = pvt->group.gr_mem; (p = strsep(&bp, ", ")) != NULL;) + if (p[0] != '\0') + *m++ = p; + *m = NULL; + + return (&pvt->group); +} + +#endif /* WANT_IRS_GR */ diff --git a/usr/src/lib/libresolv2/common/irs/lcl_ho.c b/usr/src/lib/libresolv2/common/irs/lcl_ho.c new file mode 100644 index 0000000000..cebf63ef08 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl_ho.c @@ -0,0 +1,629 @@ +/* + * Copyright 1997-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1985, 1988, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_ho.c,v 1.26 2001/05/29 05:49:04 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" +#ifdef SUNW_AVOIDSTDIO_FDLIMIT +#include "../../../libnsl/include/nsl_stdio_prv.h" +#endif + +#include "irs_p.h" +#include "dns_p.h" +#include "lcl_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + __NSL_FILE * fp; +#else + FILE * fp; +#endif + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +typedef union { + int32_t al; + char ac; +} align; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static size_t ns_namelen(const char *); +static int init(struct irs_ho *this); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_ho * +irs_lcl_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->fp) +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + (void) __nsl_fclose(pvt->fp); +#else + (void) fclose(pvt->fp); +#endif + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + char **hap; + size_t n; + + if (init(this) == -1) + return (NULL); + + ho_rewind(this); + n = ns_namelen(name); + while ((hp = ho_next(this)) != NULL) { + size_t nn; + + if (hp->h_addrtype != af) + continue; + nn = ns_namelen(hp->h_name); + if (strncasecmp(hp->h_name, name, Max(n, nn)) == 0) + goto found; + for (hap = hp->h_aliases; *hap; hap++) { + nn = ns_namelen(*hap); + if (strncasecmp(*hap, name, Max(n, nn)) == 0) + goto found; + } + } + found: + if (!hp) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + struct hostent *hp; + int size; + + if (init(this) == -1) + return (NULL); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (const u_char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (size > len) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + + /* + * Do the search. + */ + ho_rewind(this); + while ((hp = ho_next(this)) != NULL) { + char **hap; + + for (hap = hp->h_addr_list; *hap; hap++) { + const u_char *taddr = (const u_char *)*hap; + int taf = hp->h_addrtype; + int tlen = hp->h_length; + + if (taf == AF_INET6 && tlen == IN6ADDRSZ && + (!memcmp(taddr, mapped, sizeof mapped) || + !memcmp(taddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + taddr += sizeof mapped; + taf = AF_INET; + tlen = INADDRSZ; + } + if (taf == af && tlen == len && + !memcmp(taddr, uaddr, tlen)) + goto found; + } + } + found: + if (!hp) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **q, *p; + char *bufp, *ndbuf, *dbuf = NULL; + int c, af, len, bufsiz, offset; + + if (init(this) == -1) + return (NULL); + + if (!pvt->fp) + ho_rewind(this); + if (!pvt->fp) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + bufp = pvt->hostbuf; + bufsiz = sizeof pvt->hostbuf; + offset = 0; + again: +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + if (!(p = __nsl_fgets(bufp + offset, bufsiz - offset, pvt->fp))) { +#else + if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) { +#endif + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + if (dbuf) + free(dbuf); + return (NULL); + } +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + if (!strchr(p, '\n') && !__nsl_feof(pvt->fp)) { +#else + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#endif +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + while ((c = __nsl_getc(pvt->fp)) != EOF) +#else + while ((c = getc(pvt->fp)) != EOF) +#endif + if (c == '\n') + break; + if (c != EOF) +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + __nsl_ungetc(c, pvt->fp); +#else + ungetc(c, pvt->fp); +#endif + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + if ((cp = strpbrk(p, "#\n")) != NULL) + *cp = '\0'; + if (!(cp = strpbrk(p, " \t"))) + goto again; + *cp++ = '\0'; + if (inet_pton(AF_INET6, p, pvt->host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) { + if (pvt->res->options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + goto again; + } + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + while (*cp == ' ' || *cp == '\t') + cp++; + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES - 1]) + *q++ = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + } + *q = NULL; + if (dbuf) + free(dbuf); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + if (pvt->fp) { + if (__nsl_fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)__nsl_fclose(pvt->fp); + } + if (!(pvt->fp = __nsl_fopen(_PATH_HOSTS, "r"))) + return; + if (fcntl(__nsl_fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)__nsl_fclose(pvt->fp); + pvt->fp = NULL; + } +#else + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_HOSTS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +#endif + +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + (void)__nsl_fclose(pvt->fp); +#else + (void)fclose(pvt->fp); +#endif + pvt->fp = NULL; + } + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +struct lcl_res_target { + struct lcl_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct lcl_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /* INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + +/* Private. */ + +static size_t +ns_namelen(const char *s) { + int i; + + for (i = strlen(s); i > 0 && s[i-1] == '.'; i--) + (void)NULL; + return ((size_t) i); +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/irs/lcl_ng.c b/usr/src/lib/libresolv2/common/irs/lcl_ng.c new file mode 100644 index 0000000000..05adcdf9f9 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl_ng.c @@ -0,0 +1,451 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: lcl_ng.c,v 1.17 2001/05/29 05:49:05 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Definitions */ + +#define NG_HOST 0 /* Host name */ +#define NG_USER 1 /* User name */ +#define NG_DOM 2 /* and Domain name */ +#define LINSIZ 1024 /* Length of netgroup file line */ + +/* + * XXX Warning XXX + * This code is a hack-and-slash special. It realy needs to be + * rewritten with things like strdup, and realloc in mind. + * More reasonable data structures would not be a bad thing. + */ + +/* + * Static Variables and functions used by setnetgrent(), getnetgrent() and + * endnetgrent(). + * There are two linked lists: + * - linelist is just used by setnetgrent() to parse the net group file via. + * parse_netgrp() + * - netgrp is the list of entries for the current netgroup + */ +struct linelist { + struct linelist *l_next; /* Chain ptr. */ + int l_parsed; /* Flag for cycles */ + char * l_groupname; /* Name of netgroup */ + char * l_line; /* Netgroup entrie(s) to be parsed */ +}; + +struct ng_old_struct { + struct ng_old_struct *ng_next; /* Chain ptr */ + char * ng_str[3]; /* Field pointers, see below */ +}; + +struct pvt { + FILE *fp; + struct linelist *linehead; + struct ng_old_struct *nextgrp; + struct { + struct ng_old_struct *gr; + char *grname; + } grouphead; +}; + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + +static int parse_netgrp(struct irs_ng *, const char*); +static struct linelist *read_for_group(struct irs_ng *, const char *); +static void freelists(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_lcl_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + UNUSED(this); + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) + fclose(pvt->fp); + freelists(this); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +/* + * Parse the netgroup file looking for the netgroup and build the list + * of netgrp structures. Let parse_netgrp() and read_for_group() do + * most of the work. + */ +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) { + fclose(pvt->fp); + pvt->fp = NULL; + } + + if (pvt->fp == NULL || pvt->grouphead.gr == NULL || + strcmp(group, pvt->grouphead.grname)) { + freelists(this); + if (pvt->fp != NULL) + fclose(pvt->fp); + pvt->fp = fopen(_PATH_NETGROUP, "r"); + if (pvt->fp != NULL) { + if (parse_netgrp(this, group)) + freelists(this); + if (!(pvt->grouphead.grname = strdup(group))) + freelists(this); + fclose(pvt->fp); + pvt->fp = NULL; + } + } + pvt->nextgrp = pvt->grouphead.gr; +} + +/* + * Get the next netgroup off the list. + */ +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->nextgrp) { + *host = pvt->nextgrp->ng_str[NG_HOST]; + *user = pvt->nextgrp->ng_str[NG_USER]; + *domain = pvt->nextgrp->ng_str[NG_DOM]; + pvt->nextgrp = pvt->nextgrp->ng_next; + return (1); + } + return (0); +} + +/* + * Search for a match in a netgroup. + */ +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + const char *ng_host, *ng_user, *ng_domain; + + ng_rewind(this, name); + while (ng_next(this, &ng_host, &ng_user, &ng_domain)) + if ((host == NULL || ng_host == NULL || + !strcmp(host, ng_host)) && + (user == NULL || ng_user == NULL || + !strcmp(user, ng_user)) && + (domain == NULL || ng_domain == NULL || + !strcmp(domain, ng_domain))) { + freelists(this); + return (1); + } + freelists(this); + return (0); +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private */ + +/* + * endnetgrent() - cleanup + */ +static void +freelists(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct linelist *lp, *olp; + struct ng_old_struct *gp, *ogp; + + lp = pvt->linehead; + while (lp) { + olp = lp; + lp = lp->l_next; + free(olp->l_groupname); + free(olp->l_line); + free((char *)olp); + } + pvt->linehead = NULL; + if (pvt->grouphead.grname) { + free(pvt->grouphead.grname); + pvt->grouphead.grname = NULL; + } + gp = pvt->grouphead.gr; + while (gp) { + ogp = gp; + gp = gp->ng_next; + if (ogp->ng_str[NG_HOST]) + free(ogp->ng_str[NG_HOST]); + if (ogp->ng_str[NG_USER]) + free(ogp->ng_str[NG_USER]); + if (ogp->ng_str[NG_DOM]) + free(ogp->ng_str[NG_DOM]); + free((char *)ogp); + } + pvt->grouphead.gr = NULL; +} + +/* + * Parse the netgroup file setting up the linked lists. + */ +static int +parse_netgrp(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *spos, *epos; + int len, strpos; + char *pos, *gpos; + struct ng_old_struct *grp; + struct linelist *lp = pvt->linehead; + + /* + * First, see if the line has already been read in. + */ + while (lp) { + if (!strcmp(group, lp->l_groupname)) + break; + lp = lp->l_next; + } + if (lp == NULL && + (lp = read_for_group(this, group)) == NULL) + return (1); + if (lp->l_parsed) { + /*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/ + return (1); + } else + lp->l_parsed = 1; + pos = lp->l_line; + while (*pos != '\0') { + if (*pos == '(') { + if (!(grp = malloc(sizeof (struct ng_old_struct)))) { + freelists(this); + errno = ENOMEM; + return (1); + } + memset(grp, 0, sizeof (struct ng_old_struct)); + grp->ng_next = pvt->grouphead.gr; + pvt->grouphead.gr = grp; + pos++; + gpos = strsep(&pos, ")"); + for (strpos = 0; strpos < 3; strpos++) { + if ((spos = strsep(&gpos, ","))) { + while (*spos == ' ' || *spos == '\t') + spos++; + if ((epos = strpbrk(spos, " \t"))) { + *epos = '\0'; + len = epos - spos; + } else + len = strlen(spos); + if (len > 0) { + if(!(grp->ng_str[strpos] + = (char *) + malloc(len + 1))) { + freelists(this); + return (1); + } + memcpy(grp->ng_str[strpos], + spos, + len + 1); + } + } else + goto errout; + } + } else { + spos = strsep(&pos, ", \t"); + if (spos != NULL && parse_netgrp(this, spos)) { + freelists(this); + return (1); + } + } + if (pos == NULL) + break; + while (*pos == ' ' || *pos == ',' || *pos == '\t') + pos++; + } + return (0); + errout: + /*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, + spos);*/ + return (1); +} + +/* + * Read the netgroup file and save lines until the line for the netgroup + * is found. Return 1 if eof is encountered. + */ +static struct linelist * +read_for_group(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *pos, *spos, *linep = NULL, *olinep; + int len, olen, cont; + struct linelist *lp; + char line[LINSIZ + 1]; + + while (fgets(line, LINSIZ, pvt->fp) != NULL) { + pos = line; + if (*pos == '#') + continue; + while (*pos == ' ' || *pos == '\t') + pos++; + spos = pos; + while (*pos != ' ' && *pos != '\t' && *pos != '\n' && + *pos != '\0') + pos++; + len = pos - spos; + while (*pos == ' ' || *pos == '\t') + pos++; + if (*pos != '\n' && *pos != '\0') { + if (!(lp = malloc(sizeof (*lp)))) { + freelists(this); + return (NULL); + } + lp->l_parsed = 0; + if (!(lp->l_groupname = malloc(len + 1))) { + free(lp); + freelists(this); + return (NULL); + } + memcpy(lp->l_groupname, spos, len); + *(lp->l_groupname + len) = '\0'; + len = strlen(pos); + olen = 0; + olinep = NULL; + + /* + * Loop around handling line continuations. + */ + do { + if (*(pos + len - 1) == '\n') + len--; + if (*(pos + len - 1) == '\\') { + len--; + cont = 1; + } else + cont = 0; + if (len > 0) { + if (!(linep = malloc(olen + len + 1))){ + if (olen > 0) + free(olinep); + free(lp->l_groupname); + free(lp); + freelists(this); + errno = ENOMEM; + return (NULL); + } + if (olen > 0) { + memcpy(linep, olinep, olen); + free(olinep); + } + memcpy(linep + olen, pos, len); + olen += len; + *(linep + olen) = '\0'; + olinep = linep; + } + if (cont) { + if (fgets(line, LINSIZ, pvt->fp)) { + pos = line; + len = strlen(pos); + } else + cont = 0; + } + } while (cont); + lp->l_line = linep; + lp->l_next = pvt->linehead; + pvt->linehead = lp; + + /* + * If this is the one we wanted, we are done. + */ + if (!strcmp(lp->l_groupname, group)) + return (lp); + } + } + return (NULL); +} diff --git a/usr/src/lib/libresolv2/common/irs/lcl_nw.c b/usr/src/lib/libresolv2/common/irs/lcl_nw.c new file mode 100644 index 0000000000..38a7d584a3 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl_nw.c @@ -0,0 +1,378 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1989, 1993, 1995 + * The 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. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_nw.c,v 1.22 2001/05/29 05:49:07 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <fcntl.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include <isc/misc.h> +#include "irs_p.h" +#include "lcl_p.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct nwent net; + char * aliases[MAXALIASES]; + char addr[MAXADDRSIZE]; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static int init(struct irs_nw *this); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_nw * +irs_lcl_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt->fp) + (void)fclose(pvt->fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct nwent *p; + + if (init(this) == -1) + return(NULL); + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) + if (p->n_addrtype == type && p->n_length == length) + if (bitncmp(p->n_addr, net, length) == 0) + break; + return (p); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct nwent *p; + char **ap; + + if (init(this) == -1) + return(NULL); + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) { + if (ns_samename(p->n_name, name) == 1 && + p->n_addrtype == type) + break; + for (ap = p->n_aliases; *ap; ap++) + if ((ns_samename(*ap, name) == 1) && + (p->n_addrtype == type)) + goto found; + } + found: + return (p); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_NETWORKS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *ret = NULL; + char *p, *cp, **q; + char *bufp, *ndbuf, *dbuf = NULL; + int c, bufsiz, offset = 0; + + if (init(this) == -1) + return(NULL); + + if (pvt->fp == NULL) + nw_rewind(this); + if (pvt->fp == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + bufp = pvt->line; + bufsiz = sizeof(pvt->line); + + again: + p = fgets(bufp + offset, bufsiz - offset, pvt->fp); + if (p == NULL) + goto cleanup; + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; + pvt->net.n_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr, + sizeof pvt->addr); + if (pvt->net.n_length < 0) + goto again; + pvt->net.n_addrtype = AF_INET; + pvt->net.n_addr = pvt->addr; + q = pvt->net.n_aliases = pvt->aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + ret = &pvt->net; + + cleanup: + if (dbuf) + free(dbuf); + + return (ret); +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/irs/lcl_p.h b/usr/src/lib/libresolv2/common/irs/lcl_p.h new file mode 100644 index 0000000000..061ec1b8ad --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl_p.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: lcl_p.h,v 1.7 1999/01/08 19:24:51 vixie Exp $ + */ + +/* + * lcl_p.h - private include file for the local accessor functions. + */ + +#ifndef _LCL_P_H_INCLUDED +#define _LCL_P_H_INCLUDED + +/* + * Object state. + */ +struct lcl_p { + struct __res_state * res; + void (*free_res) __P((void *)); +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_lcl_acc __P((const char *)); +extern struct irs_gr * irs_lcl_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_lcl_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_lcl_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_lcl_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_lcl_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_lcl_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_lcl_ng __P((struct irs_acc *)); + +#endif /*_LCL_P_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2/common/irs/lcl_pr.c b/usr/src/lib/libresolv2/common/irs/lcl_pr.c new file mode 100644 index 0000000000..f6a8d312c9 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl_pr.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1989, 1993, 1995 + * The 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. + */ + +/* + * Portions Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pr.c,v 1.18 1999/10/13 17:11:20 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifndef _PATH_PROTOCOLS +#define _PATH_PROTOCOLS "/etc/protocols" +#endif +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct protoent proto; + char * proto_aliases[MAXALIASES]; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_pr * +irs_lcl_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *this); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + pr->res_get = NULL; + pr->res_set = NULL; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void) fclose(pvt->fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + + struct protoent *p; + char **cp; + + pr_rewind(this); + while ((p = pr_next(this))) { + if (!strcmp(p->p_name, name)) + goto found; + for (cp = p->p_aliases; *cp; cp++) + if (!strcmp(*cp, name)) + goto found; + } + found: + return (p); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct protoent *p; + + pr_rewind(this); + while ((p = pr_next(this))) + if (p->p_proto == proto) + break; + return (p); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_PROTOCOLS, "r" ))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **q; + char *bufp, *ndbuf, *dbuf = NULL; + int c, bufsiz, offset; + + if (!pvt->fp) + pr_rewind(this); + if (!pvt->fp) + return (NULL); + bufp = pvt->line; + bufsiz = BUFSIZ; + offset = 0; + again: + if ((p = fgets(bufp + offset, bufsiz - offset, pvt->fp)) == NULL) { + if (dbuf) + free(dbuf); + return (NULL); + } + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; + pvt->proto.p_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + pvt->proto.p_proto = atoi(cp); + q = pvt->proto.p_aliases = pvt->proto_aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->proto_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + return (&pvt->proto); +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} diff --git a/usr/src/lib/libresolv2/common/irs/lcl_pw.c b/usr/src/lib/libresolv2/common/irs/lcl_pw.c new file mode 100644 index 0000000000..5fa0d965e7 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl_pw.c @@ -0,0 +1,315 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1989, 1993, 1995 + * The 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. + */ + +/* + * Portions Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pw.c,v 1.20 2001/05/29 05:49:08 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Extern */ + +#include "port_before.h" + +#ifndef WANT_IRS_PW +static int __bind_irs_pw_unneeded; +#else + +#include <sys/param.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <db.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <utmp.h> +#include <unistd.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* + * The lookup techniques and data extraction code here must be kept + * in sync with that in `pwd_mkdb'. + */ + + +/* Types */ + +struct pvt { + struct passwd passwd; /* password structure */ + DB *pw_db; /* password database */ + int pw_keynum; /* key counter */ + int warned; + u_int max; + char * line; +}; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static int initdb(struct pvt *); +static int hashpw(struct irs_pw *, DBT *); + +/* Public */ +struct irs_pw * +irs_lcl_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + free(pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = NULL; + pw->res_set = NULL; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pw_db) { + (void)(pvt->pw_db->close)(pvt->pw_db); + pvt->pw_db = NULL; + } + if (pvt->line) + memput(pvt->line, pvt->max); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + DBT key; + char bf[sizeof(pvt->pw_keynum) + 1]; + + if (!initdb(pvt)) + return (NULL); + + ++pvt->pw_keynum; + bf[0] = _PW_KEYBYNUM; + memcpy(bf + 1, (char *)&pvt->pw_keynum, sizeof(pvt->pw_keynum)); + key.data = (u_char *)bf; + key.size = sizeof(pvt->pw_keynum) + 1; + return (hashpw(this, &key) ? &pvt->passwd : NULL); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + DBT key; + int len, rval; + char bf[UT_NAMESIZE + 1]; + + if (!initdb(pvt)) + return (NULL); + + bf[0] = _PW_KEYBYNAME; + len = strlen(name); + memcpy(bf + 1, name, MIN(len, UT_NAMESIZE)); + key.data = (u_char *)bf; + key.size = len + 1; + rval = hashpw(this, &key); + + return (rval ? &pvt->passwd : NULL); +} + + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + DBT key; + int keyuid, rval; + char bf[sizeof(keyuid) + 1]; + + if (!initdb(pvt)) + return (NULL); + + bf[0] = _PW_KEYBYUID; + keyuid = uid; + memcpy(bf + 1, &keyuid, sizeof(keyuid)); + key.data = (u_char *)bf; + key.size = sizeof(keyuid) + 1; + rval = hashpw(this, &key); + + return (rval ? &pvt->passwd : NULL); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->pw_keynum = 0; +} + +static void +pw_minimize(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pw_db != NULL) { + (void) (*pvt->pw_db->close)(pvt->pw_db); + pvt->pw_db = NULL; + } +} + +/* Private. */ + +static int +initdb(struct pvt *pvt) { + const char *p; + + if (pvt->pw_db) { + if (lseek((*pvt->pw_db->fd)(pvt->pw_db), 0L, SEEK_CUR) >= 0L) + return (1); + else + (void) (*pvt->pw_db->close)(pvt->pw_db); + } + pvt->pw_db = dbopen((p = _PATH_SMP_DB), O_RDONLY, 0, DB_HASH, NULL); + if (!pvt->pw_db) + pvt->pw_db = dbopen((p =_PATH_MP_DB), O_RDONLY, + 0, DB_HASH, NULL); + if (pvt->pw_db) + return (1); + if (!pvt->warned) { + syslog(LOG_ERR, "%s: %m", p); + pvt->warned++; + } + return (0); +} + +static int +hashpw(struct irs_pw *this, DBT *key) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *t, *l; + DBT data; + + if ((pvt->pw_db->get)(pvt->pw_db, key, &data, 0)) + return (0); + p = (char *)data.data; + if (data.size > pvt->max) { + size_t newlen = pvt->max + 1024; + char *p = memget(newlen); + if (p == NULL) { + return (0); + } + if (pvt->line != NULL) { + memcpy(p, pvt->line, pvt->max); + memput(pvt->line, pvt->max); + } + pvt->max = newlen; + pvt->line = p; + } + + /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ + t = pvt->line; + l = pvt->line + pvt->max; +#define EXPAND(e) if ((e = t) == NULL) return (0); else \ + do if (t >= l) return (0); while ((*t++ = *p++) != '\0') +#define SCALAR(v) if (t + sizeof v >= l) return (0); else \ + (memmove(&(v), p, sizeof v), p += sizeof v) + EXPAND(pvt->passwd.pw_name); + EXPAND(pvt->passwd.pw_passwd); + SCALAR(pvt->passwd.pw_uid); + SCALAR(pvt->passwd.pw_gid); + SCALAR(pvt->passwd.pw_change); + EXPAND(pvt->passwd.pw_class); + EXPAND(pvt->passwd.pw_gecos); + EXPAND(pvt->passwd.pw_dir); + EXPAND(pvt->passwd.pw_shell); + SCALAR(pvt->passwd.pw_expire); + return (1); +} + +#endif /* WANT_IRS_PW */ diff --git a/usr/src/lib/libresolv2/common/irs/lcl_sv.c b/usr/src/lib/libresolv2/common/irs/lcl_sv.c new file mode 100644 index 0000000000..afbdf3f3da --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/lcl_sv.c @@ -0,0 +1,438 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1989, 1993, 1995 + * The 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. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_sv.c,v 1.22 2001/06/18 14:43:59 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#ifdef IRS_LCL_SV_DB +#include <db.h> +#endif +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Types */ + +struct pvt { +#ifdef IRS_LCL_SV_DB + DB * dbh; + int dbf; +#endif + struct lcl_sv sv; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +/*global*/ struct servent * irs_lclsv_fnxt(struct lcl_sv *); +#ifdef IRS_LCL_SV_DB +static struct servent * sv_db_rec(struct lcl_sv *, DBT *, DBT *); +#endif + +/* Portability */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_sv * +irs_lcl_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + UNUSED(this); + + if ((sv = memget(sizeof *sv)) == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if ((pvt = memget(sizeof *pvt)) == NULL) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = NULL; + sv->res_set = NULL; +#ifdef IRS_LCL_SV_DB + pvt->dbf = R_FIRST; +#endif + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) + (*pvt->dbh->close)(pvt->dbh); +#endif + if (pvt->sv.fp) + fclose(pvt->sv.fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { +#ifdef IRS_LCL_SV_DB + struct pvt *pvt = (struct pvt *)this->private; +#endif + struct servent *p; + char **cp; + + sv_rewind(this); +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + + /* Note that (sizeof "/") == 2. */ + if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0) + > sizeof pvt->sv.line) + goto try_local; + key.data = pvt->sv.line; + key.size = SPRINTF((pvt->sv.line, "%s/%s", name, + proto ? proto : "")) + 1; + if (proto != NULL) { + if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) + return (NULL); + } else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) + != 0) + return (NULL); + return (sv_db_rec(&pvt->sv, &key, &data)); + } + try_local: +#endif + + while ((p = sv_next(this))) { + if (strcmp(name, p->s_name) == 0) + goto gotname; + for (cp = p->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; + gotname: + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { +#ifdef IRS_LCL_SV_DB + struct pvt *pvt = (struct pvt *)this->private; +#endif + struct servent *p; + + sv_rewind(this); +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + u_short *ports; + + ports = (u_short *)pvt->sv.line; + ports[0] = 0; + ports[1] = port; + key.data = ports; + key.size = sizeof(u_short) * 2; + if (proto && *proto) { + strncpy((char *)ports + key.size, proto, + BUFSIZ - key.size); + key.size += strlen((char *)ports + key.size) + 1; + if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) + return (NULL); + } else { + if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) + != 0) + return (NULL); + } + return (sv_db_rec(&pvt->sv, &key, &data)); + } +#endif + while ((p = sv_next(this))) { + if (p->s_port != port) + continue; + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->sv.fp) { + if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +#ifdef IRS_LCL_SV_DB + pvt->dbf = R_FIRST; + if (pvt->dbh != NULL) + return; + pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL); + if (pvt->dbh != NULL) { + if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) { + (*pvt->dbh->close)(pvt->dbh); + pvt->dbh = NULL; + } + return; + } +#endif + if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL) + return; + if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh == NULL && pvt->sv.fp == NULL) +#else + if (pvt->sv.fp == NULL) +#endif + sv_rewind(this); + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + + while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){ + pvt->dbf = R_NEXT; + if (((char *)key.data)[0]) + continue; + return (sv_db_rec(&pvt->sv, &key, &data)); + } + } +#endif + + if (pvt->sv.fp == NULL) + return (NULL); + return (irs_lclsv_fnxt(&pvt->sv)); +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + (*pvt->dbh->close)(pvt->dbh); + pvt->dbh = NULL; + } +#endif + if (pvt->sv.fp != NULL) { + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +} + +/* Quasipublic. */ + +struct servent * +irs_lclsv_fnxt(struct lcl_sv *sv) { + char *p, *cp, **q; + + again: + if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL) + return (NULL); + if (*p == '#') + goto again; + sv->serv.s_name = p; + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + if (*p == '\0' || *p == '#' || *p == '\n') + goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '\0' || *p == '#' || *p == '\n') + goto again; + sv->serv.s_port = htons((u_short)strtol(p, &cp, 10)); + if (cp == p || (*cp != '/' && *cp != ',')) + goto again; + p = cp + 1; + sv->serv.s_proto = p; + + q = sv->serv.s_aliases = sv->serv_aliases; + + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + + while (*p == ' ' || *p == '\t') { + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + ++p; + if (*p == '\0' || *p == '#' || *p == '\n') + break; + if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) + *q++ = p; + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + } + + *p = '\0'; + *q = NULL; + return (&sv->serv); +} + +/* Private. */ + +#ifdef IRS_LCL_SV_DB +static struct servent * +sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) { + char *p, **q; + int n; + + p = data->data; + p[data->size - 1] = '\0'; /* should be, but we depend on it */ + + if (((char *)key->data)[0] == '\0') { + if (key->size < sizeof(u_short)*2 || data->size < 2) + return (NULL); + sv->serv.s_port = ((u_short *)key->data)[1]; + n = strlen(p) + 1; + if ((size_t)n > sizeof(sv->line)) { + n = sizeof(sv->line); + } + memcpy(sv->line, p, n); + sv->serv.s_name = sv->line; + if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL) + *(sv->serv.s_proto)++ = '\0'; + p += n; + data->size -= n; + } else { + if (data->size < sizeof(u_short) + 1) + return (NULL); + if (key->size > sizeof(sv->line)) + key->size = sizeof(sv->line); + ((char *)key->data)[key->size - 1] = '\0'; + memcpy(sv->line, key->data, key->size); + sv->serv.s_name = sv->line; + if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL) + *(sv->serv.s_proto)++ = '\0'; + sv->serv.s_port = *(u_short *)data->data; + p += sizeof(u_short); + data->size -= sizeof(u_short); + } + q = sv->serv.s_aliases = sv->serv_aliases; + while (data->size > 0 && q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) { + + *q++ = p; + n = strlen(p) + 1; + data->size -= n; + p += n; + } + *q = NULL; + return (&sv->serv); +} +#endif diff --git a/usr/src/lib/libresolv2/common/irs/nis.c b/usr/src/lib/libresolv2/common/irs/nis.c new file mode 100644 index 0000000000..bdac586cc1 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis.c @@ -0,0 +1,158 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis.c,v 1.15 2001/05/29 05:49:11 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifdef WANT_IRS_NIS + +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "nis_p.h" + +/* Forward */ + +static void nis_close(struct irs_acc *); +static struct __res_state * nis_res_get(struct irs_acc *); +static void nis_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_acc * +irs_nis_acc(const char *options) { + struct nis_p *nis; + struct irs_acc *acc; + char *domain; + + UNUSED(options); + + if (yp_get_default_domain(&domain) != 0) + return (NULL); + if (!(nis = memget(sizeof *nis))) { + errno = ENOMEM; + return (NULL); + } + memset(nis, 0, sizeof *nis); + if (!(acc = memget(sizeof *acc))) { + memput(nis, sizeof *nis); + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + acc->private = nis; + nis->domain = strdup(domain); +#ifdef WANT_IRS_GR + acc->gr_map = irs_nis_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_nis_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_nis_sv; + acc->pr_map = irs_nis_pr; + acc->ho_map = irs_nis_ho; + acc->nw_map = irs_nis_nw; + acc->ng_map = irs_nis_ng; + acc->res_get = nis_res_get; + acc->res_set = nis_res_set; + acc->close = nis_close; + return (acc); +} + +/* Methods */ + +static struct __res_state * +nis_res_get(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + nis_res_set(this, res, free); + } + + if ((nis->res->options & RES_INIT) == 0 && + res_ninit(nis->res) < 0) + return (NULL); + + return (nis->res); +} + +static void +nis_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res && nis->free_res) { + res_nclose(nis->res); + (*nis->free_res)(nis->res); + } + + nis->res = res; + nis->free_res = free_res; +} + +static void +nis_close(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res && nis->free_res) + (*nis->free_res)(nis->res); + free(nis->domain); + memput(nis, sizeof *nis); + memput(this, sizeof *this); +} + +#endif /*WANT_IRS_NIS*/ diff --git a/usr/src/lib/libresolv2/common/irs/nis_gr.c b/usr/src/lib/libresolv2/common/irs/nis_gr.c new file mode 100644 index 0000000000..3f9f059db2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis_gr.c @@ -0,0 +1,360 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1989, 1993, 1995 + * The 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. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_gr.c,v 1.22 2002/07/08 06:26:11 marka Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_GR) || !defined(WANT_IRS_NIS) +static int __bind_irs_gr_unneeded; +#else + +#include <sys/param.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <isc/memcluster.h> + +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <errno.h> +#include <grp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <isc/memcluster.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + /* + * Need space to store the entries read from the group file. + * The members list also needs space per member, and the + * strings making up the user names must be allocated + * somewhere. Rather than doing lots of small allocations, + * we keep one buffer and resize it as needed. + */ + struct group group; + size_t nmemb; /* Malloc'd max index of gr_mem[]. */ + char * membuf; + size_t membufsize; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char group_bygid[] = "group.bygid"; +static /*const*/ char group_byname[] = "group.byname"; + +/* Forward */ + +static void gr_close(struct irs_gr *); +static struct group * gr_next(struct irs_gr *); +static struct group * gr_byname(struct irs_gr *, const char *); +static struct group * gr_bygid(struct irs_gr *, gid_t); +static void gr_rewind(struct irs_gr *); +static void gr_minimize(struct irs_gr *); + +static struct group * makegroupent(struct irs_gr *); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_gr * +irs_nis_gr(struct irs_acc *this) { + struct irs_gr *gr; + struct pvt *pvt; + + if (!(gr = memget(sizeof *gr))) { + errno = ENOMEM; + return (NULL); + } + memset(gr, 0x5e, sizeof *gr); + if (!(pvt = memget(sizeof *pvt))) { + memput(gr, sizeof *gr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + gr->private = pvt; + gr->close = gr_close; + gr->next = gr_next; + gr->byname = gr_byname; + gr->bygid = gr_bygid; + gr->rewind = gr_rewind; + gr->list = make_group_list; + gr->minimize = gr_minimize; + gr->res_get = NULL; + gr->res_set = NULL; + return (gr); +} + +/* Methods */ + +static void +gr_close(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->group.gr_mem) + free(pvt->group.gr_mem); + if (pvt->membuf) + free(pvt->membuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct group * +gr_next(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct group *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, group_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, group_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makegroupent(this); + } while (rval == NULL); + return (rval); +} + +static struct group * +gr_byname(struct irs_gr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, group_byname, name, strlen(name), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makegroupent(this)); +} + +static struct group * +gr_bygid(struct irs_gr *this, gid_t gid) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%u", (unsigned int)gid); + r = yp_match(pvt->nis_domain, group_bygid, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makegroupent(this)); +} + +static void +gr_rewind(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +gr_minimize(struct irs_gr *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct group * +makegroupent(struct irs_gr *this) { + struct pvt *pvt = (struct pvt *)this->private; + unsigned int num_members = 0; + char *cp, **new; + u_long t; + + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + pvt->nmemb = 0; + } + if (pvt->membuf) + free(pvt->membuf); + pvt->membuf = pvt->curval_data; + pvt->curval_data = NULL; + + cp = pvt->membuf; + pvt->group.gr_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->group.gr_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + errno = 0; + t = strtoul(cp, NULL, 10); + if (errno == ERANGE) + goto cleanup; + pvt->group.gr_gid = (gid_t) t; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + cp++; + + if (*cp && cp[strlen(cp)-1] == '\n') + cp[strlen(cp)-1] = '\0'; + + /* + * Parse the members out. + */ + while (*cp) { + if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { + pvt->nmemb += 10; + new = realloc(pvt->group.gr_mem, + pvt->nmemb * sizeof(char *)); + if (new == NULL) + goto cleanup; + pvt->group.gr_mem = new; + } + pvt->group.gr_mem[num_members++] = cp; + if (!(cp = strchr(cp, ','))) + break; + *cp++ = '\0'; + } + if (pvt->group.gr_mem == NULL) { + pvt->group.gr_mem = malloc(sizeof(char*)); + if (!pvt->group.gr_mem) + goto cleanup; + pvt->nmemb = 1; + } + pvt->group.gr_mem[num_members] = NULL; + + return (&pvt->group); + + cleanup: + if (pvt->group.gr_mem) { + free(pvt->group.gr_mem); + pvt->group.gr_mem = NULL; + pvt->nmemb = 0; + } + if (pvt->membuf) { + free(pvt->membuf); + pvt->membuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /* WANT_IRS_GR && WANT_IRS_NIS */ diff --git a/usr/src/lib/libresolv2/common/irs/nis_ho.c b/usr/src/lib/libresolv2/common/irs/nis_ho.c new file mode 100644 index 0000000000..7a38d12035 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis_ho.c @@ -0,0 +1,537 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_ho.c,v 1.19 2003/04/24 04:09:11 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES + 1]; + char hostbuf[8*1024]; + u_char host_addr[16]; /* IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; +static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; +static /*const*/ char hosts_byname[] = "hosts.byname"; +static /*const*/ char hosts_byaddr[] = "hosts.byaddr"; +static /*const*/ char ipnode_byname[] = "ipnode.byname"; +static /*const*/ char ipnode_byaddr[] = "ipnode.byaddr"; +static /*const*/ char yp_multi[] = "YP_MULTI_"; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static struct hostent * makehostent(struct irs_ho *this); +static void nisfree(struct pvt *, enum do_what); +static int init(struct irs_ho *this); + +/* Public */ + +struct irs_ho * +irs_nis_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_set = ho_res_set; + ho->res_get = ho_res_get; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + nisfree(pvt, do_all); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + char *tmp; + + UNUSED(af); + + if (init(this) == -1) + return (NULL); + + nisfree(pvt, do_val); + + strcpy(pvt->hostbuf, yp_multi); + strncat(pvt->hostbuf, name, sizeof(pvt->hostbuf) - sizeof(yp_multi)); + pvt->hostbuf[sizeof(pvt->hostbuf) - 1] = '\0'; + for (r = sizeof(yp_multi) - 1; pvt->hostbuf[r] != '\0'; r++) + if (isupper((unsigned char)pvt->hostbuf[r])) + tolower(pvt->hostbuf[r]); + + tmp = pvt->hostbuf; + r = yp_match(pvt->nis_domain, ipnode_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + tmp = pvt->hostbuf + sizeof(yp_multi) - 1; + r = yp_match(pvt->nis_domain, ipnode_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + } + if (r != 0) { + tmp = pvt->hostbuf; + r = yp_match(pvt->nis_domain, hosts_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + } + if (r != 0) { + tmp = pvt->hostbuf + sizeof(yp_multi) - 1; + r = yp_match(pvt->nis_domain, hosts_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makehostent(this)); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + const u_char *uaddr = addr; + int r; + + if (init(this) == -1) + return (NULL); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (const u_char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + if (inet_ntop(af, uaddr, tmp, sizeof tmp) == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + nisfree(pvt, do_val); + r = yp_match(pvt->nis_domain, ipnode_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) + r = yp_match(pvt->nis_domain, hosts_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makehostent(this)); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + int r; + + if (init(this) == -1) + return (NULL); + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, hosts_byaddr, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, hosts_byaddr, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + rval = makehostent(this); + } while (rval == NULL); + return (rval); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +struct nis_res_target { + struct nis_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct nis_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /* INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + +/* Private */ + +/* +ipnodes: +::1 localhost +127.0.0.1 localhost +1.2.3.4 FOO bar +1.2.6.4 FOO bar +1.2.6.5 host + +ipnodes.byname: +YP_MULTI_localhost ::1,127.0.0.1 localhost +YP_MULTI_foo 1.2.3.4,1.2.6.4 FOO bar +YP_MULTI_bar 1.2.3.4,1.2.6.4 FOO bar +host 1.2.6.5 host + +hosts.byname: +localhost 127.0.0.1 localhost +host 1.2.6.5 host +YP_MULTI_foo 1.2.3.4,1.2.6.4 FOO bar +YP_MULTI_bar 1.2.3.4,1.2.6.4 FOO bar +*/ + +static struct hostent * +makehostent(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *cp, **q, *p, *comma, *ap; + int af = 0, len = 0; + int multi = 0; + int addr = 0; + + p = pvt->curval_data; + if ((cp = strpbrk(p, "#\n")) != NULL) + *cp = '\0'; + if (!(cp = strpbrk(p, spaces))) + return (NULL); + *cp++ = '\0'; + ap = pvt->hostbuf; + do { + if ((comma = strchr(p, ',')) != NULL) { + *comma++ = '\0'; + multi = 1; + } + if ((ap + IN6ADDRSZ) > (pvt->hostbuf + sizeof(pvt->hostbuf))) + break; + if ((pvt->res->options & RES_USE_INET6) && + inet_pton(AF_INET6, p, ap) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_pton(AF_INET, p, pvt->host_addr) > 0) { + if (pvt->res->options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, ap); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + if (!multi) + return (NULL); + continue; + } + if (addr < MAXADDRS) { + pvt->h_addr_ptrs[addr++] = ap; + pvt->h_addr_ptrs[addr] = NULL; + ap += len; + } + } while ((p = comma) != NULL); + if (ap == pvt->hostbuf) + return (NULL); + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + cp += strspn(cp, spaces); + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, spaces)) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES]) + *q++ = cp; + if ((cp = strpbrk(cp, spaces)) != NULL) + *cp++ = '\0'; + } + *q = NULL; + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} +#endif /*WANT_IRS_NIS*/ diff --git a/usr/src/lib/libresolv2/common/irs/nis_ng.c b/usr/src/lib/libresolv2/common/irs/nis_ng.c new file mode 100644 index 0000000000..109e9cde1f --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis_ng.c @@ -0,0 +1,306 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_ng.c,v 1.17 2001/05/29 05:49:14 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> +#include <netinet/in.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <isc/assertions.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct tmpgrp { + const char * name; + const char * host; + const char * user; + const char * domain; + struct tmpgrp * next; +}; + +struct pvt { + char * nis_domain; + struct tmpgrp * tmp; + struct tmpgrp * cur; + char * tmpgroup; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char netgroup_map[] = "netgroup"; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +static void add_group_to_list(struct pvt *, const char *, int); +static void add_tuple_to_list(struct pvt *, const char *, char *); +static void tmpfree(struct pvt *); + +/* Public */ + +struct irs_ng * +irs_nis_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + tmpfree(pvt); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, const char **domain) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->cur) + return (0); + *host = pvt->cur->host; + *user = pvt->cur->user; + *domain = pvt->cur->domain; + pvt->cur = pvt->cur->next; + return (1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct tmpgrp *cur; + + tmpfree(pvt); + add_group_to_list(pvt, name, strlen(name)); + for (cur = pvt->tmp; cur; cur = cur->next) { + if ((!host || !cur->host || !strcmp(host, cur->host)) && + (!user || !cur->user || !strcmp(user, cur->user)) && + (!domain || !cur->domain || !strcmp(domain, cur->domain))) + break; + } + tmpfree(pvt); + return ((cur == NULL) ? 0 : 1); +} + +static void +ng_rewind(struct irs_ng *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + + /* Either hand back or free the existing list. */ + if (pvt->tmpgroup) { + if (pvt->tmp && !strcmp(pvt->tmpgroup, name)) + goto reset; + tmpfree(pvt); + } + pvt->tmpgroup = strdup(name); + add_group_to_list(pvt, name, strlen(name)); + reset: + pvt->cur = pvt->tmp; +} + +static void +ng_minimize(struct irs_ng *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static void +add_group_to_list(struct pvt *pvt, const char *name, int len) { + char *vdata, *cp, *np; + struct tmpgrp *tmp; + int vlen, r; + char *nametmp; + + /* Don't add the same group to the list more than once. */ + for (tmp = pvt->tmp; tmp; tmp = tmp->next) + if (!strcmp(tmp->name, name)) + return; + + DE_CONST(name, nametmp); + r = yp_match(pvt->nis_domain, netgroup_map, nametmp, len, + &vdata, &vlen); + if (r == 0) { + cp = vdata; + if (*cp && cp[strlen(cp)-1] == '\n') + cp[strlen(cp)-1] = '\0'; + for ( ; cp; cp = np) { + np = strchr(cp, ' '); + if (np) + *np++ = '\0'; + if (*cp == '(') + add_tuple_to_list(pvt, name, cp); + else + add_group_to_list(pvt, cp, strlen(cp)); + } + free(vdata); + } +} + +static void +add_tuple_to_list(struct pvt *pvt, const char *name, char *cp) { + struct tmpgrp *tmp; + char *tp, *np; + + INSIST(*cp++ == '('); + + tmp = malloc(sizeof *tmp + strlen(name) + sizeof '\0' + + strlen(cp) - sizeof ')'); + if (!tmp) + return; + memset(tmp, 0, sizeof *tmp); + tp = ((char *)tmp) + sizeof *tmp; + + /* Name */ + strcpy(tp, name); + tmp->name = tp; + tp += strlen(tp) + 1; + + /* Host */ + if (!(np = strchr(cp, ','))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->host = tp; + tp += strlen(tp) + 1; + cp = np; + + /* User */ + if (!(np = strchr(cp, ','))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->user = tp; + tp += strlen(tp) + 1; + cp = np; + + /* Domain */ + if (!(np = strchr(cp, ')'))) + goto cleanup; + *np++ = '\0'; + strcpy(tp, cp); + tmp->domain = tp; + + /* + * Empty string in file means wildcard, but + * NULL string in return value means wildcard. + */ + if (!*tmp->host) + tmp->host = NULL; + if (!*tmp->user) + tmp->user = NULL; + if (!*tmp->domain) + tmp->domain = NULL; + + /* Add to list (LIFO). */ + tmp->next = pvt->tmp; + pvt->tmp = tmp; + return; + + cleanup: + free(tmp); +} + +static void +tmpfree(struct pvt *pvt) { + struct tmpgrp *cur, *next; + + if (pvt->tmpgroup) { + free(pvt->tmpgroup); + pvt->tmpgroup = NULL; + } + for (cur = pvt->tmp; cur; cur = next) { + next = cur->next; + free(cur); + } + pvt->tmp = NULL; +} + +#endif /*WANT_IRS_NIS*/ diff --git a/usr/src/lib/libresolv2/common/irs/nis_nw.c b/usr/src/lib/libresolv2/common/irs/nis_nw.c new file mode 100644 index 0000000000..dae568e54b --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis_nw.c @@ -0,0 +1,388 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_nw.c,v 1.16 2001/05/29 05:49:15 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <errno.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + + struct nwent nwent; + char * nwbuf; + + char * aliases[MAXALIASES + 1]; + u_char addr[MAXADDRSIZE]; + + struct __res_state * res; + void (*free_res)(void *); +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char networks_byname[] = "networks.byname"; +static /*const*/ char networks_byaddr[] = "networks.byaddr"; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static struct nwent * makenwent(struct irs_nw *this); +static void nisfree(struct pvt *, enum do_what); +static int init(struct irs_nw *this); + +/* Public */ + +struct irs_nw * +irs_nis_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt->nwbuf) + free(pvt->nwbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int af) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "255.255.255.255/32"], *t; + int r; + + if (init(this) == -1) + return (NULL); + + if (af != AF_INET) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); + } + nisfree(pvt, do_val); + /* Try it with /CIDR first. */ + if (inet_net_ntop(AF_INET, net, length, tmp, sizeof tmp) == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + r = yp_match(pvt->nis_domain, networks_byaddr, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + /* Give it a shot without the /CIDR. */ + if ((t = strchr(tmp, '/')) != NULL) { + *t = '\0'; + r = yp_match(pvt->nis_domain, networks_byaddr, + tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + } + return (makenwent(this)); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + char *tmp; + + if (init(this) == -1) + return (NULL); + + if (af != AF_INET) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); + } + nisfree(pvt, do_val); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, networks_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + return (makenwent(this)); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + int r; + + if (init(this) == -1) + return (NULL); + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, networks_byaddr, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, networks_byaddr, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + rval = makenwent(this); + } while (rval == NULL); + return (rval); +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private */ + +static struct nwent * +makenwent(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *t, *cp, **ap; + + if (pvt->nwbuf) + free(pvt->nwbuf); + pvt->nwbuf = pvt->curval_data; + pvt->curval_data = NULL; + + if ((cp = strpbrk(pvt->nwbuf, "#\n")) != NULL) + *cp = '\0'; + cp = pvt->nwbuf; + + /* Name */ + pvt->nwent.n_name = cp; + cp += strcspn(cp, spaces); + if (!*cp) + goto cleanup; + *cp++ = '\0'; + cp += strspn(cp, spaces); + + /* Network */ + pvt->nwent.n_addrtype = AF_INET; + t = cp + strcspn(cp, spaces); + if (*t) + *t++ = '\0'; + pvt->nwent.n_length = inet_net_pton(AF_INET, cp, + pvt->addr, sizeof pvt->addr); + if (pvt->nwent.n_length < 0) + goto cleanup; + pvt->nwent.n_addr = pvt->addr; + cp = t; + + /* Aliases */ + ap = pvt->nwent.n_aliases = pvt->aliases; + while (*cp) { + if (ap >= &pvt->aliases[MAXALIASES]) + break; + *ap++ = cp; + cp += strcspn(cp, spaces); + if (!*cp) + break; + *cp++ = '\0'; + cp += strspn(cp, spaces); + } + *ap = NULL; + + return (&pvt->nwent); + + cleanup: + if (pvt->nwbuf) { + free(pvt->nwbuf); + pvt->nwbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} + +#endif /*WANT_IRS_NIS*/ diff --git a/usr/src/lib/libresolv2/common/irs/nis_p.h b/usr/src/lib/libresolv2/common/irs/nis_p.h new file mode 100644 index 0000000000..cd80d19235 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis_p.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: nis_p.h,v 1.6 1999/01/08 19:25:03 vixie Exp $ + */ + +/* + * nis_p.h - private include file for the NIS functions. + */ + +/* + * Object state. + */ +struct nis_p { + char * domain; + struct __res_state * res; + void (*free_res) __P((void *)); +}; + + +/* + * Methods. + */ + +extern struct irs_gr * irs_nis_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_nis_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_nis_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_nis_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_nis_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_nis_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_nis_ng __P((struct irs_acc *)); diff --git a/usr/src/lib/libresolv2/common/irs/nis_pr.c b/usr/src/lib/libresolv2/common/irs/nis_pr.c new file mode 100644 index 0000000000..c4695f3234 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis_pr.c @@ -0,0 +1,304 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_pr.c,v 1.14 2001/05/29 05:49:16 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct protoent proto; + char * prbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char protocols_byname[] = "protocols.byname"; +static /*const*/ char protocols_bynumber[] = "protocols.bynumber"; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static struct protoent * makeprotoent(struct irs_pr *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_pr * +irs_nis_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + pr->res_get = NULL; + pr->res_set = NULL; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + char *tmp; + + nisfree(pvt, do_val); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, protocols_byname, tmp, + strlen(tmp), &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makeprotoent(this)); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "-4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%d", num); + r = yp_match(pvt->nis_domain, protocols_bynumber, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makeprotoent(this)); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, protocols_bynumber, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, protocols_bynumber, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makeprotoent(this); + } while (rval == NULL); + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +pr_minimize(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct protoent * +makeprotoent(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, **t; + int n, m; + + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = pvt->curval_data; + pvt->curval_data = NULL; + + for (p = pvt->prbuf; *p && *p != '#';) + p++; + while (p > pvt->prbuf && isspace((unsigned char)(p[-1]))) + p--; + *p = '\0'; + + p = pvt->prbuf; + n = m = 0; + + pvt->proto.p_name = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + return (NULL); + *p++ = '\0'; + + while (*p && isspace((unsigned char)*p)) + p++; + pvt->proto.p_proto = atoi(p); + while (*p && !isspace((unsigned char)*p)) + p++; + *p++ = '\0'; + + while (*p) { + if ((n + 1) >= m || !pvt->proto.p_aliases) { + m += 10; + t = realloc(pvt->proto.p_aliases, + m * sizeof(char *)); + if (!t) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = t; + } + pvt->proto.p_aliases[n++] = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[n] = NULL; + return (&pvt->proto); + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ diff --git a/usr/src/lib/libresolv2/common/irs/nis_pw.c b/usr/src/lib/libresolv2/common/irs/nis_pw.c new file mode 100644 index 0000000000..5e8c4e76a2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis_pw.c @@ -0,0 +1,294 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_pw.c,v 1.17 2001/05/29 05:49:18 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(WANT_IRS_PW) || !defined(WANT_IRS_NIS) +static int __bind_irs_pw_unneeded; +#else + +#include <sys/param.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <isc/memcluster.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <errno.h> +#include <fcntl.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <isc/memcluster.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + struct passwd passwd; + char * pwbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char passwd_byname[] = "passwd.byname"; +static /*const*/ char passwd_byuid[] = "passwd.byuid"; + +/* Forward */ + +static void pw_close(struct irs_pw *); +static struct passwd * pw_next(struct irs_pw *); +static struct passwd * pw_byname(struct irs_pw *, const char *); +static struct passwd * pw_byuid(struct irs_pw *, uid_t); +static void pw_rewind(struct irs_pw *); +static void pw_minimize(struct irs_pw *); + +static struct passwd * makepasswdent(struct irs_pw *); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_pw * +irs_nis_pw(struct irs_acc *this) { + struct irs_pw *pw; + struct pvt *pvt; + + if (!(pw = memget(sizeof *pw))) { + errno = ENOMEM; + return (NULL); + } + memset(pw, 0x5e, sizeof *pw); + if (!(pvt = memget(sizeof *pvt))) { + memput(pw, sizeof *pw); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + pw->private = pvt; + pw->close = pw_close; + pw->next = pw_next; + pw->byname = pw_byname; + pw->byuid = pw_byuid; + pw->rewind = pw_rewind; + pw->minimize = pw_minimize; + pw->res_get = NULL; + pw->res_set = NULL; + return (pw); +} + +/* Methods */ + +static void +pw_close(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->pwbuf) + free(pvt->pwbuf); + nisfree(pvt, do_all); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct passwd * +pw_next(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct passwd *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, passwd_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, passwd_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makepasswdent(this); + } while (rval == NULL); + return (rval); +} + +static struct passwd * +pw_byname(struct irs_pw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + int r; + char *tmp; + + nisfree(pvt, do_val); + DE_CONST(name, tmp); + r = yp_match(pvt->nis_domain, passwd_byname, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makepasswdent(this)); +} + +static struct passwd * +pw_byuid(struct irs_pw *this, uid_t uid) { + struct pvt *pvt = (struct pvt *)this->private; + char tmp[sizeof "4294967295"]; + int r; + + nisfree(pvt, do_val); + (void) sprintf(tmp, "%u", (unsigned int)uid); + r = yp_match(pvt->nis_domain, passwd_byuid, tmp, strlen(tmp), + &pvt->curval_data, &pvt->curval_len); + if (r != 0) { + errno = ENOENT; + return (NULL); + } + return (makepasswdent(this)); +} + +static void +pw_rewind(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static void +pw_minimize(struct irs_pw *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct passwd * +makepasswdent(struct irs_pw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp; + + memset(&pvt->passwd, 0, sizeof pvt->passwd); + if (pvt->pwbuf) + free(pvt->pwbuf); + pvt->pwbuf = pvt->curval_data; + pvt->curval_data = NULL; + + cp = pvt->pwbuf; + pvt->passwd.pw_name = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; +#ifdef HAS_PW_CLASS + pvt->passwd.pw_class = cp; /* Needs to point at a \0. */ +#endif + *cp++ = '\0'; + + pvt->passwd.pw_passwd = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_uid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gid = atoi(cp); + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_gecos = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_dir = cp; + if (!(cp = strchr(cp, ':'))) + goto cleanup; + *cp++ = '\0'; + + pvt->passwd.pw_shell = cp; + + if ((cp = strchr(cp, '\n')) != NULL) + *cp = '\0'; + + return (&pvt->passwd); + + cleanup: + free(pvt->pwbuf); + pvt->pwbuf = NULL; + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /* WANT_IRS_PW && WANT_IRS_NIS */ diff --git a/usr/src/lib/libresolv2/common/irs/nis_sv.c b/usr/src/lib/libresolv2/common/irs/nis_sv.c new file mode 100644 index 0000000000..da5cf57693 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nis_sv.c @@ -0,0 +1,312 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis_sv.c,v 1.15 2001/05/29 05:49:19 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#ifndef WANT_IRS_NIS +static int __bind_irs_nis_unneeded; +#else + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <sys/socket.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "nis_p.h" + +/* Definitions */ + +struct pvt { + int needrewind; + char * nis_domain; + char * curkey_data; + int curkey_len; + char * curval_data; + int curval_len; + char line[BUFSIZ+1]; + struct servent serv; + char * svbuf; +}; + +enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 }; + +static /*const*/ char services_byname[] = "services.byname"; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static struct servent * makeservent(struct irs_sv *this); +static void nisfree(struct pvt *, enum do_what); + +/* Public */ + +struct irs_sv * +irs_nis_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = memget(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = memget(sizeof *pvt))) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->needrewind = 1; + pvt->nis_domain = ((struct nis_p *)this->private)->domain; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = NULL; + sv->res_set = NULL; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nisfree(pvt, do_all); + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct servent *serv; + char **sap; + + sv_rewind(this); + while ((serv = sv_next(this)) != NULL) { + if (proto != NULL && strcmp(proto, serv->s_proto)) + continue; + if (!strcmp(name, serv->s_name)) + break; + for (sap = serv->s_aliases; sap && *sap; sap++) + if (!strcmp(name, *sap)) + break; + } + return (serv); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct servent *serv; + + sv_rewind(this); + while ((serv = sv_next(this)) != NULL) { + if (proto != NULL && strcmp(proto, serv->s_proto)) + continue; + if (serv->s_port == port) + break; + } + return (serv); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pvt->needrewind = 1; +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + int r; + + do { + if (pvt->needrewind) { + nisfree(pvt, do_all); + r = yp_first(pvt->nis_domain, services_byname, + &pvt->curkey_data, &pvt->curkey_len, + &pvt->curval_data, &pvt->curval_len); + pvt->needrewind = 0; + } else { + char *newkey_data; + int newkey_len; + + nisfree(pvt, do_val); + r = yp_next(pvt->nis_domain, services_byname, + pvt->curkey_data, pvt->curkey_len, + &newkey_data, &newkey_len, + &pvt->curval_data, &pvt->curval_len); + nisfree(pvt, do_key); + pvt->curkey_data = newkey_data; + pvt->curkey_len = newkey_len; + } + if (r != 0) { + errno = ENOENT; + return (NULL); + } + rval = makeservent(this); + } while (rval == NULL); + return (rval); +} + +static void +sv_minimize(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct servent * +makeservent(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + static const char spaces[] = " \t"; + char *p, **t; + int n, m; + + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = pvt->curval_data; + pvt->curval_data = NULL; + + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + + if ((p = strpbrk(pvt->svbuf, "#\n"))) + *p = '\0'; + + p = pvt->svbuf; + + pvt->serv.s_name = p; + p += strcspn(p, spaces); + if (!*p) + goto cleanup; + *p++ = '\0'; + p += strspn(p, spaces); + + pvt->serv.s_port = htons((u_short) atoi(p)); + pvt->serv.s_proto = NULL; + + while (*p && !isspace((unsigned char)*p)) + if (*p++ == '/') + pvt->serv.s_proto = p; + if (!pvt->serv.s_proto) + goto cleanup; + if (*p) { + *p++ = '\0'; + p += strspn(p, spaces); + } + + n = m = 0; + while (*p) { + if ((n + 1) >= m || !pvt->serv.s_aliases) { + m += 10; + t = realloc(pvt->serv.s_aliases, m * sizeof(char *)); + if (!t) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = t; + } + pvt->serv.s_aliases[n++] = p; + p += strcspn(p, spaces); + if (!*p) + break; + *p++ = '\0'; + p += strspn(p, spaces); + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[n] = NULL; + return (&pvt->serv); + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +nisfree(struct pvt *pvt, enum do_what do_what) { + if ((do_what & do_key) && pvt->curkey_data) { + free(pvt->curkey_data); + pvt->curkey_data = NULL; + } + if ((do_what & do_val) && pvt->curval_data) { + free(pvt->curval_data); + pvt->curval_data = NULL; + } +} + +#endif /*WANT_IRS_NIS*/ diff --git a/usr/src/lib/libresolv2/common/irs/nul_ng.c b/usr/src/lib/libresolv2/common/irs/nul_ng.c new file mode 100644 index 0000000000..7aaa760cd3 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/nul_ng.c @@ -0,0 +1,133 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nul_ng.c,v 1.11 2001/05/29 05:49:20 marka Exp $"; +#endif + +/* + * nul_ng.c - the netgroup accessor null map + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Forward. */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public. */ + +struct irs_ng * +irs_nul_ng(struct irs_acc *this) { + struct irs_ng *ng; + + UNUSED(this); + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + ng->private = NULL; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods. */ + +static void +ng_close(struct irs_ng *this) { + memput(this, sizeof *this); +} + +/* ARGSUSED */ +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + UNUSED(this); + UNUSED(host); + UNUSED(user); + UNUSED(domain); + errno = ENOENT; + return (-1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + UNUSED(this); + UNUSED(name); + UNUSED(user); + UNUSED(host); + UNUSED(domain); + errno = ENODEV; + return (-1); +} + +static void +ng_rewind(struct irs_ng *this, const char *netgroup) { + UNUSED(this); + UNUSED(netgroup); + /* NOOP */ +} + +static void +ng_minimize(struct irs_ng *this) { + UNUSED(this); + /* NOOP */ +} diff --git a/usr/src/lib/libresolv2/common/irs/pathnames.h b/usr/src/lib/libresolv2/common/irs/pathnames.h new file mode 100644 index 0000000000..c223a6bf53 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/pathnames.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: pathnames.h,v 1.7 1999/01/08 19:25:10 vixie Exp $ + */ + +#ifndef _PATH_IRS_CONF +#define _PATH_IRS_CONF "/etc/irs.conf" +#endif + +#ifndef _PATH_NETWORKS +#define _PATH_NETWORKS "/etc/networks" +#endif + +#ifndef _PATH_GROUP +#define _PATH_GROUP "/etc/group" +#endif + +#ifndef _PATH_NETGROUP +#define _PATH_NETGROUP "/etc/netgroup" +#endif + +#ifndef _PATH_SERVICES +#define _PATH_SERVICES "/etc/services" +#endif + +#ifdef IRS_LCL_SV_DB +#ifndef _PATH_SERVICES_DB +#define _PATH_SERVICES_DB _PATH_SERVICES ".db" +#endif +#endif + +#ifndef _PATH_HESIOD_CONF +#define _PATH_HESIOD_CONF "/etc/hesiod.conf" +#endif diff --git a/usr/src/lib/libresolv2/common/irs/util.c b/usr/src/lib/libresolv2/common/irs/util.c new file mode 100644 index 0000000000..2f27b2ae34 --- /dev/null +++ b/usr/src/lib/libresolv2/common/irs/util.c @@ -0,0 +1,113 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: util.c,v 1.12 2001/05/29 05:49:21 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +void +map_v4v6_address(const char *src, char *dst) { + u_char *p = (u_char *)dst; + char tmp[NS_INADDRSZ]; + int i; + + /* Stash a temporary copy so our caller can update in place. */ + memcpy(tmp, src, NS_INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Retrieve the saved copy and we're done. */ + memcpy((void*)p, tmp, NS_INADDRSZ); +} + +int +make_group_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct group *grp; + int i, ng; + int ret, maxgroups; + + ret = -1; + ng = 0; + maxgroups = *ngroups; + /* + * When installing primary group, duplicate it; + * the first element of groups is the effective gid + * and will be overwritten when a setgid file is executed. + */ + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + /* + * Scan the group file to find additional groups. + */ + (*this->rewind)(this); + while ((grp = (*this->next)(this)) != NULL) { + if ((gid_t)grp->gr_gid == basegid) + continue; + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], name)) { + if (ng >= maxgroups) + goto done; + groups[ng++] = grp->gr_gid; + break; + } + } + } + ret = 0; + done: + *ngroups = ng; + return (ret); +} diff --git a/usr/src/lib/libresolv2/common/isc/assertions.c b/usr/src/lib/libresolv2/common/isc/assertions.c new file mode 100644 index 0000000000..1afff62208 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/assertions.c @@ -0,0 +1,98 @@ +/* + * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: assertions.c,v 8.4 2001/05/29 05:49:22 marka Exp $"; +#endif + +#include "port_before.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/assertions.h> + +#include "port_after.h" + +/* + * Forward. + */ + +static void default_assertion_failed(const char *, int, assertion_type, + const char *, int); + +/* + * Public. + */ + +assertion_failure_callback __assertion_failed = default_assertion_failed; + +void +set_assertion_failure_callback(assertion_failure_callback f) { + if (f == NULL) + __assertion_failed = default_assertion_failed; + else + __assertion_failed = f; +} + +const char * +assertion_type_to_text(assertion_type type) { + const char *result; + + switch (type) { + case assert_require: + result = "REQUIRE"; + break; + case assert_ensure: + result = "ENSURE"; + break; + case assert_insist: + result = "INSIST"; + break; + case assert_invariant: + result = "INVARIANT"; + break; + default: + result = NULL; + } + return (result); +} + +/* + * Private. + */ + +static void +default_assertion_failed(const char *file, int line, assertion_type type, + const char *cond, int print_errno) +{ + fprintf(stderr, "%s:%d: %s(%s)%s%s failed.\n", + file, line, assertion_type_to_text(type), cond, + (print_errno) ? ": " : "", + (print_errno) ? strerror(errno) : ""); + abort(); + /* NOTREACHED */ +} diff --git a/usr/src/lib/libresolv2/common/isc/base64.c b/usr/src/lib/libresolv2/common/isc/base64.c new file mode 100644 index 0000000000..3e55d161ce --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/base64.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: base64.c,v 8.7 1999/10/13 16:39:33 vixie Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#ifdef ORIGINAL_ISC_CODE +#else +#pragma weak __b64_ntop = b64_ntop +#pragma weak __b64_pton = b64_pton +#endif /* ORIGINAL_ISC_CODE */ + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/usr/src/lib/libresolv2/common/isc/bitncmp.c b/usr/src/lib/libresolv2/common/isc/bitncmp.c new file mode 100644 index 0000000000..cc205bdad6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/bitncmp.c @@ -0,0 +1,73 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: bitncmp.c,v 1.7 2001/05/29 05:49:23 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> + +#include <string.h> + +#include "port_after.h" + +#include <isc/misc.h> + +/* + * int + * bitncmp(l, r, n) + * compare bit masks l and r, for n bits. + * return: + * -1, 1, or 0 in the libc tradition. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +bitncmp(const void *l, const void *r, int n) { + u_int lb, rb; + int x, b; + + b = n / 8; + x = memcmp(l, r, b); + if (x) + return (x); + + lb = ((const u_char *)l)[b]; + rb = ((const u_char *)r)[b]; + for (b = n % 8; b > 0; b--) { + if ((lb & 0x80) != (rb & 0x80)) { + if (lb & 0x80) + return (1); + return (-1); + } + lb <<= 1; + rb <<= 1; + } + return (0); +} diff --git a/usr/src/lib/libresolv2/common/isc/ctl_clnt.c b/usr/src/lib/libresolv2/common/isc/ctl_clnt.c new file mode 100644 index 0000000000..5da3f30075 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ctl_clnt.c @@ -0,0 +1,609 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_clnt.c,v 8.18 2002/07/08 05:10:23 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Extern. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <isc/assertions.h> +#include <isc/ctl.h> +#include <isc/eventlib.h> +#include <isc/list.h> +#include <isc/memcluster.h> + +#include "ctl_p.h" + +#include "port_after.h" + +/* Constants. */ + + +/* Macros. */ + +#define donefunc_p(ctx) ((ctx).donefunc != NULL) +#define arpacode_p(line) (isdigit((unsigned char)(line[0])) && \ + isdigit((unsigned char)(line[1])) && \ + isdigit((unsigned char)(line[2]))) +#define arpacont_p(line) (line[3] == '-') +#define arpadone_p(line) (line[3] == ' ' || line[3] == '\t' || \ + line[3] == '\r' || line[3] == '\0') + +/* Types. */ + +enum state { + initializing = 0, connecting, connected, destroyed +}; + +struct ctl_tran { + LINK(struct ctl_tran) link; + LINK(struct ctl_tran) wlink; + struct ctl_cctx * ctx; + struct ctl_buf outbuf; + ctl_clntdone donefunc; + void * uap; +}; + +struct ctl_cctx { + enum state state; + evContext ev; + int sock; + ctl_logfunc logger; + ctl_clntdone donefunc; + void * uap; + evConnID coID; + evTimerID tiID; + evFileID rdID; + evStreamID wrID; + struct ctl_buf inbuf; + struct timespec timeout; + LIST(struct ctl_tran) tran; + LIST(struct ctl_tran) wtran; +}; + +/* Forward. */ + +static struct ctl_tran *new_tran(struct ctl_cctx *, ctl_clntdone, void *, int); +static void start_write(struct ctl_cctx *); +static void destroy(struct ctl_cctx *, int); +static void error(struct ctl_cctx *); +static void new_state(struct ctl_cctx *, enum state); +static void conn_done(evContext, void *, int, + const void *, int, + const void *, int); +static void write_done(evContext, void *, int, int); +static void start_read(struct ctl_cctx *); +static void stop_read(struct ctl_cctx *); +static void readable(evContext, void *, int, int); +static void start_timer(struct ctl_cctx *); +static void stop_timer(struct ctl_cctx *); +static void touch_timer(struct ctl_cctx *); +static void timer(evContext, void *, + struct timespec, struct timespec); + +/* Private data. */ + +static const char * const state_names[] = { + "initializing", "connecting", "connected", "destroyed" +}; + +/* Public. */ + +/* + * void + * ctl_client() + * create, condition, and connect to a listener on the control port. + */ +struct ctl_cctx * +ctl_client(evContext lev, const struct sockaddr *cap, size_t cap_len, + const struct sockaddr *sap, size_t sap_len, + ctl_clntdone donefunc, void *uap, + u_int timeout, ctl_logfunc logger) +{ + static const char me[] = "ctl_client"; + static const int on = 1; + struct ctl_cctx *ctx; + struct sockaddr *captmp; + + if (logger == NULL) + logger = ctl_logger; + ctx = memget(sizeof *ctx); + if (ctx == NULL) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + goto fatal; + } + ctx->state = initializing; + ctx->ev = lev; + ctx->logger = logger; + ctx->timeout = evConsTime(timeout, 0); + ctx->donefunc = donefunc; + ctx->uap = uap; + ctx->coID.opaque = NULL; + ctx->tiID.opaque = NULL; + ctx->rdID.opaque = NULL; + ctx->wrID.opaque = NULL; + buffer_init(ctx->inbuf); + INIT_LIST(ctx->tran); + INIT_LIST(ctx->wtran); + ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC); + if (ctx->sock > evHighestFD(ctx->ev)) { + ctx->sock = -1; + errno = ENOTSOCK; + } + if (ctx->sock < 0) { + (*ctx->logger)(ctl_error, "%s: socket: %s", + me, strerror(errno)); + goto fatal; + } + if (cap != NULL) { + if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, + (const char *)&on, sizeof on) != 0) { + (*ctx->logger)(ctl_warning, + "%s: setsockopt(REUSEADDR): %s", + me, strerror(errno)); + } + DE_CONST(cap, captmp); + if (bind(ctx->sock, captmp, cap_len) < 0) { + (*ctx->logger)(ctl_error, "%s: bind: %s", me, + strerror(errno)); + goto fatal; + } + } + if (evConnect(lev, ctx->sock, (const struct sockaddr *)sap, sap_len, + conn_done, ctx, &ctx->coID) < 0) { + (*ctx->logger)(ctl_error, "%s: evConnect(fd %d): %s", + me, ctx->sock, strerror(errno)); + fatal: + if (ctx != NULL) { + if (ctx->sock >= 0) + close(ctx->sock); + memput(ctx, sizeof *ctx); + } + return (NULL); + } + new_state(ctx, connecting); + return (ctx); +} + +/* + * void + * ctl_endclient(ctx) + * close a client and release all of its resources. + */ +void +ctl_endclient(struct ctl_cctx *ctx) { + if (ctx->state != destroyed) + destroy(ctx, 0); + memput(ctx, sizeof *ctx); +} + +/* + * int + * ctl_command(ctx, cmd, len, donefunc, uap) + * Queue a transaction, which will begin with sending cmd + * and complete by calling donefunc with the answer. + */ +int +ctl_command(struct ctl_cctx *ctx, const char *cmd, size_t len, + ctl_clntdone donefunc, void *uap) +{ + struct ctl_tran *tran; + char *pc; + unsigned int n; + + switch (ctx->state) { + case destroyed: + errno = ENOTCONN; + return (-1); + case connecting: + case connected: + break; + default: + abort(); + } + if (len >= MAX_LINELEN) { + errno = EMSGSIZE; + return (-1); + } + tran = new_tran(ctx, donefunc, uap, 1); + if (tran == NULL) + return (-1); + if (ctl_bufget(&tran->outbuf, ctx->logger) < 0) + return (-1); + memcpy(tran->outbuf.text, cmd, len); + tran->outbuf.used = len; + for (pc = tran->outbuf.text, n = 0; n < tran->outbuf.used; pc++, n++) + if (!isascii((unsigned char)*pc) || + !isprint((unsigned char)*pc)) + *pc = '\040'; + start_write(ctx); + return (0); +} + +/* Private. */ + +static struct ctl_tran * +new_tran(struct ctl_cctx *ctx, ctl_clntdone donefunc, void *uap, int w) { + struct ctl_tran *new = memget(sizeof *new); + + if (new == NULL) + return (NULL); + new->ctx = ctx; + buffer_init(new->outbuf); + new->donefunc = donefunc; + new->uap = uap; + INIT_LINK(new, link); + INIT_LINK(new, wlink); + APPEND(ctx->tran, new, link); + if (w) + APPEND(ctx->wtran, new, wlink); + return (new); +} + +static void +start_write(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_write"; + struct ctl_tran *tran; + struct iovec iov[2], *iovp = iov; + char * tmp; + + REQUIRE(ctx->state == connecting || ctx->state == connected); + /* If there is a write in progress, don't try to write more yet. */ + if (ctx->wrID.opaque != NULL) + return; + /* If there are no trans, make sure timer is off, and we're done. */ + if (EMPTY(ctx->wtran)) { + if (ctx->tiID.opaque != NULL) + stop_timer(ctx); + return; + } + /* Pull it off the head of the write queue. */ + tran = HEAD(ctx->wtran); + UNLINK(ctx->wtran, tran, wlink); + /* Since there are some trans, make sure timer is successfully "on". */ + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + else + start_timer(ctx); + if (ctx->state == destroyed) + return; + /* Marshall a newline-terminated message and clock it out. */ + *iovp++ = evConsIovec(tran->outbuf.text, tran->outbuf.used); + DE_CONST("\r\n", tmp); + *iovp++ = evConsIovec(tmp, 2); + if (evWrite(ctx->ev, ctx->sock, iov, iovp - iov, + write_done, tran, &ctx->wrID) < 0) { + (*ctx->logger)(ctl_error, "%s: evWrite: %s", me, + strerror(errno)); + error(ctx); + return; + } + if (evTimeRW(ctx->ev, ctx->wrID, ctx->tiID) < 0) { + (*ctx->logger)(ctl_error, "%s: evTimeRW: %s", me, + strerror(errno)); + error(ctx); + return; + } +} + +static void +destroy(struct ctl_cctx *ctx, int notify) { + struct ctl_tran *this, *next; + + if (ctx->sock != -1) { + (void) close(ctx->sock); + ctx->sock = -1; + } + switch (ctx->state) { + case connecting: + REQUIRE(ctx->wrID.opaque == NULL); + REQUIRE(EMPTY(ctx->tran)); + /* + * This test is nec'y since destroy() can be called from + * start_read() while the state is still "connecting". + */ + if (ctx->coID.opaque != NULL) { + (void)evCancelConn(ctx->ev, ctx->coID); + ctx->coID.opaque = NULL; + } + break; + case connected: + REQUIRE(ctx->coID.opaque == NULL); + if (ctx->wrID.opaque != NULL) { + (void)evCancelRW(ctx->ev, ctx->wrID); + ctx->wrID.opaque = NULL; + } + if (ctx->rdID.opaque != NULL) + stop_read(ctx); + break; + case destroyed: + break; + default: + abort(); + } + if (allocated_p(ctx->inbuf)) + ctl_bufput(&ctx->inbuf); + for (this = HEAD(ctx->tran); this != NULL; this = next) { + next = NEXT(this, link); + if (allocated_p(this->outbuf)) + ctl_bufput(&this->outbuf); + if (notify && this->donefunc != NULL) + (*this->donefunc)(ctx, this->uap, NULL, 0); + memput(this, sizeof *this); + } + if (ctx->tiID.opaque != NULL) + stop_timer(ctx); + new_state(ctx, destroyed); +} + +static void +error(struct ctl_cctx *ctx) { + REQUIRE(ctx->state != destroyed); + destroy(ctx, 1); +} + +static void +new_state(struct ctl_cctx *ctx, enum state new_state) { + static const char me[] = "isc/ctl_clnt::new_state"; + + (*ctx->logger)(ctl_debug, "%s: %s -> %s", me, + state_names[ctx->state], state_names[new_state]); + ctx->state = new_state; +} + +static void +conn_done(evContext ev, void *uap, int fd, + const void *la, int lalen, + const void *ra, int ralen) +{ + static const char me[] = "isc/ctl_clnt::conn_done"; + struct ctl_cctx *ctx = uap; + struct ctl_tran *tran; + + UNUSED(ev); + UNUSED(la); + UNUSED(lalen); + UNUSED(ra); + UNUSED(ralen); + + ctx->coID.opaque = NULL; + if (fd < 0) { + (*ctx->logger)(ctl_error, "%s: evConnect: %s", me, + strerror(errno)); + error(ctx); + return; + } + new_state(ctx, connected); + tran = new_tran(ctx, ctx->donefunc, ctx->uap, 0); + if (tran == NULL) { + (*ctx->logger)(ctl_error, "%s: new_tran failed: %s", me, + strerror(errno)); + error(ctx); + return; + } + start_read(ctx); + if (ctx->state == destroyed) { + (*ctx->logger)(ctl_error, "%s: start_read failed: %s", + me, strerror(errno)); + error(ctx); + return; + } +} + +static void +write_done(evContext lev, void *uap, int fd, int bytes) { + struct ctl_tran *tran = (struct ctl_tran *)uap; + struct ctl_cctx *ctx = tran->ctx; + + UNUSED(lev); + UNUSED(fd); + + ctx->wrID.opaque = NULL; + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + ctl_bufput(&tran->outbuf); + start_write(ctx); + if (bytes < 0) + destroy(ctx, 1); + else + start_read(ctx); +} + +static void +start_read(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_read"; + + REQUIRE(ctx->state == connecting || ctx->state == connected); + REQUIRE(ctx->rdID.opaque == NULL); + if (evSelectFD(ctx->ev, ctx->sock, EV_READ, readable, ctx, + &ctx->rdID) < 0) + { + (*ctx->logger)(ctl_error, "%s: evSelect(fd %d): %s", me, + ctx->sock, strerror(errno)); + error(ctx); + return; + } +} + +static void +stop_read(struct ctl_cctx *ctx) { + REQUIRE(ctx->coID.opaque == NULL); + REQUIRE(ctx->rdID.opaque != NULL); + (void)evDeselectFD(ctx->ev, ctx->rdID); + ctx->rdID.opaque = NULL; +} + +static void +readable(evContext ev, void *uap, int fd, int evmask) { + static const char me[] = "isc/ctl_clnt::readable"; + struct ctl_cctx *ctx = uap; + struct ctl_tran *tran; + ssize_t n; + char *eos; + + UNUSED(ev); + + REQUIRE(ctx != NULL); + REQUIRE(fd >= 0); + REQUIRE(evmask == EV_READ); + REQUIRE(ctx->state == connected); + REQUIRE(!EMPTY(ctx->tran)); + tran = HEAD(ctx->tran); + if (!allocated_p(ctx->inbuf) && + ctl_bufget(&ctx->inbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: can't get an input buffer", me); + error(ctx); + return; + } + n = read(ctx->sock, ctx->inbuf.text + ctx->inbuf.used, + MAX_LINELEN - ctx->inbuf.used); + if (n <= 0) { + (*ctx->logger)(ctl_warning, "%s: read: %s", me, + (n == 0) ? "Unexpected EOF" : strerror(errno)); + error(ctx); + return; + } + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + ctx->inbuf.used += n; + (*ctx->logger)(ctl_debug, "%s: read %d, used %d", me, + n, ctx->inbuf.used); + again: + eos = memchr(ctx->inbuf.text, '\n', ctx->inbuf.used); + if (eos != NULL && eos != ctx->inbuf.text && eos[-1] == '\r') { + int done = 0; + + eos[-1] = '\0'; + if (!arpacode_p(ctx->inbuf.text)) { + /* XXX Doesn't FTP do this sometimes? Is it legal? */ + (*ctx->logger)(ctl_error, "%s: no arpa code (%s)", me, + ctx->inbuf.text); + error(ctx); + return; + } + if (arpadone_p(ctx->inbuf.text)) + done = 1; + else if (arpacont_p(ctx->inbuf.text)) + done = 0; + else { + /* XXX Doesn't FTP do this sometimes? Is it legal? */ + (*ctx->logger)(ctl_error, "%s: no arpa flag (%s)", me, + ctx->inbuf.text); + error(ctx); + return; + } + (*tran->donefunc)(ctx, tran->uap, ctx->inbuf.text, + (done ? 0 : CTL_MORE)); + ctx->inbuf.used -= ((eos - ctx->inbuf.text) + 1); + if (ctx->inbuf.used == 0) + ctl_bufput(&ctx->inbuf); + else + memmove(ctx->inbuf.text, eos + 1, ctx->inbuf.used); + if (done) { + UNLINK(ctx->tran, tran, link); + memput(tran, sizeof *tran); + stop_read(ctx); + start_write(ctx); + return; + } + if (allocated_p(ctx->inbuf)) + goto again; + return; + } + if (ctx->inbuf.used == MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: line too long (%-10s...)", me, + ctx->inbuf.text); + error(ctx); + } +} + +/* Timer related stuff. */ + +static void +start_timer(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_timer"; + + REQUIRE(ctx->tiID.opaque == NULL); + if (evSetIdleTimer(ctx->ev, timer, ctx, ctx->timeout, &ctx->tiID) < 0){ + (*ctx->logger)(ctl_error, "%s: evSetIdleTimer: %s", me, + strerror(errno)); + error(ctx); + return; + } +} + +static void +stop_timer(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::stop_timer"; + + REQUIRE(ctx->tiID.opaque != NULL); + if (evClearIdleTimer(ctx->ev, ctx->tiID) < 0) { + (*ctx->logger)(ctl_error, "%s: evClearIdleTimer: %s", me, + strerror(errno)); + error(ctx); + return; + } + ctx->tiID.opaque = NULL; +} + +static void +touch_timer(struct ctl_cctx *ctx) { + REQUIRE(ctx->tiID.opaque != NULL); + + evTouchIdleTimer(ctx->ev, ctx->tiID); +} + +static void +timer(evContext ev, void *uap, struct timespec due, struct timespec itv) { + static const char me[] = "isc/ctl_clnt::timer"; + struct ctl_cctx *ctx = uap; + + UNUSED(ev); + UNUSED(due); + UNUSED(itv); + + ctx->tiID.opaque = NULL; + (*ctx->logger)(ctl_error, "%s: timeout after %u seconds while %s", me, + ctx->timeout.tv_sec, state_names[ctx->state]); + error(ctx); +} diff --git a/usr/src/lib/libresolv2/common/isc/ctl_p.c b/usr/src/lib/libresolv2/common/isc/ctl_p.c new file mode 100644 index 0000000000..ef785e70bd --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ctl_p.c @@ -0,0 +1,193 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_p.c,v 8.8 2001/05/29 05:49:26 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Extern. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <isc/assertions.h> +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> +#include <isc/ctl.h> + +#include "ctl_p.h" + +#include "port_after.h" + +/* Constants. */ + +const char * const ctl_sevnames[] = { + "debug", "warning", "error" +}; + +/* Public. */ + +/* + * ctl_logger() + * if ctl_startup()'s caller didn't specify a logger, this one + * is used. this pollutes stderr with all kinds of trash so it will + * probably never be used in real applications. + */ +void +ctl_logger(enum ctl_severity severity, const char *format, ...) { + va_list ap; + static const char me[] = "ctl_logger"; + + fprintf(stderr, "%s(%s): ", me, ctl_sevnames[severity]); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc('\n', stderr); +} + +int +ctl_bufget(struct ctl_buf *buf, ctl_logfunc logger) { + static const char me[] = "ctl_bufget"; + + REQUIRE(!allocated_p(*buf) && buf->used == 0); + buf->text = memget(MAX_LINELEN); + if (!allocated_p(*buf)) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + return (-1); + } + buf->used = 0; + return (0); +} + +void +ctl_bufput(struct ctl_buf *buf) { + + REQUIRE(allocated_p(*buf)); + memput(buf->text, MAX_LINELEN); + buf->text = NULL; + buf->used = 0; +} + +const char * +ctl_sa_ntop(const struct sockaddr *sa, + char *buf, size_t size, + ctl_logfunc logger) +{ + static const char me[] = "ctl_sa_ntop"; + static const char punt[] = "[0].-1"; + char tmp[INET6_ADDRSTRLEN]; + + switch (sa->sa_family) { + case AF_INET6: { + const struct sockaddr_in6 *in6 = + (const struct sockaddr_in6 *) sa; + + if (inet_ntop(in6->sin6_family, &in6->sin6_addr, tmp, sizeof tmp) + == NULL) { + (*logger)(ctl_error, "%s: inet_ntop(%u %04x): %s", + me, in6->sin6_family, + in6->sin6_port, strerror(errno)); + return (punt); + } + if (strlen(tmp) + sizeof "[].65535" > size) { + (*logger)(ctl_error, "%s: buffer overflow", me); + return (punt); + } + (void) sprintf(buf, "[%s].%u", tmp, ntohs(in6->sin6_port)); + return (buf); + } + case AF_INET: { + const struct sockaddr_in *in = + (const struct sockaddr_in *) sa; + + if (inet_ntop(in->sin_family, &in->sin_addr, tmp, sizeof tmp) + == NULL) { + (*logger)(ctl_error, "%s: inet_ntop(%u %04x %08x): %s", + me, in->sin_family, + in->sin_port, in->sin_addr.s_addr, + strerror(errno)); + return (punt); + } + if (strlen(tmp) + sizeof "[].65535" > size) { + (*logger)(ctl_error, "%s: buffer overflow", me); + return (punt); + } + (void) sprintf(buf, "[%s].%u", tmp, ntohs(in->sin_port)); + return (buf); + } +#ifndef NO_SOCKADDR_UN + case AF_UNIX: { + const struct sockaddr_un *un = + (const struct sockaddr_un *) sa; + unsigned int x = sizeof un->sun_path; + + if (x > size) + x = size; + strncpy(buf, un->sun_path, x - 1); + buf[x - 1] = '\0'; + return (buf); + } +#endif + default: + return (punt); + } +} + +void +ctl_sa_copy(const struct sockaddr *src, struct sockaddr *dst) { + switch (src->sa_family) { + case AF_INET6: + *((struct sockaddr_in6 *)dst) = + *((const struct sockaddr_in6 *)src); + break; + case AF_INET: + *((struct sockaddr_in *)dst) = + *((const struct sockaddr_in *)src); + break; +#ifndef NO_SOCKADDR_UN + case AF_UNIX: + *((struct sockaddr_un *)dst) = + *((const struct sockaddr_un *)src); + break; +#endif + default: + *dst = *src; + break; + } +} diff --git a/usr/src/lib/libresolv2/common/isc/ctl_p.h b/usr/src/lib/libresolv2/common/isc/ctl_p.h new file mode 100644 index 0000000000..df86107f4d --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ctl_p.h @@ -0,0 +1,33 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +struct ctl_buf { + char * text; + size_t used; +}; + +#define MAX_LINELEN 990 /* Like SMTP. */ +#ifndef NO_SOCKADDR_UN +#define MAX_NTOP PATH_MAX +#else +#define MAX_NTOP (sizeof "[255.255.255.255].65535") +#endif + +#define allocated_p(Buf) ((Buf).text != NULL) +#define buffer_init(Buf) ((Buf).text = 0, (Buf.used) = 0) + +#define ctl_bufget __ctl_bufget +#define ctl_bufput __ctl_bufput +#define ctl_sa_ntop __ctl_sa_ntop +#define ctl_sa_copy __ctl_sa_copy + +int ctl_bufget(struct ctl_buf *, ctl_logfunc); +void ctl_bufput(struct ctl_buf *); +const char * ctl_sa_ntop(const struct sockaddr *, char *, size_t, + ctl_logfunc); +void ctl_sa_copy(const struct sockaddr *, + struct sockaddr *); diff --git a/usr/src/lib/libresolv2/common/isc/ctl_srvr.c b/usr/src/lib/libresolv2/common/isc/ctl_srvr.c new file mode 100644 index 0000000000..8593ba9a30 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ctl_srvr.c @@ -0,0 +1,787 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_srvr.c,v 8.26 2002/07/08 05:10:25 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Extern. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <fcntl.h> + +#include <isc/assertions.h> +#include <isc/ctl.h> +#include <isc/eventlib.h> +#include <isc/list.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "ctl_p.h" + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Macros. */ + +#define lastverb_p(verb) (verb->name == NULL || verb->func == NULL) +#define address_expr ctl_sa_ntop((struct sockaddr *)&sess->sa, \ + tmp, sizeof tmp, ctx->logger) + +/* Types. */ + +enum state { + available = 0, initializing, writing, reading, reading_data, + processing, idling, quitting, closing +}; + +union sa_un { + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif +}; + +struct ctl_sess { + LINK(struct ctl_sess) link; + struct ctl_sctx * ctx; + enum state state; + int sock; + union sa_un sa; + evFileID rdID; + evStreamID wrID; + evTimerID rdtiID; + evTimerID wrtiID; + struct ctl_buf inbuf; + struct ctl_buf outbuf; + const struct ctl_verb * verb; + u_int helpcode; + const void * respctx; + u_int respflags; + ctl_srvrdone donefunc; + void * uap; + void * csctx; +}; + +struct ctl_sctx { + evContext ev; + void * uctx; + u_int unkncode; + u_int timeoutcode; + const struct ctl_verb * verbs; + const struct ctl_verb * connverb; + int sock; + int max_sess; + int cur_sess; + struct timespec timeout; + ctl_logfunc logger; + evConnID acID; + LIST(struct ctl_sess) sess; +}; + +/* Forward. */ + +static void ctl_accept(evContext, void *, int, + const void *, int, + const void *, int); +static void ctl_close(struct ctl_sess *); +static void ctl_new_state(struct ctl_sess *, + enum state, + const char *); +static void ctl_start_read(struct ctl_sess *); +static void ctl_stop_read(struct ctl_sess *); +static void ctl_readable(evContext, void *, int, int); +static void ctl_rdtimeout(evContext, void *, + struct timespec, + struct timespec); +static void ctl_wrtimeout(evContext, void *, + struct timespec, + struct timespec); +static void ctl_docommand(struct ctl_sess *); +static void ctl_writedone(evContext, void *, int, int); +static void ctl_morehelp(struct ctl_sctx *, + struct ctl_sess *, + const struct ctl_verb *, + const char *, + u_int, const void *, void *); +static void ctl_signal_done(struct ctl_sctx *, + struct ctl_sess *); + +/* Private data. */ + +static const char * state_names[] = { + "available", "initializing", "writing", "reading", + "reading_data", "processing", "idling", "quitting", "closing" +}; + +static const char space[] = " "; + +static const struct ctl_verb fakehelpverb = { + "fakehelp", ctl_morehelp , NULL +}; + +/* Public. */ + +/* + * void + * ctl_server() + * create, condition, and start a listener on the control port. + */ +struct ctl_sctx * +ctl_server(evContext lev, const struct sockaddr *sap, size_t sap_len, + const struct ctl_verb *verbs, + u_int unkncode, u_int timeoutcode, + u_int timeout, int backlog, int max_sess, + ctl_logfunc logger, void *uctx) +{ + static const char me[] = "ctl_server"; + static const int on = 1; + const struct ctl_verb *connverb; + struct ctl_sctx *ctx; + int save_errno; + + if (logger == NULL) + logger = ctl_logger; + for (connverb = verbs; + connverb->name != NULL && connverb->func != NULL; + connverb++) + if (connverb->name[0] == '\0') + break; + if (connverb->func == NULL) { + (*logger)(ctl_error, "%s: no connection verb found", me); + return (NULL); + } + ctx = memget(sizeof *ctx); + if (ctx == NULL) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + return (NULL); + } + ctx->ev = lev; + ctx->uctx = uctx; + ctx->unkncode = unkncode; + ctx->timeoutcode = timeoutcode; + ctx->verbs = verbs; + ctx->timeout = evConsTime(timeout, 0); + ctx->logger = logger; + ctx->connverb = connverb; + ctx->max_sess = max_sess; + ctx->cur_sess = 0; + INIT_LIST(ctx->sess); + ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC); + if (ctx->sock > evHighestFD(ctx->ev)) { + ctx->sock = -1; + errno = ENOTSOCK; + } + if (ctx->sock < 0) { + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: socket: %s", + me, strerror(errno)); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + if (ctx->sock > evHighestFD(lev)) { + close(ctx->sock); + (*ctx->logger)(ctl_error, "%s: file descriptor > evHighestFD"); + errno = ENFILE; + memput(ctx, sizeof *ctx); + return (NULL); + } +#ifdef NO_UNIX_REUSEADDR + if (sap->sa_family != AF_UNIX) +#endif + if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, + (const char *)&on, sizeof on) != 0) { + (*ctx->logger)(ctl_warning, + "%s: setsockopt(REUSEADDR): %s", + me, strerror(errno)); + } + if (bind(ctx->sock, sap, sap_len) < 0) { + char tmp[MAX_NTOP]; + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: bind: %s: %s", + me, ctl_sa_ntop((const struct sockaddr *)sap, + tmp, sizeof tmp, ctx->logger), + strerror(save_errno)); + close(ctx->sock); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + if (fcntl(ctx->sock, F_SETFD, 1) < 0) { + (*ctx->logger)(ctl_warning, "%s: fcntl: %s", me, + strerror(errno)); + } + if (evListen(lev, ctx->sock, backlog, ctl_accept, ctx, + &ctx->acID) < 0) { + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: evListen(fd %d): %s", + me, ctx->sock, strerror(errno)); + close(ctx->sock); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + (*ctx->logger)(ctl_debug, "%s: new ctx %p, sock %d", + me, ctx, ctx->sock); + return (ctx); +} + +/* + * void + * ctl_endserver(ctx) + * if the control listener is open, close it. clean out all eventlib + * stuff. close all active sessions. + */ +void +ctl_endserver(struct ctl_sctx *ctx) { + static const char me[] = "ctl_endserver"; + struct ctl_sess *this, *next; + + (*ctx->logger)(ctl_debug, "%s: ctx %p, sock %d, acID %p, sess %p", + me, ctx, ctx->sock, ctx->acID.opaque, ctx->sess); + if (ctx->acID.opaque != NULL) { + (void)evCancelConn(ctx->ev, ctx->acID); + ctx->acID.opaque = NULL; + } + if (ctx->sock != -1) { + (void) close(ctx->sock); + ctx->sock = -1; + } + for (this = HEAD(ctx->sess); this != NULL; this = next) { + next = NEXT(this, link); + ctl_close(this); + } + memput(ctx, sizeof *ctx); +} + +/* + * If body is non-NULL then it we add a "." line after it. + * Caller must have escaped lines with leading ".". + */ +void +ctl_response(struct ctl_sess *sess, u_int code, const char *text, + u_int flags, const void *respctx, ctl_srvrdone donefunc, + void *uap, const char *body, size_t bodylen) +{ + static const char me[] = "ctl_response"; + struct iovec iov[3], *iovp = iov; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP], *pc; + int n; + + REQUIRE(sess->state == initializing || + sess->state == processing || + sess->state == reading_data || + sess->state == writing); + REQUIRE(sess->wrtiID.opaque == NULL); + REQUIRE(sess->wrID.opaque == NULL); + ctl_new_state(sess, writing, me); + sess->donefunc = donefunc; + sess->uap = uap; + if (!allocated_p(sess->outbuf) && + ctl_bufget(&sess->outbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: cant get an output buffer", + me, address_expr); + goto untimely; + } + if (sizeof "000-\r\n" + strlen(text) > MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: %s: output buffer ovf, closing", + me, address_expr); + goto untimely; + } + sess->outbuf.used = SPRINTF((sess->outbuf.text, "%03d%c%s\r\n", + code, (flags & CTL_MORE) != 0 ? '-' : ' ', + text)); + for (pc = sess->outbuf.text, n = 0; + n < (int)sess->outbuf.used-2; pc++, n++) + if (!isascii((unsigned char)*pc) || + !isprint((unsigned char)*pc)) + *pc = '\040'; + *iovp++ = evConsIovec(sess->outbuf.text, sess->outbuf.used); + if (body != NULL) { + char *tmp; + DE_CONST(body, tmp); + *iovp++ = evConsIovec(tmp, bodylen); + DE_CONST(".\r\n", tmp); + *iovp++ = evConsIovec(tmp, 3); + } + (*ctx->logger)(ctl_debug, "%s: [%d] %s", me, + sess->outbuf.used, sess->outbuf.text); + if (evWrite(ctx->ev, sess->sock, iov, iovp - iov, + ctl_writedone, sess, &sess->wrID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evWrite: %s", me, + address_expr, strerror(errno)); + goto untimely; + } + if (evSetIdleTimer(ctx->ev, ctl_wrtimeout, sess, ctx->timeout, + &sess->wrtiID) < 0) + { + (*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me, + address_expr, strerror(errno)); + goto untimely; + } + if (evTimeRW(ctx->ev, sess->wrID, sess->wrtiID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evTimeRW: %s", me, + address_expr, strerror(errno)); + untimely: + ctl_signal_done(ctx, sess); + ctl_close(sess); + return; + } + sess->respctx = respctx; + sess->respflags = flags; +} + +void +ctl_sendhelp(struct ctl_sess *sess, u_int code) { + static const char me[] = "ctl_sendhelp"; + struct ctl_sctx *ctx = sess->ctx; + + sess->helpcode = code; + sess->verb = &fakehelpverb; + ctl_morehelp(ctx, sess, NULL, me, CTL_MORE, + (const void *)ctx->verbs, NULL); +} + +void * +ctl_getcsctx(struct ctl_sess *sess) { + return (sess->csctx); +} + +void * +ctl_setcsctx(struct ctl_sess *sess, void *csctx) { + void *old = sess->csctx; + + sess->csctx = csctx; + return (old); +} + +/* Private functions. */ + +static void +ctl_accept(evContext lev, void *uap, int fd, + const void *lav, int lalen, + const void *rav, int ralen) +{ + static const char me[] = "ctl_accept"; + struct ctl_sctx *ctx = uap; + struct ctl_sess *sess = NULL; + char tmp[MAX_NTOP]; + + UNUSED(lev); + UNUSED(lalen); + UNUSED(ralen); + + if (fd < 0) { + (*ctx->logger)(ctl_error, "%s: accept: %s", + me, strerror(errno)); + return; + } + if (ctx->cur_sess == ctx->max_sess) { + (*ctx->logger)(ctl_error, "%s: %s: too many control sessions", + me, ctl_sa_ntop((const struct sockaddr *)rav, + tmp, sizeof tmp, + ctx->logger)); + (void) close(fd); + return; + } + sess = memget(sizeof *sess); + if (sess == NULL) { + (*ctx->logger)(ctl_error, "%s: memget: %s", me, + strerror(errno)); + (void) close(fd); + return; + } + if (fcntl(fd, F_SETFD, 1) < 0) { + (*ctx->logger)(ctl_warning, "%s: fcntl: %s", me, + strerror(errno)); + } + ctx->cur_sess++; + INIT_LINK(sess, link); + APPEND(ctx->sess, sess, link); + sess->ctx = ctx; + sess->sock = fd; + sess->wrID.opaque = NULL; + sess->rdID.opaque = NULL; + sess->wrtiID.opaque = NULL; + sess->rdtiID.opaque = NULL; + sess->respctx = NULL; + sess->csctx = NULL; + if (((const struct sockaddr *)rav)->sa_family == AF_UNIX) + ctl_sa_copy((const struct sockaddr *)lav, + (struct sockaddr *)&sess->sa); + else + ctl_sa_copy((const struct sockaddr *)rav, + (struct sockaddr *)&sess->sa); + sess->donefunc = NULL; + buffer_init(sess->inbuf); + buffer_init(sess->outbuf); + sess->state = available; + ctl_new_state(sess, initializing, me); + sess->verb = ctx->connverb; + (*ctx->logger)(ctl_debug, "%s: %s: accepting (fd %d)", + me, address_expr, sess->sock); + (*ctx->connverb->func)(ctx, sess, ctx->connverb, "", 0, + (const struct sockaddr *)rav, ctx->uctx); +} + +static void +ctl_new_state(struct ctl_sess *sess, enum state new_state, const char *reason) +{ + static const char me[] = "ctl_new_state"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + (*ctx->logger)(ctl_debug, "%s: %s: %s -> %s (%s)", + me, address_expr, + state_names[sess->state], + state_names[new_state], reason); + sess->state = new_state; +} + +static void +ctl_close(struct ctl_sess *sess) { + static const char me[] = "ctl_close"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == initializing || + sess->state == writing || + sess->state == reading || + sess->state == processing || + sess->state == reading_data || + sess->state == idling); + REQUIRE(sess->sock != -1); + if (sess->state == reading || sess->state == reading_data) + ctl_stop_read(sess); + else if (sess->state == writing) { + if (sess->wrID.opaque != NULL) { + (void) evCancelRW(ctx->ev, sess->wrID); + sess->wrID.opaque = NULL; + } + if (sess->wrtiID.opaque != NULL) { + (void) evClearIdleTimer(ctx->ev, sess->wrtiID); + sess->wrtiID.opaque = NULL; + } + } + ctl_new_state(sess, closing, me); + (void) close(sess->sock); + if (allocated_p(sess->inbuf)) + ctl_bufput(&sess->inbuf); + if (allocated_p(sess->outbuf)) + ctl_bufput(&sess->outbuf); + (*ctx->logger)(ctl_debug, "%s: %s: closed (fd %d)", + me, address_expr, sess->sock); + UNLINK(ctx->sess, sess, link); + memput(sess, sizeof *sess); + ctx->cur_sess--; +} + +static void +ctl_start_read(struct ctl_sess *sess) { + static const char me[] = "ctl_start_read"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == initializing || + sess->state == writing || + sess->state == processing || + sess->state == idling); + REQUIRE(sess->rdtiID.opaque == NULL); + REQUIRE(sess->rdID.opaque == NULL); + sess->inbuf.used = 0; + if (evSetIdleTimer(ctx->ev, ctl_rdtimeout, sess, ctx->timeout, + &sess->rdtiID) < 0) + { + (*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me, + address_expr, strerror(errno)); + ctl_close(sess); + return; + } + if (evSelectFD(ctx->ev, sess->sock, EV_READ, + ctl_readable, sess, &sess->rdID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evSelectFD: %s", me, + address_expr, strerror(errno)); + return; + } + ctl_new_state(sess, reading, me); +} + +static void +ctl_stop_read(struct ctl_sess *sess) { + static const char me[] = "ctl_stop_read"; + struct ctl_sctx *ctx = sess->ctx; + + REQUIRE(sess->state == reading || sess->state == reading_data); + REQUIRE(sess->rdID.opaque != NULL); + (void) evDeselectFD(ctx->ev, sess->rdID); + sess->rdID.opaque = NULL; + if (sess->rdtiID.opaque != NULL) { + (void) evClearIdleTimer(ctx->ev, sess->rdtiID); + sess->rdtiID.opaque = NULL; + } + ctl_new_state(sess, idling, me); +} + +static void +ctl_readable(evContext lev, void *uap, int fd, int evmask) { + static const char me[] = "ctl_readable"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char *eos, tmp[MAX_NTOP]; + ssize_t n; + + REQUIRE(sess != NULL); + REQUIRE(fd >= 0); + REQUIRE(evmask == EV_READ); + REQUIRE(sess->state == reading || sess->state == reading_data); + evTouchIdleTimer(lev, sess->rdtiID); + if (!allocated_p(sess->inbuf) && + ctl_bufget(&sess->inbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: cant get an input buffer", + me, address_expr); + ctl_close(sess); + return; + } + n = read(sess->sock, sess->inbuf.text + sess->inbuf.used, + MAX_LINELEN - sess->inbuf.used); + if (n <= 0) { + (*ctx->logger)(ctl_debug, "%s: %s: read: %s", + me, address_expr, + (n == 0) ? "Unexpected EOF" : strerror(errno)); + ctl_close(sess); + return; + } + sess->inbuf.used += n; + eos = memchr(sess->inbuf.text, '\n', sess->inbuf.used); + if (eos != NULL && eos != sess->inbuf.text && eos[-1] == '\r') { + eos[-1] = '\0'; + if ((sess->respflags & CTL_DATA) != 0) { + INSIST(sess->verb != NULL); + (*sess->verb->func)(sess->ctx, sess, sess->verb, + sess->inbuf.text, + CTL_DATA, sess->respctx, + sess->ctx->uctx); + } else { + ctl_stop_read(sess); + ctl_docommand(sess); + } + sess->inbuf.used -= ((eos - sess->inbuf.text) + 1); + if (sess->inbuf.used == 0) + ctl_bufput(&sess->inbuf); + else + memmove(sess->inbuf.text, eos + 1, sess->inbuf.used); + return; + } + if (sess->inbuf.used == MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: %s: line too long, closing", + me, address_expr); + ctl_close(sess); + } +} + +static void +ctl_wrtimeout(evContext lev, void *uap, + struct timespec due, + struct timespec itv) +{ + static const char me[] = "ctl_wrtimeout"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + UNUSED(lev); + UNUSED(due); + UNUSED(itv); + + REQUIRE(sess->state == writing); + sess->wrtiID.opaque = NULL; + (*ctx->logger)(ctl_warning, "%s: %s: write timeout, closing", + me, address_expr); + if (sess->wrID.opaque != NULL) { + (void) evCancelRW(ctx->ev, sess->wrID); + sess->wrID.opaque = NULL; + } + ctl_signal_done(ctx, sess); + ctl_new_state(sess, processing, me); + ctl_close(sess); +} + +static void +ctl_rdtimeout(evContext lev, void *uap, + struct timespec due, + struct timespec itv) +{ + static const char me[] = "ctl_rdtimeout"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + UNUSED(lev); + UNUSED(due); + UNUSED(itv); + + REQUIRE(sess->state == reading); + sess->rdtiID.opaque = NULL; + (*ctx->logger)(ctl_warning, "%s: %s: timeout, closing", + me, address_expr); + if (sess->state == reading || sess->state == reading_data) + ctl_stop_read(sess); + ctl_signal_done(ctx, sess); + ctl_new_state(sess, processing, me); + ctl_response(sess, ctx->timeoutcode, "Timeout.", CTL_EXIT, NULL, + NULL, NULL, NULL, 0); +} + +static void +ctl_docommand(struct ctl_sess *sess) { + static const char me[] = "ctl_docommand"; + char *name, *rest, tmp[MAX_NTOP]; + struct ctl_sctx *ctx = sess->ctx; + const struct ctl_verb *verb; + + REQUIRE(allocated_p(sess->inbuf)); + (*ctx->logger)(ctl_debug, "%s: %s: \"%s\" [%u]", + me, address_expr, + sess->inbuf.text, (u_int)sess->inbuf.used); + ctl_new_state(sess, processing, me); + name = sess->inbuf.text + strspn(sess->inbuf.text, space); + rest = name + strcspn(name, space); + if (*rest != '\0') { + *rest++ = '\0'; + rest += strspn(rest, space); + } + for (verb = ctx->verbs; + verb != NULL && verb->name != NULL && verb->func != NULL; + verb++) + if (verb->name[0] != '\0' && strcasecmp(name, verb->name) == 0) + break; + if (verb != NULL && verb->name != NULL && verb->func != NULL) { + sess->verb = verb; + (*verb->func)(ctx, sess, verb, rest, 0, NULL, ctx->uctx); + } else { + char buf[1100]; + + if (sizeof "Unrecognized command \"\" (args \"\")" + + strlen(name) + strlen(rest) > sizeof buf) + strcpy(buf, "Unrecognized command (buf ovf)"); + else + sprintf(buf, + "Unrecognized command \"%s\" (args \"%s\")", + name, rest); + ctl_response(sess, ctx->unkncode, buf, 0, NULL, NULL, NULL, + NULL, 0); + } +} + +static void +ctl_writedone(evContext lev, void *uap, int fd, int bytes) { + static const char me[] = "ctl_writedone"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + int save_errno = errno; + + UNUSED(lev); + UNUSED(uap); + + REQUIRE(sess->state == writing); + REQUIRE(fd == sess->sock); + REQUIRE(sess->wrtiID.opaque != NULL); + sess->wrID.opaque = NULL; + (void) evClearIdleTimer(ctx->ev, sess->wrtiID); + sess->wrtiID.opaque = NULL; + if (bytes < 0) { + (*ctx->logger)(ctl_error, "%s: %s: %s", + me, address_expr, strerror(save_errno)); + ctl_close(sess); + return; + } + + INSIST(allocated_p(sess->outbuf)); + ctl_bufput(&sess->outbuf); + if ((sess->respflags & CTL_EXIT) != 0) { + ctl_signal_done(ctx, sess); + ctl_close(sess); + return; + } else if ((sess->respflags & CTL_MORE) != 0) { + INSIST(sess->verb != NULL); + (*sess->verb->func)(sess->ctx, sess, sess->verb, "", + CTL_MORE, sess->respctx, sess->ctx->uctx); + } else { + ctl_signal_done(ctx, sess); + ctl_start_read(sess); + } +} + +static void +ctl_morehelp(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *text, + u_int respflags, const void *respctx, void *uctx) +{ + const struct ctl_verb *this = respctx, *next = this + 1; + + UNUSED(ctx); + UNUSED(verb); + UNUSED(text); + UNUSED(uctx); + + REQUIRE(!lastverb_p(this)); + REQUIRE((respflags & CTL_MORE) != 0); + if (lastverb_p(next)) + respflags &= ~CTL_MORE; + ctl_response(sess, sess->helpcode, this->help, respflags, next, + NULL, NULL, NULL, 0); +} + +static void +ctl_signal_done(struct ctl_sctx *ctx, struct ctl_sess *sess) { + if (sess->donefunc != NULL) { + (*sess->donefunc)(ctx, sess, sess->uap); + sess->donefunc = NULL; + } +} diff --git a/usr/src/lib/libresolv2/common/isc/ev_connects.c b/usr/src/lib/libresolv2/common/isc/ev_connects.c new file mode 100644 index 0000000000..533b544a49 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ev_connects.c @@ -0,0 +1,372 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* ev_connects.c - implement asynch connect/accept for the eventlib + * vix 16sep96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_connects.c,v 8.32 2001/07/03 13:26:35 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> + +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Macros. */ + +#define GETXXXNAME(f, s, sa, len) ( \ + (f((s), (&sa), (&len)) >= 0) ? 0 : \ + (errno != EAFNOSUPPORT && errno != EOPNOTSUPP) ? -1 : ( \ + memset(&(sa), 0, sizeof (sa)), \ + (len) = sizeof (sa), \ + (sa).sa_family = AF_UNIX, \ + 0 \ + ) \ + ) + +/* Forward. */ + +static void listener(evContext ctx, void *uap, int fd, int evmask); +static void connector(evContext ctx, void *uap, int fd, int evmask); + +/* Public. */ + +int +evListen(evContext opaqueCtx, int fd, int maxconn, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + int mode; + + OKNEW(new); + new->flags = EV_CONN_LISTEN; + OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ + /* + * Remember the nonblocking status. We assume that either evSelectFD + * has not been done to this fd, or that if it has then the caller + * will evCancelConn before they evDeselectFD. If our assumptions + * are not met, then we might restore the old nonblocking status + * incorrectly. + */ + if ((mode & PORT_NONBLOCK) == 0) { +#ifdef USE_FIONBIO_IOCTL + int on = 1; + OK(ioctl(fd, FIONBIO, (char *)&on)); +#else + OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK)); +#endif + new->flags |= EV_CONN_BLOCK; + } + OK(listen(fd, maxconn)); + if (evSelectFD(opaqueCtx, fd, EV_READ, listener, new, &new->file) < 0){ + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evConnect(evContext opaqueCtx, int fd, const void *ra, int ralen, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + + OKNEW(new); + new->flags = 0; + /* Do the select() first to get the socket into nonblocking mode. */ + if (evSelectFD(opaqueCtx, fd, EV_MASK_ALL, + connector, new, &new->file) < 0) { + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + if (connect(fd, ra, ralen) < 0 && + errno != EWOULDBLOCK && + errno != EAGAIN && + errno != EINPROGRESS) { + int save = errno; + + (void) evDeselectFD(opaqueCtx, new->file); + FREE(new); + errno = save; + return (-1); + } + /* No error, or EWOULDBLOCK. select() tells when it's ready. */ + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evCancelConn(evContext opaqueCtx, evConnID id) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *this = id.opaque; + evAccept *acc, *nxtacc; + int mode; + + if ((this->flags & EV_CONN_SELECTED) != 0) + (void) evDeselectFD(opaqueCtx, this->file); + if ((this->flags & EV_CONN_BLOCK) != 0) { + mode = fcntl(this->fd, F_GETFL, NULL); + if (mode == -1) { + if (errno != EBADF) + return (-1); + } else { +#ifdef USE_FIONBIO_IOCTL + int on = 1; + OK(ioctl(this->fd, FIONBIO, (char *)&on)); +#else + OK(fcntl(this->fd, F_SETFL, mode | PORT_NONBLOCK)); +#endif + } + } + + /* Unlink from ctx->conns. */ + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->conns = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + + /* + * Remove `this' from the ctx->accepts list (zero or more times). + */ + for (acc = HEAD(ctx->accepts), nxtacc = NULL; + acc != NULL; + acc = nxtacc) + { + nxtacc = NEXT(acc, link); + if (acc->conn == this) { + UNLINK(ctx->accepts, acc, link); + close(acc->fd); + FREE(acc); + } + } + + /* Wrap up and get out. */ + FREE(this); + return (0); +} + +int evHold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) == 0) + return (0); + this->flags &= ~EV_CONN_SELECTED; + return (evDeselectFD(opaqueCtx, this->file)); +} + +int evUnhold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + int ret; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) != 0) + return (0); + ret = evSelectFD(opaqueCtx, this->fd, EV_READ, listener, this, + &this->file); + if (ret == 0) + this->flags |= EV_CONN_SELECTED; + return (ret); +} + +int +evTryAccept(evContext opaqueCtx, evConnID id, int *sys_errno) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = id.opaque; + evAccept *new; + + if ((conn->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + OKNEW(new); + new->conn = conn; + new->ralen = sizeof new->ra; + new->fd = accept(conn->fd, &new->ra.sa, &new->ralen); + if (new->fd > ctx->highestFD) { + close(new->fd); + new->fd = -1; + new->ioErrno = ENOTSOCK; + } + if (new->fd >= 0) { + new->lalen = sizeof new->la; + if (GETXXXNAME(getsockname, new->fd, new->la.sa, new->lalen) < 0) { + new->ioErrno = errno; + (void) close(new->fd); + new->fd = -1; + } else + new->ioErrno = 0; + } else { + new->ioErrno = errno; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + FREE(new); + return (-1); + } + } + INIT_LINK(new, link); + APPEND(ctx->accepts, new, link); + *sys_errno = new->ioErrno; + return (0); +} + +/* Private. */ + +static void +listener(evContext opaqueCtx, void *uap, int fd, int evmask) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = uap; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la, ra; + int new; + ISC_SOCKLEN_T lalen = 0, ralen; + + REQUIRE((evmask & EV_READ) != 0); + ralen = sizeof ra; + new = accept(fd, &ra.sa, &ralen); + if (new > ctx->highestFD) { + close(new); + new = -1; + errno = ENOTSOCK; + } + if (new >= 0) { + lalen = sizeof la; + if (GETXXXNAME(getsockname, new, la.sa, lalen) < 0) { + int save = errno; + + (void) close(new); + errno = save; + new = -1; + } + } else if (errno == EAGAIN || errno == EWOULDBLOCK) + return; + (*conn->func)(opaqueCtx, conn->uap, new, &la.sa, lalen, &ra.sa, ralen); +} + +static void +connector(evContext opaqueCtx, void *uap, int fd, int evmask) { + evConn *conn = uap; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la, ra; + ISC_SOCKLEN_T lalen, ralen; + char buf[1]; + void *conn_uap; + evConnFunc conn_func; + evConnID id; + int socket_errno = 0; + ISC_SOCKLEN_T optlen; + + UNUSED(evmask); + + lalen = sizeof la; + ralen = sizeof ra; + conn_uap = conn->uap; + conn_func = conn->func; + id.opaque = conn; +#ifdef SO_ERROR + optlen = sizeof socket_errno; + if (fd < 0 && + getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char *)&socket_errno, + &optlen) < 0) + socket_errno = errno; + else + errno = socket_errno; +#endif + if (evCancelConn(opaqueCtx, id) < 0 || + socket_errno || +#ifdef NETREAD_BROKEN + 0 || +#else + read(fd, buf, 0) < 0 || +#endif + GETXXXNAME(getsockname, fd, la.sa, lalen) < 0 || + GETXXXNAME(getpeername, fd, ra.sa, ralen) < 0) { + int save = errno; + + (void) close(fd); /* XXX closing caller's fd */ + errno = save; + fd = -1; + } + (*conn_func)(opaqueCtx, conn_uap, fd, &la.sa, lalen, &ra.sa, ralen); +} diff --git a/usr/src/lib/libresolv2/common/isc/ev_files.c b/usr/src/lib/libresolv2/common/isc/ev_files.c new file mode 100644 index 0000000000..8c9b1b22d6 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ev_files.c @@ -0,0 +1,303 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* ev_files.c - implement asynch file IO for the eventlib + * vix 11sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_files.c,v 1.22 2002/07/08 05:50:07 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include "eventlib_p.h" + +#include "port_after.h" + +static evFile *FindFD(const evContext_p *ctx, int fd, int eventmask); + +int +evSelectFD(evContext opaqueCtx, + int fd, + int eventmask, + evFileFunc func, + void *uap, + evFileID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *id; + int mode; + + evPrintf(ctx, 1, + "evSelectFD(ctx %p, fd %d, mask 0x%x, func %p, uap %p)\n", + ctx, fd, eventmask, func, uap); + if (eventmask == 0 || (eventmask & ~EV_MASK_ALL) != 0) + EV_ERR(EINVAL); +#ifdef SUNW_POLL +#else + if (fd > ctx->highestFD) + EV_ERR(EINVAL); +#endif /* SUNW_POLL */ + OK(mode = fcntl(fd, F_GETFL, NULL)); /* side effect: validate fd. */ + + /* + * The first time we touch a file descriptor, we need to check to see + * if the application already had it in O_NONBLOCK mode and if so, all + * of our deselect()'s have to leave it in O_NONBLOCK. If not, then + * all but our last deselect() has to leave it in O_NONBLOCK. + */ +#ifdef SUNW_POLL + /* Make sure both ctx->pollfds[] and ctx->fdTable[] are large enough */ + if (fd >= ctx->maxnfds) + evPollfdRealloc(ctx, 1, fd); +#endif /* SUNW_POLL */ + id = FindFD(ctx, fd, EV_MASK_ALL); + if (id == NULL) { + if (mode & PORT_NONBLOCK) + FD_SET(fd, &ctx->nonblockBefore); + else { +#ifdef USE_FIONBIO_IOCTL + int on = 1; + OK(ioctl(fd, FIONBIO, (char *)&on)); +#else + OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK)); +#endif + FD_CLR(fd, &ctx->nonblockBefore); + } + } + + /* + * If this descriptor is already in use, search for it again to see + * if any of the eventmask bits we want to set are already captured. + * We cannot usefully capture the same fd event more than once in the + * same context. + */ + if (id != NULL && FindFD(ctx, fd, eventmask) != NULL) + EV_ERR(ETOOMANYREFS); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->fd = fd; + id->eventmask = eventmask; + + /* + * Insert at head. Order could be important for performance if we + * believe that evGetNext()'s accesses to the fd_sets will be more + * serial and therefore more cache-lucky if the list is ordered by + * ``fd.'' We do not believe these things, so we don't do it. + * + * The interesting sequence is where GetNext() has cached a select() + * result and the caller decides to evSelectFD() on some descriptor. + * Since GetNext() starts at the head, it can miss new entries we add + * at the head. This is not a serious problem since the event being + * evSelectFD()'d for has to occur before evSelectFD() is called for + * the file event to be considered "missed" -- a real corner case. + * Maintaining a "tail" pointer for ctx->files would fix this, but I'm + * not sure it would be ``more correct.'' + */ + if (ctx->files != NULL) + ctx->files->prev = id; + id->prev = NULL; + id->next = ctx->files; + ctx->files = id; + + /* Insert into fd table. */ + if (ctx->fdTable[fd] != NULL) + ctx->fdTable[fd]->fdprev = id; + id->fdprev = NULL; + id->fdnext = ctx->fdTable[fd]; + ctx->fdTable[fd] = id; + + /* Turn on the appropriate bits in the {rd,wr,ex}Next fd_set's. */ + if (eventmask & EV_READ) + FD_SET(fd, &ctx->rdNext); + if (eventmask & EV_WRITE) + FD_SET(fd, &ctx->wrNext); + if (eventmask & EV_EXCEPT) + FD_SET(fd, &ctx->exNext); + + /* Update fdMax. */ + if (fd > ctx->fdMax) + ctx->fdMax = fd; + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + +#ifdef SUNW_POLL +#else + evPrintf(ctx, 5, + "evSelectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n", + fd, eventmask, + (u_long)ctx->rdNext.fds_bits[0], + (u_long)ctx->wrNext.fds_bits[0], + (u_long)ctx->exNext.fds_bits[0]); +#endif /* SUNW_POLL */ + + return (0); +} + +int +evDeselectFD(evContext opaqueCtx, evFileID opaqueID) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *del = opaqueID.opaque; + evFile *cur; + int mode, eventmask; + + if (!del) { + evPrintf(ctx, 11, "evDeselectFD(NULL) ignored\n"); + errno = EINVAL; + return (-1); + } + + evPrintf(ctx, 1, "evDeselectFD(fd %d, mask 0x%x)\n", + del->fd, del->eventmask); + + /* Get the mode. Unless the file has been closed, errors are bad. */ + mode = fcntl(del->fd, F_GETFL, NULL); + if (mode == -1 && errno != EBADF) + EV_ERR(errno); + + /* Remove from the list of files. */ + if (del->prev != NULL) + del->prev->next = del->next; + else + ctx->files = del->next; + if (del->next != NULL) + del->next->prev = del->prev; + + /* Remove from the fd table. */ + if (del->fdprev != NULL) + del->fdprev->fdnext = del->fdnext; + else + ctx->fdTable[del->fd] = del->fdnext; + if (del->fdnext != NULL) + del->fdnext->fdprev = del->fdprev; + + /* + * If the file descriptor does not appear in any other select() entry, + * and if !EV_WASNONBLOCK, and if we got no EBADF when we got the mode + * earlier, then: restore the fd to blocking status. + */ + if (!(cur = FindFD(ctx, del->fd, EV_MASK_ALL)) && + !FD_ISSET(del->fd, &ctx->nonblockBefore) && + mode != -1) { + /* + * Note that we won't return an error status to the caller if + * this fcntl() fails since (a) we've already done the work + * and (b) the caller didn't ask us anything about O_NONBLOCK. + */ +#ifdef USE_FIONBIO_IOCTL + int off = 1; + (void) ioctl(del->fd, FIONBIO, (char *)&off); +#else + (void) fcntl(del->fd, F_SETFL, mode & ~PORT_NONBLOCK); +#endif + } + + /* + * Now find all other uses of this descriptor and OR together an event + * mask so that we don't turn off {rd,wr,ex}Next bits that some other + * file event is using. As an optimization, stop if the event mask + * fills. + */ + eventmask = 0; + for ((void)NULL; + cur != NULL && eventmask != EV_MASK_ALL; + cur = cur->next) + if (cur->fd == del->fd) + eventmask |= cur->eventmask; + + /* OK, now we know which bits we can clear out. */ + if (!(eventmask & EV_READ)) { + FD_CLR(del->fd, &ctx->rdNext); + if (FD_ISSET(del->fd, &ctx->rdLast)) { + FD_CLR(del->fd, &ctx->rdLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_WRITE)) { + FD_CLR(del->fd, &ctx->wrNext); + if (FD_ISSET(del->fd, &ctx->wrLast)) { + FD_CLR(del->fd, &ctx->wrLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_EXCEPT)) { + FD_CLR(del->fd, &ctx->exNext); + if (FD_ISSET(del->fd, &ctx->exLast)) { + FD_CLR(del->fd, &ctx->exLast); + ctx->fdCount--; + } + } + + /* If this was the maxFD, find the new one. */ + if (del->fd == ctx->fdMax) { + ctx->fdMax = -1; + for (cur = ctx->files; cur; cur = cur->next) + if (cur->fd > ctx->fdMax) + ctx->fdMax = cur->fd; + } + + /* If this was the fdNext, cycle that to the next entry. */ + if (del == ctx->fdNext) + ctx->fdNext = del->next; + +#ifdef SUNW_POLL +#else + evPrintf(ctx, 5, + "evDeselectFD(fd %d, mask 0x%x): new masks: 0x%lx 0x%lx 0x%lx\n", + del->fd, eventmask, + (u_long)ctx->rdNext.fds_bits[0], + (u_long)ctx->wrNext.fds_bits[0], + (u_long)ctx->exNext.fds_bits[0]); +#endif /* SUNW_POLL */ + + /* Couldn't free it before now since we were using fields out of it. */ + FREE(del); + + return (0); +} + +static evFile * +FindFD(const evContext_p *ctx, int fd, int eventmask) { + evFile *id; + + for (id = ctx->fdTable[fd]; id != NULL; id = id->fdnext) + if (id->fd == fd && (id->eventmask & eventmask) != 0) + break; + return (id); +} diff --git a/usr/src/lib/libresolv2/common/isc/ev_streams.c b/usr/src/lib/libresolv2/common/isc/ev_streams.c new file mode 100644 index 0000000000..04ac464354 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ev_streams.c @@ -0,0 +1,312 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1996-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* ev_streams.c - implement asynch stream file IO for the eventlib + * vix 04mar96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_streams.c,v 8.22 2001/05/29 05:49:29 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/uio.h> + +#include <errno.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +static int copyvec(evStream *str, const struct iovec *iov, int iocnt); +static void consume(evStream *str, size_t bytes); +static void done(evContext opaqueCtx, evStream *str); +static void writable(evContext opaqueCtx, void *uap, int fd, int evmask); +static void readable(evContext opaqueCtx, void *uap, int fd, int evmask); + +struct iovec +evConsIovec(void *buf, size_t cnt) { + struct iovec ret; + + memset(&ret, 0xf5, sizeof ret); + ret.iov_base = buf; + ret.iov_len = cnt; + return (ret); +} + +int +evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id != NULL) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + return (-1); +} + +int +evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + return (-1); +} + +int +evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ { + evStream *str = id.opaque; + + UNUSED(opaqueCtx); + + str->timer = timer; + str->flags |= EV_STR_TIMEROK; + return (0); +} + +int +evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ { + evStream *str = id.opaque; + + UNUSED(opaqueCtx); + + str->flags &= ~EV_STR_TIMEROK; + return (0); +} + +int +evCancelRW(evContext opaqueCtx, evStreamID id) { + evContext_p *ctx = opaqueCtx.opaque; + evStream *old = id.opaque; + + /* + * The streams list is doubly threaded. First, there's ctx->streams + * that's used by evDestroy() to find and cancel all streams. Second, + * there's ctx->strDone (head) and ctx->strLast (tail) which thread + * through the potentially smaller number of "IO completed" streams, + * used in evGetNext() to avoid scanning the entire list. + */ + + /* Unlink from ctx->streams. */ + if (old->prev != NULL) + old->prev->next = old->next; + else + ctx->streams = old->next; + if (old->next != NULL) + old->next->prev = old->prev; + + /* + * If 'old' is on the ctx->strDone list, remove it. Update + * ctx->strLast if necessary. + */ + if (old->prevDone == NULL && old->nextDone == NULL) { + /* + * Either 'old' is the only item on the done list, or it's + * not on the done list. If the former, then we unlink it + * from the list. If the latter, we leave the list alone. + */ + if (ctx->strDone == old) { + ctx->strDone = NULL; + ctx->strLast = NULL; + } + } else { + if (old->prevDone != NULL) + old->prevDone->nextDone = old->nextDone; + else + ctx->strDone = old->nextDone; + if (old->nextDone != NULL) + old->nextDone->prevDone = old->prevDone; + else + ctx->strLast = old->prevDone; + } + + /* Deallocate the stream. */ + if (old->file.opaque) + evDeselectFD(opaqueCtx, old->file); + memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount); + FREE(old); + return (0); +} + +/* Copy a scatter/gather vector and initialize a stream handler's IO. */ +static int +copyvec(evStream *str, const struct iovec *iov, int iocnt) { + int i; + + str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt); + if (str->iovOrig == NULL) { + errno = ENOMEM; + return (-1); + } + str->ioTotal = 0; + for (i = 0; i < iocnt; i++) { + str->iovOrig[i] = iov[i]; + str->ioTotal += iov[i].iov_len; + } + str->iovOrigCount = iocnt; + str->iovCur = str->iovOrig; + str->iovCurCount = str->iovOrigCount; + str->ioDone = 0; + return (0); +} + +/* Pull off or truncate lead iovec(s). */ +static void +consume(evStream *str, size_t bytes) { + while (bytes > 0) { + if (bytes < (size_t)str->iovCur->iov_len) { + str->iovCur->iov_len -= bytes; + str->iovCur->iov_base = (void *) + ((u_char *)str->iovCur->iov_base + bytes); + str->ioDone += bytes; + bytes = 0; + } else { + bytes -= str->iovCur->iov_len; + str->ioDone += str->iovCur->iov_len; + str->iovCur++; + str->iovCurCount--; + } + } +} + +/* Add a stream to Done list and deselect the FD. */ +static void +done(evContext opaqueCtx, evStream *str) { + evContext_p *ctx = opaqueCtx.opaque; + + if (ctx->strLast != NULL) { + str->prevDone = ctx->strLast; + ctx->strLast->nextDone = str; + ctx->strLast = str; + } else { + INSIST(ctx->strDone == NULL); + ctx->strDone = ctx->strLast = str; + } + evDeselectFD(opaqueCtx, str->file); + str->file.opaque = NULL; + /* evDrop() will call evCancelRW() on us. */ +} + +/* Dribble out some bytes on the stream. (Called by evDispatch().) */ +static void +writable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + UNUSED(evmask); + + bytes = writev(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes < 0 && errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + if (str->ioDone == -1 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} + +/* Scoop up some bytes from the stream. (Called by evDispatch().) */ +static void +readable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + UNUSED(evmask); + + bytes = readv(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes == 0) + str->ioDone = 0; + else { + if (errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + } + if (str->ioDone <= 0 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} diff --git a/usr/src/lib/libresolv2/common/isc/ev_timers.c b/usr/src/lib/libresolv2/common/isc/ev_timers.c new file mode 100644 index 0000000000..9afc4a0ccd --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ev_timers.c @@ -0,0 +1,422 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* ev_timers.c - implement timers for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_timers.c,v 1.33 2002/07/08 05:50:09 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <errno.h> + +#include <isc/assertions.h> +#include <isc/eventlib.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Constants. */ + +#define MILLION 1000000 +#define BILLION 1000000000 + +/* Forward. */ + +static int due_sooner(void *, void *); +static void set_index(void *, int); +static void free_timer(void *, void *); +static void print_timer(void *, void *); +static void idle_timeout(evContext, void *, struct timespec, struct timespec); + +/* Private type. */ + +typedef struct { + evTimerFunc func; + void * uap; + struct timespec lastTouched; + struct timespec max_idle; + evTimer * timer; +} idle_timer; + +/* Public. */ + +struct timespec +evConsTime(time_t sec, long nsec) { + struct timespec x; + + x.tv_sec = sec; + x.tv_nsec = nsec; + return (x); +} + +struct timespec +evAddTime(struct timespec addend1, struct timespec addend2) { + struct timespec x; + + x.tv_sec = addend1.tv_sec + addend2.tv_sec; + x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec; + if (x.tv_nsec >= BILLION) { + x.tv_sec++; + x.tv_nsec -= BILLION; + } + return (x); +} + +struct timespec +evSubTime(struct timespec minuend, struct timespec subtrahend) { + struct timespec x; + + x.tv_sec = minuend.tv_sec - subtrahend.tv_sec; + if (minuend.tv_nsec >= subtrahend.tv_nsec) + x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec; + else { + x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec; + x.tv_sec--; + } + return (x); +} + +int +evCmpTime(struct timespec a, struct timespec b) { + long x = a.tv_sec - b.tv_sec; + + if (x == 0L) + x = a.tv_nsec - b.tv_nsec; + return (x < 0L ? (-1) : x > 0L ? (1) : (0)); +} + +struct timespec +evNowTime() { + struct timeval now; + + if (gettimeofday(&now, NULL) < 0) + return (evConsTime(0, 0)); + return (evTimeSpec(now)); +} + +struct timespec +evLastEventTime(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->lastEventTime); +} + +struct timespec +evTimeSpec(struct timeval tv) { + struct timespec ts; + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + return (ts); +} + +struct timeval +evTimeVal(struct timespec ts) { + struct timeval tv; + + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return (tv); +} + +int +evSetTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *id; + + evPrintf(ctx, 1, +"evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n", + ctx, func, uap, + (long)due.tv_sec, due.tv_nsec, + (long)inter.tv_sec, inter.tv_nsec); + + /* due={0,0} is a magic cookie meaning "now." */ + if (due.tv_sec == 0 && due.tv_nsec == 0L) + due = evNowTime(); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->due = due; + id->inter = inter; + + if (heap_insert(ctx->timers, id) < 0) + return (-1); + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evSetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evClearTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *del = id.opaque; + + if (ctx->cur != NULL && + ctx->cur->type == Timer && + ctx->cur->u.timer.this == del) { + evPrintf(ctx, 8, "deferring delete of timer (executing)\n"); + /* + * Setting the interval to zero ensures that evDrop() will + * clean up the timer. + */ + del->inter = evConsTime(0, 0); + return (0); + } + + if (heap_element(ctx->timers, del->index) != del) + EV_ERR(ENOENT); + + if (heap_delete(ctx->timers, del->index) < 0) + return (-1); + FREE(del); + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evClearTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evResetTimer(evContext opaqueCtx, + evTimerID id, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = id.opaque; + struct timespec old_due; + int result=0; + + if (heap_element(ctx->timers, timer->index) != timer) + EV_ERR(ENOENT); + + old_due = timer->due; + + timer->func = func; + timer->uap = uap; + timer->due = due; + timer->inter = inter; + + switch (evCmpTime(due, old_due)) { + case -1: + result = heap_increased(ctx->timers, timer->index); + break; + case 0: + result = 0; + break; + case 1: + result = heap_decreased(ctx->timers, timer->index); + break; + } + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evResetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (result); +} + +int +evSetIdleTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec max_idle, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *tt; + + /* Allocate and fill. */ + OKNEW(tt); + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + if (evSetTimer(opaqueCtx, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle, opaqueID) < 0) { + FREE(tt); + return (-1); + } + + tt->timer = opaqueID->opaque; + + return (0); +} + +int +evClearIdleTimer(evContext opaqueCtx, evTimerID id) { + evTimer *del = id.opaque; + idle_timer *tt = del->uap; + + FREE(tt); + return (evClearTimer(opaqueCtx, id)); +} + +int +evResetIdleTimer(evContext opaqueCtx, + evTimerID opaqueID, + evTimerFunc func, + void *uap, + struct timespec max_idle +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = opaqueID.opaque; + idle_timer *tt = timer->uap; + + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle)); +} + +int +evTouchIdleTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *t = id.opaque; + idle_timer *tt = t->uap; + + tt->lastTouched = ctx->lastEventTime; + + return (0); +} + +/* Public to the rest of eventlib. */ + +heap_context +evCreateTimers(const evContext_p *ctx) { + + UNUSED(ctx); + + return (heap_new(due_sooner, set_index, 2048)); +} + +void +evDestroyTimers(const evContext_p *ctx) { + (void) heap_for_each(ctx->timers, free_timer, NULL); + (void) heap_free(ctx->timers); +} + +/* Private. */ + +static int +due_sooner(void *a, void *b) { + evTimer *a_timer, *b_timer; + + a_timer = a; + b_timer = b; + return (evCmpTime(a_timer->due, b_timer->due) < 0); +} + +static void +set_index(void *what, int index) { + evTimer *timer; + + timer = what; + timer->index = index; +} + +static void +free_timer(void *what, void *uap) { + evTimer *t = what; + + UNUSED(uap); + + FREE(t); +} + +static void +print_timer(void *what, void *uap) { + evTimer *cur = what; + evContext_p *ctx = uap; + + cur = what; + evPrintf(ctx, 7, + " func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n", + cur->func, cur->uap, + (long)cur->due.tv_sec, cur->due.tv_nsec, + (long)cur->inter.tv_sec, cur->inter.tv_nsec); +} + +static void +idle_timeout(evContext opaqueCtx, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *this = uap; + struct timespec idle; + + UNUSED(due); + UNUSED(inter); + + idle = evSubTime(ctx->lastEventTime, this->lastTouched); + if (evCmpTime(idle, this->max_idle) >= 0) { + (this->func)(opaqueCtx, this->uap, this->timer->due, + this->max_idle); + /* + * Setting the interval to zero will cause the timer to + * be cleaned up in evDrop(). + */ + this->timer->inter = evConsTime(0, 0); + FREE(this); + } else { + /* evDrop() will reschedule the timer. */ + this->timer->inter = evSubTime(this->max_idle, idle); + } +} diff --git a/usr/src/lib/libresolv2/common/isc/ev_waits.c b/usr/src/lib/libresolv2/common/isc/ev_waits.c new file mode 100644 index 0000000000..223915c853 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/ev_waits.c @@ -0,0 +1,252 @@ +/* + * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* ev_waits.c - implement deferred function calls for the eventlib + * vix 05dec95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_waits.c,v 8.12 2002/07/08 05:50:10 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <errno.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void print_waits(evContext_p *ctx); +static evWaitList * evNewWaitList(evContext_p *); +static void evFreeWaitList(evContext_p *, evWaitList *); +static evWaitList * evGetWaitList(evContext_p *, const void *, int); + + +/* Public. */ + +/* + * Enter a new wait function on the queue. + */ +int +evWaitFor(evContext opaqueCtx, const void *tag, + evWaitFunc func, void *uap, evWaitID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + evWaitList *wl = evGetWaitList(ctx, tag, 1); + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = tag; + new->next = NULL; + if (wl->last != NULL) + wl->last->next = new; + else + wl->first = new; + wl->last = new; + if (id != NULL) + id->opaque = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* + * Mark runnable all waiting functions having a certain tag. + */ +int +evDo(evContext opaqueCtx, const void *tag) { + evContext_p *ctx = opaqueCtx.opaque; + evWaitList *wl = evGetWaitList(ctx, tag, 0); + evWait *first; + + if (!wl) { + errno = ENOENT; + return (-1); + } + + first = wl->first; + INSIST(first != NULL); + + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = first; + else + ctx->waitDone.first = first; + ctx->waitDone.last = wl->last; + evFreeWaitList(ctx, wl); + + return (0); +} + +/* + * Remove a waiting (or ready to run) function from the queue. + */ +int +evUnwait(evContext opaqueCtx, evWaitID id) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *this, *prev; + evWaitList *wl; + int found = 0; + + this = id.opaque; + INSIST(this != NULL); + wl = evGetWaitList(ctx, this->tag, 0); + if (wl != NULL) { + for (prev = NULL, this = wl->first; + this != NULL; + prev = this, this = this->next) + if (this == (evWait *)id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + wl->first = this->next; + if (wl->last == this) + wl->last = prev; + if (wl->first == NULL) + evFreeWaitList(ctx, wl); + break; + } + } + + if (!found) { + /* Maybe it's done */ + for (prev = NULL, this = ctx->waitDone.first; + this != NULL; + prev = this, this = this->next) + if (this == (evWait *)id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + ctx->waitDone.first = this->next; + if (ctx->waitDone.last == this) + ctx->waitDone.last = prev; + break; + } + } + + if (!found) { + errno = ENOENT; + return (-1); + } + + FREE(this); + + if (ctx->debug >= 9) + print_waits(ctx); + + return (0); +} + +int +evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = NULL; + new->next = NULL; + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = new; + else + ctx->waitDone.first = new; + ctx->waitDone.last = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* Private. */ + +static void +print_waits(evContext_p *ctx) { + evWaitList *wl; + evWait *this; + + evPrintf(ctx, 9, "wait waiting:\n"); + for (wl = ctx->waitLists; wl != NULL; wl = wl->next) { + INSIST(wl->first != NULL); + evPrintf(ctx, 9, " tag %p:", wl->first->tag); + for (this = wl->first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %p", this); + evPrintf(ctx, 9, "\n"); + } + evPrintf(ctx, 9, "wait done:"); + for (this = ctx->waitDone.first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %p", this); + evPrintf(ctx, 9, "\n"); +} + +static evWaitList * +evNewWaitList(evContext_p *ctx) { + evWaitList *new; + + NEW(new); + if (new == NULL) + return (NULL); + new->first = new->last = NULL; + new->prev = NULL; + new->next = ctx->waitLists; + if (new->next != NULL) + new->next->prev = new; + ctx->waitLists = new; + return (new); +} + +static void +evFreeWaitList(evContext_p *ctx, evWaitList *this) { + + INSIST(this != NULL); + + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->waitLists = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + FREE(this); +} + +static evWaitList * +evGetWaitList(evContext_p *ctx, const void *tag, int should_create) { + evWaitList *this; + + for (this = ctx->waitLists; this != NULL; this = this->next) { + if (this->first != NULL && this->first->tag == tag) + break; + } + if (this == NULL && should_create) + this = evNewWaitList(ctx); + return (this); +} diff --git a/usr/src/lib/libresolv2/common/isc/eventlib.c b/usr/src/lib/libresolv2/common/isc/eventlib.c new file mode 100644 index 0000000000..8bd1eaf5e0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/eventlib.c @@ -0,0 +1,899 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* eventlib.c - implement glue for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: eventlib.c,v 1.48 2002/07/17 07:37:34 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> +#ifdef SUNW_POLL +#include <limits.h> +#endif /* SUNW_POLL */ + +#include <errno.h> +#include <signal.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +#ifdef SUNW_POLL +#define pselect Pselect +#endif /* SUNW_POLL */ + +/* Forward. */ + +#ifdef NEED_PSELECT +static int pselect(int, void *, void *, void *, + struct timespec *, + const sigset_t *); +#endif + +/* Public. */ + +int +evCreate(evContext *opaqueCtx) { + evContext_p *ctx; + + /* Make sure the memory heap is initialized. */ + if (meminit(0, 0) < 0 && errno != EEXIST) + return (-1); + + OKNEW(ctx); + + /* Global. */ + ctx->cur = NULL; + + /* Debugging. */ + ctx->debug = 0; + ctx->output = NULL; + + /* Connections. */ + ctx->conns = NULL; + INIT_LIST(ctx->accepts); + + /* Files. */ + ctx->files = NULL; +#ifdef SUNW_POLL + ctx->pollfds = 0; + ctx->maxnfds = 0; + ctx->firstfd = 0; + emulMaskInit(ctx, rdLast, EV_READ, 1); + emulMaskInit(ctx, rdNext, EV_READ, 0); + emulMaskInit(ctx, wrLast, EV_WRITE, 1); + emulMaskInit(ctx, wrNext, EV_WRITE, 0); + emulMaskInit(ctx, exLast, EV_EXCEPT, 1); + emulMaskInit(ctx, exNext, EV_EXCEPT, 0); + emulMaskInit(ctx, nonblockBefore, EV_WASNONBLOCKING, 0); +#endif /* SUNW_POLL */ + FD_ZERO(&ctx->rdNext); + FD_ZERO(&ctx->wrNext); + FD_ZERO(&ctx->exNext); + FD_ZERO(&ctx->nonblockBefore); + ctx->fdMax = -1; + ctx->fdNext = NULL; + ctx->fdCount = 0; /* Invalidate {rd,wr,ex}Last. */ +#ifdef SUNW_POLL + ctx->highestFD = INT_MAX; +#else + ctx->highestFD = FD_SETSIZE - 1; +#endif /* SUNW_POLL */ +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = 0; +#endif +#ifdef SUNW_POLL + ctx->fdTable = 0; +#else + memset(ctx->fdTable, 0, sizeof ctx->fdTable); +#endif /* SUNW_POLL */ + + /* Streams. */ + ctx->streams = NULL; + ctx->strDone = NULL; + ctx->strLast = NULL; + + /* Timers. */ + ctx->lastEventTime = evNowTime(); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + ctx->timers = evCreateTimers(ctx); + if (ctx->timers == NULL) + return (-1); + + /* Waits. */ + ctx->waitLists = NULL; + ctx->waitDone.first = ctx->waitDone.last = NULL; + ctx->waitDone.prev = ctx->waitDone.next = NULL; + + opaqueCtx->opaque = ctx; + return (0); +} + +void +evSetDebug(evContext opaqueCtx, int level, FILE *output) { + evContext_p *ctx = opaqueCtx.opaque; + + ctx->debug = level; + ctx->output = output; +} + +int +evDestroy(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + int revs = 424242; /* Doug Adams. */ + evWaitList *this_wl, *next_wl; + evWait *this_wait, *next_wait; + + /* Connections. */ + while (revs-- > 0 && ctx->conns != NULL) { + evConnID id; + + id.opaque = ctx->conns; + (void) evCancelConn(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Streams. */ + while (revs-- > 0 && ctx->streams != NULL) { + evStreamID id; + + id.opaque = ctx->streams; + (void) evCancelRW(opaqueCtx, id); + } + + /* Files. */ + while (revs-- > 0 && ctx->files != NULL) { + evFileID id; + + id.opaque = ctx->files; + (void) evDeselectFD(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Timers. */ + evDestroyTimers(ctx); + + /* Waits. */ + for (this_wl = ctx->waitLists; + revs-- > 0 && this_wl != NULL; + this_wl = next_wl) { + next_wl = this_wl->next; + for (this_wait = this_wl->first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + FREE(this_wl); + } + for (this_wait = ctx->waitDone.first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + + FREE(ctx); + return (0); +} + +int +evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) { + evContext_p *ctx = opaqueCtx.opaque; + struct timespec nextTime; + evTimer *nextTimer; + evEvent_p *new; + int x, pselect_errno, timerPast; +#ifdef EVENTLIB_TIME_CHECKS + struct timespec interval; +#endif + + /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */ + x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0); + if (x != 1) + EV_ERR(EINVAL); + + /* Get the time of day. We'll do this again after select() blocks. */ + ctx->lastEventTime = evNowTime(); + + again: + /* Finished accept()'s do not require a select(). */ + if (!EMPTY(ctx->accepts)) { + OKNEW(new); + new->type = Accept; + new->u.accept.this = HEAD(ctx->accepts); + UNLINK(ctx->accepts, HEAD(ctx->accepts), link); + opaqueEv->opaque = new; + return (0); + } + + /* Stream IO does not require a select(). */ + if (ctx->strDone != NULL) { + OKNEW(new); + new->type = Stream; + new->u.stream.this = ctx->strDone; + ctx->strDone = ctx->strDone->nextDone; + if (ctx->strDone == NULL) + ctx->strLast = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Waits do not require a select(). */ + if (ctx->waitDone.first != NULL) { + OKNEW(new); + new->type = Wait; + new->u.wait.this = ctx->waitDone.first; + ctx->waitDone.first = ctx->waitDone.first->next; + if (ctx->waitDone.first == NULL) + ctx->waitDone.last = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Get the status and content of the next timer. */ + if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) { + nextTime = nextTimer->due; + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } else + timerPast = 0; /* Make gcc happy. */ + + evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount); + if (ctx->fdCount == 0) { + static const struct timespec NoTime = {0, 0L}; + enum { JustPoll, Block, Timer } m; + struct timespec t, *tp; + + /* Are there any events at all? */ + if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1) + EV_ERR(ENOENT); + + /* Figure out what select()'s timeout parameter should be. */ + if ((options & EV_POLL) != 0) { + m = JustPoll; + t = NoTime; + tp = &t; + } else if (nextTimer == NULL) { + m = Block; + /* ``t'' unused. */ + tp = NULL; + } else if (timerPast) { + m = JustPoll; + t = NoTime; + tp = &t; + } else { + m = Timer; + /* ``t'' filled in later. */ + tp = &t; + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(ctx->lastEventTime, + ctx->lastSelectTime); + if (interval.tv_sec > 0) + evPrintf(ctx, 1, + "time between pselect() %u.%09u count %d\n", + interval.tv_sec, interval.tv_nsec, + ctx->lastFdCount); + } +#endif + do { +#ifdef SUNW_POLL + /* + * The pollfd structure uses separate fields for + * the input and output events (corresponding to + * the ??Next and ??Last fd sets), so there's no + * need to copy one to the other. + */ +#else + /* XXX need to copy only the bits we are using. */ + ctx->rdLast = ctx->rdNext; + ctx->wrLast = ctx->wrNext; + ctx->exLast = ctx->exNext; +#endif /* SUNW_POLL */ + + if (m == Timer) { + INSIST(tp == &t); + t = evSubTime(nextTime, ctx->lastEventTime); + } + +#ifdef SUNW_POLL +#else + evPrintf(ctx, 4, + "pselect(%d, 0x%lx, 0x%lx, 0x%lx, %ld.%09ld)\n", + ctx->fdMax+1, + (u_long)ctx->rdLast.fds_bits[0], + (u_long)ctx->wrLast.fds_bits[0], + (u_long)ctx->exLast.fds_bits[0], + tp ? (long)tp->tv_sec : -1L, + tp ? tp->tv_nsec : -1); +#endif + + /* XXX should predict system's earliness and adjust. */ + x = pselect(ctx->fdMax+1, + &ctx->rdLast, &ctx->wrLast, &ctx->exLast, + tp, NULL); + pselect_errno = errno; + +#ifdef SUNW_POLL + evPrintf(ctx, 4, "poll() returns %d (err: %s)\n", + x, (x == -1) ? strerror(errno) : "none"); +#else + evPrintf(ctx, 4, "select() returns %d (err: %s)\n", + x, (x == -1) ? strerror(errno) : "none"); +#endif /* SUNW_POLL */ + + /* Anything but a poll can change the time. */ + if (m != JustPoll) + ctx->lastEventTime = evNowTime(); + + /* Select() likes to finish about 10ms early. */ + } while (x == 0 && m == Timer && + evCmpTime(ctx->lastEventTime, nextTime) < 0); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + if (x < 0) { + if (pselect_errno == EINTR) { + if ((options & EV_NULL) != 0) + goto again; + OKNEW(new); + new->type = Null; + /* No data. */ + opaqueEv->opaque = new; + return (0); + } + if (pselect_errno == EBADF) { + for (x = 0; x <= ctx->fdMax; x++) { + struct stat sb; + + if (FD_ISSET(x, &ctx->rdNext) == 0 && + FD_ISSET(x, &ctx->wrNext) == 0 && + FD_ISSET(x, &ctx->exNext) == 0) + continue; + if (fstat(x, &sb) == -1 && + errno == EBADF) + evPrintf(ctx, 1, "EBADF: %d\n", + x); + } + abort(); + } + EV_ERR(pselect_errno); + } + if (x == 0 && (nextTimer == NULL || !timerPast) && + (options & EV_POLL)) + EV_ERR(EWOULDBLOCK); + ctx->fdCount = x; +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = x; +#endif + } + INSIST(nextTimer || ctx->fdCount); + + /* Timers go first since we'd like them to be accurate. */ + if (nextTimer && !timerPast) { + /* Has anything happened since we blocked? */ + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } + if (nextTimer && timerPast) { + OKNEW(new); + new->type = Timer; + new->u.timer.this = nextTimer; + opaqueEv->opaque = new; + return (0); + } + + /* No timers, so there should be a ready file descriptor. */ + x = 0; + while (ctx->fdCount > 0) { + evFile *fid; + int fd, eventmask; + + if (ctx->fdNext == NULL) { + if (++x == 2) { + /* + * Hitting the end twice means that the last + * select() found some FD's which have since + * been deselected. + * + * On some systems, the count returned by + * selects is the total number of bits in + * all masks that are set, and on others it's + * the number of fd's that have some bit set, + * and on others, it's just broken. We + * always assume that it's the number of + * bits set in all masks, because that's what + * the man page says it should do, and + * the worst that can happen is we do an + * extra select(). + */ + ctx->fdCount = 0; + break; + } + ctx->fdNext = ctx->files; + } + fid = ctx->fdNext; + ctx->fdNext = fid->next; + + fd = fid->fd; + eventmask = 0; + if (FD_ISSET(fd, &ctx->rdLast)) + eventmask |= EV_READ; + if (FD_ISSET(fd, &ctx->wrLast)) + eventmask |= EV_WRITE; + if (FD_ISSET(fd, &ctx->exLast)) + eventmask |= EV_EXCEPT; + eventmask &= fid->eventmask; + if (eventmask != 0) { + if ((eventmask & EV_READ) != 0) { + FD_CLR(fd, &ctx->rdLast); + ctx->fdCount--; + } + if ((eventmask & EV_WRITE) != 0) { + FD_CLR(fd, &ctx->wrLast); + ctx->fdCount--; + } + if ((eventmask & EV_EXCEPT) != 0) { + FD_CLR(fd, &ctx->exLast); + ctx->fdCount--; + } + OKNEW(new); + new->type = File; + new->u.file.this = fid; + new->u.file.eventmask = eventmask; + opaqueEv->opaque = new; + return (0); + } + } + if (ctx->fdCount < 0) { + /* + * select()'s count is off on a number of systems, and + * can result in fdCount < 0. + */ + evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount); + ctx->fdCount = 0; + } + + /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ + goto again; +} + +int +evDispatch(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; +#ifdef EVENTLIB_TIME_CHECKS + void *func; + struct timespec start_time; + struct timespec interval; +#endif + +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) + start_time = evNowTime(); +#endif + ctx->cur = ev; + switch (ev->type) { + case Accept: { + evAccept *this = ev->u.accept.this; + + evPrintf(ctx, 5, + "Dispatch.Accept: fd %d -> %d, func %p, uap %p\n", + this->conn->fd, this->fd, + this->conn->func, this->conn->uap); + errno = this->ioErrno; + (this->conn->func)(opaqueCtx, this->conn->uap, this->fd, + &this->la, this->lalen, + &this->ra, this->ralen); +#ifdef EVENTLIB_TIME_CHECKS + func = this->conn->func; +#endif + break; + } + case File: { + evFile *this = ev->u.file.this; + int eventmask = ev->u.file.eventmask; + + evPrintf(ctx, 5, + "Dispatch.File: fd %d, mask 0x%x, func %p, uap %p\n", + this->fd, this->eventmask, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->fd, eventmask); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Stream: { + evStream *this = ev->u.stream.this; + + evPrintf(ctx, 5, + "Dispatch.Stream: fd %d, func %p, uap %p\n", + this->fd, this->func, this->uap); + errno = this->ioErrno; + (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + + evPrintf(ctx, 5, "Dispatch.Timer: func %p, uap %p\n", + this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->due, this->inter); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Wait: { + evWait *this = ev->u.wait.this; + + evPrintf(ctx, 5, + "Dispatch.Wait: tag %p, func %p, uap %p\n", + this->tag, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->tag); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Null: { + /* No work. */ +#ifdef EVENTLIB_TIME_CHECKS + func = NULL; +#endif + break; + } + default: { + abort(); + } + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(evNowTime(), start_time); + /* + * Complain if it took longer than 50 milliseconds. + * + * We call getuid() to make an easy to find mark in a kernel + * trace. + */ + if (interval.tv_sec > 0 || interval.tv_nsec > 50000000) + evPrintf(ctx, 1, + "dispatch interval %u.%09u uid %d type %d func %p\n", + interval.tv_sec, interval.tv_nsec, + getuid(), ev->type, func); + } +#endif + ctx->cur = NULL; + evDrop(opaqueCtx, opaqueEv); + return (0); +} + +void +evDrop(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; + + switch (ev->type) { + case Accept: { + FREE(ev->u.accept.this); + break; + } + case File: { + /* No work. */ + break; + } + case Stream: { + evStreamID id; + + id.opaque = ev->u.stream.this; + (void) evCancelRW(opaqueCtx, id); + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + evTimerID opaque; + + /* Check to see whether the user func cleared the timer. */ + if (heap_element(ctx->timers, this->index) != this) { + evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n"); + break; + } + /* + * Timer is still there. Delete it if it has expired, + * otherwise set it according to its next interval. + */ + if (this->inter.tv_sec == 0 && this->inter.tv_nsec == 0L) { + opaque.opaque = this; + (void) evClearTimer(opaqueCtx, opaque); + } else { + opaque.opaque = this; + (void) evResetTimer(opaqueCtx, opaque, this->func, + this->uap, + evAddTime(ctx->lastEventTime, + this->inter), + this->inter); + } + break; + } + case Wait: { + FREE(ev->u.wait.this); + break; + } + case Null: { + /* No work. */ + break; + } + default: { + abort(); + } + } + FREE(ev); +} + +int +evMainLoop(evContext opaqueCtx) { + evEvent event; + int x; + + while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) + if ((x = evDispatch(opaqueCtx, event)) < 0) + break; + return (x); +} + +int +evHighestFD(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->highestFD); +} + +void +evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + if (ctx->output != NULL && ctx->debug >= level) { + vfprintf(ctx->output, fmt, ap); + fflush(ctx->output); + } + va_end(ap); +} + +#ifdef NEED_PSELECT +/* XXX needs to move to the porting library. */ +static int +pselect(int nfds, void *rfds, void *wfds, void *efds, + struct timespec *tsp, + const sigset_t *sigmask) +{ + struct timeval tv, *tvp; + sigset_t sigs; + int n; +#ifdef SUNW_POLL + int polltimeout = INFTIM; + evContext_p *ctx; + struct pollfd *fds; + nfds_t pnfds; +#endif + + if (tsp) { + tvp = &tv; + tv = evTimeVal(*tsp); +#ifdef SUNW_POLL + polltimeout = 1000*tv.tv_sec + tv.tv_usec/1000; +#endif + } else + tvp = NULL; + if (sigmask) + sigprocmask(SIG_SETMASK, sigmask, &sigs); +#ifdef SUNW_POLL + /* + * rfds, wfds, and efds should all be from the same evContext_p, + * so any of them will do. If they're all NULL, the caller is + * presumably calling us to block. + */ + if (rfds != 0) + ctx = ((__evEmulMask *)rfds)->ctx; + else if (wfds != 0) + ctx = ((__evEmulMask *)wfds)->ctx; + else if (efds != 0) + ctx = ((__evEmulMask *)efds)->ctx; + else + ctx = 0; + if (ctx != 0) { + fds = &(ctx->pollfds[ctx->firstfd]); + pnfds = ctx->fdMax - ctx->firstfd + 1; + } else { + fds = 0; + pnfds = 0; + } + n = poll(fds, pnfds, polltimeout); + /* + * pselect() should return the total number of events on the file + * descriptors, not just the count of fd:s with activity. Hence, + * traverse the pollfds array and count the events. + */ + if (n > 0) { + int i, e; + for (e = 0, i = ctx->firstfd; i <= ctx->fdMax; i++) { + if (ctx->pollfds[i].fd < 0) + continue; + if (FD_ISSET(i, &ctx->rdLast)) + e++; + if (FD_ISSET(i, &ctx->wrLast)) + e++; + if (FD_ISSET(i, &ctx->exLast)) + e++; + } + n = e; + } +#else + n = select(nfds, rfds, wfds, efds, tvp); +#endif /* SUNW_POLL */ + if (sigmask) + sigprocmask(SIG_SETMASK, &sigs, NULL); + if (tsp) + *tsp = evTimeSpec(tv); + return (n); +} +#endif + +#ifdef SUNW_POLL +void +evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd) { + + int old_maxnfds = ctx->maxnfds; + int i; + + if (fd < old_maxnfds) + return; + + /* Don't allow ridiculously small values for pollfd_chunk_size */ + if (pollfd_chunk_size < 20) + pollfd_chunk_size = 20; + + ctx->maxnfds = (1 + (fd/pollfd_chunk_size)) * pollfd_chunk_size; + + ctx->pollfds = realloc(ctx->pollfds, + ctx->maxnfds * sizeof(*ctx->pollfds)); + ctx->fdTable = realloc(ctx->fdTable, + ctx->maxnfds * sizeof(*ctx->fdTable)); + + if (ctx->pollfds == 0 || ctx->fdTable == 0) { + evPrintf(ctx, 2, "pollfd() realloc (%lu) failed\n", + ctx->maxnfds*sizeof(struct pollfd)); + exit(1); + } + + for (i = old_maxnfds; i < ctx->maxnfds; i++) { + ctx->pollfds[i].fd = -1; + ctx->pollfds[i].events = 0; + ctx->fdTable[i] = 0; + } +} + +/* + * Neither evPollfdAdd() nor evPollfdDel() are needed anymore. We keep + * them as no-ops for now so that the in.named code doesn't have to change. + */ +void +evPollfdAdd(evContext opaqueCtx, int pollfd_chunk_size, int fd, short events) +{ +} + +void +evPollfdDel(evContext opaqueCtx, int fd) +{ +} + +/* Find the appropriate 'events' or 'revents' field in the pollfds array */ +short * +__fd_eventfield(int fd, __evEmulMask *maskp) { + + evContext_p *ctx = (evContext_p *)maskp->ctx; + + if (!maskp->result || maskp->type == EV_WASNONBLOCKING) + return (&(ctx->pollfds[fd].events)); + else + return (&(ctx->pollfds[fd].revents)); +} + +/* Translate to poll(2) event */ +short +__poll_event(__evEmulMask *maskp) { + + switch ((maskp)->type) { + case EV_READ: + return (POLLRDNORM); + case EV_WRITE: + return (POLLWRNORM); + case EV_EXCEPT: + return (POLLRDBAND | POLLPRI | POLLWRBAND); + case EV_WASNONBLOCKING: + return (POLLHUP); + default: + return (0); + } +} + +/* + * Clear the events corresponding to the specified mask. If this leaves + * the events mask empty (apart from the POLLHUP bit), set the fd field + * to -1 so that poll(2) will ignore this fd. + */ +void +__fd_clr(int fd, __evEmulMask *maskp) { + + evContext_p *ctx = maskp->ctx; + + *__fd_eventfield(fd, maskp) &= ~__poll_event(maskp); + if ((ctx->pollfds[fd].events & ~POLLHUP) == 0) { + ctx->pollfds[fd].fd = -1; + for ( ; ctx->fdMax > 0 && ctx->pollfds[ctx->fdMax].fd < 0; + ctx->fdMax--); + for ( ; ctx->firstfd <= ctx->fdMax && + ctx->pollfds[ctx->firstfd].fd < 0; + ctx->firstfd++); + } +} + +/* + * Set the events bit(s) corresponding to the specified mask. If the events + * field has any other bits than POLLHUP set, also set the fd field so that + * poll(2) will watch this fd. + */ +void +__fd_set(int fd, __evEmulMask *maskp) { + + evContext_p *ctx = maskp->ctx; + + *__fd_eventfield(fd, maskp) |= __poll_event(maskp); + if ((ctx->pollfds[fd].events & ~POLLHUP) != 0) { + ctx->pollfds[fd].fd = fd; + if (fd < ctx->firstfd || ctx->firstfd == 0) + ctx->firstfd = fd; + if (fd > ctx->fdMax) + ctx->fdMax = fd; + } +} +#endif diff --git a/usr/src/lib/libresolv2/common/isc/eventlib_p.h b/usr/src/lib/libresolv2/common/isc/eventlib_p.h new file mode 100644 index 0000000000..28aa9fb25d --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/eventlib_p.h @@ -0,0 +1,281 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* eventlib_p.h - private interfaces for eventlib + * vix 09sep95 [initial] + * + * $Id: eventlib_p.h,v 1.31 2003/04/03 05:37:56 marka Exp $ + */ + +#ifndef _EVENTLIB_P_H +#define _EVENTLIB_P_H + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/un.h> + +#define EVENTLIB_DEBUG 1 + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/heap.h> +#include <isc/list.h> +#include <isc/memcluster.h> + +#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT) +#define EV_ERR(e) return (errno = (e), -1) +#define OK(x) if ((x) < 0) EV_ERR(errno); else (void)NULL + +#define NEW(p) if (((p) = memget(sizeof *(p))) != NULL) \ + FILL(p); \ + else \ + (void)NULL; +#define OKNEW(p) if (!((p) = memget(sizeof *(p)))) { \ + errno = ENOMEM; \ + return (-1); \ + } else \ + FILL(p) +#define FREE(p) memput((p), sizeof *(p)) + +#if EVENTLIB_DEBUG +#define FILL(p) memset((p), 0xF5, sizeof *(p)) +#else +#define FILL(p) +#endif + +#ifdef SUNW_POLL +#include <stropts.h> +#include <poll.h> +#endif + +typedef struct evConn { + evConnFunc func; + void * uap; + int fd; + int flags; +#define EV_CONN_LISTEN 0x0001 /* Connection is a listener. */ +#define EV_CONN_SELECTED 0x0002 /* evSelectFD(conn->file). */ +#define EV_CONN_BLOCK 0x0004 /* Listener fd was blocking. */ + evFileID file; + struct evConn * prev; + struct evConn * next; +} evConn; + +typedef struct evAccept { + int fd; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la; + ISC_SOCKLEN_T lalen; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } ra; + ISC_SOCKLEN_T ralen; + int ioErrno; + evConn * conn; + LINK(struct evAccept) link; +} evAccept; + +typedef struct evFile { + evFileFunc func; + void * uap; + int fd; + int eventmask; + int preemptive; + struct evFile * prev; + struct evFile * next; + struct evFile * fdprev; + struct evFile * fdnext; +} evFile; + +typedef struct evStream { + evStreamFunc func; + void * uap; + evFileID file; + evTimerID timer; + int flags; +#define EV_STR_TIMEROK 0x0001 /* IFF timer valid. */ + int fd; + struct iovec * iovOrig; + int iovOrigCount; + struct iovec * iovCur; + int iovCurCount; + int ioTotal; + int ioDone; + int ioErrno; + struct evStream *prevDone, *nextDone; + struct evStream *prev, *next; +} evStream; + +typedef struct evTimer { + evTimerFunc func; + void * uap; + struct timespec due, inter; + int index; +} evTimer; + +typedef struct evWait { + evWaitFunc func; + void * uap; + const void * tag; + struct evWait * next; +} evWait; + +typedef struct evWaitList { + evWait * first; + evWait * last; + struct evWaitList * prev; + struct evWaitList * next; +} evWaitList; + +typedef struct evEvent_p { + enum { Accept, File, Stream, Timer, Wait, Free, Null } type; + union { + struct { evAccept *this; } accept; + struct { evFile *this; int eventmask; } file; + struct { evStream *this; } stream; + struct { evTimer *this; } timer; + struct { evWait *this; } wait; + struct { struct evEvent_p *next; } free; + struct { const void *placeholder; } null; + } u; +} evEvent_p; + +#ifdef SUNW_POLL +typedef struct { + void *ctx; /* Pointer to the evContext_p */ + uint32_t type; /* READ, WRITE, EXCEPT, nonblk */ + uint32_t result; /* 1 => revents, 0 => events */ +} __evEmulMask; + +#define emulMaskInit(ctx, field, ev, lastnext) \ + ctx->field.ctx = ctx; \ + ctx->field.type = ev; \ + ctx->field.result = lastnext; + +/* Any value other than EV_* values from <isc/eventlib.h> will do */ +#define EV_WASNONBLOCKING 4000000001 + +extern short *__fd_eventfield(int fd, __evEmulMask *maskp); +extern short __poll_event(__evEmulMask *maskp); +extern void __fd_clr(int fd, __evEmulMask *maskp); +extern void __fd_set(int fd, __evEmulMask *maskp); + +#undef FD_ZERO +#define FD_ZERO(maskp) + +#undef FD_SET +#define FD_SET(fd, maskp) \ + __fd_set(fd, maskp) + +#undef FD_CLR +#define FD_CLR(fd, maskp) \ + __fd_clr(fd, maskp) + +#undef FD_ISSET +#define FD_ISSET(fd, maskp) \ + ((*__fd_eventfield(fd, maskp) & __poll_event(maskp)) != 0) + +#endif /* SUNW_POLL */ + +typedef struct { + /* Global. */ + const evEvent_p *cur; + /* Debugging. */ + int debug; + FILE *output; + /* Connections. */ + evConn *conns; + LIST(evAccept) accepts; + /* Files. */ + evFile *files, *fdNext; +#ifdef SUNW_POLL + struct pollfd *pollfds; /* Allocated as needed */ + evFile **fdTable; /* Ditto */ + int maxnfds; /* # elements in above */ + int firstfd; /* First active fd */ + int fdMax; /* Last active fd */ + int fdCount; /* # fd:s with I/O */ + int highestFD; /* Max fd allowed by OS */ + __evEmulMask rdLast, rdNext; + __evEmulMask wrLast, wrNext; + __evEmulMask exLast, exNext; + __evEmulMask nonblockBefore; +#else + fd_set rdLast, rdNext; + fd_set wrLast, wrNext; + fd_set exLast, exNext; + fd_set nonblockBefore; + int fdMax, fdCount, highestFD; + evFile *fdTable[FD_SETSIZE]; +#endif +#ifdef EVENTLIB_TIME_CHECKS + struct timespec lastSelectTime; + int lastFdCount; +#endif + /* Streams. */ + evStream *streams; + evStream *strDone, *strLast; + /* Timers. */ + struct timespec lastEventTime; + heap_context timers; + /* Waits. */ + evWaitList *waitLists; + evWaitList waitDone; +} evContext_p; + +/* eventlib.c */ +#define evPrintf __evPrintf +void evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) + ISC_FORMAT_PRINTF(3, 4); + +#ifdef SUNW_POLL +extern void evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd); +#endif /* SUNW_POLL */ + +/* ev_timers.c */ +#define evCreateTimers __evCreateTimers +heap_context evCreateTimers(const evContext_p *); +#define evDestroyTimers __evDestroyTimers +void evDestroyTimers(const evContext_p *); + +/* ev_waits.c */ +#define evFreeWait __evFreeWait +evWait *evFreeWait(evContext_p *ctx, evWait *old); + +#endif /*_EVENTLIB_P_H*/ diff --git a/usr/src/lib/libresolv2/common/isc/heap.c b/usr/src/lib/libresolv2/common/isc/heap.c new file mode 100644 index 0000000000..72c823d9d8 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/heap.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Heap implementation of priority queues adapted from the following: + * + * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest, + * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7. + * + * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988, + * ISBN 0-201-06673-4, chapter 11. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: heap.c,v 8.7 1999/10/13 16:39:34 vixie Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <stddef.h> +#include <stdlib.h> +#include <errno.h> + +#include "port_after.h" + +#include <isc/heap.h> + +/* + * Note: to make heap_parent and heap_left easy to compute, the first + * element of the heap array is not used; i.e. heap subscripts are 1-based, + * not 0-based. + */ +#define heap_parent(i) ((i) >> 1) +#define heap_left(i) ((i) << 1) + +#define ARRAY_SIZE_INCREMENT 512 + +heap_context +heap_new(heap_higher_priority_func higher_priority, heap_index_func index, + int array_size_increment) { + heap_context ctx; + + ctx = (heap_context)malloc(sizeof (struct heap_context)); + if (ctx == NULL || higher_priority == NULL) + return (NULL); + ctx->array_size = 0; + if (array_size_increment == 0) + ctx->array_size_increment = ARRAY_SIZE_INCREMENT; + else + ctx->array_size_increment = array_size_increment; + ctx->heap_size = 0; + ctx->heap = NULL; + ctx->higher_priority = higher_priority; + ctx->index = index; + return (ctx); +} + +int +heap_free(heap_context ctx) { + if (ctx == NULL) { + errno = EINVAL; + return (-1); + } + + if (ctx->heap != NULL) + free(ctx->heap); + free(ctx); + + return (0); +} + +static int +heap_resize(heap_context ctx) { + void **new_heap; + + ctx->array_size += ctx->array_size_increment; + new_heap = (void **)realloc(ctx->heap, + (ctx->array_size) * (sizeof (void *))); + if (new_heap == NULL) { + errno = ENOMEM; + return (-1); + } + ctx->heap = new_heap; + return (0); +} + +static void +float_up(heap_context ctx, int i, void *elt) { + int p; + + for ( p = heap_parent(i); + i > 1 && ctx->higher_priority(elt, ctx->heap[p]); + i = p, p = heap_parent(i) ) { + ctx->heap[i] = ctx->heap[p]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +static void +sink_down(heap_context ctx, int i, void *elt) { + int j, size, half_size; + + size = ctx->heap_size; + half_size = size / 2; + while (i <= half_size) { + /* find smallest of the (at most) two children */ + j = heap_left(i); + if (j < size && ctx->higher_priority(ctx->heap[j+1], + ctx->heap[j])) + j++; + if (ctx->higher_priority(elt, ctx->heap[j])) + break; + ctx->heap[i] = ctx->heap[j]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + i = j; + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +int +heap_insert(heap_context ctx, void *elt) { + int i; + + if (ctx == NULL || elt == NULL) { + errno = EINVAL; + return (-1); + } + + i = ++ctx->heap_size; + if (ctx->heap_size >= ctx->array_size && heap_resize(ctx) < 0) + return (-1); + + float_up(ctx, i, elt); + + return (0); +} + +int +heap_delete(heap_context ctx, int i) { + void *elt; + + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + elt = ctx->heap[ctx->heap_size]; + if (--ctx->heap_size > 0) + sink_down(ctx, i, elt); + + return (0); +} + +int +heap_increased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + float_up(ctx, i, ctx->heap[i]); + + return (0); +} + +int +heap_decreased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + sink_down(ctx, i, ctx->heap[i]); + + return (0); +} + +void * +heap_element(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (NULL); + } + + return (ctx->heap[i]); +} + +int +heap_for_each(heap_context ctx, heap_for_each_func action, void *uap) { + int i; + + if (ctx == NULL || action == NULL) { + errno = EINVAL; + return (-1); + } + + for (i = 1; i <= ctx->heap_size; i++) + (action)(ctx->heap[i], uap); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/isc/hex.c b/usr/src/lib/libresolv2/common/isc/hex.c new file mode 100644 index 0000000000..5e1f6e8364 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/hex.c @@ -0,0 +1,123 @@ +/* + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 2001 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <port_before.h> +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <isc/misc.h> +#include <port_after.h> + +static const char hex[17] = "0123456789abcdef"; + +int +isc_gethexstring(unsigned char *buf, size_t len, int count, FILE *fp, + int *multiline) +{ + int c, n; + unsigned char x; + char *s; + int result = count; + + x = 0; /* silence compiler */ + n = 0; + while (count > 0) { + c = fgetc(fp); + + if ((c == EOF) || + (c == '\n' && !*multiline) || + (c == '(' && *multiline) || + (c == ')' && !*multiline)) + goto formerr; + /* comment */ + if (c == ';') { + while ((c = fgetc(fp)) != EOF && c != '\n') + /* empty */ + if (c == '\n' && *multiline) + continue; + goto formerr; + } + /* white space */ + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') + continue; + /* multiline */ + if ('(' == c || c == ')') { + *multiline = (c == '(' /*)*/); + continue; + } + if ((s = strchr(hex, tolower(c))) == NULL) + goto formerr; + x = (x<<4) | (s - hex); + if (++n == 2) { + if (len > 0) { + *buf++ = x; + len--; + } else + result = -1; + count--; + n = 0; + } + } + return (result); + + formerr: + if (c == '\n') + ungetc(c, fp); + return (-1); +} + +void +isc_puthexstring(FILE *fp, const unsigned char *buf, size_t buflen, + size_t len1, size_t len2, const char *sep) +{ + size_t i = 0; + + if (len1 < 4) + len1 = 4; + if (len2 < 4) + len2 = 4; + while (buflen > 0) { + fputc(hex[(buf[0]>>4)&0xf], fp); + fputc(hex[buf[0]&0xf], fp); + i += 2; + buflen--; + buf++; + if (i >= len1 && sep != NULL) { + fputs(sep, fp); + i = 0; + len1 = len2; + } + } +} + +void +isc_tohex(const unsigned char *buf, size_t buflen, char *t) { + while (buflen > 0) { + *t++ = hex[(buf[0]>>4)&0xf]; + *t++ = hex[buf[0]&0xf]; + buf++; + buflen--; + } + *t = '\0'; +} diff --git a/usr/src/lib/libresolv2/common/isc/logging.c b/usr/src/lib/libresolv2/common/isc/logging.c new file mode 100644 index 0000000000..13fc49259d --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/logging.c @@ -0,0 +1,727 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: logging.c,v 8.32 2003/01/02 00:35:42 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> + +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <syslog.h> +#include <errno.h> +#include <time.h> +#include <unistd.h> + +#include <isc/assertions.h> +#include <isc/logging.h> +#include <isc/memcluster.h> +#include <isc/misc.h> + +#include "port_after.h" + +#ifdef VSPRINTF_CHAR +# define VSPRINTF(x) strlen(vsprintf/**/x) +#else +# define VSPRINTF(x) ((size_t)vsprintf x) +#endif + +#include "logging_p.h" + +static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, + LOG_WARNING, LOG_ERR, LOG_CRIT }; + +static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +static const char *level_text[] = { + "info: ", "notice: ", "warning: ", "error: ", "critical: " +}; + +static void +version_rename(log_channel chan) { + unsigned int ver; + char old_name[PATH_MAX+1]; + char new_name[PATH_MAX+1]; + + ver = chan->out.file.versions; + if (ver < 1) + return; + if (ver > LOG_MAX_VERSIONS) + ver = LOG_MAX_VERSIONS; + /* + * Need to have room for '.nn' (XXX assumes LOG_MAX_VERSIONS < 100) + */ + if (strlen(chan->out.file.name) > (PATH_MAX-3)) + return; + for (ver--; ver > 0; ver--) { + sprintf(old_name, "%s.%d", chan->out.file.name, ver-1); + sprintf(new_name, "%s.%d", chan->out.file.name, ver); + (void)rename(old_name, new_name); + } + sprintf(new_name, "%s.0", chan->out.file.name); + (void)rename(chan->out.file.name, new_name); +} + +FILE * +log_open_stream(log_channel chan) { + FILE *stream; + int fd, flags; + struct stat sb; + int regular; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + + /* + * Don't open already open streams + */ + if (chan->out.file.stream != NULL) + return (chan->out.file.stream); + + if (stat(chan->out.file.name, &sb) < 0) { + if (errno != ENOENT) { + syslog(LOG_ERR, + "log_open_stream: stat of %s failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + regular = 1; + } else + regular = (sb.st_mode & S_IFREG); + + if (chan->out.file.versions) { + if (!regular) { + syslog(LOG_ERR, + "log_open_stream: want versions but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + flags = O_WRONLY|O_CREAT|O_APPEND; + + if ((chan->flags & LOG_TRUNCATE) != 0) { + if (regular) { + (void)unlink(chan->out.file.name); + flags |= O_EXCL; + } else { + syslog(LOG_ERR, + "log_open_stream: want truncation but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + fd = open(chan->out.file.name, flags, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (fd < 0) { + syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + stream = fdopen(fd, "a"); + if (stream == NULL) { + syslog(LOG_ERR, "log_open_stream: fdopen() failed"); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + (void) fchown(fd, chan->out.file.owner, chan->out.file.group); + + chan->out.file.stream = stream; + return (stream); +} + +int +log_close_stream(log_channel chan) { + FILE *stream; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (0); + } + stream = chan->out.file.stream; + chan->out.file.stream = NULL; + if (stream != NULL && fclose(stream) == EOF) + return (-1); + return (0); +} + +void +log_close_debug_channels(log_context lc) { + log_channel_list lcl; + int i; + + for (i = 0; i < lc->num_categories; i++) + for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl->next) + if (lcl->channel->type == log_file && + lcl->channel->out.file.stream != NULL && + lcl->channel->flags & LOG_REQUIRE_DEBUG) + (void)log_close_stream(lcl->channel); +} + +FILE * +log_get_stream(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.stream); +} + +char * +log_get_filename(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.name); +} + +int +log_check_channel(log_context lc, int level, log_channel chan) { + int debugging, chan_level; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if ((chan->flags & (LOG_CHANNEL_BROKEN|LOG_CHANNEL_OFF)) != 0) + return (0); + + /* Some channels only log when debugging is on. */ + if ((chan->flags & LOG_REQUIRE_DEBUG) && !debugging) + return (0); + + /* Some channels use the global level. */ + if ((chan->flags & LOG_USE_CONTEXT_LEVEL) != 0) { + chan_level = lc->level; + } else + chan_level = chan->level; + + if (level > chan_level) + return (0); + + return (1); +} + +int +log_check(log_context lc, int category, int level) { + log_channel_list lcl; + int debugging; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if (category < 0 || category > lc->num_categories) + category = 0; /* use default */ + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + if (log_check_channel(lc, level, lcl->channel)) + return (1); + } + return (0); +} + +void +log_vwrite(log_context lc, int category, int level, const char *format, + va_list args) { + log_channel_list lcl; + int pri, debugging, did_vsprintf = 0; + int original_category; + FILE *stream; + log_channel chan; + struct timeval tv; + struct tm *local_tm; +#ifdef HAVE_TIME_R + struct tm tm_tmp; +#endif + time_t tt; + const char *category_name; + const char *level_str; + char time_buf[256]; + char level_buf[256]; + + REQUIRE(lc != NULL); + + debugging = (lc->flags & LOG_OPTION_DEBUG); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return; + + if (category < 0 || category > lc->num_categories) + category = 0; /* use default */ + original_category = category; + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + /* + * Get the current time and format it. + */ + time_buf[0]='\0'; + if (gettimeofday(&tv, NULL) < 0) { + syslog(LOG_INFO, "gettimeofday failed in log_vwrite()"); + } else { + tt = tv.tv_sec; +#ifdef HAVE_TIME_R + local_tm = localtime_r(&tt, &tm_tmp); +#else + local_tm = localtime(&tt); +#endif + if (local_tm != NULL) { + sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ", + local_tm->tm_mday, months[local_tm->tm_mon], + local_tm->tm_year+1900, local_tm->tm_hour, + local_tm->tm_min, local_tm->tm_sec, + (long)tv.tv_usec/1000); + } + } + + /* + * Make a string representation of the current category and level + */ + + if (lc->category_names != NULL && + lc->category_names[original_category] != NULL) + category_name = lc->category_names[original_category]; + else + category_name = ""; + + if (level >= log_critical) { + if (level >= 0) { + sprintf(level_buf, "debug %d: ", level); + level_str = level_buf; + } else + level_str = level_text[-level-1]; + } else { + sprintf(level_buf, "level %d: ", level); + level_str = level_buf; + } + + /* + * Write the message to channels. + */ + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + chan = lcl->channel; + + if (!log_check_channel(lc, level, chan)) + continue; + + if (!did_vsprintf) { + if (VSPRINTF((lc->buffer, format, args)) > + LOG_BUFFER_SIZE) { + syslog(LOG_CRIT, + "memory overrun in log_vwrite()"); + exit(1); + } + did_vsprintf = 1; + } + + switch (chan->type) { + case log_syslog: + if (level >= log_critical) + pri = (level >= 0) ? 0 : -level; + else + pri = -log_critical; + syslog(chan->out.facility|syslog_priority[pri], + "%s%s%s%s", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + break; + case log_file: + stream = chan->out.file.stream; + if (stream == NULL) { + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + if (chan->out.file.max_size != ULONG_MAX) { + long pos; + + pos = ftell(stream); + if (pos >= 0 && + (unsigned long)pos > + chan->out.file.max_size) { + /* + * try to roll over the log files, + * ignoring all all return codes + * except the open (we don't want + * to write any more anyway) + */ + log_close_stream(chan); + version_rename(chan); + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + } + fprintf(stream, "%s%s%s%s\n", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + fflush(stream); + break; + case log_null: + break; + default: + syslog(LOG_ERR, + "unknown channel type in log_vwrite()"); + } + } +} + +void +log_write(log_context lc, int category, int level, const char *format, ...) { + va_list args; + + va_start(args, format); + log_vwrite(lc, category, level, format, args); + va_end(args); +} + +/* + * Functions to create, set, or destroy contexts + */ + +int +log_new_context(int num_categories, char **category_names, log_context *lc) { + log_context nlc; + + nlc = memget(sizeof (struct log_context)); + if (nlc == NULL) { + errno = ENOMEM; + return (-1); + } + nlc->num_categories = num_categories; + nlc->category_names = category_names; + nlc->categories = memget(num_categories * sizeof (log_channel_list)); + if (nlc->categories == NULL) { + memput(nlc, sizeof (struct log_context)); + errno = ENOMEM; + return (-1); + } + memset(nlc->categories, '\0', + num_categories * sizeof (log_channel_list)); + nlc->flags = 0U; + nlc->level = 0; + *lc = nlc; + return (0); +} + +void +log_free_context(log_context lc) { + log_channel_list lcl, lcl_next; + log_channel chan; + int i; + + REQUIRE(lc != NULL); + + for (i = 0; i < lc->num_categories; i++) + for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl_next) { + lcl_next = lcl->next; + chan = lcl->channel; + (void)log_free_channel(chan); + memput(lcl, sizeof (struct log_channel_list)); + } + memput(lc->categories, + lc->num_categories * sizeof (log_channel_list)); + memput(lc, sizeof (struct log_context)); +} + +int +log_add_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + lcl = memget(sizeof (struct log_channel_list)); + if (lcl == NULL) { + errno = ENOMEM; + return(-1); + } + lcl->channel = chan; + lcl->next = lc->categories[category]; + lc->categories[category] = lcl; + chan->references++; + return (0); +} + +int +log_remove_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl, prev_lcl, next_lcl; + int found = 0; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + for (prev_lcl = NULL, lcl = lc->categories[category]; + lcl != NULL; + lcl = next_lcl) { + next_lcl = lcl->next; + if (lcl->channel == chan) { + log_free_channel(chan); + if (prev_lcl != NULL) + prev_lcl->next = next_lcl; + else + lc->categories[category] = next_lcl; + memput(lcl, sizeof (struct log_channel_list)); + /* + * We just set found instead of returning because + * the channel might be on the list more than once. + */ + found = 1; + } else + prev_lcl = lcl; + } + if (!found) { + errno = ENOENT; + return (-1); + } + return (0); +} + +int +log_option(log_context lc, int option, int value) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + switch (option) { + case LOG_OPTION_DEBUG: + if (value) + lc->flags |= option; + else + lc->flags &= ~option; + break; + case LOG_OPTION_LEVEL: + lc->level = value; + break; + default: + errno = EINVAL; + return (-1); + } + return (0); +} + +int +log_category_is_active(log_context lc, int category) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + if (category >= 0 && category < lc->num_categories && + lc->categories[category] != NULL) + return (1); + return (0); +} + +log_channel +log_new_syslog_channel(unsigned int flags, int level, int facility) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_syslog; + chan->flags = flags; + chan->level = level; + chan->out.facility = facility; + chan->references = 0; + return (chan); +} + +log_channel +log_new_file_channel(unsigned int flags, int level, + const char *name, FILE *stream, unsigned int versions, + unsigned long max_size) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_file; + chan->flags = flags; + chan->level = level; + if (name != NULL) { + size_t len; + + len = strlen(name); + /* + * Quantize length to a multiple of 256. There's space for the + * NUL, since if len is a multiple of 256, the size chosen will + * be the next multiple. + */ + chan->out.file.name_size = ((len / 256) + 1) * 256; + chan->out.file.name = memget(chan->out.file.name_size); + if (chan->out.file.name == NULL) { + memput(chan, sizeof (struct log_channel)); + errno = ENOMEM; + return (NULL); + } + /* This is safe. */ + strcpy(chan->out.file.name, name); + } else { + chan->out.file.name_size = 0; + chan->out.file.name = NULL; + } + chan->out.file.stream = stream; + chan->out.file.versions = versions; + chan->out.file.max_size = max_size; + chan->out.file.owner = getuid(); + chan->out.file.group = getgid(); + chan->references = 0; + return (chan); +} + +int +log_set_file_owner(log_channel chan, uid_t owner, gid_t group) { + if (chan->type != log_file) { + errno = EBADF; + return (-1); + } + chan->out.file.owner = owner; + chan->out.file.group = group; + return (0); +} + +log_channel +log_new_null_channel() { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_null; + chan->flags = LOG_CHANNEL_OFF; + chan->level = log_info; + chan->references = 0; + return (chan); +} + +int +log_inc_references(log_channel chan) { + if (chan == NULL) { + errno = EINVAL; + return (-1); + } + chan->references++; + return (0); +} + +int +log_dec_references(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + return (0); +} + +log_channel_type +log_get_channel_type(log_channel chan) { + REQUIRE(chan != NULL); + + return (chan->type); +} + +int +log_free_channel(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + if (chan->references == 0) { + if (chan->type == log_file) { + if ((chan->flags & LOG_CLOSE_STREAM) && + chan->out.file.stream != NULL) + (void)fclose(chan->out.file.stream); + if (chan->out.file.name != NULL) + memput(chan->out.file.name, + chan->out.file.name_size); + } + memput(chan, sizeof (struct log_channel)); + } + return (0); +} diff --git a/usr/src/lib/libresolv2/common/isc/logging_p.h b/usr/src/lib/libresolv2/common/isc/logging_p.h new file mode 100644 index 0000000000..d85af6f2fc --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/logging_p.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1997-2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef LOGGING_P_H +#define LOGGING_P_H + +typedef struct log_file_desc { + char *name; + size_t name_size; + FILE *stream; + unsigned int versions; + unsigned long max_size; + uid_t owner; + gid_t group; +} log_file_desc; + +typedef union log_output { + int facility; + log_file_desc file; +} log_output; + +struct log_channel { + int level; /* don't log messages > level */ + log_channel_type type; + log_output out; + unsigned int flags; + int references; +}; + +typedef struct log_channel_list { + log_channel channel; + struct log_channel_list *next; +} *log_channel_list; + +#define LOG_BUFFER_SIZE 20480 + +struct log_context { + int num_categories; + char **category_names; + log_channel_list *categories; + int flags; + int level; + char buffer[LOG_BUFFER_SIZE]; +}; + +#endif /* !LOGGING_P_H */ diff --git a/usr/src/lib/libresolv2/common/isc/memcluster.c b/usr/src/lib/libresolv2/common/isc/memcluster.c new file mode 100644 index 0000000000..03fb6d3c8b --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/memcluster.c @@ -0,0 +1,588 @@ +/* + * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* When this symbol is defined allocations via memget are made slightly + bigger and some debugging info stuck before and after the region given + back to the caller. */ +/* #define DEBUGGING_MEMCLUSTER */ +#define MEMCLUSTER_ATEND + + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: memcluster.c,v 8.23 2001/06/18 14:44:05 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/param.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <isc/memcluster.h> +#include <isc/assertions.h> + +#include "port_after.h" + +#ifdef MEMCLUSTER_RECORD +#ifndef DEBUGGING_MEMCLUSTER +#define DEBUGGING_MEMCLUSTER +#endif +#endif + +#define DEF_MAX_SIZE 1100 +#define DEF_MEM_TARGET 4096 + +typedef u_int32_t fence_t; + +typedef struct { + void * next; +#if defined(DEBUGGING_MEMCLUSTER) +#if defined(MEMCLUSTER_RECORD) + const char * file; + int line; +#endif + size_t size; + fence_t fencepost; +#endif +} memcluster_element; + +#define SMALL_SIZE_LIMIT sizeof(memcluster_element) +#define P_SIZE sizeof(void *) +#define FRONT_FENCEPOST 0xfebafeba +#define BACK_FENCEPOST 0xabefabef +#define FENCEPOST_SIZE 4 + +#ifndef MEMCLUSTER_LITTLE_MALLOC +#define MEMCLUSTER_BIG_MALLOC 1 +#define NUM_BASIC_BLOCKS 64 +#endif + +struct stats { + u_long gets; + u_long totalgets; + u_long blocks; + u_long freefrags; +}; + +/* Private data. */ + +#ifdef SUNW_MT_RESOLVER +#include <thread.h> +#include <synch.h> +static mutex_t memlock = DEFAULTMUTEX; +#define SUNW_MEMLOCK (void)mutex_lock(&memlock) +#define SUNW_MEMUNLOCK (void)mutex_unlock(&memlock) +#define SUNW_MEMLOCKBLOCK_BEGIN { +#define SUNW_MEMLOCKBLOCK_END } +#else +#define SUNW_MEMLOCK +#define SUNW_MEMUNLOCK +#define SUNW_MEMLOCKBLOCK_BEGIN +#define SUNW_MEMLOCKBLOCK_END +#endif /* SUNW_MT_RESOLVER */ + +static size_t max_size; +static size_t mem_target; +static size_t mem_target_half; +static size_t mem_target_fudge; +static memcluster_element ** freelists; +#ifdef MEMCLUSTER_RECORD +static memcluster_element ** activelists; +#endif +#ifdef MEMCLUSTER_BIG_MALLOC +static memcluster_element * basic_blocks; +#endif +static struct stats * stats; + +/* Forward. */ + +static size_t quantize(size_t); +#if defined(DEBUGGING_MEMCLUSTER) +static void check(unsigned char *, int, size_t); +#endif + +/* Public. */ + +int +meminit(size_t init_max_size, size_t target_size) { + +#if defined(DEBUGGING_MEMCLUSTER) + INSIST(sizeof(fence_t) == FENCEPOST_SIZE); +#endif + if (freelists != NULL) { + errno = EEXIST; + return (-1); + } + if (init_max_size == 0) + max_size = DEF_MAX_SIZE; + else + max_size = init_max_size; + if (target_size == 0) + mem_target = DEF_MEM_TARGET; + else + mem_target = target_size; + mem_target_half = mem_target / 2; + mem_target_fudge = mem_target + mem_target / 4; + freelists = malloc(max_size * sizeof (memcluster_element *)); + stats = malloc((max_size+1) * sizeof (struct stats)); + if (freelists == NULL || stats == NULL) { + errno = ENOMEM; + return (-1); + } + memset(freelists, 0, + max_size * sizeof (memcluster_element *)); + memset(stats, 0, (max_size + 1) * sizeof (struct stats)); +#ifdef MEMCLUSTER_RECORD + activelists = malloc((max_size + 1) * sizeof (memcluster_element *)); + if (activelists == NULL) { + errno = ENOMEM; + return (-1); + } + memset(activelists, 0, + (max_size + 1) * sizeof (memcluster_element *)); +#endif +#ifdef MEMCLUSTER_BIG_MALLOC + basic_blocks = NULL; +#endif + return (0); +} + +void * +__memget(size_t size) { + return (__memget_record(size, NULL, 0)); +} + +void * +__memget_record(size_t size, const char *file, int line) { + size_t new_size = quantize(size); +#if defined(DEBUGGING_MEMCLUSTER) + memcluster_element *e; + char *p; + fence_t fp = BACK_FENCEPOST; +#endif + void *ret; + + SUNW_MEMLOCK; + +#if !defined(MEMCLUSTER_RECORD) + UNUSED(file); + UNUSED(line); +#endif + if (freelists == NULL) + if (meminit(0, 0) == -1) +SUNW_MEMLOCKBLOCK_BEGIN + SUNW_MEMUNLOCK; + return (NULL); +SUNW_MEMLOCKBLOCK_END + if (size == 0) { + SUNW_MEMUNLOCK; + errno = EINVAL; + return (NULL); + } + if (size >= max_size || new_size >= max_size) { + /* memget() was called on something beyond our upper limit. */ + stats[max_size].gets++; + stats[max_size].totalgets++; +#if defined(DEBUGGING_MEMCLUSTER) + e = malloc(new_size); + if (e == NULL) { + SUNW_MEMUNLOCK; + errno = ENOMEM; + return (NULL); + } + e->next = NULL; + e->size = size; +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; + e->next = activelists[max_size]; + activelists[max_size] = e; +#endif + SUNW_MEMUNLOCK; + e->fencepost = FRONT_FENCEPOST; + p = (char *)e + sizeof *e + size; + memcpy(p, &fp, sizeof fp); + return ((char *)e + sizeof *e); +#else + SUNW_MEMUNLOCK; + return (malloc(size)); +#endif + } + + /* + * If there are no blocks in the free list for this size, get a chunk + * of memory and then break it up into "new_size"-sized blocks, adding + * them to the free list. + */ + if (freelists[new_size] == NULL) { + int i, frags; + size_t total_size; + void *new; + char *curr, *next; + +#ifdef MEMCLUSTER_BIG_MALLOC + if (basic_blocks == NULL) { + new = malloc(NUM_BASIC_BLOCKS * mem_target); + if (new == NULL) { + SUNW_MEMUNLOCK; + errno = ENOMEM; + return (NULL); + } + curr = new; + next = curr + mem_target; + for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) { + ((memcluster_element *)curr)->next = next; + curr = next; + next += mem_target; + } + /* + * curr is now pointing at the last block in the + * array. + */ + ((memcluster_element *)curr)->next = NULL; + basic_blocks = new; + } + total_size = mem_target; + new = basic_blocks; + basic_blocks = basic_blocks->next; +#else + if (new_size > mem_target_half) + total_size = mem_target_fudge; + else + total_size = mem_target; + new = malloc(total_size); + if (new == NULL) { + SUNW_MEMUNLOCK; + errno = ENOMEM; + return (NULL); + } +#endif + frags = total_size / new_size; + stats[new_size].blocks++; + stats[new_size].freefrags += frags; + /* Set up a linked-list of blocks of size "new_size". */ + curr = new; + next = curr + new_size; + for (i = 0; i < (frags - 1); i++) { +#if defined (DEBUGGING_MEMCLUSTER) + memset(curr, 0xa5, new_size); +#endif + ((memcluster_element *)curr)->next = next; + curr = next; + next += new_size; + } + /* curr is now pointing at the last block in the array. */ +#if defined (DEBUGGING_MEMCLUSTER) + memset(curr, 0xa5, new_size); +#endif + ((memcluster_element *)curr)->next = freelists[new_size]; + freelists[new_size] = new; + } + + /* The free list uses the "rounded-up" size "new_size". */ +#if defined (DEBUGGING_MEMCLUSTER) + e = freelists[new_size]; + ret = (char *)e + sizeof *e; + /* + * Check to see if this buffer has been written to while on free list. + */ + check(ret, 0xa5, new_size - sizeof *e); + /* + * Mark memory we are returning. + */ + memset(ret, 0xe5, size); +#else + ret = freelists[new_size]; +#endif + freelists[new_size] = freelists[new_size]->next; +#if defined(DEBUGGING_MEMCLUSTER) + e->next = NULL; + e->size = size; + e->fencepost = FRONT_FENCEPOST; +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; + e->next = activelists[size]; + activelists[size] = e; +#endif + p = (char *)e + sizeof *e + size; + memcpy(p, &fp, sizeof fp); +#endif + + /* + * The stats[] uses the _actual_ "size" requested by the + * caller, with the caveat (in the code above) that "size" >= the + * max. size (max_size) ends up getting recorded as a call to + * max_size. + */ + stats[size].gets++; + stats[size].totalgets++; + stats[new_size].freefrags--; + SUNW_MEMUNLOCK; +#if defined(DEBUGGING_MEMCLUSTER) + return ((char *)e + sizeof *e); +#else + return (ret); +#endif +} + +/* + * This is a call from an external caller, + * so we want to count this as a user "put". + */ +void +__memput(void *mem, size_t size) { + __memput_record(mem, size, NULL, 0); +} + +void +__memput_record(void *mem, size_t size, const char *file, int line) { + size_t new_size = quantize(size); +#if defined (DEBUGGING_MEMCLUSTER) + memcluster_element *e; + memcluster_element *el; +#ifdef MEMCLUSTER_RECORD + memcluster_element *prev; +#endif + fence_t fp; + char *p; +#endif + + SUNW_MEMLOCK; + +#if !defined (MEMCLUSTER_RECORD) + UNUSED(file); + UNUSED(line); +#endif + + REQUIRE(freelists != NULL); + + if (size == 0) { + SUNW_MEMUNLOCK; + errno = EINVAL; + return; + } + +#if defined (DEBUGGING_MEMCLUSTER) + e = (memcluster_element *) ((char *)mem - sizeof *e); + INSIST(e->fencepost == FRONT_FENCEPOST); + INSIST(e->size == size); + p = (char *)e + sizeof *e + size; + memcpy(&fp, p, sizeof fp); + INSIST(fp == BACK_FENCEPOST); + INSIST(((int)mem % 4) == 0); +#ifdef MEMCLUSTER_RECORD + prev = NULL; + if (size == max_size || new_size >= max_size) + el = activelists[max_size]; + else + el = activelists[size]; + while (el != NULL && el != e) { + prev = el; + el = el->next; + } + INSIST(el != NULL); /* double free */ + if (prev == NULL) { + if (size == max_size || new_size >= max_size) + activelists[max_size] = el->next; + else + activelists[size] = el->next; + } else + prev->next = el->next; +#endif +#endif + + if (size == max_size || new_size >= max_size) { + /* memput() called on something beyond our upper limit */ +#if defined(DEBUGGING_MEMCLUSTER) + free(e); +#else + free(mem); +#endif + + INSIST(stats[max_size].gets != 0); + stats[max_size].gets--; + SUNW_MEMUNLOCK; + return; + } + + /* The free list uses the "rounded-up" size "new_size": */ +#if defined(DEBUGGING_MEMCLUSTER) + memset(mem, 0xa5, new_size - sizeof *e); /* catch write after free */ + e->size = 0; /* catch double memput() */ +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; +#endif +#ifdef MEMCLUSTER_ATEND + e->next = NULL; + el = freelists[new_size]; + while (el != NULL && el->next != NULL) + el = el->next; + if (el) + el->next = e; + else + freelists[new_size] = e; +#else + e->next = freelists[new_size]; + freelists[new_size] = (void *)e; +#endif +#else + ((memcluster_element *)mem)->next = freelists[new_size]; + freelists[new_size] = (memcluster_element *)mem; +#endif + + /* + * The stats[] uses the _actual_ "size" requested by the + * caller, with the caveat (in the code above) that "size" >= the + * max. size (max_size) ends up getting recorded as a call to + * max_size. + */ + INSIST(stats[size].gets != 0); + stats[size].gets--; + stats[new_size].freefrags++; + SUNW_MEMUNLOCK; +} + +void * +__memget_debug(size_t size, const char *file, int line) { + void *ptr; + ptr = __memget_record(size, file, line); + fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line, + (u_long)size, ptr); + return (ptr); +} + +void +__memput_debug(void *ptr, size_t size, const char *file, int line) { + fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, ptr, + (u_long)size); + __memput_record(ptr, size, file, line); +} + +/* + * Print the stats[] on the stream "out" with suitable formatting. + */ +void +memstats(FILE *out) { + size_t i; +#ifdef MEMCLUSTER_RECORD + memcluster_element *e; +#endif + + SUNW_MEMLOCK; + if (freelists == NULL) +SUNW_MEMLOCKBLOCK_BEGIN + SUNW_MEMUNLOCK; + return; +SUNW_MEMLOCKBLOCK_END + for (i = 1; i <= max_size; i++) { + const struct stats *s = &stats[i]; + + if (s->totalgets == 0 && s->gets == 0) + continue; + fprintf(out, "%s%5d: %11lu gets, %11lu rem", + (i == max_size) ? ">=" : " ", + i, s->totalgets, s->gets); + if (s->blocks != 0) + fprintf(out, " (%lu bl, %lu ff)", + s->blocks, s->freefrags); + fputc('\n', out); + } +#ifdef MEMCLUSTER_RECORD + fprintf(out, "Active Memory:\n"); + for (i = 1; i <= max_size; i++) { + if ((e = activelists[i]) != NULL) + while (e != NULL) { + fprintf(out, "%s:%d %p:%d\n", + e->file != NULL ? e->file : + "<UNKNOWN>", e->line, + (char *)e + sizeof *e, e->size); + e = e->next; + } + } +#endif + SUNW_MEMUNLOCK; +} + +int +memactive(void) { + size_t i; + + if (stats == NULL) + return (0); + for (i = 1; i <= max_size; i++) + if (stats[i].gets != 0) + return (1); + return (0); +} + +/* Private. */ + +/* + * Round up size to a multiple of sizeof(void *). This guarantees that a + * block is at least sizeof void *, and that we won't violate alignment + * restrictions, both of which are needed to make lists of blocks. + */ +static size_t +quantize(size_t size) { + int remainder; + /* + * If there is no remainder for the integer division of + * + * (rightsize/P_SIZE) + * + * then we already have a good size; if not, then we need + * to round up the result in order to get a size big + * enough to satisfy the request _and_ aligned on P_SIZE boundaries. + */ + remainder = size % P_SIZE; + if (remainder != 0) + size += P_SIZE - remainder; +#if defined(DEBUGGING_MEMCLUSTER) + return (size + SMALL_SIZE_LIMIT + sizeof (int)); +#else + return (size); +#endif +} + +#if defined(DEBUGGING_MEMCLUSTER) +static void +check(unsigned char *a, int value, size_t len) { + size_t i; + for (i = 0; i < len; i++) + INSIST(a[i] == value); +} +#endif diff --git a/usr/src/lib/libresolv2/common/isc/tree.c b/usr/src/lib/libresolv2/common/isc/tree.c new file mode 100644 index 0000000000..fea38085e0 --- /dev/null +++ b/usr/src/lib/libresolv2/common/isc/tree.c @@ -0,0 +1,543 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef LINT +static const char rcsid[] = "$Id: tree.c,v 8.10 2001/11/01 05:33:46 marka Exp $"; +#endif + +/* + * tree - balanced binary tree library + * + * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names] + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 23jun86 [added delete uar to add for replaced nodes] + * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224] + * vix 06feb86 [added tree_mung()] + * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221] + * vix 14dec85 [written] + */ + +/* + * This program text was created by Paul Vixie using examples from the book: + * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN + * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul + * Vixie's. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/*#define DEBUG "tree"*/ + +#include "port_before.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "port_after.h" + +#include <isc/memcluster.h> +#include <isc/tree.h> + +#ifdef DEBUG +static int debugDepth = 0; +static char *debugFuncs[256]; +# define ENTER(proc) { \ + debugFuncs[debugDepth] = proc; \ + fprintf(stderr, "ENTER(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + debugDepth++; \ + } +# define RET(value) { \ + debugDepth--; \ + fprintf(stderr, "RET(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return (value); \ + } +# define RETV { \ + debugDepth--; \ + fprintf(stderr, "RETV(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return; \ + } +# define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg); +#else +# define ENTER(proc) ; +# define RET(value) return (value); +# define RETV return; +# define MSG(msg) ; +#endif + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)()); +static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *); +static void del(tree **, int *, tree **, void (*)(), int *); +static void bal_L(tree **, int *); +static void bal_R(tree **, int *); + +void +tree_init(tree **ppr_tree) { + ENTER("tree_init") + *ppr_tree = NULL; + RETV +} + +tree_t +tree_srch(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), tree_t p_user) { + ENTER("tree_srch") + + if (*ppr_tree) { + int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data); + + if (i_comp > 0) + RET(tree_srch(&(**ppr_tree).right, + pfi_compare, + p_user)) + + if (i_comp < 0) + RET(tree_srch(&(**ppr_tree).left, + pfi_compare, + p_user)) + + /* not higher, not lower... this must be the one. + */ + RET((**ppr_tree).data) + } + + /* grounded. NOT found. + */ + RET(NULL) +} + +tree_t +tree_add(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE; + + ENTER("tree_add") + if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar)) + RET(NULL) + RET(p_user) +} + +int +tree_delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE, i_uar_called = FALSE; + + ENTER("tree_delete"); + RET(delete(ppr_p, pfi_compare, p_user, pfv_uar, + &i_balance, &i_uar_called)) +} + +int +tree_trav(tree **ppr_tree, int (*pfi_uar)(tree_t)) { + ENTER("tree_trav") + + if (!*ppr_tree) + RET(TRUE) + + if (!tree_trav(&(**ppr_tree).left, pfi_uar)) + RET(FALSE) + if (!(*pfi_uar)((**ppr_tree).data)) + RET(FALSE) + if (!tree_trav(&(**ppr_tree).right, pfi_uar)) + RET(FALSE) + RET(TRUE) +} + +void +tree_mung(tree **ppr_tree, void (*pfv_uar)(tree_t)) { + ENTER("tree_mung") + if (*ppr_tree) { + tree_mung(&(**ppr_tree).left, pfv_uar); + tree_mung(&(**ppr_tree).right, pfv_uar); + if (pfv_uar) + (*pfv_uar)((**ppr_tree).data); + memput(*ppr_tree, sizeof(tree)); + *ppr_tree = NULL; + } + RETV +} + +static tree * +sprout(tree **ppr, tree_t p_data, int *pi_balance, + int (*pfi_compare)(tree_t, tree_t), void (*pfv_delete)(tree_t)) +{ + tree *p1, *p2, *sub; + int cmp; + + ENTER("sprout") + + /* are we grounded? if so, add the node "here" and set the rebalance + * flag, then exit. + */ + if (!*ppr) { + MSG("grounded. adding new node, setting h=true") + *ppr = (tree *) memget(sizeof(tree)); + if (*ppr) { + (*ppr)->left = NULL; + (*ppr)->right = NULL; + (*ppr)->bal = 0; + (*ppr)->data = p_data; + *pi_balance = TRUE; + } +#ifdef ORIGINAL_ISC_CODE + RET(*ppr); +#else + RET(*ppr) +#endif + } + + /* compare the data using routine passed by caller. + */ + cmp = (*pfi_compare)(p_data, (*ppr)->data); + + /* if LESS, prepare to move to the left. + */ + if (cmp < 0) { + MSG("LESS. sprouting left.") + sub = sprout(&(*ppr)->left, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { /* left branch has grown */ + MSG("LESS: left branch has grown") + switch ((*ppr)->bal) { + case 1: + /* right branch WAS longer; bal is ok now */ + MSG("LESS: case 1.. bal restored implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + /* balance WAS okay; now left branch longer */ + MSG("LESS: case 0.. balnce bad but still ok") + (*ppr)->bal = -1; + break; + case -1: + /* left branch was already too long. rebal */ + MSG("LESS: case -1: rebalancing") + p1 = (*ppr)->left; + if (p1->bal == -1) { /* LL */ + MSG("LESS: single LL") + (*ppr)->left = p1->right; + p1->right = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /* double LR */ + MSG("LESS: double LR") + + p2 = p1->right; + p1->right = p2->left; + p2->left = p1; + + (*ppr)->left = p2->right; + p2->right = *ppr; + + if (p2->bal == -1) + (*ppr)->bal = 1; + else + (*ppr)->bal = 0; + + if (p2->bal == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* if MORE, prepare to move to the right. + */ + if (cmp > 0) { + MSG("MORE: sprouting to the right") + sub = sprout(&(*ppr)->right, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { + MSG("MORE: right branch has grown") + + switch ((*ppr)->bal) { + case -1: + MSG("MORE: balance was off, fixed implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + MSG("MORE: balance was okay, now off but ok") + (*ppr)->bal = 1; + break; + case 1: + MSG("MORE: balance was off, need to rebalance") + p1 = (*ppr)->right; + if (p1->bal == 1) { /* RR */ + MSG("MORE: single RR") + (*ppr)->right = p1->left; + p1->left = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /* double RL */ + MSG("MORE: double RL") + + p2 = p1->left; + p1->left = p2->right; + p2->right = p1; + + (*ppr)->right = p2->left; + p2->left = *ppr; + + if (p2->bal == 1) + (*ppr)->bal = -1; + else + (*ppr)->bal = 0; + + if (p2->bal == -1) + p1->bal = 1; + else + p1->bal = 0; + + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* not less, not more: this is the same key! replace... + */ + MSG("FOUND: Replacing data value") + *pi_balance = FALSE; + if (pfv_delete) + (*pfv_delete)((*ppr)->data); + (*ppr)->data = p_data; + RET(*ppr) +} + +static int +delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), tree_t p_user, + void (*pfv_uar)(tree_t), int *pi_balance, int *pi_uar_called) +{ + tree *pr_q; + int i_comp, i_ret; + + ENTER("delete") + + if (*ppr_p == NULL) { + MSG("key not in tree") + RET(FALSE) + } + + i_comp = (*pfi_compare)((*ppr_p)->data, p_user); + if (i_comp > 0) { + MSG("too high - scan left") + i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } else if (i_comp < 0) { + MSG("too low - scan right") + i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_R(ppr_p, pi_balance); + } else { + MSG("equal") + pr_q = *ppr_p; + if (pr_q->right == NULL) { + MSG("right subtree null") + *ppr_p = pr_q->left; + *pi_balance = TRUE; + } else if (pr_q->left == NULL) { + MSG("right subtree non-null, left subtree null") + *ppr_p = pr_q->right; + *pi_balance = TRUE; + } else { + MSG("neither subtree null") + del(&pr_q->left, pi_balance, &pr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } + if (!*pi_uar_called && pfv_uar) + (*pfv_uar)(pr_q->data); + /* Thanks to wuth@castrov.cuc.ab.ca for the following stmt. */ + memput(pr_q, sizeof(tree)); + i_ret = TRUE; + } + RET(i_ret) +} + +static void +del(tree **ppr_r, int *pi_balance, tree **ppr_q, + void (*pfv_uar)(tree_t), int *pi_uar_called) +{ + ENTER("del") + + if ((*ppr_r)->right != NULL) { + del(&(*ppr_r)->right, pi_balance, ppr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_R(ppr_r, pi_balance); + } else { + if (pfv_uar) + (*pfv_uar)((*ppr_q)->data); + *pi_uar_called = TRUE; + (*ppr_q)->data = (*ppr_r)->data; + *ppr_q = *ppr_r; + *ppr_r = (*ppr_r)->left; + *pi_balance = TRUE; + } + + RETV +} + +static void +bal_L(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_L") + MSG("left branch has shrunk") + + switch ((*ppr_p)->bal) { + case -1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = 1; + *pi_balance = FALSE; + break; + case 1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->right; + b1 = p1->bal; + if (b1 >= 0) { + MSG("single RR") + (*ppr_p)->right = p1->left; + p1->left = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = 1; + p1->bal = -1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double RL") + p2 = p1->left; + b2 = p2->bal; + p1->left = p2->right; + p2->right = p1; + (*ppr_p)->right = p2->left; + p2->left = *ppr_p; + if (b2 == 1) + (*ppr_p)->bal = -1; + else + (*ppr_p)->bal = 0; + if (b2 == -1) + p1->bal = 1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} + +static void +bal_R(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_R") + MSG("right branch has shrunk") + switch ((*ppr_p)->bal) { + case 1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = -1; + *pi_balance = FALSE; + break; + case -1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->left; + b1 = p1->bal; + if (b1 <= 0) { + MSG("single LL") + (*ppr_p)->left = p1->right; + p1->right = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = -1; + p1->bal = 1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double LR") + p2 = p1->right; + b2 = p2->bal; + p1->right = p2->left; + p2->left = p1; + (*ppr_p)->left = p2->right; + p2->right = *ppr_p; + if (b2 == -1) + (*ppr_p)->bal = 1; + else + (*ppr_p)->bal = 0; + if (b2 == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} diff --git a/usr/src/lib/libresolv2/common/llib-lresolv b/usr/src/lib/libresolv2/common/llib-lresolv new file mode 100644 index 0000000000..aedd06a0fa --- /dev/null +++ b/usr/src/lib/libresolv2/common/llib-lresolv @@ -0,0 +1,59 @@ +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +/* + * Copyright (c) 1997-1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/nameser.h> +#include <resolv.h> + +/* + * usr/src/lib/libresolv2 routines + */ + +int dn_skipname(const uchar_t *, const uchar_t *); +void fp_query(const u_char *, FILE *); +const uchar_t * p_cdname(const uchar_t *, const uchar_t *, FILE *); +const char * p_class(int); +void p_query(const u_char *); +const char * p_time(unsigned int); +const char * p_type(int); +void putlong(unsigned int, uchar_t *); +uint32_t _getlong(const u_char *); +uint16_t _getshort(const u_char *); +const char * hstrerror(int); +int res_init(void); +int res_mkquery(int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int); +int res_query(const char *, int, int, u_char *, int); +int res_querydomain(const char *, const char *, int, int, + u_char *, int); +int res_search(const char *, int, int, u_char *, int); +int res_send(const u_char *, int, u_char *, int); +int res_update(ns_updrec *); +int res_ninit(res_state); +void fp_resstat(const res_state, FILE *); +const char * res_hostalias(const res_state, const char *, char *, size_t); +int res_nquery(res_state, const char *, int, int, u_char *, int); +int res_nsearch(res_state, const char *, int, int, u_char *, int); +int res_nquerydomain(res_state, const char *, const char *, + int, int, u_char *, int); +int res_nmkquery(res_state, int, const char *, int, int, + const u_char *, int, const u_char *, + u_char *, int); +int res_nsend(res_state, const u_char *, int, u_char *, int); +int res_nmkupdate(res_state, ns_updrec *, u_char *, int); +void res_nclose(res_state); +int res_nsendsigned(res_state, const u_char *, int, ns_tsig_key *, + u_char *, int); +int dn_comp(const char *, u_char *, int, u_char **, u_char **); +int dn_expand(const u_char *, const u_char *, const u_char *, + char *, int); diff --git a/usr/src/lib/libresolv2/common/mapfile-vers b/usr/src/lib/libresolv2/common/mapfile-vers new file mode 100644 index 0000000000..e700b09635 --- /dev/null +++ b/usr/src/lib/libresolv2/common/mapfile-vers @@ -0,0 +1,15 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# Special mapfile to establish h_errno as a filter on libnsl. As a filtered +# symbol, this isn't visible to apptrace, and thus doesn't have to be defined +# from the specfiles. To ensure the symbol remains in .bss, with the correct +# size, its filtering capabilities are assigned here rather than via a specfile. + +SUNW_2.1 { + global: + h_errno = FILTER libnsl.so.1; +}; diff --git a/usr/src/lib/libresolv2/common/nameser/ns_date.c b/usr/src/lib/libresolv2/common/nameser/ns_date.c new file mode 100644 index 0000000000..b089063c71 --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_date.c @@ -0,0 +1,135 @@ +/* + * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_date.c,v 1.3 2001/05/29 05:49:34 marka Exp $"; +#endif + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Import. */ + +#include "port_before.h" + +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int datepart(const char *, int, int, int, int *); + +/* Public. */ + +/* Convert a date in ASCII into the number of seconds since + 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all + digits required, no spaces allowed. */ + +u_int32_t +ns_datetosecs(const char *cp, int *errp) { + struct tm time; + u_int32_t result; + int mdays, i; + static const int days_per_month[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (strlen(cp) != 14) { + *errp = 1; + return (0); + } + *errp = 0; + + memset(&time, 0, sizeof time); + time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; + time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; + time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); + time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); + time.tm_min = datepart(cp + 10, 2, 00, 59, errp); + time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); + if (*errp) /* Any parse errors? */ + return (0); + + /* + * OK, now because timegm() is not available in all environments, + * we will do it by hand. Roll up sleeves, curse the gods, begin! + */ + +#define SECS_PER_DAY ((u_int32_t)24*60*60) +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + + result = time.tm_sec; /* Seconds */ + result += time.tm_min * 60; /* Minutes */ + result += time.tm_hour * (60*60); /* Hours */ + result += (time.tm_mday - 1) * SECS_PER_DAY; /* Days */ + + /* Months are trickier. Look without leaping, then leap */ + mdays = 0; + for (i = 0; i < time.tm_mon; i++) + mdays += days_per_month[i]; + result += mdays * SECS_PER_DAY; /* Months */ + if (time.tm_mon > 1 && isleap(1900+time.tm_year)) + result += SECS_PER_DAY; /* Add leapday for this year */ + + /* First figure years without leapdays, then add them in. */ + /* The loop is slow, FIXME, but simple and accurate. */ + result += (time.tm_year - 70) * (SECS_PER_DAY*365); /* Years */ + for (i = 70; i < time.tm_year; i++) + if (isleap(1900+i)) + result += SECS_PER_DAY; /* Add leapday for prev year */ + + return (result); +} + +/* Private. */ + +/* + * Parse part of a date. Set error flag if any error. + * Don't reset the flag if there is no error. + */ +static int +datepart(const char *buf, int size, int min, int max, int *errp) { + int result = 0; + int i; + + for (i = 0; i < size; i++) { + if (!isdigit((unsigned char)(buf[i]))) + *errp = 1; + result = (result * 10) + buf[i] - '0'; + } + if (result < min) + *errp = 1; + if (result > max) + *errp = 1; + return (result); +} diff --git a/usr/src/lib/libresolv2/common/nameser/ns_name.c b/usr/src/lib/libresolv2/common/nameser/ns_name.c new file mode 100644 index 0000000000..fbe2c5ccc7 --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_name.c @@ -0,0 +1,970 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef lint +static const char rcsid[] = "$Id: ns_name.c,v 8.20 2003/04/03 06:00:07 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <limits.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */ +#define DNS_LABELTYPE_BITSTRING 0x41 + +/* Data. */ + +static const char digits[] = "0123456789"; + +static const char digitvalue[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ +}; + +/* Forward. */ + +static int special(int); +static int printable(int); +static int dn_find(const u_char *, const u_char *, + const u_char * const *, + const u_char * const *); +static int encode_bitsring(const char **, const char *, + char **, char **, const char *); +static int labellen(const u_char *); +static int decode_bitstring(const char **, char *, const char *); + +/* Public. */ + +/* + * ns_name_ntop(src, dst, dstsiz) + * Convert an encoded domain name to printable ascii as per RFC1035. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * The root is returned as "." + * All other domains are returned in non absolute form + */ +int +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) +{ + const u_char *cp; + char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + if (dn != dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; /* XXX */ + return(-1); + } + if (dn + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { + int m; + + if (n != DNS_LABELTYPE_BITSTRING) { + /* XXX: labellen should reject this case */ + errno = EINVAL; + return(-1); + } + if ((m = decode_bitstring((const char **)&cp, dn, eom)) < 0) + { + errno = EMSGSIZE; + return(-1); + } + dn += m; + continue; + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (special(c)) { + if (dn + 1 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = (char)c; + } else if (!printable(c)) { + if (dn + 3 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = digits[c / 100]; + *dn++ = digits[(c % 100) / 10]; + *dn++ = digits[c % 10]; + } else { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = (char)c; + } + } + } + if (dn == dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\0'; + return (dn - dst); +} + +/* + * ns_name_pton(src, dst, dstsiz) + * Convert a ascii string into an encoded domain name as per RFC1035. + * return: + * -1 if it fails + * 1 if string was fully qualified + * 0 is string was not fully qualified + * notes: + * Enforces label and domain length limits. + */ + +int +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) +{ + u_char *label, *bp, *eom; + int c, n, escaped, e = 0; + char *cp; + + escaped = 0; + bp = dst; + eom = dst + dstsiz; + label = bp++; + + while ((c = *src++) != 0) { + if (escaped) { + if (c == '[') { /* start a bit string label */ + if ((cp = strchr(src, ']')) == NULL) { + errno = EINVAL; /* ??? */ + return(-1); + } + if ((e = encode_bitsring(&src, + cp + 2, + (char **)&label, + (char **)&bp, + (const char *)eom)) + != 0) { + errno = e; + return(-1); + } + escaped = 0; + label = bp++; + if ((c = *src++) == 0) + goto done; + else if (c != '.') { + errno = EINVAL; + return(-1); + } + continue; + } + else if ((cp = strchr(digits, c)) != NULL) { + n = (cp - digits) * 100; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits) * 10; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits); + if (n > 255) { + errno = EMSGSIZE; + return (-1); + } + c = n; + } + escaped = 0; + } else if (c == '\\') { + escaped = 1; + continue; + } else if (c == '.') { + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ + errno = EMSGSIZE; + return (-1); + } + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + /* Fully qualified ? */ + if (*src == '\0') { + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = '\0'; + } + if ((bp - dst) > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + return (1); + } + if (c == 0 || *src == '.') { + errno = EMSGSIZE; + return (-1); + } + label = bp++; + continue; + } + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = (u_char)c; + } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ + errno = EMSGSIZE; + return (-1); + } + done: + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = 0; + } + if ((bp - dst) > MAXCDNAME) { /* src too big */ + errno = EMSGSIZE; + return (-1); + } + return (0); +} + +/* + * ns_name_ntol(src, dst, dstsiz) + * Convert a network strings labels into all lowercase. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * Enforces label and domain length limits. + */ + +int +ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) +{ + const u_char *cp; + u_char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + *dn++ = n; + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; + return (-1); + } + if (dn + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (isupper(c)) + *dn++ = tolower(c); + else + *dn++ = c; + } + } + *dn++ = '\0'; + return (dn - dst); +} + +/* + * ns_name_unpack(msg, eom, src, dst, dstsiz) + * Unpack a domain name from a message, source may be compressed. + * return: + * -1 if it fails, or consumed octets if it succeeds. + */ +int +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz) +{ + const u_char *srcp, *dstlim; + u_char *dstp; + int n, len, checked, l; + + len = -1; + checked = 0; + dstp = dst; + srcp = src; + dstlim = dst + dstsiz; + if (srcp < msg || srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: + case NS_TYPE_ELT: + /* Limit checks. */ + if ((l = labellen(srcp - 1)) < 0) { + errno = EMSGSIZE; + return(-1); + } + if (dstp + l + 1 >= dstlim || srcp + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + checked += l + 1; + *dstp++ = n; + memcpy(dstp, srcp, l); + dstp += l; + srcp += l; + break; + + case NS_CMPRSFLGS: + if (srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + if (len < 0) + len = srcp - src + 1; + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); + if (srcp < msg || srcp >= eom) { /* Out of range. */ + errno = EMSGSIZE; + 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 >= eom - msg) { + errno = EMSGSIZE; + return (-1); + } + break; + + default: + errno = EMSGSIZE; + return (-1); /* flag error */ + } + } + *dstp = '\0'; + if (len < 0) + len = srcp - src; + return (len); +} + +/* + * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) + * Pack domain name 'domain' into 'comp_dn'. + * return: + * Size of the compressed name, or -1. + * notes: + * 'dnptrs' is an array of pointers to previous compressed names. + * dnptrs[0] is a pointer to the beginning of the message. The array + * ends with NULL. + * 'lastdnptr' is a pointer to the end of the array pointed to + * by 'dnptrs'. + * Side effects: + * The list of pointers in dnptrs is updated 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. + */ +int +ns_name_pack(const u_char *src, u_char *dst, int dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char *dstp; + const u_char **cpp, **lpp, *eob, *msg; + const u_char *srcp; + int n, l, first = 1; + + srcp = src; + dstp = dst; + eob = dstp + dstsiz; + lpp = cpp = NULL; + if (dnptrs != NULL) { + if ((msg = *dnptrs++) != NULL) { + for (cpp = dnptrs; *cpp != NULL; cpp++) + (void)NULL; + lpp = cpp; /* end of list to search */ + } + } else + msg = NULL; + + /* make sure the domain we are about to add is legal */ + l = 0; + do { + int l0; + + n = *srcp; + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + errno = EMSGSIZE; + return (-1); + } + if ((l0 = labellen(srcp)) < 0) { + errno = EINVAL; + return(-1); + } + l += l0 + 1; + if (l > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + srcp += l0 + 1; + } while (n != 0); + + /* from here on we need to reset compression pointer array on error */ + srcp = src; + do { + /* Look to see if we can use pointers. */ + n = *srcp; + if (n != 0 && msg != NULL) { + l = dn_find(srcp, msg, (const u_char * const *)dnptrs, + (const u_char * const *)lpp); + if (l >= 0) { + if (dstp + 1 >= eob) { + goto cleanup; + } + *dstp++ = (l >> 8) | NS_CMPRSFLGS; + *dstp++ = l % 256; + return (dstp - dst); + } + /* Not found, save it. */ + if (lastdnptr != NULL && cpp < lastdnptr - 1 && + (dstp - msg) < 0x4000 && first) { + *cpp++ = dstp; + *cpp = NULL; + first = 0; + } + } + /* copy label to buffer */ + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Should not happen. */ + goto cleanup; + } + n = labellen(srcp); + if (dstp + 1 + n >= eob) { + goto cleanup; + } + memcpy(dstp, srcp, n + 1); + srcp += n + 1; + dstp += n + 1; + } while (n != 0); + + if (dstp > eob) { +cleanup: + if (msg != NULL) + *lpp = NULL; + errno = EMSGSIZE; + return (-1); + } + return (dstp - dst); +} + +/* + * ns_name_uncompress(msg, eom, src, dst, dstsiz) + * Expand compressed domain name to presentation format. + * return: + * Number of bytes read out of `src', or -1 (with errno set). + * note: + * Root domain returns as "." not "". + */ +int +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, size_t dstsiz) +{ + u_char tmp[NS_MAXCDNAME]; + int n; + + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) + return (-1); + if (ns_name_ntop(tmp, dst, dstsiz) == -1) + return (-1); + return (n); +} + +/* + * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) + * Compress a domain name into wire format, using compression pointers. + * return: + * Number of bytes consumed in `dst' or -1 (with errno set). + * notes: + * 'dnptrs' is an array of pointers to previous compressed names. + * dnptrs[0] is a pointer to the beginning of the message. + * The list ends with NULL. 'lastdnptr' is a pointer to the end of the + * array 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. + */ +int +ns_name_compress(const char *src, u_char *dst, size_t dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char tmp[NS_MAXCDNAME]; + + if (ns_name_pton(src, tmp, sizeof tmp) == -1) + return (-1); + return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); +} + +/* + * Reset dnptrs so that there are no active references to pointers at or + * after src. + */ +void +ns_name_rollback(const u_char *src, const u_char **dnptrs, + const u_char **lastdnptr) +{ + while (dnptrs < lastdnptr && *dnptrs != NULL) { + if (*dnptrs >= src) { + *dnptrs = NULL; + break; + } + dnptrs++; + } +} + +/* + * ns_name_skip(ptrptr, eom) + * Advance *ptrptr to skip over the compressed name it points at. + * return: + * 0 on success, -1 (with errno set) on failure. + */ +int +ns_name_skip(const u_char **ptrptr, const u_char *eom) +{ + const u_char *cp; + u_int n; + int l; + + cp = *ptrptr; + while (cp < eom && (n = *cp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: /* normal case, n == len */ + cp += n; + continue; + case NS_TYPE_ELT: /* EDNS0 extended label */ + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; /* XXX */ + return(-1); + } + cp += l; + continue; + case NS_CMPRSFLGS: /* indirection */ + cp++; + break; + default: /* illegal type */ + errno = EMSGSIZE; + return (-1); + } + break; + } + if (cp > eom) { + errno = EMSGSIZE; + return (-1); + } + *ptrptr = cp; + return (0); +} + +/* Private. */ + +/* + * special(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this characted special ("in need of quoting") ? + * return: + * boolean. + */ +static int +special(int ch) { + switch (ch) { + case 0x22: /* '"' */ + case 0x2E: /* '.' */ + case 0x3B: /* ';' */ + case 0x5C: /* '\\' */ + case 0x28: /* '(' */ + case 0x29: /* ')' */ + /* Special modifiers in zone files. */ + case 0x40: /* '@' */ + case 0x24: /* '$' */ + return (1); + default: + return (0); + } +} + +/* + * printable(ch) + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? + * return: + * boolean. + */ +static int +printable(int ch) { + return (ch > 0x20 && ch < 0x7f); +} + +/* + * Thinking in noninternationalized USASCII (per the DNS spec), + * convert this character to lower case if it's upper case. + */ +static int +mklower(int ch) { + if (ch >= 0x41 && ch <= 0x5A) + return (ch + 0x20); + return (ch); +} + +/* + * dn_find(domain, msg, dnptrs, lastdnptr) + * Search for the counted-label name in an array of compressed names. + * return: + * offset from msg if found, or -1. + * notes: + * dnptrs is the pointer to the first name on the list, + * not the pointer to the start of the message. + */ +static int +dn_find(const u_char *domain, const u_char *msg, + const u_char * const *dnptrs, + const u_char * const *lastdnptr) +{ + const u_char *dn, *cp, *sp; + const u_char * const *cpp; + u_int n; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + sp = *cpp; + /* + * terminate search on: + * root label + * compression pointer + * unusable offset + */ + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && + (sp - msg) < 0x4000) { + dn = domain; + cp = sp; + while ((n = *cp++) != 0) { + /* + * check for indirection + */ + switch (n & NS_CMPRSFLGS) { + case 0: /* normal case, n == len */ + n = labellen(cp - 1); /* XXX */ + + if (n != *dn++) + goto next; + + for ((void)NULL; n > 0; n--) + if (mklower(*dn++) != + mklower(*cp++)) + goto next; + /* Is next root for both ? */ + if (*dn == '\0' && *cp == '\0') + return (sp - msg); + if (*dn) + continue; + goto next; + case NS_CMPRSFLGS: /* indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /* illegal type */ + errno = EMSGSIZE; + return (-1); + } + } + next: ; + sp += *sp + 1; + } + } + errno = ENOENT; + return (-1); +} + +static int +decode_bitstring(const char **cpp, char *dn, const char *eom) +{ + const char *cp = *cpp; + char *beg = dn, tc; + int b, blen, plen, i; + + if ((blen = (*cp & 0xff)) == 0) + blen = 256; + plen = (blen + 3) / 4; + plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); + if (dn + plen >= eom) + return(-1); + + cp++; + i = SPRINTF((dn, "\\[x")); + if (i < 0) + return (-1); + dn += i; + for (b = blen; b > 7; b -= 8, cp++) { + i = SPRINTF((dn, "%02x", *cp & 0xff)); + if (i < 0) + return (-1); + dn += i; + } + if (b > 4) { + tc = *cp++; + i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b)))); + if (i < 0) + return (-1); + dn += i; + } else if (b > 0) { + tc = *cp++; + i = SPRINTF((dn, "%1x", + ((tc >> 4) & 0x0f) & (0x0f << (4 - b)))); + if (i < 0) + return (-1); + dn += i; + } + i = SPRINTF((dn, "/%d]", blen)); + if (i < 0) + return (-1); + dn += i; + + *cpp = cp; + return(dn - beg); +} + +static int +encode_bitsring(const char **bp, const char *end, char **labelp, + char ** dst, const char *eom) +{ + int afterslash = 0; + const char *cp = *bp; + char *tp, c; + const char *beg_blen; + char *end_blen = NULL; + int value = 0, count = 0, tbcount = 0, blen = 0; + + beg_blen = end_blen = NULL; + + /* a bitstring must contain at least 2 characters */ + if (end - cp < 2) + return(EINVAL); + + /* XXX: currently, only hex strings are supported */ + if (*cp++ != 'x') + return(EINVAL); + if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */ + return(EINVAL); + + for (tp = *dst + 1; cp < end && tp < eom; cp++) { + switch((c = *cp)) { + case ']': /* end of the bitstring */ + if (afterslash) { + if (beg_blen == NULL) + return(EINVAL); + blen = (int)strtol(beg_blen, &end_blen, 10); + if (*end_blen != ']') + return(EINVAL); + } + if (count) + *tp++ = ((value << 4) & 0xff); + cp++; /* skip ']' */ + goto done; + case '/': + afterslash = 1; + break; + default: + if (afterslash) { + if (!isdigit(c&0xff)) + return(EINVAL); + if (beg_blen == NULL) { + + if (c == '0') { + /* blen never begings with 0 */ + return(EINVAL); + } + beg_blen = cp; + } + } else { + if (!isxdigit(c&0xff)) + return(EINVAL); + value <<= 4; + value += digitvalue[(int)c]; + count += 4; + tbcount += 4; + if (tbcount > 256) + return(EINVAL); + if (count == 8) { + *tp++ = value; + count = 0; + } + } + break; + } + } + done: + if (cp >= end || tp >= eom) + return(EMSGSIZE); + + /* + * bit length validation: + * If a <length> is present, the number of digits in the <bit-data> + * MUST be just sufficient to contain the number of bits specified + * by the <length>. If there are insignificant bits in a final + * hexadecimal or octal digit, they MUST be zero. + * RFC 2673, Section 3.2. + */ + if (blen > 0) { + int traillen; + + if (((blen + 3) & ~3) != tbcount) + return(EINVAL); + traillen = tbcount - blen; /* between 0 and 3 */ + if (((value << (8 - traillen)) & 0xff) != 0) + return(EINVAL); + } + else + blen = tbcount; + if (blen == 256) + blen = 0; + + /* encode the type and the significant bit fields */ + **labelp = DNS_LABELTYPE_BITSTRING; + **dst = blen; + + *bp = cp; + *dst = tp; + + return(0); +} + +static int +labellen(const u_char *lp) +{ + int bitlen; + u_char l = *lp; + + if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* should be avoided by the caller */ + return(-1); + } + + if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { + if (l == DNS_LABELTYPE_BITSTRING) { + if ((bitlen = *(lp + 1)) == 0) + bitlen = 256; + return((bitlen + 7 ) / 8 + 1); + } + return(-1); /* unknwon ELT */ + } + return(l); +} diff --git a/usr/src/lib/libresolv2/common/nameser/ns_netint.c b/usr/src/lib/libresolv2/common/nameser/ns_netint.c new file mode 100644 index 0000000000..e753ce9809 --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_netint.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef lint +static const char rcsid[] = "$Id: ns_netint.c,v 8.4 1999/10/13 16:39:35 vixie Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <arpa/nameser.h> + +#include "port_after.h" + +/* Public. */ + +u_int +ns_get16(const u_char *src) { + u_int dst; + + NS_GET16(dst, src); + return (dst); +} + +u_long +ns_get32(const u_char *src) { + u_long dst; + + NS_GET32(dst, src); + return (dst); +} + +void +ns_put16(u_int src, u_char *dst) { + NS_PUT16(src, dst); +} + +void +ns_put32(u_long src, u_char *dst) { + NS_PUT32(src, dst); +} diff --git a/usr/src/lib/libresolv2/common/nameser/ns_parse.c b/usr/src/lib/libresolv2/common/nameser/ns_parse.c new file mode 100644 index 0000000000..65476deeb2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_parse.c @@ -0,0 +1,214 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef lint +static const char rcsid[] = "$Id: ns_parse.c,v 8.18 2003/04/03 06:10:10 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> + +#include "port_after.h" + +/* Forward. */ + +static void setsection(ns_msg *msg, ns_sect sect); + +/* Macros. */ + +#ifdef ORIGINAL_ISC_CODE +#define RETERR(err) do { errno = (err); return (-1); } while (0) +#else +#define RETERR(err) { errno = (err); return (-1); } +#endif + +/* Public. */ + +/* These need to be in the same order as the nres.h:ns_flag enum. */ +struct _ns_flagdata _ns_flagdata[16] = { + { 0x8000, 15 }, /* qr. */ + { 0x7800, 11 }, /* opcode. */ + { 0x0400, 10 }, /* aa. */ + { 0x0200, 9 }, /* tc. */ + { 0x0100, 8 }, /* rd. */ + { 0x0080, 7 }, /* ra. */ + { 0x0040, 6 }, /* z. */ + { 0x0020, 5 }, /* ad. */ + { 0x0010, 4 }, /* cd. */ + { 0x000f, 0 }, /* rcode. */ + { 0x0000, 0 }, /* expansion (1/6). */ + { 0x0000, 0 }, /* expansion (2/6). */ + { 0x0000, 0 }, /* expansion (3/6). */ + { 0x0000, 0 }, /* expansion (4/6). */ + { 0x0000, 0 }, /* expansion (5/6). */ + { 0x0000, 0 }, /* expansion (6/6). */ +}; + +int ns_msg_getflag(ns_msg handle, int flag) { + return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift); +} + +int +ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { + const u_char *optr = ptr; + + for ((void)NULL; count > 0; count--) { + int b, rdlength; + + b = dn_skipname(ptr, eom); + if (b < 0) + RETERR(EMSGSIZE); + ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + if (section != ns_s_qd) { + if (ptr + NS_INT32SZ + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + ptr += NS_INT32SZ/*TTL*/; + NS_GET16(rdlength, ptr); + ptr += rdlength/*RData*/; + } + } + if (ptr > eom) + RETERR(EMSGSIZE); + return (ptr - optr); +} + +int +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { + const u_char *eom = msg + msglen; + int i; + + memset(handle, 0x5e, sizeof *handle); + handle->_msg = msg; + handle->_eom = eom; + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_id, msg); + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_flags, msg); + for (i = 0; i < ns_s_max; i++) { + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_counts[i], msg); + } + for (i = 0; i < ns_s_max; i++) + if (handle->_counts[i] == 0) + handle->_sections[i] = NULL; + else { + int b = ns_skiprr(msg, eom, (ns_sect)i, + handle->_counts[i]); + + if (b < 0) + return (-1); + handle->_sections[i] = msg; + msg += b; + } + if (msg != eom) + RETERR(EMSGSIZE); + setsection(handle, ns_s_max); + return (0); +} + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { + int b; + int tmp; + + /* Make section right. */ + if ((tmp = section) < 0 || section >= ns_s_max) + RETERR(ENODEV); + if (section != handle->_sect) + setsection(handle, section); + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) + RETERR(ENODEV); + if (rrnum < handle->_rrnum) + setsection(handle, section); + if (rrnum > handle->_rrnum) { + b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return (-1); + handle->_msg_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_msg_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return (-1); + handle->_msg_ptr += b; + if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET16(rr->type, handle->_msg_ptr); + NS_GET16(rr->rr_class, handle->_msg_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET32(rr->ttl, handle->_msg_ptr); + NS_GET16(rr->rdlength, handle->_msg_ptr); + if (handle->_msg_ptr + rr->rdlength > handle->_eom) + RETERR(EMSGSIZE); + rr->rdata = handle->_msg_ptr; + handle->_msg_ptr += rr->rdlength; + } + if (++handle->_rrnum > handle->_counts[(int)section]) + setsection(handle, (ns_sect)((int)section + 1)); + + /* All done. */ + return (0); +} + +/* Private. */ + +static void +setsection(ns_msg *msg, ns_sect sect) { + msg->_sect = sect; + if (sect == ns_s_max) { + msg->_rrnum = -1; + msg->_msg_ptr = NULL; + } else { + msg->_rrnum = 0; + msg->_msg_ptr = msg->_sections[(int)sect]; + } +} diff --git a/usr/src/lib/libresolv2/common/nameser/ns_print.c b/usr/src/lib/libresolv2/common/nameser/ns_print.c new file mode 100644 index 0000000000..ced16b0828 --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_print.c @@ -0,0 +1,913 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef lint +static const char rcsid[] = "$Id: ns_print.c,v 8.26 2003/02/24 23:56:35 vixie Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <isc/assertions.h> +#include <isc/dst.h> +#include <errno.h> +#include <resolv.h> +#include <string.h> +#include <ctype.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static size_t prune_origin(const char *name, const char *origin); +static int charstr(const u_char *rdata, const u_char *edata, + char **buf, size_t *buflen); +static int addname(const u_char *msg, size_t msglen, + const u_char **p, const char *origin, + char **buf, size_t *buflen); +static void addlen(size_t len, char **buf, size_t *buflen); +static int addstr(const char *src, size_t len, + char **buf, size_t *buflen); +static int addtab(size_t len, size_t target, int spaced, + char **buf, size_t *buflen); + +#ifdef ORIGINAL_ISC_CODE +#else +/* Proto. */ + +u_int16_t dst_s_dns_key_id(const u_char *, const int); +#endif + +/* Macros. */ + +#define T(x) \ + do { \ + if ((x) < 0) \ + return (-1); \ + } while (0) + +/* Public. */ + +/* + * int + * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) + * Convert an RR to presentation format. + * return: + * Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrr(const ns_msg *handle, const ns_rr *rr, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + int n; + + n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), + ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), + ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), + name_ctx, origin, buf, buflen); + return (n); +} + +/* + * int + * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, + * name_ctx, origin, buf, buflen) + * Convert the fields of an RR into presentation format. + * return: + * Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrrf(const u_char *msg, size_t msglen, + const char *name, ns_class class, ns_type type, + u_long ttl, const u_char *rdata, size_t rdlen, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + const char *obuf = buf; + const u_char *edata = rdata + rdlen; + int spaced = 0; + + const char *comment; + char tmp[100]; + int len, x; + + /* + * Owner. + */ + if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { + T(addstr("\t\t\t", 3, &buf, &buflen)); + } else { + len = prune_origin(name, origin); + if (*name == '\0') { + goto root; + } else if (len == 0) { + T(addstr("@\t\t\t", 4, &buf, &buflen)); + } else { + T(addstr(name, len, &buf, &buflen)); + /* Origin not used or not root, and no trailing dot? */ + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + name[len] == '\0')) && name[len - 1] != '.') { + root: + T(addstr(".", 1, &buf, &buflen)); + len++; + } + T(spaced = addtab(len, 24, spaced, &buf, &buflen)); + } + } + + /* + * TTL, Class, Type. + */ + T(x = ns_format_ttl(ttl, buf, buflen)); + addlen(x, &buf, &buflen); + len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); + T(addstr(tmp, len, &buf, &buflen)); + if (rdlen == 0) + return (buf - obuf); + T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); + + /* + * RData. + */ + switch (type) { + case ns_t_a: + if (rdlen != NS_INADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + case ns_t_dname: + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + + case ns_t_hinfo: + case ns_t_isdn: + /* First word. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + + /* Second word, optional in ISDN records. */ + if (type == ns_t_isdn && rdata == edata) + break; + + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_soa: { + u_long t; + + /* Server name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Administrator name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" (\n", 3, &buf, &buflen)); + spaced = 0; + + if ((edata - rdata) != 5*NS_INT32SZ) + goto formerr; + + /* Serial number. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + len = SPRINTF((tmp, "%lu", t)); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; serial\n", 9, &buf, &buflen)); + spaced = 0; + + /* Refresh interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; refresh\n", 10, &buf, &buflen)); + spaced = 0; + + /* Retry interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; retry\n", 8, &buf, &buflen)); + spaced = 0; + + /* Expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; expiry\n", 9, &buf, &buflen)); + spaced = 0; + + /* Minimum TTL. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(addstr(" )", 2, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; minimum\n", 10, &buf, &buflen)); + + break; + } + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: { + u_int t; + + if (rdlen < NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Target. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_px: { + u_int t; + + if (rdlen < NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_x25: + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_txt: + while (rdata < edata) { + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + if (rdata < edata) + T(addstr(" ", 1, &buf, &buflen)); + } + break; + + case ns_t_nsap: { + char t[2+255*3]; + + (void) inet_nsap_ntoa(rdlen, rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_aaaa: + if (rdlen != NS_IN6ADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET6, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_loc: { + char t[255]; + + /* XXX protocol format checking? */ + (void) loc_ntoa(rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_naptr: { + u_int order, preference; + char t[50]; + + if (rdlen < 2*NS_INT16SZ) + goto formerr; + + /* Order, Precedence. */ + order = ns_get16(rdata); rdata += NS_INT16SZ; + preference = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u ", order, preference)); + T(addstr(t, len, &buf, &buflen)); + + /* Flags. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Service. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Regexp. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len < 0) + return (-1); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_srv: { + u_int priority, weight, port; + char t[50]; + + if (rdlen < NS_INT16SZ*3) + goto formerr; + + /* Priority, Weight, Port. */ + priority = ns_get16(rdata); rdata += NS_INT16SZ; + weight = ns_get16(rdata); rdata += NS_INT16SZ; + port = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u %u ", priority, weight, port)); + T(addstr(t, len, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_minfo: + case ns_t_rp: + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + + case ns_t_wks: { + int n, lcnt; + + if (rdlen < NS_INT32SZ + 1) + goto formerr; + + /* Address. */ + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += NS_INADDRSZ; + + /* Protocol. */ + len = SPRINTF((tmp, " %u ( ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata += NS_INT8SZ; + + /* Bit map. */ + n = 0; + lcnt = 0; + while (rdata < edata) { + u_int c = *rdata++; + do { + if (c & 0200) { + if (lcnt == 0) { + T(addstr("\n\t\t\t\t", 5, + &buf, &buflen)); + lcnt = 10; + spaced = 0; + } + len = SPRINTF((tmp, "%d ", n)); + T(addstr(tmp, len, &buf, &buflen)); + lcnt--; + } + c <<= 1; + } while (++n & 07); + } + T(addstr(")", 1, &buf, &buflen)); + + break; + } + + case ns_t_key: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int keyflags, protocol, algorithm, key_id; + const char *leader; + int n; + + if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) + goto formerr; + + /* Key flags, Protocol, Algorithm. */ + key_id = dst_s_dns_key_id(rdata, edata-rdata); + keyflags = ns_get16(rdata); rdata += NS_INT16SZ; + protocol = *rdata++; + algorithm = *rdata++; + len = SPRINTF((tmp, "0x%04x %u %u", + keyflags, protocol, algorithm)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Public key data. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len < 0) + goto formerr; + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + n = SPRINTF((tmp, " ; key_tag= %u", key_id)); + T(addstr(tmp, n, &buf, &buflen)); + + break; + } + + case ns_t_sig: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int type, algorithm, labels, footprint; + const char *leader; + u_long t; + int n; + + if (rdlen < 22) + goto formerr; + + /* Type covered, Algorithm, Label count, Original TTL. */ + type = ns_get16(rdata); rdata += NS_INT16SZ; + algorithm = *rdata++; + labels = *rdata++; + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s %d %d %lu ", + p_type(type), algorithm, labels, t)); + T(addstr(tmp, len, &buf, &buflen)); + if (labels > (u_int)dn_count_labels(name)) + goto formerr; + + /* Signature expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Time signed. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signature Footprint. */ + footprint = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", footprint)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signer's name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Signature. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + if (len < 0) + goto formerr; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + break; + } + + case ns_t_nxt: { + int n, c; + + /* Next domain name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Type bit map. */ + n = edata - rdata; + for (c = 0; c < n*8; c++) + if (NS_NXT_BIT_ISSET(c, rdata)) { + len = SPRINTF((tmp, " %s", p_type(c))); + T(addstr(tmp, len, &buf, &buflen)); + } + break; + } + + case ns_t_cert: { + u_int c_type, key_tag, alg; + int n; + unsigned int siz; + char base64_cert[8192], tmp[40]; + const char *leader; + + c_type = ns_get16(rdata); rdata += NS_INT16SZ; + key_tag = ns_get16(rdata); rdata += NS_INT16SZ; + alg = (u_int) *rdata++; + + len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); + T(addstr(tmp, len, &buf, &buflen)); + siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ + if (siz > sizeof(base64_cert) * 3/4) { + const char *str = "record too long to print"; + T(addstr(str, strlen(str), &buf, &buflen)); + } + else { + len = b64_ntop(rdata, edata-rdata, base64_cert, siz); + + if (len < 0) + goto formerr; + else if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } + else + leader = " "; + + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), + &buf, &buflen)); + T(addstr(base64_cert + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + } + break; + } + + case ns_t_tkey: { + /* KJD - need to complete this */ + u_long t; + int mode, err, keysize; + + /* Algorithm name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Inception. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Experation. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Mode , Error, Key Size. */ + /* Priority, Weight, Port. */ + mode = ns_get16(rdata); rdata += NS_INT16SZ; + err = ns_get16(rdata); rdata += NS_INT16SZ; + keysize = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); + T(addstr(tmp, len, &buf, &buflen)); + + /* need to dump key, print otherdata length & other data */ + break; + } + + case ns_t_tsig: { + /* BEW - need to complete this */ + int n; + + T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + rdata += 8; /* time */ + n = ns_get16(rdata); rdata += INT16SZ; + rdata += n; /* sig */ + n = ns_get16(rdata); rdata += INT16SZ; /* original id */ + sprintf(buf, "%d", ns_get16(rdata)); + rdata += INT16SZ; + addlen(strlen(buf), &buf, &buflen); + break; + } + + case ns_t_a6: { + struct in6_addr a; + int pbyte, pbit; + + /* prefix length */ + if (rdlen == 0) goto formerr; + len = SPRINTF((tmp, "%d ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + pbit = *rdata; + if (pbit > 128) goto formerr; + pbyte = (pbit & ~7) / 8; + rdata++; + + /* address suffix: provided only when prefix len != 128 */ + if (pbit < 128) { + if (rdata + pbyte >= edata) goto formerr; + memset(&a, 0, sizeof(a)); + memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); + (void) inet_ntop(AF_INET6, &a, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += sizeof(a) - pbyte; + } + + /* prefix name: provided only when prefix len > 0 */ + if (pbit == 0) + break; + if (rdata >= edata) goto formerr; + T(addstr(" ", 1, &buf, &buflen)); + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_opt: { + len = SPRINTF((tmp, "%u bytes", class)); + T(addstr(tmp, len, &buf, &buflen)); + break; + } + + default: + comment = "unknown RR type"; + goto hexify; + } + return (buf - obuf); + formerr: + comment = "RR format error"; + hexify: { + int n, m; + char *p; + + len = SPRINTF((tmp, "\\# %u (\t; %s", edata - rdata, comment)); + T(addstr(tmp, len, &buf, &buflen)); + while (rdata < edata) { + p = tmp; + p += SPRINTF((p, "\n\t")); + spaced = 0; + n = MIN(16, edata - rdata); + for (m = 0; m < n; m++) + p += SPRINTF((p, "%02x ", rdata[m])); + T(addstr(tmp, p - tmp, &buf, &buflen)); + if (n < 16) { + T(addstr(")", 1, &buf, &buflen)); + T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); + } + p = tmp; + p += SPRINTF((p, "; ")); + for (m = 0; m < n; m++) + *p++ = (isascii(rdata[m]) && isprint(rdata[m])) + ? rdata[m] + : '.'; + T(addstr(tmp, p - tmp, &buf, &buflen)); + rdata += n; + } + return (buf - obuf); + } +} + +/* Private. */ + +/* + * size_t + * prune_origin(name, origin) + * Find out if the name is at or under the current origin. + * return: + * Number of characters in name before start of origin, + * or length of name if origin does not match. + * notes: + * This function should share code with samedomain(). + */ +static size_t +prune_origin(const char *name, const char *origin) { + const char *oname = name; + + while (*name != '\0') { + if (origin != NULL && ns_samename(name, origin) == 1) + return (name - oname - (name > oname)); + while (*name != '\0') { + if (*name == '\\') { + name++; + /* XXX need to handle \nnn form. */ + if (*name == '\0') + break; + } else if (*name == '.') { + name++; + break; + } + name++; + } + } + return (name - oname); +} + +/* + * int + * charstr(rdata, edata, buf, buflen) + * Format a <character-string> into the presentation buffer. + * return: + * Number of rdata octets consumed + * 0 for protocol format error + * -1 for output buffer error + * side effects: + * buffer is advanced on success. + */ +static int +charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { + const u_char *odata = rdata; + size_t save_buflen = *buflen; + char *save_buf = *buf; + + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + if (rdata < edata) { + int n = *rdata; + + if (rdata + 1 + n <= edata) { + rdata++; + while (n-- > 0) { + if (strchr("\n\"\\", *rdata) != NULL) + if (addstr("\\", 1, buf, buflen) < 0) + goto enospc; + if (addstr((const char *)rdata, 1, + buf, buflen) < 0) + goto enospc; + rdata++; + } + } + } + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + return (rdata - odata); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static int +addname(const u_char *msg, size_t msglen, + const u_char **pp, const char *origin, + char **buf, size_t *buflen) +{ + size_t newlen, save_buflen = *buflen; + char *save_buf = *buf; + int n; + + n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); + if (n < 0) + goto enospc; /* Guess. */ + newlen = prune_origin(*buf, origin); + if (**buf == '\0') { + goto root; + } else if (newlen == 0) { + /* Use "@" instead of name. */ + if (newlen + 2 > *buflen) + goto enospc; /* No room for "@\0". */ + (*buf)[newlen++] = '@'; + (*buf)[newlen] = '\0'; + } else { + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { + /* No trailing dot. */ + root: + if (newlen + 2 > *buflen) + goto enospc; /* No room for ".\0". */ + (*buf)[newlen++] = '.'; + (*buf)[newlen] = '\0'; + } + } + *pp += n; + addlen(newlen, buf, buflen); + **buf = '\0'; + return (newlen); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static void +addlen(size_t len, char **buf, size_t *buflen) { + INSIST(len <= *buflen); + *buf += len; + *buflen -= len; +} + +static int +addstr(const char *src, size_t len, char **buf, size_t *buflen) { + if (len >= *buflen) { + errno = ENOSPC; + return (-1); + } + memcpy(*buf, src, len); + addlen(len, buf, buflen); + **buf = '\0'; + return (0); +} + +static int +addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { + size_t save_buflen = *buflen; + char *save_buf = *buf; + int t; + + if (spaced || len >= target - 1) { + T(addstr(" ", 2, buf, buflen)); + spaced = 1; + } else { + for (t = (target - len - 1) / 8; t >= 0; t--) + if (addstr("\t", 1, buf, buflen) < 0) { + *buflen = save_buflen; + *buf = save_buf; + return (-1); + } + spaced = 0; + } + return (spaced); +} diff --git a/usr/src/lib/libresolv2/common/nameser/ns_samedomain.c b/usr/src/lib/libresolv2/common/nameser/ns_samedomain.c new file mode 100644 index 0000000000..9ae0195f27 --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_samedomain.c @@ -0,0 +1,213 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Copyright (c) 1995,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_samedomain.c,v 8.11 2003/04/14 14:52:48 vixie Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <arpa/nameser.h> +#include <errno.h> +#include <string.h> + +#include "port_after.h" + +/* + * int + * ns_samedomain(a, b) + * Check whether a name belongs to a domain. + * Inputs: + * a - the domain whose ancestory is being verified + * b - the potential ancestor we're checking against + * Return: + * boolean - is a at or below b? + * Notes: + * Trailing dots are first removed from name and domain. + * Always compare complete subdomains, not only whether the + * domain name is the trailing string of the given name. + * + * "host.foobar.top" lies in "foobar.top" and in "top" and in "" + * but NOT in "bar.top" + */ + +int +ns_samedomain(const char *a, const char *b) { + size_t la, lb; + int diff, i, escaped; + const char *cp; + + la = strlen(a); + lb = strlen(b); + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */ + if (la != 0 && a[la - 1] == '.') { + escaped = 0; + /* Note this loop doesn't get executed if la==1. */ + for (i = la - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + la--; + } + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */ + if (lb != 0 && b[lb - 1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if lb==1 */ + for (i = lb - 2; i >= 0; i--) + if (b[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + lb--; + } + + /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */ + if (lb == 0) + return (1); + + /* 'b' longer than 'a' means 'a' can't be in 'b'. */ + if (lb > la) + return (0); + + /* 'a' and 'b' being equal at this point indicates sameness. */ + if (lb == la) + return (strncasecmp(a, b, lb) == 0); + + /* Ok, we know la > lb. */ + + diff = la - lb; + + /* + * If 'a' is only 1 character longer than 'b', then it can't be + * a subdomain of 'b' (because of the need for the '.' label + * separator). + */ + if (diff < 2) + return (0); + + /* + * If the character before the last 'lb' characters of 'b' + * isn't '.', then it can't be a match (this lets us avoid + * having "foobar.com" match "bar.com"). + */ + if (a[diff - 1] != '.') + return (0); + + /* + * We're not sure about that '.', however. It could be escaped + * and thus not a really a label separator. + */ + escaped = 0; + for (i = diff - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (escaped) + return (0); + + /* Now compare aligned trailing substring. */ + cp = a + diff; + return (strncasecmp(cp, b, lb) == 0); +} + +/* + * int + * ns_subdomain(a, b) + * is "a" a subdomain of "b"? + */ +int +ns_subdomain(const char *a, const char *b) { + return (ns_samename(a, b) != 1 && ns_samedomain(a, b)); +} + +/* + * int + * ns_makecanon(src, dst, dstsize) + * make a canonical copy of domain name "src" + * notes: + * foo -> foo. + * foo. -> foo. + * foo.. -> foo. + * foo\. -> foo\.. + * foo\\. -> foo\\. + */ + +int +ns_makecanon(const char *src, char *dst, size_t dstsize) { + size_t n = strlen(src); + + if (n + sizeof "." > dstsize) { /* Note: sizeof == 2 */ + errno = EMSGSIZE; + return (-1); + } + strcpy(dst, src); + while (n >= 1 && dst[n - 1] == '.') /* Ends in "." */ + if (n >= 2 && dst[n - 2] == '\\' && /* Ends in "\." */ + (n < 3 || dst[n - 3] != '\\')) /* But not "\\." */ + break; + else + dst[--n] = '\0'; + dst[n++] = '.'; + dst[n] = '\0'; + return (0); +} + +/* + * int + * ns_samename(a, b) + * determine whether domain name "a" is the same as domain name "b" + * return: + * -1 on error + * 0 if names differ + * 1 if names are the same + */ + +int +ns_samename(const char *a, const char *b) { + char ta[NS_MAXDNAME], tb[NS_MAXDNAME]; + + if (ns_makecanon(a, ta, sizeof ta) < 0 || + ns_makecanon(b, tb, sizeof tb) < 0) + return (-1); + if (strcasecmp(ta, tb) == 0) + return (1); + else + return (0); +} diff --git a/usr/src/lib/libresolv2/common/nameser/ns_sign.c b/usr/src/lib/libresolv2/common/nameser/ns_sign.c new file mode 100644 index 0000000000..74674134c5 --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_sign.c @@ -0,0 +1,387 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_sign.c,v 8.12 2002/10/01 06:48:37 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <isc/dst.h> +#include <isc/assertions.h> + +#include "port_after.h" + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eob) { \ + errno = EMSGSIZE; \ + return(NS_TSIG_ERROR_NO_SPACE); \ + } \ + } while (0) + +/* ns_sign + * Parameters: + * msg message to be sent + * msglen input - length of message + * output - length of signed message + * msgsize length of buffer containing message + * error value to put in the error field + * key tsig key used for signing + * querysig (response), the signature in the query + * querysiglen (response), the length of the signature in the query + * sig a buffer to hold the generated signature + * siglen input - length of signature buffer + * output - length of signature + * + * Errors: + * - bad input data (-1) + * - bad key / sign failed (-BADKEY) + * - not enough space (NS_TSIG_ERROR_NO_SPACE) + */ +int +ns_sign(u_char *msg, int *msglen, int msgsize, int error, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t in_timesigned) +{ + return(ns_sign2(msg, msglen, msgsize, error, k, + querysig, querysiglen, sig, siglen, + in_timesigned, NULL, NULL)); +} + +int +ns_sign2(u_char *msg, int *msglen, int msgsize, int error, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t in_timesigned, u_char **dnptrs, u_char **lastdnptr) +{ + HEADER *hp = (HEADER *)msg; + DST_KEY *key = (DST_KEY *)k; + u_char *cp = msg + *msglen, *eob = msg + msgsize; + u_char *lenp; + u_char *alg; + int n; + time_t timesigned; + u_char name[NS_MAXCDNAME]; + + dst_init(); + if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL) + return (-1); + + /* Name. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + n = ns_name_pton(key->dk_key_name, name, sizeof name); + if (n != -1) + n = ns_name_pack(name, cp, eob - cp, + (const u_char **)dnptrs, + (const u_char **)lastdnptr); + + } else { + n = ns_name_pton("", name, sizeof name); + if (n != -1) + n = ns_name_pack(name, cp, eob - cp, NULL, NULL); + } + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + cp += n; + + /* Type, class, ttl, length (not filled in yet). */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(ns_t_tsig, cp); + PUTSHORT(ns_c_any, cp); + PUTLONG(0, cp); /* TTL */ + lenp = cp; + cp += 2; + + /* Alg. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + if (key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL); + } + else + n = dn_comp("", cp, eob - cp, NULL, NULL); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + alg = cp; + cp += n; + + /* Time. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(0, cp); + timesigned = time(NULL); + if (error != ns_r_badtime) + PUTLONG(timesigned, cp); + else + PUTLONG(in_timesigned, cp); + PUTSHORT(NS_TSIG_FUDGE, cp); + + /* Compute the signature. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + void *ctx; + u_char buf[NS_MAXCDNAME], *cp2; + int n; + + dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); + + /* Digest the query signature, if this is a response. */ + if (querysiglen > 0 && querysig != NULL) { + u_int16_t len_n = htons(querysiglen); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, + (u_char *)&len_n, INT16SZ, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, + querysig, querysiglen, NULL, 0); + } + + /* Digest the message. */ + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen, + NULL, 0); + + /* Digest the key name. */ + n = ns_name_ntol(name, buf, sizeof(buf)); + INSIST(n > 0); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the class and TTL. */ + cp2 = buf; + PUTSHORT(ns_c_any, cp2); + PUTLONG(0, cp2); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf, + NULL, 0); + + /* Digest the algorithm. */ + n = ns_name_ntol(alg, buf, sizeof(buf)); + INSIST(n > 0); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the time signed, fudge, error, and other data */ + cp2 = buf; + PUTSHORT(0, cp2); /* Top 16 bits of time */ + if (error != ns_r_badtime) + PUTLONG(timesigned, cp2); + else + PUTLONG(in_timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + PUTSHORT(error, cp2); /* Error */ + if (error != ns_r_badtime) + PUTSHORT(0, cp2); /* Other data length */ + else { + PUTSHORT(INT16SZ+INT32SZ, cp2); /* Other data length */ + PUTSHORT(0, cp2); /* Top 16 bits of time */ + PUTLONG(timesigned, cp2); + } + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf, + NULL, 0); + + n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, + sig, *siglen); + if (n < 0) + return (-ns_r_badkey); + *siglen = n; + } else + *siglen = 0; + + /* Add the signature. */ + BOUNDS_CHECK(cp, INT16SZ + (*siglen)); + PUTSHORT(*siglen, cp); + memcpy(cp, sig, *siglen); + cp += (*siglen); + + /* The original message ID & error. */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ); + PUTSHORT(ntohs(hp->id), cp); /* already in network order */ + PUTSHORT(error, cp); + + /* Other data. */ + BOUNDS_CHECK(cp, INT16SZ); + if (error != ns_r_badtime) + PUTSHORT(0, cp); /* Other data length */ + else { + PUTSHORT(INT16SZ+INT32SZ, cp); /* Other data length */ + BOUNDS_CHECK(cp, INT32SZ+INT16SZ); + PUTSHORT(0, cp); /* Top 16 bits of time */ + PUTLONG(timesigned, cp); + } + + /* Go back and fill in the length. */ + PUTSHORT(cp - lenp - INT16SZ, lenp); + + hp->arcount = htons(ntohs(hp->arcount) + 1); + *msglen = (cp - msg); + return (0); +} + +int +ns_sign_tcp_init(void *k, const u_char *querysig, int querysiglen, + ns_tcp_tsig_state *state) +{ + dst_init(); + if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) + return (-1); + state->counter = -1; + state->key = k; + if (state->key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (querysiglen > (int)sizeof(state->sig)) + return (-1); + memcpy(state->sig, querysig, querysiglen); + state->siglen = querysiglen; + return (0); +} + +int +ns_sign_tcp(u_char *msg, int *msglen, int msgsize, int error, + ns_tcp_tsig_state *state, int done) +{ + return (ns_sign_tcp2(msg, msglen, msgsize, error, state, + done, NULL, NULL)); +} + +int +ns_sign_tcp2(u_char *msg, int *msglen, int msgsize, int error, + ns_tcp_tsig_state *state, int done, + u_char **dnptrs, u_char **lastdnptr) +{ + u_char *cp, *eob, *lenp; + u_char buf[MAXDNAME], *cp2; + HEADER *hp = (HEADER *)msg; + time_t timesigned; + int n; + + if (msg == NULL || msglen == NULL || state == NULL) + return (-1); + + state->counter++; + if (state->counter == 0) + return (ns_sign2(msg, msglen, msgsize, error, state->key, + state->sig, state->siglen, + state->sig, &state->siglen, 0, + dnptrs, lastdnptr)); + + if (state->siglen > 0) { + u_int16_t siglen_n = htons(state->siglen); + dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx, + NULL, 0, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + (u_char *)&siglen_n, INT16SZ, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + state->sig, state->siglen, NULL, 0); + state->siglen = 0; + } + + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen, + NULL, 0); + + if (done == 0 && (state->counter % 100 != 0)) + return (0); + + cp = msg + *msglen; + eob = msg + msgsize; + + /* Name. */ + n = dn_comp(state->key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + cp += n; + + /* Type, class, ttl, length (not filled in yet). */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(ns_t_tsig, cp); + PUTSHORT(ns_c_any, cp); + PUTLONG(0, cp); /* TTL */ + lenp = cp; + cp += 2; + + /* Alg. */ + n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + cp += n; + + /* Time. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(0, cp); + timesigned = time(NULL); + PUTLONG(timesigned, cp); + PUTSHORT(NS_TSIG_FUDGE, cp); + + /* + * Compute the signature. + */ + + /* Digest the time signed and fudge. */ + cp2 = buf; + PUTSHORT(0, cp2); /* Top 16 bits of time */ + PUTLONG(timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + buf, cp2 - buf, NULL, 0); + + n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, + state->sig, sizeof(state->sig)); + if (n < 0) + return (-ns_r_badkey); + state->siglen = n; + + /* Add the signature. */ + BOUNDS_CHECK(cp, INT16SZ + state->siglen); + PUTSHORT(state->siglen, cp); + memcpy(cp, state->sig, state->siglen); + cp += state->siglen; + + /* The original message ID & error. */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ); + PUTSHORT(ntohs(hp->id), cp); /* already in network order */ + PUTSHORT(error, cp); + + /* Other data. */ + BOUNDS_CHECK(cp, INT16SZ); + PUTSHORT(0, cp); + + /* Go back and fill in the length. */ + PUTSHORT(cp - lenp - INT16SZ, lenp); + + hp->arcount = htons(ntohs(hp->arcount) + 1); + *msglen = (cp - msg); + return (0); +} diff --git a/usr/src/lib/libresolv2/common/nameser/ns_ttl.c b/usr/src/lib/libresolv2/common/nameser/ns_ttl.c new file mode 100644 index 0000000000..274359036f --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_ttl.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef lint +static const char rcsid[] = "$Id: ns_ttl.c,v 8.8 1999/10/13 16:39:36 vixie Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int fmt1(int t, char s, char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) if ((x) < 0) return (-1); else (void)NULL + +/* Public. */ + +int +ns_format_ttl(u_long src, char *dst, size_t dstlen) { + char *odst = dst; + int secs, mins, hours, days, weeks, x; + char *p; + + secs = src % 60; src /= 60; + mins = src % 60; src /= 60; + hours = src % 24; src /= 24; + days = src % 7; src /= 7; + weeks = src; src = 0; + + x = 0; + if (weeks) { + T(fmt1(weeks, 'W', &dst, &dstlen)); + x++; + } + if (days) { + T(fmt1(days, 'D', &dst, &dstlen)); + x++; + } + if (hours) { + T(fmt1(hours, 'H', &dst, &dstlen)); + x++; + } + if (mins) { + T(fmt1(mins, 'M', &dst, &dstlen)); + x++; + } + if (secs || !(weeks || days || hours || mins)) { + T(fmt1(secs, 'S', &dst, &dstlen)); + x++; + } + + if (x > 1) { + int ch; + + for (p = odst; (ch = *p) != '\0'; p++) + if (isascii(ch) && isupper(ch)) + *p = tolower(ch); + } + + return (dst - odst); +} + +int +ns_parse_ttl(const char *src, u_long *dst) { + u_long ttl, tmp; + int ch, digits, dirty; + + ttl = 0; + tmp = 0; + digits = 0; + dirty = 0; + while ((ch = *src++) != '\0') { + if (!isascii(ch) || !isprint(ch)) + goto einval; + if (isdigit(ch)) { + tmp *= 10; + tmp += (ch - '0'); + digits++; + continue; + } + if (digits == 0) + goto einval; + if (islower(ch)) + ch = toupper(ch); + switch (ch) { + case 'W': tmp *= 7; + case 'D': tmp *= 24; + case 'H': tmp *= 60; + case 'M': tmp *= 60; + case 'S': break; + default: goto einval; + } + ttl += tmp; + tmp = 0; + digits = 0; + dirty = 1; + } + if (digits > 0) { + if (dirty) + goto einval; + else + ttl += tmp; + } + *dst = ttl; + return (0); + + einval: + errno = EINVAL; + return (-1); +} + +/* Private. */ + +static int +fmt1(int t, char s, char **buf, size_t *buflen) { + char tmp[50]; + size_t len; + + len = SPRINTF((tmp, "%d%c", t, s)); + if (len + 1 > *buflen) + return (-1); + strcpy(*buf, tmp); + *buf += len; + *buflen -= len; + return (0); +} diff --git a/usr/src/lib/libresolv2/common/nameser/ns_verify.c b/usr/src/lib/libresolv2/common/nameser/ns_verify.c new file mode 100644 index 0000000000..c8ccf219d5 --- /dev/null +++ b/usr/src/lib/libresolv2/common/nameser/ns_verify.c @@ -0,0 +1,487 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef lint +static const char rcsid[] = "$Id: ns_verify.c,v 8.14 2001/05/29 05:49:40 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <isc/dst.h> + +#include "port_after.h" + +/* Private. */ + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + return (NS_TSIG_ERROR_FORMERR); \ + } \ + } while (0) + +/* Public. */ + +u_char * +ns_find_tsig(u_char *msg, u_char *eom) { + HEADER *hp = (HEADER *)msg; + int n, type; + u_char *cp = msg, *start; + + if (msg == NULL || eom == NULL || msg > eom) + return (NULL); + + if (cp + HFIXEDSZ >= eom) + return (NULL); + + if (hp->arcount == 0) + return (NULL); + + cp += HFIXEDSZ; + + n = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_ar, ntohs(hp->arcount) - 1); + if (n < 0) + return (NULL); + cp += n; + + start = cp; + n = dn_skipname(cp, eom); + if (n < 0) + return (NULL); + cp += n; + if (cp + INT16SZ >= eom) + return (NULL); + + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NULL); + return (start); +} + +/* ns_verify + * Parameters: + * statp res stuff + * msg received message + * msglen length of message + * key tsig key used for verifying. + * querysig (response), the signature in the query + * querysiglen (response), the length of the signature in the query + * sig (query), a buffer to hold the signature + * siglen (query), input - length of signature buffer + * output - length of signature + * + * Errors: + * - bad input (-1) + * - invalid dns message (NS_TSIG_ERROR_FORMERR) + * - TSIG is not present (NS_TSIG_ERROR_NO_TSIG) + * - key doesn't match (-ns_r_badkey) + * - TSIG verification fails with BADKEY (-ns_r_badkey) + * - TSIG verification fails with BADSIG (-ns_r_badsig) + * - TSIG verification fails with BADTIME (-ns_r_badtime) + * - TSIG verification succeeds, error set to BAKEY (ns_r_badkey) + * - TSIG verification succeeds, error set to BADSIG (ns_r_badsig) + * - TSIG verification succeeds, error set to BADTIME (ns_r_badtime) + */ +int +ns_verify(u_char *msg, int *msglen, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t *timesigned, int nostrip) +{ + HEADER *hp = (HEADER *)msg; + DST_KEY *key = (DST_KEY *)k; + u_char *cp = msg, *eom; + char name[MAXDNAME], alg[MAXDNAME]; + u_char *recstart, *rdatastart; + u_char *sigstart, *otherstart; + int n; + int error; + u_int16_t type, length; + u_int16_t fudge, sigfieldlen, id, otherfieldlen; + + dst_init(); + if (msg == NULL || msglen == NULL || *msglen < 0) + return (-1); + + eom = msg + *msglen; + + recstart = ns_find_tsig(msg, eom); + if (recstart == NULL) + return (NS_TSIG_ERROR_NO_TSIG); + + cp = recstart; + + /* Read the key name. */ + n = dn_expand(msg, eom, cp, name, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + cp += n; + + /* Read the type. */ + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NS_TSIG_ERROR_NO_TSIG); + + /* Skip the class and TTL, save the length. */ + cp += INT16SZ + INT32SZ; + GETSHORT(length, cp); + if (eom - cp != length) + return (NS_TSIG_ERROR_FORMERR); + + /* Read the algorithm name. */ + rdatastart = cp; + n = dn_expand(msg, eom, cp, alg, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) + return (-ns_r_badkey); + cp += n; + + /* Read the time signed and fudge. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + cp += INT16SZ; + GETLONG((*timesigned), cp); + GETSHORT(fudge, cp); + + /* Read the signature. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(sigfieldlen, cp); + BOUNDS_CHECK(cp, sigfieldlen); + sigstart = cp; + cp += sigfieldlen; + + /* Read the original id and error. */ + BOUNDS_CHECK(cp, 2*INT16SZ); + GETSHORT(id, cp); + GETSHORT(error, cp); + + /* Parse the other data. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(otherfieldlen, cp); + BOUNDS_CHECK(cp, otherfieldlen); + otherstart = cp; + cp += otherfieldlen; + + if (cp != eom) + return (NS_TSIG_ERROR_FORMERR); + + /* Verify that the key used is OK. */ + if (key != NULL) { + if (key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (error != ns_r_badsig && error != ns_r_badkey) { + if (ns_samename(key->dk_key_name, name) != 1) + return (-ns_r_badkey); + } + } + + hp->arcount = htons(ntohs(hp->arcount) - 1); + + /* + * Do the verification. + */ + + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + void *ctx; + u_char buf[MAXDNAME]; + u_char buf2[MAXDNAME]; + + /* Digest the query signature, if this is a response. */ + dst_verify_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); + if (querysiglen > 0 && querysig != NULL) { + u_int16_t len_n = htons(querysiglen); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + (u_char *)&len_n, INT16SZ, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + querysig, querysiglen, NULL, 0); + } + + /* Digest the message. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, msg, recstart - msg, + NULL, 0); + + /* Digest the key name. */ + n = ns_name_pton(name, buf2, sizeof(buf2)); + if (n < 0) + return (-1); + n = ns_name_ntol(buf2, buf, sizeof(buf)); + if (n < 0) + return (-1); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the class and TTL. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + recstart + dn_skipname(recstart, eom) + INT16SZ, + INT16SZ + INT32SZ, NULL, 0); + + /* Digest the algorithm. */ + n = ns_name_pton(alg, buf2, sizeof(buf2)); + if (n < 0) + return (-1); + n = ns_name_ntol(buf2, buf, sizeof(buf)); + if (n < 0) + return (-1); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the time signed and fudge. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + rdatastart + dn_skipname(rdatastart, eom), + INT16SZ + INT32SZ + INT16SZ, NULL, 0); + + /* Digest the error and other data. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + otherstart - INT16SZ - INT16SZ, + otherfieldlen + INT16SZ + INT16SZ, NULL, 0); + + n = dst_verify_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, + sigstart, sigfieldlen); + + if (n < 0) + return (-ns_r_badsig); + + if (sig != NULL && siglen != NULL) { + if (*siglen < sigfieldlen) + return (NS_TSIG_ERROR_NO_SPACE); + memcpy(sig, sigstart, sigfieldlen); + *siglen = sigfieldlen; + } + } else { + if (sigfieldlen > 0) + return (NS_TSIG_ERROR_FORMERR); + if (sig != NULL && siglen != NULL) + *siglen = 0; + } + + /* Reset the counter, since we still need to check for badtime. */ + hp->arcount = htons(ntohs(hp->arcount) + 1); + + /* Verify the time. */ + if (abs((*timesigned) - time(NULL)) > fudge) + return (-ns_r_badtime); + + if (nostrip == 0) { + *msglen = recstart - msg; + hp->arcount = htons(ntohs(hp->arcount) - 1); + } + + if (error != NOERROR) + return (error); + + return (0); +} + +int +ns_verify_tcp_init(void *k, const u_char *querysig, int querysiglen, + ns_tcp_tsig_state *state) +{ + dst_init(); + if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) + return (-1); + state->counter = -1; + state->key = k; + if (state->key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (querysiglen > (int)sizeof(state->sig)) + return (-1); + memcpy(state->sig, querysig, querysiglen); + state->siglen = querysiglen; + return (0); +} + +int +ns_verify_tcp(u_char *msg, int *msglen, ns_tcp_tsig_state *state, + int required) +{ + HEADER *hp = (HEADER *)msg; + u_char *recstart, *rdatastart, *sigstart; + unsigned int sigfieldlen, otherfieldlen; + u_char *cp, *eom = msg + *msglen, *cp2; + char name[MAXDNAME], alg[MAXDNAME]; + u_char buf[MAXDNAME]; + int n, type, length, fudge, id, error; + time_t timesigned; + + if (msg == NULL || msglen == NULL || state == NULL) + return (-1); + + state->counter++; + if (state->counter == 0) + return (ns_verify(msg, msglen, state->key, + state->sig, state->siglen, + state->sig, &state->siglen, ×igned, 0)); + + if (state->siglen > 0) { + u_int16_t siglen_n = htons(state->siglen); + + dst_verify_data(SIG_MODE_INIT, state->key, &state->ctx, + NULL, 0, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + (u_char *)&siglen_n, INT16SZ, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + state->sig, state->siglen, NULL, 0); + state->siglen = 0; + } + + cp = recstart = ns_find_tsig(msg, eom); + + if (recstart == NULL) { + if (required) + return (NS_TSIG_ERROR_NO_TSIG); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + msg, *msglen, NULL, 0); + return (0); + } + + hp->arcount = htons(ntohs(hp->arcount) - 1); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + msg, recstart - msg, NULL, 0); + + /* Read the key name. */ + n = dn_expand(msg, eom, cp, name, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + cp += n; + + /* Read the type. */ + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NS_TSIG_ERROR_NO_TSIG); + + /* Skip the class and TTL, save the length. */ + cp += INT16SZ + INT32SZ; + GETSHORT(length, cp); + if (eom - cp != length) + return (NS_TSIG_ERROR_FORMERR); + + /* Read the algorithm name. */ + rdatastart = cp; + n = dn_expand(msg, eom, cp, alg, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) + return (-ns_r_badkey); + cp += n; + + /* Verify that the key used is OK. */ + if ((ns_samename(state->key->dk_key_name, name) != 1 || + state->key->dk_alg != KEY_HMAC_MD5)) + return (-ns_r_badkey); + + /* Read the time signed and fudge. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + cp += INT16SZ; + GETLONG(timesigned, cp); + GETSHORT(fudge, cp); + + /* Read the signature. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(sigfieldlen, cp); + BOUNDS_CHECK(cp, sigfieldlen); + sigstart = cp; + cp += sigfieldlen; + + /* Read the original id and error. */ + BOUNDS_CHECK(cp, 2*INT16SZ); + GETSHORT(id, cp); + GETSHORT(error, cp); + + /* Parse the other data. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(otherfieldlen, cp); + BOUNDS_CHECK(cp, otherfieldlen); + cp += otherfieldlen; + + if (cp != eom) + return (NS_TSIG_ERROR_FORMERR); + + /* + * Do the verification. + */ + + /* Digest the time signed and fudge. */ + cp2 = buf; + PUTSHORT(0, cp2); /* Top 16 bits of time. */ + PUTLONG(timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + buf, cp2 - buf, NULL, 0); + + n = dst_verify_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, + sigstart, sigfieldlen); + if (n < 0) + return (-ns_r_badsig); + + if (sigfieldlen > sizeof(state->sig)) + return (NS_TSIG_ERROR_NO_SPACE); + + memcpy(state->sig, sigstart, sigfieldlen); + state->siglen = sigfieldlen; + + /* Verify the time. */ + if (abs(timesigned - time(NULL)) > fudge) + return (-ns_r_badtime); + + *msglen = recstart - msg; + + if (error != NOERROR) + return (error); + + return (0); +} diff --git a/usr/src/lib/libresolv2/common/resolv/herror.c b/usr/src/lib/libresolv2/common/resolv/herror.c new file mode 100644 index 0000000000..1101057748 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/herror.c @@ -0,0 +1,132 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1987, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: herror.c,v 8.13 2001/06/18 14:44:06 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <netdb.h> +#include <resolv.h> +#include <string.h> +#include <unistd.h> +#include <irs.h> + +#include "port_after.h" +#undef h_errno + +const char *h_errlist[] = { + "Resolver Error 0 (no error)", + "Unknown host", /* 1 HOST_NOT_FOUND */ + "Host name lookup failure", /* 2 TRY_AGAIN */ + "Unknown server error", /* 3 NO_RECOVERY */ + "No address associated with name", /* 4 NO_ADDRESS */ +}; +int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; + +int h_errno; + +/* + * herror -- + * print the error indicated by the h_errno value. + */ +void +herror(const char *s) { + struct iovec iov[4], *v = iov; + char *t; + + if (s != NULL && *s != '\0') { + DE_CONST(s, t); + v->iov_base = t; + v->iov_len = strlen(t); + v++; + DE_CONST(": ", t); + v->iov_base = t; + v->iov_len = 2; + v++; + } + DE_CONST(hstrerror(*__h_errno()), t); + v->iov_base = t; + v->iov_len = strlen(v->iov_base); + v++; + DE_CONST("\n", t); + v->iov_base = t; + v->iov_len = 1; + writev(STDERR_FILENO, iov, (v - iov) + 1); +} + +/* + * hstrerror -- + * return the string associated with a given "host" errno value. + */ +const char * +hstrerror(int err) { + if (err < 0) + return ("Resolver internal error"); + else if (err < h_nerr) + return (h_errlist[err]); + return ("Unknown resolver error"); +} diff --git a/usr/src/lib/libresolv2/common/resolv/res_comp.c b/usr/src/lib/libresolv2/common/resolv/res_comp.c new file mode 100644 index 0000000000..a0a3d9abb2 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_comp.c @@ -0,0 +1,284 @@ +/* + * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1985, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_comp.c,v 8.16 2002/08/07 03:47:34 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "port_after.h" + +#ifdef ORIGINAL_ISC_CODE +#else +#pragma weak __dn_skipname = dn_skipname +#pragma weak __res_dnok = res_dnok +#pragma weak __res_hnok = res_hnok +#pragma weak __res_mailok = res_mailok +#pragma weak __res_ownok = res_ownok +#endif /* ORIGINAL_ISC_CODE */ +/* + * Expand compressed domain name 'src' to full domain name. + * 'msg' is a pointer to the begining of the message, + * 'eom' points to the first location after the message, + * 'dst' is a pointer to a buffer of size 'dstsiz' for the result. + * Return size of compressed name or -1 if there was an error. + */ +int +dn_expand(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, int dstsiz) +{ + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + + if (n > 0 && dst[0] == '.') + dst[0] = '\0'; + return (n); +} + +/* + * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. + * Return the size of the compressed name or -1. + * 'length' is the size of the array pointed to by 'comp_dn'. + */ +int +dn_comp(const char *src, u_char *dst, int dstsiz, + u_char **dnptrs, u_char **lastdnptr) +{ + return (ns_name_compress(src, dst, (size_t)dstsiz, + (const u_char **)dnptrs, + (const u_char **)lastdnptr)); +} + +/* + * Skip over a compressed domain name. Return the size or -1. + */ +int +dn_skipname(const u_char *ptr, const u_char *eom) { + const u_char *saveptr = ptr; + + if (ns_name_skip(&ptr, eom) == -1) + return (-1); + return (ptr - saveptr); +} + +/* + * Verify that a domain name uses an acceptable character set. + */ + +/* + * Note the conspicuous absence of ctype macros in these definitions. On + * non-ASCII hosts, we can't depend on string literals or ctype macros to + * tell us anything about network-format data. The rest of the BIND system + * is not careful about this, but for some reason, we're doing it right here. + */ +#define PERIOD 0x2e +#define hyphenchar(c) ((c) == 0x2d) +#define bslashchar(c) ((c) == 0x5c) +#ifdef SUNW_HNOK_UNDERSCORE +#define underscorechar(c) ((c) == 0x5f) +#endif /* SUNW_HNOK_UNDERSCORE */ +#define periodchar(c) ((c) == PERIOD) +#define asterchar(c) ((c) == 0x2a) +#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ + || ((c) >= 0x61 && (c) <= 0x7a)) +#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) + +#define borderchar(c) (alphachar(c) || digitchar(c)) +#ifdef SUNW_HNOK_UNDERSCORE +#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c)) +#else +#define middlechar(c) (borderchar(c) || hyphenchar(c)) +#endif /* SUNW_HNOK_UNDERSCORE */ +#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) + +int +res_hnok(const char *dn) { + int ppch = '\0', pch = PERIOD, ch = *dn++; + + while (ch != '\0') { + int nch = *dn++; + + if (periodchar(ch)) { + (void)NULL; + } else if (periodchar(pch)) { + if (!borderchar(ch)) + return (0); + } else if (periodchar(nch) || nch == '\0') { + if (!borderchar(ch)) + return (0); + } else { + if (!middlechar(ch)) + return (0); + } + ppch = pch, pch = ch, ch = nch; + } + return (1); +} + +/* + * hostname-like (A, MX, WKS) owners can have "*" as their first label + * but must otherwise be as a host name. + */ +int +res_ownok(const char *dn) { + if (asterchar(dn[0])) { + if (periodchar(dn[1])) + return (res_hnok(dn+2)); + if (dn[1] == '\0') + return (1); + } + return (res_hnok(dn)); +} + +/* + * SOA RNAMEs and RP RNAMEs can have any printable character in their first + * label, but the rest of the name has to look like a host name. + */ +int +res_mailok(const char *dn) { + int ch, escaped = 0; + + /* "." is a valid missing representation */ + if (*dn == '\0') + return (1); + + /* otherwise <label>.<hostname> */ + while ((ch = *dn++) != '\0') { + if (!domainchar(ch)) + return (0); + if (!escaped && periodchar(ch)) + break; + if (escaped) + escaped = 0; + else if (bslashchar(ch)) + escaped = 1; + } + if (periodchar(ch)) + return (res_hnok(dn)); + return (0); +} + +/* + * This function is quite liberal, since RFC 1034's character sets are only + * recommendations. + */ +int +res_dnok(const char *dn) { + int ch; + + while ((ch = *dn++) != '\0') + if (!domainchar(ch)) + return (0); + return (1); +} + +#ifdef BIND_4_COMPAT +/* + * This module must export the following externally-visible symbols: + * ___putlong + * ___putshort + * __getlong + * __getshort + * Note that one _ comes from C and the others come from us. + */ +#ifdef ORIGINAL_ISC_CODE +#else +#ifdef __putlong +#undef __putlong +#endif +#ifdef __putshort +#undef __putshort +#endif +#pragma weak putlong = __putlong +#pragma weak putshort = __putshort +#endif /* ORIGINAL_ISC_CODE */ +void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); } +void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } +#ifndef __ultrix__ +u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } +u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } +#endif /*__ultrix__*/ +#endif /*BIND_4_COMPAT*/ diff --git a/usr/src/lib/libresolv2/common/resolv/res_data.c b/usr/src/lib/libresolv2/common/resolv/res_data.c new file mode 100644 index 0000000000..50368f6600 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_data.c @@ -0,0 +1,306 @@ +/* + * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: res_data.c,v 8.18 2000/12/23 08:14:58 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <netdb.h> +#include <resolv.h> +#include <res_update.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" +#undef _res + +#ifdef ORIGINAL_ISC_CODE +#else +#pragma weak __fp_nquery = fp_nquery +#pragma weak __fp_query = fp_query +#pragma weak __p_query = p_query +#pragma weak __hostalias = hostalias +#endif + +const char *_res_opcodes[] = { + "QUERY", + "IQUERY", + "CQUERYM", + "CQUERYU", /* experimental */ + "NOTIFY", /* experimental */ + "UPDATE", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "ZONEINIT", + "ZONEREF", +}; + +#ifdef BIND_UPDATE +const char *_res_sectioncodes[] = { + "ZONE", + "PREREQUISITES", + "UPDATE", + "ADDITIONAL", +}; +#endif + +#ifndef __BIND_NOSTATIC +struct __res_state _res +# if defined(__BIND_RES_TEXT) + = { RES_TIMEOUT, } /* Motorola, et al. */ +# endif + ; + +/* Proto. */ + +int res_ourserver_p(const res_state, const struct sockaddr_in *); + +int +res_init(void) { + extern int __res_vinit(res_state, int); + + /* + * These three fields used to be statically initialized. This made + * it hard to use this code in a shared library. It is necessary, + * now that we're doing dynamic initialization here, that we preserve + * the old semantics: if an application modifies one of these three + * fields of _res before res_init() is called, res_init() will not + * alter them. Of course, if an application is setting them to + * _zero_ before calling res_init(), hoping to override what used + * to be the static default, we can't detect it and unexpected results + * will follow. Zero for any of these fields would make no sense, + * so one can safely assume that the applications were already getting + * unexpected results. + * + * _res.options is tricky since some apps were known to diddle the bits + * before res_init() was first called. We can't replicate that semantic + * with dynamic initialization (they may have turned bits off that are + * set in RES_DEFAULT). Our solution is to declare such applications + * "broken". They could fool us by setting RES_INIT but none do (yet). + */ + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = 4; + if (!(_res.options & RES_INIT)) + _res.options = RES_DEFAULT; + + /* + * This one used to initialize implicitly to zero, so unless the app + * has set it to something in particular, we can randomize it now. + */ + if (!_res.id) + _res.id = res_randomid(); + + return (__res_vinit(&_res, 1)); +} + +void +p_query(const u_char *msg) { + fp_query(msg, stdout); +} + +void +fp_query(const u_char *msg, FILE *file) { + fp_nquery(msg, PACKETSZ, file); +} + +void +fp_nquery(const u_char *msg, int len, FILE *file) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return; + + res_pquery(&_res, msg, len, file); +} + +int +res_mkquery(int op, /* opcode of query */ + const char *dname, /* domain name */ + int class, int type, /* class and type of query */ + const u_char *data, /* resource record data */ + int datalen, /* length of data */ + const u_char *newrr_in, /* new rr for modify or append */ + u_char *buf, /* buffer to put query */ + int buflen) /* size of buffer */ +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + return (res_nmkquery(&_res, op, dname, class, type, + data, datalen, + newrr_in, buf, buflen)); +} + +int +res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); +} + +int +res_query(const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer buffer */ +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + return (res_nquery(&_res, name, class, type, answer, anslen)); +} + +void +res_send_setqhook(res_send_qhook hook) { + _res.qhook = hook; +} + +void +res_send_setrhook(res_send_rhook hook) { + _res.rhook = hook; +} + +int +res_isourserver(const struct sockaddr_in *inp) { + return (res_ourserver_p(&_res, inp)); +} + +int +res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + return (-1); + } + + return (res_nsend(&_res, buf, buflen, ans, anssiz)); +} + +int +res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, + u_char *ans, int anssiz) +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + return (-1); + } + + return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); +} + +void +res_close(void) { + res_nclose(&_res); +} + +int +res_update(ns_updrec *rrecp_in) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nupdate(&_res, rrecp_in, NULL)); +} + +int +res_search(const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nsearch(&_res, name, class, type, answer, anslen)); +} + +int +res_querydomain(const char *name, + const char *domain, + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ +{ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nquerydomain(&_res, name, domain, + class, type, + answer, anslen)); +} + +const char * +hostalias(const char *name) { + static char abuf[MAXDNAME]; + + return (res_hostalias(&_res, name, abuf, sizeof abuf)); +} + +#ifdef ultrix +int +local_hostname_length(const char *hostname) { + int len_host, len_domain; + + if (!*_res.defdname) + res_init(); + len_host = strlen(hostname); + len_domain = strlen(_res.defdname); + if (len_host > len_domain && + !strcasecmp(hostname + len_host - len_domain, _res.defdname) && + hostname[len_host - len_domain - 1] == '.') + return (len_host - len_domain - 1); + return (0); +} +#endif /*ultrix*/ + +#endif diff --git a/usr/src/lib/libresolv2/common/resolv/res_debug.c b/usr/src/lib/libresolv2/common/resolv/res_debug.c new file mode 100644 index 0000000000..838ed3fd8a --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_debug.c @@ -0,0 +1,1222 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1985 + * The 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. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_debug.c,v 8.50 2003/04/16 04:55:40 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +extern const char *_res_opcodes[]; +extern const char *_res_sectioncodes[]; + +#ifdef ORIGINAL_ISC_CODE +#else +#pragma weak __dn_count_labels = dn_count_labels +#pragma weak __fp_resstat = fp_resstat +#pragma weak __loc_aton = loc_aton +#pragma weak __loc_ntoa = loc_ntoa +#pragma weak __p_cdname = p_cdname +#pragma weak __p_class = p_class +#pragma weak __p_secstodate = p_secstodate +#pragma weak __p_section = p_section +#pragma weak __p_time = p_time +#pragma weak __p_type = p_type +#pragma weak __sym_ntop = sym_ntop +#pragma weak __sym_ntos = sym_ntos +#pragma weak __sym_ston = sym_ston +#endif /* ORIGINAL_ISC_CODE */ + +/* + * Print the current options. + */ +void +fp_resstat(const res_state statp, FILE *file) { + u_long mask; + + fprintf(file, ";; res options:"); + for (mask = 1; mask != 0; mask <<= 1) + if (statp->options & mask) + fprintf(file, " %s", p_option(mask)); + putc('\n', file); +} + +static void +do_section(const res_state statp, + ns_msg *handle, ns_sect section, + int pflag, FILE *file) +{ + int n, sflag, rrnum; + static int buflen = 2048; + char *buf; + ns_opcode opcode; + ns_rr rr; + + /* + * Print answer records. + */ + sflag = (statp->pfcode & pflag); + if (statp->pfcode && !sflag) + return; + + buf = malloc(buflen); + if (buf == NULL) { + fprintf(file, ";; memory allocation failure\n"); + return; + } + + opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode); + rrnum = 0; + for (;;) { + if (ns_parserr(handle, section, rrnum, &rr)) { + if (errno != ENODEV) + fprintf(file, ";; ns_parserr: %s\n", + strerror(errno)); + else if (rrnum > 0 && sflag != 0 && + (statp->pfcode & RES_PRF_HEAD1)) + putc('\n', file); + goto cleanup; + } + if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) + fprintf(file, ";; %s SECTION:\n", + p_section(section, opcode)); + if (section == ns_s_qd) + fprintf(file, ";;\t%s, type = %s, class = %s\n", + ns_rr_name(rr), + p_type(ns_rr_type(rr)), + p_class(ns_rr_class(rr))); + else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) { + u_int32_t ttl = ns_rr_ttl(rr); + fprintf(file, + "; EDNS: version: %u, udp=%u, flags=%04x\n", + (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff); + } else { + n = ns_sprintrr(handle, &rr, NULL, NULL, + buf, buflen); + if (n < 0) { + if (errno == ENOSPC) { + free(buf); + buf = NULL; + if (buflen < 131072) + buf = malloc(buflen += 1024); + if (buf == NULL) { + fprintf(file, + ";; memory allocation failure\n"); + return; + } + continue; + } + fprintf(file, ";; ns_sprintrr: %s\n", + strerror(errno)); + goto cleanup; + } + fputs(buf, file); + fputc('\n', file); + } + rrnum++; + } + cleanup: + if (buf != NULL) + free(buf); +} + +/* + * Print the contents of a query. + * This is intended to be primarily a debugging routine. + */ +void +res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { + ns_msg handle; + int qdcount, ancount, nscount, arcount; + u_int opcode, rcode, id; + + if (ns_initparse(msg, len, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + return; + } + opcode = ns_msg_getflag(handle, ns_f_opcode); + rcode = ns_msg_getflag(handle, ns_f_rcode); + id = ns_msg_id(handle); + qdcount = ns_msg_count(handle, ns_s_qd); + ancount = ns_msg_count(handle, ns_s_an); + nscount = ns_msg_count(handle, ns_s_ns); + arcount = ns_msg_count(handle, ns_s_ar); + + /* + * Print header fields. + */ + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode) + fprintf(file, + ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", + _res_opcodes[opcode], p_rcode(rcode), id); + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX)) + putc(';', file); + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) { + fprintf(file, "; flags:"); + if (ns_msg_getflag(handle, ns_f_qr)) + fprintf(file, " qr"); + if (ns_msg_getflag(handle, ns_f_aa)) + fprintf(file, " aa"); + if (ns_msg_getflag(handle, ns_f_tc)) + fprintf(file, " tc"); + if (ns_msg_getflag(handle, ns_f_rd)) + fprintf(file, " rd"); + if (ns_msg_getflag(handle, ns_f_ra)) + fprintf(file, " ra"); + if (ns_msg_getflag(handle, ns_f_z)) + fprintf(file, " ??"); + if (ns_msg_getflag(handle, ns_f_ad)) + fprintf(file, " ad"); + if (ns_msg_getflag(handle, ns_f_cd)) + fprintf(file, " cd"); + } + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) { + fprintf(file, "; %s: %d", + p_section(ns_s_qd, opcode), qdcount); + fprintf(file, ", %s: %d", + p_section(ns_s_an, opcode), ancount); + fprintf(file, ", %s: %d", + p_section(ns_s_ns, opcode), nscount); + fprintf(file, ", %s: %d", + p_section(ns_s_ar, opcode), arcount); + } + if ((!statp->pfcode) || (statp->pfcode & + (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { + putc('\n',file); + } + /* + * Print the various sections. + */ + do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file); + do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file); + do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file); + do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file); + if (qdcount == 0 && ancount == 0 && + nscount == 0 && arcount == 0) + putc('\n', file); +} + +const u_char * +p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { + char name[MAXDNAME]; + int n; + + if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) + return (NULL); + if (name[0] == '\0') + putc('.', file); + else + fputs(name, file); + return (cp + n); +} + +const u_char * +p_cdname(const u_char *cp, const u_char *msg, FILE *file) { + return (p_cdnname(cp, msg, PACKETSZ, file)); +} + +/* Return a fully-qualified domain name from a compressed name (with + length supplied). */ + +const u_char * +p_fqnname(cp, msg, msglen, name, namelen) + const u_char *cp, *msg; + int msglen; + char *name; + int namelen; +{ + int n, newlen; + + if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) + return (NULL); + newlen = strlen(name); + if (newlen == 0 || name[newlen - 1] != '.') { + if (newlen + 1 >= namelen) /* Lack space for final dot */ + return (NULL); + else + strcpy(name + newlen, "."); + } + return (cp + n); +} + +/* XXX: the rest of these functions need to become length-limited, too. */ + +const u_char * +p_fqname(const u_char *cp, const u_char *msg, FILE *file) { + char name[MAXDNAME]; + const u_char *n; + + n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); + if (n == NULL) + return (NULL); + fputs(name, file); + return (n); +} + +/* + * Names of RR classes and qclasses. Classes and qclasses are the same, except + * that C_ANY is a qclass but not a class. (You can ask for records of class + * C_ANY, but you can't have any records of that class in the database.) + */ +const struct res_sym __p_class_syms[] = { + {C_IN, "IN", (char *)0}, + {C_CHAOS, "CHAOS", (char *)0}, + {C_HS, "HS", (char *)0}, + {C_HS, "HESIOD", (char *)0}, + {C_ANY, "ANY", (char *)0}, + {C_NONE, "NONE", (char *)0}, + {C_IN, (char *)0, (char *)0} +}; + +/* + * Names of message sections. + */ +const struct res_sym __p_default_section_syms[] = { + {ns_s_qd, "QUERY", (char *)0}, + {ns_s_an, "ANSWER", (char *)0}, + {ns_s_ns, "AUTHORITY", (char *)0}, + {ns_s_ar, "ADDITIONAL", (char *)0}, + {0, (char *)0, (char *)0} +}; + +const struct res_sym __p_update_section_syms[] = { + {S_ZONE, "ZONE", (char *)0}, + {S_PREREQ, "PREREQUISITE", (char *)0}, + {S_UPDATE, "UPDATE", (char *)0}, + {S_ADDT, "ADDITIONAL", (char *)0}, + {0, (char *)0, (char *)0} +}; + +const struct res_sym __p_key_syms[] = { + {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"}, + {NS_ALG_DH, "DH", "Diffie Hellman"}, + {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"}, + {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"}, + {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"}, + {0, NULL, NULL} +}; + +const struct res_sym __p_cert_syms[] = { + {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"}, + {cert_t_spki, "SPKI", "SPKI certificate"}, + {cert_t_pgp, "PGP", "PGP certificate"}, + {cert_t_url, "URL", "URL Private"}, + {cert_t_oid, "OID", "OID Private"}, + {0, NULL, NULL} +}; + +/* + * Names of RR types and qtypes. Types and qtypes are the same, except + * that T_ANY is a qtype but not a type. (You can ask for records of type + * T_ANY, but you can't have any records of that type in the database.) + */ +const struct res_sym __p_type_syms[] = { + {ns_t_a, "A", "address"}, + {ns_t_ns, "NS", "name server"}, + {ns_t_md, "MD", "mail destination (deprecated)"}, + {ns_t_mf, "MF", "mail forwarder (deprecated)"}, + {ns_t_cname, "CNAME", "canonical name"}, + {ns_t_soa, "SOA", "start of authority"}, + {ns_t_mb, "MB", "mailbox"}, + {ns_t_mg, "MG", "mail group member"}, + {ns_t_mr, "MR", "mail rename"}, + {ns_t_null, "NULL", "null"}, + {ns_t_wks, "WKS", "well-known service (deprecated)"}, + {ns_t_ptr, "PTR", "domain name pointer"}, + {ns_t_hinfo, "HINFO", "host information"}, + {ns_t_minfo, "MINFO", "mailbox information"}, + {ns_t_mx, "MX", "mail exchanger"}, + {ns_t_txt, "TXT", "text"}, + {ns_t_rp, "RP", "responsible person"}, + {ns_t_afsdb, "AFSDB", "DCE or AFS server"}, + {ns_t_x25, "X25", "X25 address"}, + {ns_t_isdn, "ISDN", "ISDN address"}, + {ns_t_rt, "RT", "router"}, + {ns_t_nsap, "NSAP", "nsap address"}, + {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"}, + {ns_t_sig, "SIG", "signature"}, + {ns_t_key, "KEY", "key"}, + {ns_t_px, "PX", "mapping information"}, + {ns_t_gpos, "GPOS", "geographical position (withdrawn)"}, + {ns_t_aaaa, "AAAA", "IPv6 address"}, + {ns_t_loc, "LOC", "location"}, + {ns_t_nxt, "NXT", "next valid name (unimplemented)"}, + {ns_t_eid, "EID", "endpoint identifier (unimplemented)"}, + {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"}, + {ns_t_srv, "SRV", "server selection"}, + {ns_t_atma, "ATMA", "ATM address (unimplemented)"}, + {ns_t_tkey, "TKEY", "tkey"}, + {ns_t_tsig, "TSIG", "transaction signature"}, + {ns_t_ixfr, "IXFR", "incremental zone transfer"}, + {ns_t_axfr, "AXFR", "zone transfer"}, + {ns_t_zxfr, "ZXFR", "compressed zone transfer"}, + {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"}, + {ns_t_maila, "MAILA", "mail agent (deprecated)"}, + {ns_t_naptr, "NAPTR", "URN Naming Authority"}, + {ns_t_kx, "KX", "Key Exchange"}, + {ns_t_cert, "CERT", "Certificate"}, + {ns_t_a6, "A6", "IPv6 Address"}, + {ns_t_dname, "DNAME", "dname"}, + {ns_t_sink, "SINK", "Kitchen Sink (experimental)"}, + {ns_t_opt, "OPT", "EDNS Options"}, + {ns_t_any, "ANY", "\"any\""}, + {0, NULL, NULL} +}; + +/* + * Names of DNS rcodes. + */ +const struct res_sym __p_rcode_syms[] = { + {ns_r_noerror, "NOERROR", "no error"}, + {ns_r_formerr, "FORMERR", "format error"}, + {ns_r_servfail, "SERVFAIL", "server failed"}, + {ns_r_nxdomain, "NXDOMAIN", "no such domain name"}, + {ns_r_notimpl, "NOTIMP", "not implemented"}, + {ns_r_refused, "REFUSED", "refused"}, + {ns_r_yxdomain, "YXDOMAIN", "domain name exists"}, + {ns_r_yxrrset, "YXRRSET", "rrset exists"}, + {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"}, + {ns_r_notauth, "NOTAUTH", "not authoritative"}, + {ns_r_notzone, "NOTZONE", "Not in zone"}, + {ns_r_max, "", ""}, + {ns_r_badsig, "BADSIG", "bad signature"}, + {ns_r_badkey, "BADKEY", "bad key"}, + {ns_r_badtime, "BADTIME", "bad time"}, + {0, NULL, NULL} +}; + +int +sym_ston(const struct res_sym *syms, const char *name, int *success) { + for ((void)NULL; syms->name != 0; syms++) { + if (strcasecmp (name, syms->name) == 0) { + if (success) + *success = 1; + return (syms->number); + } + } + if (success) + *success = 0; + return (syms->number); /* The default value. */ +} + +const char * +sym_ntos(const struct res_sym *syms, int number, int *success) { +#ifdef SUNW_MT_RESOLVER + char *unname = sym_ntos_unname; +#else + static char unname[20]; +#endif /* SUNW_MT_RESOLVER */ + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->name); + } + } + + sprintf(unname, "%d", number); /* XXX nonreentrant */ + if (success) + *success = 0; + return (unname); +} + +const char * +sym_ntop(const struct res_sym *syms, int number, int *success) { +#ifdef SUNW_MT_RESOLVER + char *unname = sym_ntop_unname; +#else + static char unname[20]; +#endif /* SUNW_MT_RESOLVER */ + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->humanname); + } + } + sprintf(unname, "%d", number); /* XXX nonreentrant */ + if (success) + *success = 0; + return (unname); +} + +/* + * Return a string for the type. + */ +const char * +p_type(int type) { + int success; + const char *result; + static char typebuf[20]; + + result = sym_ntos(__p_type_syms, type, &success); + if (success) + return (result); + if (type < 0 || type > 0xfff) + return ("BADTYPE"); + sprintf(typebuf, "TYPE%d", type); + return (typebuf); +} + +/* + * Return a string for the type. + */ +const char * +p_section(int section, int opcode) { + const struct res_sym *symbols; + + switch (opcode) { + case ns_o_update: + symbols = __p_update_section_syms; + break; + default: + symbols = __p_default_section_syms; + break; + } + return (sym_ntos(symbols, section, (int *)0)); +} + +/* + * Return a mnemonic for class. + */ +const char * +p_class(int class) { + int success; + const char *result; + static char classbuf[20]; + + result = sym_ntos(__p_class_syms, class, &success); + if (success) + return (result); + if (class < 0 || class > 0xfff) + return ("BADCLASS"); + sprintf(classbuf, "CLASS%d", class); + return (classbuf); +} + +/* + * Return a mnemonic for an option + */ +const char * +#ifdef ORIGINAL_ISC_CODE +p_option(u_long option) { +#else +p_option(u_int option) { +#endif +#ifdef SUNW_MT_RESOLVER + char *nbuf = p_option_nbuf; +#else + static char nbuf[40]; +#endif /* SUNW_MT_RESOLVER */ + + switch (option) { + case RES_INIT: return "init"; + case RES_DEBUG: return "debug"; + case RES_AAONLY: return "aaonly(unimpl)"; + case RES_USEVC: return "usevc"; + case RES_PRIMARY: return "primry(unimpl)"; + case RES_IGNTC: return "igntc"; + case RES_RECURSE: return "recurs"; + case RES_DEFNAMES: return "defnam"; + case RES_STAYOPEN: return "styopn"; + case RES_DNSRCH: return "dnsrch"; + case RES_INSECURE1: return "insecure1"; + case RES_INSECURE2: return "insecure2"; + case RES_NOALIASES: return "noaliases"; + case RES_USE_INET6: return "inet6"; +#ifdef RES_USE_EDNS0 /* KAME extension */ + case RES_USE_EDNS0: return "edns0"; +#endif +#ifdef RES_USE_DNAME + case RES_USE_DNAME: return "dname"; +#endif +#ifdef RES_USE_DNSSEC + case RES_USE_DNSSEC: return "dnssec"; +#endif +#ifdef RES_NOTLDQUERY + case RES_NOTLDQUERY: return "no-tld-query"; +#endif +#ifdef ORIGINAL_ISC_CODE + /* XXX nonreentrant */ + default: sprintf(nbuf, "?0x%lx?", (u_long)option); +#else + default: sprintf(nbuf, "?0x%x?", (u_int)option); +#endif + return (nbuf); + } +} + +/* + * Return a mnemonic for a time to live. + */ +const char * +p_time(u_int32_t value) { +#ifdef SUNW_MT_RESOLVER + char *nbuf = p_time_nbuf; +#else + static char nbuf[40]; /* XXX nonreentrant */ +#endif /* SUNW_MT_RESOLVER */ + + if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) + sprintf(nbuf, "%u", value); + return (nbuf); +} + +/* + * Return a string for the rcode. + */ +const char * +p_rcode(int rcode) { + return (sym_ntos(__p_rcode_syms, rcode, (int *)0)); +} + +/* + * Return a string for a res_sockaddr_union. + */ +const char * +p_sockun(union res_sockaddr_union u, char *buf, size_t size) { + char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"]; + + switch (u.sin.sin_family) { + case AF_INET: + inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret); + break; +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret); + break; +#endif + default: + sprintf(ret, "[af%d]", u.sin.sin_family); + break; + } + if (size > 0) { + strncpy(buf, ret, size - 1); + buf[size - 1] = '0'; + } + return (buf); +} + +/* + * routines to convert between on-the-wire RR format and zone file format. + * Does not contain conversion to/from decimal degrees; divide or multiply + * by 60*60*1000 for that. + */ + +static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, + 1000000,10000000,100000000,1000000000}; + +/* takes an XeY precision/size value, returns a string representation. */ +static const char * +precsize_ntoa(prec) + u_int8_t prec; +{ +#ifdef SUNW_MT_RESOLVER + char *retbuf = precsize_ntoa_retbuf; +#else + static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */ +#endif /* SUNW_MT_RESOLVER */ + unsigned long val; + int mantissa, exponent; + + mantissa = (int)((prec >> 4) & 0x0f) % 10; + exponent = (int)((prec >> 0) & 0x0f) % 10; + + val = mantissa * poweroften[exponent]; + + (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100); + return (retbuf); +} + +/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ +static u_int8_t +precsize_aton(const char **strptr) { + unsigned int mval = 0, cmval = 0; + u_int8_t retval = 0; + const char *cp; + int exponent; + int mantissa; + + cp = *strptr; + + while (isdigit((unsigned char)*cp)) + mval = mval * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* centimeters */ + cp++; + if (isdigit((unsigned char)*cp)) { + cmval = (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + cmval += (*cp++ - '0'); + } + } + } + cmval = (mval * 100) + cmval; + + for (exponent = 0; exponent < 9; exponent++) + if (cmval < poweroften[exponent+1]) + break; + + mantissa = cmval / poweroften[exponent]; + if (mantissa > 9) + mantissa = 9; + + retval = (mantissa << 4) | exponent; + + *strptr = cp; + + return (retval); +} + +/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */ +static u_int32_t +latlon2ul(const char **latlonstrptr, int *which) { + const char *cp; + u_int32_t retval; + int deg = 0, min = 0, secs = 0, secsfrac = 0; + + cp = *latlonstrptr; + + while (isdigit((unsigned char)*cp)) + deg = deg * 10 + (*cp++ - '0'); + + while (isspace((unsigned char)*cp)) + cp++; + + if (!(isdigit((unsigned char)*cp))) + goto fndhemi; + + while (isdigit((unsigned char)*cp)) + min = min * 10 + (*cp++ - '0'); + + while (isspace((unsigned char)*cp)) + cp++; + + if (!(isdigit((unsigned char)*cp))) + goto fndhemi; + + while (isdigit((unsigned char)*cp)) + secs = secs * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal seconds */ + cp++; + if (isdigit((unsigned char)*cp)) { + secsfrac = (*cp++ - '0') * 100; + if (isdigit((unsigned char)*cp)) { + secsfrac += (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + secsfrac += (*cp++ - '0'); + } + } + } + } + + while (!isspace((unsigned char)*cp)) /* if any trailing garbage */ + cp++; + + while (isspace((unsigned char)*cp)) + cp++; + + fndhemi: + switch (*cp) { + case 'N': case 'n': + case 'E': case 'e': + retval = ((unsigned)1<<31) + + (((((deg * 60) + min) * 60) + secs) * 1000) + + secsfrac; + break; + case 'S': case 's': + case 'W': case 'w': + retval = ((unsigned)1<<31) + - (((((deg * 60) + min) * 60) + secs) * 1000) + - secsfrac; + break; + default: + retval = 0; /* invalid value -- indicates error */ + break; + } + + switch (*cp) { + case 'N': case 'n': + case 'S': case 's': + *which = 1; /* latitude */ + break; + case 'E': case 'e': + case 'W': case 'w': + *which = 2; /* longitude */ + break; + default: + *which = 0; /* error */ + break; + } + + cp++; /* skip the hemisphere */ + + while (!isspace((unsigned char)*cp)) /* if any trailing garbage */ + cp++; + + while (isspace((unsigned char)*cp)) /* move to next field */ + cp++; + + *latlonstrptr = cp; + + return (retval); +} + +/* converts a zone file representation in a string to an RDATA on-the-wire + * representation. */ +int +loc_aton(ascii, binary) + const char *ascii; + u_char *binary; +{ + const char *cp, *maxcp; + u_char *bcp; + + u_int32_t latit = 0, longit = 0, alt = 0; + u_int32_t lltemp1 = 0, lltemp2 = 0; + int altmeters = 0, altfrac = 0, altsign = 1; + u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ + u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ + u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ + int which1 = 0, which2 = 0; + + cp = ascii; + maxcp = cp + strlen(ascii); + + lltemp1 = latlon2ul(&cp, &which1); + + lltemp2 = latlon2ul(&cp, &which2); + + switch (which1 + which2) { + case 3: /* 1 + 2, the only valid combination */ + if ((which1 == 1) && (which2 == 2)) { /* normal case */ + latit = lltemp1; + longit = lltemp2; + } else if ((which1 == 2) && (which2 == 1)) { /* reversed */ + longit = lltemp1; + latit = lltemp2; + } else { /* some kind of brokenness */ + return (0); + } + break; + default: /* we didn't get one of each */ + return (0); + } + + /* altitude */ + if (*cp == '-') { + altsign = -1; + cp++; + } + + if (*cp == '+') + cp++; + + while (isdigit((unsigned char)*cp)) + altmeters = altmeters * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal meters */ + cp++; + if (isdigit((unsigned char)*cp)) { + altfrac = (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + altfrac += (*cp++ - '0'); + } + } + } + + alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + siz = precsize_aton(&cp); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + hp = precsize_aton(&cp); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + vp = precsize_aton(&cp); + + defaults: + + bcp = binary; + *bcp++ = (u_int8_t) 0; /* version byte */ + *bcp++ = siz; + *bcp++ = hp; + *bcp++ = vp; + PUTLONG(latit,bcp); + PUTLONG(longit,bcp); + PUTLONG(alt,bcp); + + return (16); /* size of RR in octets */ +} + +/* takes an on-the-wire LOC RR and formats it in a human readable format. */ +const char * +loc_ntoa(binary, ascii) + const u_char *binary; + char *ascii; +{ + static const char *error = "?"; +#ifdef SUNW_MT_RESOLVER + char *tmpbuf = loc_ntoa_tmpbuf; +#else + static char tmpbuf[sizeof +"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; +#endif /* SUNW_MT_RESOLVER */ + const u_char *cp = binary; + + int latdeg, latmin, latsec, latsecfrac; + int longdeg, longmin, longsec, longsecfrac; + char northsouth, eastwest; + const char *altsign; + int altmeters, altfrac; + + const u_int32_t referencealt = 100000 * 100; + + int32_t latval, longval, altval; + u_int32_t templ; + u_int8_t sizeval, hpval, vpval, versionval; + + char *sizestr, *hpstr, *vpstr; + + versionval = *cp++; + + if (ascii == NULL) + ascii = tmpbuf; + + if (versionval) { + (void) sprintf(ascii, "; error: unknown LOC RR version"); + return (ascii); + } + + sizeval = *cp++; + + hpval = *cp++; + vpval = *cp++; + + GETLONG(templ, cp); + latval = (templ - ((unsigned)1<<31)); + + GETLONG(templ, cp); + longval = (templ - ((unsigned)1<<31)); + + GETLONG(templ, cp); + if (templ < referencealt) { /* below WGS 84 spheroid */ + altval = referencealt - templ; + altsign = "-"; + } else { + altval = templ - referencealt; + altsign = ""; + } + + if (latval < 0) { + northsouth = 'S'; + latval = -latval; + } else + northsouth = 'N'; + + latsecfrac = latval % 1000; + latval = latval / 1000; + latsec = latval % 60; + latval = latval / 60; + latmin = latval % 60; + latval = latval / 60; + latdeg = latval; + + if (longval < 0) { + eastwest = 'W'; + longval = -longval; + } else + eastwest = 'E'; + + longsecfrac = longval % 1000; + longval = longval / 1000; + longsec = longval % 60; + longval = longval / 60; + longmin = longval % 60; + longval = longval / 60; + longdeg = longval; + + altfrac = altval % 100; + altmeters = (altval / 100); + + sizestr = strdup(precsize_ntoa(sizeval)); + hpstr = strdup(precsize_ntoa(hpval)); + vpstr = strdup(precsize_ntoa(vpval)); + + sprintf(ascii, + "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm", + latdeg, latmin, latsec, latsecfrac, northsouth, + longdeg, longmin, longsec, longsecfrac, eastwest, + altsign, altmeters, altfrac, + (sizestr != NULL) ? sizestr : error, + (hpstr != NULL) ? hpstr : error, + (vpstr != NULL) ? vpstr : error); + + if (sizestr != NULL) + free(sizestr); + if (hpstr != NULL) + free(hpstr); + if (vpstr != NULL) + free(vpstr); + + return (ascii); +} + + +/* Return the number of DNS hierarchy levels in the name. */ +int +dn_count_labels(const char *name) { + int i, len, count; + + len = strlen(name); + for (i = 0, count = 0; i < len; i++) { + /* XXX need to check for \. or use named's nlabels(). */ + if (name[i] == '.') + count++; + } + + /* don't count initial wildcard */ + if (name[0] == '*') + if (count) + count--; + + /* don't count the null label for root. */ + /* if terminating '.' not found, must adjust */ + /* count to include last label */ + if (len > 0 && name[len-1] != '.') + count++; + return (count); +} + + +/* + * Make dates expressed in seconds-since-Jan-1-1970 easy to read. + * SIG records are required to be printed like this, by the Secure DNS RFC. + */ +char * +#ifdef ORIGINAL_ISC_CODE +p_secstodate (u_long secs) { +#else +p_secstodate (u_int secs) { +#endif +#ifdef SUNW_MT_RESOLVER + char *output = p_secstodate_output; +#else + /* XXX nonreentrant */ + static char output[15]; /* YYYYMMDDHHMMSS and null */ +#endif /* SUNW_MT_RESOLVER */ + time_t clock = secs; + struct tm *time; + +#ifdef HAVE_TIME_R + gmtime_r(&clock, &time); +#else + time = gmtime(&clock); +#endif + time->tm_year += 1900; + time->tm_mon += 1; + sprintf(output, "%04d%02d%02d%02d%02d%02d", + time->tm_year, time->tm_mon, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); + return (output); +} + +u_int16_t +res_nametoclass(const char *buf, int *successp) { + unsigned long result; + char *endptr; + int success; + + result = sym_ston(__p_class_syms, buf, &success); + if (success) + goto done; + + if (strncasecmp(buf, "CLASS", 5) != 0 || + !isdigit((unsigned char)buf[5])) + goto done; + errno = 0; + result = strtoul(buf + 5, &endptr, 10); + if (errno == 0 && *endptr == '\0' && result <= 0xffff) + success = 1; + done: + if (successp) + *successp = success; + return (result); +} + +u_int16_t +res_nametotype(const char *buf, int *successp) { + unsigned long result; + char *endptr; + int success; + + result = sym_ston(__p_type_syms, buf, &success); + if (success) + goto done; + + if (strncasecmp(buf, "type", 4) != 0 || + !isdigit((unsigned char)buf[4])) + goto done; + errno = 0; + result = strtoul(buf + 4, &endptr, 10); + if (errno == 0 && *endptr == '\0' && result <= 0xffff) + success = 1; + done: + if (successp) + *successp = success; + return (result); +} diff --git a/usr/src/lib/libresolv2/common/resolv/res_debug.h b/usr/src/lib/libresolv2/common/resolv/res_debug.h new file mode 100644 index 0000000000..1395d7a207 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_debug.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef _RES_DEBUG_H_ +#define _RES_DEBUG_H_ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef DEBUG +# define Dprint(cond, args) /*empty*/ +# define DprintQ(cond, args, query, size) /*empty*/ +# define Aerror(statp, file, string, error, address) /*empty*/ +# define Perror(statp, file, string, error) /*empty*/ +#else +# define Dprint(cond, args) if (cond) {fprintf args;} else {} +# define DprintQ(cond, args, query, size) if (cond) {\ + fprintf args;\ + res_pquery(statp, query, size, stdout);\ + } else {} +#endif + +#endif /* _RES_DEBUG_H_ */ diff --git a/usr/src/lib/libresolv2/common/resolv/res_findzonecut.c b/usr/src/lib/libresolv2/common/resolv/res_findzonecut.c new file mode 100644 index 0000000000..65be96235b --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_findzonecut.c @@ -0,0 +1,729 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_findzonecut.c,v 8.20 2003/05/27 23:36:53 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* Import. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/list.h> + +#include "port_after.h" + +#include <resolv.h> + +/* Data structures. */ + +typedef struct rr_a { + LINK(struct rr_a) link; + union res_sockaddr_union addr; +} rr_a; +typedef LIST(rr_a) rrset_a; + +typedef struct rr_ns { + LINK(struct rr_ns) link; + const char * name; + unsigned int flags; + rrset_a addrs; +} rr_ns; +typedef LIST(rr_ns) rrset_ns; + +#define RR_NS_HAVE_V4 0x01 +#define RR_NS_HAVE_V6 0x02 + +/* Forward. */ + +static int satisfy(res_state, const char *, rrset_ns *, + union res_sockaddr_union *, int); +static int add_addrs(res_state, rr_ns *, + union res_sockaddr_union *, int); +static int get_soa(res_state, const char *, ns_class, int, + char *, size_t, char *, size_t, + rrset_ns *); +static int get_ns(res_state, const char *, ns_class, int, rrset_ns *); +static int get_glue(res_state, ns_class, int, rrset_ns *); +static int save_ns(res_state, ns_msg *, ns_sect, + const char *, ns_class, int, rrset_ns *); +static int save_a(res_state, ns_msg *, ns_sect, + const char *, ns_class, int, rr_ns *); +static void free_nsrrset(rrset_ns *); +static void free_nsrr(rrset_ns *, rr_ns *); +static rr_ns * find_ns(rrset_ns *, const char *); +static int do_query(res_state, const char *, ns_class, ns_type, + u_char *, ns_msg *); +static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2); + +/* Macros. */ + +#define DPRINTF(x) do {\ + int save_errno = errno; \ + if ((statp->options & RES_DEBUG) != 0) res_dprintf x; \ + errno = save_errno; \ + } while (0) + +/* Public. */ + +/* + * int + * res_findzonecut(res, dname, class, zname, zsize, addrs, naddrs) + * find enclosing zone for a <dname,class>, and some server addresses + * parameters: + * res - resolver context to work within (is modified) + * dname - domain name whose enclosing zone is desired + * class - class of dname (and its enclosing zone) + * zname - found zone name + * zsize - allocated size of zname + * addrs - found server addresses + * naddrs - max number of addrs + * return values: + * < 0 - an error occurred (check errno) + * = 0 - zname is now valid, but addrs[] wasn't changed + * > 0 - zname is now valid, and return value is number of addrs[] found + * notes: + * this function calls res_nsend() which means it depends on correctly + * functioning recursive nameservers (usually defined in /etc/resolv.conf + * or its local equivilent). + * + * we start by asking for an SOA<dname,class>. if we get one as an + * answer, that just means <dname,class> is a zone top, which is fine. + * more than likely we'll be told to go pound sand, in the form of a + * negative answer. + * + * note that we are not prepared to deal with referrals since that would + * only come from authority servers and our correctly functioning local + * recursive server would have followed the referral and got us something + * more definite. + * + * if the authority section contains an SOA, this SOA should also be the + * closest enclosing zone, since any intermediary zone cuts would've been + * returned as referrals and dealt with by our correctly functioning local + * recursive name server. but an SOA in the authority section should NOT + * match our dname (since that would have been returned in the answer + * section). an authority section SOA has to be "above" our dname. + * + * however, since authority section SOA's were once optional, it's + * possible that we'll have to go hunting for the enclosing SOA by + * ripping labels off the front of our dname -- this is known as "doing + * it the hard way." + * + * ultimately we want some server addresses, which are ideally the ones + * pertaining to the SOA.MNAME, but only if there is a matching NS RR. + * so the second phase (after we find an SOA) is to go looking for the + * NS RRset for that SOA's zone. + * + * no answer section processed by this code is allowed to contain CNAME + * or DNAME RR's. for the SOA query this means we strip a label and + * keep going. for the NS and A queries this means we just give up. + */ + +int +res_findzonecut(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, struct in_addr *addrs, int naddrs) +{ + int result, i; + union res_sockaddr_union *u; + + + opts |= RES_IPV4ONLY; + opts &= ~RES_IPV6ONLY; + + u = calloc(naddrs, sizeof(*u)); + if (u == NULL) + return(-1); + + result = res_findzonecut2(statp, dname, class, opts, zname, zsize, + u, naddrs); + + for (i = 0; i < result; i++) { + addrs[i] = u[i].sin.sin_addr; + } + free(u); + return (result); +} + +int +res_findzonecut2(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, union res_sockaddr_union *addrs, + int naddrs) +{ + char mname[NS_MAXDNAME]; + u_long save_pfcode; + rrset_ns nsrrs; + int n; + + DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d", + dname, p_class(class), (long)zsize, naddrs)); + save_pfcode = statp->pfcode; + statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX | + RES_PRF_QUES | RES_PRF_ANS | + RES_PRF_AUTH | RES_PRF_ADD; + INIT_LIST(nsrrs); + + DPRINTF(("get the soa, and see if it has enough glue")); + if ((n = get_soa(statp, dname, class, opts, zname, zsize, + mname, sizeof mname, &nsrrs)) < 0 || + ((opts & RES_EXHAUSTIVE) == 0 && + (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0)) + goto done; + + DPRINTF(("get the ns rrset and see if it has enough glue")); + if ((n = get_ns(statp, zname, class, opts, &nsrrs)) < 0 || + ((opts & RES_EXHAUSTIVE) == 0 && + (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0)) + goto done; + + DPRINTF(("get the missing glue and see if it's finally enough")); + if ((n = get_glue(statp, class, opts, &nsrrs)) >= 0) + n = satisfy(statp, mname, &nsrrs, addrs, naddrs); + + done: + DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK")); + free_nsrrset(&nsrrs); + statp->pfcode = save_pfcode; + return (n); +} + +/* Private. */ + +static int +satisfy(res_state statp, const char *mname, rrset_ns *nsrrsp, + union res_sockaddr_union *addrs, int naddrs) +{ + rr_ns *nsrr; + int n, x; + + n = 0; + nsrr = find_ns(nsrrsp, mname); + if (nsrr != NULL) { + x = add_addrs(statp, nsrr, addrs, naddrs); + addrs += x; + naddrs -= x; + n += x; + } + for (nsrr = HEAD(*nsrrsp); + nsrr != NULL && naddrs > 0; + nsrr = NEXT(nsrr, link)) + if (ns_samename(nsrr->name, mname) != 1) { + x = add_addrs(statp, nsrr, addrs, naddrs); + addrs += x; + naddrs -= x; + n += x; + } + DPRINTF(("satisfy(%s): %d", mname, n)); + return (n); +} + +static int +add_addrs(res_state statp, rr_ns *nsrr, + union res_sockaddr_union *addrs, int naddrs) +{ + rr_a *arr; + int n = 0; + + for (arr = HEAD(nsrr->addrs); arr != NULL; arr = NEXT(arr, link)) { + if (naddrs <= 0) + return (0); + *addrs++ = arr->addr; + naddrs--; + n++; + } + DPRINTF(("add_addrs: %d", n)); + return (n); +} + +static int +get_soa(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, char *mname, size_t msize, + rrset_ns *nsrrsp) +{ + char tname[NS_MAXDNAME]; + u_char *resp = NULL; + int n, i, ancount, nscount; + ns_sect sect; + ns_msg msg; + u_int rcode; + + /* + * Find closest enclosing SOA, even if it's for the root zone. + */ + + /* First canonicalize dname (exactly one unescaped trailing "."). */ + if (ns_makecanon(dname, tname, sizeof tname) < 0) + goto cleanup; + dname = tname; + + resp = malloc(NS_MAXMSG); + if (resp == NULL) + goto cleanup; + + /* Now grovel the subdomains, hunting for an SOA answer or auth. */ + for (;;) { + /* Leading or inter-label '.' are skipped here. */ + while (*dname == '.') + dname++; + + /* Is there an SOA? */ + n = do_query(statp, dname, class, ns_t_soa, resp, &msg); + if (n < 0) { + DPRINTF(("get_soa: do_query('%s', %s) failed (%d)", + dname, p_class(class), n)); + goto cleanup; + } + if (n > 0) { + DPRINTF(("get_soa: CNAME or DNAME found")); + sect = ns_s_max, n = 0; + } else { + rcode = ns_msg_getflag(msg, ns_f_rcode); + ancount = ns_msg_count(msg, ns_s_an); + nscount = ns_msg_count(msg, ns_s_ns); + if (ancount > 0 && rcode == ns_r_noerror) + sect = ns_s_an, n = ancount; + else if (nscount > 0) + sect = ns_s_ns, n = nscount; + else + sect = ns_s_max, n = 0; + } + for (i = 0; i < n; i++) { + const char *t; + const u_char *rdata; + int rdlen; + ns_rr rr; + + if (ns_parserr(&msg, sect, i, &rr) < 0) { + DPRINTF(("get_soa: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + goto cleanup; + } + if (ns_rr_type(rr) == ns_t_cname || + ns_rr_type(rr) == ns_t_dname) + break; + if (ns_rr_type(rr) != ns_t_soa || + ns_rr_class(rr) != class) + continue; + t = ns_rr_name(rr); + switch (sect) { + case ns_s_an: + if (ns_samedomain(dname, t) == 0) { + DPRINTF( + ("get_soa: ns_samedomain('%s', '%s') == 0", + dname, t) + ); + errno = EPROTOTYPE; + goto cleanup; + } + break; + case ns_s_ns: + if (ns_samename(dname, t) == 1 || + ns_samedomain(dname, t) == 0) { + DPRINTF( + ("get_soa: ns_samename() || !ns_samedomain('%s', '%s')", + dname, t) + ); + errno = EPROTOTYPE; + goto cleanup; + } + break; + default: + abort(); + } + if (strlen(t) + 1 > zsize) { + DPRINTF(("get_soa: zname(%d) too small (%d)", + zsize, strlen(t) + 1)); + errno = EMSGSIZE; + goto cleanup; + } + strcpy(zname, t); + rdata = ns_rr_rdata(rr); + rdlen = ns_rr_rdlen(rr); + if (ns_name_uncompress(resp, ns_msg_end(msg), rdata, + mname, msize) < 0) { + DPRINTF(("get_soa: ns_name_uncompress failed") + ); + goto cleanup; + } + if (save_ns(statp, &msg, ns_s_ns, + zname, class, opts, nsrrsp) < 0) { + DPRINTF(("get_soa: save_ns failed")); + goto cleanup; + } + free(resp); + return (0); + } + + /* If we're out of labels, then not even "." has an SOA! */ + if (*dname == '\0') + break; + + /* Find label-terminating "."; top of loop will skip it. */ + while (*dname != '.') { + if (*dname == '\\') + if (*++dname == '\0') { + errno = EMSGSIZE; + goto cleanup; + } + dname++; + } + } + DPRINTF(("get_soa: out of labels")); + errno = EDESTADDRREQ; + cleanup: + if (resp != NULL) + free(resp); + return (-1); +} + +static int +get_ns(res_state statp, const char *zname, ns_class class, int opts, + rrset_ns *nsrrsp) +{ + u_char *resp; + ns_msg msg; + int n; + + resp = malloc(NS_MAXMSG); + if (resp == NULL) + return (-1); + + /* Go and get the NS RRs for this zone. */ + n = do_query(statp, zname, class, ns_t_ns, resp, &msg); + if (n != 0) { + DPRINTF(("get_ns: do_query('%s', %s) failed (%d)", + zname, p_class(class), n)); + free(resp); + return (-1); + } + + /* Remember the NS RRs and associated A RRs that came back. */ + if (save_ns(statp, &msg, ns_s_an, zname, class, opts, nsrrsp) < 0) { + DPRINTF(("get_ns save_ns('%s', %s) failed", + zname, p_class(class))); + free(resp); + return (-1); + } + + free(resp); + return (0); +} + +static int +get_glue(res_state statp, ns_class class, int opts, rrset_ns *nsrrsp) { + rr_ns *nsrr, *nsrr_n; + u_char *resp; + + resp = malloc(NS_MAXMSG); + if (resp == NULL) + return(-1); + + /* Go and get the A RRs for each empty NS RR on our list. */ + for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) { + ns_msg msg; + int n; + + nsrr_n = NEXT(nsrr, link); + + if ((nsrr->flags & RR_NS_HAVE_V4) == 0) { + n = do_query(statp, nsrr->name, class, ns_t_a, + resp, &msg); + if (n < 0) { + DPRINTF( + ("get_glue: do_query('%s', %s') failed", + nsrr->name, p_class(class))); + goto cleanup; + } + if (n > 0) { + DPRINTF(( + "get_glue: do_query('%s', %s') CNAME or DNAME found", + nsrr->name, p_class(class))); + } + if (save_a(statp, &msg, ns_s_an, nsrr->name, class, + opts, nsrr) < 0) { + DPRINTF(("get_glue: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + goto cleanup; + } + } + + if ((nsrr->flags & RR_NS_HAVE_V6) == 0) { + n = do_query(statp, nsrr->name, class, ns_t_aaaa, + resp, &msg); + if (n < 0) { + DPRINTF( + ("get_glue: do_query('%s', %s') failed", + nsrr->name, p_class(class))); + goto cleanup; + } + if (n > 0) { + DPRINTF(( + "get_glue: do_query('%s', %s') CNAME or DNAME found", + nsrr->name, p_class(class))); + } + if (save_a(statp, &msg, ns_s_an, nsrr->name, class, + opts, nsrr) < 0) { + DPRINTF(("get_glue: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + goto cleanup; + } + } + + /* If it's still empty, it's just chaff. */ + if (EMPTY(nsrr->addrs)) { + DPRINTF(("get_glue: removing empty '%s' NS", + nsrr->name)); + free_nsrr(nsrrsp, nsrr); + } + } + free(resp); + return (0); + + cleanup: + free(resp); + return (-1); +} + +static int +save_ns(res_state statp, ns_msg *msg, ns_sect sect, + const char *owner, ns_class class, int opts, + rrset_ns *nsrrsp) +{ + int i; + + for (i = 0; i < ns_msg_count(*msg, sect); i++) { + char tname[MAXDNAME]; + const u_char *rdata; + rr_ns *nsrr; + ns_rr rr; + int rdlen; + + if (ns_parserr(msg, sect, i, &rr) < 0) { + DPRINTF(("save_ns: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + return (-1); + } + if (ns_rr_type(rr) != ns_t_ns || + ns_rr_class(rr) != class || + ns_samename(ns_rr_name(rr), owner) != 1) + continue; + nsrr = find_ns(nsrrsp, ns_rr_name(rr)); + if (nsrr == NULL) { + nsrr = malloc(sizeof *nsrr); + if (nsrr == NULL) { + DPRINTF(("save_ns: malloc failed")); + return (-1); + } + rdata = ns_rr_rdata(rr); + rdlen = ns_rr_rdlen(rr); + if (ns_name_uncompress(ns_msg_base(*msg), + ns_msg_end(*msg), rdata, + tname, sizeof tname) < 0) { + DPRINTF(("save_ns: ns_name_uncompress failed") + ); + free(nsrr); + return (-1); + } + nsrr->name = strdup(tname); + if (nsrr->name == NULL) { + DPRINTF(("save_ns: strdup failed")); + free(nsrr); + return (-1); + } + INIT_LINK(nsrr, link); + INIT_LIST(nsrr->addrs); + nsrr->flags = 0; + APPEND(*nsrrsp, nsrr, link); + } + if (save_a(statp, msg, ns_s_ar, + nsrr->name, class, opts, nsrr) < 0) { + DPRINTF(("save_ns: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + return (-1); + } + } + return (0); +} + +static int +save_a(res_state statp, ns_msg *msg, ns_sect sect, + const char *owner, ns_class class, int opts, + rr_ns *nsrr) +{ + int i; + + for (i = 0; i < ns_msg_count(*msg, sect); i++) { + ns_rr rr; + rr_a *arr; + + if (ns_parserr(msg, sect, i, &rr) < 0) { + DPRINTF(("save_a: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + return (-1); + } + if ((ns_rr_type(rr) != ns_t_a && + ns_rr_type(rr) != ns_t_aaaa) || + ns_rr_class(rr) != class || + ns_samename(ns_rr_name(rr), owner) != 1 || + ns_rr_rdlen(rr) != NS_INADDRSZ) + continue; + if ((opts & RES_IPV6ONLY) != 0 && ns_rr_type(rr) != ns_t_aaaa) + continue; + if ((opts & RES_IPV4ONLY) != 0 && ns_rr_type(rr) != ns_t_a) + continue; + arr = malloc(sizeof *arr); + if (arr == NULL) { + DPRINTF(("save_a: malloc failed")); + return (-1); + } + INIT_LINK(arr, link); + memset(&arr->addr, 0, sizeof(arr->addr)); + switch (ns_rr_type(rr)) { + case ns_t_a: + arr->addr.sin.sin_family = AF_INET; +#ifdef HAVE_SA_LEN + arr->addr.sin.sin_len = sizeof(arr->addr.sin); +#endif + memcpy(&arr->addr.sin.sin_addr, ns_rr_rdata(rr), + NS_INADDRSZ); + arr->addr.sin.sin_port = htons(NAMESERVER_PORT); + nsrr->flags |= RR_NS_HAVE_V4; + break; + case ns_t_aaaa: + arr->addr.sin6.sin6_family = AF_INET6; +#ifdef HAVE_SA_LEN + arr->addr.sin6.sin6_len = sizeof(arr->addr.sin6); +#endif + memcpy(&arr->addr.sin6.sin6_addr, ns_rr_rdata(rr), 16); + arr->addr.sin.sin_port = htons(NAMESERVER_PORT); + nsrr->flags |= RR_NS_HAVE_V6; + break; + default: + abort(); + } + APPEND(nsrr->addrs, arr, link); + } + return (0); +} + +static void +free_nsrrset(rrset_ns *nsrrsp) { + rr_ns *nsrr; + + while ((nsrr = HEAD(*nsrrsp)) != NULL) + free_nsrr(nsrrsp, nsrr); +} + +static void +free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) { + rr_a *arr; + char *tmp; + + while ((arr = HEAD(nsrr->addrs)) != NULL) { + UNLINK(nsrr->addrs, arr, link); + free(arr); + } + DE_CONST(nsrr->name, tmp); + free(tmp); + UNLINK(*nsrrsp, nsrr, link); + free(nsrr); +} + +static rr_ns * +find_ns(rrset_ns *nsrrsp, const char *dname) { + rr_ns *nsrr; + + for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = NEXT(nsrr, link)) + if (ns_samename(nsrr->name, dname) == 1) + return (nsrr); + return (NULL); +} + +static int +do_query(res_state statp, const char *dname, ns_class class, ns_type qtype, + u_char *resp, ns_msg *msg) +{ + u_char req[NS_PACKETSZ]; + int i, n; + + n = res_nmkquery(statp, ns_o_query, dname, class, qtype, + NULL, 0, NULL, req, NS_PACKETSZ); + if (n < 0) { + DPRINTF(("do_query: res_nmkquery failed")); + return (-1); + } + n = res_nsend(statp, req, n, resp, NS_MAXMSG); + if (n < 0) { + DPRINTF(("do_query: res_nsend failed")); + return (-1); + } + if (n == 0) { + DPRINTF(("do_query: res_nsend returned 0")); + errno = EMSGSIZE; + return (-1); + } + if (ns_initparse(resp, n, msg) < 0) { + DPRINTF(("do_query: ns_initparse failed")); + return (-1); + } + n = 0; + for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) { + ns_rr rr; + + if (ns_parserr(msg, ns_s_an, i, &rr) < 0) { + DPRINTF(("do_query: ns_parserr failed")); + return (-1); + } + n += (ns_rr_class(rr) == class && + (ns_rr_type(rr) == ns_t_cname || + ns_rr_type(rr) == ns_t_dname)); + } + return (n); +} + +static void +res_dprintf(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + fputs(";; res_findzonecut: ", stderr); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} diff --git a/usr/src/lib/libresolv2/common/resolv/res_init.c b/usr/src/lib/libresolv2/common/resolv/res_init.c new file mode 100644 index 0000000000..06b35591b1 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_init.c @@ -0,0 +1,897 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1985, 1989, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; +static const char rcsid[] = "$Id: res_init.c,v 8.32 2003/04/03 06:31:10 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> + +#include "port_after.h" +#ifdef SUNW_AVOIDSTDIO_FDLIMIT +#include "../../../libnsl/include/nsl_stdio_prv.h" +#endif + +/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ +#include <resolv.h> + +#include "res_private.h" + +/* Options. Should all be left alone. */ +#define RESOLVSORT +#define DEBUG + +#ifdef SUNW_INITCHKIF +#include <net/if.h> +#include <netinet/if_ether.h> +#include <sys/sockio.h> +#define MAXIFS 8192 +#endif /* SUNW_INITCHKIF */ + +#ifdef SUNW_DOMAINFROMNIS +#include <sys/systeminfo.h> +#include <string.h> +#endif /* SUNW_DOMAINFROMNIS */ + +#ifdef ORIGINAL_ISC_CODE +#else +#pragma weak __res_randomid = res_randomid +#endif /* ORIGINAL_ISC_CODE */ + +static void res_setoptions __P((res_state, const char *, const char *)); + +#ifdef RESOLVSORT +static const char sort_mask[] = "/&"; +#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) +static u_int32_t net_mask __P((struct in_addr)); +#endif + +#if !defined(isascii) /* XXX - could be a function */ +# define isascii(c) (!(c & 0200)) +#endif + +/* + * Resolver state default settings. + */ + +/* + * Set up default settings. If the configuration file exist, the values + * there will have precedence. Otherwise, the server address is set to + * INADDR_ANY and the default domain name comes from the gethostname(). + * + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server. It + * was later decided that since the recommended practice is to always + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. + * + * Return 0 if completes successfully, -1 on error + */ +int +res_ninit(res_state statp) { + extern int __res_vinit(res_state, int); + + return (__res_vinit(statp, 0)); +} + +/* This function has to be reachable by res_data.c but not publically. */ +int +__res_vinit(res_state statp, int preinit) { +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + register __NSL_FILE *fp; +#else + register FILE *fp; +#endif + register char *cp, **pp; + register int n; + char buf[BUFSIZ]; + int nserv = 0; /* number of nameserver records read from file */ + int haveenv = 0; + int havesearch = 0; +#ifdef RESOLVSORT + int nsort = 0; + char *net; +#endif + int dots; + union res_sockaddr_union u[2]; + + if (!preinit) { + statp->retrans = RES_TIMEOUT; + statp->retry = RES_DFLRETRY; + statp->options = RES_DEFAULT; + statp->id = res_randomid(); + } + + if ((statp->options & RES_INIT) != 0) + res_ndestroy(statp); + + memset(u, 0, sizeof(u)); +#ifdef USELOOPBACK + u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); +#else + u[nserv].sin.sin_addr.s_addr = INADDR_ANY; +#endif + u[nserv].sin.sin_family = AF_INET; + u[nserv].sin.sin_port = htons(NAMESERVER_PORT); +#ifdef HAVE_SA_LEN + u[nserv].sin.sin_len = sizeof(struct sockaddr_in); +#endif + nserv++; +#ifdef HAS_INET6_STRUCTS +#ifdef USELOOPBACK + u[nserv].sin6.sin6_addr = in6addr_loopback; +#else + u[nserv].sin6.sin6_addr = in6addr_any; +#endif + u[nserv].sin6.sin6_family = AF_INET6; + u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT); +#ifdef HAVE_SA_LEN + u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif + nserv++; +#endif + statp->nscount = 0; + statp->ndots = 1; + statp->pfcode = 0; + statp->_vcsock = -1; + statp->_flags = 0; + statp->qhook = NULL; + statp->rhook = NULL; + statp->_u._ext.nscount = 0; + statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); + if (statp->_u._ext.ext != NULL) { + memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); + statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; + strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); + strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); + } +#ifdef RESOLVSORT + statp->nsort = 0; +#endif + res_setservers(statp, u, nserv); + +#ifdef SUNW_INITCHKIF +/* + * Short circuit res_init() if no non-loopback interfaces are up. This is + * done to avoid boot delays if "dns" comes before "files" in nsswitch.conf. + * An additional fix has been added to this code, to count all external + * interfaces, which includes the IPv6 interfaces. If no external interfaces + * are found, an additional check is carried out to determine if any deprecated + * interfaces are up. + */ + { + int s; + struct lifnum lifn; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("res_init: socket"); + return (-1); + } + lifn.lifn_family = AF_UNSPEC; + lifn.lifn_flags = LIFC_EXTERNAL_SOURCE; + if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) { + close(s); + return (-1); + } + if (lifn.lifn_count == 0) { + /* + * Check if there are any deprecated interfaces up + */ + struct lifconf lifc; + uchar_t *buf; + int buflen, i, int_up = 0; + + lifn.lifn_flags = 0; + if ((ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) || + (lifn.lifn_count < 1)) { + close(s); + return (-1); + } + + buflen = lifn.lifn_count * sizeof (struct lifreq); + buf = (uchar_t *)malloc(buflen); + if (buf == NULL) { + close(s); + return (-1); + } + + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_flags = 0; + lifc.lifc_len = buflen; + lifc.lifc_lifcu.lifcu_buf = (caddr_t)buf; + if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) { + close(s); + free(buf); + return (-1); + } + + for (i = 0; i < lifn.lifn_count; ++i) { + struct lifreq *lreqp, lreq; + + lreqp = (struct lifreq *)&lifc.lifc_req[i]; + strlcpy(lreq.lifr_name, lreqp->lifr_name, + sizeof (lreq.lifr_name)); + if (ioctl(s, SIOCGLIFFLAGS, &lreq) < 0) { + close(s); + free(buf); + return (-1); + } + if ((lreq.lifr_flags & IFF_UP) && + !(lreq.lifr_flags & IFF_NOLOCAL) && + !(lreq.lifr_flags & IFF_NOXMIT) && + !(lreq.lifr_flags & IFF_LOOPBACK)) { + int_up = 1; + break; + } + } + free(buf); + + if (!int_up) { + close(s); + return (-1); + } + } + close(s); + } +#endif /* SUNW_INITCHKIF */ + +#ifdef SUNW_DOMAINFROMNIS +/* + * The old (4.8.3) libresolv derived the default domainname from NIS/NIS+. + */ + { + char buf[sizeof(statp->defdname)], *cp; + int ret; + if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 && + ret <= sizeof(buf)) { + if (buf[0] == '+') + buf[0] = '.'; + cp = strchr(buf, '.'); + if (cp == 0) + strcpy(statp->defdname, buf); + else + strcpy(statp->defdname, cp+1); + } + } +#endif /* SUNW_DOMAINFROMNIS */ + + /* Allow user to override the local domain definition */ + if ((cp = getenv("LOCALDOMAIN")) != NULL) { + (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + haveenv++; + + /* + * Set search list to be blank-separated strings + * from rest of env value. Permits users of LOCALDOMAIN + * to still have a search list, and anyone to set the + * one that they want to use as an individual (even more + * important now that the rfc1535 stuff restricts searches) + */ + cp = statp->defdname; + pp = statp->dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { + if (*cp == '\n') /* silly backwards compat */ + break; + else if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + havesearch = 1; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') + cp++; + *cp = '\0'; + *pp++ = 0; + } + +#define MATCH(line, name) \ + (!strncmp(line, name, sizeof(name) - 1) && \ + (line[sizeof(name) - 1] == ' ' || \ + line[sizeof(name) - 1] == '\t')) + + nserv = 0; + +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + if ((fp = __nsl_fopen(_PATH_RESCONF, "r")) != NULL) { + /* read the config file */ + while (__nsl_fgets(buf, sizeof(buf), fp) != NULL) { +#else + if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { + /* read the config file */ + while (fgets(buf, sizeof(buf), fp) != NULL) { +#endif + /* skip comments */ + if (*buf == ';' || *buf == '#') + continue; + /* read default domain name */ + if (MATCH(buf, "domain")) { + if (haveenv) /* skip if have from environ */ + continue; + cp = buf + sizeof("domain") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) + *cp = '\0'; + havesearch = 0; + continue; + } + /* set search list */ + if (MATCH(buf, "search")) { + if (haveenv) /* skip if have from environ */ + continue; + cp = buf + sizeof("search") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + if ((cp = strchr(statp->defdname, '\n')) != NULL) + *cp = '\0'; + /* + * Set search list to be blank-separated strings + * on rest of line. + */ + cp = statp->defdname; + pp = statp->dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { + if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t') + cp++; + *cp = '\0'; + *pp++ = 0; + havesearch = 1; + continue; + } + /* read nameservers to query */ + if (MATCH(buf, "nameserver") && nserv < MAXNS) { + struct addrinfo hints, *ai; + char sbuf[NI_MAXSERV]; + const size_t minsiz = + sizeof(statp->_u._ext.ext->nsaddrs[0]); + + cp = buf + sizeof("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + cp[strcspn(cp, ";# \t\n")] = '\0'; + if ((*cp != '\0') && (*cp != '\n')) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + sprintf(sbuf, "%u", NAMESERVER_PORT); + if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && + ai->ai_addrlen <= minsiz) { + if (statp->_u._ext.ext != NULL) { + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + ai->ai_addr, ai->ai_addrlen); + } + if (ai->ai_addrlen <= + sizeof(statp->nsaddr_list[nserv])) { + memcpy(&statp->nsaddr_list[nserv], + ai->ai_addr, ai->ai_addrlen); + } else + statp->nsaddr_list[nserv].sin_family = 0; + freeaddrinfo(ai); + nserv++; + } + } + continue; + } +#ifdef RESOLVSORT + if (MATCH(buf, "sortlist")) { + struct in_addr a; + + cp = buf + sizeof("sortlist") - 1; + while (nsort < MAXRESOLVSORT) { + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '\0' || *cp == '\n' || *cp == ';') + break; + net = cp; + while (*cp && !ISSORTMASK(*cp) && *cp != ';' && + isascii(*cp) && !isspace((unsigned char)*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + statp->sort_list[nsort].addr = a; + if (ISSORTMASK(n)) { + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && + !isspace((unsigned char)*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + statp->sort_list[nsort].mask = a.s_addr; + } else { + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); + } + } else { + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); + } + nsort++; + } + *cp = n; + } + continue; + } +#endif + if (MATCH(buf, "options")) { + res_setoptions(statp, buf + sizeof("options") - 1, "conf"); + continue; + } + } + if (nserv > 0) + statp->nscount = nserv; +#ifdef RESOLVSORT + statp->nsort = nsort; +#endif + +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + (void) __nsl_fclose(fp); +#else + (void) fclose(fp); +#endif + } +/* + * Last chance to get a nameserver. This should not normally + * be necessary + */ +#ifdef NO_RESOLV_CONF + if(nserv == 0) + nserv = get_nameservers(statp); +#endif + + if (statp->defdname[0] == 0 && + gethostname(buf, sizeof(statp->defdname) - 1) == 0 && + (cp = strchr(buf, '.')) != NULL) + strcpy(statp->defdname, cp + 1); + + /* find components of local domain that might be searched */ + if (havesearch == 0) { + pp = statp->dnsrch; + *pp++ = statp->defdname; + *pp = NULL; + + dots = 0; + for (cp = statp->defdname; *cp; cp++) + dots += (*cp == '.'); + + cp = statp->defdname; + while (pp < statp->dnsrch + MAXDFLSRCH) { + if (dots < LOCALDOMAINPARTS) + break; + cp = strchr(cp, '.') + 1; /* we know there is one */ + *pp++ = cp; + dots--; + } + *pp = NULL; +#ifdef DEBUG + if (statp->options & RES_DEBUG) { + printf(";; res_init()... default dnsrch list:\n"); + for (pp = statp->dnsrch; *pp; pp++) + printf(";;\t%s\n", *pp); + printf(";;\t..END..\n"); + } +#endif + } + + if ((cp = getenv("RES_OPTIONS")) != NULL) + res_setoptions(statp, cp, "env"); + statp->options |= RES_INIT; + return (0); +} + +static void +res_setoptions(res_state statp, const char *options, const char *source) +{ + const char *cp = options; + int i; + struct __res_state_ext *ext = statp->_u._ext.ext; + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_setoptions(\"%s\", \"%s\")...\n", + options, source); +#endif + while (*cp) { + /* skip leading and inner runs of spaces */ + while (*cp == ' ' || *cp == '\t') + cp++; + /* search for and process individual options */ + if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { + i = atoi(cp + sizeof("ndots:") - 1); + if (i <= RES_MAXNDOTS) + statp->ndots = i; + else + statp->ndots = RES_MAXNDOTS; +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";;\tndots=%d\n", statp->ndots); +#endif + } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { + i = atoi(cp + sizeof("timeout:") - 1); + if (i <= RES_MAXRETRANS) + statp->retrans = i; + else + statp->retrans = RES_MAXRETRANS; + } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ + i = atoi(cp + sizeof("attempts:") - 1); + if (i <= RES_MAXRETRY) + statp->retry = i; + else + statp->retry = RES_MAXRETRY; +#ifdef ORIGINAL_ISC_CODE +#else + } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) { + /* + * For backward compatibility, 'retrans' is + * supported as an alias for 'timeout', though + * without an imposed maximum. + */ + statp->retrans = atoi(cp + sizeof("retrans:") - 1); + } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){ + /* + * For backward compatibility, 'retry' is + * supported as an alias for 'attempts', though + * without an imposed maximum. + */ + statp->retry = atoi(cp + sizeof("retry:") - 1); +#endif /* ORIGINAL_ISC_CODE */ + } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { +#ifdef DEBUG + if (!(statp->options & RES_DEBUG)) { + printf(";; res_setoptions(\"%s\", \"%s\")..\n", + options, source); + statp->options |= RES_DEBUG; + } + printf(";;\tdebug\n"); +#endif + } else if (!strncmp(cp, "no_tld_query", + sizeof("no_tld_query") - 1) || + !strncmp(cp, "no-tld-query", + sizeof("no-tld-query") - 1)) { + statp->options |= RES_NOTLDQUERY; + } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { + statp->options |= RES_USE_INET6; + } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { + statp->options |= RES_ROTATE; + } else if (!strncmp(cp, "no-check-names", + sizeof("no-check-names") - 1)) { + statp->options |= RES_NOCHECKNAME; + } +#ifdef RES_USE_EDNS0 + else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { + statp->options |= RES_USE_EDNS0; + } +#endif + else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { + statp->options |= RES_USE_DNAME; + } + else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("nibble:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); + strncpy(ext->nsuffix, cp, i); + ext->nsuffix[i] = '\0'; + } + else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("nibble2:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1); + strncpy(ext->nsuffix2, cp, i); + ext->nsuffix2[i] = '\0'; + } + else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { + cp += sizeof("v6revmode:") - 1; + /* "nibble" and "bitstring" used to be valid */ + if (!strncmp(cp, "single", sizeof("single") - 1)) { + statp->options |= RES_NO_NIBBLE2; + } else if (!strncmp(cp, "both", sizeof("both") - 1)) { + statp->options &= + ~RES_NO_NIBBLE2; + } + } + else { + /* XXX - print a warning here? */ + } + skip: + /* skip to next run of spaces */ + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + } +} + +#ifdef RESOLVSORT +/* XXX - should really support CIDR which means explicit masks always. */ +static u_int32_t +net_mask(in) /* XXX - should really use system's version of this */ + struct in_addr in; +{ + register u_int32_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (htonl(IN_CLASSA_NET)); + else if (IN_CLASSB(i)) + return (htonl(IN_CLASSB_NET)); + return (htonl(IN_CLASSC_NET)); +} +#endif + +u_int +res_randomid(void) { + struct timeval now; + + gettimeofday(&now, NULL); + return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); +} + +/* + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. This provides support for endhostent() + * which expects to close the socket. + * + * This routine is not expected to be user visible. + */ +void +res_nclose(res_state statp) { + int ns; + + if (statp->_vcsock >= 0) { + (void) close(statp->_vcsock); + statp->_vcsock = -1; + statp->_flags &= ~(RES_F_VC | RES_F_CONN); + } + for (ns = 0; ns < statp->_u._ext.nscount; ns++) { + if (statp->_u._ext.nssocks[ns] != -1) { + (void) close(statp->_u._ext.nssocks[ns]); + statp->_u._ext.nssocks[ns] = -1; + } + } +} + +void +res_ndestroy(res_state statp) { + res_nclose(statp); + if (statp->_u._ext.ext != NULL) + free(statp->_u._ext.ext); + statp->options &= ~RES_INIT; + statp->_u._ext.ext = NULL; +} + +const char * +res_get_nibblesuffix(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->nsuffix); + return ("ip6.arpa"); +} + +const char * +res_get_nibblesuffix2(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->nsuffix2); + return ("ip6.int"); +} + +void +res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { + int i, nserv; + size_t size; + + /* close open servers */ + res_nclose(statp); + + /* cause rtt times to be forgotten */ + statp->_u._ext.nscount = 0; + + nserv = 0; + for (i = 0; i < cnt && nserv < MAXNS; i++) { + switch (set->sin.sin_family) { + case AF_INET: + size = sizeof(set->sin); + if (statp->_u._ext.ext) + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + &set->sin, size); + if (size <= sizeof(statp->nsaddr_list[nserv])) + memcpy(&statp->nsaddr_list[nserv], + &set->sin, size); + else + statp->nsaddr_list[nserv].sin_family = 0; + nserv++; + break; + +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + size = sizeof(set->sin6); + if (statp->_u._ext.ext) + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + &set->sin6, size); + if (size <= sizeof(statp->nsaddr_list[nserv])) + memcpy(&statp->nsaddr_list[nserv], + &set->sin6, size); + else + statp->nsaddr_list[nserv].sin_family = 0; + nserv++; + break; +#endif + + default: + break; + } + set++; + } + statp->nscount = nserv; + +} + +int +res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) { + int i; + size_t size; + u_int16_t family; + + for (i = 0; i < statp->nscount && i < cnt; i++) { + if (statp->_u._ext.ext) + family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; + else + family = statp->nsaddr_list[i].sin_family; + + switch (family) { + case AF_INET: + size = sizeof(set->sin); + if (statp->_u._ext.ext) + memcpy(&set->sin, + &statp->_u._ext.ext->nsaddrs[i], + size); + else + memcpy(&set->sin, &statp->nsaddr_list[i], + size); + break; + +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + size = sizeof(set->sin6); + if (statp->_u._ext.ext) + memcpy(&set->sin6, + &statp->_u._ext.ext->nsaddrs[i], + size); + else + memcpy(&set->sin6, &statp->nsaddr_list[i], + size); + break; +#endif + + default: + set->sin.sin_family = 0; + break; + } + set++; + } + return (statp->nscount); +} diff --git a/usr/src/lib/libresolv2/common/resolv/res_mkquery.c b/usr/src/lib/libresolv2/common/resolv/res_mkquery.c new file mode 100644 index 0000000000..c81e9eba32 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_mkquery.c @@ -0,0 +1,359 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1985, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_mkquery.c,v 8.16 2003/04/29 02:13:08 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/nameser.h> + +#ifdef SUNW_CONFCHECK +#include <sys/socket.h> +#include <errno.h> +#include <sys/stat.h> +#endif + +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG + +extern const char *_res_opcodes[]; + +#ifdef SUNW_CONFCHECK +static int _confcheck(res_state statp); +#endif + +/* + * Form all types of queries. + * Returns the size of the result or -1. + */ +int +res_nmkquery(res_state statp, + int op, /* opcode of query */ + const char *dname, /* domain name */ + int class, int type, /* class and type of query */ + const u_char *data, /* resource record data */ + int datalen, /* length of data */ + const u_char *newrr_in, /* new rr for modify or append */ + u_char *buf, /* buffer to put query */ + int buflen) /* size of buffer */ +{ + register HEADER *hp; + register u_char *cp, *ep; + register int n; + u_char *dnptrs[20], **dpp, **lastdnptr; + + UNUSED(newrr_in); + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nmkquery(%s, %s, %s, %s)\n", + _res_opcodes[op], dname, p_class(class), p_type(type)); +#endif + +#ifdef SUNW_CONFCHECK + /* + * 1247019, 1265838, and 4034368: Check to see if we can + * bailout quickly. + */ + if (_confcheck(statp) == -1) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return(-1); + } +#endif + + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + hp->id = htons(++statp->id); + hp->opcode = op; + hp->rd = (statp->options & RES_RECURSE) != 0; + hp->rcode = NOERROR; + cp = buf + HFIXEDSZ; + ep = buf + buflen; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + /* + * perform opcode specific processing + */ + switch (op) { + case QUERY: /*FALLTHROUGH*/ + case NS_NOTIFY_OP: + if (ep - cp < QFIXEDSZ) + return (-1); + if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, + lastdnptr)) < 0) + return (-1); + cp += n; + ns_put16(type, cp); + cp += INT16SZ; + ns_put16(class, cp); + cp += INT16SZ; + hp->qdcount = htons(1); + if (op == QUERY || data == NULL) + break; + /* + * Make an additional record for completion domain. + */ + if ((ep - cp) < RRFIXEDSZ) + return (-1); + n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ, + dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ns_put16(T_NULL, cp); + cp += INT16SZ; + ns_put16(class, cp); + cp += INT16SZ; + ns_put32(0, cp); + cp += INT32SZ; + ns_put16(0, cp); + cp += INT16SZ; + hp->arcount = htons(1); + break; + + case IQUERY: + /* + * Initialize answer section + */ + if (ep - cp < 1 + RRFIXEDSZ + datalen) + return (-1); + *cp++ = '\0'; /* no domain name */ + ns_put16(type, cp); + cp += INT16SZ; + ns_put16(class, cp); + cp += INT16SZ; + ns_put32(0, cp); + cp += INT32SZ; + ns_put16(datalen, cp); + cp += INT16SZ; + if (datalen) { + memcpy(cp, data, datalen); + cp += datalen; + } + hp->ancount = htons(1); + break; + + default: + return (-1); + } + return (cp - buf); +} + +#ifdef RES_USE_EDNS0 +/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ +#ifndef T_OPT +#define T_OPT 41 +#endif + +int +res_nopt(res_state statp, + int n0, /* current offset in buffer */ +#ifdef ORIGINAL_ISC_CODE + u_char *buf, /* buffer to put query */ +#else + uchar_t *buf, /* buffer to put query */ +#endif + int buflen, /* size of buffer */ + int anslen) /* UDP answer buffer size */ +{ + register HEADER *hp; + register u_char *cp, *ep; + u_int16_t flags = 0; + +#ifdef DEBUG + if ((statp->options & RES_DEBUG) != 0) + printf(";; res_nopt()\n"); +#endif + + hp = (HEADER *) buf; + cp = buf + n0; + ep = buf + buflen; + + if ((ep - cp) < 1 + RRFIXEDSZ) + return (-1); + + *cp++ = 0; /* "." */ + + ns_put16(T_OPT, cp); /* TYPE */ + cp += INT16SZ; + ns_put16(anslen & 0xffff, cp); /* CLASS = UDP payload size */ + cp += INT16SZ; + *cp++ = NOERROR; /* extended RCODE */ + *cp++ = 0; /* EDNS version */ + if (statp->options & RES_USE_DNSSEC) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_opt()... ENDS0 DNSSEC\n"); +#endif + flags |= NS_OPT_DNSSEC_OK; + } + ns_put16(flags, cp); + cp += INT16SZ; + ns_put16(0, cp); /* RDLEN */ + cp += INT16SZ; + hp->arcount = htons(ntohs(hp->arcount) + 1); + + return (cp - buf); +} +#endif + +#ifdef SUNW_CONFCHECK +/* + * Kludge to time out quickly if there is no /etc/resolv.conf + * and a TCP connection to the local DNS server fails. + * + * Moved function from res_send.c to res_mkquery.c. This + * solves a long timeout problem with nslookup. + * + * __areweinnamed is needed because there is a possibility that the + * user might do bad things to resolv.conf and cause in.named to call + * _confcheck and deadlock the server. + */ + +#ifdef SUNW_AREWEINNAMED +int __areweinnamed() +{ + return (0); +} +#endif /* SUNW_AREWEINNAMED */ + +static int _confcheck(res_state statp) +{ + int ns; + struct stat rc_stat; + struct sockaddr_in ns_sin; + + + if (__areweinnamed()) + return (0); + + /* First, we check to see if /etc/resolv.conf exists. + * If it doesn't, then it is likely that the localhost is + * the nameserver. + */ + if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) { + + /* Next, we check to see if _res.nsaddr is set to loopback. + * If it isn't, it has been altered by the application + * explicitly and we then want to bail with success. + */ + if (statp->nsaddr.sin_addr.S_un.S_addr == + htonl(INADDR_LOOPBACK)) { + + /* Lastly, we try to connect to the TCP port of the + * nameserver. If this fails, then we know that + * DNS is misconfigured and we can quickly exit. + */ + ns = socket(AF_INET, SOCK_STREAM, 0); + IN_SET_LOOPBACK_ADDR(&ns_sin); + ns_sin.sin_port = htons(NAMESERVER_PORT); + if (connect(ns, (struct sockaddr *) &ns_sin, + sizeof ns_sin) == -1) { + close(ns); + return(-1); + } + else { + close(ns); + + return(0); + } + } + + return(0); + } + + return (0); +} +#endif diff --git a/usr/src/lib/libresolv2/common/resolv/res_mkupdate.c b/usr/src/lib/libresolv2/common/resolv/res_mkupdate.c new file mode 100644 index 0000000000..d66f0b91ed --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_mkupdate.c @@ -0,0 +1,1165 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_mkupdate.c,v 1.30 2003/08/14 07:54:50 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <res_update.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG +#define MAXPORT 1024 + +static int getnum_str(u_char **, u_char *); +static int gethexnum_str(u_char **, u_char *); +static int getword_str(char *, int, u_char **, u_char *); +static int getstr_str(char *, int, u_char **, u_char *); + +#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2); + +/* Forward. */ + +int res_protocolnumber(const char *); +int res_servicenumber(const char *); + +/* + * Form update packets. + * Returns the size of the resulting packet if no error + * On error, + * returns -1 if error in reading a word/number in rdata + * portion for update packets + * -2 if length of buffer passed is insufficient + * -3 if zone section is not the first section in + * the linked list, or section order has a problem + * -4 on a number overflow + * -5 unknown operation or no records + */ +int +res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { + ns_updrec *rrecp_start = rrecp_in; + HEADER *hp; + u_char *cp, *sp1, *sp2, *startp, *endp; + int n, i, soanum, multiline; + ns_updrec *rrecp; + struct in_addr ina; + struct in6_addr in6a; + char buf2[MAXDNAME]; + u_char buf3[MAXDNAME]; + int section, numrrs = 0, counts[ns_s_max]; + u_int16_t rtype, rclass; + u_int32_t n1, rttl; + u_char *dnptrs[20], **dpp, **lastdnptr; + int siglen, keylen, certlen; + + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + hp->id = htons(++statp->id); + hp->opcode = ns_o_update; + hp->rcode = NOERROR; + sp1 = buf + 2*INT16SZ; /* save pointer to zocount */ + cp = buf + HFIXEDSZ; + buflen -= HFIXEDSZ; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + + if (rrecp_start == NULL) + return (-5); + else if (rrecp_start->r_section != S_ZONE) + return (-3); + + memset(counts, 0, sizeof counts); + for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) { + numrrs++; + section = rrecp->r_section; + if (section < 0 || section >= ns_s_max) + return (-1); + counts[section]++; + for (i = section + 1; i < ns_s_max; i++) + if (counts[i]) + return (-3); + rtype = rrecp->r_type; + rclass = rrecp->r_class; + rttl = rrecp->r_ttl; + /* overload class and type */ + if (section == S_PREREQ) { + rttl = 0; + switch (rrecp->r_opcode) { + case YXDOMAIN: + rclass = C_ANY; + rtype = T_ANY; + rrecp->r_size = 0; + break; + case NXDOMAIN: + rclass = C_NONE; + rtype = T_ANY; + rrecp->r_size = 0; + break; + case NXRRSET: + rclass = C_NONE; + rrecp->r_size = 0; + break; + case YXRRSET: + if (rrecp->r_size == 0) + rclass = C_ANY; + break; + default: + fprintf(stderr, + "res_mkupdate: incorrect opcode: %d\n", + rrecp->r_opcode); + fflush(stderr); + return (-1); + } + } else if (section == S_UPDATE) { + switch (rrecp->r_opcode) { + case DELETE: + rclass = rrecp->r_size == 0 ? C_ANY : C_NONE; + break; + case ADD: + break; + default: + fprintf(stderr, + "res_mkupdate: incorrect opcode: %d\n", + rrecp->r_opcode); + fflush(stderr); + return (-1); + } + } + + /* + * XXX appending default domain to owner name is omitted, + * fqdn must be provided + */ + if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs, + lastdnptr)) < 0) + return (-1); + cp += n; + ShrinkBuffer(n + 2*INT16SZ); + PUTSHORT(rtype, cp); + PUTSHORT(rclass, cp); + if (section == S_ZONE) { + if (numrrs != 1 || rrecp->r_type != T_SOA) + return (-3); + continue; + } + ShrinkBuffer(INT32SZ + INT16SZ); + PUTLONG(rttl, cp); + sp2 = cp; /* save pointer to length byte */ + cp += INT16SZ; + if (rrecp->r_size == 0) { + if (section == S_UPDATE && rclass != C_ANY) + return (-1); + else { + PUTSHORT(0, sp2); + continue; + } + } + startp = rrecp->r_data; + endp = startp + rrecp->r_size - 1; + /* XXX this should be done centrally. */ + switch (rrecp->r_type) { + case T_A: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (!inet_aton(buf2, &ina)) + return (-1); + n1 = ntohl(ina.s_addr); + ShrinkBuffer(INT32SZ); + PUTLONG(n1, cp); + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_MINFO: + case T_SOA: + case T_RP: + for (i = 0; i < 2; i++) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, + dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + } + if (rrecp->r_type == T_SOA) { + ShrinkBuffer(5 * INT32SZ); + while (isspace(*startp) || !*startp) + startp++; + if (*startp == '(') { + multiline = 1; + startp++; + } else + multiline = 0; + /* serial, refresh, retry, expire, minimum */ + for (i = 0; i < 5; i++) { + soanum = getnum_str(&startp, endp); + if (soanum < 0) + return (-1); + PUTLONG(soanum, cp); + } + if (multiline) { + while (isspace(*startp) || !*startp) + startp++; + if (*startp != ')') + return (-1); + } + } + break; + case T_MX: + case T_AFSDB: + case T_RT: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_SRV: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, NULL, NULL); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_PX: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + PUTSHORT(n, cp); + ShrinkBuffer(INT16SZ); + for (i = 0; i < 2; i++) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, + lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + } + break; + case T_WKS: { + char bm[MAXPORT/8]; + unsigned int maxbm = 0; + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (!inet_aton(buf2, &ina)) + return (-1); + n1 = ntohl(ina.s_addr); + ShrinkBuffer(INT32SZ); + PUTLONG(n1, cp); + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if ((i = res_protocolnumber(buf2)) < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = i & 0xff; + + for (i = 0; i < MAXPORT/8 ; i++) + bm[i] = 0; + + while (getword_str(buf2, sizeof buf2, &startp, endp)) { + if ((n1 = res_servicenumber(buf2)) <= 0) + return (-1); + + if (n1 < MAXPORT) { + bm[n1/8] |= (0x80>>(n1%8)); + if (n1 > maxbm) + maxbm = n1; + } else + return (-1); + } + maxbm = maxbm/8 + 1; + ShrinkBuffer(maxbm); + memcpy(cp, bm, maxbm); + cp += maxbm; + break; + } + case T_HINFO: + for (i = 0; i < 2; i++) { + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + } + break; + case T_TXT: + while (1) { + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + if (cp != (sp2 + INT16SZ)) + break; + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + } + break; + case T_X25: + /* RFC 1183 */ + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + return (-1); + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + break; + case T_ISDN: + /* RFC 1183 */ + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + return (-1); + if ((n > 255) || (n == 0)) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + n = 0; + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + break; + case T_NSAP: + if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) { + ShrinkBuffer(n); + memcpy(cp, buf2, n); + cp += n; + } else { + return (-1); + } + break; + case T_LOC: + if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) { + ShrinkBuffer(n); + memcpy(cp, buf2, n); + cp += n; + } else + return (-1); + break; + case ns_t_sig: + { + int sig_type, success, dateerror; + u_int32_t exptime, timesigned; + + /* type */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + sig_type = sym_ston(__p_type_syms, buf2, &success); + if (!success || sig_type == ns_t_any) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(sig_type, cp); + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* labels */ + n = getnum_str(&startp, endp); + if (n <= 0 || n > 255) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* ottl & expire */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + exptime = ns_datetosecs(buf2, &dateerror); + if (!dateerror) { + ShrinkBuffer(INT32SZ); + PUTLONG(rttl, cp); + } + else { + char *ulendp; + u_int32_t ottl; + + errno = 0; + ottl = strtoul(buf2, &ulendp, 10); + if (errno != 0 || + (ulendp != NULL && *ulendp != '\0')) + return (-1); + ShrinkBuffer(INT32SZ); + PUTLONG(ottl, cp); + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + exptime = ns_datetosecs(buf2, &dateerror); + if (dateerror) + return (-1); + } + /* expire */ + ShrinkBuffer(INT32SZ); + PUTLONG(exptime, cp); + /* timesigned */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + timesigned = ns_datetosecs(buf2, &dateerror); + if (!dateerror) { + ShrinkBuffer(INT32SZ); + PUTLONG(timesigned, cp); + } + else + return (-1); + /* footprint */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* signer name */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + /* sig */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + siglen = b64_pton(buf2, buf3, sizeof(buf3)); + if (siglen < 0) + return (-1); + ShrinkBuffer(siglen); + memcpy(cp, buf3, siglen); + cp += siglen; + break; + } + case ns_t_key: + /* flags */ + n = gethexnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* proto */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* key */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + keylen = b64_pton(buf2, buf3, sizeof(buf3)); + if (keylen < 0) + return (-1); + ShrinkBuffer(keylen); + memcpy(cp, buf3, keylen); + cp += keylen; + break; + case ns_t_nxt: + { + int success, nxt_type; + u_char data[32]; + int maxtype; + + /* next name */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, NULL, NULL); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + maxtype = 0; + memset(data, 0, sizeof data); + while (1) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + break; + nxt_type = sym_ston(__p_type_syms, buf2, + &success); + if (!success || !ns_t_rr_p(nxt_type)) + return (-1); + NS_NXT_BIT_SET(nxt_type, data); + if (nxt_type > maxtype) + maxtype = nxt_type; + } + n = maxtype/NS_NXT_BITS+1; + ShrinkBuffer(n); + memcpy(cp, data, n); + cp += n; + break; + } + case ns_t_cert: + /* type */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* key tag */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* cert */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + certlen = b64_pton(buf2, buf3, sizeof(buf3)); + if (certlen < 0) + return (-1); + ShrinkBuffer(certlen); + memcpy(cp, buf3, certlen); + cp += certlen; + break; + case ns_t_aaaa: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (inet_pton(AF_INET6, buf2, &in6a) <= 0) + return (-1); + ShrinkBuffer(NS_IN6ADDRSZ); + memcpy(cp, &in6a, NS_IN6ADDRSZ); + cp += NS_IN6ADDRSZ; + break; + case ns_t_naptr: + /* Order Preference Flags Service Replacement Regexp */ + /* Order */ + n = getnum_str(&startp, endp); + if (n < 0 || n > 65535) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* Preference */ + n = getnum_str(&startp, endp); + if (n < 0 || n > 65535) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* Flags */ + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + /* Service Classes */ + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + /* Pattern */ + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + /* Replacement */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, NULL, NULL); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + default: + return (-1); + } /*switch*/ + n = (u_int16_t)((cp - sp2) - INT16SZ); + PUTSHORT(n, sp2); + } /*for*/ + + hp->qdcount = htons(counts[0]); + hp->ancount = htons(counts[1]); + hp->nscount = htons(counts[2]); + hp->arcount = htons(counts[3]); + return (cp - buf); +} + +/* + * Get a whitespace delimited word from a string (not file) + * into buf. modify the start pointer to point after the + * word in the string. + */ +static int +getword_str(char *buf, int size, u_char **startpp, u_char *endp) { + char *cp; + int c; + + for (cp = buf; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (cp != buf) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + (*startpp)++; + if (cp >= buf+size-1) + break; + *cp++ = (u_char)c; + } + *cp = '\0'; + return (cp != buf); +} + +/* + * get a white spae delimited string from memory. Process quoted strings + * and \DDD escapes. Return length or -1 on error. Returned string may + * contain nulls. + */ +static char digits[] = "0123456789"; +static int +getstr_str(char *buf, int size, u_char **startpp, u_char *endp) { + char *cp; + int c, c1 = 0; + int inquote = 0; + int seen_quote = 0; + int escape = 0; + int dig = 0; + + for (cp = buf; *startpp <= endp; ) { + if ((c = **startpp) == '\0') + break; + /* leading white space */ + if ((cp == buf) && !seen_quote && isspace(c)) { + (*startpp)++; + continue; + } + + switch (c) { + case '\\': + if (!escape) { + escape = 1; + dig = 0; + c1 = 0; + (*startpp)++; + continue; + } + goto do_escape; + case '"': + if (!escape) { + inquote = !inquote; + seen_quote = 1; + (*startpp)++; + continue; + } + /* fall through */ + default: + do_escape: + if (escape) { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + c1 = c1 * 10 + + (strchr(digits, c) - digits); + + if (++dig == 3) { + c = c1 &0xff; + break; + } + (*startpp)++; + continue; + } + escape = 0; + } else if (!inquote && isspace(c)) + goto done; + if (cp >= buf+size-1) + goto done; + *cp++ = (u_char)c; + (*startpp)++; + } + } + done: + *cp = '\0'; + return ((cp == buf)? (seen_quote? 0: -1): (cp - buf)); +} +/* + * Get a whitespace delimited base 16 number from a string (not file) into buf + * update the start pointer to point after the number in the string. + */ +static int +gethexnum_str(u_char **startpp, u_char *endp) { + int c, n; + int seendigit = 0; + int m = 0; + + if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0) + return getnum_str(startpp, endp); + (*startpp)+=2; + for (n = 0; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (seendigit) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + if (c == ';') { + while ((*startpp <= endp) && + ((c = **startpp) != '\n')) + (*startpp)++; + if (seendigit) + break; + continue; + } + if (!isxdigit(c)) { + if (c == ')' && seendigit) { + (*startpp)--; + break; + } + return (-1); + } + (*startpp)++; + if (isdigit(c)) + n = n * 16 + (c - '0'); + else + n = n * 16 + (tolower(c) - 'a' + 10); + seendigit = 1; + } + return (n + m); +} + +/* + * Get a whitespace delimited base 10 number from a string (not file) into buf + * update the start pointer to point after the number in the string. + */ +static int +getnum_str(u_char **startpp, u_char *endp) { + int c, n; + int seendigit = 0; + int m = 0; + + for (n = 0; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (seendigit) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + if (c == ';') { + while ((*startpp <= endp) && + ((c = **startpp) != '\n')) + (*startpp)++; + if (seendigit) + break; + continue; + } + if (!isdigit(c)) { + if (c == ')' && seendigit) { + (*startpp)--; + break; + } + return (-1); + } + (*startpp)++; + n = n * 10 + (c - '0'); + seendigit = 1; + } + return (n + m); +} + +/* + * Allocate a resource record buffer & save rr info. + */ +ns_updrec * +res_mkupdrec(int section, const char *dname, + u_int class, u_int type, u_long ttl) { + ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec)); + + if (!rrecp || !(rrecp->r_dname = strdup(dname))) { + if (rrecp) + free((char *)rrecp); + return (NULL); + } + INIT_LINK(rrecp, r_link); + INIT_LINK(rrecp, r_glink); + rrecp->r_class = class; + rrecp->r_type = type; + rrecp->r_ttl = ttl; + rrecp->r_section = section; + return (rrecp); +} + +/* + * Free a resource record buffer created by res_mkupdrec. + */ +void +res_freeupdrec(ns_updrec *rrecp) { + /* Note: freeing r_dp is the caller's responsibility. */ + if (rrecp->r_dname != NULL) + free(rrecp->r_dname); + free(rrecp); +} + +struct valuelist { + struct valuelist * next; + struct valuelist * prev; + char * name; + char * proto; + int port; +}; +static struct valuelist *servicelist, *protolist; + +static void +res_buildservicelist() { + struct servent *sp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setservent(0); +#else + setservent(1); +#endif + while ((sp = getservent()) != NULL) { + slp = (struct valuelist *)malloc(sizeof(struct valuelist)); + if (!slp) + break; + slp->name = strdup(sp->s_name); + slp->proto = strdup(sp->s_proto); + if ((slp->name == NULL) || (slp->proto == NULL)) { + if (slp->name) free(slp->name); + if (slp->proto) free(slp->proto); + free(slp); + break; + } + slp->port = ntohs((u_int16_t)sp->s_port); /* host byt order */ + slp->next = servicelist; + slp->prev = NULL; + if (servicelist) + servicelist->prev = slp; + servicelist = slp; + } + endservent(); +} + +void +res_destroyservicelist() { + struct valuelist *slp, *slp_next; + + for (slp = servicelist; slp != NULL; slp = slp_next) { + slp_next = slp->next; + free(slp->name); + free(slp->proto); + free(slp); + } + servicelist = (struct valuelist *)0; +} + +void +res_buildprotolist(void) { + struct protoent *pp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setprotoent(0); +#else + setprotoent(1); +#endif + while ((pp = getprotoent()) != NULL) { + slp = (struct valuelist *)malloc(sizeof(struct valuelist)); + if (!slp) + break; + slp->name = strdup(pp->p_name); + if (slp->name == NULL) { + free(slp); + break; + } + slp->port = pp->p_proto; /* host byte order */ + slp->next = protolist; + slp->prev = NULL; + if (protolist) + protolist->prev = slp; + protolist = slp; + } + endprotoent(); +} + +void +res_destroyprotolist(void) { + struct valuelist *plp, *plp_next; + + for (plp = protolist; plp != NULL; plp = plp_next) { + plp_next = plp->next; + free(plp->name); + free(plp); + } + protolist = (struct valuelist *)0; +} + +static int +findservice(const char *s, struct valuelist **list) { + struct valuelist *lp = *list; + int n; + + for (; lp != NULL; lp = lp->next) + if (strcasecmp(lp->name, s) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + return (lp->port); /* host byte order */ + } + if (sscanf(s, "%d", &n) != 1 || n <= 0) + n = -1; + return (n); +} + +/* + * Convert service name or (ascii) number to int. + */ +int +res_servicenumber(const char *p) { + if (servicelist == (struct valuelist *)0) + res_buildservicelist(); + return (findservice(p, &servicelist)); +} + +/* + * Convert protocol name or (ascii) number to int. + */ +int +res_protocolnumber(const char *p) { + if (protolist == (struct valuelist *)0) + res_buildprotolist(); + return (findservice(p, &protolist)); +} + +static struct servent * +cgetservbyport(u_int16_t port, const char *proto) { /* Host byte order. */ + struct valuelist **list = &servicelist; + struct valuelist *lp = *list; + static struct servent serv; + + port = ntohs(port); + for (; lp != NULL; lp = lp->next) { + if (port != (u_int16_t)lp->port) /* Host byte order. */ + continue; + if (strcasecmp(lp->proto, proto) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + serv.s_name = lp->name; + serv.s_port = htons((u_int16_t)lp->port); + serv.s_proto = lp->proto; + return (&serv); + } + } + return (0); +} + +static struct protoent * +cgetprotobynumber(int proto) { /* Host byte order. */ + struct valuelist **list = &protolist; + struct valuelist *lp = *list; + static struct protoent prot; + + for (; lp != NULL; lp = lp->next) + if (lp->port == proto) { /* Host byte order. */ + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + prot.p_name = lp->name; + prot.p_proto = lp->port; /* Host byte order. */ + return (&prot); + } + return (0); +} + +const char * +res_protocolname(int num) { + static char number[8]; + struct protoent *pp; + + if (protolist == (struct valuelist *)0) + res_buildprotolist(); + pp = cgetprotobynumber(num); + if (pp == 0) { + (void) sprintf(number, "%d", num); + return (number); + } + return (pp->p_name); +} + +const char * +res_servicename(u_int16_t port, const char *proto) { /* Host byte order. */ + static char number[8]; + struct servent *ss; + + if (servicelist == (struct valuelist *)0) + res_buildservicelist(); + ss = cgetservbyport(htons(port), proto); + if (ss == 0) { + (void) sprintf(number, "%d", port); + return (number); + } + return (ss->s_name); +} diff --git a/usr/src/lib/libresolv2/common/resolv/res_mkupdate.h b/usr/src/lib/libresolv2/common/resolv/res_mkupdate.h new file mode 100644 index 0000000000..97a7518ee8 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_mkupdate.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef _RES_MKUPDATE_H_ +#define _RES_MKUPDATE_H_ + +#pragma ident "%Z%%M% %I% %E% SMI" + +__BEGIN_DECLS +__END_DECLS + +#endif /* _RES_MKUPDATE_H_ */ diff --git a/usr/src/lib/libresolv2/common/resolv/res_private.h b/usr/src/lib/libresolv2/common/resolv/res_private.h new file mode 100644 index 0000000000..0ee5617541 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef res_private_h +#define res_private_h + +struct __res_state_ext { + union res_sockaddr_union nsaddrs[MAXNS]; + struct sort_list { + int af; + union { + struct in_addr ina; + struct in6_addr in6a; + } addr, mask; + } sort_list[MAXRESOLVSORT]; + char nsuffix[64]; + char nsuffix2[64]; +}; + +extern int +res_ourserver_p(const res_state statp, const struct sockaddr *sa); + +#endif diff --git a/usr/src/lib/libresolv2/common/resolv/res_query.c b/usr/src/lib/libresolv2/common/resolv/res_query.c new file mode 100644 index 0000000000..55746f572f --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_query.c @@ -0,0 +1,464 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1988, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_query.c,v 8.24 2003/01/31 15:25:58 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "port_after.h" +#ifdef SUNW_AVOIDSTDIO_FDLIMIT +#include "../../../libnsl/include/nsl_stdio_prv.h" +#endif + +/* Options. Leave them on. */ +#define DEBUG + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +/* + * Formulate a normal query, send, and await answer. + * Returned answer is placed in supplied buffer "answer". + * Perform preliminary check of answer, returning success only + * if no error is indicated and the answer count is nonzero. + * Return the size of the response on success, -1 on error. + * Error number is left in H_ERRNO. + * + * Caller must parse answer and determine whether it answers the question. + */ +int +res_nquery(res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer buffer */ +{ + u_char buf[MAXPACKET]; + HEADER *hp = (HEADER *) answer; + int n; + u_int oflags; + + oflags = statp->_flags; + +again: + hp->rcode = NOERROR; /* default */ + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query(%s, %d, %d)\n", name, class, type); +#endif + + n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, + buf, sizeof(buf)); +#ifdef RES_USE_EDNS0 + if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 && + (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) + n = res_nopt(statp, n, buf, sizeof(buf), anslen); +#endif + if (n <= 0) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query: mkquery failed\n"); +#endif + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (n); + } + n = res_nsend(statp, buf, n, answer, anslen); + if (n < 0) { +#ifdef RES_USE_EDNS0 + /* if the query choked with EDNS0, retry without EDNS0 */ + if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 && + ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { + statp->_flags |= RES_F_EDNS0ERR; + if (statp->options & RES_DEBUG) + printf(";; res_nquery: retry without EDNS0\n"); + goto again; + } +#endif +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query: send error\n"); +#endif + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (n); + } + + if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n", + p_rcode(hp->rcode), + ntohs(hp->ancount), + ntohs(hp->nscount), + ntohs(hp->arcount)); +#endif + switch (hp->rcode) { + case NXDOMAIN: + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + break; + case SERVFAIL: + RES_SET_H_ERRNO(statp, TRY_AGAIN); + break; + case NOERROR: + RES_SET_H_ERRNO(statp, NO_DATA); + break; + case FORMERR: + case NOTIMP: + case REFUSED: + default: + RES_SET_H_ERRNO(statp, NO_RECOVERY); + break; + } + return (-1); + } + return (n); +} + +/* + * Formulate a normal query, send, and retrieve answer in supplied buffer. + * Return the size of the response on success, -1 on error. + * If enabled, implement search rules until answer or unrecoverable failure + * is detected. Error code, if any, is left in H_ERRNO. + */ +int +res_nsearch(res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ +{ + const char *cp, * const *domain; + HEADER *hp = (HEADER *) answer; + char tmp[NS_MAXDNAME]; + u_int dots; + int trailing_dot, ret, saved_herrno; + int got_nodata = 0, got_servfail = 0, root_on_list = 0; + int tried_as_is = 0; + int searched = 0; + + errno = 0; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */ + + dots = 0; + for (cp = name; *cp != '\0'; cp++) + dots += (*cp == '.'); + trailing_dot = 0; + if (cp > name && *--cp == '.') + trailing_dot++; + + /* If there aren't any dots, it could be a user-level alias. */ + if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) + return (res_nquery(statp, cp, class, type, answer, anslen)); + + /* + * If there are enough dots in the name, let's just give it a + * try 'as is'. The threshold can be set with the "ndots" option. + * Also, query 'as is', if there is a trailing dot in the name. + */ + saved_herrno = -1; + if (dots >= statp->ndots || trailing_dot) { + ret = res_nquerydomain(statp, name, NULL, class, type, + answer, anslen); + if (ret > 0 || trailing_dot) + return (ret); + saved_herrno = statp->res_h_errno; + tried_as_is++; + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + if ((!dots && (statp->options & RES_DEFNAMES) != 0) || + (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) { + int done = 0; + + for (domain = (const char * const *)statp->dnsrch; + *domain && !done; + domain++) { + searched = 1; + + if (domain[0][0] == '\0' || + (domain[0][0] == '.' && domain[0][1] == '\0')) + root_on_list++; + + ret = res_nquerydomain(statp, name, *domain, + class, type, + answer, anslen); + if (ret > 0) + return (ret); + + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_DATA error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's + * fully-qualified. + */ + if (errno == ECONNREFUSED) { + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); + } + + switch (statp->res_h_errno) { + case NO_DATA: + got_nodata++; + /* FALLTHROUGH */ + case HOST_NOT_FOUND: + /* keep trying */ + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) { + /* try next search element, if any */ + got_servfail++; + break; + } + /* FALLTHROUGH */ + default: + /* anything else implies that we're done */ + done++; + } + + /* if we got here for some reason other than DNSRCH, + * we only wanted one iteration of the loop, so stop. + */ + if ((statp->options & RES_DNSRCH) == 0) + done++; + } + } + + /* + * If the query has not already been tried as is then try it + * unless RES_NOTLDQUERY is set and there were no dots. + */ + if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0) && + !(tried_as_is || root_on_list)) { + ret = res_nquerydomain(statp, name, NULL, class, type, + answer, anslen); + if (ret > 0) + return (ret); + } + + /* if we got here, we didn't satisfy the search. + * if we did an initial full query, return that query's H_ERRNO + * (note that we wouldn't be here if that query had succeeded). + * else if we ever got a nodata, send that back as the reason. + * else send back meaningless H_ERRNO, that being the one from + * the last DNSRCH we did. + */ + if (saved_herrno != -1) + RES_SET_H_ERRNO(statp, saved_herrno); + else if (got_nodata) + RES_SET_H_ERRNO(statp, NO_DATA); + else if (got_servfail) + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); +} + +/* + * Perform a call on res_query on the concatenation of name and domain, + * removing a trailing dot from name if domain is NULL. + */ +int +res_nquerydomain(res_state statp, + const char *name, + const char *domain, + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ +{ + char nbuf[MAXDNAME]; + const char *longname = nbuf; + int n, d; + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nquerydomain(%s, %s, %d, %d)\n", + name, domain?domain:"<Nil>", class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name); + if (n >= MAXDNAME) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + n--; + if (n >= 0 && name[n] == '.') { + strncpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + n = strlen(name); + d = strlen(domain); + if (n + d + 1 >= MAXDNAME) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + sprintf(nbuf, "%s.%s", name, domain); + } + return (res_nquery(statp, longname, class, type, answer, anslen)); +} + +const char * +res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { + char *file, *cp1, *cp2; + char buf[BUFSIZ]; +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + __NSL_FILE *fp; +#else + FILE *fp; +#endif + + if (statp->options & RES_NOALIASES) + return (NULL); + file = getenv("HOSTALIASES"); +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + if (file == NULL || (fp = __nsl_fopen(file, "r")) == NULL) +#else + if (file == NULL || (fp = fopen(file, "r")) == NULL) +#endif + return (NULL); +#ifndef SUNW_AVOIDSTDIO_FDLIMIT + setbuf(fp, NULL); +#endif + buf[sizeof(buf) - 1] = '\0'; +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + while (__nsl_fgets(buf, sizeof(buf), fp)) { +#else + while (fgets(buf, sizeof(buf), fp)) { +#endif + for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1) + ; + if (!*cp1) + break; + *cp1 = '\0'; + if (ns_samename(buf, name) == 1) { + while (isspace((unsigned char)*++cp1)) + ; + if (!*cp1) + break; + for (cp2 = cp1 + 1; *cp2 && + !isspace((unsigned char)*cp2); ++cp2) + ; + *cp2 = '\0'; + strncpy(dst, cp1, siz - 1); + dst[siz - 1] = '\0'; +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + __nsl_fclose(fp); +#else + fclose(fp); +#endif + return (dst); + } + } +#ifdef SUNW_AVOIDSTDIO_FDLIMIT + __nsl_fclose(fp); +#else + fclose(fp); +#endif + return (NULL); +} diff --git a/usr/src/lib/libresolv2/common/resolv/res_send.c b/usr/src/lib/libresolv2/common/resolv/res_send.c new file mode 100644 index 0000000000..90ea5dad84 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_send.c @@ -0,0 +1,1087 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1985, 1989, 1993 + * The 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. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_send.c,v 8.52 2003/04/29 02:13:08 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Send query to name server and wait for reply. + */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <isc/eventlib.h> + +#include "port_after.h" + +#ifdef SUNW_POLL +#include <stropts.h> +#include <poll.h> +#define pselect Pselect +#endif /* SUNW_POLL */ + +/* Options. Leave them on. */ +#define DEBUG +#include "res_debug.h" +#include "res_private.h" + +#define EXT(res) ((res)->_u._ext) + +#ifdef ORIGINAL_ISC_CODE +static const int highestFD = FD_SETSIZE - 1; +#else +static int highestFD = 0; +#endif + +/* Forward. */ + +static int get_salen __P((const struct sockaddr *)); +static struct sockaddr * get_nsaddr __P((res_state, size_t)); +static int send_vc(res_state, const u_char *, int, + u_char *, int, int *, int); +static int send_dg(res_state, const u_char *, int, + u_char *, int, int *, int, + int *, int *); +static void Aerror(const res_state, FILE *, const char *, int, + const struct sockaddr *, int); +static void Perror(const res_state, FILE *, const char *, int); +static int sock_eq(struct sockaddr *, struct sockaddr *); +#ifdef NEED_PSELECT +static int pselect(int, void *, void *, void *, + struct timespec *, + const sigset_t *); +#endif +void res_pquery(const res_state, const u_char *, int, FILE *); + +#ifdef ORIGINAL_ISC_CODE +#else +#pragma weak __res_nameinquery = res_nameinquery +#pragma weak __res_queriesmatch = res_queriesmatch +#pragma weak res_nisourserver = res_ourserver_p +#endif /* ORIGINAL_ISC_CODE */ + +static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; + +/* Public. */ + +/* int + * res_isourserver(ina) + * looks up "ina" in _res.ns_addr_list[] + * returns: + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_ourserver_p(const res_state statp, const struct sockaddr *sa) { + const struct sockaddr_in *inp, *srv; + const struct sockaddr_in6 *in6p, *srv6; + int ns; + + switch (sa->sa_family) { + case AF_INET: + inp = (const struct sockaddr_in *)sa; + for (ns = 0; ns < statp->nscount; ns++) { + srv = (struct sockaddr_in *)get_nsaddr(statp, ns); + if (srv->sin_family == inp->sin_family && + srv->sin_port == inp->sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == inp->sin_addr.s_addr)) + return (1); + } + break; + case AF_INET6: + if (EXT(statp).ext == NULL) + break; + in6p = (const struct sockaddr_in6 *)sa; + for (ns = 0; ns < statp->nscount; ns++) { + srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); + if (srv6->sin6_family == in6p->sin6_family && + srv6->sin6_port == in6p->sin6_port && +#ifdef HAVE_SIN6_SCOPE_ID + (srv6->sin6_scope_id == 0 || + srv6->sin6_scope_id == in6p->sin6_scope_id) && +#endif + (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || + IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) + return (1); + } + break; + default: + break; + } + return (0); +} + +/* int + * res_nameinquery(name, type, class, buf, eom) + * look for (name,type,class) in the query section of packet (buf,eom) + * requires: + * buf + HFIXEDSZ <= eom + * returns: + * -1 : format error + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_nameinquery(const char *name, int type, int class, + const u_char *buf, const u_char *eom) +{ + const u_char *cp = buf + HFIXEDSZ; + int qdcount = ntohs(((const HEADER*)buf)->qdcount); + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf, eom, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom) + return (-1); + ttype = ns_get16(cp); cp += INT16SZ; + tclass = ns_get16(cp); cp += INT16SZ; + if (ttype == type && tclass == class && + ns_samename(tname, name) == 1) + return (1); + } + return (0); +} + +/* int + * res_queriesmatch(buf1, eom1, buf2, eom2) + * is there a 1:1 mapping of (name,type,class) + * in (buf1,eom1) and (buf2,eom2)? + * returns: + * -1 : format error + * 0 : not a 1:1 mapping + * >0 : is a 1:1 mapping + * author: + * paul vixie, 29may94 + */ +int +res_queriesmatch(const u_char *buf1, const u_char *eom1, + const u_char *buf2, const u_char *eom2) +{ + const u_char *cp = buf1 + HFIXEDSZ; + int qdcount = ntohs(((const HEADER*)buf1)->qdcount); + + if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) + return (-1); + + /* + * Only header section present in replies to + * dynamic update packets. + */ + if ((((const HEADER *)buf1)->opcode == ns_o_update) && + (((const HEADER *)buf2)->opcode == ns_o_update)) + return (1); + + if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) + return (0); + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom1) + return (-1); + ttype = ns_get16(cp); cp += INT16SZ; + tclass = ns_get16(cp); cp += INT16SZ; + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) + return (0); + } + return (1); +} + +int +res_nsend(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz) +{ + int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; + char abuf[NI_MAXHOST]; + +#ifdef SUNW_POLL + highestFD = sysconf(_SC_OPEN_MAX) - 1; +#endif + + if (statp->nscount == 0) { + errno = ESRCH; + return (-1); + } + if (anssiz < HFIXEDSZ) { + errno = EINVAL; + return (-1); + } + DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), + (stdout, ";; res_send()\n"), buf, buflen); + v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; + gotsomewhere = 0; + terrno = ETIMEDOUT; + + /* + * If the ns_addr_list in the resolver context has changed, then + * invalidate our cached copy and the associated timing data. + */ + if (EXT(statp).nscount != 0) { + int needclose = 0; + struct sockaddr_storage peer; + ISC_SOCKLEN_T peerlen; + + if (EXT(statp).nscount != statp->nscount) + needclose++; + else + for (ns = 0; ns < statp->nscount; ns++) { + if (statp->nsaddr_list[ns].sin_family && + !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], + (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { + needclose++; + break; + } + + if (EXT(statp).nssocks[ns] == -1) + continue; + peerlen = sizeof(peer); + if (getsockname(EXT(statp).nssocks[ns], + (struct sockaddr *)&peer, &peerlen) < 0) { + needclose++; + break; + } + if (!sock_eq((struct sockaddr *)&peer, + get_nsaddr(statp, ns))) { + needclose++; + break; + } + } + if (needclose) { + res_nclose(statp); + EXT(statp).nscount = 0; + } + } + + /* + * Maybe initialize our private copy of the ns_addr_list. + */ + if (EXT(statp).nscount == 0) { + for (ns = 0; ns < statp->nscount; ns++) { + EXT(statp).nstimes[ns] = RES_MAXTIME; + EXT(statp).nssocks[ns] = -1; + if (!statp->nsaddr_list[ns].sin_family) + continue; + EXT(statp).ext->nsaddrs[ns].sin = + statp->nsaddr_list[ns]; + } + EXT(statp).nscount = statp->nscount; + } + + /* + * Some resolvers want to even out the load on their nameservers. + * Note that RES_BLAST overrides RES_ROTATE. + */ + if ((statp->options & RES_ROTATE) != 0 && + (statp->options & RES_BLAST) == 0) { + union res_sockaddr_union inu; + struct sockaddr_in ina; + int lastns = statp->nscount - 1; + int fd; + u_int16_t nstime; + + if (EXT(statp).ext != NULL) + inu = EXT(statp).ext->nsaddrs[0]; + ina = statp->nsaddr_list[0]; + fd = EXT(statp).nssocks[0]; + nstime = EXT(statp).nstimes[0]; + for (ns = 0; ns < lastns; ns++) { + if (EXT(statp).ext != NULL) + EXT(statp).ext->nsaddrs[ns] = + EXT(statp).ext->nsaddrs[ns + 1]; + statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; + EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; + EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; + } + if (EXT(statp).ext != NULL) + EXT(statp).ext->nsaddrs[lastns] = inu; + statp->nsaddr_list[lastns] = ina; + EXT(statp).nssocks[lastns] = fd; + EXT(statp).nstimes[lastns] = nstime; + } + + /* + * Send request, RETRY times, or until successful. + */ + for (try = 0; try < statp->retry; try++) { + for (ns = 0; ns < statp->nscount; ns++) { + struct sockaddr *nsap; + int nsaplen; + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + statp->_flags &= ~RES_F_LASTMASK; + statp->_flags |= (ns << RES_F_LASTSHIFT); + same_ns: + if (statp->qhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*statp->qhook)(&nsap, &buf, &buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + done = 1; + break; + case res_nextns: + res_nclose(statp); + goto next_ns; + case res_done: + return (resplen); + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + goto fail; + } + } while (!done); + } + + Dprint(((statp->options & RES_DEBUG) && + getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), + NULL, 0, niflags) == 0), + (stdout, ";; Querying server (# %d) address = %s\n", + ns + 1, abuf)); + + + if (v_circuit) { + /* Use VC; at most one attempt per server. */ + try = statp->retry; + n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, + ns); + if (n < 0) + goto fail; + if (n == 0) + goto next_ns; + resplen = n; + } else { + /* Use datagrams. */ + n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, + ns, &v_circuit, &gotsomewhere); + if (n < 0) + goto fail; + if (n == 0) + goto next_ns; + if (v_circuit) + goto same_ns; + resplen = n; + } + + Dprint((statp->options & RES_DEBUG) || + ((statp->pfcode & RES_PRF_REPLY) && + (statp->pfcode & RES_PRF_HEAD1)), + (stdout, ";; got answer:\n")); + + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, "%s", ""), + ans, (resplen > anssiz) ? anssiz : resplen); + + /* + * If we have temporarily opened a virtual circuit, + * or if we haven't been asked to keep a socket open, + * close the socket. + */ + if ((v_circuit && (statp->options & RES_USEVC) == 0) || + (statp->options & RES_STAYOPEN) == 0) { + res_nclose(statp); + } + if (statp->rhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*statp->rhook)(nsap, buf, buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + case res_done: + done = 1; + break; + case res_nextns: + res_nclose(statp); + goto next_ns; + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + goto fail; + } + } while (!done); + + } + return (resplen); + next_ns: ; + } /*foreach ns*/ + } /*foreach retry*/ + res_nclose(statp); + if (!v_circuit) { + if (!gotsomewhere) + errno = ECONNREFUSED; /* no nameservers found */ + else + errno = ETIMEDOUT; /* no answer obtained */ + } else + errno = terrno; + return (-1); + fail: + res_nclose(statp); + return (-1); +} + +/* Private */ + +static int +get_salen(sa) + const struct sockaddr *sa; +{ + +#ifdef HAVE_SA_LEN + /* There are people do not set sa_len. Be forgiving to them. */ + if (sa->sa_len) + return (sa->sa_len); +#endif + + if (sa->sa_family == AF_INET) + return (sizeof(struct sockaddr_in)); + else if (sa->sa_family == AF_INET6) + return (sizeof(struct sockaddr_in6)); + else + return (0); /* unknown, die on connect */ +} + +/* + * pick appropriate nsaddr_list for use. see res_init() for initialization. + */ +static struct sockaddr * +get_nsaddr(statp, n) + res_state statp; + size_t n; +{ + + if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { + /* + * - EXT(statp).ext->nsaddrs[n] holds an address that is larger + * than struct sockaddr, and + * - user code did not update statp->nsaddr_list[n]. + */ + return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; + } else { + /* + * - user code updated statp->nsaddr_list[n], or + * - statp->nsaddr_list[n] has the same content as + * EXT(statp).ext->nsaddrs[n]. + */ + return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; + } +} + +static int +send_vc(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz, + int *terrno, int ns) +{ + const HEADER *hp = (const HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + struct sockaddr *nsap; + int nsaplen; + int truncating, connreset, resplen, n; + struct iovec iov[2]; + u_short len; + u_char *cp; + void *tmp; + + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + + connreset = 0; + same_ns: + truncating = 0; + + /* Are we still talking to whom we want to talk to? */ + if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { + struct sockaddr_storage peer; + ISC_SOCKLEN_T size = sizeof peer; + + if (getpeername(statp->_vcsock, + (struct sockaddr *)&peer, &size) < 0 || + !sock_eq((struct sockaddr *)&peer, nsap)) { + res_nclose(statp); + statp->_flags &= ~RES_F_VC; + } + } + + if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { + if (statp->_vcsock >= 0) + res_nclose(statp); + + statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); + if (statp->_vcsock > highestFD) { + res_nclose(statp); + errno = ENOTSOCK; + } + if (statp->_vcsock < 0) { + *terrno = errno; + Perror(statp, stderr, "socket(vc)", errno); + return (-1); + } + errno = 0; + if (connect(statp->_vcsock, nsap, nsaplen) < 0) { + *terrno = errno; + Aerror(statp, stderr, "connect/vc", errno, nsap, + nsaplen); + res_nclose(statp); + return (0); + } + statp->_flags |= RES_F_VC; + } + + /* + * Send length & message + */ + ns_put16((u_short)buflen, (u_char*)&len); + iov[0] = evConsIovec(&len, INT16SZ); + DE_CONST(buf, tmp); + iov[1] = evConsIovec(tmp, buflen); + if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { + *terrno = errno; + Perror(statp, stderr, "write failed", errno); + res_nclose(statp); + return (0); + } + /* + * Receive length & response + */ + read_len: + cp = ans; + len = INT16SZ; + while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) { + cp += n; + if ((len -= n) <= 0) + break; + } + if (n <= 0) { + *terrno = errno; + Perror(statp, stderr, "read failed", errno); + res_nclose(statp); + /* + * A long running process might get its TCP + * connection reset if the remote server was + * restarted. Requery the server instead of + * trying a new one. When there is only one + * server, this means that a query might work + * instead of failing. We only allow one reset + * per query to prevent looping. + */ + if (*terrno == ECONNRESET && !connreset) { + connreset = 1; + res_nclose(statp); + goto same_ns; + } + res_nclose(statp); + return (0); + } + resplen = ns_get16(ans); + if (resplen > anssiz) { + Dprint(statp->options & RES_DEBUG, + (stdout, ";; response truncated\n") + ); + truncating = 1; + len = anssiz; + } else + len = resplen; + if (len < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; undersized: %d\n", len)); + *terrno = EMSGSIZE; + res_nclose(statp); + return (0); + } + cp = ans; + while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ + cp += n; + len -= n; + } + if (n <= 0) { + *terrno = errno; + Perror(statp, stderr, "read(vc)", errno); + res_nclose(statp); + return (0); + } + if (truncating) { + /* + * Flush rest of answer so connection stays in synch. + */ + anhp->tc = 1; + len = resplen - anssiz; + /* + * Reset the value of resplen to anssiz, + * this is done because the caller assumes + * resplen contains the size of message read + * into the "ans" buffer passed in. + */ + resplen = anssiz; + + while (len != 0) { + char junk[PACKETSZ]; + + n = read(statp->_vcsock, junk, + (len > sizeof junk) ? sizeof junk : len); + if (n > 0) + len -= n; + else + break; + } + } + /* + * If the calling applicating has bailed out of + * a previous call and failed to arrange to have + * the circuit closed or the server has got + * itself confused, then drop the packet and + * wait for the correct one. + */ + if (hp->id != anhp->id) { + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; old answer (unexpected):\n"), + ans, (resplen > anssiz) ? anssiz: resplen); + goto read_len; + } + + /* + * All is well, or the error is fatal. Signal that the + * next nameserver ought not be tried. + */ + return (resplen); +} + +static int +send_dg(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz, + int *terrno, int ns, int *v_circuit, int *gotsomewhere) +{ + const HEADER *hp = (const HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + const struct sockaddr *nsap; + int nsaplen; + struct timespec now, timeout, finish; + fd_set dsmask; + struct sockaddr_storage from; + ISC_SOCKLEN_T fromlen; + int resplen, seconds, n, s; +#ifdef SUNW_POLL + int polltimeout; + struct pollfd pollfd; +#endif + + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + if (EXT(statp).nssocks[ns] == -1) { + EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); + if (EXT(statp).nssocks[ns] > highestFD) { + res_nclose(statp); + errno = ENOTSOCK; + } + if (EXT(statp).nssocks[ns] < 0) { + *terrno = errno; + Perror(statp, stderr, "socket(dg)", errno); + return (-1); + } +#ifndef CANNOT_CONNECT_DGRAM + /* + * On a 4.3BSD+ machine (client and server, + * actually), sending to a nameserver datagram + * port with no nameserver will cause an + * ICMP port unreachable message to be returned. + * If our datagram socket is "connected" to the + * server, we get an ECONNREFUSED error on the next + * socket operation, and select returns if the + * error message is received. We can thus detect + * the absence of a nameserver without timing out. + */ + if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { + Aerror(statp, stderr, "connect(dg)", errno, nsap, + nsaplen); + res_nclose(statp); + return (0); + } +#endif /* !CANNOT_CONNECT_DGRAM */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; new DG socket\n")) + } + s = EXT(statp).nssocks[ns]; +#ifndef CANNOT_CONNECT_DGRAM + if (send(s, (const char*)buf, buflen, 0) != buflen) { + Perror(statp, stderr, "send", errno); + res_nclose(statp); + return (0); + } +#else /* !CANNOT_CONNECT_DGRAM */ + if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) + { + Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); + res_nclose(statp); + return (0); + } +#endif /* !CANNOT_CONNECT_DGRAM */ + + /* + * Wait for reply. + */ + seconds = (statp->retrans << ns); + if (ns > 0) + seconds /= statp->nscount; + if (seconds <= 0) + seconds = 1; + now = evNowTime(); + timeout = evConsTime(seconds, 0); + finish = evAddTime(now, timeout); + goto nonow; + wait: + now = evNowTime(); + nonow: +#ifdef SUNW_POLL + timeout = evSubTime(finish, now); + if (timeout.tv_sec < 0) + timeout = evConsTime(0, 0); + polltimeout = 1000*timeout.tv_sec + + timeout.tv_nsec/1000000; + pollfd.fd = s; + pollfd.events = POLLRDNORM; + n = poll(&pollfd, 1, polltimeout); +#else + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + if (evCmpTime(finish, now) > 0) + timeout = evSubTime(finish, now); + else + timeout = evConsTime(0, 0); + n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); +#endif + if (n == 0) { + Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); + *gotsomewhere = 1; + return (0); + } + if (n < 0) { + if (errno == EINTR) + goto wait; +#ifdef SUNW_POLL + Perror(statp, stderr, "poll", errno); +#else + Perror(statp, stderr, "select", errno); +#endif + res_nclose(statp); + return (0); + } + errno = 0; + fromlen = sizeof(from); + resplen = recvfrom(s, (char*)ans, anssiz,0, + (struct sockaddr *)&from, &fromlen); + if (resplen <= 0) { + Perror(statp, stderr, "recvfrom", errno); + res_nclose(statp); + return (0); + } + *gotsomewhere = 1; + if (resplen < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; undersized: %d\n", + resplen)); + *terrno = EMSGSIZE; + res_nclose(statp); + return (0); + } + if (hp->id != anhp->id) { + /* + * response from old query, ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; old answer:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } + if (!(statp->options & RES_INSECURE1) && + !res_ourserver_p(statp, (struct sockaddr *)&from)) { + /* + * response from wrong server? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; not our server:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } +#ifdef RES_USE_EDNS0 + if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0) { + /* + * Do not retry if the server do not understand EDNS0. + * The case has to be captured here, as FORMERR packet do not + * carry query section, hence res_queriesmatch() returns 0. + */ + DprintQ(statp->options & RES_DEBUG, + (stdout, "server rejected query with EDNS0:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + /* record the error */ + statp->_flags |= RES_F_EDNS0ERR; + res_nclose(statp); + return (0); + } +#endif + if (!(statp->options & RES_INSECURE2) && + !res_queriesmatch(buf, buf + buflen, + ans, ans + anssiz)) { + /* + * response contains wrong query? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; wrong query name:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || + anhp->rcode == REFUSED) { + DprintQ(statp->options & RES_DEBUG, + (stdout, "server rejected query:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + res_nclose(statp); + /* don't retry if called from dig */ + if (!statp->pfcode) + return (0); + } + if (!(statp->options & RES_IGNTC) && anhp->tc) { + /* + * To get the rest of answer, + * use TCP with same server. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; truncated answer\n")); + *v_circuit = 1; + res_nclose(statp); + return (1); + } + /* + * All is well, or the error is fatal. Signal that the + * next nameserver ought not be tried. + */ + return (resplen); +} + +static void +Aerror(const res_state statp, FILE *file, const char *string, int error, + const struct sockaddr *address, int alen) +{ + int save = errno; + char hbuf[NI_MAXHOST]; + char sbuf[NI_MAXSERV]; + + alen = alen; + + if ((statp->options & RES_DEBUG) != 0) { + if (getnameinfo(address, alen, hbuf, sizeof(hbuf), + sbuf, sizeof(sbuf), niflags)) { + strncpy(hbuf, "?", sizeof(hbuf) - 1); + hbuf[sizeof(hbuf) - 1] = '\0'; + strncpy(sbuf, "?", sizeof(sbuf) - 1); + sbuf[sizeof(sbuf) - 1] = '\0'; + } + fprintf(file, "res_send: %s ([%s].%s): %s\n", + string, hbuf, sbuf, strerror(error)); + } + errno = save; +} + +static void +Perror(const res_state statp, FILE *file, const char *string, int error) { + int save = errno; + + if ((statp->options & RES_DEBUG) != 0) + fprintf(file, "res_send: %s: %s\n", + string, strerror(error)); + errno = save; +} + +static int +sock_eq(struct sockaddr *a, struct sockaddr *b) { + struct sockaddr_in *a4, *b4; + struct sockaddr_in6 *a6, *b6; + + if (a->sa_family != b->sa_family) + return 0; + switch (a->sa_family) { + case AF_INET: + a4 = (struct sockaddr_in *)a; + b4 = (struct sockaddr_in *)b; + return a4->sin_port == b4->sin_port && + a4->sin_addr.s_addr == b4->sin_addr.s_addr; + case AF_INET6: + a6 = (struct sockaddr_in6 *)a; + b6 = (struct sockaddr_in6 *)b; + return a6->sin6_port == b6->sin6_port && +#ifdef HAVE_SIN6_SCOPE_ID + a6->sin6_scope_id == b6->sin6_scope_id && +#endif + IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); + default: + return 0; + } +} + +#ifdef NEED_PSELECT +/* XXX needs to move to the porting library. */ +static int +pselect(int nfds, void *rfds, void *wfds, void *efds, + struct timespec *tsp, const sigset_t *sigmask) +{ + struct timeval tv, *tvp; + sigset_t sigs; + int n; + + if (tsp) { + tvp = &tv; + tv = evTimeVal(*tsp); + } else + tvp = NULL; + if (sigmask) + sigprocmask(SIG_SETMASK, sigmask, &sigs); + n = select(nfds, rfds, wfds, efds, tvp); + if (sigmask) + sigprocmask(SIG_SETMASK, &sigs, NULL); + if (tsp) + *tsp = evTimeSpec(tv); + return (n); +} +#endif diff --git a/usr/src/lib/libresolv2/common/resolv/res_sendsigned.c b/usr/src/lib/libresolv2/common/resolv/res_sendsigned.c new file mode 100644 index 0000000000..63fe5cc2d9 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_sendsigned.c @@ -0,0 +1,148 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * No ISC copyright for this file. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <isc/dst.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +#define DEBUG +#include "res_debug.h" + + +/* res_nsendsigned */ +int +res_nsendsigned(res_state statp, const u_char *msg, int msglen, + ns_tsig_key *key, u_char *answer, int anslen) +{ + res_state nstatp; + DST_KEY *dstkey; + int usingTCP = 0; + u_char *newmsg; + int newmsglen, bufsize, siglen; + u_char sig[64]; + HEADER *hp; + time_t tsig_time; + int ret; + + dst_init(); + + nstatp = (res_state) malloc(sizeof(*statp)); + if (nstatp == NULL) { + errno = ENOMEM; + return (-1); + } + memcpy(nstatp, statp, sizeof(*statp)); + + bufsize = msglen + 1024; + newmsg = (u_char *) malloc(bufsize); + if (newmsg == NULL) { + errno = ENOMEM; + return (-1); + } + memcpy(newmsg, msg, msglen); + newmsglen = msglen; + + if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) + dstkey = NULL; + else + dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, + NS_KEY_TYPE_AUTH_ONLY, + NS_KEY_PROT_ANY, + key->data, key->len); + if (dstkey == NULL) { + errno = EINVAL; + free(nstatp); + free(newmsg); + return (-1); + } + + nstatp->nscount = 1; + siglen = sizeof(sig); + ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, + sig, &siglen, 0); + if (ret < 0) { + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + if (ret == NS_TSIG_ERROR_NO_SPACE) + errno = EMSGSIZE; + else if (ret == -1) + errno = EINVAL; + return (ret); + } + + if (newmsglen > PACKETSZ || (nstatp->options & RES_IGNTC)) + usingTCP = 1; + if (usingTCP == 0) + nstatp->options |= RES_IGNTC; + else + nstatp->options |= RES_USEVC; + +retry: + + ret = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); + if (ret < 0) { + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + return (ret); + } + + anslen = ret; + ret = ns_verify(answer, &anslen, dstkey, sig, siglen, + NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG); + if (ret != 0) { +#ifdef ORIGINAL_ISC_CODE + Dprint(nstatp->pfcode & RES_PRF_REPLY, + (stdout, ";; TSIG invalid (%s)\n", p_rcode(ret))); +#else + Dprint(nstatp->pfcode & RES_PRF_REPLY, + (stdout, ";; TSIG invalid (%s)\n", p_rcode(-ret))); +#endif + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + if (ret == -1) + errno = EINVAL; + else + errno = ENOTTY; + return (-1); + } + Dprint(nstatp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); + + hp = (HEADER *) answer; + if (hp->tc && usingTCP == 0) { + nstatp->options &= ~RES_IGNTC; + usingTCP = 1; + goto retry; + } + + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + return (anslen); +} diff --git a/usr/src/lib/libresolv2/common/resolv/res_update.c b/usr/src/lib/libresolv2/common/resolv/res_update.c new file mode 100644 index 0000000000..8983dee245 --- /dev/null +++ b/usr/src/lib/libresolv2/common/resolv/res_update.c @@ -0,0 +1,219 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_update.c,v 1.38 2003/05/27 23:36:53 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <res_update.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/list.h> +#include <resolv.h> + +#include "port_after.h" +#include "res_private.h" + +/* + * Separate a linked list of records into groups so that all records + * in a group will belong to a single zone on the nameserver. + * Create a dynamic update packet for each zone and send it to the + * nameservers for that zone, and await answer. + * Abort if error occurs in updating any zone. + * Return the number of zones updated on success, < 0 on error. + * + * On error, caller must deal with the unsynchronized zones + * eg. an A record might have been successfully added to the forward + * zone but the corresponding PTR record would be missing if error + * was encountered while updating the reverse zone. + */ + +struct zonegrp { + char z_origin[MAXDNAME]; + ns_class z_class; + union res_sockaddr_union z_nsaddrs[MAXNS]; + int z_nscount; + int z_flags; + LIST(ns_updrec) z_rrlist; + LINK(struct zonegrp) z_link; +}; + +#define ZG_F_ZONESECTADDED 0x0001 + +/* Forward. */ + +static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2); + +/* Macros. */ + +#define DPRINTF(x) do {\ + int save_errno = errno; \ + if ((statp->options & RES_DEBUG) != 0) res_dprintf x; \ + errno = save_errno; \ + } while (0) + +/* Public. */ + +int +res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { + ns_updrec *rrecp; + u_char answer[PACKETSZ]; + u_char *packet; + struct zonegrp *zptr, tgrp; + LIST(struct zonegrp) zgrps; + int nzones = 0, nscount = 0, n; + union res_sockaddr_union nsaddrs[MAXNS]; + + packet = malloc(NS_MAXMSG); + if (packet == NULL) { + DPRINTF(("malloc failed")); + return (0); + } + /* Thread all of the updates onto a list of groups. */ + INIT_LIST(zgrps); + memset(&tgrp, 0, sizeof (tgrp)); + for (rrecp = rrecp_in; rrecp; + rrecp = LINKED(rrecp, r_link) ? NEXT(rrecp, r_link) : NULL) { + int nscnt; + /* Find the origin for it if there is one. */ + tgrp.z_class = rrecp->r_class; + nscnt = res_findzonecut2(statp, rrecp->r_dname, tgrp.z_class, + RES_EXHAUSTIVE, tgrp.z_origin, + sizeof tgrp.z_origin, + tgrp.z_nsaddrs, MAXNS); + if (nscnt <= 0) { + DPRINTF(("res_findzonecut failed (%d)", nscnt)); + goto done; + } + tgrp.z_nscount = nscnt; + /* Find the group for it if there is one. */ + for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) + if (ns_samename(tgrp.z_origin, zptr->z_origin) == 1 && + tgrp.z_class == zptr->z_class) + break; + /* Make a group for it if there isn't one. */ + if (zptr == NULL) { + zptr = malloc(sizeof *zptr); + if (zptr == NULL) { + DPRINTF(("malloc failed")); + goto done; + } + *zptr = tgrp; + zptr->z_flags = 0; + INIT_LINK(zptr, z_link); + INIT_LIST(zptr->z_rrlist); + APPEND(zgrps, zptr, z_link); + } + /* Thread this rrecp onto the right group. */ + APPEND(zptr->z_rrlist, rrecp, r_glink); + } + + for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) { + /* Construct zone section and prepend it. */ + rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin, + zptr->z_class, ns_t_soa, 0); + if (rrecp == NULL) { + DPRINTF(("res_mkupdrec failed")); + goto done; + } + PREPEND(zptr->z_rrlist, rrecp, r_glink); + zptr->z_flags |= ZG_F_ZONESECTADDED; + + /* Marshall the update message. */ + n = res_nmkupdate(statp, HEAD(zptr->z_rrlist), + packet, NS_MAXMSG); + DPRINTF(("res_mkupdate -> %d", n)); + if (n < 0) + goto done; + + /* Temporarily replace the resolver's nameserver set. */ + nscount = res_getservers(statp, nsaddrs, MAXNS); + res_setservers(statp, zptr->z_nsaddrs, zptr->z_nscount); + + /* Send the update and remember the result. */ + if (key != NULL) + n = res_nsendsigned(statp, packet, n, key, + answer, sizeof answer); + else + n = res_nsend(statp, packet, n, answer, sizeof answer); + if (n < 0) { + DPRINTF(("res_nsend: send error, n=%d (%s)\n", + n, strerror(errno))); + goto done; + } + if (((HEADER *)answer)->rcode == NOERROR) + nzones++; + + /* Restore resolver's nameserver set. */ + res_setservers(statp, nsaddrs, nscount); + nscount = 0; + } + done: + while (!EMPTY(zgrps)) { + zptr = HEAD(zgrps); + if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0) + res_freeupdrec(HEAD(zptr->z_rrlist)); + UNLINK(zgrps, zptr, z_link); + free(zptr); + } + if (nscount != 0) + res_setservers(statp, nsaddrs, nscount); + + free(packet); + return (nzones); +} + +/* Private. */ + +static void +res_dprintf(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + fputs(";; res_nupdate: ", stderr); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_dst_init.c b/usr/src/lib/libresolv2/common/sunw/sunw_dst_init.c new file mode 100644 index 0000000000..9d299a6f90 --- /dev/null +++ b/usr/src/lib/libresolv2/common/sunw/sunw_dst_init.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define __SUNW_DST_INIT_NODEFINE + +#include <port_before.h> + +#include <dlfcn.h> + +#include <isc/dst.h> + +#include <port_after.h> + + +static int +genInit(char *library, char *symbol, int (**initFunc)(void)) { + + void *dlHandle; + + if (*initFunc == 0) { + if ((dlHandle = dlopen(library, RTLD_LAZY|RTLD_GLOBAL)) == 0) + return (0); + if ((*(initFunc) = (int (*)(void))dlsym(dlHandle, + symbol)) == 0) { + /* + * Can't close the library, since it may be in use + * as a result of a previous, successful, call to + * this function. + */ + return (0); + } + } + + return ((**initFunc)()); +} + + +int +sunw_dst_bsafe_init(void) { + + static int (*initFunc)(void); + + return (genInit("/usr/lib/dns/dnssafe.so.1", "dst_bsafe_init", + &initFunc) || + genInit("/usr/lib/dns/sparcv9/dnssafe.so.1", "dst_bsafe_init", + &initFunc)); +} + + +int +sunw_dst_eay_dss_init(void) { + + static int (*initFunc)(void); + + return (genInit("/usr/lib/dns/cylink.so.1", "dst_eay_dss_init", + &initFunc) || + genInit("/usr/lib/dns/sparcv9/cylink.so.1", "dst_eay_dss_init", + &initFunc)); +} + + +int +sunw_dst_cylink_init(void) { + + static int (*initFunc)(void); + + return (genInit("/usr/lib/dns/cylink.so.1", "dst_cylink_init", + &initFunc) || + genInit("/usr/lib/dns/sparcv9/cylink.so.1", "dst_cylink_init", + &initFunc)); +} + + +int +sunw_dst_hmac_md5_init(void) { + + static int (*initFunc)(void); + + return (genInit("/usr/lib/dns/dnssafe.so.1", "dst_md5_hmac_init", + &initFunc) || + genInit("/usr/lib/dns/sparcv9/dnssafe.so.1", + "dst_hmac_md5_init", + &initFunc)); +} + + +int +sunw_dst_rsaref_init(void) { + + static int (*initFunc)(void); + + return (genInit("/usr/lib/dns/dnssafe.so.1", "dst_rsaref_init", + &initFunc) || + genInit("/usr/lib/dns/sparcv9/dnssafe.so.1", "dst_rsaref_init", + &initFunc)); +} diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_irs_init.c b/usr/src/lib/libresolv2/common/sunw/sunw_irs_init.c new file mode 100644 index 0000000000..542172cf25 --- /dev/null +++ b/usr/src/lib/libresolv2/common/sunw/sunw_irs_init.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define __SUNW_IRS_INIT_NODEFINE + +#include <port_before.h> + +#include <dlfcn.h> + +#include <port_after.h> + + +static struct irs_acc * +genInit(char *library, char *symbol, + struct irs_acc *(**initFunc)(const char *), const char *options) { + + void *dlHandle; + + if (*initFunc == 0) { + if ((dlHandle = dlopen(library, RTLD_LAZY|RTLD_GLOBAL)) == 0) + return (0); + if ((*(initFunc) = + (struct irs_acc *(*)(const char *))dlsym(dlHandle, + symbol)) == 0) { + /* + * Can't close the library, since it may be in use + * as a result of a previous, successful, call to + * this function. + */ + return (0); + } + } + + return ((**initFunc)(options)); +} + + +#ifdef WANT_IRS_NIS +struct irs_acc * +sunw_irs_nis_acc(const char *options) { + + static struct irs_acc *(*initFunc)(const char *); + struct irs_acc *ret; + + ret = genInit("/usr/lib/dns/irs.so.1", "irs_nis_acc", &initFunc, + options); + if (ret == 0) + ret = genInit("/usr/lib/dns/sparcv9/irs.so.1", "irs_nis_acc", + &initFunc, options); + return (ret); +} +#else +struct irs_acc * +sunw_irs_nis_acc(const char *options) { + return (0); +} +#endif /* WANT_IRS_NIS */ + +struct irs_acc * +sunw_irs_irp_acc(const char *options) { + + static struct irs_acc *(*initFunc)(const char *); + struct irs_acc *ret; + + ret = genInit("/usr/lib/dns/irs.so.1", "irs_irp_acc", &initFunc, + options); + if (ret == 0) + ret = genInit("/usr/lib/dns/sparcv9/irs.so.1", "irs_irp_acc", + &initFunc, options); + return (ret); +} diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_irs_nis_acc.c b/usr/src/lib/libresolv2/common/sunw/sunw_irs_nis_acc.c new file mode 100644 index 0000000000..0b5422b991 --- /dev/null +++ b/usr/src/lib/libresolv2/common/sunw/sunw_irs_nis_acc.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <port_before.h> + +#include <irs.h> + +#include <port_after.h> + +#ifdef WANT_IRS_NIS +static int __deliberately_empty; +#else +/* + * Never called; defined here so that the mapfile doesn't have to change + * depending on WANT_IRS_NIS. + */ +struct irs_acc * +irs_nis_acc(const char *options) { + return (0); +} +#endif /* WANT_IRS_NIS */ diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_mtctxres.c b/usr/src/lib/libresolv2/common/sunw/sunw_mtctxres.c new file mode 100644 index 0000000000..c77e103e22 --- /dev/null +++ b/usr/src/lib/libresolv2/common/sunw/sunw_mtctxres.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 1998-2000 by Sun Microsystems, Inc. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <port_before.h> +#include <thread.h> +#include <errno.h> +#include <netdb.h> +#include <malloc.h> +#include <string.h> +#include <resolv_mt.h> +#include <irs.h> +#include <port_after.h> + +static int thr_keycreate_ret = 0; + +static thread_key_t key; +static int mt_key_initialized = 0; + +static mtctxres_t sharedctx; + +static int __res_init_ctx(thread_key_t); +static void __res_destroy_ctx(void *); + +#pragma init (_mtctxres_init) + +/* + * Initialize the TSD key. By doing this at library load time, we're + * implicitly running without interference from other threads, so there's + * no need for locking. + */ +static void +_mtctxres_init(void) { + + if ((thr_keycreate_ret = thr_keycreate(&key, __res_destroy_ctx)) == 0) { + mt_key_initialized = 1; + } +} + + +/* + * To support binaries that used the private MT-safe interface in + * on998 or on28, we still need to provide the __res_enable_mt() + * and __res_disable_mt() entry points. They're do-nothing routines. + */ +int +__res_enable_mt(void) { + return (-1); +} + +int +__res_disable_mt(void) { + return (0); +} + + +static int +__res_init_ctx(thread_key_t key) { + + mtctxres_t *mt; + int ret; + + + if (thr_getspecific(key, (void **)&mt) == 0 && mt != 0) { + /* Already exists */ + return (0); + } + + if ((mt = malloc(sizeof (mtctxres_t))) == 0) { + errno = ENOMEM; + return (-1); + } + + memset(mt, 0, sizeof (*mt)); + + if ((ret = thr_setspecific(key, mt)) != 0) { + errno = ret; + free(mt); + return (-1); + } + + return (0); + +} + + +static void +__res_destroy_ctx(void *value) { + + mtctxres_t *mt = (mtctxres_t *)value; + + if (mt != 0) { + free(mt); + } +} + + +mtctxres_t * +___mtctxres() { + + mtctxres_t *mt; + + + if (mt_key_initialized) { + if ((thr_getspecific(key, (void **)&mt) == 0 && mt != 0) || + (__res_init_ctx(key) == 0 && + thr_getspecific(key, (void **)&mt) == 0 && mt != 0)) { + return (mt); + } + } + + return (&sharedctx); +} + + +/* + * There used to be a private, MT-safe resolver interface that used TSD + * to store per-thread _res, h_errno, etc. We continue to provide the + * access functions __res_get_res() and __res_get_h_errno() so that binaries + * that used the private interface will continue to work. + */ + +#ifdef _res +#undef _res +#endif + +extern struct __res_state *__res_state(void); + +struct __res_state * +__res_get_res(void) { + return (__res_state()); +} + + +#ifdef h_errno +#undef h_errno +#endif + +extern int *__h_errno(void); + +int * +__res_get_h_errno(void) { + return (__h_errno()); +} + + +#ifdef SUNW_HOSTS_FALLBACK + +/* + * When the name service switch calls libresolv, it doesn't want fallback + * to /etc/hosts, so we provide a method to turn it off. + */ + +void +__res_set_no_hosts_fallback(void) { + ___mtctxres()->no_hosts_fallback_private = 1; +} + +void +__res_unset_no_hosts_fallback(void) { + ___mtctxres()->no_hosts_fallback_private = 0; +} + +int +__res_no_hosts_fallback(void) { + return (___mtctxres()->no_hosts_fallback_private); +} + +#endif /* SUNW_HOSTS_FALLBACK */ + +#ifdef SUNW_OVERRIDE_RETRY + +/* + * The NS switch wants to be able to override the number of retries. + */ + +int +__res_override_retry(int retry) { + ___mtctxres()->retry_private = retry; + /* + * This function doesn't really need a return value; saving the + * old retry setting, and restoring it, is handled by __res_retry() + * and __res_retry_reset() below. However, the nss_dns library + * must have a private version of this function to be used when + * running with an old libresolv. That private nss_dns function + * needs a return value, and a function pointer is used to select + * the right function at runtime. Thus, __res_override_retry + * must have a function prototype consistent with the private + * nss_dns function, i.e., one that returns an int. + * + * Given that we do have a return value, that value must be zero. + * That's because retry_private == 0 is used to indicate that + * no override retry value is in effect, and the way we expect + * nss_dns to call us is: + * + * int oldretry = __res_override_retry(N); + * <whatever> + * (void)__res_override_retry(old_retry); + */ + return (0); +} + +int +__res_retry(int retry) { + mtctxres_t *mt = ___mtctxres(); + + mt->retry_save = retry; + return ((mt->retry_private != 0) ? mt->retry_private : retry); +} + +int +__res_retry_reset(void) { + mtctxres_t *mt = ___mtctxres(); + + return (mt->retry_save); +} + +#endif /* SUNW_OVERRIDE_RETRY */ diff --git a/usr/src/lib/libresolv2/common/sunw/sunw_updrec.c b/usr/src/lib/libresolv2/common/sunw/sunw_updrec.c new file mode 100644 index 0000000000..c9bc2b2038 --- /dev/null +++ b/usr/src/lib/libresolv2/common/sunw/sunw_updrec.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * As of BIND 8.2.2, ISC (a) removed res_mkupdate(), res_update(), and + * res_mkupdrec() from what they consider the supported interface. The + * functions still exist, but their calling interface has changed, since + * the ns_updrec structure has changed. + * + * It seems probable that res_mkupdate() etc. will return, though possibly + * with other changes, in some future BIND release. In order to avoid + * going to PSARC twice (once to remove the functions, and then again to + * add them back), we retain the old interface as a wrapper around the + * new one. + */ + +#include <port_before.h> + +#include <malloc.h> +#include <strings.h> +#include <sys/types.h> +#include <netinet/in.h> + +#include <res_update.h> +#undef ns_updrec +#undef res_mkupdate +#undef res_update +#undef res_mkupdrec +#undef res_freeupdrec +#include <arpa/nameser.h> + +#include <port_after.h> + +void res_freeupdrec(ns_updrec *); + + +static int +old2new(ns_updrec *old, __ISC_ns_updrec *new) { + + if (old->r_dname != 0) { + if ((new->r_dname = strdup(old->r_dname)) == 0) + return (-1); + } else { + new->r_dname = 0; + } + + new->r_glink.prev = + new->r_glink.next = + new->r_link.prev = + new->r_link.next = 0; + + new->r_section = old->r_section; + new->r_class = old->r_class; + new->r_type = old->r_type; + new->r_ttl = old->r_ttl; + new->r_data = old->r_data; + new->r_size = old->r_size; + new->r_opcode = old->r_opcode; + new->r_dp = old->r_dp; + new->r_deldp = old->r_deldp; + new->r_zone = old->r_zone; + + return (0); +} + + +static int +new2old(__ISC_ns_updrec *new, ns_updrec *old) { + /* XXX r_prev and r_next unchanged */ + if (new->r_dname != 0) { + if ((old->r_dname = strdup(new->r_dname)) == 0) + return (-1); + } else { + old->r_dname = 0; + } + old->r_section = new->r_section; + old->r_class = new->r_class; + old->r_type = new->r_type; + old->r_ttl = new->r_ttl; + old->r_data = new->r_data; + old->r_size = new->r_size; + old->r_opcode = new->r_opcode; + old->r_grpnext = 0; /* XXX */ + old->r_dp = new->r_dp; + old->r_deldp = new->r_deldp; + old->r_zone = new->r_zone; + + return (0); +} + + +static void +delete_list(__ISC_ns_updrec *list) { + + __ISC_ns_updrec *next; + + for (; list != 0; list = next) { + next = list->r_link.next; + __ISC_res_freeupdrec(list); + } +} + + +static __ISC_ns_updrec * +copy_list(ns_updrec *old) { + + __ISC_ns_updrec *list = 0, *r, *p; + + if (old == 0) + return (0); + + for (p = 0; old != 0; old = old->r_next, p = r) { + if ((r = calloc(1, sizeof (*r))) == 0 || + old2new(old, r) != 0) { + free(r); + delete_list(list); + return (0); + } + r->r_link.prev = p; + r->r_link.next = 0; + if (p != 0) + p->r_link.next = r; + else + list = r; + } + + return (list); +} + + +int +res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int length) { + + __ISC_ns_updrec *r; + int ret; + + if ((r = copy_list(rrecp_in)) == 0) + return (-1); + + ret = __ISC_res_mkupdate(r, buf, length); + + delete_list(r); + + return (ret); +} + + +int +res_update(ns_updrec *rrecp_in) { + + __ISC_ns_updrec *r; + int ret; + + if ((r = copy_list(rrecp_in)) == 0) + return (-1); + + ret = __ISC_res_update(r); + + delete_list(r); + + return (ret); +} + + + +ns_updrec * +res_mkupdrec(int section, const char *dname, uint_t class, uint_t type, + uint_t ttl) { + + __ISC_ns_updrec *n; + ns_updrec *o; + + n = __ISC_res_mkupdrec(section, dname, class, type, ttl); + if (n == 0) + return (0); + + if ((o = calloc(1, sizeof (*o))) != 0) { + if (new2old(n, o) != 0) { + res_freeupdrec(o); + o = 0; + } + } + + __ISC_res_freeupdrec(n); + + return (o); +} + + +void +res_freeupdrec(ns_updrec *rrecp) { + if (rrecp == 0) + return; + /* Note: freeing r_dp is the caller's responsibility. */ + if (rrecp->r_dname != NULL) + free(rrecp->r_dname); + free(rrecp); +} diff --git a/usr/src/lib/libresolv2/cylink/Makefile b/usr/src/lib/libresolv2/cylink/Makefile new file mode 100644 index 0000000000..cb38b82b0a --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/cylink/Makefile + +include ../../../Makefile.master +include ../../Makefile.lib + +SUBDIRS= spec $(MACH) $(BUILD64) $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +delete := TARGET= delete +install := TARGET= install +lint := TARGET= lint +_msg := TARGET= _msg +package := TARGET= package + +LIBRARY= cylink.a +TEXT_DOMAIN= SUNW_OST_OSLIB +XGETFLAGS= -a +POFILE= $(LIBRARY:.a=.po) +POFILES= generic.po + +SED= sed +GREP= grep +CP= cp + +.KEEP_STATE: + +all clean clobber delete install lint package: $(SUBDIRS) + +# install rule for install_h target +$(ROOTHDRDIR)/%: % + $(INS.file) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(MACH) $(MACH64) spec: FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +_msg: $(MSGDOMAIN) $(POFILE) + $(RM) $(MSGDOMAIN)/$(POFILE) + $(CP) $(POFILE) $(MSGDOMAIN) + +$(POFILE): $(POFILES) + $(RM) $@ + $(CAT) $(POFILES) > $@ + +$(POFILES): + $(RM) messages.po + $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]* + $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ + $(RM) messages.po + +FRC: diff --git a/usr/src/lib/libresolv2/cylink/Makefile.com b/usr/src/lib/libresolv2/cylink/Makefile.com new file mode 100644 index 0000000000..427ca32947 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/Makefile.com @@ -0,0 +1,69 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/cylink/Makefile.com +# + +LIBRARY= cylink.a +VERS= .1 + +DSTOBJS= cylink_link.o + +CYLINKOBJS= bits.o dss.o rand.o bn.o \ + lbn00.o lbnmem.o sha.o bn00.o \ + legal.o swap.o ctk_prime.o math.o + +OBJECTS= $(DSTOBJS) $(CYLINKOBJS) + +# include library definitions +include ../../../Makefile.lib + +LIBNAME= $(LIBRARY:%.a=%) +LIBS= $(DYNLIB) +LDLIBS += -lresolv -lc + +MAPDIR = ../spec/$(TRANSMACH) +SPECMAPFILE = $(MAPDIR)/mapfile +SRCDIR= ../../common/cylink +SRCS= $(DSTOBJS:%.o=../../common/dst/%.c) \ + $(CYLINKOBJS:%.o=$(SRCDIR)/%.c) + +ROOTLIBDIR= $(ROOT)/usr/lib/dns +ROOTLIBDIR64= $(ROOT)/usr/lib/dns/$(MACH64) + +# Local Libresolv definitions +SOLCOMPAT = -Dgethostbyname=res_gethostbyname \ + -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \ + -Dgethostbyname2=res_gethostbyname2\ + -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \ + -Dendhostent=res_endhostent -Dgethostent=res_gethostent \ + -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \ + -Dgetnetent=res_getnetent -Dsocket=_socket + +CRYPTINCL= -I../../common/cylink -I../../common/dnssafe +CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE \ + -D__SUNW_DST_INIT_NODEFINE + +CPPFLAGS += $(CRYPTFLAGS) $(CRYPTINCL) +CPPFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \ + $(SOLCOMPAT) -I../../include + +REDLOC= $(ZREDLOCSYM) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +$(ROOTLIBDIR) $(ROOTLIBDIR64): + $(INS.dir) + +include ../../../Makefile.targ + +pics/%.o: ../../common/dst/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) diff --git a/usr/src/lib/libresolv2/cylink/amd64/Makefile b/usr/src/lib/libresolv2/cylink/amd64/Makefile new file mode 100644 index 0000000000..2b37434e6b --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/amd64/Makefile @@ -0,0 +1,15 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +MAPDIR= ../spec/amd64 + +include ../Makefile.com +include ../../../Makefile.lib.64 + +all: $(LIBS) + +install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64) diff --git a/usr/src/lib/libresolv2/cylink/i386/Makefile b/usr/src/lib/libresolv2/cylink/i386/Makefile new file mode 100644 index 0000000000..ef5c431bf7 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/i386/Makefile @@ -0,0 +1,12 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/cylink/i386/Makefile +# + +include ../Makefile.com + +install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS) diff --git a/usr/src/lib/libresolv2/cylink/sparc/Makefile b/usr/src/lib/libresolv2/cylink/sparc/Makefile new file mode 100644 index 0000000000..5f69358368 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/sparc/Makefile @@ -0,0 +1,12 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/cylink/sparc/Makefile +# + +include ../Makefile.com + +install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS) diff --git a/usr/src/lib/libresolv2/cylink/sparcv9/Makefile b/usr/src/lib/libresolv2/cylink/sparcv9/Makefile new file mode 100644 index 0000000000..a99c57a229 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/sparcv9/Makefile @@ -0,0 +1,13 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/cylink/sparcv9/Makefile +# + +include ../Makefile.com +include ../../../Makefile.lib.64 + +install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64) diff --git a/usr/src/lib/libresolv2/cylink/spec/Makefile b/usr/src/lib/libresolv2/cylink/spec/Makefile new file mode 100644 index 0000000000..335473f4cc --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/spec/Makefile @@ -0,0 +1,8 @@ +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/cylink/spec/Makefile + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/lib/libresolv2/cylink/spec/Makefile.targ b/usr/src/lib/libresolv2/cylink/spec/Makefile.targ new file mode 100644 index 0000000000..25ade9b830 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/spec/Makefile.targ @@ -0,0 +1,12 @@ +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/cylink/spec/Makefile.targ + +LIBRARY = cylink.a +VERS = .1 + +OBJECTS = cylink.o + diff --git a/usr/src/lib/libresolv2/cylink/spec/amd64/Makefile b/usr/src/lib/libresolv2/cylink/spec/amd64/Makefile new file mode 100644 index 0000000000..84ccf3ca89 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/spec/amd64/Makefile @@ -0,0 +1,26 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#amd64_C_PICFLAGS = $(amd64_C_BIGPICFLAGS) + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libresolv2/cylink/spec/cylink.spec b/usr/src/lib/libresolv2/cylink/spec/cylink.spec new file mode 100644 index 0000000000..aaa45150f4 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/spec/cylink.spec @@ -0,0 +1,11 @@ +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/cylink/spec/cylink.spec + +function dst_cylink_init +version SUNWprivate_1.1 +end diff --git a/usr/src/lib/libresolv2/cylink/spec/i386/Makefile b/usr/src/lib/libresolv2/cylink/spec/i386/Makefile new file mode 100644 index 0000000000..1c7d394c11 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/spec/i386/Makefile @@ -0,0 +1,26 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/cylink/spec/i386/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libresolv2/cylink/spec/sparc/Makefile b/usr/src/lib/libresolv2/cylink/spec/sparc/Makefile new file mode 100644 index 0000000000..59d2b5cd6c --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/spec/sparc/Makefile @@ -0,0 +1,26 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 2000 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/cylink/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libresolv2/cylink/spec/sparcv9/Makefile b/usr/src/lib/libresolv2/cylink/spec/sparcv9/Makefile new file mode 100644 index 0000000000..311dcf33e4 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/spec/sparcv9/Makefile @@ -0,0 +1,27 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/cylink/spec/sparcv9/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#sparcv9_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libresolv2/cylink/spec/versions b/usr/src/lib/libresolv2/cylink/spec/versions new file mode 100644 index 0000000000..6a318d48a3 --- /dev/null +++ b/usr/src/lib/libresolv2/cylink/spec/versions @@ -0,0 +1,19 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +sparc { + SUNWprivate_1.1; +} +sparcv9 { + SUNWprivate_1.1; +} +i386 { + SUNWprivate_1.1; +} +amd64 { + SUNWprivate_1.1; +} diff --git a/usr/src/lib/libresolv2/dnssafe/Makefile b/usr/src/lib/libresolv2/dnssafe/Makefile new file mode 100644 index 0000000000..03fb3d5f5b --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/dnssafe/Makefile + +include ../../../Makefile.master +include ../../Makefile.lib + +SUBDIRS= spec $(MACH) $(BUILD64) $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +delete := TARGET= delete +install := TARGET= install +lint := TARGET= lint +_msg := TARGET= _msg +package := TARGET= package + +LIBRARY= dnssafe.a +TEXT_DOMAIN= SUNW_OST_OSLIB +XGETFLAGS= -a +POFILE= $(LIBRARY:.a=.po) +POFILES= generic.po + +SED= sed +GREP= grep +CP= cp + +.KEEP_STATE: + +all clean clobber delete install lint package: $(SUBDIRS) + +# install rule for install_h target +$(ROOTHDRDIR)/%: % + $(INS.file) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(MACH) $(MACH64) spec: FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +_msg: $(MSGDOMAIN) $(POFILE) + $(RM) $(MSGDOMAIN)/$(POFILE) + $(CP) $(POFILE) $(MSGDOMAIN) + +$(POFILE): $(POFILES) + $(RM) $@ + $(CAT) $(POFILES) > $@ + +$(POFILES): + $(RM) messages.po + $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]* + $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ + $(RM) messages.po + +FRC: diff --git a/usr/src/lib/libresolv2/dnssafe/Makefile.com b/usr/src/lib/libresolv2/dnssafe/Makefile.com new file mode 100644 index 0000000000..1d85bdbc47 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/Makefile.com @@ -0,0 +1,88 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/dnssafe/Makefile.com +# + +LIBRARY= dnssafe.a +VERS= .1 + +DSTOBJS= bsafe_link.o hmac_link.o rsaref_link.o eay_dss_link.o + +DNSSAFEOBJS= ahcbcpad.o ahchdig.o ahchencr.o ahchgen.o \ + ahchrand.o ahdigest.o ahencryp.o ahgen.o \ + ahrandom.o ahrsaenc.o ahrsaepr.o ahrsaepu.o \ + aichdig.o aichenc8.o aichencn.o aichencr.o \ + aichgen.o aichrand.o aimd5.o aimd5ran.o \ + ainfotyp.o ainull.o airsaepr.o airsaepu.o \ + airsakgn.o airsaprv.o airsapub.o algchoic.o \ + algobj.o amcrte.o ammd5.o ammd5r.o \ + amrkg.o amrsae.o balg.o bgclrbit.o \ + bgmdmpyx.o bgmdsqx.o bgmodexp.o bgpegcd.o \ + big2exp.o bigabs.o bigacc.o bigarith.o \ + bigcmp.o bigconst.o biginv.o biglen.o \ + bigmodx.o bigmpy.o bigpdiv.o bigpmpy.o \ + bigpmpyh.o bigpmpyl.o bigpsq.o bigqrx.o \ + bigsmod.o bigtocan.o bigu.o bigunexp.o \ + binfocsh.o bkey.o bmempool.o cantobig.o \ + crt2.o digest.o digrand.o encrypt.o \ + generate.o intbits.o intitem.o keyobj.o \ + ki8byte.o kifulprv.o kiitem.o kinfotyp.o \ + kipkcrpr.o kirsacrt.o kirsapub.o \ + md5rand.o prime.o random.o rsa.o \ + rsakeygn.o seccbcd.o seccbce.o surrendr.o + +OBJECTS= $(DSTOBJS) $(DNSSAFEOBJS) + +include ../../../Makefile.lib + +LIBNAME= $(LIBRARY:%.a=%) +LIBS= $(DYNLIB) +LDLIBS += -lmd5 -lresolv -lc + +MAPDIR = ../spec/$(TRANSMACH) +SPECMAPFILE = $(MAPDIR)/mapfile +SRCDIR= ../../common/dnssafe +SRCS= $(DSTOBJS:%.o=../../common/dst/%.c) \ + $(DNSSAFEOBJS:%o=$(SRCDIR)/%.c) + +ROOTLIBDIR= $(ROOT)/usr/lib/dns +ROOTLIBDIR64= $(ROOT)/usr/lib/dns/$(MACH64) + + +# Local Libresolv definitions +SOLCOMPAT = -Dgethostbyname=res_gethostbyname \ + -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \ + -Dgethostbyname2=res_gethostbyname2\ + -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \ + -Dendhostent=res_endhostent -Dgethostent=res_gethostent \ + -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \ + -Dgetnetent=res_getnetent -Dsocket=_socket + +CRYPTINCL= -I../../common/cylink -I../../common/dnssafe +CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE \ + -D__SUNW_DST_INIT_NODEFINE + +CPPFLAGS += $(CRYPTFLAGS) $(CRYPTINCL) +CPPFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \ + $(SOLCOMPAT) -I../../include + +REDLOC= $(ZREDLOCSYM) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +$(ROOTLIBDIR) $(ROOTLIBDIR64): + $(INS.dir) + +include ../../../Makefile.targ + +pics/%.o: ../../common/dst/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) diff --git a/usr/src/lib/libresolv2/dnssafe/amd64/Makefile b/usr/src/lib/libresolv2/dnssafe/amd64/Makefile new file mode 100644 index 0000000000..2b37434e6b --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/amd64/Makefile @@ -0,0 +1,15 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +MAPDIR= ../spec/amd64 + +include ../Makefile.com +include ../../../Makefile.lib.64 + +all: $(LIBS) + +install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64) diff --git a/usr/src/lib/libresolv2/dnssafe/i386/Makefile b/usr/src/lib/libresolv2/dnssafe/i386/Makefile new file mode 100644 index 0000000000..5377e53c07 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/i386/Makefile @@ -0,0 +1,12 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/dnssafe/i386/Makefile +# + +include ../Makefile.com + +install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS) diff --git a/usr/src/lib/libresolv2/dnssafe/sparc/Makefile b/usr/src/lib/libresolv2/dnssafe/sparc/Makefile new file mode 100644 index 0000000000..f8244e9564 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/sparc/Makefile @@ -0,0 +1,12 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/dnssafe/sparc/Makefile +# + +include ../Makefile.com + +install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS) diff --git a/usr/src/lib/libresolv2/dnssafe/sparcv9/Makefile b/usr/src/lib/libresolv2/dnssafe/sparcv9/Makefile new file mode 100644 index 0000000000..2737e64129 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/sparcv9/Makefile @@ -0,0 +1,13 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/dnssafe/sparcv9/Makefile +# + +include ../Makefile.com +include ../../../Makefile.lib.64 + +install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64) diff --git a/usr/src/lib/libresolv2/dnssafe/spec/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/Makefile new file mode 100644 index 0000000000..8ad8521042 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/spec/Makefile @@ -0,0 +1,8 @@ +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/dnssafe/spec/Makefile + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/lib/libresolv2/dnssafe/spec/Makefile.targ b/usr/src/lib/libresolv2/dnssafe/spec/Makefile.targ new file mode 100644 index 0000000000..84dd50716e --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/spec/Makefile.targ @@ -0,0 +1,12 @@ +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/dnssafe/spec/Makefile.targ + +LIBRARY = dnssafe.a +VERS = .1 + +OBJECTS = dnssafe.o + diff --git a/usr/src/lib/libresolv2/dnssafe/spec/amd64/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/amd64/Makefile new file mode 100644 index 0000000000..84ccf3ca89 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/spec/amd64/Makefile @@ -0,0 +1,26 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#amd64_C_PICFLAGS = $(amd64_C_BIGPICFLAGS) + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libresolv2/dnssafe/spec/dnssafe.spec b/usr/src/lib/libresolv2/dnssafe/spec/dnssafe.spec new file mode 100644 index 0000000000..55b7a26fe0 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/spec/dnssafe.spec @@ -0,0 +1,23 @@ +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/dnssafe/spec/dnssafe.spec + +function dst_bsafe_init +version SUNWprivate_1.1 +end + +function dst_eay_dss_init +version SUNWprivate_1.1 +end + +function dst_md5_hmac_init +version SUNWprivate_1.1 +end + +function dst_rsaref_init +version SUNWprivate_1.1 +end diff --git a/usr/src/lib/libresolv2/dnssafe/spec/i386/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/i386/Makefile new file mode 100644 index 0000000000..d60f7c85f9 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/spec/i386/Makefile @@ -0,0 +1,26 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/dnssafe/spec/i386/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libresolv2/dnssafe/spec/sparc/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/sparc/Makefile new file mode 100644 index 0000000000..6046f459ec --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/spec/sparc/Makefile @@ -0,0 +1,26 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/dnssafe/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libresolv2/dnssafe/spec/sparcv9/Makefile b/usr/src/lib/libresolv2/dnssafe/spec/sparcv9/Makefile new file mode 100644 index 0000000000..e405d11dc7 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/spec/sparcv9/Makefile @@ -0,0 +1,27 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/dnssafe/spec/sparcv9/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#sparcv9_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libresolv2/dnssafe/spec/versions b/usr/src/lib/libresolv2/dnssafe/spec/versions new file mode 100644 index 0000000000..6a318d48a3 --- /dev/null +++ b/usr/src/lib/libresolv2/dnssafe/spec/versions @@ -0,0 +1,19 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +sparc { + SUNWprivate_1.1; +} +sparcv9 { + SUNWprivate_1.1; +} +i386 { + SUNWprivate_1.1; +} +amd64 { + SUNWprivate_1.1; +} diff --git a/usr/src/lib/libresolv2/i386/Makefile b/usr/src/lib/libresolv2/i386/Makefile new file mode 100644 index 0000000000..417285a02e --- /dev/null +++ b/usr/src/lib/libresolv2/i386/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (c) 1997-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/sparc/Makefile + +MAPDIR= ../spec/i386 + +include ../Makefile.com + +.KEEP_STATE: + +all: $(LIBS) + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libresolv2/include/Makefile b/usr/src/lib/libresolv2/include/Makefile new file mode 100644 index 0000000000..65931f43f0 --- /dev/null +++ b/usr/src/lib/libresolv2/include/Makefile @@ -0,0 +1,41 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../../../Makefile.master + +HDRS= os_version.h port_ipv6.h +TMPHDRS= new_os_version.h new_port_ipv6.h + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install + +.KEEP_STATE: + +all lint: $(HDRS) + +install: all + +clean: + $(RM) $(HDRS) $(TMPHDRS) + +clobber: clean + +# os_version.h and port_ipv6.h should be rebuilt when you change OS +# revision. Since that's not easily expressed as a dependency, we +# rebuild them every time. + +os_version.h: make_os_version FRC + $(CHMOD) a+x make_os_version + ./make_os_version + +port_ipv6.h: probe_ipv6 FRC + $(CHMOD) a+x probe_ipv6 + CC="$(CC)" ./probe_ipv6 + +FRC: diff --git a/usr/src/lib/libresolv2/include/conf/sunoptions.h b/usr/src/lib/libresolv2/include/conf/sunoptions.h new file mode 100644 index 0000000000..9e4257b81d --- /dev/null +++ b/usr/src/lib/libresolv2/include/conf/sunoptions.h @@ -0,0 +1,63 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SUNOPTIONS_H +#define _SUNOPTIONS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * The following options are PP flags available in the reference implementation + * but do not get compiled due to the elimination of the options.h file + * This section selectively reintroduces them + */ + +#define HAVE_GETRUSAGE + +/* + * The following options are PP flags introduced as part of the Sun/Solaris + * port. + */ + +/* We may have to pull this out */ +#define SUNW_LIBNSL /* conflicts for inet_addr, inet_ntoa */ + +/* Additions for Solaris 2 */ +#define SUNW_NSSEARCH /* fix nslookup domain search */ +#define SUNW_AVOIDOVERFLOW /* Avoid buffer overflows */ +#define SUNW_INITCHKIF /* Check if any non-loopback interface is up */ +#define SUNW_DOMAINFROMNIS /* Default domain name from NIS/NIS+ */ +#define USELOOPBACK /* Resolver library defaults to 127.0.0.1 */ +#define SUNW_CONFCHECK /* Abort quickly if no /etc/resolv.conf or local */ + /* named */ +#define SUNW_AREWEINNAMED /* Override _confcheck if proc is in.named */ +#define SUNW_OPENFDOFFSET /* Open non-stdio fd:s with offset */ +#define SUNW_POLL /* Use poll(2) instead of select(3) */ +#define SUNW_SYNONYMS /* Include synonyms.h (libresolv) */ +#define SUNW_HOSTS_FALLBACK /* Configurable /etc/hosts fallback */ +#define SUNW_LISTEN_BACKLOG /* Configurable listen(3N) backlog (named) */ +#define SUNW_REJECT_BOGUS_H_LENGTH /* (libresolv) */ +#define SUNW_HNOK_UNDERSCORE /* Allow underscore in hostnames (libresolv) */ +#define SUNW_MT_RESOLVER /* MT hot extensions (libresolv) */ +#define SUNW_QSTREAM_CLEANUP /* Avoid using free()d struct qstreams */ +#define SUNW_SETHERRNO /* ISC does not set h_errno in gethostbyname */ +#define SUNW_OVERRIDE_RETRY /* Allow NS switch to override res->retry */ +#define SUNW_CLOSEFROM /* closefrom(3C) per PSARC 2000/193 */ +#define SUNW_AVOIDSTDIO_FDLIMIT /* Avoid 256 file descriptor limit in stdio */ +#define SUNW_LIBMD5 /* Use md5(3EXT) instead of internal implementation */ + +/* If compiling an MT warm libresolv, we also need reentrancy */ +#if defined(SUNW_MT_RESOLVER) && !defined(_REENTRANT) +#define _REENTRANT +#endif + +/* SUNW_AREWEINNAMED and SUNW_CONFCHECCK are mutually inclusive */ +#if defined(SUNW_AREWEINNAMED) && !defined(SUNW_CONFCHECK) +#define SUNW_CONFCHECK +#endif + +/* End additions for Solaris 2 */ + +#endif /* _SUNOPTIONS_H */ diff --git a/usr/src/lib/libresolv2/include/err.h b/usr/src/lib/libresolv2/include/err.h new file mode 100644 index 0000000000..45992ea336 --- /dev/null +++ b/usr/src/lib/libresolv2/include/err.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/*- + * Copyright (c) 1993 + * The 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. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _ERR_H_ +#define _ERR_H_ + +#include <sys/cdefs.h> +#include <stdarg.h> + +__BEGIN_DECLS +__dead void err __P((int, const char *, ...)) __attribute__((__volatile)); +__dead void verr __P((int, const char *, va_list)) + __attribute__((__volatile)); +__dead void errx __P((int, const char *, ...)) __attribute__((__volatile)); +__dead void verrx __P((int, const char *, va_list)) + __attribute__((__volatile)); +void warn __P((const char *, ...)); +void vwarn __P((const char *, va_list)); +void warnx __P((const char *, ...)); +void vwarnx __P((const char *, va_list)); +__END_DECLS + +#endif /* !_ERR_H_ */ diff --git a/usr/src/lib/libresolv2/include/fd_setsize.h b/usr/src/lib/libresolv2/include/fd_setsize.h new file mode 100644 index 0000000000..f6af1b2488 --- /dev/null +++ b/usr/src/lib/libresolv2/include/fd_setsize.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + * + * No ISC copyright for this file. + */ + +#ifndef _FD_SETSIZE_H +#define _FD_SETSIZE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * If you need a bigger FD_SETSIZE, this is NOT the place to set it. + * This file is a fallback for BIND ports which don't specify their own. + */ + +#endif /* _FD_SETSIZE_H */ diff --git a/usr/src/lib/libresolv2/include/hesiod.h b/usr/src/lib/libresolv2/include/hesiod.h new file mode 100644 index 0000000000..5f113734c8 --- /dev/null +++ b/usr/src/lib/libresolv2/include/hesiod.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. + */ + +/* + * $Id: hesiod.h,v 1.7 1999/01/08 19:22:45 vixie Exp $ + */ + +#ifndef _HESIOD_H_INCLUDED +#define _HESIOD_H_INCLUDED + +int hesiod_init __P((void **context)); +void hesiod_end __P((void *context)); +char * hesiod_to_bind __P((void *context, const char *name, + const char *type)); +char ** hesiod_resolve __P((void *context, const char *name, + const char *type)); +void hesiod_free_list __P((void *context, char **list)); +struct __res_state * __hesiod_res_get __P((void *context)); +void __hesiod_res_set __P((void *context, struct __res_state *, + void (*)(void *))); + +#endif /*_HESIOD_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2/include/inet_private.h b/usr/src/lib/libresolv2/include/inet_private.h new file mode 100644 index 0000000000..c9c03ab478 --- /dev/null +++ b/usr/src/lib/libresolv2/include/inet_private.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _INET_PRIVATE_H +#define _INET_PRIVATE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Functions defined by the ISC for BIND 8.2, but which do not appear + * in RFC 2553 (hence, aren't suitable for inclusion in <inet.h>). + */ + +#ifdef __STDC__ +#ifndef __P +#define __P(x) x +#endif +#else +#ifndef __P +#define __P(x) () +#endif +#endif /* __STDC__ */ + +char * inet_net_ntop __P((int, const void *, int, char *, size_t)); +int inet_net_pton __P((int, const char *, void *, size_t)); +u_int inet_nsap_addr __P((const char *, u_char *, int)); +char * inet_nsap_ntoa __P((int, const u_char *, char *)); + +#endif /* _INET_PRIVATE_H */ diff --git a/usr/src/lib/libresolv2/include/irp.h b/usr/src/lib/libresolv2/include/irp.h new file mode 100644 index 0000000000..76b7b23441 --- /dev/null +++ b/usr/src/lib/libresolv2/include/irp.h @@ -0,0 +1,112 @@ +/* + * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + */ + +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irp.h,v 8.4 2003/05/02 05:56:21 marka Exp $ + */ + +#ifndef _IRP_H_INCLUDED +#define _IRP_H_INCLUDED + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define IRPD_TIMEOUT 30 /* seconds */ +#define IRPD_MAXSESS 50 /* number of simultaneous sessions. */ +#define IRPD_PORT 6660 /* 10 times the number of the beast. */ +#define IRPD_PATH "/var/run/irpd" /* af_unix socket path */ + +/* If sets the environment variable IRPDSERVER to an IP address + (e.g. "192.5.5.1"), then that's the host the client expects irpd to be + running on. */ +#define IRPD_HOST_ENV "IRPDSERVER" + +/* Protocol response codes. */ +#define IRPD_WELCOME_CODE 200 +#define IRPD_NOT_WELCOME_CODE 500 + +#define IRPD_GETHOST_ERROR 510 +#define IRPD_GETHOST_NONE 210 +#define IRPD_GETHOST_OK 211 +#define IRPD_GETHOST_SETOK 212 + +#define IRPD_GETNET_ERROR 520 +#define IRPD_GETNET_NONE 220 +#define IRPD_GETNET_OK 221 +#define IRPD_GETNET_SETOK 222 + +#define IRPD_GETUSER_ERROR 530 +#define IRPD_GETUSER_NONE 230 +#define IRPD_GETUSER_OK 231 +#define IRPD_GETUSER_SETOK 232 + +#define IRPD_GETGROUP_ERROR 540 +#define IRPD_GETGROUP_NONE 240 +#define IRPD_GETGROUP_OK 241 +#define IRPD_GETGROUP_SETOK 242 + +#define IRPD_GETSERVICE_ERROR 550 +#define IRPD_GETSERVICE_NONE 250 +#define IRPD_GETSERVICE_OK 251 +#define IRPD_GETSERVICE_SETOK 252 + +#define IRPD_GETPROTO_ERROR 560 +#define IRPD_GETPROTO_NONE 260 +#define IRPD_GETPROTO_OK 261 +#define IRPD_GETPROTO_SETOK 262 + +#define IRPD_GETNETGR_ERROR 570 +#define IRPD_GETNETGR_NONE 270 +#define IRPD_GETNETGR_OK 271 +#define IRPD_GETNETGR_NOMORE 272 +#define IRPD_GETNETGR_MATCHES 273 +#define IRPD_GETNETGR_NOMATCH 274 +#define IRPD_GETNETGR_SETOK 275 +#define IRPD_GETNETGR_SETERR 276 + +#define irs_irp_read_body __irs_irp_read_body +#define irs_irp_read_response __irs_irp_read_response +#define irs_irp_disconnect __irs_irp_disconnect +#define irs_irp_connect __irs_irp_connect +#define irs_irp_connection_setup __irs_irp_connection_setup +#define irs_irp_send_command __irs_irp_send_command + +struct irp_p; + +char *irs_irp_read_body(struct irp_p *pvt, size_t *size); +int irs_irp_read_response(struct irp_p *pvt, char *text, size_t len); +void irs_irp_disconnect(struct irp_p *pvt); +int irs_irp_connect(struct irp_p *pvt); +int irs_irp_is_connected(struct irp_p *pvt); +int irs_irp_connection_setup(struct irp_p *cxndata, int *warned); +#ifdef __GNUC__ +int irs_irp_send_command(struct irp_p *, const char *, ...) + __attribute__((__format__(__printf__, 2, 3))); +#else +int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...); +#endif +int irs_irp_get_full_response(struct irp_p *pvt, int *code, char *text, + size_t textlen, char **body, + size_t *bodylen); +int irs_irp_read_line(struct irp_p *pvt, char *buffer, int len); + +#endif diff --git a/usr/src/lib/libresolv2/include/irs.h b/usr/src/lib/libresolv2/include/irs.h new file mode 100644 index 0000000000..d676136ac9 --- /dev/null +++ b/usr/src/lib/libresolv2/include/irs.h @@ -0,0 +1,383 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: irs.h,v 8.9 2003/04/29 05:51:13 marka Exp $ + */ + +#ifndef _IRS_H_INCLUDED +#define _IRS_H_INCLUDED + +#include <sys/types.h> + +#include <arpa/nameser.h> + +#include <grp.h> +#include <netdb.h> +#include <resolv.h> +#include <pwd.h> + +/* + * This is the group map class. + */ +struct irs_gr { + void * private; + void (*close) __P((struct irs_gr *)); + struct group * (*next) __P((struct irs_gr *)); + struct group * (*byname) __P((struct irs_gr *, const char *)); + struct group * (*bygid) __P((struct irs_gr *, gid_t)); + int (*list) __P((struct irs_gr *, const char *, + gid_t, gid_t *, int *)); + void (*rewind) __P((struct irs_gr *)); + void (*minimize) __P((struct irs_gr *)); + struct __res_state * (*res_get) __P((struct irs_gr *)); + void (*res_set) __P((struct irs_gr *, res_state, + void (*)(void *))); +}; + +/* + * This is the password map class. + */ +struct irs_pw { + void * private; + void (*close) __P((struct irs_pw *)); + struct passwd * (*next) __P((struct irs_pw *)); + struct passwd * (*byname) __P((struct irs_pw *, const char *)); + struct passwd * (*byuid) __P((struct irs_pw *, uid_t)); + void (*rewind) __P((struct irs_pw *)); + void (*minimize) __P((struct irs_pw *)); + struct __res_state * (*res_get) __P((struct irs_pw *)); + void (*res_set) __P((struct irs_pw *, res_state, + void (*)(void *))); +}; + +/* + * This is the service map class. + */ +struct irs_sv { + void * private; + void (*close) __P((struct irs_sv *)); + struct servent *(*byname) __P((struct irs_sv *, + const char *, const char *)); + struct servent *(*byport) __P((struct irs_sv *, int, const char *)); + struct servent *(*next) __P((struct irs_sv *)); + void (*rewind) __P((struct irs_sv *)); + void (*minimize) __P((struct irs_sv *)); + struct __res_state * (*res_get) __P((struct irs_sv *)); + void (*res_set) __P((struct irs_sv *, res_state, + void (*)(void *))); +}; + +/* + * This is the protocols map class. + */ +struct irs_pr { + void * private; + void (*close) __P((struct irs_pr *)); + struct protoent *(*byname) __P((struct irs_pr *, const char *)); + struct protoent *(*bynumber) __P((struct irs_pr *, int)); + struct protoent *(*next) __P((struct irs_pr *)); + void (*rewind) __P((struct irs_pr *)); + void (*minimize) __P((struct irs_pr *)); + struct __res_state * (*res_get) __P((struct irs_pr *)); + void (*res_set) __P((struct irs_pr *, res_state, + void (*)(void *))); +}; + +/* + * This is the hosts map class. + */ +struct irs_ho { + void * private; + void (*close) __P((struct irs_ho *)); + struct hostent *(*byname) __P((struct irs_ho *, const char *)); + struct hostent *(*byname2) __P((struct irs_ho *, const char *, int)); + struct hostent *(*byaddr) __P((struct irs_ho *, + const void *, int, int)); + struct hostent *(*next) __P((struct irs_ho *)); + void (*rewind) __P((struct irs_ho *)); + void (*minimize) __P((struct irs_ho *)); + struct __res_state * (*res_get) __P((struct irs_ho *)); + void (*res_set) __P((struct irs_ho *, res_state, + void (*)(void *))); + struct addrinfo *(*addrinfo) __P((struct irs_ho *, const char *, + const struct addrinfo *)); +}; + +/* + * This is the networks map class. + */ +struct irs_nw { + void * private; + void (*close) __P((struct irs_nw *)); + struct nwent * (*byname) __P((struct irs_nw *, const char *, int)); + struct nwent * (*byaddr) __P((struct irs_nw *, void *, int, int)); + struct nwent * (*next) __P((struct irs_nw *)); + void (*rewind) __P((struct irs_nw *)); + void (*minimize) __P((struct irs_nw *)); + struct __res_state * (*res_get) __P((struct irs_nw *)); + void (*res_set) __P((struct irs_nw *, res_state, + void (*)(void *))); +}; + +/* + * This is the netgroups map class. + */ +struct irs_ng { + void * private; + void (*close) __P((struct irs_ng *)); + int (*next) __P((struct irs_ng *, const char **, + const char **, const char **)); + int (*test) __P((struct irs_ng *, const char *, + const char *, const char *, + const char *)); + void (*rewind) __P((struct irs_ng *, const char *)); + void (*minimize) __P((struct irs_ng *)); +}; + +/* + * This is the generic map class, which copies the front of all others. + */ +struct irs_map { + void * private; + void (*close) __P((void *)); +}; + +/* + * This is the accessor class. It contains pointers to all of the + * initializers for the map classes for a particular accessor. + */ +struct irs_acc { + void * private; + void (*close) __P((struct irs_acc *)); + struct irs_gr * (*gr_map) __P((struct irs_acc *)); + struct irs_pw * (*pw_map) __P((struct irs_acc *)); + struct irs_sv * (*sv_map) __P((struct irs_acc *)); + struct irs_pr * (*pr_map) __P((struct irs_acc *)); + struct irs_ho * (*ho_map) __P((struct irs_acc *)); + struct irs_nw * (*nw_map) __P((struct irs_acc *)); + struct irs_ng * (*ng_map) __P((struct irs_acc *)); + struct __res_state * (*res_get) __P((struct irs_acc *)); + void (*res_set) __P((struct irs_acc *, res_state, + void (*)(void *))); +}; + +/* + * This is because the official definition of "struct netent" has no + * concept of CIDR even though it allows variant address families (on + * output but not input). The compatibility stubs convert the structs + * below into "struct netent"'s. + */ +struct nwent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + int n_addrtype; /* net address type */ + void *n_addr; /* network address */ + int n_length; /* address length, in bits */ +}; + +/* + * Hide external function names from POSIX. + */ +#define irs_gen_acc __irs_gen_acc +#define irs_lcl_acc __irs_lcl_acc +#define irs_dns_acc __irs_dns_acc +#define irs_nis_acc __irs_nis_acc +#define irs_irp_acc __irs_irp_acc +#ifdef ORIGINAL_ISC_CODE +#define irs_destroy __irs_destroy +#else +#endif +#define irs_dns_gr __irs_dns_gr +#define irs_dns_ho __irs_dns_ho +#define irs_dns_nw __irs_dns_nw +#define irs_dns_pr __irs_dns_pr +#define irs_dns_pw __irs_dns_pw +#define irs_dns_sv __irs_dns_sv +#define irs_gen_gr __irs_gen_gr +#define irs_gen_ho __irs_gen_ho +#define irs_gen_ng __irs_gen_ng +#define irs_gen_nw __irs_gen_nw +#define irs_gen_pr __irs_gen_pr +#define irs_gen_pw __irs_gen_pw +#define irs_gen_sv __irs_gen_sv +#define irs_irp_get_full_response __irs_irp_get_full_response +#define irs_irp_gr __irs_irp_gr +#define irs_irp_ho __irs_irp_ho +#define irs_irp_is_connected __irs_irp_is_connected +#define irs_irp_ng __irs_irp_ng +#define irs_irp_nw __irs_irp_nw +#define irs_irp_pr __irs_irp_pr +#define irs_irp_pw __irs_irp_pw +#define irs_irp_read_line __irs_irp_read_line +#define irs_irp_sv __irs_irp_sv +#define irs_lcl_gr __irs_lcl_gr +#define irs_lcl_ho __irs_lcl_ho +#define irs_lcl_ng __irs_lcl_ng +#define irs_lcl_nw __irs_lcl_nw +#define irs_lcl_pr __irs_lcl_pr +#define irs_lcl_pw __irs_lcl_pw +#define irs_lcl_sv __irs_lcl_sv +#define irs_nis_gr __irs_nis_gr +#define irs_nis_ho __irs_nis_ho +#define irs_nis_ng __irs_nis_ng +#define irs_nis_nw __irs_nis_nw +#define irs_nis_pr __irs_nis_pr +#define irs_nis_pw __irs_nis_pw +#define irs_nis_sv __irs_nis_sv +#define net_data_create __net_data_create +#define net_data_destroy __net_data_destroy +#ifdef ORIGINAL_ISC_CODE +#define net_data_minimize __net_data_minimize +#else +#endif + +/* + * Externs. + */ +extern struct irs_acc * irs_gen_acc __P((const char *options, + const char *conf_file)); +extern struct irs_acc * irs_lcl_acc __P((const char *options)); +extern struct irs_acc * irs_dns_acc __P((const char *options)); +extern struct irs_acc * irs_nis_acc __P((const char *options)); +extern struct irs_acc * irs_irp_acc __P((const char *options)); + +extern void irs_destroy(void); + +/* + * These forward declarations are for the semi-private functions in + * the get*.c files. Each of these funcs implements the real get* + * functionality and the standard versions are just wrappers that + * call these. Apart from the wrappers, only irpd is expected to + * call these directly, hence these decls are put here and not in + * the /usr/include replacements. + */ + +struct net_data; /* forward */ + +/* + * net_data_create gets a singleton net_data object. net_data_init + * creates as many net_data objects as times it is called. Clients using + * the default interface will use net_data_create by default. Servers will + * probably want net_data_init (one call per client) + */ +struct net_data *net_data_create(const char *conf_file); +struct net_data *net_data_init(const char *conf_file); +void net_data_destroy(void *p); + +extern struct group *getgrent_p __P((struct net_data *net_data)); +extern struct group *getgrnam_p __P((const char *name, + struct net_data *net_data)); +extern struct group *getgrgid_p __P((gid_t gid, + struct net_data *net_data)); +extern int setgroupent_p __P((int stayopen, + struct net_data *net_data)); +extern void endgrent_p __P((struct net_data *net_data)); +extern int getgrouplist_p __P((const char *name, + gid_t basegid, + gid_t *groups, + int *ngroups, + struct net_data *net_data)); + +#ifdef SETGRENT_VOID +extern void setgrent_p __P((struct net_data *net_data)); +#else +extern int setgrent_p __P((struct net_data *net_data)); +#endif + +extern struct hostent *gethostbyname_p __P((const char *name, + struct net_data *net_data)); +extern struct hostent *gethostbyname2_p __P((const char *name, int af, + struct net_data *net_data)); +extern struct hostent *gethostbyaddr_p __P((const char *addr, int len, + int af, + struct net_data *net_data)); +extern struct hostent *gethostent_p __P((struct net_data *net_data)); +extern void sethostent_p __P((int stayopen, + struct net_data *net_data)); +extern void endhostent_p __P((struct net_data *net_data)); +extern struct hostent *getipnodebyname_p __P((const char *name, int af, + int flags, int *errp, + struct net_data *net_data)); +extern struct hostent *getipnodebyaddr_p __P((const void *addr, size_t len, + int af, int *errp, + struct net_data *net_data)); + +extern struct netent *getnetent_p __P((struct net_data *net_data)); +extern struct netent *getnetbyname_p __P((const char *name, + struct net_data *net_data)); +extern struct netent *getnetbyaddr_p __P((unsigned long net, int type, + struct net_data *net_data)); +extern void setnetent_p __P((int stayopen, + struct net_data *net_data)); +extern void endnetent_p __P((struct net_data *net_data)); + +extern void setnetgrent_p __P((const char *netgroup, + struct net_data *net_data)); +extern void endnetgrent_p __P((struct net_data *net_data)); +extern int innetgr_p __P((const char *netgroup, + const char *host, + const char *user, + const char *domain, + struct net_data *net_data)); +extern int getnetgrent_p __P((const char **host, const char **user, + const char **domain, + struct net_data *net_data)); + +extern struct protoent *getprotoent_p __P((struct net_data *net_data)); +extern struct protoent *getprotobyname_p __P((const char *name, + struct net_data *net_data)); +extern struct protoent *getprotobynumber_p __P((int proto, + struct net_data *net_data)); +extern void setprotoent_p __P((int stayopen, + struct net_data *net_data)); +extern void endprotoent_p __P((struct net_data *net_data)); + + +extern struct passwd *getpwent_p __P((struct net_data *net_data)); +extern struct passwd *getpwnam_p __P((const char *name, + struct net_data *net_data)); +extern struct passwd *getpwuid_p __P((uid_t uid, + struct net_data *net_data)); +extern int setpassent_p __P((int stayopen, + struct net_data *net_data)); +extern void endpwent_p __P((struct net_data *net_data)); + +#ifdef SETPWENT_VOID +extern void setpwent_p __P((struct net_data *net_data)); +#else +extern int setpwent_p __P((struct net_data *net_data)); +#endif + +extern struct servent *getservent_p __P((struct net_data *net_data)); +extern struct servent *getservbyname_p __P((const char *name, + const char *proto, + struct net_data *net_data)); +extern struct servent *getservbyport_p __P((int port, const char *proto, + struct net_data *net_data)); +extern void setservent_p __P((int stayopen, + struct net_data *net_data)); +extern void endservent_p __P((struct net_data *net_data)); + +#endif /*_IRS_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2/include/isc/assertions.h b/usr/src/lib/libresolv2/include/isc/assertions.h new file mode 100644 index 0000000000..1f02d666ce --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/assertions.h @@ -0,0 +1,129 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1997-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * $Id: assertions.h,v 8.4 2001/05/29 05:47:07 marka Exp $ + */ + +#ifndef ASSERTIONS_H +#define ASSERTIONS_H 1 + +typedef enum { + assert_require, assert_ensure, assert_insist, assert_invariant +} assertion_type; + +typedef void (*assertion_failure_callback)(const char *, int, assertion_type, + const char *, int); + +extern assertion_failure_callback __assertion_failed; +void set_assertion_failure_callback(assertion_failure_callback f); +const char *assertion_type_to_text(assertion_type type); + +#ifdef CHECK_ALL +#define CHECK_REQUIRE 1 +#define CHECK_ENSURE 1 +#define CHECK_INSIST 1 +#define CHECK_INVARIANT 1 +#endif + +#ifdef CHECK_NONE +#define CHECK_REQUIRE 0 +#define CHECK_ENSURE 0 +#define CHECK_INSIST 0 +#define CHECK_INVARIANT 0 +#endif + +#ifndef CHECK_REQUIRE +#define CHECK_REQUIRE 1 +#endif + +#ifndef CHECK_ENSURE +#define CHECK_ENSURE 1 +#endif + +#ifndef CHECK_INSIST +#define CHECK_INSIST 1 +#endif + +#ifndef CHECK_INVARIANT +#define CHECK_INVARIANT 1 +#endif + +#if CHECK_REQUIRE != 0 +#define REQUIRE(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_require, \ + #cond, 0), 0))) +#define REQUIRE_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_require, \ + #cond, 1), 0))) +#else +#define REQUIRE(cond) ((void) (cond)) +#define REQUIRE_ERR(cond) ((void) (cond)) +#endif /* CHECK_REQUIRE */ + +#if CHECK_ENSURE != 0 +#define ENSURE(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_ensure, \ + #cond, 0), 0))) +#define ENSURE_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_ensure, \ + #cond, 1), 0))) +#else +#define ENSURE(cond) ((void) (cond)) +#define ENSURE_ERR(cond) ((void) (cond)) +#endif /* CHECK_ENSURE */ + +#if CHECK_INSIST != 0 +#define INSIST(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_insist, \ + #cond, 0), 0))) +#define INSIST_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_insist, \ + #cond, 1), 0))) +#else +#define INSIST(cond) ((void) (cond)) +#define INSIST_ERR(cond) ((void) (cond)) +#endif /* CHECK_INSIST */ + +#if CHECK_INVARIANT != 0 +#define INVARIANT(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_invariant, \ + #cond, 0), 0))) +#define INVARIANT_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_invariant, \ + #cond, 1), 0))) +#else +#define INVARIANT(cond) ((void) (cond)) +#define INVARIANT_ERR(cond) ((void) (cond)) +#endif /* CHECK_INVARIANT */ + +#endif /* ASSERTIONS_H */ diff --git a/usr/src/lib/libresolv2/include/isc/ctl.h b/usr/src/lib/libresolv2/include/isc/ctl.h new file mode 100644 index 0000000000..6b178c446a --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/ctl.h @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef ISC_CTL_H +#define ISC_CTL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Copyright (c) 1998,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: ctl.h,v 8.11 2001/08/10 02:40:49 marka Exp $ + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <isc/eventlib.h> + +/* Macros. */ + +#define CTL_MORE 0x0001 /* More will be / should be sent. */ +#define CTL_EXIT 0x0002 /* Close connection after this. */ +#define CTL_DATA 0x0004 /* Go into / this is DATA mode. */ + +/* Types. */ + +struct ctl_cctx; +struct ctl_sctx; +struct ctl_sess; +struct ctl_verb; + +enum ctl_severity { ctl_debug, ctl_warning, ctl_error }; + +typedef void (*ctl_logfunc)(enum ctl_severity, const char *fmt, ...); + +typedef void (*ctl_verbfunc)(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, const char *rest, + u_int respflags, const void *respctx, void *uctx); + +typedef void (*ctl_srvrdone)(struct ctl_sctx *, struct ctl_sess *, void *); + +typedef void (*ctl_clntdone)(struct ctl_cctx *, void *, const char *, u_int); + +struct ctl_verb { + const char * name; + ctl_verbfunc func; + const char * help; +}; + +/* General symbols. */ + +#define ctl_logger __ctl_logger + +#ifdef __GNUC__ +void ctl_logger(enum ctl_severity, const char *, ...) + __attribute__((__format__(__printf__, 2, 3))); +#else +void ctl_logger(enum ctl_severity, const char *, ...); +#endif + +/* Client symbols. */ + +#define ctl_client __ctl_client +#define ctl_endclient __ctl_endclient +#define ctl_command __ctl_command + +struct ctl_cctx * ctl_client(evContext, const struct sockaddr *, size_t, + const struct sockaddr *, size_t, + ctl_clntdone, void *, + u_int, ctl_logfunc); +void ctl_endclient(struct ctl_cctx *); +int ctl_command(struct ctl_cctx *, const char *, size_t, + ctl_clntdone, void *); + +/* Server symbols. */ + +#define ctl_server __ctl_server +#define ctl_endserver __ctl_endserver +#define ctl_response __ctl_response +#define ctl_sendhelp __ctl_sendhelp +#define ctl_getcsctx __ctl_getcsctx +#define ctl_setcsctx __ctl_setcsctx + +struct ctl_sctx * ctl_server(evContext, const struct sockaddr *, size_t, + const struct ctl_verb *, + u_int, u_int, + u_int, int, int, + ctl_logfunc, void *); +void ctl_endserver(struct ctl_sctx *); +void ctl_response(struct ctl_sess *, u_int, + const char *, u_int, const void *, + ctl_srvrdone, void *, + const char *, size_t); +void ctl_sendhelp(struct ctl_sess *, u_int); +void * ctl_getcsctx(struct ctl_sess *); +void * ctl_setcsctx(struct ctl_sess *, void *); + +#endif /*ISC_CTL_H*/ diff --git a/usr/src/lib/libresolv2/include/isc/dst.h b/usr/src/lib/libresolv2/include/isc/dst.h new file mode 100644 index 0000000000..4460cf63ae --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/dst.h @@ -0,0 +1,193 @@ +/* + * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef DST_H +#define DST_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef HAS_DST_KEY +typedef struct dst_key { + char *dk_key_name; /* name of the key */ + int dk_key_size; /* this is the size of the key in bits */ + int dk_proto; /* what protocols this key can be used for */ + int dk_alg; /* algorithm number from key record */ + u_int32_t dk_flags; /* and the flags of the public key */ + u_int16_t dk_id; /* identifier of the key */ +} DST_KEY; +#endif /* HAS_DST_KEY */ + +#ifdef ORIGINAL_ISC_CODE +/* + * do not taint namespace + */ +#define dst_bsafe_init __dst_bsafe_init +#define dst_buffer_to_key __dst_buffer_to_key +#define dst_check_algorithm __dst_check_algorithm +#define dst_compare_keys __dst_compare_keys +#define dst_cylink_init __dst_cylink_init +#define dst_dnskey_to_key __dst_dnskey_to_key +#define dst_eay_dss_init __dst_eay_dss_init +#define dst_free_key __dst_free_key +#define dst_generate_key __dst_generate_key +#define dst_hmac_md5_init __dst_hmac_md5_init +#define dst_init __dst_init +#define dst_key_to_buffer __dst_key_to_buffer +#define dst_key_to_dnskey __dst_key_to_dnskey +#define dst_random __dst_random +#define dst_read_key __dst_read_key +#define dst_rsaref_init __dst_rsaref_init +#define dst_s_build_filename __dst_s_build_filename +#define dst_s_calculate_bits __dst_s_calculate_bits +#define dst_s_conv_bignum_b64_to_u8 __dst_s_conv_bignum_b64_to_u8 +#define dst_s_conv_bignum_u8_to_b64 __dst_s_conv_bignum_u8_to_b64 +#define dst_s_dns_key_id __dst_s_dns_key_id +#define dst_s_dump __dst_s_dump +#define dst_s_filename_length __dst_s_filename_length +#define dst_s_fopen __dst_s_fopen +#define dst_s_get_int16 __dst_s_get_int16 +#define dst_s_get_int32 __dst_s_get_int32 +#define dst_s_id_calc __dst_s_id_calc +#define dst_s_put_int16 __dst_s_put_int16 +#define dst_s_put_int32 __dst_s_put_int32 +#define dst_s_quick_random __dst_s_quick_random +#define dst_s_quick_random_set __dst_s_quick_random_set +#define dst_s_random __dst_s_random +#define dst_s_semi_random __dst_s_semi_random +#define dst_s_verify_str __dst_s_verify_str +#define dst_sig_size __dst_sig_size +#define dst_sign_data __dst_sign_data +#define dst_verify_data __dst_verify_data +#define dst_write_key __dst_write_key +#else +#endif + +/* + * DST Crypto API defintions + */ +void dst_init(void); +int dst_check_algorithm(const int); + +int dst_sign_data(const int mode, /* specifies INIT/UPDATE/FINAL/ALL */ + DST_KEY *in_key, /* the key to use */ + void **context, /* pointer to state structure */ + const u_char *data, /* data to be signed */ + const int len, /* length of input data */ + u_char *signature, /* buffer to write signature to */ + const int sig_len); /* size of output buffer */ + +int dst_verify_data(const int mode, /* specifies INIT/UPDATE/FINAL/ALL */ + DST_KEY *in_key, /* the key to use */ + void **context, /* pointer to state structure */ + const u_char *data, /* data to be verified */ + const int len, /* length of input data */ + const u_char *signature,/* buffer containing signature */ + const int sig_len); /* length of signature */ + + +DST_KEY *dst_read_key(const char *in_name, /* name of key */ + const u_int16_t in_id, /* key tag identifier */ + const int in_alg, /* key algorithm */ + const int key_type); /* Private/PublicKey wanted*/ + +int dst_write_key(const DST_KEY *key, /* key to write out */ + const int key_type); /* Public/Private */ + +DST_KEY *dst_dnskey_to_key(const char *in_name, /* KEY record name */ + const u_char *key, /* KEY RDATA */ + const int len); /* size of input buffer*/ + + +int dst_key_to_dnskey(const DST_KEY *key, /* key to translate */ + u_char *out_storage, /* output buffer */ + const int out_len); /* size of out_storage*/ + + +DST_KEY *dst_buffer_to_key(const char *key_name, /* name of the key */ + const int alg, /* algorithm */ + const int flags, /* dns flags */ + const int protocol, /* dns protocol */ + const u_char *key_buf, /* key in dns wire fmt */ + const int key_len); /* size of key */ + + +int dst_key_to_buffer(DST_KEY *key, u_char *out_buff, int buf_len); + +DST_KEY *dst_generate_key(const char *name, /* name of new key */ + const int alg, /* key algorithm to generate */ + const int bits, /* size of new key */ + const int exp, /* alg dependent parameter*/ + const int flags, /* key DNS flags */ + const int protocol); /* key DNS protocol */ + +DST_KEY *dst_free_key(DST_KEY *f_key); +int dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2); + +int dst_sig_size(DST_KEY *key); + +int dst_random(const int mode, int wanted, u_char *outran); + + +/* support for dns key tags/ids */ +u_int16_t dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len); +u_int16_t dst_s_id_calc(const u_char *key_data, const int key_len); + +/* Used by callers as well as by the library. */ +#define RAW_KEY_SIZE 8192 /* large enough to store any key */ + +/* DST_API control flags */ +/* These are used used in functions dst_sign_data and dst_verify_data */ +#define SIG_MODE_INIT 1 /* initialize digest */ +#define SIG_MODE_UPDATE 2 /* add data to digest */ +#define SIG_MODE_FINAL 4 /* generate/verify signature */ +#define SIG_MODE_ALL (SIG_MODE_INIT|SIG_MODE_UPDATE|SIG_MODE_FINAL) + +/* Flags for dst_read_private_key() */ +#define DST_FORCE_READ 0x1000000 +#define DST_CAN_SIGN 0x010F +#define DST_NO_AUTHEN 0x8000 +#define DST_EXTEND_FLAG 0x1000 +#define DST_STANDARD 0 +#define DST_PRIVATE 0x2000000 +#define DST_PUBLIC 0x4000000 +#define DST_RAND_SEMI 1 +#define DST_RAND_STD 2 +#define DST_RAND_KEY 3 +#define DST_RAND_DSS 4 + + +/* DST algorithm codes */ +#define KEY_RSA 1 +#define KEY_DH 2 +#define KEY_DSA 3 +#define KEY_PRIVATE 254 +#define KEY_EXPAND 255 +#define KEY_HMAC_MD5 157 +#define KEY_HMAC_SHA1 158 +#define UNKNOWN_KEYALG 0 +#define DST_MAX_ALGS KEY_HMAC_SHA1 + +/* DST constants to locations in KEY record changes in new KEY record */ +#define DST_FLAGS_SIZE 2 +#define DST_KEY_PROT 2 +#define DST_KEY_ALG 3 +#define DST_EXT_FLAG 4 +#define DST_KEY_START 4 + +#ifndef SIGN_F_NOKEY +#define SIGN_F_NOKEY 0xC000 +#endif + +/* error codes from dst routines */ +#define SIGN_INIT_FAILURE (-23) +#define SIGN_UPDATE_FAILURE (-24) +#define SIGN_FINAL_FAILURE (-25) +#define VERIFY_INIT_FAILURE (-26) +#define VERIFY_UPDATE_FAILURE (-27) +#define VERIFY_FINAL_FAILURE (-28) +#define MISSING_KEY_OR_SIGNATURE (-30) +#define UNSUPPORTED_KEYALG (-31) + +#endif /* DST_H */ diff --git a/usr/src/lib/libresolv2/include/isc/eventlib.h b/usr/src/lib/libresolv2/include/isc/eventlib.h new file mode 100644 index 0000000000..92988f63ca --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/eventlib.h @@ -0,0 +1,209 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* eventlib.h - exported interfaces for eventlib + * vix 09sep95 [initial] + * + * $Id: eventlib.h,v 1.23 2001/05/29 05:47:09 marka Exp $ + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _EVENTLIB_H +#define _EVENTLIB_H + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <stdio.h> + +#ifndef __P +# define __EVENTLIB_P_DEFINED +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +/* In the absence of branded types... */ +typedef struct { void *opaque; } evConnID; +typedef struct { void *opaque; } evFileID; +typedef struct { void *opaque; } evStreamID; +typedef struct { void *opaque; } evTimerID; +typedef struct { void *opaque; } evWaitID; +typedef struct { void *opaque; } evContext; +typedef struct { void *opaque; } evEvent; + +#define evInitID(id) ((id)->opaque = NULL) +#define evTestID(id) ((id).opaque != NULL) + +typedef void (*evConnFunc)__P((evContext ctx, void *uap, int fd, + const void *la, int lalen, + const void *ra, int ralen)); +typedef void (*evFileFunc)__P((evContext ctx, void *uap, int fd, int evmask)); +typedef void (*evStreamFunc)__P((evContext ctx, void *uap, int fd, int bytes)); +typedef void (*evTimerFunc)__P((evContext ctx, void *uap, + struct timespec due, struct timespec inter)); +typedef void (*evWaitFunc)__P((evContext ctx, void *uap, const void *tag)); + +typedef struct { unsigned char mask[256/8]; } evByteMask; +#define EV_BYTEMASK_BYTE(b) ((b) / 8) +#define EV_BYTEMASK_MASK(b) (1 << ((b) % 8)) +#define EV_BYTEMASK_SET(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] |= EV_BYTEMASK_MASK(b)) +#define EV_BYTEMASK_CLR(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] &= ~EV_BYTEMASK_MASK(b)) +#define EV_BYTEMASK_TST(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] & EV_BYTEMASK_MASK(b)) + +#define EV_POLL 1 +#define EV_WAIT 2 +#define EV_NULL 4 + +#define EV_READ 1 +#define EV_WRITE 2 +#define EV_EXCEPT 4 + +/* eventlib.c */ +#define evCreate __evCreate +#define evSetDebug __evSetDebug +#define evDestroy __evDestroy +#define evGetNext __evGetNext +#define evDispatch __evDispatch +#define evDrop __evDrop +#define evMainLoop __evMainLoop +#define evHighestFD __evHighestFD + +int evCreate __P((evContext *ctx)); +void evSetDebug __P((evContext ctx, int lev, FILE *out)); +int evDestroy __P((evContext ctx)); +int evGetNext __P((evContext ctx, evEvent *ev, int options)); +int evDispatch __P((evContext ctx, evEvent ev)); +void evDrop __P((evContext ctx, evEvent ev)); +int evMainLoop __P((evContext ctx)); +int evHighestFD __P((evContext ctx)); + +#ifdef SUNW_POLL +extern void evPollfdAdd(evContext ctx, int pollfd_chunk_size, int fd, + short events); +extern void evPollfdDel(evContext ctx, int fd); +#endif /* SUNW_POLL */ + +/* ev_connects.c */ +#define evListen __evListen +#define evConnect __evConnect +#define evCancelConn __evCancelConn +#define evHold __evHold +#define evUnhold __evUnhold +#define evTryAccept __evTryAccept + +int evListen __P((evContext ctx, int fd, int maxconn, + evConnFunc func, void *uap, evConnID *id)); +int evConnect __P((evContext ctx, int fd, const void *ra, int ralen, + evConnFunc func, void *uap, evConnID *id)); +int evCancelConn __P((evContext ctx, evConnID id)); +int evHold __P((evContext, evConnID)); +int evUnhold __P((evContext, evConnID)); +int evTryAccept __P((evContext, evConnID, int *)); + +/* ev_files.c */ +#define evSelectFD __evSelectFD +#define evDeselectFD __evDeselectFD + +int evSelectFD __P((evContext ctx, int fd, int eventmask, + evFileFunc func, void *uap, evFileID *id)); +int evDeselectFD __P((evContext ctx, evFileID id)); + +/* ev_streams.c */ +#define evConsIovec __evConsIovec +#define evWrite __evWrite +#define evRead __evRead +#define evTimeRW __evTimeRW +#define evUntimeRW __evUntimeRW +#define evCancelRW __evCancelRW + +struct iovec evConsIovec __P((void *buf, size_t cnt)); +int evWrite __P((evContext ctx, int fd, const struct iovec *iov, int cnt, + evStreamFunc func, void *uap, evStreamID *id)); +int evRead __P((evContext ctx, int fd, const struct iovec *iov, int cnt, + evStreamFunc func, void *uap, evStreamID *id)); +int evTimeRW __P((evContext ctx, evStreamID id, evTimerID timer)); +int evUntimeRW __P((evContext ctx, evStreamID id)); +int evCancelRW __P((evContext ctx, evStreamID id)); + +/* ev_timers.c */ +#define evConsTime __evConsTime +#define evAddTime __evAddTime +#define evSubTime __evSubTime +#define evCmpTime __evCmpTime +#define evTimeSpec __evTimeSpec +#define evTimeVal __evTimeVal + +#define evNowTime __evNowTime +#define evLastEventTime __evLastEventTime +#define evSetTimer __evSetTimer +#define evClearTimer __evClearTimer +#define evResetTimer __evResetTimer +#define evSetIdleTimer __evSetIdleTimer +#define evClearIdleTimer __evClearIdleTimer +#define evResetIdleTimer __evResetIdleTimer +#define evTouchIdleTimer __evTouchIdleTimer + +struct timespec evConsTime __P((time_t sec, long nsec)); +struct timespec evAddTime __P((struct timespec add1, struct timespec add2)); +struct timespec evSubTime __P((struct timespec minu, struct timespec subtra)); +struct timespec evNowTime __P((void)); +struct timespec evLastEventTime __P((evContext)); +struct timespec evTimeSpec __P((struct timeval)); +struct timeval evTimeVal __P((struct timespec)); +int evCmpTime __P((struct timespec a, struct timespec b)); +int evSetTimer __P((evContext ctx, evTimerFunc func, void *uap, + struct timespec due, struct timespec inter, + evTimerID *id)); +int evClearTimer __P((evContext ctx, evTimerID id)); +int evResetTimer __P((evContext, evTimerID, evTimerFunc, void *, + struct timespec, struct timespec)); +int evSetIdleTimer __P((evContext, evTimerFunc, void *, struct timespec, + evTimerID *)); +int evClearIdleTimer __P((evContext, evTimerID)); +int evResetIdleTimer __P((evContext, evTimerID, evTimerFunc, void *, + struct timespec)); +int evTouchIdleTimer __P((evContext, evTimerID)); + +/* ev_waits.c */ +#define evWaitFor __evWaitFor +#define evDo __evDo +#define evUnwait __evUnwait +#define evDefer __evDefer + +int evWaitFor __P((evContext ctx, const void *tag, evWaitFunc func, void *uap, + evWaitID *id)); +int evDo __P((evContext ctx, const void *tag)); +int evUnwait __P((evContext ctx, evWaitID id)); +int evDefer __P((evContext, evWaitFunc, void *)); + +#ifdef __EVENTLIB_P_DEFINED +# undef __P +#endif + +#endif /*_EVENTLIB_H*/ diff --git a/usr/src/lib/libresolv2/include/isc/heap.h b/usr/src/lib/libresolv2/include/isc/heap.h new file mode 100644 index 0000000000..46093f506d --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/heap.h @@ -0,0 +1,54 @@ + +/* + * Copyright (c) 1997, by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1997 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ +#pragma ident "%Z%%M% %I% %E% SMI" + +typedef int (*heap_higher_priority_func)(void *, void *); +typedef void (*heap_index_func)(void *, int); +typedef void (*heap_for_each_func)(void *, void *); + +typedef struct heap_context { + int array_size; + int array_size_increment; + int heap_size; + void **heap; + heap_higher_priority_func higher_priority; + heap_index_func index; +} *heap_context; + +#define heap_new __heap_new +#define heap_free __heap_free +#define heap_insert __heap_insert +#define heap_delete __heap_delete +#define heap_increased __heap_increased +#define heap_decreased __heap_decreased +#define heap_element __heap_element +#define heap_for_each __heap_for_each + +heap_context heap_new(heap_higher_priority_func, heap_index_func, int); +int heap_free(heap_context); +int heap_insert(heap_context, void *); +int heap_delete(heap_context, int); +int heap_increased(heap_context, int); +int heap_decreased(heap_context, int); +void * heap_element(heap_context, int); +int heap_for_each(heap_context, heap_for_each_func, void *); diff --git a/usr/src/lib/libresolv2/include/isc/irpmarshall.h b/usr/src/lib/libresolv2/include/isc/irpmarshall.h new file mode 100644 index 0000000000..9ef0f2e4e4 --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/irpmarshall.h @@ -0,0 +1,123 @@ +/* + * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: irpmarshall.h,v 8.2 2001/05/29 05:47:10 marka Exp $ + */ + +#ifndef _IRPMARSHALL_H_INCLUDED +#define _IRPMARSHALL_H_INCLUDED + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* Hide function names */ +#define irp_marshall_gr __irp_marshall_gr +#define irp_marshall_ho __irp_marshall_ho +#define irp_marshall_ne __irp_marshall_ne +#define irp_marshall_ng __irp_marshall_ng +#define irp_marshall_nw __irp_marshall_nw +#define irp_marshall_pr __irp_marshall_pr +#define irp_marshall_pw __irp_marshall_pw +#define irp_marshall_sv __irp_marshall_sv +#define irp_unmarshall_gr __irp_unmarshall_gr +#define irp_unmarshall_ho __irp_unmarshall_ho +#define irp_unmarshall_ne __irp_unmarshall_ne +#define irp_unmarshall_ng __irp_unmarshall_ng +#define irp_unmarshall_nw __irp_unmarshall_nw +#define irp_unmarshall_pr __irp_unmarshall_pr +#define irp_unmarshall_pw __irp_unmarshall_pw +#define irp_unmarshall_sv __irp_unmarshall_sv + +#define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) +#define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ + (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) + +/* See comment below on usage */ +int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len); +int irp_unmarshall_pw(struct passwd *pw, char *buffer); +int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len); +int irp_unmarshall_gr(struct group *gr, char *buffer); +int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len); +int irp_unmarshall_sv(struct servent *sv, char *buffer); +int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len); +int irp_unmarshall_pr(struct protoent *pr, char *buffer); +int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len); +int irp_unmarshall_ho(struct hostent *ho, char *buffer); +int irp_marshall_ng(const char *host, const char *user, const char *domain, + char **buffer, size_t *len); +int irp_unmarshall_ng(const char **host, const char **user, + const char **domain, char *buffer); +int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len); +int irp_unmarshall_nw(struct nwent *ne, char *buffer); +int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len); +int irp_unmarshall_ne(struct netent *ne, char *buffer); + +/* + * Functions to marshall and unmarshall various system data structures. We + * use a printable ascii format that is as close to various system config + * files as reasonable (e.g. /etc/passwd format). + * + * We are not forgiving with unmarhsalling misformatted buffers. In + * particular whitespace in fields is not ignored. So a formatted password + * entry "brister :1364:100:...." will yield a username of "brister " + * + * We potentially do a lot of mallocs to fill fields that are of type + * (char **) like a hostent h_addr field. Building (for example) the + * h_addr field and its associated addresses all in one buffer is + * certainly possible, but not done here. + * + * The following description is true for all the marshalling functions: + * + */ + +/* int irp_marshall_XX(struct yyyy *XX, char **buffer, size_t *len); + * + * The argument XX (of type struct passwd for example) is marshalled in the + * buffer pointed at by *BUFFER, which is of length *LEN. Returns 0 + * on success and -1 on failure. Failure will occur if *LEN is + * smaller than needed. + * + * If BUFFER is NULL, then *LEN is set to the size of the buffer + * needed to marshall the data and no marshalling is actually done. + * + * If *BUFFER is NULL, then a buffer large enough will be allocated + * with memget() and the size allocated will be stored in *LEN. An extra 2 + * bytes will be allocated for the client to append CRLF if wanted. The + * value of *LEN will include these two bytes. + * + * All the marshalling functions produce a buffer with the fields + * separated by colons (except for the hostent marshalling, which uses '@' + * to separate fields). Fields that have multiple subfields (like the + * gr_mem field in struct group) have their subparts separated by + * commas. + */ + +/* + * int irp_unmarshall_XX(struct YYYYY *XX, char *buffer); + * + * The unmashalling functions break apart the buffer and store the + * values in the struct pointed to by XX. All pointer values inside + * XX are allocated with malloc. All arrays of pointers have a NULL + * as the last element. + */ + +#endif diff --git a/usr/src/lib/libresolv2/include/isc/list.h b/usr/src/lib/libresolv2/include/isc/list.h new file mode 100644 index 0000000000..dba0aad62d --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/list.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1998-2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef LIST_H +#define LIST_H 1 +#include <isc/assertions.h> + +#define LIST(type) struct { type *head, *tail; } +#define INIT_LIST(list) \ + do { (list).head = NULL; (list).tail = NULL; } while (0) + +#define LINK(type) struct { type *prev, *next; } +#define INIT_LINK_TYPE(elt, link, type) \ + do { \ + (elt)->link.prev = (type *)(-1); \ + (elt)->link.next = (type *)(-1); \ + } while (0) +#define INIT_LINK(elt, link) \ + INIT_LINK_TYPE(elt, link, void) +#define LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1)) + +#define HEAD(list) ((list).head) +#define TAIL(list) ((list).tail) +#define EMPTY(list) ((list).head == NULL) + +#define PREPEND(list, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((list).head != NULL) \ + (list).head->link.prev = (elt); \ + else \ + (list).tail = (elt); \ + (elt)->link.prev = NULL; \ + (elt)->link.next = (list).head; \ + (list).head = (elt); \ + } while (0) + +#define APPEND(list, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((list).tail != NULL) \ + (list).tail->link.next = (elt); \ + else \ + (list).head = (elt); \ + (elt)->link.prev = (list).tail; \ + (elt)->link.next = NULL; \ + (list).tail = (elt); \ + } while (0) + +#define UNLINK_TYPE(list, elt, link, type) \ + do { \ + INSIST(LINKED(elt, link));\ + if ((elt)->link.next != NULL) \ + (elt)->link.next->link.prev = (elt)->link.prev; \ + else \ + (list).tail = (elt)->link.prev; \ + if ((elt)->link.prev != NULL) \ + (elt)->link.prev->link.next = (elt)->link.next; \ + else \ + (list).head = (elt)->link.next; \ + INIT_LINK_TYPE(elt, link, type); \ + } while (0) +#define UNLINK(list, elt, link) \ + UNLINK_TYPE(list, elt, link, void) + +#define PREV(elt, link) ((elt)->link.prev) +#define NEXT(elt, link) ((elt)->link.next) + +#define INSERT_BEFORE(list, before, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((before)->link.prev == NULL) \ + PREPEND(list, elt, link); \ + else { \ + (elt)->link.prev = (before)->link.prev; \ + (before)->link.prev = (elt); \ + (elt)->link.prev->link.next = (elt); \ + (elt)->link.next = (before); \ + } \ + } while (0) + +#define INSERT_AFTER(list, after, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((after)->link.next == NULL) \ + APPEND(list, elt, link); \ + else { \ + (elt)->link.next = (after)->link.next; \ + (after)->link.next = (elt); \ + (elt)->link.next->link.prev = (elt); \ + (elt)->link.prev = (after); \ + } \ + } while (0) + +#define ENQUEUE(list, elt, link) APPEND(list, elt, link) +#define DEQUEUE(list, elt, link) UNLINK(list, elt, link) + +#endif /* LIST_H */ diff --git a/usr/src/lib/libresolv2/include/isc/logging.h b/usr/src/lib/libresolv2/include/isc/logging.h new file mode 100644 index 0000000000..99f0e40fea --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/logging.h @@ -0,0 +1,118 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef LOGGING_H +#define LOGGING_H + +#include <sys/types.h> +#include <stdio.h> +#include <stdarg.h> +#include <unistd.h> + +#define log_critical (-5) +#define log_error (-4) +#define log_warning (-3) +#define log_notice (-2) +#define log_info (-1) +#define log_debug(level) (level) + +typedef enum { log_syslog, log_file, log_null } log_channel_type; + +#define LOG_MAX_VERSIONS 99 + +#define LOG_CLOSE_STREAM 0x0001 +#define LOG_TIMESTAMP 0x0002 +#define LOG_TRUNCATE 0x0004 +#define LOG_USE_CONTEXT_LEVEL 0x0008 +#define LOG_PRINT_LEVEL 0x0010 +#define LOG_REQUIRE_DEBUG 0x0020 +#define LOG_CHANNEL_BROKEN 0x0040 +#define LOG_PRINT_CATEGORY 0x0080 +#define LOG_CHANNEL_OFF 0x0100 + +typedef struct log_context *log_context; +typedef struct log_channel *log_channel; + +#define LOG_OPTION_DEBUG 0x01 +#define LOG_OPTION_LEVEL 0x02 + +#define log_open_stream __log_open_stream +#define log_close_stream __log_close_stream +#define log_get_stream __log_get_stream +#define log_get_filename __log_get_filename +#define log_check_channel __log_check_channel +#define log_check __log_check +#define log_vwrite __log_vwrite +#define log_write __log_write +#define log_new_context __log_new_context +#define log_free_context __log_free_context +#define log_add_channel __log_add_channel +#define log_remove_channel __log_remove_channel +#define log_option __log_option +#define log_category_is_active __log_category_is_active +#define log_new_syslog_channel __log_new_syslog_channel +#define log_new_file_channel __log_new_file_channel +#define log_set_file_owner __log_set_file_owner +#define log_new_null_channel __log_new_null_channel +#define log_inc_references __log_inc_references +#define log_dec_references __log_dec_references +#define log_get_channel_type __log_get_channel_type +#define log_free_channel __log_free_channel +#define log_close_debug_channels __log_close_debug_channels + +FILE * log_open_stream(log_channel); +int log_close_stream(log_channel); +FILE * log_get_stream(log_channel); +char * log_get_filename(log_channel); +int log_check_channel(log_context, int, log_channel); +int log_check(log_context, int, int); +#ifdef __GNUC__ +void log_vwrite(log_context, int, int, const char *, + va_list args) + __attribute__((__format__(__printf__, 4, 0))); +void log_write(log_context, int, int, const char *, ...) + __attribute__((__format__(__printf__, 4, 5))); +#else +void log_vwrite(log_context, int, int, const char *, + va_list args); +void log_write(log_context, int, int, const char *, ...); +#endif +int log_new_context(int, char **, log_context *); +void log_free_context(log_context); +int log_add_channel(log_context, int, log_channel); +int log_remove_channel(log_context, int, log_channel); +int log_option(log_context, int, int); +int log_category_is_active(log_context, int); +log_channel log_new_syslog_channel(unsigned int, int, int); +log_channel log_new_file_channel(unsigned int, int, const char *, + FILE *, unsigned int, + unsigned long); +int log_set_file_owner(log_channel, uid_t, gid_t); +log_channel log_new_null_channel(void); +int log_inc_references(log_channel); +int log_dec_references(log_channel); +log_channel_type log_get_channel_type(log_channel); +int log_free_channel(log_channel); +void log_close_debug_channels(log_context); + +#endif /* !LOGGING_H */ diff --git a/usr/src/lib/libresolv2/include/isc/memcluster.h b/usr/src/lib/libresolv2/include/isc/memcluster.h new file mode 100644 index 0000000000..28e7c444a8 --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/memcluster.h @@ -0,0 +1,56 @@ +/* + * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1997,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef MEMCLUSTER_H +#define MEMCLUSTER_H + +#include <stdio.h> + +#define meminit __meminit +#ifdef MEMCLUSTER_DEBUG +#define memget(s) __memget_debug(s, __FILE__, __LINE__) +#define memput(p, s) __memput_debug(p, s, __FILE__, __LINE__) +#else /*MEMCLUSTER_DEBUG*/ +#ifdef MEMCLUSTER_RECORD +#define memget(s) __memget_record(s, __FILE__, __LINE__) +#define memput(p, s) __memput_record(p, s, __FILE__, __LINE__) +#else /*MEMCLUSTER_RECORD*/ +#define memget __memget +#define memput __memput +#endif /*MEMCLUSTER_RECORD*/ +#endif /*MEMCLUSTER_DEBUG*/ +#define memstats __memstats +#define memactive __memactive + +int meminit(size_t, size_t); +void * __memget(size_t); +void __memput(void *, size_t); +void * __memget_debug(size_t, const char *, int); +void __memput_debug(void *, size_t, const char *, int); +void * __memget_record(size_t, const char *, int); +void __memput_record(void *, size_t, const char *, int); +void memstats(FILE *); +int memactive(void); + +#endif /* MEMCLUSTER_H */ diff --git a/usr/src/lib/libresolv2/include/isc/misc.h b/usr/src/lib/libresolv2/include/isc/misc.h new file mode 100644 index 0000000000..89afbc6c51 --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/misc.h @@ -0,0 +1,44 @@ +/* + * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: misc.h,v 8.5 2001/06/18 06:40:43 marka Exp $ + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _ISC_MISC_H +#define _ISC_MISC_H + +#include <stdio.h> + +#define bitncmp __bitncmp + +extern int bitncmp(const void *l, const void *r, int n); + +extern int isc_gethexstring(unsigned char *, size_t, int, FILE *, + int *); +extern void isc_puthexstring(FILE *, const unsigned char *, size_t, + size_t, size_t, const char *); +extern void isc_tohex(const unsigned char *, size_t, char *); + +#endif /*_ISC_MISC_H*/ diff --git a/usr/src/lib/libresolv2/include/isc/tree.h b/usr/src/lib/libresolv2/include/isc/tree.h new file mode 100644 index 0000000000..384832830c --- /dev/null +++ b/usr/src/lib/libresolv2/include/isc/tree.h @@ -0,0 +1,66 @@ +/* + * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* tree.h - declare structures used by tree library + * + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 27jun86 [broken out of tree.c] + * + * $Id: tree.h,v 8.3 2002/12/03 05:26:48 marka Exp $ + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _TREE_H_INCLUDED +#define _TREE_H_INCLUDED + + +#ifndef __P +# if defined(__STDC__) || defined(__GNUC__) +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +/* + * tree_t is our package-specific anonymous pointer. + */ +#if defined(__STDC__) || defined(__GNUC__) +typedef void *tree_t; +#else +typedef char *tree_t; +#endif + +#ifdef ORIGINAL_ISC_CODE +/* + * Do not taint namespace + */ +#define tree_add __tree_add +#define tree_delete __tree_delete +#define tree_init __tree_init +#define tree_mung __tree_mung +#define tree_srch __tree_srch +#define tree_trav __tree_trav +#else +#endif + +typedef struct tree_s { + tree_t data; + struct tree_s *left, *right; + short bal; + } + tree; + + +void tree_init __P((tree **)); +tree_t tree_srch __P((tree **, int (*)(), tree_t)); +tree_t tree_add __P((tree **, int (*)(), tree_t, void (*)())); +int tree_delete __P((tree **, int (*)(), tree_t, void (*)())); +int tree_trav __P((tree **, int (*)())); +void tree_mung __P((tree **, void (*)())); + + +#endif /* _TREE_H_INCLUDED */ diff --git a/usr/src/lib/libresolv2/include/make_os_version b/usr/src/lib/libresolv2/include/make_os_version new file mode 100644 index 0000000000..3654490fee --- /dev/null +++ b/usr/src/lib/libresolv2/include/make_os_version @@ -0,0 +1,34 @@ +#!/bin/sh + +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" + +UNAME_R=`/usr/bin/uname -r` + +OS_MAJOR=`echo $UNAME_R | /usr/bin/sed -e 's/^\([^.]*\).*/\1/'` +OS_MINOR=`echo $UNAME_R | /usr/bin/sed -e 's/^[^.]*\.\([^.]*\).*/\1/'` +OS_VERSION=`echo $UNAME_R | tr '.' '_'` + +cat <<EOF > new_os_version.h +#ifndef OS_VERSION_H +#define OS_VERSION_H + +#define SUNOS_$OS_VERSION +#define OS_MAJOR $OS_MAJOR +#define OS_MINOR $OS_MINOR + +#endif +EOF + +if [ -f os_version.h ]; then + if /usr/bin/cmp -s new_os_version.h os_version.h; then + /usr/bin/rm -f new_os_version.h + else + /usr/bin/rm -f os_version.h + /usr/bin/mv new_os_version.h os_version.h + fi +else + /usr/bin/mv new_os_version.h os_version.h +fi diff --git a/usr/src/lib/libresolv2/include/netdb_private.h b/usr/src/lib/libresolv2/include/netdb_private.h new file mode 100644 index 0000000000..58a6c5905f --- /dev/null +++ b/usr/src/lib/libresolv2/include/netdb_private.h @@ -0,0 +1,41 @@ +/* + * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _NETDB_PRIVATE_H +#define _NETDB_PRIVATE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Constants defined by the ISC for BIND 8.2, but which do not appear + * in RFC 2553 (hence, aren't suitable for inclusion in <netdb.h>). + */ + +/* + * Error return codes from getaddrinfo() + */ + +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_MAX 14 + +/* + * Flag values for getaddrinfo() + */ + +#define AI_MASK 0x00000007 + +/* + * Scope delimit character + */ +#define SCOPE_DELIMITER '%' + +/* + * XXX + * Various data types (hostent_data, netent_data, protoent_data, servent_data) + * only defined for __osf__ or __hpux => we don't need them ?? + */ + +#endif /* _NETDB_PRIVATE_H */ diff --git a/usr/src/lib/libresolv2/include/netgroup.h b/usr/src/lib/libresolv2/include/netgroup.h new file mode 100644 index 0000000000..36cc9a742f --- /dev/null +++ b/usr/src/lib/libresolv2/include/netgroup.h @@ -0,0 +1,26 @@ +/* + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef ORIGINAL_ISC_CODE +#ifndef netgroup_h +#define netgroup_h + +int getnetgrent(const char **machinep, const char **userp, + const char **domainp); + +int getnetgrent_r(char **machinep, char **userp, char **domainp, + char *buffer, int buflen); + +void setnetgrent(const char *netgroup); + +void endnetgrent(void); + +int innetgr(const char *netgroup, const char *machine, + const char *user, const char *domain); + +#endif +#endif /* ORIGINAL_ISC_CODE */ diff --git a/usr/src/lib/libresolv2/include/paths.h b/usr/src/lib/libresolv2/include/paths.h new file mode 100644 index 0000000000..648c624e02 --- /dev/null +++ b/usr/src/lib/libresolv2/include/paths.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 1997, by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define _PATH_DEVNULL "/dev/null" + diff --git a/usr/src/lib/libresolv2/include/port_after.h b/usr/src/lib/libresolv2/include/port_after.h new file mode 100644 index 0000000000..2f449c0a7a --- /dev/null +++ b/usr/src/lib/libresolv2/include/port_after.h @@ -0,0 +1,294 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef PORT_AFTER_H +#define PORT_AFTER_H +#include "os_version.h" + +#undef HAVE_SA_LEN +#define USE_POSIX +#define POSIX_SIGNALS +#define NETREAD_BROKEN +#define USE_WAITPID +#define HAVE_FCHMOD +#define NEED_PSELECT +#define SETGRENT_VOID +#define SETPWENT_VOID +#define SIOCGIFCONF_ADDR +#define IP_OPT_BUF_SIZE 40 +#define HAVE_CHROOT +#define CAN_CHANGE_ID +#define POSIX_GETPWNAM_R +#define POSIX_GETPWUID_R +#define POSIX_GETGRGID_R +#define POSIX_GETGRNAM_R +#define NEED_SECURE_DIRECTORY +#define HAVE_DEV_RANDOM +#define NO_MSG_CONTROL + +#define PORT_NONBLOCK O_NONBLOCK +#define PORT_WOULDBLK EWOULDBLOCK +#define WAIT_T int +#ifndef SUNW_LIBNSL +#define INADDR_NONE 0xffffffff +#endif + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +#include <sys/bitypes.h> +#endif +#include <sys/time.h> + +#ifndef MIN +#define MIN(x, y) ((x > y) ?y :x) +#endif +#ifndef MAX +#define MAX(x, y) ((x > y) ?x :y) +#endif + +/* + * We need to know the IPv6 address family number even on IPv4-only systems. + * Note that this is NOT a protocol constant, and that if the system has its + * own AF_INET6, different from ours below, all of BIND's libraries and + * executables will need to be recompiled after the system <sys/socket.h> + * has had this type added. The type number below is correct on most BSD- + * derived systems for which AF_INET6 is defined. + */ +#ifndef AF_INET6 +#define AF_INET6 24 +#endif + +#ifndef PF_INET6 +#define PF_INET6 AF_INET6 +#endif +#include <port_ipv6.h> + +#ifndef HAS_INET6_STRUCTS +/* Replace with structure from later rev of O/S if known. */ +struct in6_addr { + u_int8_t s6_addr[16]; +}; + +/* Replace with structure from later rev of O/S if known. */ +struct sockaddr_in6 { +#ifdef HAVE_SA_LEN + u_int8_t sin6_len; /* length of this struct */ + u_int8_t sin6_family; /* AF_INET6 */ +#else + u_int16_t sin6_family; /* AF_INET6 */ +#endif + u_int16_t sin6_port; /* transport layer port # */ + u_int32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + u_int32_t sin6_scope_id; /* set of interfaces for a scope */ +}; + +#ifndef IN6ADDR_ANY_INIT +#define IN6ADDR_ANY_INIT {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} +#endif +#ifndef IN6ADDR_LOOPBACK_INIT +#define IN6ADDR_LOOPBACK_INIT {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}} +#endif +#endif /* HAS_INET6_STRUCTS */ + +#if defined(NEED_SOCKADDR_STORAGE) || !defined(HAS_INET6_STRUCTS) +#define __SS_MAXSIZE 128 +#define __SS_ALLIGSIZE (sizeof (long)) + +struct sockaddr_storage { +#ifdef HAVE_SA_LEN + u_int8_t ss_len; /* address length */ + u_int8_t ss_family; /* address family */ + char __ss_pad1[__SS_ALLIGSIZE - 2 * sizeof (u_int8_t)]; + long __ss_align; + char __ss_pad2[__SS_MAXSIZE - 2 * __SS_ALLIGSIZE]; +#else + u_int16_t ss_family; /* address family */ + char __ss_pad1[__SS_ALLIGSIZE - sizeof (u_int16_t)]; + long __ss_align; + char __ss_pad2[__SS_MAXSIZE - 2 * __SS_ALLIGSIZE]; +#endif +}; +#endif + + +#if !defined(HAS_INET6_STRUCTS) || defined(NEED_IN6ADDR_ANY) +#define in6addr_any isc_in6addr_any +extern const struct in6_addr in6addr_any; +#endif + +#ifndef IN6_ARE_ADDR_EQUAL +#define IN6_ARE_ADDR_EQUAL(a, b) \ + (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof (struct in6_addr)) == 0) +#endif + +#ifndef IN6_IS_ADDR_UNSPECIFIED +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + IN6_ARE_ADDR_EQUAL(a, &in6addr_any) +#endif + +#ifndef IN6_IS_ADDR_LOOPBACK +extern const struct in6_addr isc_in6addr_loopback; +#define IN6_IS_ADDR_LOOPBACK(a) \ + IN6_ARE_ADDR_EQUAL(a, &isc_in6addr_loopback) +#endif + +#ifndef IN6_IS_ADDR_V4COMPAT +#define IN6_IS_ADDR_V4COMPAT(a) \ + ((a)->s6_addr[0] == 0x00 && (a)->s6_addr[1] == 0x00 && \ + (a)->s6_addr[2] == 0x00 && (a)->s6_addr[3] == 0x00 && \ + (a)->s6_addr[4] == 0x00 && (a)->s6_addr[5] == 0x00 && \ + (a)->s6_addr[6] == 0x00 && (a)->s6_addr[7] == 0x00 && \ + (a)->s6_addr[8] == 0x00 && (a)->s6_addr[9] == 0x00 && \ + (a)->s6_addr[10] == 0x00 && (a)->s6_addr[11] == 0x00 && \ + ((a)->s6_addr[12] != 0x00 || (a)->s6_addr[13] != 0x00 || \ + (a)->s6_addr[14] != 0x00 || \ + ((a)->s6_addr[15] != 0x00 && (a)->s6_addr[15] != 1))) +#endif + +#ifndef IN6_IS_ADDR_V4MAPPED +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((a)->s6_addr[0] == 0x00 && (a)->s6_addr[1] == 0x00 && \ + (a)->s6_addr[2] == 0x00 && (a)->s6_addr[3] == 0x00 && \ + (a)->s6_addr[4] == 0x00 && (a)->s6_addr[5] == 0x00 && \ + (a)->s6_addr[6] == 0x00 && (a)->s6_addr[7] == 0x00 && \ + (a)->s6_addr[8] == 0x00 && (a)->s6_addr[9] == 0x00 && \ + (a)->s6_addr[10] == 0xff && (a)->s6_addr[11] == 0xff) +#endif + +#ifndef IN6_IS_ADDR_SITELOCAL +#define IN6_IS_ADDR_SITELOCAL(a) \ + (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0)) +#endif + +#ifndef IN6_IS_ADDR_LINKLOCAL +#define IN6_IS_ADDR_LINKLOCAL(a) \ + (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80)) +#endif + +#ifndef IN6_IS_ADDR_MULTICAST +#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff) +#endif + +#ifndef __IPV6_ADDR_MC_SCOPE +#define __IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f) +#endif + +#ifndef __IPV6_ADDR_SCOPE_SITELOCAL +#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05 +#endif + +#ifndef __IPV6_ADDR_SCOPE_ORGLOCAL +#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08 +#endif + +#ifndef IN6_IS_ADDR_MC_SITELOCAL +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL)) +#endif + +#ifndef IN6_IS_ADDR_MC_ORGLOCAL +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL)) +#endif + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + +/* + * Prior to 2.6, Solaris needs a prototype for gethostname(). + */ +#if (OS_MAJOR == 5 && OS_MINOR < 6) +extern int gethostname(char *, size_t); +#endif +/* + * gethostid() was not available until 2.5 + * setsockopt(SO_REUSEADDR) fails on unix domain sockets before 2.5 + * use ioctl(FIONBIO) rather than fcntl() calls to set/clear non-blocking i/o. + */ +#if (OS_MAJOR == 5 && OS_MINOR < 5) +#define GET_HOST_ID_MISSING +#define NO_UNIX_REUSEADDR +#define USE_FIONBIO_IOCTL +#endif + +#define NEED_STRSEP +extern char *strsep(char **, const char *); + +#define NEED_DAEMON +int daemon(int nochdir, int noclose); + +/* + * Solaris defines this in <netdb.h> instead of in <sys/param.h>. We don't + * define it in our <netdb.h>, so we define it here. + */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +/* + * Solaris 2.5 and later have getrlimit(), setrlimit() and getrusage(). + */ +#if (OS_MAJOR > 5 || (OS_MAJOR == 5 && OS_MINOR >= 5)) +#include <sys/resource.h> +#define HAVE_GETRUSAGE +#define RLIMIT_TYPE rlim_t +#define RLIMIT_FILE_INFINITY +#endif + +#include <resolv_mt.h> +#include <netdb_private.h> +#include <inet_private.h> +#include <ctype.h> +#include <sunw_dst_init.h> +#include <sunw_irs_init.h> + +#ifdef ORIGINAL_ISC_CODE +const char *isc_strerror(int errnum); +#define strerror isc_strerror +#endif + +#ifndef ISC_FACILITY +#define ISC_FACILITY LOG_DAEMON +#endif + +/* res_mkquery.c refers explicitly to __putlong and __putshort */ +#define __putlong putlong +#define __putshort putshort + +/* + * If one wanted to use isc__gettimeofday for Solaris, they would + * need to define NEED_GETTIMEOFDAY (common/bsd/gettimeofday.c), + * which is not defined for Solaris. Hence there is no reason to + * change the current definition of gettimeofday which currently + * comes from libc and we comment the following out. + */ +#ifdef ORIGINAL_ISC_CODE +int isc__gettimeofday(struct timeval *, struct timezone *); +#define gettimeofday isc__gettimeofday +#endif + +/* + * Solaris 8 has if_nametoindex(). + */ +#if (OS_MAJOR > 5 || (OS_MAJOR == 5 && OS_MINOR >= 8)) +#define USE_IFNAMELINKID +#endif + +#define UNUSED(x) (x) = (x) +#define DE_CONST(konst, var) \ + do { \ + union { const void *k; void *v; } _u; \ + _u.k = konst; \ + var = _u.v; \ + } while (0) +#endif /* ! PORT_AFTER_H */ diff --git a/usr/src/lib/libresolv2/include/port_before.h b/usr/src/lib/libresolv2/include/port_before.h new file mode 100644 index 0000000000..32595ef5e0 --- /dev/null +++ b/usr/src/lib/libresolv2/include/port_before.h @@ -0,0 +1,159 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef SUNW_OPTIONS +#include "conf/sunoptions.h" +#endif + +#define __EXTENSIONS__ +/* #define SVR4 */ +#ifdef WANT_IRS_NIS +#undef WANT_IRS_NIS +#endif +#undef WANT_IRS_PW +#undef WANT_IRS_GR +#define SIG_FN void +#define ISC_SOCKLEN_T int +#include "os_version.h" +#if (OS_MAJOR == 5 && OS_MINOR < 5) +#undef HAS_PTHREADS +#else +#define HAS_PTHREADS +#endif + +#if defined(HAS_PTHREADS) && defined(_REENTRANT) +#define DO_PTHREADS +#endif + +#define GROUP_R_RETURN struct group * +#define GROUP_R_SET_RETURN void +#undef GROUP_R_SET_RESULT /*empty*/ +#define GROUP_R_END_RETURN void +#undef GROUP_R_END_RESULT /*empty*/ +#define GROUP_R_ARGS char *buf, int buflen +#undef GROUP_R_ENT_ARGS /*empty*/ +#define GROUP_R_OK gptr +#define GROUP_R_BAD NULL +#define GETGROUPLIST_ARGS const char *name, gid_t basegid, gid_t *groups, \ + int *ngroups + +#define HOST_R_RETURN struct hostent * +#define HOST_R_SET_RETURN void +#undef HOST_R_SET_RESULT /*empty*/ +#define HOST_R_END_RETURN void +#define HOST_R_END_RESULT(x) /*empty*/ +#define HOST_R_ARGS char *buf, int buflen, int *h_errnop +#undef HOST_R_ENT_ARGS /*empty*/ +#define HOST_R_COPY buf, buflen +#define HOST_R_COPY_ARGS char *buf, int buflen +#define HOST_R_ERRNO *h_errnop = h_errno +#define HOST_R_OK hptr +#define HOST_R_BAD NULL + +#define NET_R_RETURN struct netent * +#define NET_R_SET_RETURN void +#undef NET_R_SET_RESULT /*empty*/ +#define NET_R_END_RETURN void +#define NET_R_END_RESULT(x) /*empty*/ +#define NET_R_ARGS char *buf, int buflen +#undef NET_R_ENT_ARGS /*empty*/ +#define NET_R_COPY buf, buflen +#define NET_R_COPY_ARGS NET_R_ARGS +#define NET_R_OK nptr +#define NET_R_BAD NULL + +#define NGR_R_RETURN int +#define NGR_R_SET_RETURN void +#undef NGR_R_SET_RESULT /*empty*/ +#define NGR_R_END_RETURN void +#ifdef ORIGINAL_ISC_CODE +#undef NGR_R_END_RESULT /*empty*/ +#else +#define NGR_R_END_RESULT(x) /*empty*/ +#endif +#define NGR_R_ARGS char *buf, int buflen +#undef NGR_R_ENT_ARGS /*empty*/ +#define NGR_R_COPY buf, buflen +#define NGR_R_COPY_ARGS NGR_R_ARGS +#define NGR_R_OK 1 +#define NGR_R_BAD (0) + +#define PROTO_R_RETURN struct protoent * +#define PROTO_R_SET_RETURN void +#undef PROTO_R_SET_RESULT /*empty*/ +#define PROTO_R_END_RETURN void +#define PROTO_R_END_RESULT(x) /*empty*/ +#define PROTO_R_ARGS char *buf, int buflen +#undef PROTO_R_ENT_ARGS /*empty*/ +#define PROTO_R_COPY buf, buflen +#define PROTO_R_COPY_ARGS PROTO_R_ARGS +#define PROTO_R_OK pptr +#define PROTO_R_BAD NULL + +#define PASS_R_RETURN struct passwd * +#define PASS_R_SET_RETURN void +#undef PASS_R_SET_RESULT /*empty*/ +#define PASS_R_END_RETURN void +#undef PASS_R_END_RESULT /*empty*/ +#define PASS_R_ARGS char *buf, int buflen +#undef PASS_R_ENT_ARGS /*empty*/ +#define PASS_R_COPY buf, buflen +#define PASS_R_COPY_ARGS PASS_R_ARGS +#define PASS_R_OK pwptr +#define PASS_R_BAD NULL + +#define SERV_R_RETURN struct servent * +#define SERV_R_SET_RETURN void +#undef SERV_R_SET_RESULT /*empty*/ +#define SERV_R_END_RETURN void +#define SERV_R_END_RESULT(x) /*empty*/ +#define SERV_R_ARGS char *buf, int buflen +#undef SERV_R_ENT_ARGS /*empty*/ +#define SERV_R_COPY buf, buflen +#define SERV_R_COPY_ARGS SERV_R_ARGS +#define SERV_R_OK sptr +#define SERV_R_BAD NULL + +/* make #include <sys/ioctl.h> also #include <sys/sockio.h> */ +#define BSD_COMP + +#include <limits.h> /* _POSIX_PATH_MAX */ + +#ifdef __GNUC__ +#define ISC_FORMAT_PRINTF(fmt, args) \ + __attribute__((__format__(__printf__, fmt, args))) +#else +#define ISC_FORMAT_PRINTF(fmt, args) +#endif + +/* + * Several files in the ISC distribution use an ALIGN macro which doesn't + * appear to be defined anywhere. From the context, it's intended to round + * up its argument to the nearest suitable boundary. We'll guess that eight + * byte alignment is sufficient. + */ +#define ALIGN(p) (uint64_t)(((uintptr_t)(p) + (sizeof (uint64_t) - 1)) \ + & ~(sizeof (uint64_t) - 1)) + +#ifdef SUNW_SYNONYMS +#include "synonyms.h" +#endif + +/* + * Remove compiler warnings without modifying ISC source by including + * various headers here, mostly to get function prototypes. + */ +#include <string.h> +#include <strings.h> +#include <unistd.h> + +#include <sys/types.h> +#include "sys/bitypes.h" +#include "sys/cdefs.h" + +#define HAS_INET6_STRUCTS +#define H_ERRNO_IS_FUNCTION diff --git a/usr/src/lib/libresolv2/include/prand_conf.h b/usr/src/lib/libresolv2/include/prand_conf.h new file mode 100644 index 0000000000..89aa78295c --- /dev/null +++ b/usr/src/lib/libresolv2/include/prand_conf.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + * + * No ISC copyright for this file. + */ + +#ifndef _PRAND_CMD_H_ +#define _PRAND_CMD_H_ + +#pragma ident "%Z%%M% %I% %E% SMI" + +static const char *cmds[] = { + "/bin/ps -ef 2>&1", + "/usr/ucb/netstat -an 2>&1", + "/bin/df 2>&1", + "/usr/bin/dig com. soa +ti=1 +retry=0 2>&1", + "/usr/ucb/uptime 2>&1", + "/usr/ucb/netstat -an 2>&1", + "/bin/iostat 2>&1", + NULL +}; + +static const char *dirs[] = { + "/tmp", + "/var/tmp", + ".", + "/", + "/var/spool", + "/var/adm", + "/dev", + "/var/mail", + "/home", + NULL +}; + +static const char *files[] = { + "/proc/self/status", + "/var/adm/messages", + "/var/adm/wtmp", + "/var/adm/lastlog", + NULL +}; + +#endif /* _PRAND_CMD_H_ */ diff --git a/usr/src/lib/libresolv2/include/probe_ipv6 b/usr/src/lib/libresolv2/include/probe_ipv6 new file mode 100644 index 0000000000..371ac96c55 --- /dev/null +++ b/usr/src/lib/libresolv2/include/probe_ipv6 @@ -0,0 +1,73 @@ +#!/bin/sh + +# Copyright 2003 by Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" + +set -e +PATH=/bin:/usr/bin:$PATH; export PATH +trap "rm -f tmp$$[abc].[oc]" 0 +target=port_ipv6 +new=new_${target}.h +old=${target}.h + +cat > tmp$$a.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct sockaddr_in6 xx; +EOF + +cat > tmp$$b.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct in6_addr xx; +EOF + +cat > tmp$$c.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct sockaddr_in6 xx; +main() { xx.sin6_scope_id = 0; } +EOF + +cat > ${new} <<EOF + +/* This file is automatically generated. Do Not Edit. */ + +#ifndef ${target}_h +#define ${target}_h + +EOF + +if ${CC} -c tmp$$a.c > /dev/null 2>&1 +then + echo "#define HAS_INET6_STRUCTS" >> ${new} + if ${CC} -c tmp$$b.c > /dev/null 2>&1 + then + : + else + echo "#define in6_addr in_addr6" >> ${new} + fi + if ${CC} -c tmp$$c.c > /dev/null 2>&1 + then + echo "#define HAVE_SIN6_SCOPE_ID" >> ${new} + else + echo "#undef HAVE_SIN6_SCOPE_ID" >> ${new} + fi +else + echo "#undef HAS_INET6_STRUCTS" >> ${new} +fi +echo >> ${new} +echo "#endif" >> ${new} +if [ -f ${old} ]; then + if cmp -s ${new} ${old} ; then + rm -f ${new} + else + rm -f ${old} + mv ${new} ${old} + fi +else + mv ${new} ${old} +fi +exit 0 diff --git a/usr/src/lib/libresolv2/include/res_update.h b/usr/src/lib/libresolv2/include/res_update.h new file mode 100644 index 0000000000..e2eb9c651f --- /dev/null +++ b/usr/src/lib/libresolv2/include/res_update.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $Id: res_update.h,v 8.1 1999/10/07 08:24:13 vixie Exp $ + */ + +#ifndef __RES_UPDATE_H +#define __RES_UPDATE_H + +#include <sys/types.h> +#include <sys/bitypes.h> +#include <arpa/nameser.h> +#include <isc/list.h> +#include <resolv.h> + +#ifdef ORIGINAL_ISC_CODE +#else +/* + * ISC changed the ns_updrec structure. However, it's a public interface + * in Solaris, so it's time to break out that old #define magic. + */ +#define ns_updrec __ISC_ns_updrec +#endif /* ORIGINAL_ISC_CODE */ +/* + * This RR-like structure is particular to UPDATE. + */ +struct ns_updrec { + LINK(struct ns_updrec) r_link, r_glink; + ns_sect r_section; /* ZONE/PREREQUISITE/UPDATE */ + char * r_dname; /* owner of the RR */ + ns_class r_class; /* class number */ + ns_type r_type; /* type number */ + u_int32_t r_ttl; /* time to live */ + u_char * r_data; /* rdata fields as text string */ + u_int r_size; /* size of r_data field */ + int r_opcode; /* type of operation */ + /* following fields for private use by the resolver/server routines */ + struct databuf *r_dp; /* databuf to process */ + struct databuf *r_deldp; /* databuf's deleted/overwritten */ + u_int r_zone; /* zone number on server */ +}; +typedef struct ns_updrec ns_updrec; + +typedef LIST(ns_updrec) ns_updque; + +#ifdef ORIGINAL_ISC_CODE +#define res_mkupdate __res_mkupdate +#define res_update __res_update +#define res_mkupdrec __res_mkupdrec +#define res_freeupdrec __res_freeupdrec +#define res_nmkupdate __res_nmkupdate +#define res_nupdate __res_nupdate +#else +/* + * For BIND 8.2.2, ISC removed the dynamic update functions, and the + * definition of the ns_updrec structure, from the public include files + * (<resolv.h>, <arpa/nameser.h>. However, res_update(), res_mkupdate(), + * and res_mkupdrec() are in the public libresolv interface in Solaris, + * so we can't easily remove them. Thus, ISC's new versions of res_mkupdate() + * etc. can't be exposed under their original names. + * + * res_nmkupdate() and res_nupdate are new. We could either change them + * to accept the <arpa/nameser.h> ns_updrec, or leave them unchanged and + * undocumented. Since ISC may change ns_updrec again, we pick the latter + * solution for now. + */ +#define res_mkupdate __ISC_res_mkupdate +#define res_update __ISC_res_update +#define res_mkupdrec __ISC_res_mkupdrec +#define res_freeupdrec __ISC_res_freeupdrec +#define res_nmkupdate __ISC_res_nmkupdate +#define res_nupdate __ISC_res_nupdate +#endif /* ORIGINAL_ISC_CODE */ + +int res_mkupdate __P((ns_updrec *, u_char *, int)); +int res_update __P((ns_updrec *)); +ns_updrec * res_mkupdrec __P((int, const char *, u_int, u_int, u_long)); +void res_freeupdrec __P((ns_updrec *)); +int res_nmkupdate __P((res_state, ns_updrec *, u_char *, int)); +int res_nupdate __P((res_state, ns_updrec *, ns_tsig_key *)); + +#endif /*__RES_UPDATE_H*/ diff --git a/usr/src/lib/libresolv2/include/resolv_mt.h b/usr/src/lib/libresolv2/include/resolv_mt.h new file mode 100644 index 0000000000..e26fd18f02 --- /dev/null +++ b/usr/src/lib/libresolv2/include/resolv_mt.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1998-1999 by Sun Microsystems, Inc. + */ + +#ifndef _RESOLV_MT_H +#define _RESOLV_MT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SUNW_MT_RESOLVER + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +/* Access functions for the libresolv private interface */ + +int __res_enable_mt(void); +int __res_disable_mt(void); + +/* Per-thread context */ + +typedef struct { +#ifdef SUNW_HOSTS_FALLBACK + int no_hosts_fallback_private; +#endif /* SUNW_HOSTS_FALLBACK */ +#ifdef SUNW_OVERRIDE_RETRY + int retry_save; + int retry_private; +#endif /* SUNW_OVERRIDE_RETRY */ + char inet_nsap_ntoa_tmpbuf[255*3]; + char sym_ntos_unname[20]; + char sym_ntop_unname[20]; + char p_option_nbuf[40]; + char p_time_nbuf[40]; + char precsize_ntoa_retbuf[sizeof "90000000.00"]; + char loc_ntoa_tmpbuf[sizeof +"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; + char p_secstodate_output[15]; +} mtctxres_t; + +/* Thread-specific data (TSD) */ + +extern mtctxres_t *___mtctxres(); +#define mtctxres (___mtctxres()) + +/* Various static data that should be TSD */ + +#define sym_ntos_unname (mtctxres->sym_ntos_unname) +#define sym_ntop_unname (mtctxres->sym_ntop_unname) +#define inet_nsap_ntoa_tmpbuf (mtctxres->inet_nsap_ntoa_tmpbuf) +#define p_option_nbuf (mtctxres->p_option_nbuf) +#define p_time_nbuf (mtctxres->p_time_nbuf) +#define precsize_ntoa_retbuf (mtctxres->precsize_ntoa_retbuf) +#define loc_ntoa_tmpbuf (mtctxres->loc_ntoa_tmpbuf) +#define p_secstodate_output (mtctxres->p_secstodate_output) + +#endif /* SUNW_MT_RESOLVER */ + +#ifdef __cplusplus +} +#endif + +#endif /* _RESOLV_MT_H */ diff --git a/usr/src/lib/libresolv2/include/sunw_dst_init.h b/usr/src/lib/libresolv2/include/sunw_dst_init.h new file mode 100644 index 0000000000..72a93e3d70 --- /dev/null +++ b/usr/src/lib/libresolv2/include/sunw_dst_init.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _SUNW_DST_INIT_H +#define _SUNW_DST_INIT_H + +extern int sunw_dst_bsafe_init(void); +extern int sunw_dst_rsaref_init(void); +extern int sunw_dst_hmac_md5_init(void); +extern int sunw_dst_eay_dss_init(void); +extern int sunw_dst_cylink_init(void); + +#ifndef __SUNW_DST_INIT_NODEFINE + +#define dst_bsafe_init sunw_dst_bsafe_init +#define dst_rsaref_init sunw_dst_rsaref_init +#define dst_hmac_md5_init sunw_dst_hmac_md5_init +#define dst_eay_dss_init sunw_dst_eay_dss_init +#define dst_cylink_init sunw_dst_cylink_init + +#endif /* __SUNW_DST_INIT_NODEFINE */ + +#endif /* _SUNW_DST_INIT_H */ diff --git a/usr/src/lib/libresolv2/include/sunw_irs_init.h b/usr/src/lib/libresolv2/include/sunw_irs_init.h new file mode 100644 index 0000000000..d249a0f7e6 --- /dev/null +++ b/usr/src/lib/libresolv2/include/sunw_irs_init.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _SUNW_IRS_INIT_H +#define _SUNW_IRS_INIT_H + +extern struct irs_acc *sunw_irs_nis_acc(const char *); +extern struct irs_acc *sunw_irs_irp_acc(const char *); + +#ifndef __SUNW_IRS_INIT_NODEFINE + +#define __irs_nis_acc sunw_irs_nis_acc +#define __irs_irp_acc sunw_irs_irp_acc + +#endif /* __SUNW_IRS_INIT_NODEFINE */ + +#endif /* _SUNW_IRS_INIT_H */ diff --git a/usr/src/lib/libresolv2/include/synonyms.h b/usr/src/lib/libresolv2/include/synonyms.h new file mode 100644 index 0000000000..a1a17fb7d4 --- /dev/null +++ b/usr/src/lib/libresolv2/include/synonyms.h @@ -0,0 +1,564 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1988 AT&T */ +/* All Rights Reserved */ + + +#ifndef _SYNONYMS_H +#define _SYNONYMS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__STDC__) + +/* external data */ +#define altzone _altzone +#define daylight _daylight +#define lone _lone +#define lten _lten +#define lzero _lzero +#define timezone _timezone +#define tzname _tzname + +/* functions */ +#define Msgdb _Msgdb +#define a64l _a64l +#define access _access +#define acct _acct +#define acl _acl +#define addseverity _addseverity +#define adjtime _adjtime +#define alarm _alarm +#define ascftime _ascftime +#define basename _basename +#define brk _brk +#define brkbase _brkbase +#define bsd_signal _bsd_signal +#define catclose _catclose +#define catgets _catgets +#define catopen _catopen +#define cfgetispeed _cfgetispeed +#define cfgetospeed _cfgetospeed +#define cfree _cfree +#define cfsetispeed _cfsetispeed +#define cfsetospeed _cfsetospeed +#define cftime _cftime +#define chdir _chdir +#define chmod _chmod +#define chown _chown +#define chroot _chroot +#define close _close +#define closedir _closedir +#define closelog _closelog +#define countbase _countbase +#define creat _creat +#define crypt _crypt +#define ctermid _ctermid +#define cuserid _cuserid +#define dial _dial +#define dirname _dirname +#define door_bind _door_bind +#define door_call _door_call +#define door_create _door_create +#define door_cred _door_cred +#define door_getparam _door_getparam +#define door_info _door_info +#define door_return _door_return +#define door_revoke _door_revoke +#define door_setparam _door_setparam +#define door_server_create _door_server_create +#define door_ucred _door_ucred +#define door_unbind _door_unbind +#define drand48 _drand48 +#define dup _dup +#define dup2 _dup2 +#define ecvt _ecvt +#define edata _edata +#define encrypt _encrypt +#define end _end +#define endgrent _endgrent +#define endpwent _endpwent +#define endspent _endspent +#define endutent _endutent +#define endutxent _endutxent +#define environ _environ +#define erand48 _erand48 +#define etext _etext +#define execl _execl +#define execle _execle +#define execlp _execlp +#define execv _execv +#define execve _execve +#define execvp _execvp +#define exportfs _exportfs +#define facl _facl +#define fattach _fattach +#define fchdir _fchdir +#define fchmod _fchmod +#define fchown _fchown +#define fchroot _fchroot +#define fcntl _fcntl +#define fcvt _fcvt +#define fdetach _fdetach +#define fdopen _fdopen +#define ffs _ffs +#define fgetgrent _fgetgrent +#define fgetgrent_r _fgetgrent_r +#define fgetpwent _fgetpwent +#define fgetpwent_r _fgetpwent_r +#define fgetspent _fgetspent +#define fgetspent_r _fgetspent_r +#define finite _finite +#define fmtmsg _fmtmsg +#define fork _fork +#define fork1 _fork1 +#define fpathconf _fpathconf +#define fpclass _fpclass +#define fpgetmask _fpgetmask +#define fpgetround _fpgetround +#define fpgetsticky _fpgetsticky +#define fprintf _fprintf +#define fpsetmask _fpsetmask +#define fpsetround _fpsetround +#define fpsetsticky _fpsetsticky +#define fstat _fstat +#define fstatfs _fstatfs +#define fstatvfs _fstatvfs +#define fsync _fsync +/* #define ftell _ftell */ +#define ftello _ftello +/* #define fseek _fseek */ +#define fseeko _fseeko +#define ftok _ftok +#define ftruncate _ftruncate +#define gcvt _gcvt +#define getcontext _getcontext +#define getcwd _getcwd +#define getdate _getdate +#if !defined(_REENTRANT) +#define getdate_err _getdate_err +#else /* defined(_REENTRANT) */ +#define _getdate_err getdate_err +#endif /* !defined(_REENTRANT) */ +#define getdents _getdents +#define getegid _getegid +#define geteuid _geteuid +#define getgid _getgid +#define getgrent _getgrent +#define getgrent_r _getgrent_r +#define getgrgid _getgrgid +#define getgrgid_r _getgrgid_r +#define getgrnam _getgrnam +#define getgrnam_r _getgrnam_r +#define getgroups _getgroups +#define gethz _gethz +#define getitimer _getitimer +#define getlogin _getlogin +#define getmntany _getmntany +#define getmntent _getmntent +#define getmsg _getmsg +#define getopt _getopt +#define getpass _getpass +#define getpassphrase _getpassphrase +#define getpgid _getpgid +#define getpgrp _getpgrp +#define getpid _getpid +#define getpmsg _getpmsg +#define getppid _getppid +#define getpw _getpw +#define getpwent _getpwent +#define getpwent_r _getpwent_r +#define getpwnam _getpwnam +#define getpwnam_r _getpwnam_r +#define getpwuid _getpwuid +#define getpwuid_r _getpwuid_r +#define getrlimit _getrlimit +#define getsid _getsid +#define getspent _getspent +#define getspent_r _getspent_r +#define getspnam _getspnam +#define getspnam_r _getspnam_r +#define getsubopt _getsubopt +#define gettimeofday _gettimeofday +#define gettxt _gettxt +#define getuid _getuid +#define getutent _getutent +#define getutid _getutid +#define getutline _getutline +#define getutmp _getutmp +#define getutmpx _getutmpx +#define getutxent _getutxent +#define getutxid _getutxid +#define getutxline _getutxline +#define getvfsany _getvfsany +#define getvfsent _getvfsent +#define getvfsfile _getvfsfile +#define getvfsspec _getvfsspec +#define getw _getw +#define grantpt _grantpt +#define gsignal _gsignal +#define gtty _gtty +#define hasmntopt _hasmntopt +#define hcreate _hcreate +#define hdestroy _hdestroy +#define hsearch _hsearch +#define id2str _id2str +#define initgroups _initgroups +#define insque _insque +#define install_utrap _install_utrap +#define ioctl _ioctl +#define isastream _isastream +#define isatty _isatty +#define jrand48 _jrand48 +#define kaio _kaio +#define kill _kill +#define l64a _l64a +#define ladd _ladd +#define lchown _lchown +#define lckpwdf _lckpwdf +#define lcong48 _lcong48 +#define ldivide _ldivide +#define lexp10 _lexp10 +#define lfind _lfind +#define link _link +#define llog10 _llog10 +#define llseek _llseek +#define lmul _lmul +#define lockf _lockf +#define longjmp _longjmp +#define lrand48 _lrand48 +#define lsearch _lsearch +#define lseek _lseek +#define lshiftl _lshiftl +#define lsign _lsign +#define lstat _lstat +#define lsub _lsub +#define ltol3 _ltol3 +#define madvise _madvise +#define makecontext _makecontext +#define makeut _makeut +#define makeutx _makeutx +#define memalign _memalign +#define memccpy _memccpy +#define memcntl _memcntl +#define memcmp _memcmp +#define memcpy _memcpy +#define memmove _memmove +#define memset _memset +#define mincore _mincore +#define mkdir _mkdir +#define mkfifo _mkfifo +#define mknod _mknod +#define mktemp _mktemp +#define mkstemp _mkstemp +#define mlock _mlock +#define mlockall _mlockall +#define mmap _mmap +#define modut _modut +#define modutx _modutx +#define monitor _monitor +#define mount _mount +#define mprotect _mprotect +#define mrand48 _mrand48 +#define msgctl _msgctl +#define msgget _msgget +#define msgrcv _msgrcv +#define msgsnd _msgsnd +#define msync _msync +#define munlock _munlock +#define munlockall _munlockall +#define munmap _munmap +#define nfs_getfh _nfs_getfh +#define nfssvc _nfssvc +#define nftw _nftw +#define nice _nice +#define nrand48 _nrand48 +#define nss_delete _nss_delete +#define nss_endent _nss_endent +#define nss_getent _nss_getent +#define nss_search _nss_search +#define nss_setent _nss_setent +#define open _open +#define opendir _opendir +#define openlog _openlog +#define pathconf _pathconf +#define pause _pause +#define pclose _pclose +#define pipe _pipe +#define plock _plock +#define poll _poll +#define popen _popen +#define pread _pread +#define pset_create _pset_create +#define pset_destroy _pset_destroy +#define pset_assign _pset_assign +#define pset_info _pset_info +#define pset_bind _pset_bind +#define profil _profil +#define psiginfo _psiginfo +#define psignal _psignal +#define ptrace _ptrace +#define ptsname _ptsname +#define pwrite _pwrite +#define putenv _putenv +#define putmsg _putmsg +#define putpmsg _putpmsg +#define putpwent _putpwent +#define putspent _putspent +#define pututline _pututline +#define pututxline _pututxline +#define putw _putw +#define read _read +#define readdir _readdir +#define readdir_r _readdir_r +#define readlink _readlink +#define readv _readv +#define realpath _realpath +#define regcmp _regcmp +#define regex _regex +#define remque _remque +#define rmdir _rmdir +#define sbrk _sbrk +#define seed48 _seed48 +#define seekdir _seekdir +#define select _select +#define semctl _semctl +#define semget _semget +#define semop _semop +#define setcontext _setcontext +#define setegid _setegid +#define seteuid _seteuid +#define setgid _setgid +#define setgrent _setgrent +#define setgroups _setgroups +#define setitimer _setitimer +#define setjmp _setjmp +#define setkey _setkey +#define setlocale _setlocale +#define setlogmask _setlogmask +#define setpgid _setpgid +#define setpgrp _setpgrp +#define setpwent _setpwent +#define setregid _setregid +#define setreuid _setreuid +#define setrlimit _setrlimit +#define setsid _setsid +#define setspent _setspent +#define settimeofday _settimeofday +#define setuid _setuid +#define setutent _setutent +#define setutxent _setutxent +#define shmat _shmat +#define shmctl _shmctl +#define shmdt _shmdt +#define shmget _shmget +#define sig2str _sig2str +#define sigaction _sigaction +#define sigaddset _sigaddset +#define sigaltstack _sigaltstack +#define sigdelset _sigdelset +#define sigemptyset _sigemptyset +#define sigfillset _sigfillset +#define sigflag _sigflag +#define sigfpe _sigfpe +#define sighold _sighold +#define sigignore _sigignore +#define siginterrupt _siginterrupt +#define sigismember _sigismember +#define siglongjmp _siglongjmp +#define sigpause _sigpause +#define sigpending _sigpending +#define sigprocmask _sigprocmask +#define sigrelse _sigrelse +#define sigsend _sigsend +#define sigsendset _sigsendset +#define sigset _sigset +#define signal _signal +#define sigsetjmp _sigsetjmp +#define sigsuspend _sigsuspend +#define sigwait _sigwait +#define sleep _sleep +#define srand48 _srand48 +#define ssignal _ssignal +#define stat _stat +#define statfs _statfs +#define statvfs _statvfs +#define stime _stime +#define str2id _str2id +#define str2sig _str2sig +#define strdup _strdup +#define stty _stty +#define swab _swab +#define swapcontext _swapcontext +#define swapctl _swapctl +#define symlink _symlink +#define sync _sync +#define synchutmp _synchutmp +#if defined(__ppc) +#define sysppc _sysppc +#else +#define syssun _syssun +#endif +#define sys_errlist _sys_errlist +#define sys_nerr _sys_nerr +#define syscall _syscall +#define sysconf _sysconf +#define sysfs _sysfs +#define sysinfo _sysinfo +#define syslog _syslog +#define tcdrain _tcdrain +#define tcflow _tcflow +#define tcflush _tcflush +#define tcgetattr _tcgetattr +#define tcgetpgrp _tcgetpgrp +#define tcgetsid _tcgetsid +#define tcsendbreak _tcsendbreak +#define tcsetattr _tcsetattr +#define tcsetpgrp _tcsetpgrp +#define tdelete _tdelete +#define tell _tell +#define telldir _telldir +#define tempnam _tempnam +#define tfind _tfind +#define time _time +#define times _times +#define truncate _truncate +#define tsearch _tsearch +#define ttyname _ttyname +#define ttyslot _ttyslot +#define twalk _twalk +#define tzname _tzname +#define tzset _tzset +#define uadmin _uadmin +#define ulckpwdf _ulckpwdf +#define ulimit _ulimit +#define umask _umask +#define umount _umount +#define uname _uname +#define undial _undial +#define unlink _unlink +#define unlockpt _unlockpt +#define unordered _unordered +#define updutfile _updutfile +#define updutxfile _updutxfile +#define updutmp _updutmp +#define updutmpx _updutmpx +#define updwtmp _updwtmp +#define updwtmpx _updwtmpx +#define ustat _ustat +#define utime _utime +#define utimes _utimes +#define utmpname _utmpname +#define utmpxname _utmpxname +#define utssys _utssys +#define valloc _valloc +#define vfork _vfork +#define vhangup _vhangup +#define vsyslog _vsyslog +#define wait _wait +#define waitid _waitid +#define waitpid _waitpid +#define write _write +#define writev _writev +#define yield _yield +#define _assert __assert +#define _ctype __ctype +#define _filbuf __filbuf +#define _flsbuf __flsbuf +#define _iob __iob + +/* fp and ll functions */ +#define decimal_to_double _decimal_to_double +#define decimal_to_extended _decimal_to_extended +#define decimal_to_quadruple _decimal_to_quadruple +#define decimal_to_single _decimal_to_single +#define double_to_decimal _double_to_decimal +#define econvert _econvert +#define extended_to_decimal _extended_to_decimal +#define fconvert _fconvert +#define file_to_decimal _file_to_decimal +#define func_to_decimal _func_to_decimal +#define gconvert _gconvert +#define qeconvert _qeconvert +#define qecvt _qecvt +#define qfconvert _qfconvert +#define qfcvt _qfcvt +#define qgconvert _qgconvert +#define qgcvt _qgcvt +#define quadruple_to_decimal _quadruple_to_decimal +#define seconvert _seconvert +#define sfconvert _sfconvert +#define sgconvert _sgconvert +#define single_to_decimal _single_to_decimal +#define string_to_decimal _string_to_decimal +#define atoll _atoll +#define llabs _llabs +#define lldiv _lldiv +#define lltostr _lltostr +#define strtoll _strtoll +#define strtoull _strtoull +#define ulltostr _ulltostr + +#if !defined(_LP64) +/* transitional large file interfaces */ +#define creat64 _creat64 +#define ftello64 _ftello64 +#define fseeko64 _fseeko64 +#define fstat64 _fstat64 +#define ftw64 _ftw64 +#define fstatvfs64 _fstatvfs64 +#define ftruncate64 _ftruncate64 +#define getdents64 _getdents64 +#define getrlimit64 _getrlimit64 +#define lockf64 _lockf64 +#define lseek64 _lseek64 +#define lstat64 _lstat64 +#define mkstemp64 _mkstemp64 +#define mmap64 _mmap64 +#define nftw64 _nftw64 +#define open64 _open64 +#define pread64 _pread64 +#define pwrite64 _pwrite64 +#define readdir64 _readdir64 +#define readdir64_r _readdir64_r +#define seekdir64 _seekdir64 +#define telldir64 _telldir64 +#define setrlimit64 _setrlimit64 +#define stat64 _stat64 +#define statvfs64 _statvfs64 +#define truncate64 _truncate64 +#endif /* !_LP64 */ + +#define thr_setspecific _thr_setspecific +#define thr_getspecific _thr_getspecific +#define thr_keycreate _thr_keycreate + +#ifdef SUNW_LIBNSL +#define inet_aton _inet_aton +#endif + +#else /* !defined(__STDC__) */ + +#if !defined(_ASM) +#define const + +#if !defined(_SIZE_T) +#define _SIZE_T +typedef unsigned int size_t; +#endif /* !defined(_SIZE_T) */ +#endif /* !defined(_ASM) */ + +#endif /* defined(__STDC__) */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYNONYMS_H */ diff --git a/usr/src/lib/libresolv2/include/sys/bitypes.h b/usr/src/lib/libresolv2/include/sys/bitypes.h new file mode 100644 index 0000000000..5228129f3b --- /dev/null +++ b/usr/src/lib/libresolv2/include/sys/bitypes.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997-2000 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ + + /* + * Basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ +#ifndef _SYS_INT_TYPES_H + typedef /*signed*/ char int8_t; + typedef short int16_t; + typedef int int32_t; +#endif /* _SYS_INT_TYPES_H */ + typedef unsigned char u_int8_t; + typedef unsigned short u_int16_t; + typedef unsigned int u_int32_t; + +# if 0 /* don't fight with these unless you need them */ + typedef long long int64_t; + typedef unsigned long long u_int64_t; +# endif + +#endif /* __BIT_TYPES_DEFINED__ */ diff --git a/usr/src/lib/libresolv2/include/sys/cdefs.h b/usr/src/lib/libresolv2/include/sys/cdefs.h new file mode 100644 index 0000000000..9738c69582 --- /dev/null +++ b/usr/src/lib/libresolv2/include/sys/cdefs.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1997, by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * ++Copyright++ 1991, 1993 + * - + * Copyright (c) 1991, 1993 + * The 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. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +/* + * @(#)cdefs.h 8.1 (Berkeley) 6/2/93 + * $Id: cdefs.h,v 1.1 1996/11/22 02:20:19 vixie Exp $ + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _CDEFS_H_ +#define _CDEFS_H_ + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS }; +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. __CONCAT can also concatenate double-quoted + * strings produced by the __STRING macro, but this only works with ANSI C. + */ +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) +#define __inline inline /* convert to C++ keyword */ +#else +#ifndef __GNUC__ +#define __inline /* delete GCC keyword */ +#endif /* !__GNUC__ */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#ifndef __GNUC__ +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * When using a compiler other than gcc, programs using the ANSI C keywords + * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. + * When using "gcc -traditional", we assume that this is the intent; if + * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. + */ +#ifndef NO_ANSI_KEYWORDS +#define const /* delete ANSI C keywords */ +#define inline +#define signed +#define volatile +#endif +#endif /* !__GNUC__ */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of + * these work for GNU C++ (modulo a slight glitch in the C++ grammar + * in the distribution version of 2.5.5). + */ +#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5 +#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define __dead __volatile +#define __pure __const +#endif +#endif + +/* Delete pseudo-keywords wherever they are not available or needed. */ +#ifndef __dead +#define __dead +#define __pure +#endif + +#endif /* !_CDEFS_H_ */ diff --git a/usr/src/lib/libresolv2/irs/Makefile b/usr/src/lib/libresolv2/irs/Makefile new file mode 100644 index 0000000000..42a540092b --- /dev/null +++ b/usr/src/lib/libresolv2/irs/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/irs/Makefile + +include ../../../Makefile.master +include ../../Makefile.lib + +SUBDIRS= spec $(MACH) $(BUILD64) $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +delete := TARGET= delete +install := TARGET= install +lint := TARGET= lint +_msg := TARGET= _msg +package := TARGET= package + +LIBRARY= irs.a +TEXT_DOMAIN= SUNW_OST_OSLIB +XGETFLAGS= -a +POFILE= $(LIBRARY:.a=.po) +POFILES= generic.po + +SED= sed +GREP= grep +CP= cp + +.KEEP_STATE: + +all clean clobber delete install lint package: $(SUBDIRS) + +# install rule for install_h target +$(ROOTHDRDIR)/%: % + $(INS.file) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(MACH) $(MACH64) spec: FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +_msg: $(MSGDOMAIN) $(POFILE) + $(RM) $(MSGDOMAIN)/$(POFILE) + $(CP) $(POFILE) $(MSGDOMAIN) + +$(POFILE): $(POFILES) + $(RM) $@ + $(CAT) $(POFILES) > $@ + +$(POFILES): + $(RM) messages.po + $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]* + $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ + $(RM) messages.po + +FRC: diff --git a/usr/src/lib/libresolv2/irs/Makefile.com b/usr/src/lib/libresolv2/irs/Makefile.com new file mode 100644 index 0000000000..d99eb7f828 --- /dev/null +++ b/usr/src/lib/libresolv2/irs/Makefile.com @@ -0,0 +1,70 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/irs/Makefile.com +# + +LIBRARY= irs.a +VERS= .1 + +IRSDYNOBJS= nis_nw.o nis_pr.o nis_pw.o nis_sv.o \ + nis.o nis_gr.o nis_ho.o nis_ng.o \ + irp.o irpmarshall.o irp_ho.o irp_nw.o \ + irp_pr.o irp_sv.o irp_gr.o irp_ng.o \ + irp_pw.o getnetent.o getpwent_r.o getgrent_r.o \ + getservent_r.o getnetent_r.o getnetgrent_r.o getgrent.o \ + getnetgrent.o getprotoent.o getpwent.o getservent.o \ + getprotoent_r.o getnameinfo.o gai_strerror.o + +SUNWOBJS= sunw_irs_nis_acc.o + +OBJECTS= $(IRSDYNOBJS) $(SUNWOBJS) + +include ../../../Makefile.lib + +LIBNAME= $(LIBRARY:%.a=%) +LIBS= $(DYNLIB) +LDLIBS += -lresolv -lnsl -lsocket -lc + +MAPDIR = ../spec/$(TRANSMACH) +SPECMAPFILE = $(MAPDIR)/mapfile +SRCDIR= ../../common/irs +SRCS= $(IRSDYNOBJS:%.$(SRCDIR)/%.c) \ + $(SUNWOBJS:%.o=../../common/sunw/%.c) + +ROOTLIBDIR= $(ROOT)/usr/lib/dns +ROOTLIBDIR64= $(ROOT)/usr/lib/dns/$(MACH64) + +# Local Libresolv definitions +SOLCOMPAT = -Dgethostbyname=res_gethostbyname \ + -Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \ + -Dgethostbyname2=res_gethostbyname2\ + -Dgetnetbyaddr=res_getnetbyaddr -Dsethostent=res_sethostent \ + -Dendhostent=res_endhostent -Dgethostent=res_gethostent \ + -Dsetnetent=res_setnetent -Dendnetent=res_endnetent \ + -Dgetnetent=res_getnetent -Dsocket=_socket + +CRYPTINCL= -I../../common/cylink -I../../common/dnssafe +CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE + +CPPFLAGS += $(CRYPTFLAGS) $(CRYPTINCL) +CPPFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \ + -D__SUNW_IRS_INIT_NODEFINE $(SOLCOMPAT) -I../../include + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +$(ROOTLIBDIR) $(ROOTLIBDIR64): + $(INS.dir) + +include ../../../Makefile.targ + +pics/%.o: ../../common/sunw/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) diff --git a/usr/src/lib/libresolv2/irs/amd64/Makefile b/usr/src/lib/libresolv2/irs/amd64/Makefile new file mode 100644 index 0000000000..2b37434e6b --- /dev/null +++ b/usr/src/lib/libresolv2/irs/amd64/Makefile @@ -0,0 +1,15 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +MAPDIR= ../spec/amd64 + +include ../Makefile.com +include ../../../Makefile.lib.64 + +all: $(LIBS) + +install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64) diff --git a/usr/src/lib/libresolv2/irs/i386/Makefile b/usr/src/lib/libresolv2/irs/i386/Makefile new file mode 100644 index 0000000000..009d72b5eb --- /dev/null +++ b/usr/src/lib/libresolv2/irs/i386/Makefile @@ -0,0 +1,12 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/irs/i386/Makefile +# + +include ../Makefile.com + +install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS) diff --git a/usr/src/lib/libresolv2/irs/sparc/Makefile b/usr/src/lib/libresolv2/irs/sparc/Makefile new file mode 100644 index 0000000000..8dd442702e --- /dev/null +++ b/usr/src/lib/libresolv2/irs/sparc/Makefile @@ -0,0 +1,12 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/irs/sparc/Makefile +# + +include ../Makefile.com + +install: all $(ROOTLIBDIR) .WAIT $(ROOTLIBS) diff --git a/usr/src/lib/libresolv2/irs/sparcv9/Makefile b/usr/src/lib/libresolv2/irs/sparcv9/Makefile new file mode 100644 index 0000000000..51ec6b8a9d --- /dev/null +++ b/usr/src/lib/libresolv2/irs/sparcv9/Makefile @@ -0,0 +1,13 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/irs/sparcv9/Makefile +# + +include ../Makefile.com +include ../../../Makefile.lib.64 + +install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64) diff --git a/usr/src/lib/libresolv2/irs/spec/Makefile b/usr/src/lib/libresolv2/irs/spec/Makefile new file mode 100644 index 0000000000..1928a002a5 --- /dev/null +++ b/usr/src/lib/libresolv2/irs/spec/Makefile @@ -0,0 +1,8 @@ +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/irs/spec/Makefile + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/lib/libresolv2/irs/spec/Makefile.targ b/usr/src/lib/libresolv2/irs/spec/Makefile.targ new file mode 100644 index 0000000000..fe57106695 --- /dev/null +++ b/usr/src/lib/libresolv2/irs/spec/Makefile.targ @@ -0,0 +1,12 @@ +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/irs/spec/Makefile.targ + +LIBRARY = irs.a +VERS = .1 + +OBJECTS = irs.o + diff --git a/usr/src/lib/libresolv2/irs/spec/amd64/Makefile b/usr/src/lib/libresolv2/irs/spec/amd64/Makefile new file mode 100644 index 0000000000..84ccf3ca89 --- /dev/null +++ b/usr/src/lib/libresolv2/irs/spec/amd64/Makefile @@ -0,0 +1,26 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#amd64_C_PICFLAGS = $(amd64_C_BIGPICFLAGS) + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libresolv2/irs/spec/i386/Makefile b/usr/src/lib/libresolv2/irs/spec/i386/Makefile new file mode 100644 index 0000000000..b399d8191c --- /dev/null +++ b/usr/src/lib/libresolv2/irs/spec/i386/Makefile @@ -0,0 +1,26 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/irs/spec/i386/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libresolv2/irs/spec/irs.spec b/usr/src/lib/libresolv2/irs/spec/irs.spec new file mode 100644 index 0000000000..9b08d54093 --- /dev/null +++ b/usr/src/lib/libresolv2/irs/spec/irs.spec @@ -0,0 +1,15 @@ +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/irs/spec/irs.spec + +function __irs_nis_acc +version SUNWprivate_1.1 +end + +function __irs_irp_acc +version SUNWprivate_1.1 +end diff --git a/usr/src/lib/libresolv2/irs/spec/sparc/Makefile b/usr/src/lib/libresolv2/irs/spec/sparc/Makefile new file mode 100644 index 0000000000..0440fdd8c6 --- /dev/null +++ b/usr/src/lib/libresolv2/irs/spec/sparc/Makefile @@ -0,0 +1,26 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/irs/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libresolv2/irs/spec/sparcv9/Makefile b/usr/src/lib/libresolv2/irs/spec/sparcv9/Makefile new file mode 100644 index 0000000000..63a2917247 --- /dev/null +++ b/usr/src/lib/libresolv2/irs/spec/sparcv9/Makefile @@ -0,0 +1,27 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/irs/spec/sparcv9/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#sparcv9_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +# No public interface, so don't install spec libraries in the proto area +INS.abilib= + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libresolv2/irs/spec/versions b/usr/src/lib/libresolv2/irs/spec/versions new file mode 100644 index 0000000000..6a318d48a3 --- /dev/null +++ b/usr/src/lib/libresolv2/irs/spec/versions @@ -0,0 +1,19 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +sparc { + SUNWprivate_1.1; +} +sparcv9 { + SUNWprivate_1.1; +} +i386 { + SUNWprivate_1.1; +} +amd64 { + SUNWprivate_1.1; +} diff --git a/usr/src/lib/libresolv2/req.flg b/usr/src/lib/libresolv2/req.flg new file mode 100644 index 0000000000..9ca59f35c3 --- /dev/null +++ b/usr/src/lib/libresolv2/req.flg @@ -0,0 +1,9 @@ +#!/bin/sh +# +# Copyright 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +echo_file usr/src/lib/libnsl/include/nsl_stdio_prv.h diff --git a/usr/src/lib/libresolv2/sparc/Makefile b/usr/src/lib/libresolv2/sparc/Makefile new file mode 100644 index 0000000000..490d924db5 --- /dev/null +++ b/usr/src/lib/libresolv2/sparc/Makefile @@ -0,0 +1,17 @@ +# +# Copyright (c) 1997-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/sparc/Makefile + +MAPDIR= ../spec/sparc + +include ../Makefile.com + +.KEEP_STATE: + +all: $(LIBS) + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libresolv2/sparcv9/Makefile b/usr/src/lib/libresolv2/sparcv9/Makefile new file mode 100644 index 0000000000..72aa5e4563 --- /dev/null +++ b/usr/src/lib/libresolv2/sparcv9/Makefile @@ -0,0 +1,27 @@ +# +# Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/sparcv9/Makefile + +MAPDIR= ../spec/sparcv9 + +include ../Makefile.com +include ../../Makefile.lib.64 + +# With the adition of BIND 8.3.3, the symbol table for 64 bit went over +# the limit for Kpic, so we've added -KPIC here, for just the 64 bit +# library. This avoids compiling the 32-bit library with PIC unnecessarily. + +sparcv9_C_PICFLAGS = -K PIC +sparcv9_CC_PICFLAGS = -KPIC + +LIBS = $(DYNLIB) $(LINTLIB) + +.KEEP_STATE: + +all: $(LIBS) + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libresolv2/spec/Makefile b/usr/src/lib/libresolv2/spec/Makefile new file mode 100644 index 0000000000..bc844c2654 --- /dev/null +++ b/usr/src/lib/libresolv2/spec/Makefile @@ -0,0 +1,8 @@ +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/spec/Makefile + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/lib/libresolv2/spec/Makefile.targ b/usr/src/lib/libresolv2/spec/Makefile.targ new file mode 100644 index 0000000000..16385fb51f --- /dev/null +++ b/usr/src/lib/libresolv2/spec/Makefile.targ @@ -0,0 +1,12 @@ +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/spec/Makefile.targ + +LIBRARY = libresolv.a +VERS = .2 + +OBJECTS = resolv2.o + diff --git a/usr/src/lib/libresolv2/spec/amd64/Makefile b/usr/src/lib/libresolv2/spec/amd64/Makefile new file mode 100644 index 0000000000..96bda57a49 --- /dev/null +++ b/usr/src/lib/libresolv2/spec/amd64/Makefile @@ -0,0 +1,23 @@ +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#amd64_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libresolv2/spec/i386/Makefile b/usr/src/lib/libresolv2/spec/i386/Makefile new file mode 100644 index 0000000000..9d0faf35d0 --- /dev/null +++ b/usr/src/lib/libresolv2/spec/i386/Makefile @@ -0,0 +1,23 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/spec/i386/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#i386_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libresolv2/spec/resolv2.spec b/usr/src/lib/libresolv2/spec/resolv2.spec new file mode 100644 index 0000000000..ef489c41ff --- /dev/null +++ b/usr/src/lib/libresolv2/spec/resolv2.spec @@ -0,0 +1,1096 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# lib/libresolv2/spec/resolv2.spec + +function b64_ntop +version SUNWprivate_2.1 +end + +function __b64_ntop +version SUNWprivate_2.1 +end + +function b64_pton +version SUNWprivate_2.1 +end + +function __b64_pton +version SUNWprivate_2.1 +end + +function dn_count_labels +version SUNWprivate_2.1 +end + +function __dn_count_labels +version SUNWprivate_2.1 +end + +function dn_skipname +version SUNWprivate_2.1 +end + +function __dn_skipname +version SUNW_2.1 +end + +function __evAddTime +version SUNWprivate_2.1 +end + +function __evCancelConn +version SUNWprivate_2.1 +end + +function __evCancelRW +version SUNWprivate_2.1 +end + +function __evClearTimer +version SUNWprivate_2.1 +end + +function __evConnect +version SUNWprivate_2.1 +end + +function __evConsIovec +version SUNWprivate_2.1 +end + +function __evConsTime +version SUNWprivate_2.1 +end + +function __evCreate +version SUNWprivate_2.1 +end + +function __evDeselectFD +version SUNWprivate_2.1 +end + +function __evDispatch +version SUNWprivate_2.1 +end + +function __evDo +version SUNWprivate_2.1 +end + +function __evGetNext +version SUNWprivate_2.1 +end + +function __evListen +version SUNWprivate_2.1 +end + +function __evNowTime +version SUNWprivate_2.1 +end + +function __evRead +version SUNWprivate_2.1 +end + +function __evResetTimer +version SUNWprivate_2.1 +end + +function __evSelectFD +version SUNWprivate_2.1 +end + +function __evSetDebug +version SUNWprivate_2.1 +end + +function __evSetTimer +version SUNWprivate_2.1 +end + +function __evWaitFor +version SUNWprivate_2.1 +end + +function fp_nquery +version SUNWprivate_2.1 +end + +function __fp_nquery +version SUNWprivate_2.1 +end + +function fp_query +version SUNWprivate_2.1 +end + +function __fp_query +version SUNW_2.1 +end + +function fp_resstat +version SUNW_2.2 +end + +function __fp_resstat +version SUNWprivate_2.1 +end + +function __hostalias +version SUNW_2.1 +end + +function res_hostalias +version SUNW_2.2 +end + +function hostalias +version SUNWprivate_2.1 +end + +function loc_aton +version SUNWprivate_2.1 +end + +function __loc_aton +version SUNWprivate_2.1 +end + +function loc_ntoa +version SUNWprivate_2.1 +end + +function __loc_ntoa +version SUNWprivate_2.1 +end + +function __log_add_channel +version SUNWprivate_2.1 +end + +function __log_category_is_active +version SUNWprivate_2.1 +end + +function __log_close_stream +version SUNWprivate_2.1 +end + +function __log_free_context +version SUNWprivate_2.1 +end + +function __log_get_stream +version SUNWprivate_2.1 +end + +function __log_inc_references +version SUNWprivate_2.1 +end + +function __log_new_context +version SUNWprivate_2.1 +end + +function __log_new_file_channel +version SUNWprivate_2.1 +end + +function __log_new_null_channel +version SUNWprivate_2.1 +end + +function __log_set_file_owner +version SUNWprivate_2.1 +end + +function __log_new_syslog_channel +version SUNWprivate_2.1 +end + +function __log_open_stream +version SUNWprivate_2.1 +end + +function __log_option +version SUNWprivate_2.1 +end + +function __log_vwrite +version SUNWprivate_2.1 +end + +function __log_write +version SUNWprivate_2.1 +end + +function __ns_get16 +version SUNWprivate_2.1 +end + +function __ns_get32 +version SUNWprivate_2.1 +end + +function __ns_initparse +version SUNWprivate_2.1 +end + +function __ns_name_ntop +version SUNWprivate_2.1 +end + +function __ns_name_pton +version SUNWprivate_2.1 +end + +function __ns_name_rollback +version SUNWprivate_2.1 +end + +function __ns_name_unpack +version SUNWprivate_2.1 +end + +function __ns_parse_ttl +version SUNWprivate_2.1 +end + +function __ns_parserr +version SUNWprivate_2.1 +end + +function __ns_put16 +version SUNWprivate_2.1 +end + +function __ns_sprintrr +version SUNWprivate_2.1 +end + +function __ns_sprintrrf +version SUNWprivate_2.1 +end + +function p_cdname +version SUNWprivate_2.1 +end + +function __p_cdname +version SUNW_2.1 +end + +function p_class +version SUNWprivate_2.1 +end + +function __p_class +version SUNW_2.1 +end + +function __p_class_syms +version SUNWprivate_2.1 +end + +function __p_query +version SUNW_2.1 +end + +function p_secstodate +version SUNWprivate_2.1 +end + +function __p_secstodate +version SUNWprivate_2.1 +end + +function p_section +version SUNWprivate_2.1 +end + +function __p_section +version SUNWprivate_2.1 +end + +function p_time +version SUNWprivate_2.1 +end + +function __p_time +version SUNW_2.1 +end + +function p_type +version SUNWprivate_2.1 +end + +function __p_type +version SUNW_2.1 +end + +function __p_type_syms +version SUNWprivate_2.1 +end + +function p_fqnname +version SUNWprivate_2.1 +end + +function putlong +version SUNWprivate_2.1 +end + +function __putlong +version SUNW_2.1 +end + +function putshort +version SUNWprivate_2.1 +end + +function __putshort +version SUNWprivate_2.1 +end + +function res_dnok +version SUNWprivate_2.1 +end + +function __res_dnok +version SUNWprivate_2.1 +end + +function res_hnok +version SUNWprivate_2.1 +end + +function __res_hnok +version SUNWprivate_2.1 +end + +function res_mailok +version SUNWprivate_2.1 +end + +function __res_mailok +version SUNWprivate_2.1 +end + +function res_nameinquery +version SUNWprivate_2.1 +end + +function __res_nameinquery +version SUNWprivate_2.1 +end + +function res_ownok +version SUNWprivate_2.1 +end + +function __res_ownok +version SUNWprivate_2.1 +end + +function res_randomid +version SUNWprivate_2.1 +end + +function __res_randomid +version SUNWprivate_2.1 +end + +function sym_ntop +version SUNWprivate_2.1 +end + +function __sym_ntop +version SUNWprivate_2.1 +end + +function sym_ntos +version SUNWprivate_2.1 +end + +function __sym_ntos +version SUNWprivate_2.1 +end + +function sym_ston +version SUNWprivate_2.1 +end + +function __sym_ston +version SUNWprivate_2.1 +end + +function _getlong +version SUNW_2.1 +end + +function _getshort +version SUNW_2.1 +end + +function _ns_flagdata +version SUNWprivate_2.1 +end + +function _res +version SUNW_2.1 +end + +function _res_opcodes +version SUNWprivate_2.1 +end + +function daemon +version SUNWprivate_2.1 +end + +function dn_comp +include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h> +declaration int dn_comp(const char *exp_dn, uchar_t *comp_dn, int length, \ + uchar_t **dnptrs, uchar_t **lastdnptr) +version SUNW_2.1 +exception $return == -1 +end + +function dn_expand +include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h> +declaration int dn_expand(const uchar_t *msg, const uchar_t *eomorig, \ + const uchar_t *comp_dn, char *exp_dn, int length) +version SUNW_2.1 +exception $return == -1 +end + +function h_errlist +version SUNWprivate_2.1 +end + +# h_errno moved to explicit mapfile definition to provide correct type and size. + +function herror +version SUNW_2.2 +end + +function hstrerror +version SUNW_2.1 +end + +function inet_aton +version SUNW_2.3 +filter libnsl.so.1 +end + +function inet_nsap_addr +version SUNWprivate_2.1 +end + +function inet_nsap_ntoa +version SUNWprivate_2.1 +end + +function res_endhostent +version SUNWprivate_2.1 +end + +function res_gethostbyaddr +version SUNWprivate_2.1 +end + +function res_gethostbyname +version SUNWprivate_2.1 +end + +function res_gethostbyname2 +version SUNWprivate_2.2 +end + +function res_gethostent +version SUNWprivate_2.1 +end + +function res_getipnodebyname +version SUNWprivate_2.1 +end + +function res_getipnodebyaddr +version SUNWprivate_2.1 +end + +function res_freehostent +version SUNWprivate_2.1 +end + +function res_init +include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h> +declaration int res_init(void) +version SUNW_2.1 +end + +function res_mkquery +include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h> +declaration int res_mkquery(int op, const char *dname, int class, \ + int type, const uchar_t *data, int datalen, \ + const uchar_t *newrr, uchar_t *buf, int buflen) +version SUNW_2.1 +exception $return == -1 +end + +function res_mkupdrec +version SUNWprivate_2.1 +end + +function res_queriesmatch +version SUNWprivate_2.1 +end + +function __res_queriesmatch +version SUNWprivate_2.1 +end + +function res_query +include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h> +declaration int res_query(const char *dname, int class, int type, \ + uchar_t *answer, int anslen) +version SUNW_2.1 +end + +function res_querydomain +version SUNW_2.1 +end + +function res_search +include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h> +declaration int res_search(const char *dname, int class, int type, \ + uchar_t *answer, int anslen) +version SUNW_2.1 +end + +function res_send +include <sys/types.h>, <netinet/in.h>, <arpa/nameser.h>, <resolv.h> +declaration int res_send(const uchar_t *msg, int msglen, uchar_t *answer, \ + int anslen) +version SUNW_2.1 +exception $return == -1 +end + +function res_sethostent +version SUNWprivate_2.1 +end + +function res_update +version SUNW_2.1 +end + +function res_close +version SUNWprivate_2.1 +end + +function tree_add +version SUNWprivate_2.1 +end + +function tree_init +version SUNWprivate_2.1 +end + +function tree_srch +version SUNWprivate_2.1 +end + +function tree_trav +version SUNWprivate_2.1 +end + +function __assertion_failed +version SUNWprivate_2.1 +end + +function __evDestroy +version SUNWprivate_2.1 +end + +function __evUnwait +version SUNWprivate_2.1 +end + +function __log_free_channel +version SUNWprivate_2.1 +end + +function __log_get_channel_type +version SUNWprivate_2.1 +end + +function __memget +version SUNWprivate_2.1 +end + +function __memput +version SUNWprivate_2.1 +end + +function __memstats +version SUNWprivate_2.1 +end + +function __res_disable_mt +version SUNWprivate_2.1 +end + +function __res_enable_mt +version SUNWprivate_2.1 +end + +function __res_get_res +version SUNWprivate_2.1 +end + +function __res_get_h_errno +version SUNWprivate_2.1 +end + +function __res_set_no_hosts_fallback +version SUNWprivate_2.1 +end + +function __res_unset_no_hosts_fallback +version SUNWprivate_2.1 +end + +function __res_override_retry +version SUNWprivate_2.1 +end + +function assertion_type_to_text +version SUNWprivate_2.1 +end + +function set_assertion_failure_callback +version SUNWprivate_2.1 +end + +function tree_mung +version SUNWprivate_2.1 +end + +function res_ninit +version SUNW_2.2 +end + +function res_nquery +version SUNW_2.2 +end + +function p_query +version SUNWprivate_2.1 +end + +function res_nsearch +version SUNW_2.2 +end + +function res_nquerydomain +version SUNW_2.2 +end + +function res_nmkquery +version SUNW_2.2 +end + +function res_nsend +version SUNW_2.2 +end + +function res_nsendsigned +version SUNW_2.2 +end + +function res_findzonecut +version SUNWprivate_2.1 +end + +function __ISC_res_nupdate +version SUNWprivate_2.1 +end + +function __ISC_res_nmkupdate +version SUNWprivate_2.1 +end + +function res_nclose +version SUNW_2.2 +end + +function res_nsendsigned +version SUNW_2.2 +end + +function res_nisourserver +version SUNWprivate_2.1 +end + +function res_isourserver +version SUNWprivate_2.1 +end + +function res_mkupdate +version SUNWprivate_2.1 +end + +function res_sendsigned +version SUNWprivate_2.1 +end + +function p_rcode +version SUNWprivate_2.1 +end + +function __res_state +version SUNWprivate_2.1 +end + +function res_freeupdrec +version SUNWprivate_2.1 +end + +function dst_init +version SUNWprivate_2.1 +end + +function dst_check_algorithm +version SUNWprivate_2.1 +end + +function dst_generate_key +version SUNWprivate_2.1 +end + +function dst_write_key +version SUNWprivate_2.1 +end + +function res_pquery +version SUNWprivate_2.1 +end + +function __h_errno +version SUNWprivate_2.1 +end + +function __ctl_command +version SUNWprivate_2.1 +end + +function __ctl_endclient +version SUNWprivate_2.1 +end + +function __ctl_client +version SUNWprivate_2.1 +end + +function __ctl_getcsctx +version SUNWprivate_2.1 +end + +function __log_check +version SUNWprivate_2.1 +end + +function __ctl_response +version SUNWprivate_2.1 +end + +function __p_cert_syms +version SUNWprivate_2.1 +end + +function __ns_name_ntol +version SUNWprivate_2.1 +end + +function dst_buffer_to_key +version SUNWprivate_2.1 +end + +function __ctl_setcsctx +version SUNWprivate_2.1 +end + +function __ctl_server +version SUNWprivate_2.1 +end + +function __evHighestFD +version SUNWprivate_2.1 +end + +function dst_verify_data +version SUNWprivate_2.1 +end + +function __ctl_sendhelp +version SUNWprivate_2.1 +end + +function __ns_skiprr +version SUNWprivate_2.1 +end + +function __ns_verify +version SUNWprivate_2.1 +end + +function __p_key_syms +version SUNWprivate_2.1 +end + +function __evTimeVal +version SUNWprivate_2.1 +end + +function __ns_datetosecs +version SUNWprivate_2.1 +end + +function dst_key_to_buffer +version SUNWprivate_2.1 +end + +function dst_free_key +version SUNWprivate_2.1 +end + +function __ctl_endserver +version SUNWprivate_2.1 +end + +function dst_dnskey_to_key +version SUNWprivate_2.1 +end + +function __ns_find_tsig +version SUNWprivate_2.1 +end + +function __ns_verify_tcp +version SUNWprivate_2.1 +end + +function __ns_verify_tcp_init +version SUNWprivate_2.1 +end + +function key_file_fmt_str +version SUNWprivate_2.1 +end + +function dst_s_id_calc +version SUNWprivate_2.1 +end + +function dst_s_conv_bignum_u8_to_b64 +version SUNWprivate_2.1 +end + +function dst_random +version SUNWprivate_2.1 +end + + +function dst_s_verify_str +version SUNWprivate_2.1 +end + +function dst_t_func +version SUNWprivate_2.1 +end + +function dst_s_conv_bignum_b64_to_u8 +version SUNWprivate_2.1 +end + +function dst_s_get_int16 +version SUNWprivate_2.1 +end + +function dst_s_calculate_bits +version SUNWprivate_2.1 +end + +function dst_s_put_int16 +version SUNWprivate_2.1 +end + +function inet_net_pton +version SUNWprivate_2.1 +end + +function inet_net_ntop +version SUNWprivate_2.1 +end + +function net_data_minimize +version SUNWprivate_2.1 +end + +function __h_errno_set +version SUNWprivate_2.1 +end + +function __net_data_init +version SUNWprivate_2.1 +end + +# BIND 8.2 adds the various ns_sign*() functions for TSIG. Until the +# interface has seen some actual use and has stabilized, we'll leave +# those functions undocumented and in the private interface. + +function __ns_sign +version SUNWprivate_2.1 +end + +function __ns_sign2 +version SUNWprivate_2.1 +end + +function __ns_sign_tcp +version SUNWprivate_2.1 +end + +function __ns_sign_tcp2 +version SUNWprivate_2.1 +end + +function __ns_sign_tcp_init +version SUNWprivate_2.1 +end + +function __ns_verify +version SUNWprivate_2.1 +end + +function __ns_verify_tcp +version SUNWprivate_2.1 +end + +function __ns_verify_tcp_init +version SUNWprivate_2.1 +end + +function __ns_find_tsig +version SUNWprivate_2.1 +end + +function __ISC_res_freeupdrec +version SUNWprivate_2.1 +end + +function __ISC_res_mkupdrec +version SUNWprivate_2.1 +end + +function __ISC_res_update +version SUNWprivate_2.1 +end + +function __ISC_res_mkupdate +version SUNWprivate_2.1 +end + +function irs_destroy +version SUNWprivate_2.1 +end + +function __ns_samedomain +version SUNWprivate_2.1 +end + +function __ns_samename +version SUNWprivate_2.1 +end + +function __ns_makecanon +version SUNWprivate_2.1 +end + +function __ns_msg_getflag +version SUNWprivate_2.1 +end + +function __memget_record +version SUNWprivate_2.1 +end + +function __memput_record +version SUNWprivate_2.1 +end + +function dst_read_key +version SUNWprivate_2.1 +end + +function dst_sign_data +version SUNWprivate_2.1 +end + +function dst_s_dns_key_id +version SUNWprivate_2.1 +end + +function __ns_format_ttl +version SUNWprivate_2.1 +end + +function __areweinnamed +version SUNWprivate_2.1 +end + +function __log_close_debug_channels +version SUNWprivate_2.2 +end + +function res_getservers +version SUNWprivate_2.2 +end + +function res_setservers +version SUNWprivate_2.2 +end + +function res_nametotype +version SUNWprivate_2.2 +end + +function res_nametoclass +version SUNWprivate_2.2 +end + +function res_nopt +version SUNWprivate_2.2 +end + +function isc_puthexstring +version SUNWprivate_2.2 +end + +function isc_gethexstring +version SUNWprivate_2.2 +end + +function __memactive +version SUNWprivate_2.2 +end + +function p_sockun +version SUNWprivate_2.2 +end diff --git a/usr/src/lib/libresolv2/spec/sparc/Makefile b/usr/src/lib/libresolv2/spec/sparc/Makefile new file mode 100644 index 0000000000..ee76178462 --- /dev/null +++ b/usr/src/lib/libresolv2/spec/sparc/Makefile @@ -0,0 +1,23 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib + +# Uncomment the following if the linker complains +#sparc_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libresolv2/spec/sparcv9/Makefile b/usr/src/lib/libresolv2/spec/sparcv9/Makefile new file mode 100644 index 0000000000..a6ebe9c847 --- /dev/null +++ b/usr/src/lib/libresolv2/spec/sparcv9/Makefile @@ -0,0 +1,24 @@ +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 1998-1999 by Sun Microsystems, Inc. +# All rights reserved. +# +# lib/libresolv2/spec/sparcv9/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +# Add arch specific objects here +OBJECTS += + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +# Uncomment the following if the linker complains +#sparcv9_C_PICFLAGS = -K PIC + +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libresolv2/spec/versions b/usr/src/lib/libresolv2/spec/versions new file mode 100644 index 0000000000..90e69aa7fb --- /dev/null +++ b/usr/src/lib/libresolv2/spec/versions @@ -0,0 +1,35 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +sparc { + SUNW_2.3: {SUNW_2.2}; + SUNW_2.2: {SUNW_2.1}; + SUNW_2.1; + SUNWprivate_2.2: {SUNWprivate_2.1}; + SUNWprivate_2.1; +} +sparcv9 { + SUNW_2.3: {SUNW_2.2}; + SUNW_2.2: {SUNW_2.1}; + SUNW_2.1; + SUNWprivate_2.2: {SUNWprivate_2.1}; + SUNWprivate_2.1; +} +i386 { + SUNW_2.3: {SUNW_2.2}; + SUNW_2.2: {SUNW_2.1}; + SUNW_2.1; + SUNWprivate_2.2: {SUNWprivate_2.1}; + SUNWprivate_2.1; +} +amd64 { + SUNW_2.3: {SUNW_2.2}; + SUNW_2.2: {SUNW_2.1}; + SUNW_2.1; + SUNWprivate_2.2: {SUNWprivate_2.1}; + SUNWprivate_2.1; +} |