From 099d1a58f7bc088a9f71af6d32542ca3949468a3 Mon Sep 17 00:00:00 2001 From: des Date: Tue, 29 Oct 2002 09:43:00 +0000 Subject: Vendor import of OpenSSH-portable 3.5p1. --- crypto/openssh/openbsd-compat/Makefile.in | 4 +- crypto/openssh/openbsd-compat/base64.c | 5 +- crypto/openssh/openbsd-compat/bindresvport.c | 2 +- crypto/openssh/openbsd-compat/bsd-cray.c | 613 +++++++++++++++++++--- crypto/openssh/openbsd-compat/bsd-cray.h | 17 +- crypto/openssh/openbsd-compat/bsd-getpeereid.c | 56 ++ crypto/openssh/openbsd-compat/bsd-getpeereid.h | 14 + crypto/openssh/openbsd-compat/bsd-misc.c | 6 +- crypto/openssh/openbsd-compat/dirname.c | 8 +- crypto/openssh/openbsd-compat/getcwd.c | 2 +- crypto/openssh/openbsd-compat/getopt.c | 2 +- crypto/openssh/openbsd-compat/glob.c | 45 +- crypto/openssh/openbsd-compat/glob.h | 18 +- crypto/openssh/openbsd-compat/inet_ntoa.c | 6 +- crypto/openssh/openbsd-compat/inet_ntop.c | 51 +- crypto/openssh/openbsd-compat/mktemp.c | 6 +- crypto/openssh/openbsd-compat/openbsd-compat.h | 3 +- crypto/openssh/openbsd-compat/port-aix.c | 45 +- crypto/openssh/openbsd-compat/port-aix.h | 30 +- crypto/openssh/openbsd-compat/readpassphrase.c | 35 +- crypto/openssh/openbsd-compat/readpassphrase.h | 5 +- crypto/openssh/openbsd-compat/realpath.c | 6 +- crypto/openssh/openbsd-compat/rresvport.c | 2 +- crypto/openssh/openbsd-compat/setenv.c | 2 +- crypto/openssh/openbsd-compat/sigact.c | 2 +- crypto/openssh/openbsd-compat/strlcat.c | 2 +- crypto/openssh/openbsd-compat/strlcpy.c | 2 +- crypto/openssh/openbsd-compat/strsep.c | 2 +- crypto/openssh/openbsd-compat/sys-queue.h | 584 +++++++++++++++++++++ crypto/openssh/openbsd-compat/sys-tree.h | 675 +++++++++++++++++++++++++ crypto/openssh/openbsd-compat/xmmap.c | 67 +++ crypto/openssh/openbsd-compat/xmmap.h | 23 + 32 files changed, 2170 insertions(+), 170 deletions(-) create mode 100644 crypto/openssh/openbsd-compat/bsd-getpeereid.c create mode 100644 crypto/openssh/openbsd-compat/bsd-getpeereid.h create mode 100644 crypto/openssh/openbsd-compat/sys-queue.h create mode 100644 crypto/openssh/openbsd-compat/sys-tree.h create mode 100644 crypto/openssh/openbsd-compat/xmmap.c create mode 100644 crypto/openssh/openbsd-compat/xmmap.h (limited to 'crypto/openssh/openbsd-compat') diff --git a/crypto/openssh/openbsd-compat/Makefile.in b/crypto/openssh/openbsd-compat/Makefile.in index 3e09cfe..5229e7e 100644 --- a/crypto/openssh/openbsd-compat/Makefile.in +++ b/crypto/openssh/openbsd-compat/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.21 2002/02/19 20:27:57 mouring Exp $ +# $Id: Makefile.in,v 1.23 2002/09/12 00:33:02 djm Exp $ sysconfdir=@sysconfdir@ piddir=@piddir@ @@ -18,7 +18,7 @@ LDFLAGS=-L. @LDFLAGS@ OPENBSD=base64.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o -COMPAT=bsd-arc4random.o bsd-cray.o bsd-cygwin_util.o bsd-misc.o bsd-nextstep.o bsd-snprintf.o bsd-waitpid.o fake-getaddrinfo.o fake-getnameinfo.o +COMPAT=bsd-arc4random.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-snprintf.o bsd-waitpid.o fake-getaddrinfo.o fake-getnameinfo.o xmmap.o PORTS=port-irix.o port-aix.o diff --git a/crypto/openssh/openbsd-compat/base64.c b/crypto/openssh/openbsd-compat/base64.c index d12b993..005170b 100644 --- a/crypto/openssh/openbsd-compat/base64.c +++ b/crypto/openssh/openbsd-compat/base64.c @@ -1,4 +1,4 @@ -/* $OpenBSD: base64.c,v 1.3 1997/11/08 20:46:55 deraadt Exp $ */ +/* $OpenBSD: base64.c,v 1.4 2002/01/02 23:00:10 deraadt Exp $ */ /* * Copyright (c) 1996 by Internet Software Consortium. @@ -42,7 +42,7 @@ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ -#include "config.h" +#include "includes.h" #if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) @@ -60,6 +60,7 @@ #include "base64.h" +/* XXX abort illegal in library */ #define Assert(Cond) if (!(Cond)) abort() static const char Base64[] = diff --git a/crypto/openssh/openbsd-compat/bindresvport.c b/crypto/openssh/openbsd-compat/bindresvport.c index 332bcb0..620f980 100644 --- a/crypto/openssh/openbsd-compat/bindresvport.c +++ b/crypto/openssh/openbsd-compat/bindresvport.c @@ -29,7 +29,7 @@ * Mountain View, California 94043 */ -#include "config.h" +#include "includes.h" #ifndef HAVE_BINDRESVPORT_SA diff --git a/crypto/openssh/openbsd-compat/bsd-cray.c b/crypto/openssh/openbsd-compat/bsd-cray.c index 9bab75b..edb3112 100644 --- a/crypto/openssh/openbsd-compat/bsd-cray.c +++ b/crypto/openssh/openbsd-compat/bsd-cray.c @@ -1,5 +1,5 @@ /* - * $Id: bsd-cray.c,v 1.6 2002/05/15 16:39:51 mouring Exp $ + * $Id: bsd-cray.c,v 1.8 2002/09/26 00:38:51 tim Exp $ * * bsd-cray.c * @@ -34,8 +34,8 @@ * on UNICOS systems. * */ +#ifdef _UNICOS -#ifdef _CRAY #include #include #include @@ -45,19 +45,33 @@ #include #include #include +#include #include #include #include +#include #include +#include #include #include #include #include - +#include +#include +#include "ssh.h" +#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. */ @@ -65,68 +79,538 @@ 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(); + fsent.revision = 0; + fsent.uname = username; + fsent.host = (char *)get_canonical_hostname(options.verify_reverse_mapping); + 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); +} /* - * Orignal written by: - * Wayne Schroeder - * San Diego Supercomputer Center - * schroeder@sdsc.edu -*/ -void -cray_setup(uid_t uid, char *username) + * Cray access denied + */ +int +cray_access_denied(char *username) { - struct udb *p; + 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 && ueptr->ue_disabled) + errcode = IA_DISABLED; + if (errcode) + cray_login_failure(username, errcode); + return (errcode); +} + +int +cray_setup (uid_t uid, char *username, const char *command) +{ + extern struct udb *getudb(); extern char *setlimits(); - int i, j; - int accts[MAXVIDS]; - int naccts; - int err; - char *sr; - int pid; - struct jtab jbuf; - int jid; - if ((jid = getjtab(&jbuf)) < 0) - fatal("getjtab: no jid"); - - err = setudb(); /* open and rewind the Cray User DataBase */ - if (err != 0) - fatal("UDB open failure"); - naccts = 0; - p = getudbnam(username); - if (p == NULL) - fatal("No UDB entry for %.100s", username); - if (uid != p->ue_uid) - fatal("UDB entry %.100s uid(%d) does not match uid %d", - username, (int) p->ue_uid, (int) uid); - for (j = 0; p->ue_acids[j] != -1 && j < MAXVIDS; j++) { - accts[naccts] = p->ue_acids[j]; - naccts++; + 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_t pwdacm, + pwddialup, + pwdudb, + pwdwal, + pwddce; /* passwd stuff for ia_user */ + 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) { + debug("getusrv() failed, errno = %d",errno); + exit(1); + } } - endudb(); /* close the udb */ - - if (naccts != 0) { - /* Perhaps someday we'll prompt users who have multiple accounts - to let them pick one (like CRI's login does), but for now just set - the account to the first entry. */ - if (acctid(0, accts[0]) < 0) - fatal("System call acctid failed, accts[0]=%d", accts[0]); + hostname[0] = '\0'; + strncpy(hostname, + (char *)get_canonical_hostname(options.verify_reverse_mapping), + MAXHOSTNAMELEN); + /* + * Fetch user's UDB entry. + */ + getsysudb(); + if ((up = getudbnam(username)) == UDB_NULL) { + debug("cannot fetch user's UDB entry"); + exit(1); + } + + /* + * 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) { + debug("IA uid missmatch"); + exit(1); + } + endudb(); + + if ((jid = getjtab (&jtab)) < 0) { + debug("getjtab"); + return -1; + } + pid = getpid(); + ttyn = ttyname(0); + if (SecureSys) { + if (ttyn) { + secstatrc = secstat(ttyn, &secinfo); + } else { + secstatrc = fsecstat(1, &secinfo); + } + if (secstatrc == 0) { + debug("[f]secstat() successful"); + } else { + debug("[f]secstat() error, rc = %d", secstatrc); + exit(1); + } + } + 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: + strcpy(ue.ue_name, "root"); + strcpy(ue.ue_passwd, ""); + strcpy(ue.ue_dir, "/"); + strcpy(ue.ue_shell, "/bin/sh"); + strcpy(ue.ue_age, ""); + strcpy(ue.ue_comment, ""); + strcpy(ue.ue_loghost, ""); + strcpy(ue.ue_logline, ""); + ue.ue_uid=-1; + ue.ue_nice[UDBRC_INTER]=0; + for (i=0;i 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_DIALUPERR: + 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_LOCALHOST: + break; + case IA_MAXLOGS: + printf ("Maximum number of failed login attempts exceeded.\n"); + printf ("Access denied.\n"); + break; + case IA_NOPASS: + break; + case IA_PUBLIC: + break; + case IA_SECURIDERR: + break; + case IA_CONSOLE: + break; + case IA_TRUSTED: + break; + case IA_UDBERR: + break; + case IA_UDBPWDNULL: + /* + * NULL password not allowed on MLS systems + */ + if (SecureSys) { + printf("NULL Password not allowed on MLS systems.\n"); + } + break; + case IA_UNKNOWN: + break; + case IA_UNKNOWNYP: + break; + case IA_WALERR: + break; + default: + /* nothing special */ + ; + } /* 2. switch (ia_rcode) */ + /* + * 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); + } /* 1. switch (ia_rcode) */ + 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); } - /* Now set limits, including CPU time for the (interactive) job and process, - and set up permissions (for chown etc), etc. This is via an internal CRI - routine, setlimits, used by CRI's login. */ + /* 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])); + gets(acct_name); + switch (acct_name[0]) { + case EOF: + exit(0); + break; + case '\0': + valid_acct = ue.ue_acids[0]; + strcpy(acct_name, acid2nam(valid_acct)); + 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: + if ((valid_acct = nam2acid(acct_name)) == -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); + } + +/* set up shares and quotas */ +/* 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); + } - pid = getpid(); sr = setlimits(username, C_PROC, pid, UDBRC_INTER); - if (sr != NULL) - fatal("%.200s", sr); - + if (sr != NULL) { + debug("%.200s", sr); + exit(1); + } sr = setlimits(username, C_JOB, jid, UDBRC_INTER); - if (sr != NULL) - fatal("%.200s", sr); + 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. + */ + bzero((char *)&init_info, sizeof(struct servprov)); + init_info.s_sessinit.si_id = URM_SPT_LOGIN; + init_info.s_sessinit.si_pid = getpid(); + init_info.s_sessinit.si_sid = jid; + init_info.s_routing.seqno = 0; + init_info.s_routing.iadrs = 0; + 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); } /* @@ -143,7 +627,6 @@ drop_cray_privs() int result; extern int priv_set_proc(); extern priv_proc_t* priv_init_proc(); - struct usrv usrv; /* * If ether of theses two flags are not set @@ -154,9 +637,23 @@ drop_cray_privs() if (!sysconf(_SC_CRAY_POSIX_PRIV)) fatal("Not POSIX_PRIV."); - debug("Dropping privileges."); + 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); - memset(&usrv, 0, sizeof(usrv)); if (setusrv(&usrv) < 0) fatal("%s(%d): setusrv(): %s", __FILE__, __LINE__, strerror(errno)); @@ -189,7 +686,6 @@ cray_retain_utmp(struct utmp *ut, int pid) while (read(fd, (char *)&utmp, sizeof(utmp)) == sizeof(utmp)) { if (pid == utmp.ut_pid) { ut->ut_jid = utmp.ut_jid; - /* XXX: MIN_SIZEOF here? can this go in loginrec? */ 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)); @@ -198,7 +694,8 @@ cray_retain_utmp(struct utmp *ut, int pid) } close(fd); } - /* XXX: error message? */ + else + fatal("Unable to open utmp file"); } /* @@ -245,7 +742,7 @@ cray_job_termination_handler(int sig) char *login = NULL; struct jtab jtab; - debug("Received SIG JOB."); + debug("received signal %d",sig); if ((jid = waitjob(&jtab)) == -1 || (login = uid2nam(jtab.j_uid)) == NULL) diff --git a/crypto/openssh/openbsd-compat/bsd-cray.h b/crypto/openssh/openbsd-compat/bsd-cray.h index 9067a38..8868b43 100644 --- a/crypto/openssh/openbsd-compat/bsd-cray.h +++ b/crypto/openssh/openbsd-compat/bsd-cray.h @@ -1,5 +1,5 @@ /* - * $Id: bsd-cray.h,v 1.3 2002/05/15 16:39:52 mouring Exp $ + * $Id: bsd-cray.h,v 1.5 2002/09/26 00:38:51 tim Exp $ * * bsd-cray.h * @@ -37,11 +37,18 @@ #ifndef _BSD_CRAY_H #define _BSD_CRAY_H -#ifdef _CRAY -void cray_init_job(struct passwd *); /* init cray job */ -void cray_job_termination_handler(int); /* process end of job signal */ -void cray_setup(uid_t, char *); /* set cray limits */ +#ifdef _UNICOS +void cray_init_job(struct passwd *); /* init cray job */ +void cray_job_termination_handler(int); /* process end of job signal */ +void cray_login_failure(char *username, int errcode); +int cray_access_denied(char *username); extern char cray_tmpdir[]; /* cray tmpdir */ +#ifndef IA_SSHD +#define IA_SSHD IA_LOGIN +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif #endif #endif /* _BSD_CRAY_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..c787682 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-getpeereid.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002 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. + */ + +#include "includes.h" + +RCSID("$Id: bsd-getpeereid.c,v 1.1 2002/09/12 00:33:02 djm Exp $"); + +#if !defined(HAVE_GETPEEREID) + +#if defined(SO_PEERCRED) +int +getpeereid(int s, uid_t *euid, gid_t *gid) +{ + struct ucred cred; + size_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-getpeereid.h b/crypto/openssh/openbsd-compat/bsd-getpeereid.h new file mode 100644 index 0000000..2e9f077 --- /dev/null +++ b/crypto/openssh/openbsd-compat/bsd-getpeereid.h @@ -0,0 +1,14 @@ +/* $Id: bsd-getpeereid.h,v 1.1 2002/09/12 00:33:02 djm Exp $ */ + +#ifndef _BSD_GETPEEREID_H +#define _BSD_GETPEEREID_H + +#include "config.h" + +#include /* For uid_t, gid_t */ + +#ifndef HAVE_GETPEEREID +int getpeereid(int , uid_t *, gid_t *); +#endif /* HAVE_GETPEEREID */ + +#endif /* _BSD_GETPEEREID_H */ diff --git a/crypto/openssh/openbsd-compat/bsd-misc.c b/crypto/openssh/openbsd-compat/bsd-misc.c index fa48afe..1c1e43a 100644 --- a/crypto/openssh/openbsd-compat/bsd-misc.c +++ b/crypto/openssh/openbsd-compat/bsd-misc.c @@ -24,7 +24,7 @@ #include "includes.h" -RCSID("$Id: bsd-misc.c,v 1.8 2002/06/13 21:34:58 mouring Exp $"); +RCSID("$Id: bsd-misc.c,v 1.10 2002/07/08 21:09:41 mouring Exp $"); char *get_progname(char *argv0) { @@ -93,8 +93,8 @@ int utimes(char *filename, struct timeval *tvp) { struct utimbuf ub; - ub.actime = tvp->tv_sec; - ub.modtime = tvp->tv_usec; + ub.actime = tvp[0].tv_sec; + ub.modtime = tvp[1].tv_sec; return(utime(filename, &ub)); } diff --git a/crypto/openssh/openbsd-compat/dirname.c b/crypto/openssh/openbsd-compat/dirname.c index 391b2dd..35c7d8e 100644 --- a/crypto/openssh/openbsd-compat/dirname.c +++ b/crypto/openssh/openbsd-compat/dirname.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dirname.c,v 1.6 2001/06/28 04:27:19 pjanzen Exp $ */ +/* $OpenBSD: dirname.c,v 1.7 2002/05/24 21:22:37 deraadt Exp $ */ /* * Copyright (c) 1997 Todd C. Miller @@ -31,7 +31,7 @@ #ifndef HAVE_DIRNAME #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: dirname.c,v 1.6 2001/06/28 04:27:19 pjanzen Exp $"; +static char rcsid[] = "$OpenBSD: dirname.c,v 1.7 2002/05/24 21:22:37 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -47,7 +47,7 @@ dirname(path) /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { - (void)strcpy(bname, "."); + (void)strlcpy(bname, ".", sizeof bname); return(bname); } @@ -62,7 +62,7 @@ dirname(path) /* Either the dir is "/" or there are no slashes */ if (endp == path) { - (void)strcpy(bname, *endp == '/' ? "/" : "."); + (void)strlcpy(bname, *endp == '/' ? "/" : ".", sizeof bname); return(bname); } else { do { diff --git a/crypto/openssh/openbsd-compat/getcwd.c b/crypto/openssh/openbsd-compat/getcwd.c index de3bacc..6fd8543 100644 --- a/crypto/openssh/openbsd-compat/getcwd.c +++ b/crypto/openssh/openbsd-compat/getcwd.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. */ -#include "config.h" +#include "includes.h" #if !defined(HAVE_GETCWD) diff --git a/crypto/openssh/openbsd-compat/getopt.c b/crypto/openssh/openbsd-compat/getopt.c index f4fbc9b..4a5cfe5 100644 --- a/crypto/openssh/openbsd-compat/getopt.c +++ b/crypto/openssh/openbsd-compat/getopt.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -#include "config.h" +#include "includes.h" #if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) #if defined(LIBC_SCCS) && !defined(lint) diff --git a/crypto/openssh/openbsd-compat/glob.c b/crypto/openssh/openbsd-compat/glob.c index 365d433..e928a22 100644 --- a/crypto/openssh/openbsd-compat/glob.c +++ b/crypto/openssh/openbsd-compat/glob.c @@ -56,7 +56,7 @@ get_arg_max(void) #if 0 static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; #else -static char rcsid[] = "$OpenBSD: glob.c,v 1.16 2001/04/05 18:36:12 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: glob.c,v 1.20 2002/06/14 21:34:58 todd Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -97,6 +97,7 @@ static char rcsid[] = "$OpenBSD: glob.c,v 1.16 2001/04/05 18:36:12 deraadt Exp $ #define RBRACKET ']' #define SEP '/' #define STAR '*' +#undef TILDE /* Some platforms may already define it */ #define TILDE '~' #define UNDERSCORE '_' #define LBRACE '{' @@ -136,32 +137,32 @@ typedef char Char; #define ismeta(c) (((c)&M_QUOTE) != 0) -static int compare __P((const void *, const void *)); -static int g_Ctoc __P((const Char *, char *, u_int)); -static int g_lstat __P((Char *, struct stat *, glob_t *)); -static DIR *g_opendir __P((Char *, glob_t *)); -static Char *g_strchr __P((Char *, int)); -static int g_stat __P((Char *, struct stat *, glob_t *)); -static int glob0 __P((const Char *, glob_t *)); -static int glob1 __P((Char *, Char *, glob_t *, size_t *)); -static int glob2 __P((Char *, Char *, Char *, Char *, Char *, Char *, - glob_t *, size_t *)); -static int glob3 __P((Char *, Char *, Char *, Char *, Char *, Char *, - Char *, Char *, glob_t *, size_t *)); -static int globextend __P((const Char *, glob_t *, size_t *)); +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 __P((const Char *, Char *, size_t, glob_t *)); -static int globexp1 __P((const Char *, glob_t *)); -static int globexp2 __P((const Char *, const Char *, glob_t *, int *)); -static int match __P((Char *, Char *, 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 __P((const char *, Char *)); +static void qprintf(const char *, Char *); #endif int glob(pattern, flags, errfunc, pglob) const char *pattern; - int flags, (*errfunc) __P((const char *, int)); + int flags, (*errfunc)(const char *, int); glob_t *pglob; { const u_char *patnext; @@ -676,7 +677,7 @@ glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, /* - * Extend the gl_pathv member of a glob_t structure to accomodate a new item, + * 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 @@ -821,7 +822,7 @@ g_opendir(str, pglob) char buf[MAXPATHLEN]; if (!*str) - strcpy(buf, "."); + strlcpy(buf, ".", sizeof buf); else { if (g_Ctoc(str, buf, sizeof(buf))) return(NULL); diff --git a/crypto/openssh/openbsd-compat/glob.h b/crypto/openssh/openbsd-compat/glob.h index b4c8f7a..6421f70 100644 --- a/crypto/openssh/openbsd-compat/glob.h +++ b/crypto/openssh/openbsd-compat/glob.h @@ -1,4 +1,4 @@ -/* $OpenBSD: glob.h,v 1.5 2001/03/18 17:18:58 deraadt Exp $ */ +/* $OpenBSD: glob.h,v 1.7 2002/02/17 19:42:21 millert Exp $ */ /* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */ /* @@ -53,18 +53,18 @@ typedef struct { 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) __P((const char *, int)); + 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) __P((void *)); - struct dirent *(*gl_readdir) __P((void *)); - void *(*gl_opendir) __P((const char *)); - int (*gl_lstat) __P((const char *, struct stat *)); - int (*gl_stat) __P((const char *, struct stat *)); + 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 */ @@ -91,8 +91,8 @@ typedef struct { #define GLOB_NOSYS (-4) /* Function not supported. */ #define GLOB_ABEND GLOB_ABORTED -int glob __P((const char *, int, int (*)(const char *, int), glob_t *)); -void globfree __P((glob_t *)); +int glob(const char *, int, int (*)(const char *, int), glob_t *); +void globfree(glob_t *); #endif /* !_GLOB_H_ */ diff --git a/crypto/openssh/openbsd-compat/inet_ntoa.c b/crypto/openssh/openbsd-compat/inet_ntoa.c index 8a8b3c8..ac5f567 100644 --- a/crypto/openssh/openbsd-compat/inet_ntoa.c +++ b/crypto/openssh/openbsd-compat/inet_ntoa.c @@ -31,12 +31,12 @@ * SUCH DAMAGE. */ -#include "config.h" +#include "includes.h" #if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: inet_ntoa.c,v 1.2 1996/08/19 08:29:16 tholo Exp $"; +static char rcsid[] = "$OpenBSD: inet_ntoa.c,v 1.3 2002/06/27 10:14:01 itojun Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -57,7 +57,7 @@ char *inet_ntoa(struct in_addr in) p = (char *)∈ #define UC(b) (((int)b)&0xff) (void)snprintf(b, sizeof(b), - "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); + "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); return (b); } diff --git a/crypto/openssh/openbsd-compat/inet_ntop.c b/crypto/openssh/openbsd-compat/inet_ntop.c index 2b8d31f..3bea519 100644 --- a/crypto/openssh/openbsd-compat/inet_ntop.c +++ b/crypto/openssh/openbsd-compat/inet_ntop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $ */ +/* $OpenBSD: inet_ntop.c,v 1.5 2002/08/23 16:27:31 itojun Exp $ */ /* Copyright (c) 1996 by Internet Software Consortium. * @@ -16,7 +16,7 @@ * SOFTWARE. */ -#include "config.h" +#include "includes.h" #ifndef HAVE_INET_NTOP @@ -24,7 +24,7 @@ #if 0 static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $"; #else -static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $"; +static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.5 2002/08/23 16:27:31 itojun Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -54,8 +54,8 @@ static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Ex * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ -static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); -static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); +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) @@ -103,13 +103,14 @@ inet_ntop4(src, dst, size) { static const char fmt[] = "%u.%u.%u.%u"; char tmp[sizeof "255.255.255.255"]; + int l; - if (snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], - src[3]) > size) { + l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]); + if (l <= 0 || l >= size) { errno = ENOSPC; return (NULL); } - strcpy(dst, tmp); + strlcpy(dst, tmp, size); return (dst); } @@ -132,10 +133,12 @@ inet_ntop6(src, dst, size) * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ - char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + 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: @@ -172,31 +175,45 @@ inet_ntop6(src, dst, size) * Format the result. */ tp = tmp; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + 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 (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 (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, sizeof tmp - (tp - tmp))) + if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) return (NULL); tp += strlen(tp); break; } - snprintf(tp, sizeof(tmp - (tp - tmp)), "%x", words[i]); - tp += strlen(tp); + 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 (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { + if (tp + 1 >= ep) + return (NULL); *tp++ = ':'; + } + if (tp + 1 >= ep) + return (NULL); *tp++ = '\0'; /* @@ -206,7 +223,7 @@ inet_ntop6(src, dst, size) errno = ENOSPC; return (NULL); } - strcpy(dst, tmp); + strlcpy(dst, tmp, size); return (dst); } diff --git a/crypto/openssh/openbsd-compat/mktemp.c b/crypto/openssh/openbsd-compat/mktemp.c index d69dc5c..d256ee4 100644 --- a/crypto/openssh/openbsd-compat/mktemp.c +++ b/crypto/openssh/openbsd-compat/mktemp.c @@ -39,7 +39,7 @@ #ifndef HAVE_MKDTEMP #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: mktemp.c,v 1.14 2002/01/02 20:18:32 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: mktemp.c,v 1.16 2002/05/27 18:20:45 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #ifdef HAVE_CYGWIN @@ -102,11 +102,11 @@ _gettemp(path, doopen, domkdir, slen) return (0); } pid = getpid(); - while (*trv == 'X' && pid != 0) { + while (trv >= path && *trv == 'X' && pid != 0) { *trv-- = (pid % 10) + '0'; pid /= 10; } - while (*trv == 'X') { + while (trv >= path && *trv == 'X') { char c; pid = (arc4random() & 0xffff) % (26+26); diff --git a/crypto/openssh/openbsd-compat/openbsd-compat.h b/crypto/openssh/openbsd-compat/openbsd-compat.h index 1191844..ae18afd 100644 --- a/crypto/openssh/openbsd-compat/openbsd-compat.h +++ b/crypto/openssh/openbsd-compat/openbsd-compat.h @@ -1,4 +1,4 @@ -/* $Id: openbsd-compat.h,v 1.16 2002/02/19 20:27:57 mouring Exp $ */ +/* $Id: openbsd-compat.h,v 1.17 2002/09/12 00:33:02 djm Exp $ */ #ifndef _OPENBSD_H #define _OPENBSD_H @@ -29,6 +29,7 @@ /* Home grown routines */ #include "bsd-arc4random.h" +#include "bsd-getpeereid.h" #include "bsd-misc.h" #include "bsd-snprintf.h" #include "bsd-waitpid.h" diff --git a/crypto/openssh/openbsd-compat/port-aix.c b/crypto/openssh/openbsd-compat/port-aix.c index ca0a88e..4c96a31 100644 --- a/crypto/openssh/openbsd-compat/port-aix.c +++ b/crypto/openssh/openbsd-compat/port-aix.c @@ -1,3 +1,28 @@ +/* + * + * Copyright (c) 2001 Gert Doering. 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 _AIX @@ -6,21 +31,21 @@ #include <../xmalloc.h> /* - * 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 + * 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, char *tty, int ttyfd) +aix_usrinfo(struct passwd *pw) { u_int i; - char *cp=NULL; + char *cp; - if (ttyfd == -1) - tty[0] = '\0'; - cp = xmalloc(22 + strlen(tty) + 2 * strlen(pw->pw_name)); - i = sprintf(cp, "LOGNAME=%s%cNAME=%s%cTTY=%s%c%c", pw->pw_name, 0, - pw->pw_name, 0, tty, 0, 0); + cp = xmalloc(16 + 2 * strlen(pw->pw_name)); + i = sprintf(cp, "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); diff --git a/crypto/openssh/openbsd-compat/port-aix.h b/crypto/openssh/openbsd-compat/port-aix.h index e4d14f4..79570a2 100644 --- a/crypto/openssh/openbsd-compat/port-aix.h +++ b/crypto/openssh/openbsd-compat/port-aix.h @@ -1,5 +1,29 @@ -#ifdef _AIX - -void aix_usrinfo(struct passwd *pw, char *tty, int ttyfd); +/* + * + * Copyright (c) 2001 Gert Doering. 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 +void aix_usrinfo(struct passwd *pw); #endif /* _AIX */ diff --git a/crypto/openssh/openbsd-compat/readpassphrase.c b/crypto/openssh/openbsd-compat/readpassphrase.c index 8c2f5f8..4e549b6 100644 --- a/crypto/openssh/openbsd-compat/readpassphrase.c +++ b/crypto/openssh/openbsd-compat/readpassphrase.c @@ -1,7 +1,7 @@ -/* $OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $ */ +/* $OpenBSD: readpassphrase.c,v 1.14 2002/06/28 01:43:58 millert Exp $ */ /* - * Copyright (c) 2000 Todd C. Miller + * Copyright (c) 2000-2002 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $"; +static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.14 2002/06/28 01:43:58 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include "includes.h" @@ -60,8 +60,8 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) int input, output, save_errno; char ch, *p, *end; struct termios term, oterm; - struct sigaction sa, saveint, savehup, savequit, saveterm; - struct sigaction savetstp, savettin, savettou; + 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) { @@ -70,11 +70,13 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) } 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 ((input = output = open(_PATH_TTY, O_RDWR)) == -1) { + if ((flags & RPP_STDIN) || + (input = output = open(_PATH_TTY, O_RDWR)) == -1) { if (flags & RPP_REQUIRE_TTY) { errno = ENOTTY; return(NULL); @@ -86,13 +88,15 @@ restart: /* * Catch signals that would otherwise cause the user to end * up with echo turned off in the shell. Don't worry about - * things like SIGALRM and SIGPIPE for now. + * 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(SIGINT, &sa, &saveint); + (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); @@ -100,7 +104,7 @@ restart: (void)sigaction(SIGTTOU, &sa, &savettou); /* Turn off echo if possible. */ - if (tcgetattr(input, &oterm) == 0) { + if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { memcpy(&term, &oterm, sizeof(term)); if (!(flags & RPP_ECHO_ON)) term.c_lflag &= ~(ECHO | ECHONL); @@ -111,10 +115,13 @@ restart: (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; } - (void)write(output, prompt, strlen(prompt)); + 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) { @@ -137,13 +144,14 @@ restart: /* Restore old terminal settings and signals. */ if (memcmp(&term, &oterm, sizeof(term)) != 0) (void)tcsetattr(input, _T_FLUSH, &oterm); - (void)sigaction(SIGINT, &saveint, NULL); + (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); - (void)sigaction(SIGTTOU, &savettou, NULL); if (input != STDIN_FILENO) (void)close(input); @@ -152,12 +160,11 @@ restart: * now that we have restored the signal handlers. */ if (signo) { - kill(getpid(), signo); + kill(getpid(), signo); switch (signo) { case SIGTSTP: case SIGTTIN: case SIGTTOU: - signo = 0; goto restart; } } diff --git a/crypto/openssh/openbsd-compat/readpassphrase.h b/crypto/openssh/openbsd-compat/readpassphrase.h index 9077b6e..92908a4 100644 --- a/crypto/openssh/openbsd-compat/readpassphrase.h +++ b/crypto/openssh/openbsd-compat/readpassphrase.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readpassphrase.h,v 1.1 2000/11/21 00:48:38 millert Exp $ */ +/* $OpenBSD: readpassphrase.h,v 1.3 2002/06/28 12:32:22 millert Exp $ */ /* * Copyright (c) 2000 Todd C. Miller @@ -40,8 +40,9 @@ #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); +char * readpassphrase(const char *, char *, size_t, int); #endif /* HAVE_READPASSPHRASE */ diff --git a/crypto/openssh/openbsd-compat/realpath.c b/crypto/openssh/openbsd-compat/realpath.c index b4a05db..b9035ca 100644 --- a/crypto/openssh/openbsd-compat/realpath.c +++ b/crypto/openssh/openbsd-compat/realpath.c @@ -32,7 +32,7 @@ #if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: realpath.c,v 1.6 2002/01/12 16:24:35 millert Exp $"; +static char *rcsid = "$OpenBSD: realpath.c,v 1.7 2002/05/24 21:22:37 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -69,7 +69,7 @@ realpath(const char *path, char *resolved) /* Save the starting point. */ getcwd(start,MAXPATHLEN); if ((fd = open(".", O_RDONLY)) < 0) { - (void)strcpy(resolved, "."); + (void)strlcpy(resolved, ".", MAXPATHLEN); return (NULL); } close(fd); @@ -129,7 +129,7 @@ loop: * Save the last component name and get the full pathname of * the current directory. */ - (void)strcpy(wbuf, p); + (void)strlcpy(wbuf, p, sizeof wbuf); if (getcwd(resolved, MAXPATHLEN) == 0) goto err1; diff --git a/crypto/openssh/openbsd-compat/rresvport.c b/crypto/openssh/openbsd-compat/rresvport.c index 44eac20..9f05896 100644 --- a/crypto/openssh/openbsd-compat/rresvport.c +++ b/crypto/openssh/openbsd-compat/rresvport.c @@ -33,7 +33,7 @@ * SUCH DAMAGE. */ -#include "config.h" +#include "includes.h" #ifndef HAVE_RRESVPORT_AF diff --git a/crypto/openssh/openbsd-compat/setenv.c b/crypto/openssh/openbsd-compat/setenv.c index 6c2d5cd..1dff15c 100644 --- a/crypto/openssh/openbsd-compat/setenv.c +++ b/crypto/openssh/openbsd-compat/setenv.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -#include "config.h" +#include "includes.h" #ifndef HAVE_SETENV #if defined(LIBC_SCCS) && !defined(lint) diff --git a/crypto/openssh/openbsd-compat/sigact.c b/crypto/openssh/openbsd-compat/sigact.c index 806eb02..35fbab0 100644 --- a/crypto/openssh/openbsd-compat/sigact.c +++ b/crypto/openssh/openbsd-compat/sigact.c @@ -33,7 +33,7 @@ * and: Eric S. Raymond * ****************************************************************************/ -#include "config.h" +#include "includes.h" #include #include "sigact.h" diff --git a/crypto/openssh/openbsd-compat/strlcat.c b/crypto/openssh/openbsd-compat/strlcat.c index 6ff65c1..3a9b5d1 100644 --- a/crypto/openssh/openbsd-compat/strlcat.c +++ b/crypto/openssh/openbsd-compat/strlcat.c @@ -27,7 +27,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#include "includes.h" #ifndef HAVE_STRLCAT #if defined(LIBC_SCCS) && !defined(lint) diff --git a/crypto/openssh/openbsd-compat/strlcpy.c b/crypto/openssh/openbsd-compat/strlcpy.c index b5e5a55..2f87eca 100644 --- a/crypto/openssh/openbsd-compat/strlcpy.c +++ b/crypto/openssh/openbsd-compat/strlcpy.c @@ -27,7 +27,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#include "includes.h" #ifndef HAVE_STRLCPY #if defined(LIBC_SCCS) && !defined(lint) diff --git a/crypto/openssh/openbsd-compat/strsep.c b/crypto/openssh/openbsd-compat/strsep.c index c03649c..d0afc44 100644 --- a/crypto/openssh/openbsd-compat/strsep.c +++ b/crypto/openssh/openbsd-compat/strsep.c @@ -33,7 +33,7 @@ * SUCH DAMAGE. */ -#include "config.h" +#include "includes.h" #if !defined(HAVE_STRSEP) diff --git a/crypto/openssh/openbsd-compat/sys-queue.h b/crypto/openssh/openbsd-compat/sys-queue.h new file mode 100644 index 0000000..176fe31 --- /dev/null +++ b/crypto/openssh/openbsd-compat/sys-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 since older platforms have broken/incomplete + * 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/sys-tree.h b/crypto/openssh/openbsd-compat/sys-tree.h new file mode 100644 index 0000000..0a58710 --- /dev/null +++ b/crypto/openssh/openbsd-compat/sys-tree.h @@ -0,0 +1,675 @@ +/* $OpenBSD: tree.h,v 1.6 2002/06/11 22:09:52 provos Exp $ */ +/* + * Copyright 2002 Niels Provos + * 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); \ +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); \ + 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 *);\ +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/xmmap.c b/crypto/openssh/openbsd-compat/xmmap.c new file mode 100644 index 0000000..8f1d202 --- /dev/null +++ b/crypto/openssh/openbsd-compat/xmmap.c @@ -0,0 +1,67 @@ +/* + * 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_SYS_MMAN_H +#include +#endif + +#include "log.h" + +void *xmmap(size_t size) +{ + void *address; + +#ifdef HAVE_MMAP +# ifdef MAP_ANON + address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, + -1, 0); +# else + address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED, + open("/dev/zero", O_RDWR), 0); +# endif + +#define MM_SWAP_TEMPLATE "/var/run/sshd.mm.XXXXXXXX" + if (address == MAP_FAILED) { + char tmpname[sizeof(MM_SWAP_TEMPLATE)] = MM_SWAP_TEMPLATE; + int tmpfd; + + tmpfd = mkstemp(tmpname); + 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, 0); + close(tmpfd); + } + + return (address); +#else + fatal("%s: UsePrivilegeSeparation=yes and Compression=yes not supported", + __func__); +#endif /* HAVE_MMAP */ + +} + diff --git a/crypto/openssh/openbsd-compat/xmmap.h b/crypto/openssh/openbsd-compat/xmmap.h new file mode 100644 index 0000000..c0fa04a --- /dev/null +++ b/crypto/openssh/openbsd-compat/xmmap.h @@ -0,0 +1,23 @@ +/* + * 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. + */ + +void *xmmap(size_t size); -- cgit v1.1