diff options
Diffstat (limited to 'crypto/openssh/openbsd-compat')
81 files changed, 15100 insertions, 0 deletions
diff --git a/crypto/openssh/openbsd-compat/Makefile.in b/crypto/openssh/openbsd-compat/Makefile.in new file mode 100644 index 0000000..9f06605 --- /dev/null +++ b/crypto/openssh/openbsd-compat/Makefile.in @@ -0,0 +1,42 @@ +# $Id: Makefile.in,v 1.40 2006/08/30 17:24:41 djm Exp $ + +sysconfdir=@sysconfdir@ +piddir=@piddir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ + +VPATH=@srcdir@ +CC=@CC@ +LD=@LD@ +CFLAGS=@CFLAGS@ +CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ +LIBS=@LIBS@ +AR=@AR@ +RANLIB=@RANLIB@ +INSTALL=@INSTALL@ +LDFLAGS=-L. @LDFLAGS@ + +OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o + +COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-snprintf.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o + +PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o + +.c.o: + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< + +all: libopenbsd-compat.a + +$(COMPAT): ../config.h +$(OPENBSD): ../config.h +$(PORTS): ../config.h + +libopenbsd-compat.a: $(COMPAT) $(OPENBSD) $(PORTS) + $(AR) rv $@ $(COMPAT) $(OPENBSD) $(PORTS) + $(RANLIB) $@ + +clean: + rm -f *.o *.a core + +distclean: clean + rm -f Makefile *~ diff --git a/crypto/openssh/openbsd-compat/base64.c b/crypto/openssh/openbsd-compat/base64.c new file mode 100644 index 0000000..9a60f58 --- /dev/null +++ b/crypto/openssh/openbsd-compat/base64.c @@ -0,0 +1,325 @@ +/* $OpenBSD: base64.c,v 1.4 2002/01/02 23:00:10 deraadt Exp $ */ + +/* + * 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. + */ + +/* + * 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/base64.c */ + +#include "includes.h" + +#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <stdio.h> + +#include <stdlib.h> +#include <string.h> + +#include "base64.h" + +/* XXX abort illegal in library */ +#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. + */ + +#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) +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]; + u_int 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); +} +#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ + +#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) + +/* 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(char const *src, u_char *target, size_t targsize) +{ + u_int tarindex, state; + int 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 (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (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 (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 (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + } + } + + /* + * 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 (; 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 (; 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); +} + +#endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */ +#endif diff --git a/crypto/openssh/openbsd-compat/base64.h b/crypto/openssh/openbsd-compat/base64.h new file mode 100644 index 0000000..732c6b3 --- /dev/null +++ b/crypto/openssh/openbsd-compat/base64.h @@ -0,0 +1,65 @@ +/* $Id: base64.h,v 1.6 2003/08/29 16:59:52 mouring Exp $ */ + +/* + * 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. + */ + +/* + * 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. + */ + +#ifndef _BSD_BASE64_H +#define _BSD_BASE64_H + +#include "includes.h" + +#ifndef HAVE___B64_NTOP +# ifndef HAVE_B64_NTOP +int b64_ntop(u_char const *src, size_t srclength, char *target, + size_t targsize); +# endif /* !HAVE_B64_NTOP */ +# define __b64_ntop(a,b,c,d) b64_ntop(a,b,c,d) +#endif /* HAVE___B64_NTOP */ + +#ifndef HAVE___B64_PTON +# ifndef HAVE_B64_PTON +int b64_pton(char const *src, u_char *target, size_t targsize); +# endif /* !HAVE_B64_PTON */ +# define __b64_pton(a,b,c) b64_pton(a,b,c) +#endif /* HAVE___B64_PTON */ + +#endif /* _BSD_BASE64_H */ diff --git a/crypto/openssh/openbsd-compat/basename.c b/crypto/openssh/openbsd-compat/basename.c new file mode 100644 index 0000000..ffa5c89 --- /dev/null +++ b/crypto/openssh/openbsd-compat/basename.c @@ -0,0 +1,67 @@ +/* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */ + +/* + * Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/basename.c */ + +#include "includes.h" +#ifndef HAVE_BASENAME +#include <errno.h> +#include <string.h> + +char * +basename(const char *path) +{ + static char bname[MAXPATHLEN]; + size_t len; + const char *endp, *startp; + + /* Empty or NULL string gets treated as "." */ + if (path == NULL || *path == '\0') { + bname[0] = '.'; + bname[1] = '\0'; + return (bname); + } + + /* Strip any trailing slashes */ + endp = path + strlen(path) - 1; + while (endp > path && *endp == '/') + endp--; + + /* All slashes becomes "/" */ + if (endp == path && *endp == '/') { + bname[0] = '/'; + bname[1] = '\0'; + return (bname); + } + + /* Find the start of the base */ + startp = endp; + while (startp > path && *(startp - 1) != '/') + startp--; + + len = endp - startp + 1; + if (len >= sizeof(bname)) { + errno = ENAMETOOLONG; + return (NULL); + } + memcpy(bname, startp, len); + bname[len] = '\0'; + return (bname); +} + +#endif /* !defined(HAVE_BASENAME) */ diff --git a/crypto/openssh/openbsd-compat/bindresvport.c b/crypto/openssh/openbsd-compat/bindresvport.c new file mode 100644 index 0000000..65afed1 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bindresvport.c @@ -0,0 +1,118 @@ +/* This file has be substantially modified from the original OpenBSD source */ + +/* $OpenBSD: bindresvport.c,v 1.16 2005/04/01 07:44:03 otto Exp $ */ + +/* + * Copyright 1996, Jason Downs. All rights reserved. + * Copyright 1998, Theo de Raadt. All rights reserved. + * Copyright 2000, Damien Miller. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/rpc/bindresvport.c */ + +#include "includes.h" + +#ifndef HAVE_BINDRESVPORT_SA +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <string.h> + +#define STARTPORT 600 +#define ENDPORT (IPPORT_RESERVED - 1) +#define NPORTS (ENDPORT - STARTPORT + 1) + +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport_sa(int sd, struct sockaddr *sa) +{ + int error, af; + struct sockaddr_storage myaddr; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + u_int16_t *portp; + u_int16_t port; + socklen_t salen; + int i; + + if (sa == NULL) { + memset(&myaddr, 0, sizeof(myaddr)); + sa = (struct sockaddr *)&myaddr; + + if (getsockname(sd, sa, &salen) == -1) + return -1; /* errno is correctly set */ + + af = sa->sa_family; + memset(&myaddr, 0, salen); + } else + af = sa->sa_family; + + if (af == AF_INET) { + sin = (struct sockaddr_in *)sa; + salen = sizeof(struct sockaddr_in); + portp = &sin->sin_port; + } else if (af == AF_INET6) { + sin6 = (struct sockaddr_in6 *)sa; + salen = sizeof(struct sockaddr_in6); + portp = &sin6->sin6_port; + } else { + errno = EPFNOSUPPORT; + return (-1); + } + sa->sa_family = af; + + port = ntohs(*portp); + if (port == 0) + port = (arc4random() % NPORTS) + STARTPORT; + + /* Avoid warning */ + error = -1; + + for(i = 0; i < NPORTS; i++) { + *portp = htons(port); + + error = bind(sd, sa, salen); + + /* Terminate on success */ + if (error == 0) + break; + + /* Terminate on errors, except "address already in use" */ + if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL))) + break; + + port++; + if (port > ENDPORT) + port = STARTPORT; + } + + return (error); +} + +#endif /* HAVE_BINDRESVPORT_SA */ diff --git a/crypto/openssh/openbsd-compat/bsd-arc4random.c b/crypto/openssh/openbsd-compat/bsd-arc4random.c new file mode 100644 index 0000000..d45fb18 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-arc4random.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1999,2000,2004 Damien Miller <djm@mindrot.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include "includes.h" + +#include <sys/types.h> + +#include <string.h> +#include <stdarg.h> + +#include "log.h" + +#ifndef HAVE_ARC4RANDOM + +#include <openssl/rand.h> +#include <openssl/rc4.h> +#include <openssl/err.h> + +/* Size of key to use */ +#define SEED_SIZE 20 + +/* Number of bytes to reseed after */ +#define REKEY_BYTES (1 << 24) + +static int rc4_ready = 0; +static RC4_KEY rc4; + +unsigned int +arc4random(void) +{ + unsigned int r = 0; + static int first_time = 1; + + if (rc4_ready <= 0) { + if (first_time) + seed_rng(); + first_time = 0; + arc4random_stir(); + } + + RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r); + + rc4_ready -= sizeof(r); + + return(r); +} + +void +arc4random_stir(void) +{ + unsigned char rand_buf[SEED_SIZE]; + int i; + + memset(&rc4, 0, sizeof(rc4)); + if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) + fatal("Couldn't obtain random bytes (error %ld)", + ERR_get_error()); + RC4_set_key(&rc4, sizeof(rand_buf), rand_buf); + + /* + * Discard early keystream, as per recommendations in: + * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps + */ + for(i = 0; i <= 256; i += sizeof(rand_buf)) + RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf); + + memset(rand_buf, 0, sizeof(rand_buf)); + + rc4_ready = REKEY_BYTES; +} +#endif /* !HAVE_ARC4RANDOM */ diff --git a/crypto/openssh/openbsd-compat/bsd-asprintf.c b/crypto/openssh/openbsd-compat/bsd-asprintf.c new file mode 100644 index 0000000..6748013 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-asprintf.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2004 Darren Tucker. + * + * Based originally on asprintf.c from OpenBSD: + * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include "includes.h" + +#ifndef HAVE_VASPRINTF + +#include <errno.h> +#include <stdarg.h> +#include <stdlib.h> + +#ifndef VA_COPY +# ifdef HAVE_VA_COPY +# define VA_COPY(dest, src) va_copy(dest, src) +# else +# ifdef HAVE___VA_COPY +# define VA_COPY(dest, src) __va_copy(dest, src) +# else +# define VA_COPY(dest, src) (dest) = (src) +# endif +# endif +#endif + +#define INIT_SZ 128 + +int vasprintf(char **str, const char *fmt, va_list ap) +{ + int ret = -1; + va_list ap2; + char *string, *newstr; + size_t len; + + VA_COPY(ap2, ap); + if ((string = malloc(INIT_SZ)) == NULL) + goto fail; + + ret = vsnprintf(string, INIT_SZ, fmt, ap2); + if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ + *str = string; + } else if (ret == INT_MAX) { /* shouldn't happen */ + goto fail; + } else { /* bigger than initial, realloc allowing for nul */ + len = (size_t)ret + 1; + if ((newstr = realloc(string, len)) == NULL) { + free(string); + goto fail; + } else { + va_end(ap2); + VA_COPY(ap2, ap); + ret = vsnprintf(newstr, len, fmt, ap2); + if (ret >= 0 && (size_t)ret < len) { + *str = newstr; + } else { /* failed with realloc'ed string, give up */ + free(newstr); + goto fail; + } + } + } + va_end(ap2); + return (ret); + +fail: + *str = NULL; + errno = ENOMEM; + va_end(ap2); + return (-1); +} +#endif + +#ifndef HAVE_ASPRINTF +int asprintf(char **str, const char *fmt, ...) +{ + va_list ap; + int ret; + + *str = NULL; + va_start(ap, fmt); + ret = vasprintf(str, fmt, ap); + va_end(ap); + + return ret; +} +#endif diff --git a/crypto/openssh/openbsd-compat/bsd-closefrom.c b/crypto/openssh/openbsd-compat/bsd-closefrom.c new file mode 100644 index 0000000..9380b33 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-closefrom.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include "includes.h" + +#ifndef HAVE_CLOSEFROM + +#include <sys/types.h> +#include <sys/param.h> +#include <unistd.h> +#include <stdio.h> +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif +#include <limits.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#ifdef HAVE_DIRENT_H +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# ifdef HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# ifdef HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# ifdef HAVE_NDIR_H +# include <ndir.h> +# endif +#endif + +#ifndef OPEN_MAX +# define OPEN_MAX 256 +#endif + +#if 0 +__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $"; +#endif /* lint */ + +/* + * Close all file descriptors greater than or equal to lowfd. + */ +#ifdef HAVE_FCNTL_CLOSEM +void +closefrom(int lowfd) +{ + (void) fcntl(lowfd, F_CLOSEM, 0); +} +#else +void +closefrom(int lowfd) +{ + long fd, maxfd; +#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID) + char fdpath[PATH_MAX], *endp; + struct dirent *dent; + DIR *dirp; + int len; + + /* Check for a /proc/$$/fd directory. */ + len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid()); + if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) { + while ((dent = readdir(dirp)) != NULL) { + fd = strtol(dent->d_name, &endp, 10); + if (dent->d_name != endp && *endp == '\0' && + fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) + (void) close((int) fd); + } + (void) closedir(dirp); + } else +#endif + { + /* + * Fall back on sysconf() or getdtablesize(). We avoid checking + * resource limits since it is possible to open a file descriptor + * and then drop the rlimit such that it is below the open fd. + */ +#ifdef HAVE_SYSCONF + maxfd = sysconf(_SC_OPEN_MAX); +#else + maxfd = getdtablesize(); +#endif /* HAVE_SYSCONF */ + if (maxfd < 0) + maxfd = OPEN_MAX; + + for (fd = lowfd; fd < maxfd; fd++) + (void) close((int) fd); + } +} +#endif /* !HAVE_FCNTL_CLOSEM */ +#endif /* HAVE_CLOSEFROM */ diff --git a/crypto/openssh/openbsd-compat/bsd-cray.c b/crypto/openssh/openbsd-compat/bsd-cray.c new file mode 100644 index 0000000..1532c99 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-cray.c @@ -0,0 +1,819 @@ +/* + * $Id: bsd-cray.c,v 1.16 2006/09/01 05:38:41 djm Exp $ + * + * bsd-cray.c + * + * Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>) + * Significant portions provided by + * Wayne Schroeder, SDSC <schroeder@sdsc.edu> + * William Jones, UTexas <jones@tacc.utexas.edu> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Created: Apr 22 16.34:00 2002 wp + * + * This file contains functions required for proper execution + * on UNICOS systems. + * + */ +#ifdef _UNICOS + +#include <udb.h> +#include <tmpdir.h> +#include <unistd.h> +#include <sys/category.h> +#include <utmp.h> +#include <sys/jtab.h> +#include <signal.h> +#include <sys/priv.h> +#include <sys/secparm.h> +#include <sys/tfm.h> +#include <sys/usrv.h> +#include <sys/sysv.h> +#include <sys/sectab.h> +#include <sys/secstat.h> +#include <sys/stat.h> +#include <sys/session.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <pwd.h> +#include <fcntl.h> +#include <errno.h> +#include <ia.h> +#include <urm.h> +#include "ssh.h" + +#include "includes.h" +#include "sys/types.h" + +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +# define _SS_MAXSIZE 128 /* Implementation specific max size */ +# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) + +# define ss_family ss_sa.sa_family +#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +#ifndef IN6_IS_ADDR_LOOPBACK +# define IN6_IS_ADDR_LOOPBACK(a) \ + (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \ + ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1)) +#endif /* !IN6_IS_ADDR_LOOPBACK */ + +#ifndef AF_INET6 +/* Define it to something that should never appear */ +#define AF_INET6 AF_MAX +#endif + +#include "log.h" +#include "servconf.h" +#include "bsd-cray.h" + +#define MAXACID 80 + +extern ServerOptions options; + +char cray_tmpdir[TPATHSIZ + 1]; /* job TMPDIR path */ + +struct sysv sysv; /* system security structure */ +struct usrv usrv; /* user security structure */ + +/* + * Functions. + */ +void cray_retain_utmp(struct utmp *, int); +void cray_delete_tmpdir(char *, int, uid_t); +void cray_init_job(struct passwd *); +void cray_set_tmpdir(struct utmp *); +void cray_login_failure(char *, int); +int cray_setup(uid_t, char *, const char *); +int cray_access_denied(char *); + +void +cray_login_failure(char *username, int errcode) +{ + struct udb *ueptr; /* UDB pointer for username */ + ia_failure_t fsent; /* ia_failure structure */ + ia_failure_ret_t fret; /* ia_failure return stuff */ + struct jtab jtab; /* job table structure */ + int jid = 0; /* job id */ + + if ((jid = getjtab(&jtab)) < 0) + debug("cray_login_failure(): getjtab error"); + + getsysudb(); + if ((ueptr = getudbnam(username)) == UDB_NULL) + debug("cray_login_failure(): getudbname() returned NULL"); + endudb(); + + memset(&fsent, '\0', sizeof(fsent)); + fsent.revision = 0; + fsent.uname = username; + fsent.host = (char *)get_canonical_hostname(options.use_dns); + fsent.ttyn = "sshd"; + fsent.caller = IA_SSHD; + fsent.flags = IA_INTERACTIVE; + fsent.ueptr = ueptr; + fsent.jid = jid; + fsent.errcode = errcode; + fsent.pwdp = NULL; + fsent.exitcode = 0; /* dont exit in ia_failure() */ + + fret.revision = 0; + fret.normal = 0; + + /* + * Call ia_failure because of an login failure. + */ + ia_failure(&fsent, &fret); +} + +/* + * Cray access denied + */ +int +cray_access_denied(char *username) +{ + struct udb *ueptr; /* UDB pointer for username */ + int errcode; /* IA errorcode */ + + errcode = 0; + getsysudb(); + if ((ueptr = getudbnam(username)) == UDB_NULL) + debug("cray_login_failure(): getudbname() returned NULL"); + endudb(); + + if (ueptr != NULL && ueptr->ue_disabled) + errcode = IA_DISABLED; + if (errcode) + cray_login_failure(username, errcode); + + return (errcode); +} + +/* + * record_failed_login: generic "login failed" interface function + */ +void +record_failed_login(const char *user, const char *hostname, const char *ttyname) +{ + cray_login_failure((char *)user, IA_UDBERR); +} + +int +cray_setup (uid_t uid, char *username, const char *command) +{ + extern struct udb *getudb(); + extern char *setlimits(); + + int err; /* error return */ + time_t system_time; /* current system clock */ + time_t expiration_time; /* password expiration time */ + int maxattempts; /* maximum no. of failed login attempts */ + int SecureSys; /* unicos security flag */ + int minslevel = 0; /* system minimum security level */ + int i, j; + int valid_acct = -1; /* flag for reading valid acct */ + char acct_name[MAXACID] = { "" }; /* used to read acct name */ + struct jtab jtab; /* Job table struct */ + struct udb ue; /* udb entry for logging-in user */ + struct udb *up; /* pointer to UDB entry */ + struct secstat secinfo; /* file security attributes */ + struct servprov init_info; /* used for sesscntl() call */ + int jid; /* job ID */ + int pid; /* process ID */ + char *sr; /* status return from setlimits() */ + char *ttyn = NULL; /* ttyname or command name*/ + char hostname[MAXHOSTNAMELEN]; + /* passwd stuff for ia_user */ + passwd_t pwdacm, pwddialup, pwdudb, pwdwal, pwddce; + ia_user_ret_t uret; /* stuff returned from ia_user */ + ia_user_t usent; /* ia_user main structure */ + int ia_rcode; /* ia_user return code */ + ia_failure_t fsent; /* ia_failure structure */ + ia_failure_ret_t fret; /* ia_failure return stuff */ + ia_success_t ssent; /* ia_success structure */ + ia_success_ret_t sret; /* ia_success return stuff */ + int ia_mlsrcode; /* ia_mlsuser return code */ + int secstatrc; /* [f]secstat return code */ + + if (SecureSys = (int)sysconf(_SC_CRAY_SECURE_SYS)) { + getsysv(&sysv, sizeof(struct sysv)); + minslevel = sysv.sy_minlvl; + if (getusrv(&usrv) < 0) + fatal("getusrv() failed, errno = %d", errno); + } + hostname[0] = '\0'; + strlcpy(hostname, + (char *)get_canonical_hostname(options.use_dns), + MAXHOSTNAMELEN); + /* + * Fetch user's UDB entry. + */ + getsysudb(); + if ((up = getudbnam(username)) == UDB_NULL) + fatal("cannot fetch user's UDB entry"); + + /* + * Prevent any possible fudging so perform a data + * safety check and compare the supplied uid against + * the udb's uid. + */ + if (up->ue_uid != uid) + fatal("IA uid missmatch"); + endudb(); + + if ((jid = getjtab(&jtab)) < 0) { + debug("getjtab"); + return(-1); + } + pid = getpid(); + ttyn = ttyname(0); + if (SecureSys) { + if (ttyn != NULL) + secstatrc = secstat(ttyn, &secinfo); + else + secstatrc = fsecstat(1, &secinfo); + + if (secstatrc == 0) + debug("[f]secstat() successful"); + else + fatal("[f]secstat() error, rc = %d", secstatrc); + } + if ((ttyn == NULL) && ((char *)command != NULL)) + ttyn = (char *)command; + /* + * Initialize all structures to call ia_user + */ + usent.revision = 0; + usent.uname = username; + usent.host = hostname; + usent.ttyn = ttyn; + usent.caller = IA_SSHD; + usent.pswdlist = &pwdacm; + usent.ueptr = &ue; + usent.flags = IA_INTERACTIVE | IA_FFLAG; + pwdacm.atype = IA_SECURID; + pwdacm.pwdp = NULL; + pwdacm.next = &pwdudb; + + pwdudb.atype = IA_UDB; + pwdudb.pwdp = NULL; + pwdudb.next = &pwddce; + + pwddce.atype = IA_DCE; + pwddce.pwdp = NULL; + pwddce.next = &pwddialup; + + pwddialup.atype = IA_DIALUP; + pwddialup.pwdp = NULL; + /* pwddialup.next = &pwdwal; */ + pwddialup.next = NULL; + + pwdwal.atype = IA_WAL; + pwdwal.pwdp = NULL; + pwdwal.next = NULL; + + uret.revision = 0; + uret.pswd = NULL; + uret.normal = 0; + + ia_rcode = ia_user(&usent, &uret); + switch (ia_rcode) { + /* + * These are acceptable return codes from ia_user() + */ + case IA_UDBWEEK: /* Password Expires in 1 week */ + expiration_time = ue.ue_pwage.time + ue.ue_pwage.maxage; + printf ("WARNING - your current password will expire %s\n", + ctime((const time_t *)&expiration_time)); + break; + case IA_UDBEXPIRED: + if (ttyname(0) != NULL) { + /* Force a password change */ + printf("Your password has expired; Choose a new one.\n"); + execl("/bin/passwd", "passwd", username, 0); + exit(9); + } + break; + case IA_NORMAL: /* Normal Return Code */ + break; + case IA_BACKDOOR: + /* XXX: can we memset it to zero here so save some of this */ + strlcpy(ue.ue_name, "root", sizeof(ue.ue_name)); + strlcpy(ue.ue_dir, "/", sizeof(ue.ue_dir)); + strlcpy(ue.ue_shell, "/bin/sh", sizeof(ue.ue_shell)); + + ue.ue_passwd[0] = '\0'; + ue.ue_age[0] = '\0'; + ue.ue_comment[0] = '\0'; + ue.ue_loghost[0] = '\0'; + ue.ue_logline[0] = '\0'; + + ue.ue_uid = -1; + ue.ue_nice[UDBRC_INTER] = 0; + + for (i = 0; i < MAXVIDS; i++) + ue.ue_gids[i] = 0; + + ue.ue_logfails = 0; + ue.ue_minlvl = ue.ue_maxlvl = ue.ue_deflvl = minslevel; + ue.ue_defcomps = 0; + ue.ue_comparts = 0; + ue.ue_permits = 0; + ue.ue_trap = 0; + ue.ue_disabled = 0; + ue.ue_logtime = 0; + break; + case IA_CONSOLE: /* Superuser not from Console */ + case IA_TRUSTED: /* Trusted user */ + if (options.permit_root_login > PERMIT_NO) + break; /* Accept root login */ + default: + /* + * These are failed return codes from ia_user() + */ + switch (ia_rcode) + { + case IA_BADAUTH: + printf("Bad authorization, access denied.\n"); + break; + case IA_DISABLED: + printf("Your login has been disabled. Contact the system "); + printf("administrator for assistance.\n"); + break; + case IA_GETSYSV: + printf("getsysv() failed - errno = %d\n", errno); + break; + case IA_MAXLOGS: + printf("Maximum number of failed login attempts exceeded.\n"); + printf("Access denied.\n"); + break; + case IA_UDBPWDNULL: + if (SecureSys) + printf("NULL Password not allowed on MLS systems.\n"); + break; + default: + break; + } + + /* + * Authentication failed. + */ + printf("sshd: Login incorrect, (0%o)\n", + ia_rcode-IA_ERRORCODE); + + /* + * Initialize structure for ia_failure + * which will exit. + */ + fsent.revision = 0; + fsent.uname = username; + fsent.host = hostname; + fsent.ttyn = ttyn; + fsent.caller = IA_SSHD; + fsent.flags = IA_INTERACTIVE; + fsent.ueptr = &ue; + fsent.jid = jid; + fsent.errcode = ia_rcode; + fsent.pwdp = uret.pswd; + fsent.exitcode = 1; + + fret.revision = 0; + fret.normal = 0; + + /* + * Call ia_failure because of an IA failure. + * There is no return because ia_failure exits. + */ + ia_failure(&fsent, &fret); + + exit(1); + } + + ia_mlsrcode = IA_NORMAL; + if (SecureSys) { + debug("calling ia_mlsuser()"); + ia_mlsrcode = ia_mlsuser(&ue, &secinfo, &usrv, NULL, 0); + } + if (ia_mlsrcode != IA_NORMAL) { + printf("sshd: Login incorrect, (0%o)\n", + ia_mlsrcode-IA_ERRORCODE); + /* + * Initialize structure for ia_failure + * which will exit. + */ + fsent.revision = 0; + fsent.uname = username; + fsent.host = hostname; + fsent.ttyn = ttyn; + fsent.caller = IA_SSHD; + fsent.flags = IA_INTERACTIVE; + fsent.ueptr = &ue; + fsent.jid = jid; + fsent.errcode = ia_mlsrcode; + fsent.pwdp = uret.pswd; + fsent.exitcode = 1; + fret.revision = 0; + fret.normal = 0; + + /* + * Call ia_failure because of an IA failure. + * There is no return because ia_failure exits. + */ + ia_failure(&fsent,&fret); + exit(1); + } + + /* Provide login status information */ + if (options.print_lastlog && ue.ue_logtime != 0) { + printf("Last successful login was : %.*s ", 19, + (char *)ctime(&ue.ue_logtime)); + + if (*ue.ue_loghost != '\0') { + printf("from %.*s\n", sizeof(ue.ue_loghost), + ue.ue_loghost); + } else { + printf("on %.*s\n", sizeof(ue.ue_logline), + ue.ue_logline); + } + + if (SecureSys && (ue.ue_logfails != 0)) { + printf(" followed by %d failed attempts\n", + ue.ue_logfails); + } + } + + /* + * Call ia_success to process successful I/A. + */ + ssent.revision = 0; + ssent.uname = username; + ssent.host = hostname; + ssent.ttyn = ttyn; + ssent.caller = IA_SSHD; + ssent.flags = IA_INTERACTIVE; + ssent.ueptr = &ue; + ssent.jid = jid; + ssent.errcode = ia_rcode; + ssent.us = NULL; + ssent.time = 1; /* Set ue_logtime */ + + sret.revision = 0; + sret.normal = 0; + + ia_success(&ssent, &sret); + + /* + * Query for account, iff > 1 valid acid & askacid permbit + */ + if (((ue.ue_permbits & PERMBITS_ACCTID) || + (ue.ue_acids[0] >= 0) && (ue.ue_acids[1] >= 0)) && + ue.ue_permbits & PERMBITS_ASKACID) { + if (ttyname(0) != NULL) { + debug("cray_setup: ttyname true case, %.100s", ttyname); + while (valid_acct == -1) { + printf("Account (? for available accounts)" + " [%s]: ", acid2nam(ue.ue_acids[0])); + fgets(acct_name, MAXACID, stdin); + switch (acct_name[0]) { + case EOF: + exit(0); + break; + case '\0': + valid_acct = ue.ue_acids[0]; + strlcpy(acct_name, acid2nam(valid_acct), MAXACID); + break; + case '?': + /* Print the list 3 wide */ + for (i = 0, j = 0; i < MAXVIDS; i++) { + if (ue.ue_acids[i] == -1) { + printf("\n"); + break; + } + if (++j == 4) { + j = 1; + printf("\n"); + } + printf(" %s", + acid2nam(ue.ue_acids[i])); + } + if (ue.ue_permbits & PERMBITS_ACCTID) { + printf("\"acctid\" permbit also allows" + " you to select any valid " + "account name.\n"); + } + printf("\n"); + break; + default: + valid_acct = nam2acid(acct_name); + if (valid_acct == -1) + printf( + "Account id not found for" + " account name \"%s\"\n\n", + acct_name); + break; + } + /* + * If an account was given, search the user's + * acids array to verify they can use this account. + */ + if ((valid_acct != -1) && + !(ue.ue_permbits & PERMBITS_ACCTID)) { + for (i = 0; i < MAXVIDS; i++) { + if (ue.ue_acids[i] == -1) + break; + if (valid_acct == ue.ue_acids[i]) + break; + } + if (i == MAXVIDS || + ue.ue_acids[i] == -1) { + fprintf(stderr, "Cannot set" + " account name to " + "\"%s\", permission " + "denied\n\n", acct_name); + valid_acct = -1; + } + } + } + } else { + /* + * The client isn't connected to a terminal and can't + * respond to an acid prompt. Use default acid. + */ + debug("cray_setup: ttyname false case, %.100s", + ttyname); + valid_acct = ue.ue_acids[0]; + } + } else { + /* + * The user doesn't have the askacid permbit set or + * only has one valid account to use. + */ + valid_acct = ue.ue_acids[0]; + } + if (acctid(0, valid_acct) < 0) { + printf ("Bad account id: %d\n", valid_acct); + exit(1); + } + + /* + * Now set shares, quotas, limits, including CPU time for the + * (interactive) job and process, and set up permissions + * (for chown etc), etc. + */ + if (setshares(ue.ue_uid, valid_acct, printf, 0, 0)) { + printf("Unable to give %d shares to <%s>(%d/%d)\n", + ue.ue_shares, ue.ue_name, ue.ue_uid, valid_acct); + exit(1); + } + + sr = setlimits(username, C_PROC, pid, UDBRC_INTER); + if (sr != NULL) { + debug("%.200s", sr); + exit(1); + } + sr = setlimits(username, C_JOB, jid, UDBRC_INTER); + if (sr != NULL) { + debug("%.200s", sr); + exit(1); + } + /* + * Place the service provider information into + * the session table (Unicos) or job table (Unicos/mk). + * There exist double defines for the job/session table in + * unicos/mk (jtab.h) so no need for a compile time switch. + */ + memset(&init_info, '\0', sizeof(init_info)); + init_info.s_sessinit.si_id = URM_SPT_LOGIN; + init_info.s_sessinit.si_pid = getpid(); + init_info.s_sessinit.si_sid = jid; + sesscntl(0, S_SETSERVPO, (int)&init_info); + + /* + * Set user and controlling tty security attributes. + */ + if (SecureSys) { + if (setusrv(&usrv) == -1) { + debug("setusrv() failed, errno = %d",errno); + exit(1); + } + } + + return (0); +} + +/* + * The rc.* and /etc/sdaemon methods of starting a program on unicos/unicosmk + * can have pal privileges that sshd can inherit which + * could allow a user to su to root with out a password. + * This subroutine clears all privileges. + */ +void +drop_cray_privs() +{ +#if defined(_SC_CRAY_PRIV_SU) + priv_proc_t *privstate; + int result; + extern int priv_set_proc(); + extern priv_proc_t *priv_init_proc(); + + /* + * If ether of theses two flags are not set + * then don't allow this version of ssh to run. + */ + if (!sysconf(_SC_CRAY_PRIV_SU)) + fatal("Not PRIV_SU system."); + if (!sysconf(_SC_CRAY_POSIX_PRIV)) + fatal("Not POSIX_PRIV."); + + debug("Setting MLS labels.");; + + if (sysconf(_SC_CRAY_SECURE_MAC)) { + usrv.sv_minlvl = SYSLOW; + usrv.sv_actlvl = SYSHIGH; + usrv.sv_maxlvl = SYSHIGH; + } else { + usrv.sv_minlvl = sysv.sy_minlvl; + usrv.sv_actlvl = sysv.sy_minlvl; + usrv.sv_maxlvl = sysv.sy_maxlvl; + } + usrv.sv_actcmp = 0; + usrv.sv_valcmp = sysv.sy_valcmp; + + usrv.sv_intcat = TFM_SYSTEM; + usrv.sv_valcat |= (TFM_SYSTEM | TFM_SYSFILE); + + if (setusrv(&usrv) < 0) { + fatal("%s(%d): setusrv(): %s", __FILE__, __LINE__, + strerror(errno)); + } + + if ((privstate = priv_init_proc()) != NULL) { + result = priv_set_proc(privstate); + if (result != 0 ) { + fatal("%s(%d): priv_set_proc(): %s", + __FILE__, __LINE__, strerror(errno)); + } + priv_free_proc(privstate); + } + debug ("Privileges should be cleared..."); +#else + /* XXX: do this differently */ +# error Cray systems must be run with _SC_CRAY_PRIV_SU on! +#endif +} + + +/* + * Retain utmp/wtmp information - used by cray accounting. + */ +void +cray_retain_utmp(struct utmp *ut, int pid) +{ + int fd; + struct utmp utmp; + + if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) { + /* XXX use atomicio */ + while (read(fd, (char *)&utmp, sizeof(utmp)) == sizeof(utmp)) { + if (pid == utmp.ut_pid) { + ut->ut_jid = utmp.ut_jid; + strncpy(ut->ut_tpath, utmp.ut_tpath, sizeof(utmp.ut_tpath)); + strncpy(ut->ut_host, utmp.ut_host, sizeof(utmp.ut_host)); + strncpy(ut->ut_name, utmp.ut_name, sizeof(utmp.ut_name)); + break; + } + } + close(fd); + } else + fatal("Unable to open utmp file"); +} + +/* + * tmpdir support. + */ + +/* + * find and delete jobs tmpdir. + */ +void +cray_delete_tmpdir(char *login, int jid, uid_t uid) +{ + static char jtmp[TPATHSIZ]; + struct stat statbuf; + int child, c, wstat; + + for (c = 'a'; c <= 'z'; c++) { + snprintf(jtmp, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c); + if (stat(jtmp, &statbuf) == 0 && statbuf.st_uid == uid) + break; + } + + if (c > 'z') + return; + + if ((child = fork()) == 0) { + execl(CLEANTMPCMD, CLEANTMPCMD, login, jtmp, (char *)NULL); + fatal("cray_delete_tmpdir: execl of CLEANTMPCMD failed"); + } + + while (waitpid(child, &wstat, 0) == -1 && errno == EINTR) + ; +} + +/* + * Remove tmpdir on job termination. + */ +void +cray_job_termination_handler(int sig) +{ + int jid; + char *login = NULL; + struct jtab jtab; + + debug("received signal %d",sig); + + if ((jid = waitjob(&jtab)) == -1 || + (login = uid2nam(jtab.j_uid)) == NULL) + return; + + cray_delete_tmpdir(login, jid, jtab.j_uid); +} + +/* + * Set job id and create tmpdir directory. + */ +void +cray_init_job(struct passwd *pw) +{ + int jid; + int c; + + jid = setjob(pw->pw_uid, WJSIGNAL); + if (jid < 0) + fatal("System call setjob failure"); + + for (c = 'a'; c <= 'z'; c++) { + snprintf(cray_tmpdir, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c); + if (mkdir(cray_tmpdir, JTMPMODE) != 0) + continue; + if (chown(cray_tmpdir, pw->pw_uid, pw->pw_gid) != 0) { + rmdir(cray_tmpdir); + continue; + } + break; + } + + if (c > 'z') + cray_tmpdir[0] = '\0'; +} + +void +cray_set_tmpdir(struct utmp *ut) +{ + int jid; + struct jtab jbuf; + + if ((jid = getjtab(&jbuf)) < 0) + return; + + /* + * Set jid and tmpdir in utmp record. + */ + ut->ut_jid = jid; + strncpy(ut->ut_tpath, cray_tmpdir, TPATHSIZ); +} +#endif /* UNICOS */ + +#ifdef _UNICOSMP +#include <pwd.h> +/* + * Set job id and create tmpdir directory. + */ +void +cray_init_job(struct passwd *pw) +{ + initrm_silent(pw->pw_uid); + return; +} +#endif /* _UNICOSMP */ diff --git a/crypto/openssh/openbsd-compat/bsd-cray.h b/crypto/openssh/openbsd-compat/bsd-cray.h new file mode 100644 index 0000000..774eceb --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-cray.h @@ -0,0 +1,61 @@ +/* $Id: bsd-cray.h,v 1.12 2005/02/02 06:10:11 dtucker Exp $ */ + +/* + * Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>) + * Significant portions provided by + * Wayne Schroeder, SDSC <schroeder@sdsc.edu> + * William Jones, UTexas <jones@tacc.utexas.edu> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Created: Apr 22 16.34:00 2002 wp + * + * This file contains functions required for proper execution + * on UNICOS systems. + * + */ + +#ifndef _BSD_CRAY_H +#define _BSD_CRAY_H + +#ifdef _UNICOS + +void cray_init_job(struct passwd *); +void cray_job_termination_handler(int); +void cray_login_failure(char *, int ); +int cray_access_denied(char *); +extern char cray_tmpdir[]; + +#define CUSTOM_FAILED_LOGIN 1 + +#ifndef IA_SSHD +# define IA_SSHD IA_LOGIN +#endif +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 64 +#endif +#ifndef _CRAYT3E +# define TIOCGPGRP (tIOC|20) +#endif + +#endif /* UNICOS */ + +#endif /* _BSD_CRAY_H */ diff --git a/crypto/openssh/openbsd-compat/bsd-cygwin_util.c b/crypto/openssh/openbsd-compat/bsd-cygwin_util.c new file mode 100644 index 0000000..dbf8176 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-cygwin_util.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Created: Sat Sep 02 12:17:00 2000 cv + * + * This file contains functions for forcing opened file descriptors to + * binary mode on Windows systems. + */ + +#include "includes.h" + +#ifdef HAVE_CYGWIN + +#if defined(open) && open == binary_open +# undef open +#endif +#if defined(pipe) && open == binary_pipe +# undef pipe +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/utsname.h> +#include <sys/vfs.h> + +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <windows.h> + +#include "xmalloc.h" +#define is_winnt (GetVersion() < 0x80000000) + +#define ntsec_on(c) ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec")) +#define ntsec_off(c) ((c) && strstr((c),"nontsec")) +#define ntea_on(c) ((c) && strstr((c),"ntea") && !strstr((c),"nontea")) + +int +binary_open(const char *filename, int flags, ...) +{ + va_list ap; + mode_t mode; + + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + return (open(filename, flags | O_BINARY, mode)); +} + +int +binary_pipe(int fd[2]) +{ + int ret = pipe(fd); + + if (!ret) { + setmode(fd[0], O_BINARY); + setmode(fd[1], O_BINARY); + } + return (ret); +} + +#define HAS_CREATE_TOKEN 1 +#define HAS_NTSEC_BY_DEFAULT 2 +#define HAS_CREATE_TOKEN_WO_NTSEC 3 + +static int +has_capability(int what) +{ + static int inited; + static int has_create_token; + static int has_ntsec_by_default; + static int has_create_token_wo_ntsec; + + /* + * has_capability() basically calls uname() and checks if + * specific capabilities of Cygwin can be evaluated from that. + * This simplifies the calling functions which only have to ask + * for a capability using has_capability() instead of having + * to figure that out by themselves. + */ + if (!inited) { + struct utsname uts; + + if (!uname(&uts)) { + int major_high = 0, major_low = 0, minor = 0; + int api_major_version = 0, api_minor_version = 0; + char *c; + + sscanf(uts.release, "%d.%d.%d", &major_high, + &major_low, &minor); + if ((c = strchr(uts.release, '(')) != NULL) { + sscanf(c + 1, "%d.%d", &api_major_version, + &api_minor_version); + } + if (major_high > 1 || + (major_high == 1 && (major_low > 3 || + (major_low == 3 && minor >= 2)))) + has_create_token = 1; + if (api_major_version > 0 || api_minor_version >= 56) + has_ntsec_by_default = 1; + if (major_high > 1 || + (major_high == 1 && major_low >= 5)) + has_create_token_wo_ntsec = 1; + inited = 1; + } + } + switch (what) { + case HAS_CREATE_TOKEN: + return (has_create_token); + case HAS_NTSEC_BY_DEFAULT: + return (has_ntsec_by_default); + case HAS_CREATE_TOKEN_WO_NTSEC: + return (has_create_token_wo_ntsec); + } + return (0); +} + +int +check_nt_auth(int pwd_authenticated, struct passwd *pw) +{ + /* + * The only authentication which is able to change the user + * context on NT systems is the password authentication. So + * we deny all requsts for changing the user context if another + * authentication method is used. + * + * This doesn't apply to Cygwin versions >= 1.3.2 anymore which + * uses the undocumented NtCreateToken() call to create a user + * token if the process has the appropriate privileges and if + * CYGWIN ntsec setting is on. + */ + static int has_create_token = -1; + + if (pw == NULL) + return 0; + if (is_winnt) { + if (has_create_token < 0) { + char *cygwin = getenv("CYGWIN"); + + has_create_token = 0; + if (has_capability(HAS_CREATE_TOKEN) && + (ntsec_on(cygwin) || + (has_capability(HAS_NTSEC_BY_DEFAULT) && + !ntsec_off(cygwin)) || + has_capability(HAS_CREATE_TOKEN_WO_NTSEC))) + has_create_token = 1; + } + if (has_create_token < 1 && + !pwd_authenticated && geteuid() != pw->pw_uid) + return (0); + } + return (1); +} + +int +check_ntsec(const char *filename) +{ + char *cygwin; + int allow_ntea = 0, allow_ntsec = 0; + struct statfs fsstat; + + /* Windows 95/98/ME don't support file system security at all. */ + if (!is_winnt) + return (0); + + /* Evaluate current CYGWIN settings. */ + cygwin = getenv("CYGWIN"); + allow_ntea = ntea_on(cygwin); + allow_ntsec = ntsec_on(cygwin) || + (has_capability(HAS_NTSEC_BY_DEFAULT) && !ntsec_off(cygwin)); + + /* + * `ntea' is an emulation of POSIX attributes. It doesn't support + * real file level security as ntsec on NTFS file systems does + * but it supports FAT filesystems. `ntea' is minimum requirement + * for security checks. + */ + if (allow_ntea) + return (1); + + /* + * Retrieve file system flags. In Cygwin, file system flags are + * copied to f_type which has no meaning in Win32 itself. + */ + if (statfs(filename, &fsstat)) + return (1); + + /* + * Only file systems supporting ACLs are able to set permissions. + * `ntsec' is the setting in Cygwin which switches using of NTFS + * ACLs to support POSIX permissions on files. + */ + if (fsstat.f_type & FS_PERSISTENT_ACLS) + return (allow_ntsec); + + return (0); +} + +void +register_9x_service(void) +{ + HINSTANCE kerneldll; + DWORD (*RegisterServiceProcess)(DWORD, DWORD); + + /* The service register mechanism in 9x/Me is pretty different from + * NT/2K/XP. In NT/2K/XP we're using a special service starter + * application to register and control sshd as service. This method + * doesn't play nicely with 9x/Me. For that reason we register here + * as service when running under 9x/Me. This function is only called + * by the child sshd when it's going to daemonize. + */ + if (is_winnt) + return; + if (!(kerneldll = LoadLibrary("KERNEL32.DLL"))) + return; + if (!(RegisterServiceProcess = (DWORD (*)(DWORD, DWORD)) + GetProcAddress(kerneldll, "RegisterServiceProcess"))) + return; + RegisterServiceProcess(0, 1); +} + +#define NL(x) x, (sizeof (x) - 1) +#define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0])) + +static struct wenv { + const char *name; + size_t namelen; +} wenv_arr[] = { + { NL("ALLUSERSPROFILE=") }, + { NL("COMMONPROGRAMFILES=") }, + { NL("COMPUTERNAME=") }, + { NL("COMSPEC=") }, + { NL("CYGWIN=") }, + { NL("NUMBER_OF_PROCESSORS=") }, + { NL("OS=") }, + { NL("PATH=") }, + { NL("PATHEXT=") }, + { NL("PROCESSOR_ARCHITECTURE=") }, + { NL("PROCESSOR_IDENTIFIER=") }, + { NL("PROCESSOR_LEVEL=") }, + { NL("PROCESSOR_REVISION=") }, + { NL("PROGRAMFILES=") }, + { NL("SYSTEMDRIVE=") }, + { NL("SYSTEMROOT=") }, + { NL("TMP=") }, + { NL("TEMP=") }, + { NL("WINDIR=") } +}; + +char ** +fetch_windows_environment(void) +{ + char **e, **p; + unsigned int i, idx = 0; + + p = xcalloc(WENV_SIZ + 1, sizeof(char *)); + for (e = environ; *e != NULL; ++e) { + for (i = 0; i < WENV_SIZ; ++i) { + if (!strncmp(*e, wenv_arr[i].name, wenv_arr[i].namelen)) + p[idx++] = *e; + } + } + p[idx] = NULL; + return p; +} + +void +free_windows_environment(char **p) +{ + xfree(p); +} + +#endif /* HAVE_CYGWIN */ diff --git a/crypto/openssh/openbsd-compat/bsd-cygwin_util.h b/crypto/openssh/openbsd-compat/bsd-cygwin_util.h new file mode 100644 index 0000000..6719b8a --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-cygwin_util.h @@ -0,0 +1,57 @@ +/* $Id: bsd-cygwin_util.h,v 1.11 2004/08/30 10:42:08 dtucker Exp $ */ + +/* + * Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Created: Sat Sep 02 12:17:00 2000 cv + * + * This file contains functions for forcing opened file descriptors to + * binary mode on Windows systems. + */ + +#ifndef _BSD_CYGWIN_UTIL_H +#define _BSD_CYGWIN_UTIL_H + +#ifdef HAVE_CYGWIN + +#undef ERROR +#define is_winnt (GetVersion() < 0x80000000) + +#include <windows.h> +#include <sys/cygwin.h> +#include <io.h> + +int binary_open(const char *, int , ...); +int binary_pipe(int fd[2]); +int check_nt_auth(int, struct passwd *); +int check_ntsec(const char *); +void register_9x_service(void); +char **fetch_windows_environment(void); +void free_windows_environment(char **); + +#define open binary_open +#define pipe binary_pipe + +#endif /* HAVE_CYGWIN */ + +#endif /* _BSD_CYGWIN_UTIL_H */ diff --git a/crypto/openssh/openbsd-compat/bsd-getpeereid.c b/crypto/openssh/openbsd-compat/bsd-getpeereid.c new file mode 100644 index 0000000..bdae8b6 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-getpeereid.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002,2004 Damien Miller <djm@mindrot.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include "includes.h" + +#if !defined(HAVE_GETPEEREID) + +#include <sys/types.h> +#include <sys/socket.h> + +#include <unistd.h> + +#if defined(SO_PEERCRED) +int +getpeereid(int s, uid_t *euid, gid_t *gid) +{ + struct ucred cred; + socklen_t len = sizeof(cred); + + if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0) + return (-1); + *euid = cred.uid; + *gid = cred.gid; + + return (0); +} +#else +int +getpeereid(int s, uid_t *euid, gid_t *gid) +{ + *euid = geteuid(); + *gid = getgid(); + + return (0); +} +#endif /* defined(SO_PEERCRED) */ + +#endif /* !defined(HAVE_GETPEEREID) */ diff --git a/crypto/openssh/openbsd-compat/bsd-misc.c b/crypto/openssh/openbsd-compat/bsd-misc.c new file mode 100644 index 0000000..17d731b --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-misc.c @@ -0,0 +1,239 @@ + +/* + * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include "includes.h" + +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#endif +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#endif + +#include <string.h> +#include <signal.h> +#include <stdlib.h> + +#include "xmalloc.h" + +#ifndef HAVE___PROGNAME +char *__progname; +#endif + +/* + * NB. duplicate __progname in case it is an alias for argv[0] + * Otherwise it may get clobbered by setproctitle() + */ +char *ssh_get_progname(char *argv0) +{ +#ifdef HAVE___PROGNAME + extern char *__progname; + + return xstrdup(__progname); +#else + char *p; + + if (argv0 == NULL) + return ("unknown"); /* XXX */ + p = strrchr(argv0, '/'); + if (p == NULL) + p = argv0; + else + p++; + + return (xstrdup(p)); +#endif +} + +#ifndef HAVE_SETLOGIN +int setlogin(const char *name) +{ + return (0); +} +#endif /* !HAVE_SETLOGIN */ + +#ifndef HAVE_INNETGR +int innetgr(const char *netgroup, const char *host, + const char *user, const char *domain) +{ + return (0); +} +#endif /* HAVE_INNETGR */ + +#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) +int seteuid(uid_t euid) +{ + return (setreuid(-1, euid)); +} +#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ + +#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) +int setegid(uid_t egid) +{ + return(setresgid(-1, egid, -1)); +} +#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ + +#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) +const char *strerror(int e) +{ + extern int sys_nerr; + extern char *sys_errlist[]; + + if ((e >= 0) && (e < sys_nerr)) + return (sys_errlist[e]); + + return ("unlisted error"); +} +#endif + +#ifndef HAVE_UTIMES +int utimes(char *filename, struct timeval *tvp) +{ + struct utimbuf ub; + + ub.actime = tvp[0].tv_sec; + ub.modtime = tvp[1].tv_sec; + + return (utime(filename, &ub)); +} +#endif + +#ifndef HAVE_TRUNCATE +int truncate(const char *path, off_t length) +{ + int fd, ret, saverrno; + + fd = open(path, O_WRONLY); + if (fd < 0) + return (-1); + + ret = ftruncate(fd, length); + saverrno = errno; + close(fd); + if (ret == -1) + errno = saverrno; + + return(ret); +} +#endif /* HAVE_TRUNCATE */ + +#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) +int nanosleep(const struct timespec *req, struct timespec *rem) +{ + int rc, saverrno; + extern int errno; + struct timeval tstart, tstop, tremain, time2wait; + + TIMESPEC_TO_TIMEVAL(&time2wait, req) + (void) gettimeofday(&tstart, NULL); + rc = select(0, NULL, NULL, NULL, &time2wait); + if (rc == -1) { + saverrno = errno; + (void) gettimeofday (&tstop, NULL); + errno = saverrno; + tremain.tv_sec = time2wait.tv_sec - + (tstop.tv_sec - tstart.tv_sec); + tremain.tv_usec = time2wait.tv_usec - + (tstop.tv_usec - tstart.tv_usec); + tremain.tv_sec += tremain.tv_usec / 1000000L; + tremain.tv_usec %= 1000000L; + } else { + tremain.tv_sec = 0; + tremain.tv_usec = 0; + } + TIMEVAL_TO_TIMESPEC(&tremain, rem) + + return(rc); +} +#endif + +#ifndef HAVE_TCGETPGRP +pid_t +tcgetpgrp(int fd) +{ + int ctty_pgrp; + + if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1) + return(-1); + else + return(ctty_pgrp); +} +#endif /* HAVE_TCGETPGRP */ + +#ifndef HAVE_TCSENDBREAK +int +tcsendbreak(int fd, int duration) +{ +# if defined(TIOCSBRK) && defined(TIOCCBRK) + struct timeval sleepytime; + + sleepytime.tv_sec = 0; + sleepytime.tv_usec = 400000; + if (ioctl(fd, TIOCSBRK, 0) == -1) + return (-1); + (void)select(0, 0, 0, 0, &sleepytime); + if (ioctl(fd, TIOCCBRK, 0) == -1) + return (-1); + return (0); +# else + return -1; +# endif +} +#endif /* HAVE_TCSENDBREAK */ + +mysig_t +mysignal(int sig, mysig_t act) +{ +#ifdef HAVE_SIGACTION + struct sigaction sa, osa; + + if (sigaction(sig, NULL, &osa) == -1) + return (mysig_t) -1; + if (osa.sa_handler != act) { + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; +#ifdef SA_INTERRUPT + if (sig == SIGALRM) + sa.sa_flags |= SA_INTERRUPT; +#endif + sa.sa_handler = act; + if (sigaction(sig, &sa, NULL) == -1) + return (mysig_t) -1; + } + return (osa.sa_handler); +#else + #undef signal + return (signal(sig, act)); +#endif +} + +#ifndef HAVE_STRDUP +char * +strdup(const char *str) +{ + size_t len; + char *cp; + + len = strlen(str) + 1; + cp = malloc(len); + if (cp != NULL) + return(memcpy(cp, str, len)); + return NULL; +} +#endif diff --git a/crypto/openssh/openbsd-compat/bsd-misc.h b/crypto/openssh/openbsd-compat/bsd-misc.h new file mode 100644 index 0000000..b61ec42 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-misc.h @@ -0,0 +1,98 @@ +/* $Id: bsd-misc.h,v 1.18 2005/02/25 23:07:38 dtucker Exp $ */ + +/* + * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 _BSD_MISC_H +#define _BSD_MISC_H + +#include "includes.h" + +char *ssh_get_progname(char *); + +#ifndef HAVE_SETSID +#define setsid() setpgrp(0, getpid()) +#endif /* !HAVE_SETSID */ + +#ifndef HAVE_SETENV +int setenv(const char *, const char *, int); +#endif /* !HAVE_SETENV */ + +#ifndef HAVE_SETLOGIN +int setlogin(const char *); +#endif /* !HAVE_SETLOGIN */ + +#ifndef HAVE_INNETGR +int innetgr(const char *, const char *, const char *, const char *); +#endif /* HAVE_INNETGR */ + +#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) +int seteuid(uid_t); +#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ + +#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) +int setegid(uid_t); +#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ + +#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) +const char *strerror(int); +#endif + + +#ifndef HAVE_UTIMES +#ifndef HAVE_STRUCT_TIMEVAL +struct timeval { + long tv_sec; + long tv_usec; +} +#endif /* HAVE_STRUCT_TIMEVAL */ + +int utimes(char *, struct timeval *); +#endif /* HAVE_UTIMES */ + +#ifndef HAVE_TRUNCATE +int truncate (const char *, off_t); +#endif /* HAVE_TRUNCATE */ + +#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) +#ifndef HAVE_STRUCT_TIMESPEC +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif +int nanosleep(const struct timespec *, struct timespec *); +#endif + +#ifndef HAVE_TCGETPGRP +pid_t tcgetpgrp(int); +#endif + +#ifndef HAVE_TCSENDBREAK +int tcsendbreak(int, int); +#endif + +#ifndef HAVE_UNSETENV +void unsetenv(const char *); +#endif + +/* wrapper for signal interface */ +typedef void (*mysig_t)(int); +mysig_t mysignal(int sig, mysig_t act); + +#define signal(a,b) mysignal(a,b) + +#endif /* _BSD_MISC_H */ diff --git a/crypto/openssh/openbsd-compat/bsd-nextstep.c b/crypto/openssh/openbsd-compat/bsd-nextstep.c new file mode 100644 index 0000000..8195af8 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-nextstep.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2000,2001 Ben Lindstrom. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include "includes.h" + +#ifdef HAVE_NEXT +#include <errno.h> +#include <sys/wait.h> +#include "bsd-nextstep.h" + +pid_t +posix_wait(int *status) +{ + union wait statusp; + pid_t wait_pid; + + #undef wait /* Use NeXT's wait() function */ + wait_pid = wait(&statusp); + if (status) + *status = (int) statusp.w_status; + + return (wait_pid); +} + +int +tcgetattr(int fd, struct termios *t) +{ + return (ioctl(fd, TIOCGETA, t)); +} + +int +tcsetattr(int fd, int opt, const struct termios *t) +{ + struct termios localterm; + + if (opt & TCSASOFT) { + localterm = *t; + localterm.c_cflag |= CIGNORE; + t = &localterm; + } + switch (opt & ~TCSASOFT) { + case TCSANOW: + return (ioctl(fd, TIOCSETA, t)); + case TCSADRAIN: + return (ioctl(fd, TIOCSETAW, t)); + case TCSAFLUSH: + return (ioctl(fd, TIOCSETAF, t)); + default: + errno = EINVAL; + return (-1); + } +} + +int tcsetpgrp(int fd, pid_t pgrp) +{ + return (ioctl(fd, TIOCSPGRP, &pgrp)); +} + +speed_t cfgetospeed(const struct termios *t) +{ + return (t->c_ospeed); +} + +speed_t cfgetispeed(const struct termios *t) +{ + return (t->c_ispeed); +} + +int +cfsetospeed(struct termios *t,int speed) +{ + t->c_ospeed = speed; + return (0); +} + +int +cfsetispeed(struct termios *t, int speed) +{ + t->c_ispeed = speed; + return (0); +} +#endif /* HAVE_NEXT */ diff --git a/crypto/openssh/openbsd-compat/bsd-nextstep.h b/crypto/openssh/openbsd-compat/bsd-nextstep.h new file mode 100644 index 0000000..ca5b4b5 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-nextstep.h @@ -0,0 +1,59 @@ +/* $Id: bsd-nextstep.h,v 1.9 2003/08/29 16:59:52 mouring Exp $ */ + +/* + * Copyright (c) 2000,2001 Ben Lindstrom. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + */ + +#ifndef _NEXT_POSIX_H +#define _NEXT_POSIX_H + +#ifdef HAVE_NEXT +#include <sys/dir.h> + +/* NGROUPS_MAX is behind -lposix. Use the BSD version which is NGROUPS */ +#undef NGROUPS_MAX +#define NGROUPS_MAX NGROUPS + +/* NeXT's readdir() is BSD (struct direct) not POSIX (struct dirent) */ +#define dirent direct + +/* Swap out NeXT's BSD wait() for a more POSIX complient one */ +pid_t posix_wait(int *); +#define wait(a) posix_wait(a) + +/* #ifdef wrapped functions that need defining for clean compiling */ +pid_t getppid(void); +void vhangup(void); +int innetgr(const char *, const char *, const char *, const char *); + +/* TERMCAP */ +int tcgetattr(int, struct termios *); +int tcsetattr(int, int, const struct termios *); +int tcsetpgrp(int, pid_t); +speed_t cfgetospeed(const struct termios *); +speed_t cfgetispeed(const struct termios *); +int cfsetospeed(struct termios *, int); +int cfsetispeed(struct termios *, int); +#endif /* HAVE_NEXT */ +#endif /* _NEXT_POSIX_H */ diff --git a/crypto/openssh/openbsd-compat/bsd-openpty.c b/crypto/openssh/openbsd-compat/bsd-openpty.c new file mode 100644 index 0000000..9777eb5 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-openpty.c @@ -0,0 +1,220 @@ +/* + * Please note: this implementation of openpty() is far from complete. + * it is just enough for portable OpenSSH's needs. + */ + +/* + * Copyright (c) 2004 Damien Miller <djm@mindrot.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* + * Author: Tatu Ylonen <ylo@cs.hut.fi> + * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland + * All rights reserved + * Allocating a pseudo-terminal, and making it the controlling tty. + * + * As far as I am concerned, the code I have written for this software + * can be used freely for any purpose. Any derived versions of this + * software must be clearly marked as such, and if the derived work is + * incompatible with the protocol description in the RFC file, it must be + * called by a name other than "ssh" or "Secure Shell". + */ + +#include "includes.h" +#if !defined(HAVE_OPENPTY) + +#include <sys/types.h> + +#include <stdlib.h> + +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef HAVE_SYS_IOCTL_H +# include <sys/ioctl.h> +#endif + +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + +#ifdef HAVE_UTIL_H +# include <util.h> +#endif /* HAVE_UTIL_H */ + +#ifdef HAVE_PTY_H +# include <pty.h> +#endif +#if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) +# include <sys/stropts.h> +#endif + +#include <signal.h> +#include <string.h> +#include <unistd.h> + +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + +int +openpty(int *amaster, int *aslave, char *name, struct termios *termp, + struct winsize *winp) +{ +#if defined(HAVE__GETPTY) + /* + * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more + * pty's automagically when needed + */ + char *slave; + + if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL) + return (-1); + + /* Open the slave side. */ + if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) { + close(*amaster); + return (-1); + } + return (0); + +#elif defined(HAVE_DEV_PTMX) + /* + * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 + * also has bsd-style ptys, but they simply do not work.) + */ + int ptm; + char *pts; + mysig_t old_signal; + + if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) + return (-1); + + /* XXX: need to close ptm on error? */ + old_signal = signal(SIGCHLD, SIG_DFL); + if (grantpt(ptm) < 0) + return (-1); + signal(SIGCHLD, old_signal); + + if (unlockpt(ptm) < 0) + return (-1); + + if ((pts = ptsname(ptm)) == NULL) + return (-1); + *amaster = ptm; + + /* Open the slave side. */ + if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) { + close(*amaster); + return (-1); + } + + /* + * Try to push the appropriate streams modules, as described + * in Solaris pts(7). + */ + ioctl(*aslave, I_PUSH, "ptem"); + ioctl(*aslave, I_PUSH, "ldterm"); +# ifndef __hpux + ioctl(*aslave, I_PUSH, "ttcompat"); +# endif /* __hpux */ + + return (0); + +#elif defined(HAVE_DEV_PTS_AND_PTC) + /* AIX-style pty code. */ + const char *ttname; + + if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1) + return (-1); + if ((ttname = ttyname(*amaster)) == NULL) + return (-1); + if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) { + close(*amaster); + return (-1); + } + return (0); + +#elif defined(_UNICOS) + char ptbuf[64], ttbuf[64]; + int i; + int highpty; + + highpty = 128; +#ifdef _SC_CRAY_NPTY + if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1) + highpty = 128; +#endif /* _SC_CRAY_NPTY */ + + for (i = 0; i < highpty; i++) { + snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i); + snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i); + if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1) + continue; + /* Open the slave side. */ + if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) { + close(*amaster); + return (-1); + } + return (0); + } + return (-1); + +#else + /* BSD-style pty code. */ + char ptbuf[64], ttbuf[64]; + int i; + const char *ptymajors = "pqrstuvwxyzabcdefghijklmno" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const char *ptyminors = "0123456789abcdef"; + int num_minors = strlen(ptyminors); + int num_ptys = strlen(ptymajors) * num_minors; + struct termios tio; + + for (i = 0; i < num_ptys; i++) { + snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c", + ptymajors[i / num_minors], ptyminors[i % num_minors]); + snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c", + ptymajors[i / num_minors], ptyminors[i % num_minors]); + + if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) { + /* Try SCO style naming */ + snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i); + snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i); + if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) + continue; + } + + /* Open the slave side. */ + if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) { + close(*amaster); + return (-1); + } + /* set tty modes to a sane state for broken clients */ + if (tcgetattr(*amaster, &tio) != -1) { + tio.c_lflag |= (ECHO | ISIG | ICANON); + tio.c_oflag |= (OPOST | ONLCR); + tio.c_iflag |= ICRNL; + tcsetattr(*amaster, TCSANOW, &tio); + } + + return (0); + } + return (-1); +#endif +} + +#endif /* !defined(HAVE_OPENPTY) */ + diff --git a/crypto/openssh/openbsd-compat/bsd-snprintf.c b/crypto/openssh/openbsd-compat/bsd-snprintf.c new file mode 100644 index 0000000..04651e1 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-snprintf.c @@ -0,0 +1,805 @@ +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell (papowell@astart.com) + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions + */ + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * Andrew Tridgell (tridge@samba.org) Oct 1998 + * fixed handling of %.0f + * added test for HAVE_LONG_DOUBLE + * + * tridge@samba.org, idra@samba.org, April 2001 + * got rid of fcvt code (twas buggy and made testing harder) + * added C99 semantics + * + * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 + * actually print args for %g and %e + * + * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 + * Since includes.h isn't included here, VA_COPY has to be defined here. I don't + * see any include file that is guaranteed to be here, so I'm defining it + * locally. Fixes AIX and Solaris builds. + * + * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 + * put the ifdef for HAVE_VA_COPY in one place rather than in lots of + * functions + * + * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 + * Fix usage of va_list passed as an arg. Use __va_copy before using it + * when it exists. + * + * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 + * Fix incorrect zpadlen handling in fmtfp. + * Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it. + * few mods to make it easier to compile the tests. + * addedd the "Ollie" test to the floating point ones. + * + * Martin Pool (mbp@samba.org) April 2003 + * Remove NO_CONFIG_H so that the test case can be built within a source + * tree with less trouble. + * Remove unnecessary SAFE_FREE() definition. + * + * Martin Pool (mbp@samba.org) May 2003 + * Put in a prototype for dummy_snprintf() to quiet compiler warnings. + * + * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even + * if the C library has some snprintf functions already. + **************************************************************/ + +#include "includes.h" + +#if defined(BROKEN_SNPRINTF) /* For those with broken snprintf() */ +# undef HAVE_SNPRINTF +# undef HAVE_VSNPRINTF +#endif + +#ifndef VA_COPY +# ifdef HAVE_VA_COPY +# define VA_COPY(dest, src) va_copy(dest, src) +# else +# ifdef HAVE___VA_COPY +# define VA_COPY(dest, src) __va_copy(dest, src) +# else +# define VA_COPY(dest, src) (dest) = (src) +# endif +# endif +#endif + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) + +#include <ctype.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#ifdef HAVE_LONG_DOUBLE +# define LDOUBLE long double +#else +# define LDOUBLE double +#endif + +#ifdef HAVE_LONG_LONG +# define LLONG long long +#else +# define LLONG long +#endif + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 + +#define char_to_int(p) ((p)- '0') +#ifndef MAX +# define MAX(p,q) (((p) >= (q)) ? (p) : (q)) +#endif + +static size_t dopr(char *buffer, size_t maxlen, const char *format, + va_list args_in); +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + LLONG value, int base, int min, int max, int flags); +static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags); +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); + +static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) +{ + char ch; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + va_list args; + + VA_COPY(args, args_in); + + state = DP_S_DEFAULT; + currlen = flags = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) { + if (ch == '\0') + state = DP_S_DONE; + + switch(state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch (buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + min = 10*min + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; + } else { + state = DP_S_DOT; + } + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (max < 0) + max = 0; + max = 10*max + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + cflags = DP_C_LONG; + ch = *format++; + if (ch == 'l') { /* It's a long long */ + cflags = DP_C_LLONG; + ch = *format++; + } + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + if (cflags == DP_C_SHORT) + value = va_arg (args, int); + else if (cflags == DP_C_LONG) + value = va_arg (args, long int); + else if (cflags == DP_C_LLONG) + value = va_arg (args, LLONG); + else + value = va_arg (args, int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'o': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (long)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); + break; + case 'u': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (LLONG)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + case 'x': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (LLONG)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + /* um, floating point? */ + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'c': + dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); + break; + case 's': + strvalue = va_arg (args, char *); + if (!strvalue) strvalue = "(NULL)"; + if (max == -1) { + max = strlen(strvalue); + } + if (min > 0 && max >= 0 && min > max) max = min; + fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + strvalue = va_arg (args, void *); + fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); + break; + case 'n': + if (cflags == DP_C_SHORT) { + short int *num; + num = va_arg (args, short int *); + *num = currlen; + } else if (cflags == DP_C_LONG) { + long int *num; + num = va_arg (args, long int *); + *num = (long int)currlen; + } else if (cflags == DP_C_LLONG) { + LLONG *num; + num = va_arg (args, LLONG *); + *num = (LLONG)currlen; + } else { + int *num; + num = va_arg (args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch (buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* Unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + if (maxlen != 0) { + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else if (maxlen > 0) + buffer[maxlen - 1] = '\0'; + } + + return currlen; +} + +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + +#ifdef DEBUG_SNPRINTF + printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); +#endif + if (value == 0) { + value = "<NULL>"; + } + + for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while ((padlen > 0) && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + LLONG value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned LLONG uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if(!(flags & DP_F_UNSIGNED)) { + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } else { + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place); +#endif + + /* Spaces */ + while (spadlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + + if (value < 0) + result = -value; + + return result; +} + +static LDOUBLE POW10(int exp) +{ + LDOUBLE result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static LLONG ROUND(LDOUBLE value) +{ + LLONG intpart; + + intpart = (LLONG)value; + value = value - intpart; + if (value >= 0.5) intpart++; + + return intpart; +} + +/* a replacement for modf that doesn't need the math library. Should + be portable, but slow */ +static double my_modf(double x0, double *iptr) +{ + int i; + long l; + double x = x0; + double f = 1.0; + + for (i=0;i<100;i++) { + l = (long)x; + if (l <= (x+1) && l >= (x-1)) break; + x *= 0.1; + f *= 10.0; + } + + if (i == 100) { + /* yikes! the number is beyond what we can handle. What do we do? */ + (*iptr) = 0; + return 0; + } + + if (i != 0) { + double i2; + double ret; + + ret = my_modf(x0-l*f, &i2); + (*iptr) = l*f + i2; + return ret; + } + + (*iptr) = l; + return x - (*iptr); +} + + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags) +{ + int signvalue = 0; + double ufvalue; + char iconvert[311]; + char fconvert[311]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + int idx; + double intpart; + double fracpart; + double temp; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) { + signvalue = '-'; + } else { + if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ + signvalue = '+'; + } else { + if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + +#if 0 + if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ +#endif + + /* + * Sorry, we only support 16 digits past the decimal because of our + * conversion method + */ + if (max > 16) + max = 16; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + + temp = ufvalue; + my_modf(temp, &intpart); + + fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); + + if (fracpart >= POW10(max)) { + intpart++; + fracpart -= POW10(max); + } + + /* Convert integer part */ + do { + temp = intpart*0.1; + my_modf(temp, &intpart); + idx = (int) ((temp -intpart +0.05)* 10.0); + /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ + /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; + } while (intpart && (iplace < 311)); + if (iplace == 311) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + if (fracpart) + { + do { + temp = fracpart*0.1; + my_modf(temp, &fracpart); + idx = (int) ((temp -fracpart +0.05)* 10.0); + /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ + /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */ + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; + } while(fracpart && (fplace < 311)); + if (fplace == 311) fplace--; + } + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + +#ifdef DEBUG_SNPRINTF + printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); +#endif + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch (buffer, currlen, maxlen, '.'); + + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + } + + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) { + buffer[(*currlen)] = c; + } + (*currlen)++; +} +#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ + +#if !defined(HAVE_VSNPRINTF) +int vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + return dopr(str, count, fmt, args); +} +#endif + +#if !defined(HAVE_SNPRINTF) +int snprintf(char *str, size_t count, SNPRINTF_CONST char *fmt, ...) +{ + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + return ret; +} +#endif + diff --git a/crypto/openssh/openbsd-compat/bsd-waitpid.c b/crypto/openssh/openbsd-compat/bsd-waitpid.c new file mode 100644 index 0000000..40e6ffa --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-waitpid.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2000 Ben Lindstrom. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include "includes.h" + +#ifndef HAVE_WAITPID +#include <errno.h> +#include <sys/wait.h> +#include "bsd-waitpid.h" + +pid_t +waitpid(int pid, int *stat_loc, int options) +{ + union wait statusp; + pid_t wait_pid; + + if (pid <= 0) { + if (pid != -1) { + errno = EINVAL; + return (-1); + } + /* wait4() wants pid=0 for indiscriminate wait. */ + pid = 0; + } + wait_pid = wait4(pid, &statusp, options, NULL); + if (stat_loc) + *stat_loc = (int) statusp.w_status; + + return (wait_pid); +} + +#endif /* !HAVE_WAITPID */ diff --git a/crypto/openssh/openbsd-compat/bsd-waitpid.h b/crypto/openssh/openbsd-compat/bsd-waitpid.h new file mode 100644 index 0000000..2d853db --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-waitpid.h @@ -0,0 +1,51 @@ +/* $Id: bsd-waitpid.h,v 1.5 2003/08/29 16:59:52 mouring Exp $ */ + +/* + * Copyright (c) 2000 Ben Lindstrom. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + */ + +#ifndef _BSD_WAITPID_H +#define _BSD_WAITPID_H + +#ifndef HAVE_WAITPID +/* Clean out any potental issues */ +#undef WIFEXITED +#undef WIFSTOPPED +#undef WIFSIGNALED + +/* Define required functions to mimic a POSIX look and feel */ +#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */ +#define WIFEXITED(w) (!((_W_INT(w)) & 0377)) +#define WIFSTOPPED(w) ((_W_INT(w)) & 0100) +#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w)) +#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1) +#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1) +#define WCOREFLAG 0x80 +#define WCOREDUMP(w) ((_W_INT(w)) & WCOREFLAG) + +/* Prototype */ +pid_t waitpid(int, int *, int); + +#endif /* !HAVE_WAITPID */ +#endif /* _BSD_WAITPID_H */ diff --git a/crypto/openssh/openbsd-compat/daemon.c b/crypto/openssh/openbsd-compat/daemon.c new file mode 100644 index 0000000..e3a6886 --- /dev/null +++ b/crypto/openssh/openbsd-compat/daemon.c @@ -0,0 +1,92 @@ +/* $OpenBSD: daemon.c,v 1.6 2005/08/08 08:05:33 espie Exp $ */ +/*- + * 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/daemon.c */ + +#include "includes.h" + +#ifndef HAVE_DAEMON + +#include <sys/types.h> + +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif + +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +int +daemon(int nochdir, int noclose) +{ + int fd; + + switch (fork()) { + case -1: + return (-1); + case 0: +#ifdef HAVE_CYGWIN + register_9x_service(); +#endif + break; + default: +#ifdef HAVE_CYGWIN + /* + * This sleep avoids a race condition which kills the + * child process if parent is started by a NT/W2K service. + */ + sleep(1); +#endif + _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 /* !HAVE_DAEMON */ + diff --git a/crypto/openssh/openbsd-compat/dirname.c b/crypto/openssh/openbsd-compat/dirname.c new file mode 100644 index 0000000..30fcb49 --- /dev/null +++ b/crypto/openssh/openbsd-compat/dirname.c @@ -0,0 +1,72 @@ +/* $OpenBSD: dirname.c,v 1.13 2005/08/08 08:05:33 espie Exp $ */ + +/* + * Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/dirname.c */ + +#include "includes.h" +#ifndef HAVE_DIRNAME + +#include <errno.h> +#include <string.h> +#include <sys/param.h> + +char * +dirname(const char *path) +{ + static char dname[MAXPATHLEN]; + size_t len; + const char *endp; + + /* Empty or NULL string gets treated as "." */ + if (path == NULL || *path == '\0') { + dname[0] = '.'; + dname[1] = '\0'; + return (dname); + } + + /* Strip any trailing slashes */ + endp = path + strlen(path) - 1; + while (endp > path && *endp == '/') + endp--; + + /* Find the start of the dir */ + while (endp > path && *endp != '/') + endp--; + + /* Either the dir is "/" or there are no slashes */ + if (endp == path) { + dname[0] = *endp == '/' ? '/' : '.'; + dname[1] = '\0'; + return (dname); + } else { + /* Move forward past the separating slashes */ + do { + endp--; + } while (endp > path && *endp == '/'); + } + + len = endp - path + 1; + if (len >= sizeof(dname)) { + errno = ENAMETOOLONG; + return (NULL); + } + memcpy(dname, path, len); + dname[len] = '\0'; + return (dname); +} +#endif diff --git a/crypto/openssh/openbsd-compat/fake-queue.h b/crypto/openssh/openbsd-compat/fake-queue.h new file mode 100644 index 0000000..176fe31 --- /dev/null +++ b/crypto/openssh/openbsd-compat/fake-queue.h @@ -0,0 +1,584 @@ +/* $OpenBSD: queue.h,v 1.22 2001/06/23 04:39:35 angelos Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _FAKE_QUEUE_H_ +#define _FAKE_QUEUE_H_ + +/* + * Ignore all <sys/queue.h> since older platforms have broken/incomplete + * <sys/queue.h> that are too hard to work around. + */ +#undef SLIST_HEAD +#undef SLIST_HEAD_INITIALIZER +#undef SLIST_ENTRY +#undef SLIST_FIRST +#undef SLIST_END +#undef SLIST_EMPTY +#undef SLIST_NEXT +#undef SLIST_FOREACH +#undef SLIST_INIT +#undef SLIST_INSERT_AFTER +#undef SLIST_INSERT_HEAD +#undef SLIST_REMOVE_HEAD +#undef SLIST_REMOVE +#undef LIST_HEAD +#undef LIST_HEAD_INITIALIZER +#undef LIST_ENTRY +#undef LIST_FIRST +#undef LIST_END +#undef LIST_EMPTY +#undef LIST_NEXT +#undef LIST_FOREACH +#undef LIST_INIT +#undef LIST_INSERT_AFTER +#undef LIST_INSERT_BEFORE +#undef LIST_INSERT_HEAD +#undef LIST_REMOVE +#undef LIST_REPLACE +#undef SIMPLEQ_HEAD +#undef SIMPLEQ_HEAD_INITIALIZER +#undef SIMPLEQ_ENTRY +#undef SIMPLEQ_FIRST +#undef SIMPLEQ_END +#undef SIMPLEQ_EMPTY +#undef SIMPLEQ_NEXT +#undef SIMPLEQ_FOREACH +#undef SIMPLEQ_INIT +#undef SIMPLEQ_INSERT_HEAD +#undef SIMPLEQ_INSERT_TAIL +#undef SIMPLEQ_INSERT_AFTER +#undef SIMPLEQ_REMOVE_HEAD +#undef TAILQ_HEAD +#undef TAILQ_HEAD_INITIALIZER +#undef TAILQ_ENTRY +#undef TAILQ_FIRST +#undef TAILQ_END +#undef TAILQ_NEXT +#undef TAILQ_LAST +#undef TAILQ_PREV +#undef TAILQ_EMPTY +#undef TAILQ_FOREACH +#undef TAILQ_FOREACH_REVERSE +#undef TAILQ_INIT +#undef TAILQ_INSERT_HEAD +#undef TAILQ_INSERT_TAIL +#undef TAILQ_INSERT_AFTER +#undef TAILQ_INSERT_BEFORE +#undef TAILQ_REMOVE +#undef TAILQ_REPLACE +#undef CIRCLEQ_HEAD +#undef CIRCLEQ_HEAD_INITIALIZER +#undef CIRCLEQ_ENTRY +#undef CIRCLEQ_FIRST +#undef CIRCLEQ_LAST +#undef CIRCLEQ_END +#undef CIRCLEQ_NEXT +#undef CIRCLEQ_PREV +#undef CIRCLEQ_EMPTY +#undef CIRCLEQ_FOREACH +#undef CIRCLEQ_FOREACH_REVERSE +#undef CIRCLEQ_INIT +#undef CIRCLEQ_INSERT_AFTER +#undef CIRCLEQ_INSERT_BEFORE +#undef CIRCLEQ_INSERT_HEAD +#undef CIRCLEQ_INSERT_TAIL +#undef CIRCLEQ_REMOVE +#undef CIRCLEQ_REPLACE + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while( curelm->field.sle_next != (elm) ) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ + if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ +} while (0) + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue access methods + */ +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_END(head) ((void *)(head)) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define CIRCLEQ_EMPTY(head) \ + (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for((var) = CIRCLEQ_FIRST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_NEXT(var, field)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = CIRCLEQ_LAST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_PREV(var, field)) + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = CIRCLEQ_END(head); \ + (head)->cqh_last = CIRCLEQ_END(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = CIRCLEQ_END(head); \ + if ((head)->cqh_last == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = CIRCLEQ_END(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (0) + +#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ + CIRCLEQ_END(head)) \ + (head).cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ + CIRCLEQ_END(head)) \ + (head).cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ +} while (0) + +#endif /* !_FAKE_QUEUE_H_ */ diff --git a/crypto/openssh/openbsd-compat/fake-rfc2553.c b/crypto/openssh/openbsd-compat/fake-rfc2553.c new file mode 100644 index 0000000..b6ea3d2 --- /dev/null +++ b/crypto/openssh/openbsd-compat/fake-rfc2553.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 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. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#include "includes.h" + +#include <stdlib.h> +#include <string.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#ifndef HAVE_GETNAMEINFO +int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct hostent *hp; + char tmpserv[16]; + + if (serv != NULL) { + snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); + if (strlcpy(serv, tmpserv, servlen) >= servlen) + return (EAI_MEMORY); + } + + if (host != NULL) { + if (flags & NI_NUMERICHOST) { + if (strlcpy(host, inet_ntoa(sin->sin_addr), + hostlen) >= hostlen) + return (EAI_MEMORY); + else + return (0); + } else { + hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof(struct in_addr), AF_INET); + if (hp == NULL) + return (EAI_NODATA); + + if (strlcpy(host, hp->h_name, hostlen) >= hostlen) + return (EAI_MEMORY); + else + return (0); + } + } + return (0); +} +#endif /* !HAVE_GETNAMEINFO */ + +#ifndef HAVE_GAI_STRERROR +#ifdef HAVE_CONST_GAI_STRERROR_PROTO +const char * +#else +char * +#endif +gai_strerror(int err) +{ + switch (err) { + case EAI_NODATA: + return ("no address associated with name"); + case EAI_MEMORY: + return ("memory allocation failure."); + case EAI_NONAME: + return ("nodename nor servname provided, or not known"); + default: + return ("unknown/invalid error."); + } +} +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +void +freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + for(; ai != NULL;) { + next = ai->ai_next; + free(ai); + ai = next; + } +} +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETADDRINFO +static struct +addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) +{ + struct addrinfo *ai; + + ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in)); + if (ai == NULL) + return (NULL); + + memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in)); + + ai->ai_addr = (struct sockaddr *)(ai + 1); + /* XXX -- ssh doesn't use sa_len */ + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr->sa_family = ai->ai_family = AF_INET; + + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; + + /* XXX: the following is not generally correct, but does what we want */ + if (hints->ai_socktype) + ai->ai_socktype = hints->ai_socktype; + else + ai->ai_socktype = SOCK_STREAM; + + if (hints->ai_protocol) + ai->ai_protocol = hints->ai_protocol; + + return (ai); +} + +int +getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct hostent *hp; + struct servent *sp; + struct in_addr in; + int i; + long int port; + u_long addr; + + port = 0; + if (servname != NULL) { + char *cp; + + port = strtol(servname, &cp, 10); + if (port > 0 && port <= 65535 && *cp == '\0') + port = htons(port); + else if ((sp = getservbyname(servname, NULL)) != NULL) + port = sp->s_port; + else + port = 0; + } + + if (hints && hints->ai_flags & AI_PASSIVE) { + addr = htonl(0x00000000); + if (hostname && inet_aton(hostname, &in) != 0) + addr = in.s_addr; + *res = malloc_ai(port, addr, hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + if (!hostname) { + *res = malloc_ai(port, htonl(0x7f000001), hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + if (inet_aton(hostname, &in)) { + *res = malloc_ai(port, in.s_addr, hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + /* Don't try DNS if AI_NUMERICHOST is set */ + if (hints && hints->ai_flags & AI_NUMERICHOST) + return (EAI_NONAME); + + hp = gethostbyname(hostname); + if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { + struct addrinfo *cur, *prev; + + cur = prev = *res = NULL; + for (i = 0; hp->h_addr_list[i]; i++) { + struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; + + cur = malloc_ai(port, in->s_addr, hints); + if (cur == NULL) { + if (*res != NULL) + freeaddrinfo(*res); + return (EAI_MEMORY); + } + if (prev) + prev->ai_next = cur; + else + *res = cur; + + prev = cur; + } + return (0); + } + + return (EAI_NODATA); +} +#endif /* !HAVE_GETADDRINFO */ diff --git a/crypto/openssh/openbsd-compat/fake-rfc2553.h b/crypto/openssh/openbsd-compat/fake-rfc2553.h new file mode 100644 index 0000000..5c2ce5b --- /dev/null +++ b/crypto/openssh/openbsd-compat/fake-rfc2553.h @@ -0,0 +1,171 @@ +/* $Id: fake-rfc2553.h,v 1.13 2006/07/24 03:51:52 djm Exp $ */ + +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 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. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#ifndef _FAKE_RFC2553_H +#define _FAKE_RFC2553_H + +#include "includes.h" +#include <sys/types.h> +#if defined(HAVE_NETDB_H) +# include <netdb.h> +#endif + +/* + * First, socket and INET6 related definitions + */ +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +# define _SS_MAXSIZE 128 /* Implementation specific max size */ +# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) +struct sockaddr_storage { + struct sockaddr ss_sa; + char __ss_pad2[_SS_PADSIZE]; +}; +# define ss_family ss_sa.sa_family +#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +#ifndef IN6_IS_ADDR_LOOPBACK +# define IN6_IS_ADDR_LOOPBACK(a) \ + (((u_int32_t *)(a))[0] == 0 && ((u_int32_t *)(a))[1] == 0 && \ + ((u_int32_t *)(a))[2] == 0 && ((u_int32_t *)(a))[3] == htonl(1)) +#endif /* !IN6_IS_ADDR_LOOPBACK */ + +#ifndef HAVE_STRUCT_IN6_ADDR +struct in6_addr { + u_int8_t s6_addr[16]; +}; +#endif /* !HAVE_STRUCT_IN6_ADDR */ + +#ifndef HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 { + unsigned short sin6_family; + u_int16_t sin6_port; + u_int32_t sin6_flowinfo; + struct in6_addr sin6_addr; +}; +#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ + +#ifndef AF_INET6 +/* Define it to something that should never appear */ +#define AF_INET6 AF_MAX +#endif + +/* + * Next, RFC2553 name / address resolution API + */ + +#ifndef NI_NUMERICHOST +# define NI_NUMERICHOST (1) +#endif +#ifndef NI_NAMEREQD +# define NI_NAMEREQD (1<<1) +#endif +#ifndef NI_NUMERICSERV +# define NI_NUMERICSERV (1<<2) +#endif + +#ifndef AI_PASSIVE +# define AI_PASSIVE (1) +#endif +#ifndef AI_CANONNAME +# define AI_CANONNAME (1<<1) +#endif +#ifndef AI_NUMERICHOST +# define AI_NUMERICHOST (1<<2) +#endif + +#ifndef NI_MAXSERV +# define NI_MAXSERV 32 +#endif /* !NI_MAXSERV */ +#ifndef NI_MAXHOST +# define NI_MAXHOST 1025 +#endif /* !NI_MAXHOST */ + +#ifndef EAI_NODATA +# define EAI_NODATA (INT_MAX - 1) +#endif +#ifndef EAI_MEMORY +# define EAI_MEMORY (INT_MAX - 2) +#endif +#ifndef EAI_NONAME +# define EAI_NONAME (INT_MAX - 3) +#endif +#ifndef EAI_SYSTEM +# define EAI_SYSTEM (INT_MAX - 4) +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif /* !HAVE_STRUCT_ADDRINFO */ + +#ifndef HAVE_GETADDRINFO +#ifdef getaddrinfo +# undef getaddrinfo +#endif +#define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d)) +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +#endif /* !HAVE_GETADDRINFO */ + +#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO) +#define gai_strerror(a) (ssh_gai_strerror(a)) +char *gai_strerror(int); +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +#define freeaddrinfo(a) (ssh_freeaddrinfo(a)) +void freeaddrinfo(struct addrinfo *); +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETNAMEINFO +#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g)) +int getnameinfo(const struct sockaddr *, size_t, char *, size_t, + char *, size_t, int); +#endif /* !HAVE_GETNAMEINFO */ + +#endif /* !_FAKE_RFC2553_H */ + diff --git a/crypto/openssh/openbsd-compat/getcwd.c b/crypto/openssh/openbsd-compat/getcwd.c new file mode 100644 index 0000000..711cb9c --- /dev/null +++ b/crypto/openssh/openbsd-compat/getcwd.c @@ -0,0 +1,240 @@ +/* $OpenBSD: getcwd.c,v 1.14 2005/08/08 08:05:34 espie Exp $ */ +/* + * Copyright (c) 1989, 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/getcwd.c */ + +#include "includes.h" + +#if !defined(HAVE_GETCWD) + +#include <sys/param.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> +#include <sys/dir.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "includes.h" + +#define ISDOT(dp) \ + (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \ + (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) + +char * +getcwd(char *pt, size_t size) +{ + struct dirent *dp; + DIR *dir = NULL; + dev_t dev; + ino_t ino; + int first; + char *bpt, *bup; + struct stat s; + dev_t root_dev; + ino_t root_ino; + size_t ptsize, upsize; + int save_errno; + char *ept, *eup, *up; + + /* + * If no buffer specified by the user, allocate one as necessary. + * If a buffer is specified, the size has to be non-zero. The path + * is built from the end of the buffer backwards. + */ + if (pt) { + ptsize = 0; + if (!size) { + errno = EINVAL; + return (NULL); + } + ept = pt + size; + } else { + if ((pt = malloc(ptsize = MAXPATHLEN)) == NULL) + return (NULL); + ept = pt + ptsize; + } + bpt = ept - 1; + *bpt = '\0'; + + /* + * Allocate bytes for the string of "../"'s. + * Should always be enough (it's 340 levels). If it's not, allocate + * as necessary. Special * case the first stat, it's ".", not "..". + */ + if ((up = malloc(upsize = MAXPATHLEN)) == NULL) + goto err; + eup = up + upsize; + bup = up; + up[0] = '.'; + up[1] = '\0'; + + /* Save root values, so know when to stop. */ + if (stat("/", &s)) + goto err; + root_dev = s.st_dev; + root_ino = s.st_ino; + + errno = 0; /* XXX readdir has no error return. */ + + for (first = 1;; first = 0) { + /* Stat the current level. */ + if (lstat(up, &s)) + goto err; + + /* Save current node values. */ + ino = s.st_ino; + dev = s.st_dev; + + /* Check for reaching root. */ + if (root_dev == dev && root_ino == ino) { + *--bpt = '/'; + /* + * It's unclear that it's a requirement to copy the + * path to the beginning of the buffer, but it's always + * been that way and stuff would probably break. + */ + memmove(pt, bpt, ept - bpt); + free(up); + return (pt); + } + + /* + * Build pointer to the parent directory, allocating memory + * as necessary. Max length is 3 for "../", the largest + * possible component name, plus a trailing NUL. + */ + if (bup + 3 + MAXNAMLEN + 1 >= eup) { + char *nup; + + if ((nup = realloc(up, upsize *= 2)) == NULL) + goto err; + bup = nup + (bup - up); + up = nup; + eup = up + upsize; + } + *bup++ = '.'; + *bup++ = '.'; + *bup = '\0'; + + /* Open and stat parent directory. */ + if (!(dir = opendir(up)) || fstat(dirfd(dir), &s)) + goto err; + + /* Add trailing slash for next directory. */ + *bup++ = '/'; + + /* + * If it's a mount point, have to stat each element because + * the inode number in the directory is for the entry in the + * parent directory, not the inode number of the mounted file. + */ + save_errno = 0; + if (s.st_dev == dev) { + for (;;) { + if (!(dp = readdir(dir))) + goto notfound; + if (dp->d_fileno == ino) + break; + } + } else + for (;;) { + if (!(dp = readdir(dir))) + goto notfound; + if (ISDOT(dp)) + continue; + memcpy(bup, dp->d_name, dp->d_namlen + 1); + + /* Save the first error for later. */ + if (lstat(up, &s)) { + if (!save_errno) + save_errno = errno; + errno = 0; + continue; + } + if (s.st_dev == dev && s.st_ino == ino) + break; + } + + /* + * Check for length of the current name, preceding slash, + * leading slash. + */ + if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) { + size_t len; + char *npt; + + if (!ptsize) { + errno = ERANGE; + goto err; + } + len = ept - bpt; + if ((npt = realloc(pt, ptsize *= 2)) == NULL) + goto err; + bpt = npt + (bpt - pt); + pt = npt; + ept = pt + ptsize; + memmove(ept - len, bpt, len); + bpt = ept - len; + } + if (!first) + *--bpt = '/'; + bpt -= dp->d_namlen; + memcpy(bpt, dp->d_name, dp->d_namlen); + (void)closedir(dir); + + /* Truncate any file name. */ + *bup = '\0'; + } + +notfound: + /* + * If readdir set errno, use it, not any saved error; otherwise, + * didn't find the current directory in its parent directory, set + * errno to ENOENT. + */ + if (!errno) + errno = save_errno ? save_errno : ENOENT; + /* FALLTHROUGH */ +err: + save_errno = errno; + + if (ptsize) + free(pt); + free(up); + if (dir) + (void)closedir(dir); + + errno = save_errno; + + return (NULL); +} + +#endif /* !defined(HAVE_GETCWD) */ diff --git a/crypto/openssh/openbsd-compat/getgrouplist.c b/crypto/openssh/openbsd-compat/getgrouplist.c new file mode 100644 index 0000000..a57d7d3 --- /dev/null +++ b/crypto/openssh/openbsd-compat/getgrouplist.c @@ -0,0 +1,95 @@ +/* $OpenBSD: getgrouplist.c,v 1.12 2005/08/08 08:05:34 espie Exp $ */ +/* + * 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/getgrouplist.c */ + +#include "includes.h" + +#ifndef HAVE_GETGROUPLIST + +/* + * get credential + */ +#include <sys/types.h> +#include <string.h> +#include <unistd.h> +#include <grp.h> + +int +getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt) +{ + struct group *grp; + int i, ngroups; + int ret, maxgroups; + int bail; + + ret = 0; + ngroups = 0; + maxgroups = *grpcnt; + + /* + * install primary group + */ + if (ngroups >= maxgroups) { + *grpcnt = ngroups; + return (-1); + } + groups[ngroups++] = agroup; + + /* + * Scan the group file to find additional groups. + */ + setgrent(); + while ((grp = getgrent())) { + if (grp->gr_gid == agroup) + continue; + for (bail = 0, i = 0; bail == 0 && i < ngroups; i++) + if (groups[i] == grp->gr_gid) + bail = 1; + if (bail) + continue; + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], uname)) { + if (ngroups >= maxgroups) { + ret = -1; + goto out; + } + groups[ngroups++] = grp->gr_gid; + break; + } + } + } +out: + endgrent(); + *grpcnt = ngroups; + return (ret); +} + +#endif /* HAVE_GETGROUPLIST */ diff --git a/crypto/openssh/openbsd-compat/getopt.c b/crypto/openssh/openbsd-compat/getopt.c new file mode 100644 index 0000000..5450e43 --- /dev/null +++ b/crypto/openssh/openbsd-compat/getopt.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */ + +#include "includes.h" +#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: getopt.c,v 1.5 2003/06/02 20:18:37 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int BSDopterr = 1, /* if error message should be printed */ + BSDoptind = 1, /* index into parent argv vector */ + BSDoptopt, /* character checked for validity */ + BSDoptreset; /* reset getopt */ +char *BSDoptarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +BSDgetopt(nargc, nargv, ostr) + int nargc; + char * const *nargv; + const char *ostr; +{ + extern char *__progname; + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + if (ostr == NULL) + return (-1); + + if (BSDoptreset || !*place) { /* update scanning pointer */ + BSDoptreset = 0; + if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++BSDoptind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((BSDoptopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, BSDoptopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (BSDoptopt == (int)'-') + return (-1); + if (!*place) + ++BSDoptind; + if (BSDopterr && *ostr != ':') + (void)fprintf(stderr, + "%s: illegal option -- %c\n", __progname, BSDoptopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + BSDoptarg = NULL; + if (!*place) + ++BSDoptind; + } + else { /* need an argument */ + if (*place) /* no white space */ + BSDoptarg = place; + else if (nargc <= ++BSDoptind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (BSDopterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + __progname, BSDoptopt); + return (BADCH); + } + else /* white space */ + BSDoptarg = nargv[BSDoptind]; + place = EMSG; + ++BSDoptind; + } + return (BSDoptopt); /* dump back option letter */ +} + +#endif /* !defined(HAVE_GETOPT) || !defined(HAVE_OPTRESET) */ diff --git a/crypto/openssh/openbsd-compat/getrrsetbyname.c b/crypto/openssh/openbsd-compat/getrrsetbyname.c new file mode 100644 index 0000000..6c86e02 --- /dev/null +++ b/crypto/openssh/openbsd-compat/getrrsetbyname.c @@ -0,0 +1,612 @@ +/* $OpenBSD: getrrsetbyname.c,v 1.10 2005/03/30 02:58:28 tedu Exp $ */ + +/* + * Copyright (c) 2001 Jakob Schlyter. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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) 1999-2001 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */ + +#include "includes.h" + +#ifndef HAVE_GETRRSETBYNAME + +#include <stdlib.h> +#include <string.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "getrrsetbyname.h" + +#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO +extern int h_errno; +#endif + +/* We don't need multithread support here */ +#ifdef _THREAD_PRIVATE +# undef _THREAD_PRIVATE +#endif +#define _THREAD_PRIVATE(a,b,c) (c) + +/* to avoid conflicts where a platform already has _res */ +#ifdef _res +# undef _res +#endif +#define _res _compat_res + +struct __res_state _res; + +/* Necessary functions and macros */ + +/* + * Inline versions of get/put short/long. Pointer is advanced. + * + * These macros demonstrate the property of C whereby it can be + * portable or it can be elegant but rarely both. + */ + +#ifndef INT32SZ +# define INT32SZ 4 +#endif +#ifndef INT16SZ +# define INT16SZ 2 +#endif + +#ifndef GETSHORT +#define GETSHORT(s, cp) { \ + register u_char *t_cp = (u_char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += INT16SZ; \ +} +#endif + +#ifndef GETLONG +#define GETLONG(l, cp) { \ + register u_char *t_cp = (u_char *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += INT32SZ; \ +} +#endif + +/* + * Routines to insert/extract short/long's. + */ + +#ifndef HAVE__GETSHORT +static u_int16_t +_getshort(msgp) + register const u_char *msgp; +{ + register u_int16_t u; + + GETSHORT(u, msgp); + return (u); +} +#elif defined(HAVE_DECL__GETSHORT) && (HAVE_DECL__GETSHORT == 0) +u_int16_t _getshort(register const u_char *); +#endif + +#ifndef HAVE__GETLONG +static u_int32_t +_getlong(msgp) + register const u_char *msgp; +{ + register u_int32_t u; + + GETLONG(u, msgp); + return (u); +} +#elif defined(HAVE_DECL__GETLONG) && (HAVE_DECL__GETLONG == 0) +u_int32_t _getlong(register const u_char *); +#endif + +/* ************** */ + +#define ANSWER_BUFFER_SIZE 1024*64 + +struct dns_query { + char *name; + u_int16_t type; + u_int16_t class; + struct dns_query *next; +}; + +struct dns_rr { + char *name; + u_int16_t type; + u_int16_t class; + u_int16_t ttl; + u_int16_t size; + void *rdata; + struct dns_rr *next; +}; + +struct dns_response { + HEADER header; + struct dns_query *query; + struct dns_rr *answer; + struct dns_rr *authority; + struct dns_rr *additional; +}; + +static struct dns_response *parse_dns_response(const u_char *, int); +static struct dns_query *parse_dns_qsection(const u_char *, int, + const u_char **, int); +static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **, + int); + +static void free_dns_query(struct dns_query *); +static void free_dns_rr(struct dns_rr *); +static void free_dns_response(struct dns_response *); + +static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t); + +int +getrrsetbyname(const char *hostname, unsigned int rdclass, + unsigned int rdtype, unsigned int flags, + struct rrsetinfo **res) +{ + struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); + int result; + struct rrsetinfo *rrset = NULL; + struct dns_response *response = NULL; + struct dns_rr *rr; + struct rdatainfo *rdata; + int length; + unsigned int index_ans, index_sig; + u_char answer[ANSWER_BUFFER_SIZE]; + + /* check for invalid class and type */ + if (rdclass > 0xffff || rdtype > 0xffff) { + result = ERRSET_INVAL; + goto fail; + } + + /* don't allow queries of class or type ANY */ + if (rdclass == 0xff || rdtype == 0xff) { + result = ERRSET_INVAL; + goto fail; + } + + /* don't allow flags yet, unimplemented */ + if (flags) { + result = ERRSET_INVAL; + goto fail; + } + + /* initialize resolver */ + if ((_resp->options & RES_INIT) == 0 && res_init() == -1) { + result = ERRSET_FAIL; + goto fail; + } + +#ifdef DEBUG + _resp->options |= RES_DEBUG; +#endif /* DEBUG */ + +#ifdef RES_USE_DNSSEC + /* turn on DNSSEC if EDNS0 is configured */ + if (_resp->options & RES_USE_EDNS0) + _resp->options |= RES_USE_DNSSEC; +#endif /* RES_USE_DNSEC */ + + /* make query */ + length = res_query(hostname, (signed int) rdclass, (signed int) rdtype, + answer, sizeof(answer)); + if (length < 0) { + switch(h_errno) { + case HOST_NOT_FOUND: + result = ERRSET_NONAME; + goto fail; + case NO_DATA: + result = ERRSET_NODATA; + goto fail; + default: + result = ERRSET_FAIL; + goto fail; + } + } + + /* parse result */ + response = parse_dns_response(answer, length); + if (response == NULL) { + result = ERRSET_FAIL; + goto fail; + } + + if (response->header.qdcount != 1) { + result = ERRSET_FAIL; + goto fail; + } + + /* initialize rrset */ + rrset = calloc(1, sizeof(struct rrsetinfo)); + if (rrset == NULL) { + result = ERRSET_NOMEMORY; + goto fail; + } + rrset->rri_rdclass = response->query->class; + rrset->rri_rdtype = response->query->type; + rrset->rri_ttl = response->answer->ttl; + rrset->rri_nrdatas = response->header.ancount; + +#ifdef HAVE_HEADER_AD + /* check for authenticated data */ + if (response->header.ad == 1) + rrset->rri_flags |= RRSET_VALIDATED; +#endif + + /* copy name from answer section */ + rrset->rri_name = strdup(response->answer->name); + if (rrset->rri_name == NULL) { + result = ERRSET_NOMEMORY; + goto fail; + } + + /* count answers */ + rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass, + rrset->rri_rdtype); + rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass, + T_SIG); + + /* allocate memory for answers */ + rrset->rri_rdatas = calloc(rrset->rri_nrdatas, + sizeof(struct rdatainfo)); + if (rrset->rri_rdatas == NULL) { + result = ERRSET_NOMEMORY; + goto fail; + } + + /* allocate memory for signatures */ + rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo)); + if (rrset->rri_sigs == NULL) { + result = ERRSET_NOMEMORY; + goto fail; + } + + /* copy answers & signatures */ + for (rr = response->answer, index_ans = 0, index_sig = 0; + rr; rr = rr->next) { + + rdata = NULL; + + if (rr->class == rrset->rri_rdclass && + rr->type == rrset->rri_rdtype) + rdata = &rrset->rri_rdatas[index_ans++]; + + if (rr->class == rrset->rri_rdclass && + rr->type == T_SIG) + rdata = &rrset->rri_sigs[index_sig++]; + + if (rdata) { + rdata->rdi_length = rr->size; + rdata->rdi_data = malloc(rr->size); + + if (rdata->rdi_data == NULL) { + result = ERRSET_NOMEMORY; + goto fail; + } + memcpy(rdata->rdi_data, rr->rdata, rr->size); + } + } + free_dns_response(response); + + *res = rrset; + return (ERRSET_SUCCESS); + +fail: + if (rrset != NULL) + freerrset(rrset); + if (response != NULL) + free_dns_response(response); + return (result); +} + +void +freerrset(struct rrsetinfo *rrset) +{ + u_int16_t i; + + if (rrset == NULL) + return; + + if (rrset->rri_rdatas) { + for (i = 0; i < rrset->rri_nrdatas; i++) { + if (rrset->rri_rdatas[i].rdi_data == NULL) + break; + free(rrset->rri_rdatas[i].rdi_data); + } + free(rrset->rri_rdatas); + } + + if (rrset->rri_sigs) { + for (i = 0; i < rrset->rri_nsigs; i++) { + if (rrset->rri_sigs[i].rdi_data == NULL) + break; + free(rrset->rri_sigs[i].rdi_data); + } + free(rrset->rri_sigs); + } + + if (rrset->rri_name) + free(rrset->rri_name); + free(rrset); +} + +/* + * DNS response parsing routines + */ +static struct dns_response * +parse_dns_response(const u_char *answer, int size) +{ + struct dns_response *resp; + const u_char *cp; + + /* allocate memory for the response */ + resp = calloc(1, sizeof(*resp)); + if (resp == NULL) + return (NULL); + + /* initialize current pointer */ + cp = answer; + + /* copy header */ + memcpy(&resp->header, cp, HFIXEDSZ); + cp += HFIXEDSZ; + + /* fix header byte order */ + resp->header.qdcount = ntohs(resp->header.qdcount); + resp->header.ancount = ntohs(resp->header.ancount); + resp->header.nscount = ntohs(resp->header.nscount); + resp->header.arcount = ntohs(resp->header.arcount); + + /* there must be at least one query */ + if (resp->header.qdcount < 1) { + free_dns_response(resp); + return (NULL); + } + + /* parse query section */ + resp->query = parse_dns_qsection(answer, size, &cp, + resp->header.qdcount); + if (resp->header.qdcount && resp->query == NULL) { + free_dns_response(resp); + return (NULL); + } + + /* parse answer section */ + resp->answer = parse_dns_rrsection(answer, size, &cp, + resp->header.ancount); + if (resp->header.ancount && resp->answer == NULL) { + free_dns_response(resp); + return (NULL); + } + + /* parse authority section */ + resp->authority = parse_dns_rrsection(answer, size, &cp, + resp->header.nscount); + if (resp->header.nscount && resp->authority == NULL) { + free_dns_response(resp); + return (NULL); + } + + /* parse additional section */ + resp->additional = parse_dns_rrsection(answer, size, &cp, + resp->header.arcount); + if (resp->header.arcount && resp->additional == NULL) { + free_dns_response(resp); + return (NULL); + } + + return (resp); +} + +static struct dns_query * +parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count) +{ + struct dns_query *head, *curr, *prev; + int i, length; + char name[MAXDNAME]; + + for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { + + /* allocate and initialize struct */ + curr = calloc(1, sizeof(struct dns_query)); + if (curr == NULL) { + free_dns_query(head); + return (NULL); + } + if (head == NULL) + head = curr; + if (prev != NULL) + prev->next = curr; + + /* name */ + length = dn_expand(answer, answer + size, *cp, name, + sizeof(name)); + if (length < 0) { + free_dns_query(head); + return (NULL); + } + curr->name = strdup(name); + if (curr->name == NULL) { + free_dns_query(head); + return (NULL); + } + *cp += length; + + /* type */ + curr->type = _getshort(*cp); + *cp += INT16SZ; + + /* class */ + curr->class = _getshort(*cp); + *cp += INT16SZ; + } + + return (head); +} + +static struct dns_rr * +parse_dns_rrsection(const u_char *answer, int size, const u_char **cp, + int count) +{ + struct dns_rr *head, *curr, *prev; + int i, length; + char name[MAXDNAME]; + + for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { + + /* allocate and initialize struct */ + curr = calloc(1, sizeof(struct dns_rr)); + if (curr == NULL) { + free_dns_rr(head); + return (NULL); + } + if (head == NULL) + head = curr; + if (prev != NULL) + prev->next = curr; + + /* name */ + length = dn_expand(answer, answer + size, *cp, name, + sizeof(name)); + if (length < 0) { + free_dns_rr(head); + return (NULL); + } + curr->name = strdup(name); + if (curr->name == NULL) { + free_dns_rr(head); + return (NULL); + } + *cp += length; + + /* type */ + curr->type = _getshort(*cp); + *cp += INT16SZ; + + /* class */ + curr->class = _getshort(*cp); + *cp += INT16SZ; + + /* ttl */ + curr->ttl = _getlong(*cp); + *cp += INT32SZ; + + /* rdata size */ + curr->size = _getshort(*cp); + *cp += INT16SZ; + + /* rdata itself */ + curr->rdata = malloc(curr->size); + if (curr->rdata == NULL) { + free_dns_rr(head); + return (NULL); + } + memcpy(curr->rdata, *cp, curr->size); + *cp += curr->size; + } + + return (head); +} + +static void +free_dns_query(struct dns_query *p) +{ + if (p == NULL) + return; + + if (p->name) + free(p->name); + free_dns_query(p->next); + free(p); +} + +static void +free_dns_rr(struct dns_rr *p) +{ + if (p == NULL) + return; + + if (p->name) + free(p->name); + if (p->rdata) + free(p->rdata); + free_dns_rr(p->next); + free(p); +} + +static void +free_dns_response(struct dns_response *p) +{ + if (p == NULL) + return; + + free_dns_query(p->query); + free_dns_rr(p->answer); + free_dns_rr(p->authority); + free_dns_rr(p->additional); + free(p); +} + +static int +count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type) +{ + int n = 0; + + while(p) { + if (p->class == class && p->type == type) + n++; + p = p->next; + } + + return (n); +} + +#endif /* !defined(HAVE_GETRRSETBYNAME) */ diff --git a/crypto/openssh/openbsd-compat/getrrsetbyname.h b/crypto/openssh/openbsd-compat/getrrsetbyname.h new file mode 100644 index 0000000..39995b6 --- /dev/null +++ b/crypto/openssh/openbsd-compat/getrrsetbyname.h @@ -0,0 +1,110 @@ +/* OPENBSD BASED ON : include/netdb.h */ + +/* $OpenBSD: getrrsetbyname.c,v 1.4 2001/08/16 18:16:43 ho Exp $ */ + +/* + * Copyright (c) 2001 Jakob Schlyter. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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) 1999-2001 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 _GETRRSETBYNAME_H +#define _GETRRSETBYNAME_H + +#include "includes.h" + +#ifndef HAVE_GETRRSETBYNAME + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <netdb.h> +#include <resolv.h> + +#ifndef HFIXEDSZ +#define HFIXEDSZ 12 +#endif + +#ifndef T_SIG +#define T_SIG 24 +#endif + +/* + * Flags for getrrsetbyname() + */ +#ifndef RRSET_VALIDATED +# define RRSET_VALIDATED 1 +#endif + +/* + * Return codes for getrrsetbyname() + */ +#ifndef ERRSET_SUCCESS +# define ERRSET_SUCCESS 0 +# define ERRSET_NOMEMORY 1 +# define ERRSET_FAIL 2 +# define ERRSET_INVAL 3 +# define ERRSET_NONAME 4 +# define ERRSET_NODATA 5 +#endif + +struct rdatainfo { + unsigned int rdi_length; /* length of data */ + unsigned char *rdi_data; /* record data */ +}; + +struct rrsetinfo { + unsigned int rri_flags; /* RRSET_VALIDATED ... */ + unsigned int rri_rdclass; /* class number */ + unsigned int rri_rdtype; /* RR type number */ + unsigned int rri_ttl; /* time to live */ + unsigned int rri_nrdatas; /* size of rdatas array */ + unsigned int rri_nsigs; /* size of sigs array */ + char *rri_name; /* canonical name */ + struct rdatainfo *rri_rdatas; /* individual records */ + struct rdatainfo *rri_sigs; /* individual signatures */ +}; + +int getrrsetbyname(const char *, unsigned int, unsigned int, unsigned int, struct rrsetinfo **); +void freerrset(struct rrsetinfo *); + +#endif /* !defined(HAVE_GETRRSETBYNAME) */ + +#endif /* _GETRRSETBYNAME_H */ diff --git a/crypto/openssh/openbsd-compat/glob.c b/crypto/openssh/openbsd-compat/glob.c new file mode 100644 index 0000000..b3dd2b1 --- /dev/null +++ b/crypto/openssh/openbsd-compat/glob.c @@ -0,0 +1,873 @@ +/* $OpenBSD: glob.c,v 1.25 2005/08/08 08:05:34 espie Exp $ */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * 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 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/glob.c */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#include <dirent.h> +#include <ctype.h> +#include <errno.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ + !defined(GLOB_HAS_GL_MATCHC) || \ + !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 + +static long +get_arg_max(void) +{ +#ifdef ARG_MAX + return(ARG_MAX); +#elif defined(HAVE_SYSCONF) && defined(_SC_ARG_MAX) + return(sysconf(_SC_ARG_MAX)); +#else + return(256); /* XXX: arbitrary */ +#endif +} + +/* + * glob(3) -- a superset of the one defined in POSIX 1003.2. + * + * The [!...] convention to negate a range is supported (SysV, Posix, ksh). + * + * Optional extra services, controlled by flags not defined by POSIX: + * + * GLOB_QUOTE: + * Escaping convention: \ inhibits any special meaning the following + * character might have (except \ at end of string is retained). + * GLOB_MAGCHAR: + * Set in gl_flags if pattern contained a globbing character. + * GLOB_NOMAGIC: + * Same as GLOB_NOCHECK, but it will only append pattern if it did + * not contain any magic characters. [Used in csh style globbing] + * GLOB_ALTDIRFUNC: + * Use alternately specified directory access functions. + * GLOB_TILDE: + * expand ~user/foo to the /home/dir/of/user/foo + * GLOB_BRACE: + * expand {1,2}{a,b} to 1a 1b 2a 2b + * gl_matchc: + * Number of matches in the current invocation of glob. + */ + + +#define DOLLAR '$' +#define DOT '.' +#define EOS '\0' +#define LBRACKET '[' +#define NOT '!' +#define QUESTION '?' +#define QUOTE '\\' +#define RANGE '-' +#define RBRACKET ']' +#define SEP '/' +#define STAR '*' +#undef TILDE /* Some platforms may already define it */ +#define TILDE '~' +#define UNDERSCORE '_' +#define LBRACE '{' +#define RBRACE '}' +#define SLASH '/' +#define COMMA ',' + +#ifndef DEBUG + +#define M_QUOTE 0x8000 +#define M_PROTECT 0x4000 +#define M_MASK 0xffff +#define M_ASCII 0x00ff + +typedef u_short Char; + +#else + +#define M_QUOTE 0x80 +#define M_PROTECT 0x40 +#define M_MASK 0xff +#define M_ASCII 0x7f + +typedef char Char; + +#endif + + +#define CHAR(c) ((Char)((c)&M_ASCII)) +#define META(c) ((Char)((c)|M_QUOTE)) +#define M_ALL META('*') +#define M_END META(']') +#define M_NOT META('!') +#define M_ONE META('?') +#define M_RNG META('-') +#define M_SET META('[') +#define ismeta(c) (((c)&M_QUOTE) != 0) + + +static int compare(const void *, const void *); +static int g_Ctoc(const Char *, char *, u_int); +static int g_lstat(Char *, struct stat *, glob_t *); +static DIR *g_opendir(Char *, glob_t *); +static Char *g_strchr(Char *, int); +static int g_stat(Char *, struct stat *, glob_t *); +static int glob0(const Char *, glob_t *); +static int glob1(Char *, Char *, glob_t *, size_t *); +static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, + glob_t *, size_t *); +static int glob3(Char *, Char *, Char *, Char *, Char *, Char *, + Char *, Char *, glob_t *, size_t *); +static int globextend(const Char *, glob_t *, size_t *); +static const Char * + globtilde(const Char *, Char *, size_t, glob_t *); +static int globexp1(const Char *, glob_t *); +static int globexp2(const Char *, const Char *, glob_t *, int *); +static int match(Char *, Char *, Char *); +#ifdef DEBUG +static void qprintf(const char *, Char *); +#endif + +int +glob(const char *pattern, int flags, int (*errfunc)(const char *, int), + glob_t *pglob) +{ + const u_char *patnext; + int c; + Char *bufnext, *bufend, patbuf[MAXPATHLEN]; + + patnext = (u_char *) pattern; + if (!(flags & GLOB_APPEND)) { + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_offs = 0; + } + pglob->gl_flags = flags & ~GLOB_MAGCHAR; + pglob->gl_errfunc = errfunc; + pglob->gl_matchc = 0; + + bufnext = patbuf; + bufend = bufnext + MAXPATHLEN - 1; + if (flags & GLOB_NOESCAPE) + while (bufnext < bufend && (c = *patnext++) != EOS) + *bufnext++ = c; + else { + /* Protect the quoted characters. */ + while (bufnext < bufend && (c = *patnext++) != EOS) + if (c == QUOTE) { + if ((c = *patnext++) == EOS) { + c = QUOTE; + --patnext; + } + *bufnext++ = c | M_PROTECT; + } else + *bufnext++ = c; + } + *bufnext = EOS; + + if (flags & GLOB_BRACE) + return globexp1(patbuf, pglob); + else + return glob0(patbuf, pglob); +} + +/* + * Expand recursively a glob {} pattern. When there is no more expansion + * invoke the standard globbing routine to glob the rest of the magic + * characters + */ +static int +globexp1(const Char *pattern, glob_t *pglob) +{ + const Char* ptr = pattern; + int rv; + + /* Protect a single {}, for find(1), like csh */ + if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) + return glob0(pattern, pglob); + + while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) + if (!globexp2(ptr, pattern, pglob, &rv)) + return rv; + + return glob0(pattern, pglob); +} + + +/* + * Recursive brace globbing helper. Tries to expand a single brace. + * If it succeeds then it invokes globexp1 with the new pattern. + * If it fails then it tries to glob the rest of the pattern and returns. + */ +static int +globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) +{ + int i; + Char *lm, *ls; + const Char *pe, *pm, *pl; + Char patbuf[MAXPATHLEN]; + + /* copy part up to the brace */ + for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) + ; + *lm = EOS; + ls = lm; + + /* Find the balanced brace */ + for (i = 0, pe = ++ptr; *pe; pe++) + if (*pe == LBRACKET) { + /* Ignore everything between [] */ + for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) + ; + if (*pe == EOS) { + /* + * We could not find a matching RBRACKET. + * Ignore and just look for RBRACE + */ + pe = pm; + } + } else if (*pe == LBRACE) + i++; + else if (*pe == RBRACE) { + if (i == 0) + break; + i--; + } + + /* Non matching braces; just glob the pattern */ + if (i != 0 || *pe == EOS) { + *rv = glob0(patbuf, pglob); + return 0; + } + + for (i = 0, pl = pm = ptr; pm <= pe; pm++) { + switch (*pm) { + case LBRACKET: + /* Ignore everything between [] */ + for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) + ; + if (*pm == EOS) { + /* + * We could not find a matching RBRACKET. + * Ignore and just look for RBRACE + */ + pm = pl; + } + break; + + case LBRACE: + i++; + break; + + case RBRACE: + if (i) { + i--; + break; + } + /* FALLTHROUGH */ + case COMMA: + if (i && *pm == COMMA) + break; + else { + /* Append the current string */ + for (lm = ls; (pl < pm); *lm++ = *pl++) + ; + + /* + * Append the rest of the pattern after the + * closing brace + */ + for (pl = pe + 1; (*lm++ = *pl++) != EOS; ) + ; + + /* Expand the current pattern */ +#ifdef DEBUG + qprintf("globexp2:", patbuf); +#endif + *rv = globexp1(patbuf, pglob); + + /* move after the comma, to the next string */ + pl = pm + 1; + } + break; + + default: + break; + } + } + *rv = 0; + return 0; +} + + + +/* + * expand tilde from the passwd file. + */ +static const Char * +globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) +{ + struct passwd *pwd; + char *h; + const Char *p; + Char *b, *eb; + + if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) + return pattern; + + /* Copy up to the end of the string or / */ + eb = &patbuf[patbuf_len - 1]; + for (p = pattern + 1, h = (char *) patbuf; + h < (char *)eb && *p && *p != SLASH; *h++ = *p++) + ; + + *h = EOS; + +#if 0 + if (h == (char *)eb) + return what; +#endif + + if (((char *) patbuf)[0] == EOS) { + /* + * handle a plain ~ or ~/ by expanding $HOME + * first and then trying the password file + */ +#if 0 + if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { +#endif + if ((getuid() != geteuid()) || (h = getenv("HOME")) == NULL) { + if ((pwd = getpwuid(getuid())) == NULL) + return pattern; + else + h = pwd->pw_dir; + } + } else { + /* + * Expand a ~user + */ + if ((pwd = getpwnam((char*) patbuf)) == NULL) + return pattern; + else + h = pwd->pw_dir; + } + + /* Copy the home directory */ + for (b = patbuf; b < eb && *h; *b++ = *h++) + ; + + /* Append the rest of the pattern */ + while (b < eb && (*b++ = *p++) != EOS) + ; + *b = EOS; + + return patbuf; +} + + +/* + * The main glob() routine: compiles the pattern (optionally processing + * quotes), calls glob1() to do the real pattern matching, and finally + * sorts the list (unless unsorted operation is requested). Returns 0 + * if things went well, nonzero if errors occurred. It is not an error + * to find no matches. + */ +static int +glob0(const Char *pattern, glob_t *pglob) +{ + const Char *qpatnext; + int c, err, oldpathc; + Char *bufnext, patbuf[MAXPATHLEN]; + size_t limit = 0; + + qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); + oldpathc = pglob->gl_pathc; + bufnext = patbuf; + + /* We don't need to check for buffer overflow any more. */ + while ((c = *qpatnext++) != EOS) { + switch (c) { + case LBRACKET: + c = *qpatnext; + if (c == NOT) + ++qpatnext; + if (*qpatnext == EOS || + g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { + *bufnext++ = LBRACKET; + if (c == NOT) + --qpatnext; + break; + } + *bufnext++ = M_SET; + if (c == NOT) + *bufnext++ = M_NOT; + c = *qpatnext++; + do { + *bufnext++ = CHAR(c); + if (*qpatnext == RANGE && + (c = qpatnext[1]) != RBRACKET) { + *bufnext++ = M_RNG; + *bufnext++ = CHAR(c); + qpatnext += 2; + } + } while ((c = *qpatnext++) != RBRACKET); + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_END; + break; + case QUESTION: + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_ONE; + break; + case STAR: + pglob->gl_flags |= GLOB_MAGCHAR; + /* collapse adjacent stars to one, + * to avoid exponential behavior + */ + if (bufnext == patbuf || bufnext[-1] != M_ALL) + *bufnext++ = M_ALL; + break; + default: + *bufnext++ = CHAR(c); + break; + } + } + *bufnext = EOS; +#ifdef DEBUG + qprintf("glob0:", patbuf); +#endif + + if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) + return(err); + + /* + * If there was no match we are going to append the pattern + * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified + * and the pattern did not contain any magic characters + * GLOB_NOMAGIC is there just for compatibility with csh. + */ + if (pglob->gl_pathc == oldpathc) { + if ((pglob->gl_flags & GLOB_NOCHECK) || + ((pglob->gl_flags & GLOB_NOMAGIC) && + !(pglob->gl_flags & GLOB_MAGCHAR))) + return(globextend(pattern, pglob, &limit)); + else + return(GLOB_NOMATCH); + } + if (!(pglob->gl_flags & GLOB_NOSORT)) + qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, + pglob->gl_pathc - oldpathc, sizeof(char *), compare); + return(0); +} + +static int +compare(const void *p, const void *q) +{ + return(strcmp(*(char **)p, *(char **)q)); +} + +static int +glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) +{ + Char pathbuf[MAXPATHLEN]; + + /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ + if (*pattern == EOS) + return(0); + return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, + pathbuf, pathbuf+MAXPATHLEN-1, + pattern, pattern_last, pglob, limitp)); +} + +/* + * The functions glob2 and glob3 are mutually recursive; there is one level + * of recursion for each segment in the pattern that contains one or more + * meta characters. + */ +static int +glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, + Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) +{ + struct stat sb; + Char *p, *q; + int anymeta; + + /* + * Loop over pattern segments until end of pattern or until + * segment with meta character found. + */ + for (anymeta = 0;;) { + if (*pattern == EOS) { /* End of pattern? */ + *pathend = EOS; + if (g_lstat(pathbuf, &sb, pglob)) + return(0); + + if (((pglob->gl_flags & GLOB_MARK) && + pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || + (S_ISLNK(sb.st_mode) && + (g_stat(pathbuf, &sb, pglob) == 0) && + S_ISDIR(sb.st_mode)))) { + if (pathend+1 > pathend_last) + return (1); + *pathend++ = SEP; + *pathend = EOS; + } + ++pglob->gl_matchc; + return(globextend(pathbuf, pglob, limitp)); + } + + /* Find end of next segment, copy tentatively to pathend. */ + q = pathend; + p = pattern; + while (*p != EOS && *p != SEP) { + if (ismeta(*p)) + anymeta = 1; + if (q+1 > pathend_last) + return (1); + *q++ = *p++; + } + + if (!anymeta) { /* No expansion, do next segment. */ + pathend = q; + pattern = p; + while (*pattern == SEP) { + if (pathend+1 > pathend_last) + return (1); + *pathend++ = *pattern++; + } + } else + /* Need expansion, recurse. */ + return(glob3(pathbuf, pathbuf_last, pathend, + pathend_last, pattern, pattern_last, + p, pattern_last, pglob, limitp)); + } + /* NOTREACHED */ +} + +static int +glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, + Char *pattern, Char *pattern_last, Char *restpattern, + Char *restpattern_last, glob_t *pglob, size_t *limitp) +{ + struct dirent *dp; + DIR *dirp; + int err; + char buf[MAXPATHLEN]; + + /* + * The readdirfunc declaration can't be prototyped, because it is + * assigned, below, to two functions which are prototyped in glob.h + * and dirent.h as taking pointers to differently typed opaque + * structures. + */ + struct dirent *(*readdirfunc)(void *); + + if (pathend > pathend_last) + return (1); + *pathend = EOS; + errno = 0; + + if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { + /* TODO: don't call for ENOENT or ENOTDIR? */ + if (pglob->gl_errfunc) { + if (g_Ctoc(pathbuf, buf, sizeof(buf))) + return(GLOB_ABORTED); + if (pglob->gl_errfunc(buf, errno) || + pglob->gl_flags & GLOB_ERR) + return(GLOB_ABORTED); + } + return(0); + } + + err = 0; + + /* Search directory for matching names. */ + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + readdirfunc = pglob->gl_readdir; + else + readdirfunc = (struct dirent *(*)(void *))readdir; + while ((dp = (*readdirfunc)(dirp))) { + u_char *sc; + Char *dc; + + /* Initial DOT must be matched literally. */ + if (dp->d_name[0] == DOT && *pattern != DOT) + continue; + dc = pathend; + sc = (u_char *) dp->d_name; + while (dc < pathend_last && (*dc++ = *sc++) != EOS) + ; + if (dc >= pathend_last) { + *dc = EOS; + err = 1; + break; + } + + if (!match(pathend, pattern, restpattern)) { + *pathend = EOS; + continue; + } + err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, + restpattern, restpattern_last, pglob, limitp); + if (err) + break; + } + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir)(dirp); + else + closedir(dirp); + return(err); +} + + +/* + * Extend the gl_pathv member of a glob_t structure to accommodate a new item, + * add the new item, and update gl_pathc. + * + * This assumes the BSD realloc, which only copies the block when its size + * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic + * behavior. + * + * Return 0 if new item added, error code if memory couldn't be allocated. + * + * Invariant of the glob_t structure: + * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and + * gl_pathv points to (gl_offs + gl_pathc + 1) items. + */ +static int +globextend(const Char *path, glob_t *pglob, size_t *limitp) +{ + char **pathv; + int i; + u_int newsize, len; + char *copy; + const Char *p; + + newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); + pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : + malloc(newsize); + if (pathv == NULL) { + if (pglob->gl_pathv) { + free(pglob->gl_pathv); + pglob->gl_pathv = NULL; + } + return(GLOB_NOSPACE); + } + + if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { + /* first time around -- clear initial gl_offs items */ + pathv += pglob->gl_offs; + for (i = pglob->gl_offs; --i >= 0; ) + *--pathv = NULL; + } + pglob->gl_pathv = pathv; + + for (p = path; *p++;) + ; + len = (size_t)(p - path); + *limitp += len; + if ((copy = malloc(len)) != NULL) { + if (g_Ctoc(path, copy, len)) { + free(copy); + return(GLOB_NOSPACE); + } + pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; + } + pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + + if ((pglob->gl_flags & GLOB_LIMIT) && + newsize + *limitp >= (u_int) get_arg_max()) { + errno = 0; + return(GLOB_NOSPACE); + } + + return(copy == NULL ? GLOB_NOSPACE : 0); +} + + +/* + * pattern matching function for filenames. Each occurrence of the * + * pattern causes a recursion level. + */ +static int +match(Char *name, Char *pat, Char *patend) +{ + int ok, negate_range; + Char c, k; + + while (pat < patend) { + c = *pat++; + switch (c & M_MASK) { + case M_ALL: + if (pat == patend) + return(1); + do { + if (match(name, pat, patend)) + return(1); + } while (*name++ != EOS); + return(0); + case M_ONE: + if (*name++ == EOS) + return(0); + break; + case M_SET: + ok = 0; + if ((k = *name++) == EOS) + return(0); + if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) + ++pat; + while (((c = *pat++) & M_MASK) != M_END) + if ((*pat & M_MASK) == M_RNG) { + if (c <= k && k <= pat[1]) + ok = 1; + pat += 2; + } else if (c == k) + ok = 1; + if (ok == negate_range) + return(0); + break; + default: + if (*name++ != c) + return(0); + break; + } + } + return(*name == EOS); +} + +/* Free allocated data belonging to a glob_t structure. */ +void +globfree(glob_t *pglob) +{ + int i; + char **pp; + + if (pglob->gl_pathv != NULL) { + pp = pglob->gl_pathv + pglob->gl_offs; + for (i = pglob->gl_pathc; i--; ++pp) + if (*pp) + free(*pp); + free(pglob->gl_pathv); + pglob->gl_pathv = NULL; + } +} + +static DIR * +g_opendir(Char *str, glob_t *pglob) +{ + char buf[MAXPATHLEN]; + + if (!*str) + strlcpy(buf, ".", sizeof buf); + else { + if (g_Ctoc(str, buf, sizeof(buf))) + return(NULL); + } + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_opendir)(buf)); + + return(opendir(buf)); +} + +static int +g_lstat(Char *fn, struct stat *sb, glob_t *pglob) +{ + char buf[MAXPATHLEN]; + + if (g_Ctoc(fn, buf, sizeof(buf))) + return(-1); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_lstat)(buf, sb)); + return(lstat(buf, sb)); +} + +static int +g_stat(Char *fn, struct stat *sb, glob_t *pglob) +{ + char buf[MAXPATHLEN]; + + if (g_Ctoc(fn, buf, sizeof(buf))) + return(-1); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_stat)(buf, sb)); + return(stat(buf, sb)); +} + +static Char * +g_strchr(Char *str, int ch) +{ + do { + if (*str == ch) + return (str); + } while (*str++); + return (NULL); +} + +static int +g_Ctoc(const Char *str, char *buf, u_int len) +{ + + while (len--) { + if ((*buf++ = *str++) == EOS) + return (0); + } + return (1); +} + +#ifdef DEBUG +static void +qprintf(const char *str, Char *s) +{ + Char *p; + + (void)printf("%s:\n", str); + for (p = s; *p; p++) + (void)printf("%c", CHAR(*p)); + (void)printf("\n"); + for (p = s; *p; p++) + (void)printf("%c", *p & M_PROTECT ? '"' : ' '); + (void)printf("\n"); + for (p = s; *p; p++) + (void)printf("%c", ismeta(*p) ? '_' : ' '); + (void)printf("\n"); +} +#endif + +#endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || + !defined(GLOB_HAS_GL_MATCHC) */ + diff --git a/crypto/openssh/openbsd-compat/glob.h b/crypto/openssh/openbsd-compat/glob.h new file mode 100644 index 0000000..9ba07f7 --- /dev/null +++ b/crypto/openssh/openbsd-compat/glob.h @@ -0,0 +1,100 @@ +/* $OpenBSD: glob.h,v 1.9 2004/10/07 16:56:11 millert Exp $ */ +/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * 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 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. + * + * @(#)glob.h 8.1 (Berkeley) 6/2/93 + */ + +/* OPENBSD ORIGINAL: include/glob.h */ + +#if !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || \ + !defined(GLOB_HAS_GL_MATCHC) || \ + !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 + +#ifndef _GLOB_H_ +#define _GLOB_H_ + +struct stat; +typedef struct { + int gl_pathc; /* Count of total paths so far. */ + int gl_matchc; /* Count of paths matching pattern. */ + int gl_offs; /* Reserved at beginning of gl_pathv. */ + int gl_flags; /* Copy of flags parameter to glob. */ + char **gl_pathv; /* List of paths matching pattern. */ + /* Copy of errfunc parameter to glob. */ + int (*gl_errfunc)(const char *, int); + + /* + * Alternate filesystem access methods for glob; replacement + * versions of closedir(3), readdir(3), opendir(3), stat(2) + * and lstat(2). + */ + void (*gl_closedir)(void *); + struct dirent *(*gl_readdir)(void *); + void *(*gl_opendir)(const char *); + int (*gl_lstat)(const char *, struct stat *); + int (*gl_stat)(const char *, struct stat *); +} glob_t; + +/* Flags */ +#define GLOB_APPEND 0x0001 /* Append to output from previous call. */ +#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ +#define GLOB_ERR 0x0004 /* Return on error. */ +#define GLOB_MARK 0x0008 /* Append / to matching directories. */ +#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ +#define GLOB_NOSORT 0x0020 /* Don't sort. */ +#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ + +#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ +#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ +#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ +#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ +#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ +#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ +#define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */ + +/* Error values returned by glob(3) */ +#define GLOB_NOSPACE (-1) /* Malloc call failed. */ +#define GLOB_ABORTED (-2) /* Unignored error. */ +#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ +#define GLOB_NOSYS (-4) /* Function not supported. */ +#define GLOB_ABEND GLOB_ABORTED + +int glob(const char *, int, int (*)(const char *, int), glob_t *); +void globfree(glob_t *); + +#endif /* !_GLOB_H_ */ + +#endif /* !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || + !defined(GLOB_HAS_GL_MATCHC */ + diff --git a/crypto/openssh/openbsd-compat/inet_aton.c b/crypto/openssh/openbsd-compat/inet_aton.c new file mode 100644 index 0000000..130597e --- /dev/null +++ b/crypto/openssh/openbsd-compat/inet_aton.c @@ -0,0 +1,179 @@ +/* $OpenBSD: inet_addr.c,v 1.9 2005/08/06 20:30:03 espie Exp $ */ + +/* + * 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. 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-- + */ + +/* OPENBSD ORIGINAL: lib/libc/net/inet_addr.c */ + +#include "includes.h" + +#if !defined(HAVE_INET_ATON) + +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> + +#if 0 +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +in_addr_t +inet_addr(const char *cp) +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} +#endif + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(const char *cp, struct in_addr *addr) +{ + u_int32_t val; + int base, n; + char c; + u_int parts[4]; + u_int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) | + (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if ((val > 0xffffff) || (parts[0] > 0xff)) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} + +#endif /* !defined(HAVE_INET_ATON) */ diff --git a/crypto/openssh/openbsd-compat/inet_ntoa.c b/crypto/openssh/openbsd-compat/inet_ntoa.c new file mode 100644 index 0000000..0eb7b3b --- /dev/null +++ b/crypto/openssh/openbsd-compat/inet_ntoa.c @@ -0,0 +1,59 @@ +/* $OpenBSD: inet_ntoa.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */ +/* + * 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/inet_ntoa.c */ + +#include "includes.h" + +#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) + +/* + * Convert network-format internet address + * to base 256 d.d.d.d representation. + */ +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdio.h> + +char * +inet_ntoa(struct in_addr in) +{ + static char b[18]; + char *p; + + p = (char *)∈ +#define UC(b) (((int)b)&0xff) + (void)snprintf(b, sizeof(b), + "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); + return (b); +} + +#endif /* defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) */ diff --git a/crypto/openssh/openbsd-compat/inet_ntop.c b/crypto/openssh/openbsd-compat/inet_ntop.c new file mode 100644 index 0000000..e7ca4b7 --- /dev/null +++ b/crypto/openssh/openbsd-compat/inet_ntop.c @@ -0,0 +1,211 @@ +/* $OpenBSD: inet_ntop.c,v 1.7 2005/08/06 20:30:03 espie Exp $ */ + +/* 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/inet_ntop.c */ + +#include "includes.h" + +#ifndef HAVE_INET_NTOP + +#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 <stdio.h> + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#endif + +#ifndef INT16SZ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#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(const u_char *src, char *dst, size_t size); +static const char *inet_ntop6(const u_char *src, char *dst, size_t size); + +/* 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(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, more or less like inet_ntoa() + * 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(const u_char *src, char *dst, size_t size) +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + int l; + + l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]); + if (l <= 0 || l >= size) { + errno = ENOSPC; + return (NULL); + } + strlcpy(dst, tmp, size); + 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(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"]; + char *tp, *ep; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + int advance; + + /* + * 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 < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (IN6ADDRSZ / 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; + ep = tmp + sizeof(tmp); + for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; 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) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) + return (NULL); + tp += strlen(tp); + break; + } + advance = snprintf(tp, ep - tp, "%x", words[i]); + if (advance <= 0 || advance >= ep - tp) + return (NULL); + tp += advance; + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + if (tp + 1 >= ep) + return (NULL); + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strlcpy(dst, tmp, size); + return (dst); +} + +#endif /* !HAVE_INET_NTOP */ diff --git a/crypto/openssh/openbsd-compat/mktemp.c b/crypto/openssh/openbsd-compat/mktemp.c new file mode 100644 index 0000000..2285c84 --- /dev/null +++ b/crypto/openssh/openbsd-compat/mktemp.c @@ -0,0 +1,178 @@ +/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */ +/* Changes: Removed mktemp */ + +/* $OpenBSD: mktemp.c,v 1.19 2005/08/08 08:05:36 espie Exp $ */ +/* + * 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <unistd.h> + +#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) + +static int _gettemp(char *, int *, int, int); + +int +mkstemps(char *path, int slen) +{ + int fd; + + return (_gettemp(path, &fd, 0, slen) ? fd : -1); +} + +int +mkstemp(char *path) +{ + int fd; + + return (_gettemp(path, &fd, 0, 0) ? fd : -1); +} + +char * +mkdtemp(char *path) +{ + return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL); +} + +static int +_gettemp(path, doopen, domkdir, slen) + char *path; + register int *doopen; + int domkdir; + int slen; +{ + register char *start, *trv, *suffp; + struct stat sbuf; + int rval; + pid_t pid; + + if (doopen && domkdir) { + errno = EINVAL; + return(0); + } + + for (trv = path; *trv; ++trv) + ; + trv -= slen; + suffp = trv; + --trv; + if (trv < path) { + errno = EINVAL; + return (0); + } + pid = getpid(); + while (trv >= path && *trv == 'X' && pid != 0) { + *trv-- = (pid % 10) + '0'; + pid /= 10; + } + while (trv >= path && *trv == 'X') { + char c; + + pid = (arc4random() & 0xffff) % (26+26); + if (pid < 26) + c = pid + 'A'; + else + c = (pid - 26) + 'a'; + *trv-- = c; + } + start = trv + 1; + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + if (doopen || domkdir) { + for (;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + rval = stat(path, &sbuf); + *trv = '/'; + if (rval != 0) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + 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 (domkdir) { + if (mkdir(path, 0700) == 0) + return(1); + if (errno != EEXIST) + return(0); + } else if (lstat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return (0); + if (*trv == 'Z') { + if (trv == suffp) + return (0); + *trv++ = 'a'; + } else { + if (isdigit(*trv)) + *trv = 'a'; + else if (*trv == 'z') /* inc from z to A */ + *trv = 'A'; + else { + if (trv == suffp) + return (0); + ++*trv; + } + break; + } + } + } + /*NOTREACHED*/ +} + +#endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */ diff --git a/crypto/openssh/openbsd-compat/openbsd-compat.h b/crypto/openssh/openbsd-compat/openbsd-compat.h new file mode 100644 index 0000000..aac2e6c --- /dev/null +++ b/crypto/openssh/openbsd-compat/openbsd-compat.h @@ -0,0 +1,206 @@ +/* $Id: openbsd-compat.h,v 1.42 2006/09/03 12:44:50 dtucker Exp $ */ + +/* + * Copyright (c) 1999-2003 Damien Miller. All rights reserved. + * Copyright (c) 2003 Ben Lindstrom. All rights reserved. + * Copyright (c) 2002 Tim Rice. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _OPENBSD_COMPAT_H +#define _OPENBSD_COMPAT_H + +#include "includes.h" + +#include <sys/types.h> +#include <pwd.h> + +#include <sys/socket.h> + +/* OpenBSD function replacements */ +#include "base64.h" +#include "sigact.h" +#include "glob.h" +#include "readpassphrase.h" +#include "vis.h" +#include "getrrsetbyname.h" +#include "sha2.h" + +#ifndef HAVE_BASENAME +char *basename(const char *path); +#endif + +#ifndef HAVE_BINDRESVPORT_SA +int bindresvport_sa(int sd, struct sockaddr *sa); +#endif + +#ifndef HAVE_CLOSEFROM +void closefrom(int); +#endif + +#ifndef HAVE_GETCWD +char *getcwd(char *pt, size_t size); +#endif + +#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) +char *realpath(const char *path, char *resolved); +#endif + +#ifndef HAVE_RRESVPORT_AF +int rresvport_af(int *alport, sa_family_t af); +#endif + +#ifndef HAVE_STRLCPY +/* #include <sys/types.h> XXX Still needed? */ +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif + +#ifndef HAVE_STRLCAT +/* #include <sys/types.h> XXX Still needed? */ +size_t strlcat(char *dst, const char *src, size_t siz); +#endif + +#ifndef HAVE_SETENV +int setenv(register const char *name, register const char *value, int rewrite); +#endif + +#ifndef HAVE_STRMODE +void strmode(int mode, char *p); +#endif + +#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) +int mkstemps(char *path, int slen); +int mkstemp(char *path); +char *mkdtemp(char *path); +#endif + +#ifndef HAVE_DAEMON +int daemon(int nochdir, int noclose); +#endif + +#ifndef HAVE_DIRNAME +char *dirname(const char *path); +#endif + +#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) +char *inet_ntoa(struct in_addr in); +#endif + +#ifndef HAVE_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif + +#ifndef HAVE_INET_ATON +int inet_aton(const char *cp, struct in_addr *addr); +#endif + +#ifndef HAVE_STRSEP +char *strsep(char **stringp, const char *delim); +#endif + +#ifndef HAVE_SETPROCTITLE +void setproctitle(const char *fmt, ...); +void compat_init_setproctitle(int argc, char *argv[]); +#endif + +#ifndef HAVE_GETGROUPLIST +/* #include <grp.h> XXXX Still needed ? */ +int getgrouplist(const char *, gid_t, gid_t *, int *); +#endif + +#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) +int BSDgetopt(int argc, char * const *argv, const char *opts); +#endif + +#if defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0 +# include <sys/types.h> +# include <sys/uio.h> +int writev(int, struct iovec *, int); +#endif + +/* Home grown routines */ +#include "bsd-misc.h" +#include "bsd-waitpid.h" + +#ifndef HAVE_GETPEEREID +int getpeereid(int , uid_t *, gid_t *); +#endif + +#ifndef HAVE_ARC4RANDOM +unsigned int arc4random(void); +void arc4random_stir(void); +#endif /* !HAVE_ARC4RANDOM */ + +#ifndef HAVE_ASPRINTF +int asprintf(char **, const char *, ...); +#endif + +#ifndef HAVE_OPENPTY +# include <sys/ioctl.h> /* for struct winsize */ +int openpty(int *, int *, char *, struct termios *, struct winsize *); +#endif /* HAVE_OPENPTY */ + +/* #include <sys/types.h> XXX needed? For size_t */ + +#ifndef HAVE_SNPRINTF +int snprintf(char *, size_t, SNPRINTF_CONST char *, ...); +#endif + +#ifndef HAVE_STRTOLL +long long strtoll(const char *, char **, int); +#endif + +#ifndef HAVE_STRTONUM +long long strtonum(const char *, long long, long long, const char **); +#endif + +#if !defined(HAVE_VASPRINTF) || !defined(HAVE_VSNPRINTF) +# include <stdarg.h> +#endif + +#ifndef HAVE_VASPRINTF +int vasprintf(char **, const char *, va_list); +#endif + +#ifndef HAVE_VSNPRINTF +int vsnprintf(char *, size_t, const char *, va_list); +#endif + +void *xmmap(size_t size); +char *xcrypt(const char *password, const char *salt); +char *shadow_pw(struct passwd *pw); + +/* rfc2553 socket API replacements */ +#include "fake-rfc2553.h" + +/* Routines for a single OS platform */ +#include "bsd-cray.h" +#include "bsd-cygwin_util.h" + +#include "port-aix.h" +#include "port-irix.h" +#include "port-linux.h" +#include "port-solaris.h" +#include "port-tun.h" +#include "port-uw.h" + +#endif /* _OPENBSD_COMPAT_H */ diff --git a/crypto/openssh/openbsd-compat/openssl-compat.c b/crypto/openssh/openbsd-compat/openssl-compat.c new file mode 100644 index 0000000..45ebd3f --- /dev/null +++ b/crypto/openssh/openbsd-compat/openssl-compat.c @@ -0,0 +1,62 @@ +/* $Id: openssl-compat.c,v 1.4 2006/02/22 11:24:47 dtucker Exp $ */ + +/* + * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, 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. + */ + +#include "includes.h" + +#ifdef USE_OPENSSL_ENGINE +# include <openssl/engine.h> +#endif + +#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS +#include "openssl-compat.h" + +#ifdef SSH_OLD_EVP +int +ssh_EVP_CipherInit(EVP_CIPHER_CTX *evp, const EVP_CIPHER *type, + unsigned char *key, unsigned char *iv, int enc) +{ + EVP_CipherInit(evp, type, key, iv, enc); + return 1; +} + +int +ssh_EVP_Cipher(EVP_CIPHER_CTX *evp, char *dst, char *src, int len) +{ + EVP_Cipher(evp, dst, src, len); + return 1; +} + +int +ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *evp) +{ + EVP_CIPHER_CTX_cleanup(evp); + return 1; +} +#endif + +#ifdef USE_OPENSSL_ENGINE +void +ssh_SSLeay_add_all_algorithms(void) +{ + SSLeay_add_all_algorithms(); + + /* Enable use of crypto hardware */ + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); +} +#endif diff --git a/crypto/openssh/openbsd-compat/openssl-compat.h b/crypto/openssh/openbsd-compat/openssl-compat.h new file mode 100644 index 0000000..c582cd2 --- /dev/null +++ b/crypto/openssh/openbsd-compat/openssl-compat.h @@ -0,0 +1,80 @@ +/* $Id: openssl-compat.h,v 1.6 2006/02/22 11:24:47 dtucker Exp $ */ + +/* + * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, 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. + */ + +#include "includes.h" +#include <openssl/evp.h> + +#if OPENSSL_VERSION_NUMBER < 0x00906000L +# define SSH_OLD_EVP +# define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data) +#endif + +#if (OPENSSL_VERSION_NUMBER < 0x00907000L) || defined(OPENSSL_LOBOTOMISED_AES) +# define USE_BUILTIN_RIJNDAEL +#endif + +#ifdef USE_BUILTIN_RIJNDAEL +# define EVP_aes_128_cbc evp_rijndael +# define EVP_aes_192_cbc evp_rijndael +# define EVP_aes_256_cbc evp_rijndael +extern const EVP_CIPHER *evp_rijndael(void); +extern void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); +#endif + +#if !defined(EVP_CTRL_SET_ACSS_MODE) +# if (OPENSSL_VERSION_NUMBER >= 0x00907000L) +# define USE_CIPHER_ACSS 1 +extern const EVP_CIPHER *evp_acss(void); +# define EVP_acss evp_acss +# else +# define EVP_acss NULL +# endif +#endif + +/* + * We overload some of the OpenSSL crypto functions with ssh_* equivalents + * which cater for older and/or less featureful OpenSSL version. + * + * In order for the compat library to call the real functions, it must + * define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and + * implement the ssh_* equivalents. + */ +#ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS + +# ifdef SSH_OLD_EVP +# ifdef EVP_Cipher +# undef EVP_Cipher +# endif +# define EVP_CipherInit(a,b,c,d,e) ssh_EVP_CipherInit((a),(b),(c),(d),(e)) +# define EVP_Cipher(a,b,c,d) ssh_EVP_Cipher((a),(b),(c),(d)) +# define EVP_CIPHER_CTX_cleanup(a) ssh_EVP_CIPHER_CTX_cleanup((a)) +# endif /* SSH_OLD_EVP */ + +# ifdef USE_OPENSSL_ENGINE +# ifdef SSLeay_add_all_algorithms +# undef SSLeay_add_all_algorithms +# endif +# define SSLeay_add_all_algorithms() ssh_SSLeay_add_all_algorithms() +#endif + +int ssh_EVP_CipherInit(EVP_CIPHER_CTX *, const EVP_CIPHER *, unsigned char *, + unsigned char *, int); +int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int); +int ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *); +void ssh_SSLeay_add_all_algorithms(void); +#endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */ diff --git a/crypto/openssh/openbsd-compat/port-aix.c b/crypto/openssh/openbsd-compat/port-aix.c new file mode 100644 index 0000000..b9fabf6 --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-aix.c @@ -0,0 +1,397 @@ +/* + * + * Copyright (c) 2001 Gert Doering. All rights reserved. + * Copyright (c) 2003,2004,2005 Darren Tucker. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + */ +#include "includes.h" + +#include "xmalloc.h" +#include "buffer.h" +#include "key.h" +#include "hostfile.h" +#include "auth.h" +#include "ssh.h" +#include "log.h" + +#ifdef _AIX + +#include <errno.h> +#if defined(HAVE_NETDB_H) +# include <netdb.h> +#endif +#include <uinfo.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> + +#ifdef WITH_AIXAUTHENTICATE +# include <login.h> +# include <userpw.h> +# if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG) +# include <sys/audit.h> +# endif +# include <usersec.h> +#endif + +#include "port-aix.h" + +# ifdef HAVE_SETAUTHDB +static char old_registry[REGISTRY_SIZE] = ""; +# endif + +/* + * AIX has a "usrinfo" area where logname and other stuff is stored - + * a few applications actually use this and die if it's not set + * + * NOTE: TTY= should be set, but since no one uses it and it's hard to + * acquire due to privsep code. We will just drop support. + */ +void +aix_usrinfo(struct passwd *pw) +{ + u_int i; + size_t len; + char *cp; + + len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name)); + cp = xmalloc(len); + + i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0', + pw->pw_name, '\0'); + if (usrinfo(SETUINFO, cp, i) == -1) + fatal("Couldn't set usrinfo: %s", strerror(errno)); + debug3("AIX/UsrInfo: set len %d", i); + + xfree(cp); +} + +# ifdef WITH_AIXAUTHENTICATE +/* + * Remove embedded newlines in string (if any). + * Used before logging messages returned by AIX authentication functions + * so the message is logged on one line. + */ +void +aix_remove_embedded_newlines(char *p) +{ + if (p == NULL) + return; + + for (; *p; p++) { + if (*p == '\n') + *p = ' '; + } + /* Remove trailing whitespace */ + if (*--p == ' ') + *p = '\0'; +} + +/* + * Test specifically for the case where SYSTEM == NONE and AUTH1 contains + * anything other than NONE or SYSTEM, which indicates that the admin has + * configured the account for purely AUTH1-type authentication. + * + * Since authenticate() doesn't check AUTH1, and sshd can't sanely support + * AUTH1 itself, in such a case authenticate() will allow access without + * authentation, which is almost certainly not what the admin intends. + * + * (The native tools, eg login, will process the AUTH1 list in addition to + * the SYSTEM list by using ckuserID(), however ckuserID() and AUTH1 methods + * have been deprecated since AIX 4.2.x and would be very difficult for sshd + * to support. + * + * Returns 0 if an unsupportable combination is found, 1 otherwise. + */ +static int +aix_valid_authentications(const char *user) +{ + char *auth1, *sys, *p; + int valid = 1; + + if (getuserattr((char *)user, S_AUTHSYSTEM, &sys, SEC_CHAR) != 0) { + logit("Can't retrieve attribute SYSTEM for %s: %.100s", + user, strerror(errno)); + return 0; + } + + debug3("AIX SYSTEM attribute %s", sys); + if (strcmp(sys, "NONE") != 0) + return 1; /* not "NONE", so is OK */ + + if (getuserattr((char *)user, S_AUTH1, &auth1, SEC_LIST) != 0) { + logit("Can't retrieve attribute auth1 for %s: %.100s", + user, strerror(errno)); + return 0; + } + + p = auth1; + /* A SEC_LIST is concatenated strings, ending with two NULs. */ + while (p[0] != '\0' && p[1] != '\0') { + debug3("AIX auth1 attribute list member %s", p); + if (strcmp(p, "NONE") != 0 && strcmp(p, "SYSTEM")) { + logit("Account %s has unsupported auth1 value '%s'", + user, p); + valid = 0; + } + p += strlen(p) + 1; + } + + return (valid); +} + +/* + * Do authentication via AIX's authenticate routine. We loop until the + * reenter parameter is 0, but normally authenticate is called only once. + * + * Note: this function returns 1 on success, whereas AIX's authenticate() + * returns 0. + */ +int +sys_auth_passwd(Authctxt *ctxt, const char *password) +{ + char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name; + int authsuccess = 0, expired, reenter, result; + + do { + result = authenticate((char *)name, (char *)password, &reenter, + &authmsg); + aix_remove_embedded_newlines(authmsg); + debug3("AIX/authenticate result %d, authmsg %.100s", result, + authmsg); + } while (reenter); + + if (!aix_valid_authentications(name)) + result = -1; + + if (result == 0) { + authsuccess = 1; + + /* + * Record successful login. We don't have a pty yet, so just + * label the line as "ssh" + */ + aix_setauthdb(name); + + /* + * Check if the user's password is expired. + */ + expired = passwdexpired(name, &msg); + if (msg && *msg) { + buffer_append(ctxt->loginmsg, msg, strlen(msg)); + aix_remove_embedded_newlines(msg); + } + debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); + + switch (expired) { + case 0: /* password not expired */ + break; + case 1: /* expired, password change required */ + ctxt->force_pwchange = 1; + break; + default: /* user can't change(2) or other error (-1) */ + logit("Password can't be changed for user %s: %.100s", + name, msg); + if (msg) + xfree(msg); + authsuccess = 0; + } + + aix_restoreauthdb(); + } + + if (authmsg != NULL) + xfree(authmsg); + + return authsuccess; +} + +/* + * Check if specified account is permitted to log in. + * Returns 1 if login is allowed, 0 if not allowed. + */ +int +sys_auth_allowed_user(struct passwd *pw, Buffer *loginmsg) +{ + char *msg = NULL; + int result, permitted = 0; + struct stat st; + + /* + * Don't perform checks for root account (PermitRootLogin controls + * logins via * ssh) or if running as non-root user (since + * loginrestrictions will always fail due to insufficient privilege). + */ + if (pw->pw_uid == 0 || geteuid() != 0) { + debug3("%s: not checking", __func__); + return 1; + } + + result = loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg); + if (result == 0) + permitted = 1; + /* + * If restricted because /etc/nologin exists, the login will be denied + * in session.c after the nologin message is sent, so allow for now + * and do not append the returned message. + */ + if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0) + permitted = 1; + else if (msg != NULL) + buffer_append(loginmsg, msg, strlen(msg)); + if (msg == NULL) + msg = xstrdup("(none)"); + aix_remove_embedded_newlines(msg); + debug3("AIX/loginrestrictions returned %d msg %.100s", result, msg); + + if (!permitted) + logit("Login restricted for %s: %.100s", pw->pw_name, msg); + xfree(msg); + return permitted; +} + +int +sys_auth_record_login(const char *user, const char *host, const char *ttynm, + Buffer *loginmsg) +{ + char *msg = NULL; + static int msg_done = 0; + int success = 0; + + aix_setauthdb(user); + if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) { + success = 1; + if (msg != NULL && loginmsg != NULL && !msg_done) { + debug("AIX/loginsuccess: msg %s", msg); + buffer_append(loginmsg, msg, strlen(msg)); + xfree(msg); + msg_done = 1; + } + } + aix_restoreauthdb(); + return (success); +} + +# ifdef CUSTOM_FAILED_LOGIN +/* + * record_failed_login: generic "login failed" interface function + */ +void +record_failed_login(const char *user, const char *hostname, const char *ttyname) +{ + if (geteuid() != 0) + return; + + aix_setauthdb(user); +# ifdef AIX_LOGINFAILED_4ARG + loginfailed((char *)user, (char *)hostname, (char *)ttyname, + AUDIT_FAIL_AUTH); +# else + loginfailed((char *)user, (char *)hostname, (char *)ttyname); +# endif + aix_restoreauthdb(); +} +# endif /* CUSTOM_FAILED_LOGIN */ + +/* + * If we have setauthdb, retrieve the password registry for the user's + * account then feed it to setauthdb. This will mean that subsequent AIX auth + * functions will only use the specified loadable module. If we don't have + * setauthdb this is a no-op. + */ +void +aix_setauthdb(const char *user) +{ +# ifdef HAVE_SETAUTHDB + char *registry; + + if (setuserdb(S_READ) == -1) { + debug3("%s: Could not open userdb to read", __func__); + return; + } + + if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { + if (setauthdb(registry, old_registry) == 0) + debug3("AIX/setauthdb set registry '%s'", registry); + else + debug3("AIX/setauthdb set registry '%s' failed: %s", + registry, strerror(errno)); + } else + debug3("%s: Could not read S_REGISTRY for user: %s", __func__, + strerror(errno)); + enduserdb(); +# endif /* HAVE_SETAUTHDB */ +} + +/* + * Restore the user's registry settings from old_registry. + * Note that if the first aix_setauthdb fails, setauthdb("") is still safe + * (it restores the system default behaviour). If we don't have setauthdb, + * this is a no-op. + */ +void +aix_restoreauthdb(void) +{ +# ifdef HAVE_SETAUTHDB + if (setauthdb(old_registry, NULL) == 0) + debug3("%s: restoring old registry '%s'", __func__, + old_registry); + else + debug3("%s: failed to restore old registry %s", __func__, + old_registry); +# endif /* HAVE_SETAUTHDB */ +} + +# endif /* WITH_AIXAUTHENTICATE */ + +# if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO) +# undef getnameinfo +/* + * For some reason, AIX's getnameinfo will refuse to resolve the all-zeros + * IPv6 address into its textual representation ("::"), so we wrap it + * with a function that will. + */ +int +sshaix_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct sockaddr_in6 *sa6; + u_int32_t *a6; + + if (flags & (NI_NUMERICHOST|NI_NUMERICSERV) && + sa->sa_family == AF_INET6) { + sa6 = (struct sockaddr_in6 *)sa; + a6 = sa6->sin6_addr.u6_addr.u6_addr32; + + if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { + strlcpy(host, "::", hostlen); + snprintf(serv, servlen, "%d", sa6->sin6_port); + return 0; + } + } + return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); +} +# endif /* AIX_GETNAMEINFO_HACK */ + +#endif /* _AIX */ diff --git a/crypto/openssh/openbsd-compat/port-aix.h b/crypto/openssh/openbsd-compat/port-aix.h new file mode 100644 index 0000000..5a04bed --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-aix.h @@ -0,0 +1,106 @@ +/* $Id: port-aix.h,v 1.27 2006/09/18 13:54:33 dtucker Exp $ */ + +/* + * + * Copyright (c) 2001 Gert Doering. All rights reserved. + * Copyright (c) 2004, 2005 Darren Tucker. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifdef _AIX + +#ifdef HAVE_SYS_SOCKET_H +# include <sys/socket.h> +#endif + +#include "buffer.h" + +/* These should be in the system headers but are not. */ +int usrinfo(int, char *, int); +#if defined(HAVE_DECL_SETAUTHDB) && (HAVE_DECL_SETAUTHDB == 0) +int setauthdb(const char *, char *); +#endif +/* these may or may not be in the headers depending on the version */ +#if defined(HAVE_DECL_AUTHENTICATE) && (HAVE_DECL_AUTHENTICATE == 0) +int authenticate(char *, char *, int *, char **); +#endif +#if defined(HAVE_DECL_LOGINFAILED) && (HAVE_DECL_LOGINFAILED == 0) +int loginfailed(char *, char *, char *); +#endif +#if defined(HAVE_DECL_LOGINRESTRICTIONS) && (HAVE_DECL_LOGINRESTRICTIONS == 0) +int loginrestrictions(char *, int, char *, char **); +#endif +#if defined(HAVE_DECL_LOGINSUCCESS) && (HAVE_DECL_LOGINSUCCESS == 0) +int loginsuccess(char *, char *, char *, char **); +#endif +#if defined(HAVE_DECL_PASSWDEXPIRED) && (HAVE_DECL_PASSWDEXPIRED == 0) +int passwdexpired(char *, char **); +#endif + +/* Some versions define r_type in the above headers, which causes a conflict */ +#ifdef r_type +# undef r_type +#endif + +/* AIX 4.2.x doesn't have nanosleep but does have nsleep which is equivalent */ +#if !defined(HAVE_NANOSLEEP) && defined(HAVE_NSLEEP) +# define nanosleep(a,b) nsleep(a,b) +#endif + +/* For struct timespec on AIX 4.2.x */ +#ifdef HAVE_SYS_TIMERS_H +# include <sys/timers.h> +#endif + +/* + * According to the setauthdb man page, AIX password registries must be 15 + * chars or less plus terminating NUL. + */ +#ifdef HAVE_SETAUTHDB +# define REGISTRY_SIZE 16 +#endif + +void aix_usrinfo(struct passwd *); + +#ifdef WITH_AIXAUTHENTICATE +# define CUSTOM_SYS_AUTH_PASSWD 1 +# define CUSTOM_SYS_AUTH_ALLOWED_USER 1 +int sys_auth_allowed_user(struct passwd *, Buffer *); +# define CUSTOM_SYS_AUTH_RECORD_LOGIN 1 +int sys_auth_record_login(const char *, const char *, const char *, Buffer *); +# define CUSTOM_FAILED_LOGIN 1 +#endif + +void aix_setauthdb(const char *); +void aix_restoreauthdb(void); +void aix_remove_embedded_newlines(char *); + +#if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_GETADDRINFO) +# ifdef getnameinfo +# undef getnameinfo +# endif +int sshaix_getnameinfo(const struct sockaddr *, size_t, char *, size_t, + char *, size_t, int); +# define getnameinfo(a,b,c,d,e,f,g) (sshaix_getnameinfo(a,b,c,d,e,f,g)) +#endif + +#endif /* _AIX */ diff --git a/crypto/openssh/openbsd-compat/port-irix.c b/crypto/openssh/openbsd-compat/port-irix.c new file mode 100644 index 0000000..ba751a5 --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-irix.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000 Denis Parker. All rights reserved. + * Copyright (c) 2000 Michael Stone. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include "includes.h" + +#if defined(WITH_IRIX_PROJECT) || \ + defined(WITH_IRIX_JOBS) || \ + defined(WITH_IRIX_ARRAY) + +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#ifdef WITH_IRIX_PROJECT +# include <proj.h> +#endif /* WITH_IRIX_PROJECT */ +#ifdef WITH_IRIX_JOBS +# include <sys/resource.h> +#endif +#ifdef WITH_IRIX_AUDIT +# include <sat.h> +#endif /* WITH_IRIX_AUDIT */ + +void +irix_setusercontext(struct passwd *pw) +{ +#ifdef WITH_IRIX_PROJECT + prid_t projid; +#endif +#ifdef WITH_IRIX_JOBS + jid_t jid = 0; +#elif defined(WITH_IRIX_ARRAY) + int jid = 0; +#endif + +#ifdef WITH_IRIX_JOBS + jid = jlimit_startjob(pw->pw_name, pw->pw_uid, "interactive"); + if (jid == -1) + fatal("Failed to create job container: %.100s", + strerror(errno)); +#endif /* WITH_IRIX_JOBS */ +#ifdef WITH_IRIX_ARRAY + /* initialize array session */ + if (jid == 0 && newarraysess() != 0) + fatal("Failed to set up new array session: %.100s", + strerror(errno)); +#endif /* WITH_IRIX_ARRAY */ +#ifdef WITH_IRIX_PROJECT + /* initialize irix project info */ + if ((projid = getdfltprojuser(pw->pw_name)) == -1) { + debug("Failed to get project id, using projid 0"); + projid = 0; + } + if (setprid(projid)) + fatal("Failed to initialize project %d for %s: %.100s", + (int)projid, pw->pw_name, strerror(errno)); +#endif /* WITH_IRIX_PROJECT */ +#ifdef WITH_IRIX_AUDIT + if (sysconf(_SC_AUDIT)) { + debug("Setting sat id to %d", (int) pw->pw_uid); + if (satsetid(pw->pw_uid)) + debug("error setting satid: %.100s", strerror(errno)); + } +#endif /* WITH_IRIX_AUDIT */ +} + + +#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ diff --git a/crypto/openssh/openbsd-compat/port-irix.h b/crypto/openssh/openbsd-compat/port-irix.h new file mode 100644 index 0000000..67c4863 --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-irix.h @@ -0,0 +1,39 @@ +/* $Id: port-irix.h,v 1.4 2003/08/29 16:59:52 mouring Exp $ */ + +/* + * Copyright (c) 2000 Denis Parker. All rights reserved. + * Copyright (c) 2000 Michael Stone. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _PORT_IRIX_H +#define _PORT_IRIX_H + +#if defined(WITH_IRIX_PROJECT) || \ + defined(WITH_IRIX_JOBS) || \ + defined(WITH_IRIX_ARRAY) + +void irix_setusercontext(struct passwd *pw); + +#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ + +#endif /* ! _PORT_IRIX_H */ diff --git a/crypto/openssh/openbsd-compat/port-linux.c b/crypto/openssh/openbsd-compat/port-linux.c new file mode 100644 index 0000000..77f3a1c --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-linux.c @@ -0,0 +1,169 @@ +/* $Id: port-linux.c,v 1.3 2006/09/01 05:38:41 djm Exp $ */ + +/* + * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com> + * Copyright (c) 2006 Damien Miller <djm@openbsd.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* + * Linux-specific portability code - just SELinux support at present + */ + +#include "includes.h" + +#include <errno.h> +#include <stdarg.h> +#include <string.h> + +#ifdef WITH_SELINUX +#include "log.h" +#include "port-linux.h" + +#include <selinux/selinux.h> +#include <selinux/flask.h> +#include <selinux/get_context_list.h> + +/* Wrapper around is_selinux_enabled() to log its return value once only */ +static int +ssh_selinux_enabled(void) +{ + static int enabled = -1; + + if (enabled == -1) { + enabled = is_selinux_enabled(); + debug("SELinux support %s", enabled ? "enabled" : "disabled"); + } + + return (enabled); +} + +/* Return the default security context for the given username */ +static security_context_t +ssh_selinux_getctxbyname(char *pwname) +{ + security_context_t sc; + char *sename = NULL, *lvl = NULL; + int r; + +#ifdef HAVE_GETSEUSERBYNAME + if (getseuserbyname(pwname, &sename, &lvl) != 0) + return NULL; +#else + sename = pwname; + lvl = NULL; +#endif + +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL + r = get_default_context_with_level(sename, lvl, NULL, &sc); +#else + r = get_default_context(sename, NULL, &sc); +#endif + + if (r != 0) { + switch (security_getenforce()) { + case -1: + fatal("%s: ssh_selinux_getctxbyname: " + "security_getenforce() failed", __func__); + case 0: + error("%s: Failed to get default SELinux security " + "context for %s", __func__, pwname); + default: + fatal("%s: Failed to get default SELinux security " + "context for %s (in enforcing mode)", + __func__, pwname); + } + } + +#ifdef HAVE_GETSEUSERBYNAME + if (sename != NULL) + xfree(sename); + if (lvl != NULL) + xfree(lvl); +#endif + + return (sc); +} + +/* Set the execution context to the default for the specified user */ +void +ssh_selinux_setup_exec_context(char *pwname) +{ + security_context_t user_ctx = NULL; + + if (!ssh_selinux_enabled()) + return; + + debug3("%s: setting execution context", __func__); + + user_ctx = ssh_selinux_getctxbyname(pwname); + if (setexeccon(user_ctx) != 0) { + switch (security_getenforce()) { + case -1: + fatal("%s: security_getenforce() failed", __func__); + case 0: + error("%s: Failed to set SELinux execution " + "context for %s", __func__, pwname); + default: + fatal("%s: Failed to set SELinux execution context " + "for %s (in enforcing mode)", __func__, pwname); + } + } + if (user_ctx != NULL) + freecon(user_ctx); + + debug3("%s: done", __func__); +} + +/* Set the TTY context for the specified user */ +void +ssh_selinux_setup_pty(char *pwname, const char *tty) +{ + security_context_t new_tty_ctx = NULL; + security_context_t user_ctx = NULL; + security_context_t old_tty_ctx = NULL; + + if (!ssh_selinux_enabled()) + return; + + debug3("%s: setting TTY context on %s", __func__, tty); + + user_ctx = ssh_selinux_getctxbyname(pwname); + + /* XXX: should these calls fatal() upon failure in enforcing mode? */ + + if (getfilecon(tty, &old_tty_ctx) == -1) { + error("%s: getfilecon: %s", __func__, strerror(errno)); + goto out; + } + + if (security_compute_relabel(user_ctx, old_tty_ctx, + SECCLASS_CHR_FILE, &new_tty_ctx) != 0) { + error("%s: security_compute_relabel: %s", + __func__, strerror(errno)); + goto out; + } + + if (setfilecon(tty, new_tty_ctx) != 0) + error("%s: setfilecon: %s", __func__, strerror(errno)); + out: + if (new_tty_ctx != NULL) + freecon(new_tty_ctx); + if (old_tty_ctx != NULL) + freecon(old_tty_ctx); + if (user_ctx != NULL) + freecon(user_ctx); + debug3("%s: done", __func__); +} +#endif /* WITH_SELINUX */ diff --git a/crypto/openssh/openbsd-compat/port-linux.h b/crypto/openssh/openbsd-compat/port-linux.h new file mode 100644 index 0000000..05e520e --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-linux.h @@ -0,0 +1,27 @@ +/* $Id: port-linux.h,v 1.1 2006/04/22 11:26:08 djm Exp $ */ + +/* + * Copyright (c) 2006 Damien Miller <djm@openbsd.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 _PORT_LINUX_H +#define _PORT_LINUX_H + +#ifdef WITH_SELINUX +void ssh_selinux_setup_pty(char *, const char *); +void ssh_selinux_setup_exec_context(char *); +#endif + +#endif /* ! _PORT_LINUX_H */ diff --git a/crypto/openssh/openbsd-compat/port-solaris.c b/crypto/openssh/openbsd-compat/port-solaris.c new file mode 100644 index 0000000..2ab64d4 --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-solaris.c @@ -0,0 +1,199 @@ +/* $Id: port-solaris.c,v 1.3 2006/10/31 23:28:49 dtucker Exp $ */ + +/* + * Copyright (c) 2006 Chad Mynhier. + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include "config.h" +#include "includes.h" + +#ifdef USE_SOLARIS_PROCESS_CONTRACTS + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> + +#include <errno.h> +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif +#include <stdarg.h> +#include <string.h> +#include <unistd.h> + +#include <libcontract.h> +#include <sys/contract/process.h> +#include <sys/ctfs.h> + +#include "log.h" + +#define CT_TEMPLATE CTFS_ROOT "/process/template" +#define CT_LATEST CTFS_ROOT "/process/latest" + +static int tmpl_fd = -1; + +/* Lookup the latest process contract */ +static ctid_t +get_active_process_contract_id(void) +{ + int stat_fd; + ctid_t ctid = -1; + ct_stathdl_t stathdl; + + if ((stat_fd = open64(CT_LATEST, O_RDONLY)) == -1) { + error("%s: Error opening 'latest' process " + "contract: %s", __func__, strerror(errno)); + return -1; + } + if (ct_status_read(stat_fd, CTD_COMMON, &stathdl) != 0) { + error("%s: Error reading process contract " + "status: %s", __func__, strerror(errno)); + goto out; + } + if ((ctid = ct_status_get_id(stathdl)) < 0) { + error("%s: Error getting process contract id: %s", + __func__, strerror(errno)); + goto out; + } + + ct_status_free(stathdl); + out: + close(stat_fd); + return ctid; +} + +void +solaris_contract_pre_fork(void) +{ + if ((tmpl_fd = open64(CT_TEMPLATE, O_RDWR)) == -1) { + error("%s: open %s: %s", __func__, + CT_TEMPLATE, strerror(errno)); + return; + } + + debug2("%s: setting up process contract template on fd %d", + __func__, tmpl_fd); + + /* First we set the template parameters and event sets. */ + if (ct_pr_tmpl_set_param(tmpl_fd, CT_PR_PGRPONLY) != 0) { + error("%s: Error setting process contract parameter set " + "(pgrponly): %s", __func__, strerror(errno)); + goto fail; + } + if (ct_pr_tmpl_set_fatal(tmpl_fd, CT_PR_EV_HWERR) != 0) { + error("%s: Error setting process contract template " + "fatal events: %s", __func__, strerror(errno)); + goto fail; + } + if (ct_tmpl_set_critical(tmpl_fd, 0) != 0) { + error("%s: Error setting process contract template " + "critical events: %s", __func__, strerror(errno)); + goto fail; + } + if (ct_tmpl_set_informative(tmpl_fd, CT_PR_EV_HWERR) != 0) { + error("%s: Error setting process contract template " + "informative events: %s", __func__, strerror(errno)); + goto fail; + } + + /* Now make this the active template for this process. */ + if (ct_tmpl_activate(tmpl_fd) != 0) { + error("%s: Error activating process contract " + "template: %s", __func__, strerror(errno)); + goto fail; + } + return; + + fail: + if (tmpl_fd != -1) { + close(tmpl_fd); + tmpl_fd = -1; + } +} + +void +solaris_contract_post_fork_child() +{ + debug2("%s: clearing process contract template on fd %d", + __func__, tmpl_fd); + + /* Clear the active template. */ + if (ct_tmpl_clear(tmpl_fd) != 0) + error("%s: Error clearing active process contract " + "template: %s", __func__, strerror(errno)); + + close(tmpl_fd); + tmpl_fd = -1; +} + +void +solaris_contract_post_fork_parent(pid_t pid) +{ + ctid_t ctid; + char ctl_path[256]; + int r, ctl_fd = -1, stat_fd = -1; + + debug2("%s: clearing template (fd %d)", __func__, tmpl_fd); + + if (tmpl_fd == -1) + return; + + /* First clear the active template. */ + if ((r = ct_tmpl_clear(tmpl_fd)) != 0) + error("%s: Error clearing active process contract " + "template: %s", __func__, strerror(errno)); + + close(tmpl_fd); + tmpl_fd = -1; + + /* + * If either the fork didn't succeed (pid < 0), or clearing + * th active contract failed (r != 0), then we have nothing + * more do. + */ + if (r != 0 || pid <= 0) + return; + + /* Now lookup and abandon the contract we've created. */ + ctid = get_active_process_contract_id(); + + debug2("%s: abandoning contract id %ld", __func__, ctid); + + snprintf(ctl_path, sizeof(ctl_path), + CTFS_ROOT "/process/%ld/ctl", ctid); + if ((ctl_fd = open64(ctl_path, O_WRONLY)) < 0) { + error("%s: Error opening process contract " + "ctl file: %s", __func__, strerror(errno)); + goto fail; + } + if (ct_ctl_abandon(ctl_fd) < 0) { + error("%s: Error abandoning process contract: %s", + __func__, strerror(errno)); + goto fail; + } + close(ctl_fd); + return; + + fail: + if (tmpl_fd != -1) { + close(tmpl_fd); + tmpl_fd = -1; + } + if (stat_fd != -1) + close(stat_fd); + if (ctl_fd != -1) + close(ctl_fd); +} +#endif diff --git a/crypto/openssh/openbsd-compat/port-solaris.h b/crypto/openssh/openbsd-compat/port-solaris.h new file mode 100644 index 0000000..4c32487 --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-solaris.h @@ -0,0 +1,27 @@ +/* $Id: port-solaris.h,v 1.1 2006/08/30 17:24:42 djm Exp $ */ + +/* + * Copyright (c) 2006 Chad Mynhier. + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 _PORT_SOLARIS_H + +#include <sys/types.h> + +void solaris_contract_pre_fork(void); +void solaris_contract_post_fork_child(void); +void solaris_contract_post_fork_parent(pid_t pid); + +#endif diff --git a/crypto/openssh/openbsd-compat/port-tun.c b/crypto/openssh/openbsd-compat/port-tun.c new file mode 100644 index 0000000..276474d --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-tun.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2005 Reyk Floeter <reyk@openbsd.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/ioctl.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netinet/ip.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> + +#include "log.h" +#include "misc.h" +#include "buffer.h" +#include "channels.h" + +/* + * This is the portable version of the SSH tunnel forwarding, it + * uses some preprocessor definitions for various platform-specific + * settings. + * + * SSH_TUN_LINUX Use the (newer) Linux tun/tap device + * SSH_TUN_FREEBSD Use the FreeBSD tun/tap device + * SSH_TUN_COMPAT_AF Translate the OpenBSD address family + * SSH_TUN_PREPEND_AF Prepend/remove the address family + */ + +/* + * System-specific tunnel open function + */ + +#if defined(SSH_TUN_LINUX) +#include <linux/if.h> +#include <linux/if_tun.h> + +int +sys_tun_open(int tun, int mode) +{ + struct ifreq ifr; + int fd = -1; + const char *name = NULL; + + if ((fd = open("/dev/net/tun", O_RDWR)) == -1) { + debug("%s: failed to open tunnel control interface: %s", + __func__, strerror(errno)); + return (-1); + } + + bzero(&ifr, sizeof(ifr)); + + if (mode == SSH_TUNMODE_ETHERNET) { + ifr.ifr_flags = IFF_TAP; + name = "tap%d"; + } else { + ifr.ifr_flags = IFF_TUN; + name = "tun%d"; + } + ifr.ifr_flags |= IFF_NO_PI; + + if (tun != SSH_TUNID_ANY) { + if (tun > SSH_TUNID_MAX) { + debug("%s: invalid tunnel id %x: %s", __func__, + tun, strerror(errno)); + goto failed; + } + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), name, tun); + } + + if (ioctl(fd, TUNSETIFF, &ifr) == -1) { + debug("%s: failed to configure tunnel (mode %d): %s", __func__, + mode, strerror(errno)); + goto failed; + } + + if (tun == SSH_TUNID_ANY) + debug("%s: tunnel mode %d fd %d", __func__, mode, fd); + else + debug("%s: %s mode %d fd %d", __func__, ifr.ifr_name, mode, fd); + + return (fd); + + failed: + close(fd); + return (-1); +} +#endif /* SSH_TUN_LINUX */ + +#ifdef SSH_TUN_FREEBSD +#include <sys/socket.h> +#include <net/if.h> + +#ifdef HAVE_NET_IF_TUN_H +#include <net/if_tun.h> +#endif + +int +sys_tun_open(int tun, int mode) +{ + struct ifreq ifr; + char name[100]; + int fd = -1, sock, flag; + const char *tunbase = "tun"; + + if (mode == SSH_TUNMODE_ETHERNET) { +#ifdef SSH_TUN_NO_L2 + debug("%s: no layer 2 tunnelling support", __func__); + return (-1); +#else + tunbase = "tap"; +#endif + } + + /* Open the tunnel device */ + if (tun <= SSH_TUNID_MAX) { + snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); + fd = open(name, O_RDWR); + } else if (tun == SSH_TUNID_ANY) { + for (tun = 100; tun >= 0; tun--) { + snprintf(name, sizeof(name), "/dev/%s%d", + tunbase, tun); + if ((fd = open(name, O_RDWR)) >= 0) + break; + } + } else { + debug("%s: invalid tunnel %u\n", __func__, tun); + return (-1); + } + + if (fd < 0) { + debug("%s: %s open failed: %s", __func__, name, + strerror(errno)); + return (-1); + } + + /* Turn on tunnel headers */ + flag = 1; +#if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) + if (mode != SSH_TUNMODE_ETHERNET && + ioctl(fd, TUNSIFHEAD, &flag) == -1) { + debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd, + strerror(errno)); + close(fd); + } +#endif + + debug("%s: %s mode %d fd %d", __func__, name, mode, fd); + + /* Set the tunnel device operation mode */ + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) + goto failed; + + if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) + goto failed; + ifr.ifr_flags |= IFF_UP; + if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) + goto failed; + + close(sock); + return (fd); + + failed: + if (fd >= 0) + close(fd); + if (sock >= 0) + close(sock); + debug("%s: failed to set %s mode %d: %s", __func__, name, + mode, strerror(errno)); + return (-1); +} +#endif /* SSH_TUN_FREEBSD */ + +/* + * System-specific channel filters + */ + +#if defined(SSH_TUN_FILTER) +#define OPENBSD_AF_INET 2 +#define OPENBSD_AF_INET6 24 + +int +sys_tun_infilter(struct Channel *c, char *buf, int len) +{ +#if defined(SSH_TUN_PREPEND_AF) + char rbuf[CHAN_RBUF]; + struct ip *iph; +#endif + u_int32_t *af; + char *ptr = buf; + +#if defined(SSH_TUN_PREPEND_AF) + if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af))) + return (-1); + ptr = (char *)&rbuf[0]; + bcopy(buf, ptr + sizeof(u_int32_t), len); + len += sizeof(u_int32_t); + af = (u_int32_t *)ptr; + + iph = (struct ip *)(ptr + sizeof(u_int32_t)); + switch (iph->ip_v) { + case 6: + *af = AF_INET6; + break; + case 4: + default: + *af = AF_INET; + break; + } +#endif + +#if defined(SSH_TUN_COMPAT_AF) + if (len < (int)sizeof(u_int32_t)) + return (-1); + + af = (u_int32_t *)ptr; + if (*af == htonl(AF_INET6)) + *af = htonl(OPENBSD_AF_INET6); + else + *af = htonl(OPENBSD_AF_INET); +#endif + + buffer_put_string(&c->input, ptr, len); + return (0); +} + +u_char * +sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen) +{ + u_char *buf; + u_int32_t *af; + + *data = buffer_get_string(&c->output, dlen); + if (*dlen < sizeof(*af)) + return (NULL); + buf = *data; + +#if defined(SSH_TUN_PREPEND_AF) + *dlen -= sizeof(u_int32_t); + buf = *data + sizeof(u_int32_t); +#elif defined(SSH_TUN_COMPAT_AF) + af = ntohl(*(u_int32_t *)buf); + if (*af == OPENBSD_AF_INET6) + *af = htonl(AF_INET6); + else + *af = htonl(AF_INET); +#endif + + return (buf); +} +#endif /* SSH_TUN_FILTER */ diff --git a/crypto/openssh/openbsd-compat/port-tun.h b/crypto/openssh/openbsd-compat/port-tun.h new file mode 100644 index 0000000..c53df01 --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-tun.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2005 Reyk Floeter <reyk@openbsd.org> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 _PORT_TUN_H +#define _PORT_TUN_H + +struct Channel; + +#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD) +# define CUSTOM_SYS_TUN_OPEN +int sys_tun_open(int, int); +#endif + +#if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF) +# define SSH_TUN_FILTER +int sys_tun_infilter(struct Channel *, char *, int); +u_char *sys_tun_outfilter(struct Channel *, u_char **, u_int *); +#endif + +#endif diff --git a/crypto/openssh/openbsd-compat/port-uw.c b/crypto/openssh/openbsd-compat/port-uw.c new file mode 100644 index 0000000..6f35239 --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-uw.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2005 The SCO Group. All rights reserved. + * Copyright (c) 2005 Tim Rice. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include "includes.h" + +#ifdef HAVE_LIBIAF +#include <sys/types.h> +#ifdef HAVE_CRYPT_H +# include <crypt.h> +#endif +#include <pwd.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "xmalloc.h" +#include "packet.h" +#include "buffer.h" +#include "auth-options.h" +#include "log.h" +#include "servconf.h" +#include "key.h" +#include "hostfile.h" +#include "auth.h" +#include "ssh.h" + +int nischeck(char *); + +int +sys_auth_passwd(Authctxt *authctxt, const char *password) +{ + struct passwd *pw = authctxt->pw; + char *salt; + int result; + + /* Just use the supplied fake password if authctxt is invalid */ + char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; + + /* Check for users with no password. */ + if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) + return (1); + + /* Encrypt the candidate password using the proper salt. */ + salt = (pw_password[0] && pw_password[1]) ? pw_password : "xx"; + + /* + * Authentication is accepted if the encrypted passwords + * are identical. + */ +#ifdef UNIXWARE_LONG_PASSWORDS + if (!nischeck(pw->pw_name)) { + result = ((strcmp(bigcrypt(password, salt), pw_password) == 0) + || (strcmp(osr5bigcrypt(password, salt), pw_password) == 0)); + } + else +#endif /* UNIXWARE_LONG_PASSWORDS */ + result = (strcmp(xcrypt(password, salt), pw_password) == 0); + +#if !defined(BROKEN_LIBIAF) + if (authctxt->valid) + free(pw_password); +#endif + return(result); +} + +#ifdef UNIXWARE_LONG_PASSWORDS +int +nischeck(char *namep) +{ + char password_file[] = "/etc/passwd"; + FILE *fd; + struct passwd *ent = NULL; + + if ((fd = fopen (password_file, "r")) == NULL) { + /* + * If the passwd file has dissapeared we are in a bad state. + * However, returning 0 will send us back through the + * authentication scheme that has checked the ia database for + * passwords earlier. + */ + return(0); + } + + /* + * fgetpwent() only reads from password file, so we know for certain + * that the user is local. + */ + while (ent = fgetpwent(fd)) { + if (strcmp (ent->pw_name, namep) == 0) { + /* Local user */ + fclose (fd); + return(0); + } + } + + fclose (fd); + return (1); +} + +#endif /* UNIXWARE_LONG_PASSWORDS */ + +/* + NOTE: ia_get_logpwd() allocates memory for arg 2 + functions that call shadow_pw() will need to free + */ + +#if !defined(BROKEN_LIBIAF) +char * +get_iaf_password(struct passwd *pw) +{ + char *pw_password = NULL; + + uinfo_t uinfo; + if (!ia_openinfo(pw->pw_name,&uinfo)) { + ia_get_logpwd(uinfo, &pw_password); + if (pw_password == NULL) + fatal("ia_get_logpwd: Unable to get the shadow passwd"); + ia_closeinfo(uinfo); + return pw_password; + } + else + fatal("ia_openinfo: Unable to open the shadow passwd file"); +} +#endif /* !BROKEN_LIBIAF */ +#endif /* HAVE_LIBIAF */ + diff --git a/crypto/openssh/openbsd-compat/port-uw.h b/crypto/openssh/openbsd-compat/port-uw.h new file mode 100644 index 0000000..3589b2e --- /dev/null +++ b/crypto/openssh/openbsd-compat/port-uw.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2005 Tim Rice. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include "includes.h" + +#if defined(HAVE_LIBIAF) && !defined(BROKEN_LIBIAF) +char * get_iaf_password(struct passwd *pw); +#endif + diff --git a/crypto/openssh/openbsd-compat/readpassphrase.c b/crypto/openssh/openbsd-compat/readpassphrase.c new file mode 100644 index 0000000..11bd8f6 --- /dev/null +++ b/crypto/openssh/openbsd-compat/readpassphrase.c @@ -0,0 +1,191 @@ +/* $OpenBSD: readpassphrase.c,v 1.18 2005/08/08 08:05:34 espie Exp $ */ + +/* + * Copyright (c) 2000-2002 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */ + +#include "includes.h" + +#ifndef HAVE_READPASSPHRASE + +#include <termios.h> +#include <signal.h> +#include <ctype.h> +#include <fcntl.h> +#include <readpassphrase.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#ifdef TCSASOFT +# define _T_FLUSH (TCSAFLUSH|TCSASOFT) +#else +# define _T_FLUSH (TCSAFLUSH) +#endif + +/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */ +#if !defined(_POSIX_VDISABLE) && defined(VDISABLE) +# define _POSIX_VDISABLE VDISABLE +#endif + +static volatile sig_atomic_t signo; + +static void handler(int); + +char * +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) +{ + ssize_t nr; + int input, output, save_errno; + char ch, *p, *end; + struct termios term, oterm; + struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm; + struct sigaction savetstp, savettin, savettou, savepipe; + + /* I suppose we could alloc on demand in this case (XXX). */ + if (bufsiz == 0) { + errno = EINVAL; + return(NULL); + } + +restart: + signo = 0; + /* + * Read and write to /dev/tty if available. If not, read from + * stdin and write to stderr unless a tty is required. + */ + if ((flags & RPP_STDIN) || + (input = output = open(_PATH_TTY, O_RDWR)) == -1) { + if (flags & RPP_REQUIRE_TTY) { + errno = ENOTTY; + return(NULL); + } + input = STDIN_FILENO; + output = STDERR_FILENO; + } + + /* + * Catch signals that would otherwise cause the user to end + * up with echo turned off in the shell. Don't worry about + * things like SIGXCPU and SIGVTALRM for now. + */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; /* don't restart system calls */ + sa.sa_handler = handler; + (void)sigaction(SIGALRM, &sa, &savealrm); + (void)sigaction(SIGHUP, &sa, &savehup); + (void)sigaction(SIGINT, &sa, &saveint); + (void)sigaction(SIGPIPE, &sa, &savepipe); + (void)sigaction(SIGQUIT, &sa, &savequit); + (void)sigaction(SIGTERM, &sa, &saveterm); + (void)sigaction(SIGTSTP, &sa, &savetstp); + (void)sigaction(SIGTTIN, &sa, &savettin); + (void)sigaction(SIGTTOU, &sa, &savettou); + + /* Turn off echo if possible. */ + if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { + memcpy(&term, &oterm, sizeof(term)); + if (!(flags & RPP_ECHO_ON)) + term.c_lflag &= ~(ECHO | ECHONL); +#ifdef VSTATUS + if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) + term.c_cc[VSTATUS] = _POSIX_VDISABLE; +#endif + (void)tcsetattr(input, _T_FLUSH, &term); + } else { + memset(&term, 0, sizeof(term)); + term.c_lflag |= ECHO; + memset(&oterm, 0, sizeof(oterm)); + oterm.c_lflag |= ECHO; + } + + if (!(flags & RPP_STDIN)) + (void)write(output, prompt, strlen(prompt)); + end = buf + bufsiz - 1; + for (p = buf; (nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) { + if (p < end) { + if ((flags & RPP_SEVENBIT)) + ch &= 0x7f; + if (isalpha(ch)) { + if ((flags & RPP_FORCELOWER)) + ch = tolower(ch); + if ((flags & RPP_FORCEUPPER)) + ch = toupper(ch); + } + *p++ = ch; + } + } + *p = '\0'; + save_errno = errno; + if (!(term.c_lflag & ECHO)) + (void)write(output, "\n", 1); + + /* Restore old terminal settings and signals. */ + if (memcmp(&term, &oterm, sizeof(term)) != 0) { + while (tcsetattr(input, _T_FLUSH, &oterm) == -1 && + errno == EINTR) + continue; + } + (void)sigaction(SIGALRM, &savealrm, NULL); + (void)sigaction(SIGHUP, &savehup, NULL); + (void)sigaction(SIGINT, &saveint, NULL); + (void)sigaction(SIGQUIT, &savequit, NULL); + (void)sigaction(SIGPIPE, &savepipe, NULL); + (void)sigaction(SIGTERM, &saveterm, NULL); + (void)sigaction(SIGTSTP, &savetstp, NULL); + (void)sigaction(SIGTTIN, &savettin, NULL); + if (input != STDIN_FILENO) + (void)close(input); + + /* + * If we were interrupted by a signal, resend it to ourselves + * now that we have restored the signal handlers. + */ + if (signo) { + kill(getpid(), signo); + switch (signo) { + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + goto restart; + } + } + + errno = save_errno; + return(nr == -1 ? NULL : buf); +} + +#if 0 +char * +getpass(const char *prompt) +{ + static char buf[_PASSWORD_LEN + 1]; + + return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); +} +#endif + +static void handler(int s) +{ + + signo = s; +} +#endif /* HAVE_READPASSPHRASE */ diff --git a/crypto/openssh/openbsd-compat/readpassphrase.h b/crypto/openssh/openbsd-compat/readpassphrase.h new file mode 100644 index 0000000..5fd7c5d --- /dev/null +++ b/crypto/openssh/openbsd-compat/readpassphrase.h @@ -0,0 +1,44 @@ +/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */ + +/* + * Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +/* OPENBSD ORIGINAL: include/readpassphrase.h */ + +#ifndef _READPASSPHRASE_H_ +#define _READPASSPHRASE_H_ + +#include "includes.h" + +#ifndef HAVE_READPASSPHRASE + +#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ +#define RPP_ECHO_ON 0x01 /* Leave echo on. */ +#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ +#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ +#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ +#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ +#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */ + +char * readpassphrase(const char *, char *, size_t, int); + +#endif /* HAVE_READPASSPHRASE */ + +#endif /* !_READPASSPHRASE_H_ */ diff --git a/crypto/openssh/openbsd-compat/realpath.c b/crypto/openssh/openbsd-compat/realpath.c new file mode 100644 index 0000000..b6120d0 --- /dev/null +++ b/crypto/openssh/openbsd-compat/realpath.c @@ -0,0 +1,197 @@ +/* $OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ +/* + * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru> + * + * 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. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/realpath.c */ + +#include "includes.h" + +#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) + +#include <sys/param.h> +#include <sys/stat.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* + * char *realpath(const char *path, char resolved[PATH_MAX]); + * + * Find the real name of path, by removing all ".", ".." and symlink + * components. Returns (resolved) on success, or (NULL) on failure, + * in which case the path which caused trouble is left in (resolved). + */ +char * +realpath(const char *path, char resolved[PATH_MAX]) +{ + struct stat sb; + char *p, *q, *s; + size_t left_len, resolved_len; + unsigned symlinks; + int serrno, slen; + char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; + + serrno = errno; + symlinks = 0; + if (path[0] == '/') { + resolved[0] = '/'; + resolved[1] = '\0'; + if (path[1] == '\0') + return (resolved); + resolved_len = 1; + left_len = strlcpy(left, path + 1, sizeof(left)); + } else { + if (getcwd(resolved, PATH_MAX) == NULL) { + strlcpy(resolved, ".", PATH_MAX); + return (NULL); + } + resolved_len = strlen(resolved); + left_len = strlcpy(left, path, sizeof(left)); + } + if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { + errno = ENAMETOOLONG; + return (NULL); + } + + /* + * Iterate over path components in `left'. + */ + while (left_len != 0) { + /* + * Extract the next path component and adjust `left' + * and its length. + */ + p = strchr(left, '/'); + s = p ? p : left + left_len; + if (s - left >= sizeof(next_token)) { + errno = ENAMETOOLONG; + return (NULL); + } + memcpy(next_token, left, s - left); + next_token[s - left] = '\0'; + left_len -= s - left; + if (p != NULL) + memmove(left, s + 1, left_len + 1); + if (resolved[resolved_len - 1] != '/') { + if (resolved_len + 1 >= PATH_MAX) { + errno = ENAMETOOLONG; + return (NULL); + } + resolved[resolved_len++] = '/'; + resolved[resolved_len] = '\0'; + } + if (next_token[0] == '\0') + continue; + else if (strcmp(next_token, ".") == 0) + continue; + else if (strcmp(next_token, "..") == 0) { + /* + * Strip the last path component except when we have + * single "/" + */ + if (resolved_len > 1) { + resolved[resolved_len - 1] = '\0'; + q = strrchr(resolved, '/') + 1; + *q = '\0'; + resolved_len = q - resolved; + } + continue; + } + + /* + * Append the next path component and lstat() it. If + * lstat() fails we still can return successfully if + * there are no more path components left. + */ + resolved_len = strlcat(resolved, next_token, PATH_MAX); + if (resolved_len >= PATH_MAX) { + errno = ENAMETOOLONG; + return (NULL); + } + if (lstat(resolved, &sb) != 0) { + if (errno == ENOENT && p == NULL) { + errno = serrno; + return (resolved); + } + return (NULL); + } + if (S_ISLNK(sb.st_mode)) { + if (symlinks++ > MAXSYMLINKS) { + errno = ELOOP; + return (NULL); + } + slen = readlink(resolved, symlink, sizeof(symlink) - 1); + if (slen < 0) + return (NULL); + symlink[slen] = '\0'; + if (symlink[0] == '/') { + resolved[1] = 0; + resolved_len = 1; + } else if (resolved_len > 1) { + /* Strip the last path component. */ + resolved[resolved_len - 1] = '\0'; + q = strrchr(resolved, '/') + 1; + *q = '\0'; + resolved_len = q - resolved; + } + + /* + * If there are any path components left, then + * append them to symlink. The result is placed + * in `left'. + */ + if (p != NULL) { + if (symlink[slen - 1] != '/') { + if (slen + 1 >= sizeof(symlink)) { + errno = ENAMETOOLONG; + return (NULL); + } + symlink[slen] = '/'; + symlink[slen + 1] = 0; + } + left_len = strlcat(symlink, left, sizeof(left)); + if (left_len >= sizeof(left)) { + errno = ENAMETOOLONG; + return (NULL); + } + } + left_len = strlcpy(left, symlink, sizeof(left)); + } + } + + /* + * Remove trailing slash except when the resolved pathname + * is a single "/". + */ + if (resolved_len > 1 && resolved[resolved_len - 1] == '/') + resolved[resolved_len - 1] = '\0'; + return (resolved); +} +#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ diff --git a/crypto/openssh/openbsd-compat/regress/Makefile.in b/crypto/openssh/openbsd-compat/regress/Makefile.in new file mode 100644 index 0000000..bcf214b --- /dev/null +++ b/crypto/openssh/openbsd-compat/regress/Makefile.in @@ -0,0 +1,38 @@ +# $Id: Makefile.in,v 1.4 2006/08/19 09:12:14 dtucker Exp $ + +sysconfdir=@sysconfdir@ +piddir=@piddir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ + +VPATH=@srcdir@ +CC=@CC@ +LD=@LD@ +CFLAGS=@CFLAGS@ +CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ +EXEEXT=@EXEEXT@ +LIBCOMPAT=../libopenbsd-compat.a +LIBS=@LIBS@ +LDFLAGS=@LDFLAGS@ $(LIBCOMPAT) + +TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \ + strtonumtest$(EXEEXT) + +all: t-exec ${OTHERTESTS} + +%$(EXEEXT): %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBS) + +t-exec: $(TESTPROGS) + @echo running compat regress tests + @for TEST in ""$?; do \ + echo "run test $${TEST}" ... 1>&2; \ + ./$${TEST}$(EXEEXT) || exit $$? ; \ + done + @echo finished compat regress tests + +clean: + rm -f *.o *.a core $(TESTPROGS) valid.out + +distclean: clean + rm -f Makefile *~ diff --git a/crypto/openssh/openbsd-compat/regress/closefromtest.c b/crypto/openssh/openbsd-compat/regress/closefromtest.c new file mode 100644 index 0000000..feb1b56 --- /dev/null +++ b/crypto/openssh/openbsd-compat/regress/closefromtest.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006 Darren Tucker + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define NUM_OPENS 10 + +void +fail(char *msg) +{ + fprintf(stderr, "closefrom: %s\n", msg); + exit(1); +} + +int +main(void) +{ + int i, max, fds[NUM_OPENS]; + char buf[512]; + + for (i = 0; i < NUM_OPENS; i++) + if ((fds[i] = open("/dev/null", "r")) == -1) + exit(0); /* can't test */ + max = i - 1; + + /* should close last fd only */ + closefrom(fds[max]); + if (close(fds[max]) != -1) + fail("failed to close highest fd"); + + /* make sure we can still use remaining descriptors */ + for (i = 0; i < max; i++) + if (read(fds[i], buf, sizeof(buf)) == -1) + fail("closed descriptors it should not have"); + + /* should close all fds */ + closefrom(fds[0]); + for (i = 0; i < NUM_OPENS; i++) + if (close(fds[i]) != -1) + fail("failed to close from lowest fd"); +} diff --git a/crypto/openssh/openbsd-compat/regress/snprintftest.c b/crypto/openssh/openbsd-compat/regress/snprintftest.c new file mode 100644 index 0000000..4ca63e1 --- /dev/null +++ b/crypto/openssh/openbsd-compat/regress/snprintftest.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005 Darren Tucker + * Copyright (c) 2005 Damien Miller + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#define BUFSZ 2048 + +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +static int failed = 0; + +static void +fail(const char *m) +{ + fprintf(stderr, "snprintftest: %s\n", m); + failed = 1; +} + +int x_snprintf(char *str, size_t count, const char *fmt, ...) +{ + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + return ret; +} + +int +main(void) +{ + char b[5]; + char *src; + + snprintf(b,5,"123456789"); + if (b[4] != '\0') + fail("snprintf does not correctly terminate long strings"); + + /* check for read overrun on unterminated string */ + if ((src = malloc(BUFSZ)) == NULL) { + fail("malloc failed"); + } else { + memset(src, 'a', BUFSZ); + snprintf(b, sizeof(b), "%.*s", 1, src); + if (strcmp(b, "a") != 0) + fail("failed with length limit '%%.s'"); + } + + /* check that snprintf and vsnprintf return sane values */ + if (snprintf(b, 1, "%s %d", "hello", 12345) != 11) + fail("snprintf does not return required length"); + if (x_snprintf(b, 1, "%s %d", "hello", 12345) != 11) + fail("vsnprintf does not return required length"); + + return failed; +} diff --git a/crypto/openssh/openbsd-compat/regress/strduptest.c b/crypto/openssh/openbsd-compat/regress/strduptest.c new file mode 100644 index 0000000..7f6d779 --- /dev/null +++ b/crypto/openssh/openbsd-compat/regress/strduptest.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2005 Darren Tucker + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include <stdlib.h> +#include <string.h> + +static int fail = 0; + +void +test(const char *a) +{ + char *b; + + b = strdup(a); + if (b == 0) { + fail = 1; + return; + } + if (strcmp(a, b) != 0) + fail = 1; + free(b); +} + +int +main(void) +{ + test(""); + test("a"); + test("\0"); + test("abcdefghijklmnopqrstuvwxyz"); + return fail; +} diff --git a/crypto/openssh/openbsd-compat/regress/strtonumtest.c b/crypto/openssh/openbsd-compat/regress/strtonumtest.c new file mode 100644 index 0000000..cb85851 --- /dev/null +++ b/crypto/openssh/openbsd-compat/regress/strtonumtest.c @@ -0,0 +1,66 @@ +/* $OpenBSD: strtonumtest.c,v 1.1 2004/08/03 20:38:36 otto Exp $ */ +/* + * Copyright (c) 2004 Otto Moerbeek <otto@drijf.net> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: regress/lib/libc/strtonum/strtonumtest.c */ + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +int fail; + +void +test(const char *p, long long lb, long long ub, int ok) +{ + long long val; + const char *q; + + val = strtonum(p, lb, ub, &q); + if (ok && q != NULL) { + fprintf(stderr, "%s [%lld-%lld] ", p, lb, ub); + fprintf(stderr, "NUMBER NOT ACCEPTED %s\n", q); + fail = 1; + } else if (!ok && q == NULL) { + fprintf(stderr, "%s [%lld-%lld] %lld ", p, lb, ub, val); + fprintf(stderr, "NUMBER ACCEPTED\n"); + fail = 1; + } +} + +int main(int argc, char *argv[]) +{ + test("1", 0, 10, 1); + test("0", -2, 5, 1); + test("0", 2, 5, 0); + test("0", 2, LLONG_MAX, 0); + test("-2", 0, LLONG_MAX, 0); + test("0", -5, LLONG_MAX, 1); + test("-3", -3, LLONG_MAX, 1); + test("-9223372036854775808", LLONG_MIN, LLONG_MAX, 1); + test("9223372036854775807", LLONG_MIN, LLONG_MAX, 1); + test("-9223372036854775809", LLONG_MIN, LLONG_MAX, 0); + test("9223372036854775808", LLONG_MIN, LLONG_MAX, 0); + test("1000000000000000000000000", LLONG_MIN, LLONG_MAX, 0); + test("-1000000000000000000000000", LLONG_MIN, LLONG_MAX, 0); + test("-2", 10, -1, 0); + test("-2", -10, -1, 1); + test("-20", -10, -1, 0); + test("20", -10, -1, 0); + + return (fail); +} + diff --git a/crypto/openssh/openbsd-compat/rresvport.c b/crypto/openssh/openbsd-compat/rresvport.c new file mode 100644 index 0000000..5b0275c --- /dev/null +++ b/crypto/openssh/openbsd-compat/rresvport.c @@ -0,0 +1,107 @@ +/* $OpenBSD: rresvport.c,v 1.9 2005/11/10 10:00:17 espie Exp $ */ +/* + * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved. + * Copyright (c) 1983, 1993, 1994 + * 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/rresvport.c */ + +#include "includes.h" + +#ifndef HAVE_RRESVPORT_AF + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#if 0 +int +rresvport(int *alport) +{ + return rresvport_af(alport, AF_INET); +} +#endif + +int +rresvport_af(int *alport, sa_family_t af) +{ + struct sockaddr_storage ss; + struct sockaddr *sa; + u_int16_t *portp; + int s; + socklen_t salen; + + memset(&ss, '\0', sizeof ss); + sa = (struct sockaddr *)&ss; + + switch (af) { + case AF_INET: + salen = sizeof(struct sockaddr_in); + portp = &((struct sockaddr_in *)sa)->sin_port; + break; + case AF_INET6: + salen = sizeof(struct sockaddr_in6); + portp = &((struct sockaddr_in6 *)sa)->sin6_port; + break; + default: + errno = EPFNOSUPPORT; + return (-1); + } + sa->sa_family = af; + + s = socket(af, SOCK_STREAM, 0); + if (s < 0) + return (-1); + + *portp = htons(*alport); + if (*alport < IPPORT_RESERVED - 1) { + if (bind(s, sa, salen) >= 0) + return (s); + if (errno != EADDRINUSE) { + (void)close(s); + return (-1); + } + } + + *portp = 0; + sa->sa_family = af; + if (bindresvport_sa(s, sa) == -1) { + (void)close(s); + return (-1); + } + *alport = ntohs(*portp); + return (s); +} + +#endif /* HAVE_RRESVPORT_AF */ diff --git a/crypto/openssh/openbsd-compat/setenv.c b/crypto/openssh/openbsd-compat/setenv.c new file mode 100644 index 0000000..b52a99c --- /dev/null +++ b/crypto/openssh/openbsd-compat/setenv.c @@ -0,0 +1,145 @@ +/* $OpenBSD: setenv.c,v 1.9 2005/08/08 08:05:37 espie Exp $ */ +/* + * Copyright (c) 1987 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/setenv.c */ + +#include "includes.h" +#if !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) + +#include <stdlib.h> +#include <string.h> + +extern char **environ; + +/* OpenSSH Portable: __findenv is from getenv.c rev 1.8, made static */ +/* + * __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. + */ +static char * +__findenv(const char *name, int *offset) +{ + extern char **environ; + int len, i; + const char *np; + char **p, *cp; + + if (name == NULL || environ == NULL) + return (NULL); + for (np = name; *np && *np != '='; ++np) + ; + len = np - name; + for (p = environ; (cp = *p) != NULL; ++p) { + for (np = name, i = len; i && *cp; i--) + if (*cp++ != *np++) + break; + if (i == 0 && *cp++ == '=') { + *offset = p - environ; + return (cp); + } + } + return (NULL); +} + +#ifndef HAVE_SETENV +/* + * setenv -- + * Set the value of the environmental variable "name" to be + * "value". If rewrite is set, replace any current value. + */ +int +setenv(const char *name, const char *value, int rewrite) +{ + static char **lastenv; /* last value of environ */ + 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 */ + size_t cnt; + char **P; + + for (P = environ; *P != NULL; P++) + ; + cnt = P - environ; + P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); + if (!P) + return (-1); + if (lastenv != environ) + memcpy(P, environ, cnt * sizeof(char *)); + lastenv = environ = P; + offset = cnt; + environ[cnt + 1] = NULL; + } + 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); +} +#endif /* HAVE_SETENV */ + +#ifndef HAVE_UNSETENV +/* + * 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; +} +#endif /* HAVE_UNSETENV */ + +#endif /* !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) */ diff --git a/crypto/openssh/openbsd-compat/setproctitle.c b/crypto/openssh/openbsd-compat/setproctitle.c new file mode 100644 index 0000000..b511f66 --- /dev/null +++ b/crypto/openssh/openbsd-compat/setproctitle.c @@ -0,0 +1,160 @@ +/* Based on conf.c from UCB sendmail 8.8.8 */ + +/* + * Copyright 2003 Damien Miller + * Copyright (c) 1983, 1995-1997 Eric P. Allman + * 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. 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. + */ + +#include "includes.h" + +#ifndef HAVE_SETPROCTITLE + +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> +#ifdef HAVE_SYS_PSTAT_H +#include <sys/pstat.h> +#endif +#include <string.h> + +#define SPT_NONE 0 /* don't use it at all */ +#define SPT_PSTAT 1 /* use pstat(PSTAT_SETCMD, ...) */ +#define SPT_REUSEARGV 2 /* cover argv with title information */ + +#ifndef SPT_TYPE +# define SPT_TYPE SPT_NONE +#endif + +#ifndef SPT_PADCHAR +# define SPT_PADCHAR '\0' +#endif + +#if SPT_TYPE == SPT_REUSEARGV +static char *argv_start = NULL; +static size_t argv_env_len = 0; +#endif + +#endif /* HAVE_SETPROCTITLE */ + +void +compat_init_setproctitle(int argc, char *argv[]) +{ +#if defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV + extern char **environ; + char *lastargv = NULL; + char **envp = environ; + int i; + + /* + * NB: This assumes that argv has already been copied out of the + * way. This is true for sshd, but may not be true for other + * programs. Beware. + */ + + if (argc == 0 || argv[0] == NULL) + return; + + /* Fail if we can't allocate room for the new environment */ + for (i = 0; envp[i] != NULL; i++) + ; + if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) { + environ = envp; /* put it back */ + return; + } + + /* + * Find the last argv string or environment variable within + * our process memory area. + */ + for (i = 0; i < argc; i++) { + if (lastargv == NULL || lastargv + 1 == argv[i]) + lastargv = argv[i] + strlen(argv[i]); + } + for (i = 0; envp[i] != NULL; i++) { + if (lastargv + 1 == envp[i]) + lastargv = envp[i] + strlen(envp[i]); + } + + argv[1] = NULL; + argv_start = argv[0]; + argv_env_len = lastargv - argv[0] - 1; + + /* + * Copy environment + * XXX - will truncate env on strdup fail + */ + for (i = 0; envp[i] != NULL; i++) + environ[i] = strdup(envp[i]); + environ[i] = NULL; +#endif /* SPT_REUSEARGV */ +} + +#ifndef HAVE_SETPROCTITLE +void +setproctitle(const char *fmt, ...) +{ +#if SPT_TYPE != SPT_NONE + va_list ap; + char buf[1024]; + size_t len; + extern char *__progname; +#if SPT_TYPE == SPT_PSTAT + union pstun pst; +#endif + +#if SPT_TYPE == SPT_REUSEARGV + if (argv_env_len <= 0) + return; +#endif + + strlcpy(buf, __progname, sizeof(buf)); + + va_start(ap, fmt); + if (fmt != NULL) { + len = strlcat(buf, ": ", sizeof(buf)); + if (len < sizeof(buf)) + vsnprintf(buf + len, sizeof(buf) - len , fmt, ap); + } + va_end(ap); + +#if SPT_TYPE == SPT_PSTAT + pst.pst_command = buf; + pstat(PSTAT_SETCMD, pst, strlen(buf), 0, 0); +#elif SPT_TYPE == SPT_REUSEARGV +/* debug("setproctitle: copy \"%s\" into len %d", + buf, argv_env_len); */ + len = strlcpy(argv_start, buf, argv_env_len); + for(; len < argv_env_len; len++) + argv_start[len] = SPT_PADCHAR; +#endif + +#endif /* SPT_NONE */ +} + +#endif /* HAVE_SETPROCTITLE */ diff --git a/crypto/openssh/openbsd-compat/sha2.c b/crypto/openssh/openbsd-compat/sha2.c new file mode 100755 index 0000000..cf8e0ad6 --- /dev/null +++ b/crypto/openssh/openbsd-compat/sha2.c @@ -0,0 +1,882 @@ +/* $OpenBSD: sha2.c,v 1.11 2005/08/08 08:05:35 espie Exp $ */ + +/* + * FILE: sha2.c + * AUTHOR: Aaron D. Gifford <me@aarongifford.com> + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * 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 copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 AUTHOR OR CONTRIBUTOR(S) 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. + * + * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ + */ + +/* OPENBSD ORIGINAL: lib/libc/hash/sha2.c */ + +#include "includes.h" + +#include <openssl/opensslv.h> + +#if !defined(HAVE_EVP_SHA256) && !defined(HAVE_SHA256_UPDATE) && \ + (OPENSSL_VERSION_NUMBER >= 0x00907000L) +#include <sys/types.h> +#include <string.h> +#include "sha2.h" + +/* + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +/* + * BYTE_ORDER NOTE: + * + * Please make sure that your system defines BYTE_ORDER. If your + * architecture is little-endian, make sure it also defines + * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are + * equivilent. + * + * If your system does not define the above, then you can do so by + * hand like this: + * + * #define LITTLE_ENDIAN 1234 + * #define BIG_ENDIAN 4321 + * + * And for little-endian machines, add: + * + * #define BYTE_ORDER LITTLE_ENDIAN + * + * Or for big-endian machines: + * + * #define BYTE_ORDER BIG_ENDIAN + * + * The FreeBSD machine this was written on defines BYTE_ORDER + * appropriately by including <sys/types.h> (which in turn includes + * <machine/endian.h> where the appropriate definitions are actually + * made). + */ +#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +#endif + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + +/*** ENDIAN SPECIFIC COPY MACROS **************************************/ +#define BE_8_TO_32(dst, cp) do { \ + (dst) = (u_int32_t)(cp)[3] | ((u_int32_t)(cp)[2] << 8) | \ + ((u_int32_t)(cp)[1] << 16) | ((u_int32_t)(cp)[0] << 24); \ +} while(0) + +#define BE_8_TO_64(dst, cp) do { \ + (dst) = (u_int64_t)(cp)[7] | ((u_int64_t)(cp)[6] << 8) | \ + ((u_int64_t)(cp)[5] << 16) | ((u_int64_t)(cp)[4] << 24) | \ + ((u_int64_t)(cp)[3] << 32) | ((u_int64_t)(cp)[2] << 40) | \ + ((u_int64_t)(cp)[1] << 48) | ((u_int64_t)(cp)[0] << 56); \ +} while (0) + +#define BE_64_TO_8(cp, src) do { \ + (cp)[0] = (src) >> 56; \ + (cp)[1] = (src) >> 48; \ + (cp)[2] = (src) >> 40; \ + (cp)[3] = (src) >> 32; \ + (cp)[4] = (src) >> 24; \ + (cp)[5] = (src) >> 16; \ + (cp)[6] = (src) >> 8; \ + (cp)[7] = (src); \ +} while (0) + +#define BE_32_TO_8(cp, src) do { \ + (cp)[0] = (src) >> 24; \ + (cp)[1] = (src) >> 16; \ + (cp)[2] = (src) >> 8; \ + (cp)[3] = (src); \ +} while (0) + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) do { \ + (w)[0] += (u_int64_t)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} while (0) + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +const static u_int32_t K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +const static u_int32_t sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +const static u_int64_t K512[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +/* Initial hash value H for SHA-384 */ +const static u_int64_t sha384_initial_hash_value[8] = { + 0xcbbb9d5dc1059ed8ULL, + 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, + 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, + 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, + 0x47b5481dbefa4fa4ULL +}; + +/* Initial hash value H for SHA-512 */ +const static u_int64_t sha512_initial_hash_value[8] = { + 0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL +}; + + +/*** SHA-256: *********************************************************/ +void +SHA256_Init(SHA256_CTX *context) +{ + if (context == NULL) + return; + memcpy(context->state, sha256_initial_hash_value, + sizeof(sha256_initial_hash_value)); + memset(context->buffer, 0, sizeof(context->buffer)); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) do { \ + BE_8_TO_32(W256[j], data); \ + data += 4; \ + T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ + j++; \ +} while(0) + +#define ROUND256(a,b,c,d,e,f,g,h) do { \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \ + j++; \ +} while(0) + +void +SHA256_Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH]) +{ + u_int32_t a, b, c, d, e, f, g, h, s0, s1; + u_int32_t T1, W256[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 63: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void +SHA256_Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH]) +{ + u_int32_t a, b, c, d, e, f, g, h, s0, s1; + u_int32_t T1, T2, W256[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + j = 0; + do { + BE_8_TO_32(W256[j], data); + data += 4; + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void +SHA256_Update(SHA256_CTX *context, const u_int8_t *data, size_t len) +{ + size_t freespace, usedspace; + + /* Calling with no data is valid (we do nothing) */ + if (len == 0) + return; + + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + memcpy(&context->buffer[usedspace], data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + SHA256_Transform(context->state, context->buffer); + } else { + /* The buffer is not yet full */ + memcpy(&context->buffer[usedspace], data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA256_Transform(context->state, data); + context->bitcount += SHA256_BLOCK_LENGTH << 3; + len -= SHA256_BLOCK_LENGTH; + data += SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + memcpy(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void +SHA256_Pad(SHA256_CTX *context) +{ + unsigned int usedspace; + + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + memset(&context->buffer[usedspace], 0, + SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA256_BLOCK_LENGTH) { + memset(&context->buffer[usedspace], 0, + SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA256_Transform(context->state, context->buffer); + + /* Prepare for last transform: */ + memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits) in big endian format: */ + BE_64_TO_8(&context->buffer[SHA256_SHORT_BLOCK_LENGTH], + context->bitcount); + + /* Final transform: */ + SHA256_Transform(context->state, context->buffer); + + /* Clean up: */ + usedspace = 0; +} + +void +SHA256_Final(u_int8_t digest[SHA256_DIGEST_LENGTH], SHA256_CTX *context) +{ + SHA256_Pad(context); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != NULL) { +#if BYTE_ORDER == LITTLE_ENDIAN + int i; + + /* Convert TO host byte order */ + for (i = 0; i < 8; i++) + BE_32_TO_8(digest + i * 4, context->state[i]); +#else + memcpy(digest, context->state, SHA256_DIGEST_LENGTH); +#endif + memset(context, 0, sizeof(*context)); + } +} + + +/*** SHA-512: *********************************************************/ +void +SHA512_Init(SHA512_CTX *context) +{ + if (context == NULL) + return; + memcpy(context->state, sha512_initial_hash_value, + sizeof(sha512_initial_hash_value)); + memset(context->buffer, 0, sizeof(context->buffer)); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) do { \ + BE_8_TO_64(W512[j], data); \ + data += 8; \ + T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + W512[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ + j++; \ +} while(0) + + +#define ROUND512(a,b,c,d,e,f,g,h) do { \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \ + j++; \ +} while(0) + +void +SHA512_Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH]) +{ + u_int64_t a, b, c, d, e, f, g, h, s0, s1; + u_int64_t T1, W512[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void +SHA512_Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH]) +{ + u_int64_t a, b, c, d, e, f, g, h, s0, s1; + u_int64_t T1, T2, W512[16]; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + + j = 0; + do { + BE_8_TO_64(W512[j], data); + data += 8; + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void +SHA512_Update(SHA512_CTX *context, const u_int8_t *data, size_t len) +{ + size_t freespace, usedspace; + + /* Calling with no data is valid (we do nothing) */ + if (len == 0) + return; + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + memcpy(&context->buffer[usedspace], data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + SHA512_Transform(context->state, context->buffer); + } else { + /* The buffer is not yet full */ + memcpy(&context->buffer[usedspace], data, len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA512_Transform(context->state, data); + ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + memcpy(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void +SHA512_Pad(SHA512_CTX *context) +{ + unsigned int usedspace; + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + memset(&context->buffer[usedspace], 0, SHA512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA512_BLOCK_LENGTH) { + memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA512_Transform(context->state, context->buffer); + + /* And set-up for the last transform: */ + memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2); + } + } else { + /* Prepare for final transform: */ + memset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits) in big endian format: */ + BE_64_TO_8(&context->buffer[SHA512_SHORT_BLOCK_LENGTH], + context->bitcount[1]); + BE_64_TO_8(&context->buffer[SHA512_SHORT_BLOCK_LENGTH + 8], + context->bitcount[0]); + + /* Final transform: */ + SHA512_Transform(context->state, context->buffer); + + /* Clean up: */ + usedspace = 0; +} + +void +SHA512_Final(u_int8_t digest[SHA512_DIGEST_LENGTH], SHA512_CTX *context) +{ + SHA512_Pad(context); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != NULL) { +#if BYTE_ORDER == LITTLE_ENDIAN + int i; + + /* Convert TO host byte order */ + for (i = 0; i < 8; i++) + BE_64_TO_8(digest + i * 8, context->state[i]); +#else + memcpy(digest, context->state, SHA512_DIGEST_LENGTH); +#endif + memset(context, 0, sizeof(*context)); + } +} + + +#if 0 +/*** SHA-384: *********************************************************/ +void +SHA384_Init(SHA384_CTX *context) +{ + if (context == NULL) + return; + memcpy(context->state, sha384_initial_hash_value, + sizeof(sha384_initial_hash_value)); + memset(context->buffer, 0, sizeof(context->buffer)); + context->bitcount[0] = context->bitcount[1] = 0; +} + +__weak_alias(SHA384_Transform, SHA512_Transform); +__weak_alias(SHA384_Update, SHA512_Update); +__weak_alias(SHA384_Pad, SHA512_Pad); + +void +SHA384_Final(u_int8_t digest[SHA384_DIGEST_LENGTH], SHA384_CTX *context) +{ + SHA384_Pad(context); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != NULL) { +#if BYTE_ORDER == LITTLE_ENDIAN + int i; + + /* Convert TO host byte order */ + for (i = 0; i < 6; i++) + BE_64_TO_8(digest + i * 8, context->state[i]); +#else + memcpy(digest, context->state, SHA384_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + memset(context, 0, sizeof(*context)); +} +#endif + +#endif /* !defined(HAVE_EVP_SHA256) && !defined(HAVE_SHA256_UPDATE) && \ + (OPENSSL_VERSION_NUMBER >= 0x00907000L) */ diff --git a/crypto/openssh/openbsd-compat/sha2.h b/crypto/openssh/openbsd-compat/sha2.h new file mode 100755 index 0000000..821f2dd --- /dev/null +++ b/crypto/openssh/openbsd-compat/sha2.h @@ -0,0 +1,133 @@ +/* $OpenBSD: sha2.h,v 1.6 2004/06/22 01:57:30 jfb Exp $ */ + +/* + * FILE: sha2.h + * AUTHOR: Aaron D. Gifford <me@aarongifford.com> + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * 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 copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 AUTHOR OR CONTRIBUTOR(S) 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. + * + * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ + */ + +/* OPENBSD ORIGINAL: include/sha2.h */ + +#ifndef _SSHSHA2_H +#define _SSHSHA2_H + +#include "includes.h" + +#include <openssl/opensslv.h> + +#if !defined(HAVE_EVP_SHA256) && !defined(HAVE_SHA256_UPDATE) && \ + (OPENSSL_VERSION_NUMBER >= 0x00907000L) + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) + + +/*** SHA-256/384/512 Context Structures *******************************/ +typedef struct _SHA256_CTX { + u_int32_t state[8]; + u_int64_t bitcount; + u_int8_t buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; +typedef struct _SHA512_CTX { + u_int64_t state[8]; + u_int64_t bitcount[2]; + u_int8_t buffer[SHA512_BLOCK_LENGTH]; +} SHA512_CTX; + +#if 0 +typedef SHA512_CTX SHA384_CTX; +#endif + +void SHA256_Init(SHA256_CTX *); +void SHA256_Transform(u_int32_t state[8], const u_int8_t [SHA256_BLOCK_LENGTH]); +void SHA256_Update(SHA256_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA256_Pad(SHA256_CTX *); +void SHA256_Final(u_int8_t [SHA256_DIGEST_LENGTH], SHA256_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA256_DIGEST_LENGTH))); +char *SHA256_End(SHA256_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); +char *SHA256_File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); +char *SHA256_FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA256_DIGEST_STRING_LENGTH))); +char *SHA256_Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA256_DIGEST_STRING_LENGTH))); + +#if 0 +void SHA384_Init(SHA384_CTX *); +void SHA384_Transform(u_int64_t state[8], const u_int8_t [SHA384_BLOCK_LENGTH]); +void SHA384_Update(SHA384_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA384_Pad(SHA384_CTX *); +void SHA384_Final(u_int8_t [SHA384_DIGEST_LENGTH], SHA384_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA384_DIGEST_LENGTH))); +char *SHA384_End(SHA384_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); +char *SHA384_File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); +char *SHA384_FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA384_DIGEST_STRING_LENGTH))); +char *SHA384_Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA384_DIGEST_STRING_LENGTH))); +#endif /* 0 */ + +void SHA512_Init(SHA512_CTX *); +void SHA512_Transform(u_int64_t state[8], const u_int8_t [SHA512_BLOCK_LENGTH]); +void SHA512_Update(SHA512_CTX *, const u_int8_t *, size_t) + __attribute__((__bounded__(__string__,2,3))); +void SHA512_Pad(SHA512_CTX *); +void SHA512_Final(u_int8_t [SHA512_DIGEST_LENGTH], SHA512_CTX *) + __attribute__((__bounded__(__minbytes__,1,SHA512_DIGEST_LENGTH))); +char *SHA512_End(SHA512_CTX *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); +char *SHA512_File(const char *, char *) + __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); +char *SHA512_FileChunk(const char *, char *, off_t, off_t) + __attribute__((__bounded__(__minbytes__,2,SHA512_DIGEST_STRING_LENGTH))); +char *SHA512_Data(const u_int8_t *, size_t, char *) + __attribute__((__bounded__(__string__,1,2))) + __attribute__((__bounded__(__minbytes__,3,SHA512_DIGEST_STRING_LENGTH))); + +#endif /* !defined(HAVE_EVP_SHA256) && !defined(HAVE_SHA256_UPDATE) && \ + (OPENSSL_VERSION_NUMBER >= 0x00907000L) */ + +#endif /* _SSHSHA2_H */ diff --git a/crypto/openssh/openbsd-compat/sigact.c b/crypto/openssh/openbsd-compat/sigact.c new file mode 100644 index 0000000..8b8e4dd --- /dev/null +++ b/crypto/openssh/openbsd-compat/sigact.c @@ -0,0 +1,104 @@ +/* $OpenBSD: sigaction.c,v 1.4 2001/01/22 18:01:48 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +/* OPENBSD ORIGINAL: lib/libcurses/base/sigaction.c */ + +#include "includes.h" +#include <signal.h> +#include "sigact.h" + +/* This file provides sigaction() emulation using sigvec() */ +/* Use only if this is non POSIX system */ + +#if !HAVE_SIGACTION && HAVE_SIGVEC + +int +sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact) +{ + return sigvec(sig, &(sigact->sv), &(osigact->sv)); +} + +int +sigemptyset (sigset_t * mask) +{ + *mask = 0; + return 0; +} + +int +sigprocmask (int mode, sigset_t * mask, sigset_t * omask) +{ + sigset_t current = sigsetmask(0); + + if (omask) *omask = current; + + if (mode==SIG_BLOCK) + current |= *mask; + else if (mode==SIG_UNBLOCK) + current &= ~*mask; + else if (mode==SIG_SETMASK) + current = *mask; + + sigsetmask(current); + return 0; +} + +int +sigsuspend (sigset_t * mask) +{ + return sigpause(*mask); +} + +int +sigdelset (sigset_t * mask, int sig) +{ + *mask &= ~sigmask(sig); + return 0; +} + +int +sigaddset (sigset_t * mask, int sig) +{ + *mask |= sigmask(sig); + return 0; +} + +int +sigismember (sigset_t * mask, int sig) +{ + return (*mask & sigmask(sig)) != 0; +} + +#endif diff --git a/crypto/openssh/openbsd-compat/sigact.h b/crypto/openssh/openbsd-compat/sigact.h new file mode 100644 index 0000000..db96d0a --- /dev/null +++ b/crypto/openssh/openbsd-compat/sigact.h @@ -0,0 +1,90 @@ +/* $OpenBSD: SigAction.h,v 1.3 2001/01/22 18:01:32 millert Exp $ */ + +/**************************************************************************** + * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +/* + * $From: SigAction.h,v 1.6 2000/12/10 02:36:10 tom Exp $ + * + * This file exists to handle non-POSIX systems which don't have <unistd.h>, + * and usually no sigaction() nor <termios.h> + */ + +/* OPENBSD ORIGINAL: lib/libcurses/SigAction.h */ + +#ifndef _SIGACTION_H +#define _SIGACTION_H + +#if !defined(HAVE_SIGACTION) && defined(HAVE_SIGVEC) + +#undef SIG_BLOCK +#define SIG_BLOCK 00 + +#undef SIG_UNBLOCK +#define SIG_UNBLOCK 01 + +#undef SIG_SETMASK +#define SIG_SETMASK 02 + +/* + * <bsd/signal.h> is in the Linux 1.2.8 + gcc 2.7.0 configuration, + * and is useful for testing this header file. + */ +#if HAVE_BSD_SIGNAL_H +# include <bsd/signal.h> +#endif + +struct sigaction +{ + struct sigvec sv; +}; + +typedef unsigned long sigset_t; + +#undef sa_mask +#define sa_mask sv.sv_mask +#undef sa_handler +#define sa_handler sv.sv_handler +#undef sa_flags +#define sa_flags sv.sv_flags + +int sigaction(int sig, struct sigaction *sigact, struct sigaction *osigact); +int sigprocmask (int how, sigset_t *mask, sigset_t *omask); +int sigemptyset (sigset_t *mask); +int sigsuspend (sigset_t *mask); +int sigdelset (sigset_t *mask, int sig); +int sigaddset (sigset_t *mask, int sig); + +#endif /* !defined(HAVE_SIGACTION) && defined(HAVE_SIGVEC) */ + +#endif /* !defined(_SIGACTION_H) */ diff --git a/crypto/openssh/openbsd-compat/strlcat.c b/crypto/openssh/openbsd-compat/strlcat.c new file mode 100644 index 0000000..bcc1b61 --- /dev/null +++ b/crypto/openssh/openbsd-compat/strlcat.c @@ -0,0 +1,62 @@ +/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */ + +#include "includes.h" +#ifndef HAVE_STRLCAT + +#include <sys/types.h> +#include <string.h> + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + +#endif /* !HAVE_STRLCAT */ diff --git a/crypto/openssh/openbsd-compat/strlcpy.c b/crypto/openssh/openbsd-compat/strlcpy.c new file mode 100644 index 0000000..679a5b2 --- /dev/null +++ b/crypto/openssh/openbsd-compat/strlcpy.c @@ -0,0 +1,58 @@ +/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */ + +#include "includes.h" +#ifndef HAVE_STRLCPY + +#include <sys/types.h> +#include <string.h> + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +#endif /* !HAVE_STRLCPY */ diff --git a/crypto/openssh/openbsd-compat/strmode.c b/crypto/openssh/openbsd-compat/strmode.c new file mode 100644 index 0000000..4a81614 --- /dev/null +++ b/crypto/openssh/openbsd-compat/strmode.c @@ -0,0 +1,148 @@ +/* $OpenBSD: strmode.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */ +/*- + * Copyright (c) 1990 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strmode.c */ + +#include "includes.h" +#ifndef HAVE_STRMODE + +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> + +/* XXX mode should be mode_t */ + +void +strmode(int mode, char *p) +{ + /* print type */ + switch (mode & S_IFMT) { + case S_IFDIR: /* directory */ + *p++ = 'd'; + break; + case S_IFCHR: /* character special */ + *p++ = 'c'; + break; + case S_IFBLK: /* block special */ + *p++ = 'b'; + break; + case S_IFREG: /* regular */ + *p++ = '-'; + break; + case S_IFLNK: /* symbolic link */ + *p++ = 'l'; + break; +#ifdef S_IFSOCK + case S_IFSOCK: /* socket */ + *p++ = 's'; + break; +#endif +#ifdef S_IFIFO + case S_IFIFO: /* fifo */ + *p++ = 'p'; + break; +#endif + default: /* unknown */ + *p++ = '?'; + break; + } + /* usr */ + if (mode & S_IRUSR) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWUSR) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXUSR | S_ISUID)) { + case 0: + *p++ = '-'; + break; + case S_IXUSR: + *p++ = 'x'; + break; + case S_ISUID: + *p++ = 'S'; + break; + case S_IXUSR | S_ISUID: + *p++ = 's'; + break; + } + /* group */ + if (mode & S_IRGRP) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWGRP) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXGRP | S_ISGID)) { + case 0: + *p++ = '-'; + break; + case S_IXGRP: + *p++ = 'x'; + break; + case S_ISGID: + *p++ = 'S'; + break; + case S_IXGRP | S_ISGID: + *p++ = 's'; + break; + } + /* other */ + if (mode & S_IROTH) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWOTH) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXOTH | S_ISVTX)) { + case 0: + *p++ = '-'; + break; + case S_IXOTH: + *p++ = 'x'; + break; + case S_ISVTX: + *p++ = 'T'; + break; + case S_IXOTH | S_ISVTX: + *p++ = 't'; + break; + } + *p++ = ' '; /* will be a '+' if ACL's implemented */ + *p = '\0'; +} +#endif diff --git a/crypto/openssh/openbsd-compat/strsep.c b/crypto/openssh/openbsd-compat/strsep.c new file mode 100644 index 0000000..b36eb8f --- /dev/null +++ b/crypto/openssh/openbsd-compat/strsep.c @@ -0,0 +1,79 @@ +/* $OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */ + +/*- + * 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strsep.c */ + +#include "includes.h" + +#if !defined(HAVE_STRSEP) + +#include <string.h> +#include <stdio.h> + +/* + * 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 /* !defined(HAVE_STRSEP) */ diff --git a/crypto/openssh/openbsd-compat/strtoll.c b/crypto/openssh/openbsd-compat/strtoll.c new file mode 100644 index 0000000..f629303 --- /dev/null +++ b/crypto/openssh/openbsd-compat/strtoll.c @@ -0,0 +1,148 @@ +/* $OpenBSD: strtoll.c,v 1.6 2005/11/10 10:00:17 espie Exp $ */ +/*- + * Copyright (c) 1992 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/strtoll.c */ + +#include "includes.h" +#ifndef HAVE_STRTOLL + +#include <sys/types.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +/* + * Convert a string to a long long. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long long +strtoll(const char *nptr, char **endptr, int base) +{ + const char *s; + long long acc, cutoff; + int c; + int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = (unsigned char) *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + 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; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for long longs is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? LLONG_MIN : LLONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + if (neg) { + if (cutlim > 0) { + cutlim -= base; + cutoff += 1; + } + cutlim = -cutlim; + } + 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) + continue; + if (neg) { + if (acc < cutoff || (acc == cutoff && c > cutlim)) { + any = -1; + acc = LLONG_MIN; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc -= c; + } + } else { + if (acc > cutoff || (acc == cutoff && c > cutlim)) { + any = -1; + acc = LLONG_MAX; + errno = ERANGE; + } else { + any = 1; + acc *= base; + acc += c; + } + } + } + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return (acc); +} +#endif /* HAVE_STRTOLL */ diff --git a/crypto/openssh/openbsd-compat/strtonum.c b/crypto/openssh/openbsd-compat/strtonum.c new file mode 100644 index 0000000..87f2f24 --- /dev/null +++ b/crypto/openssh/openbsd-compat/strtonum.c @@ -0,0 +1,72 @@ +/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */ + +/* + * Copyright (c) 2004 Ted Unangst and Todd Miller + * All rights reserved. + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/strtonum.c */ + +#include "includes.h" + +#ifndef HAVE_STRTONUM +#include <stdlib.h> +#include <limits.h> +#include <errno.h> + +#define INVALID 1 +#define TOOSMALL 2 +#define TOOLARGE 3 + +long long +strtonum(const char *numstr, long long minval, long long maxval, + const char **errstrp) +{ + long long ll = 0; + char *ep; + int error = 0; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) + error = INVALID; + else { + ll = strtoll(numstr, &ep, 10); + if (numstr == ep || *ep != '\0') + error = INVALID; + else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + error = TOOSMALL; + else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + ll = 0; + + return (ll); +} + +#endif /* HAVE_STRTONUM */ diff --git a/crypto/openssh/openbsd-compat/strtoul.c b/crypto/openssh/openbsd-compat/strtoul.c new file mode 100644 index 0000000..8219c83 --- /dev/null +++ b/crypto/openssh/openbsd-compat/strtoul.c @@ -0,0 +1,108 @@ +/* $OpenBSD: strtoul.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */ +/* + * Copyright (c) 1990 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/strtoul.c */ + +#include "includes.h" +#ifndef HAVE_STRTOUL + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoul(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long acc, cutoff; + int c; + int neg, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + s = nptr; + do { + c = (unsigned char) *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + 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 = ULONG_MAX / (unsigned long)base; + cutlim = ULONG_MAX % (unsigned 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) + continue; + if (acc > cutoff || acc == cutoff && c > cutlim) { + any = -1; + acc = ULONG_MAX; + errno = ERANGE; + } else { + any = 1; + acc *= (unsigned long)base; + acc += c; + } + } + if (neg && any > 0) + acc = -acc; + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return (acc); +} +#endif /* !HAVE_STRTOUL */ diff --git a/crypto/openssh/openbsd-compat/sys-queue.h b/crypto/openssh/openbsd-compat/sys-queue.h new file mode 100644 index 0000000..4023433 --- /dev/null +++ b/crypto/openssh/openbsd-compat/sys-queue.h @@ -0,0 +1,593 @@ +/* $OpenBSD: queue.h,v 1.25 2004/04/08 16:08:21 henning Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * 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. 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +/* OPENBSD ORIGINAL: sys/sys/queue.h */ + +#ifndef _FAKE_QUEUE_H_ +#define _FAKE_QUEUE_H_ + +/* + * Require for OS/X and other platforms that have old/broken/incomplete + * <sys/queue.h>. + */ +#undef SLIST_HEAD +#undef SLIST_HEAD_INITIALIZER +#undef SLIST_ENTRY +#undef SLIST_FOREACH_PREVPTR +#undef SLIST_FIRST +#undef SLIST_END +#undef SLIST_EMPTY +#undef SLIST_NEXT +#undef SLIST_FOREACH +#undef SLIST_INIT +#undef SLIST_INSERT_AFTER +#undef SLIST_INSERT_HEAD +#undef SLIST_REMOVE_HEAD +#undef SLIST_REMOVE +#undef SLIST_REMOVE_NEXT +#undef LIST_HEAD +#undef LIST_HEAD_INITIALIZER +#undef LIST_ENTRY +#undef LIST_FIRST +#undef LIST_END +#undef LIST_EMPTY +#undef LIST_NEXT +#undef LIST_FOREACH +#undef LIST_INIT +#undef LIST_INSERT_AFTER +#undef LIST_INSERT_BEFORE +#undef LIST_INSERT_HEAD +#undef LIST_REMOVE +#undef LIST_REPLACE +#undef SIMPLEQ_HEAD +#undef SIMPLEQ_HEAD_INITIALIZER +#undef SIMPLEQ_ENTRY +#undef SIMPLEQ_FIRST +#undef SIMPLEQ_END +#undef SIMPLEQ_EMPTY +#undef SIMPLEQ_NEXT +#undef SIMPLEQ_FOREACH +#undef SIMPLEQ_INIT +#undef SIMPLEQ_INSERT_HEAD +#undef SIMPLEQ_INSERT_TAIL +#undef SIMPLEQ_INSERT_AFTER +#undef SIMPLEQ_REMOVE_HEAD +#undef TAILQ_HEAD +#undef TAILQ_HEAD_INITIALIZER +#undef TAILQ_ENTRY +#undef TAILQ_FIRST +#undef TAILQ_END +#undef TAILQ_NEXT +#undef TAILQ_LAST +#undef TAILQ_PREV +#undef TAILQ_EMPTY +#undef TAILQ_FOREACH +#undef TAILQ_FOREACH_REVERSE +#undef TAILQ_INIT +#undef TAILQ_INSERT_HEAD +#undef TAILQ_INSERT_TAIL +#undef TAILQ_INSERT_AFTER +#undef TAILQ_INSERT_BEFORE +#undef TAILQ_REMOVE +#undef TAILQ_REPLACE +#undef CIRCLEQ_HEAD +#undef CIRCLEQ_HEAD_INITIALIZER +#undef CIRCLEQ_ENTRY +#undef CIRCLEQ_FIRST +#undef CIRCLEQ_LAST +#undef CIRCLEQ_END +#undef CIRCLEQ_NEXT +#undef CIRCLEQ_PREV +#undef CIRCLEQ_EMPTY +#undef CIRCLEQ_FOREACH +#undef CIRCLEQ_FOREACH_REVERSE +#undef CIRCLEQ_INIT +#undef CIRCLEQ_INSERT_AFTER +#undef CIRCLEQ_INSERT_BEFORE +#undef CIRCLEQ_INSERT_HEAD +#undef CIRCLEQ_INSERT_TAIL +#undef CIRCLEQ_REMOVE +#undef CIRCLEQ_REPLACE + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != SLIST_END(head); \ + (varp) = &SLIST_NEXT((var), field)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_NEXT(head, elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while( curelm->field.sle_next != (elm) ) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ + if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ +} while (0) + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue access methods + */ +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_END(head) ((void *)(head)) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define CIRCLEQ_EMPTY(head) \ + (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for((var) = CIRCLEQ_FIRST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_NEXT(var, field)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = CIRCLEQ_LAST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_PREV(var, field)) + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = CIRCLEQ_END(head); \ + (head)->cqh_last = CIRCLEQ_END(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = CIRCLEQ_END(head); \ + if ((head)->cqh_last == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = CIRCLEQ_END(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (0) + +#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ + CIRCLEQ_END(head)) \ + (head).cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ + CIRCLEQ_END(head)) \ + (head).cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ +} while (0) + +#endif /* !_FAKE_QUEUE_H_ */ diff --git a/crypto/openssh/openbsd-compat/sys-tree.h b/crypto/openssh/openbsd-compat/sys-tree.h new file mode 100644 index 0000000..c80b90b2 --- /dev/null +++ b/crypto/openssh/openbsd-compat/sys-tree.h @@ -0,0 +1,679 @@ +/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ +/* + * Copyright 2002 Niels Provos <provos@citi.umich.edu> + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +/* OPENBSD ORIGINAL: sys/sys/tree.h */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-back tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ +void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +struct type *name##_RB_REMOVE(struct name *, struct type *); \ +struct type *name##_RB_INSERT(struct name *, struct type *); \ +struct type *name##_RB_FIND(struct name *, struct type *); \ +struct type *name##_RB_NEXT(struct name *, struct type *); \ +struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ +void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +struct type * \ +name##_RB_NEXT(struct name *head, struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(x, y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(head, x)) + +#endif /* _SYS_TREE_H_ */ diff --git a/crypto/openssh/openbsd-compat/tree.h b/crypto/openssh/openbsd-compat/tree.h new file mode 100644 index 0000000..30b4a85 --- /dev/null +++ b/crypto/openssh/openbsd-compat/tree.h @@ -0,0 +1,667 @@ +/* + * Copyright 2002 Niels Provos <provos@citi.umich.edu> + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ + \ +static __inline void \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return; \ + } \ + (head)->sph_root = (elm); \ +} \ + \ +static __inline void \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return; \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + } \ +} \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +void name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-back tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + RB_AUGMENT(RB_PARENT(elm, field)); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + RB_AUGMENT(RB_PARENT(elm, field)); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ +void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +void name##_RB_REMOVE(struct name *, struct type *); \ +struct type *name##_RB_INSERT(struct name *, struct type *); \ +struct type *name##_RB_FIND(struct name *, struct type *); \ +struct type *name##_RB_NEXT(struct name *, struct type *); \ +struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ +void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +void \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *old = elm, *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +struct type * \ +name##_RB_NEXT(struct name *head, struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(x, y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(head, x)) + +#endif /* _SYS_TREE_H_ */ diff --git a/crypto/openssh/openbsd-compat/vis.c b/crypto/openssh/openbsd-compat/vis.c new file mode 100644 index 0000000..3a087b3 --- /dev/null +++ b/crypto/openssh/openbsd-compat/vis.c @@ -0,0 +1,225 @@ +/* $OpenBSD: vis.c,v 1.19 2005/09/01 17:15:49 millert Exp $ */ +/*- + * Copyright (c) 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. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/vis.c */ + +#include "includes.h" +#if !defined(HAVE_STRNVIS) + +#include <ctype.h> +#include <string.h> + +#include "vis.h" + +#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') +#define isvisible(c) \ + (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \ + (((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \ + (flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) || \ + ((flag & VIS_SP) == 0 && (c) == ' ') || \ + ((flag & VIS_TAB) == 0 && (c) == '\t') || \ + ((flag & VIS_NL) == 0 && (c) == '\n') || \ + ((flag & VIS_SAFE) && ((c) == '\b' || \ + (c) == '\007' || (c) == '\r' || \ + isgraph((u_char)(c))))) + +/* + * vis - visually encode characters + */ +char * +vis(char *dst, int c, int flag, int nextc) +{ + if (isvisible(c)) { + *dst++ = c; + if (c == '\\' && (flag & VIS_NOSLASH) == 0) + *dst++ = '\\'; + *dst = '\0'; + return (dst); + } + + if (flag & VIS_CSTYLE) { + switch(c) { + case '\n': + *dst++ = '\\'; + *dst++ = 'n'; + goto done; + case '\r': + *dst++ = '\\'; + *dst++ = 'r'; + goto done; + case '\b': + *dst++ = '\\'; + *dst++ = 'b'; + goto done; + case '\a': + *dst++ = '\\'; + *dst++ = 'a'; + goto done; + case '\v': + *dst++ = '\\'; + *dst++ = 'v'; + goto done; + case '\t': + *dst++ = '\\'; + *dst++ = 't'; + goto done; + case '\f': + *dst++ = '\\'; + *dst++ = 'f'; + goto done; + case ' ': + *dst++ = '\\'; + *dst++ = 's'; + goto done; + case '\0': + *dst++ = '\\'; + *dst++ = '0'; + if (isoctal(nextc)) { + *dst++ = '0'; + *dst++ = '0'; + } + goto done; + } + } + if (((c & 0177) == ' ') || (flag & VIS_OCTAL) || + ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) { + *dst++ = '\\'; + *dst++ = ((u_char)c >> 6 & 07) + '0'; + *dst++ = ((u_char)c >> 3 & 07) + '0'; + *dst++ = ((u_char)c & 07) + '0'; + goto done; + } + if ((flag & VIS_NOSLASH) == 0) + *dst++ = '\\'; + if (c & 0200) { + c &= 0177; + *dst++ = 'M'; + } + if (iscntrl((u_char)c)) { + *dst++ = '^'; + if (c == 0177) + *dst++ = '?'; + else + *dst++ = c + '@'; + } else { + *dst++ = '-'; + *dst++ = c; + } +done: + *dst = '\0'; + return (dst); +} + +/* + * strvis, strnvis, strvisx - visually encode characters from src into dst + * + * Dst must be 4 times the size of src to account for possible + * expansion. The length of dst, not including the trailing NULL, + * is returned. + * + * Strnvis will write no more than siz-1 bytes (and will NULL terminate). + * The number of bytes needed to fully encode the string is returned. + * + * Strvisx encodes exactly len bytes from src into dst. + * This is useful for encoding a block of data. + */ +int +strvis(char *dst, const char *src, int flag) +{ + char c; + char *start; + + for (start = dst; (c = *src);) + dst = vis(dst, c, flag, *++src); + *dst = '\0'; + return (dst - start); +} + +int +strnvis(char *dst, const char *src, size_t siz, int flag) +{ + char *start, *end; + char tbuf[5]; + int c, i; + + i = 0; + for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) { + if (isvisible(c)) { + i = 1; + *dst++ = c; + if (c == '\\' && (flag & VIS_NOSLASH) == 0) { + /* need space for the extra '\\' */ + if (dst < end) + *dst++ = '\\'; + else { + dst--; + i = 2; + break; + } + } + src++; + } else { + i = vis(tbuf, c, flag, *++src) - tbuf; + if (dst + i <= end) { + memcpy(dst, tbuf, i); + dst += i; + } else { + src--; + break; + } + } + } + if (siz > 0) + *dst = '\0'; + if (dst + i > end) { + /* adjust return value for truncation */ + while ((c = *src)) + dst += vis(tbuf, c, flag, *++src) - tbuf; + } + return (dst - start); +} + +int +strvisx(char *dst, const char *src, size_t len, int flag) +{ + char c; + char *start; + + for (start = dst; len > 1; len--) { + c = *src; + dst = vis(dst, c, flag, *++src); + } + if (len) + dst = vis(dst, *src, flag, '\0'); + *dst = '\0'; + return (dst - start); +} + +#endif diff --git a/crypto/openssh/openbsd-compat/vis.h b/crypto/openssh/openbsd-compat/vis.h new file mode 100644 index 0000000..3898a9e --- /dev/null +++ b/crypto/openssh/openbsd-compat/vis.h @@ -0,0 +1,95 @@ +/* $OpenBSD: vis.h,v 1.11 2005/08/09 19:38:31 millert Exp $ */ +/* $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $ */ + +/*- + * Copyright (c) 1990 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. 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. + * + * @(#)vis.h 5.9 (Berkeley) 4/3/91 + */ + +/* OPENBSD ORIGINAL: include/vis.h */ + +#include "includes.h" +#if !defined(HAVE_STRNVIS) + +#ifndef _VIS_H_ +#define _VIS_H_ + +#include <sys/types.h> +#include <limits.h> + +/* + * to select alternate encoding format + */ +#define VIS_OCTAL 0x01 /* use octal \ddd format */ +#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */ + +/* + * to alter set of characters encoded (default is to encode all + * non-graphic except space, tab, and newline). + */ +#define VIS_SP 0x04 /* also encode space */ +#define VIS_TAB 0x08 /* also encode tab */ +#define VIS_NL 0x10 /* also encode newline */ +#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) +#define VIS_SAFE 0x20 /* only encode "unsafe" characters */ + +/* + * other + */ +#define VIS_NOSLASH 0x40 /* inhibit printing '\' */ +#define VIS_GLOB 0x100 /* encode glob(3) magics and '#' */ + +/* + * unvis return codes + */ +#define UNVIS_VALID 1 /* character valid */ +#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */ +#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */ +#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */ +#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */ + +/* + * unvis flags + */ +#define UNVIS_END 1 /* no more characters */ + +char *vis(char *, int, int, int); +int strvis(char *, const char *, int); +int strnvis(char *, const char *, size_t, int) + __attribute__ ((__bounded__(__string__,1,3))); +int strvisx(char *, const char *, size_t, int) + __attribute__ ((__bounded__(__string__,1,3))); +int strunvis(char *, const char *); +int unvis(char *, char, int *, int); +ssize_t strnunvis(char *, const char *, size_t) + __attribute__ ((__bounded__(__string__,1,3))); + +#endif /* !_VIS_H_ */ + +#endif /* !HAVE_STRNVIS */ diff --git a/crypto/openssh/openbsd-compat/xcrypt.c b/crypto/openssh/openbsd-compat/xcrypt.c new file mode 100644 index 0000000..1489932 --- /dev/null +++ b/crypto/openssh/openbsd-compat/xcrypt.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2003 Ben Lindstrom. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <unistd.h> +#include <pwd.h> + +# ifdef HAVE_CRYPT_H +# include <crypt.h> +# endif + +# ifdef __hpux +# include <hpsecurity.h> +# include <prot.h> +# endif + +# ifdef HAVE_SECUREWARE +# include <sys/security.h> +# include <sys/audit.h> +# include <prot.h> +# endif + +# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) +# include <shadow.h> +# endif + +# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) +# include <sys/label.h> +# include <sys/audit.h> +# include <pwdadj.h> +# endif + +# if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) +# include "md5crypt.h" +# endif + +char * +xcrypt(const char *password, const char *salt) +{ + char *crypted; + +# ifdef HAVE_MD5_PASSWORDS + if (is_md5_salt(salt)) + crypted = md5_crypt(password, salt); + else + crypted = crypt(password, salt); +# elif defined(__hpux) && !defined(HAVE_SECUREWARE) + if (iscomsec()) + crypted = bigcrypt(password, salt); + else + crypted = crypt(password, salt); +# elif defined(HAVE_SECUREWARE) + crypted = bigcrypt(password, salt); +# else + crypted = crypt(password, salt); +# endif + + return crypted; +} + +/* + * Handle shadowed password systems in a cleaner way for portable + * version. + */ + +char * +shadow_pw(struct passwd *pw) +{ + char *pw_password = pw->pw_passwd; + +# if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) + struct spwd *spw = getspnam(pw->pw_name); + + if (spw != NULL) + pw_password = spw->sp_pwdp; +# endif + +#if defined(HAVE_LIBIAF) && !defined(BROKEN_LIBIAF) + return(get_iaf_password(pw)); +#endif + +# if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) + struct passwd_adjunct *spw; + if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL) + pw_password = spw->pwa_passwd; +# elif defined(HAVE_SECUREWARE) + struct pr_passwd *spw = getprpwnam(pw->pw_name); + + if (spw != NULL) + pw_password = spw->ufld.fd_encrypt; +# endif + + return pw_password; +} diff --git a/crypto/openssh/openbsd-compat/xmmap.c b/crypto/openssh/openbsd-compat/xmmap.c new file mode 100644 index 0000000..0fb2326 --- /dev/null +++ b/crypto/openssh/openbsd-compat/xmmap.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002 Tim Rice. All rights reserved. + * MAP_FAILED code by Solar Designer. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +/* $Id: xmmap.c,v 1.12 2006/08/24 09:58:36 dtucker Exp $ */ + +#include "includes.h" + +#include <sys/types.h> +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <sys/stat.h> + +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif +#include <errno.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> + +#include "log.h" + +void *xmmap(size_t size) +{ +#ifdef HAVE_MMAP + void *address; + +# ifdef MAP_ANON + address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, + -1, (off_t)0); +# else + address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED, + open("/dev/zero", O_RDWR), (off_t)0); +# endif + +#define MM_SWAP_TEMPLATE "/var/run/sshd.mm.XXXXXXXX" + if (address == (void *)MAP_FAILED) { + char tmpname[sizeof(MM_SWAP_TEMPLATE)] = MM_SWAP_TEMPLATE; + int tmpfd; + mode_t old_umask; + + old_umask = umask(0177); + tmpfd = mkstemp(tmpname); + umask(old_umask); + if (tmpfd == -1) + fatal("mkstemp(\"%s\"): %s", + MM_SWAP_TEMPLATE, strerror(errno)); + unlink(tmpname); + ftruncate(tmpfd, size); + address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED, + tmpfd, (off_t)0); + close(tmpfd); + } + + return (address); +#else + fatal("%s: UsePrivilegeSeparation=yes and Compression=yes not supported", + __func__); +#endif /* HAVE_MMAP */ + +} + |