On 2015-02-10 9:55 AM, Bob Beck wrote:
The way to get attention around here is show diffs :)

On Tue, Feb 10, 2015 at 12:51 AM, aixtools<aixto...@gmail.com>  wrote:
L.S.,

Trying for a bit over a week to gt a response re: libressl.

1) If you have a established mailing-list for libressl - I did not find it.
That of course says something about me - and maybe you are trying to keep
people who cannot seek well enough away. I can only hope that you take this
as intended - a hint you are hard to find.
2) I have some patches/ideas that could be a step forward to having
libressl-portable be buildable/packageable for AIX 5.3 TL7 and up.

Looking forward to your reply,

regards,
Michael Felt
(aka @rootvgnet, http://www.rootvg.net)


Then first the simple diff's :)

diff -ur libressl-2.1.3/configure libressl-2.1.3.save/configure
--- libressl-2.1.3/configure    2015-01-21 14:42:11 +0000
+++ libressl-2.1.3.save/configure       2015-02-08 14:25:22 +0000
@@ -3049,7 +3049,16 @@
                PLATFORM_LDADD='-lnsl -lsocket'

                ;;
-       *) ;;
+       *aix*)
+               HOST_OS=aix
+               CFLAGS=""
+               PLATFORM_LDADD='-lpthread'
+
+               ;;
+       *)
+               echo $host_os not found
+               exit
+               ;;
 esac

 case $host_cpu in
diff -ur libressl-2.1.3/crypto/compat/arc4random.h libressl-2.1.3.save/crypto/compat/arc4random.h
--- libressl-2.1.3/crypto/compat/arc4random.h   2015-01-21 14:04:57 +0000
+++ libressl-2.1.3.save/crypto/compat/arc4random.h 2015-02-08 15:16:01 +0000
@@ -6,6 +6,9 @@
 #if defined(__FreeBSD__)
 #include "arc4random_freebsd.h"

+#elif defined(_AIX)
+#include "arc4random_aix.h"
+
 #elif defined(__hpux)
 #include "arc4random_hpux.h"

For arc4random_aix.h I was lazy and just copied arc4random_hpux.h

root@x064:[/data/prj/openbsd/libressl/libressl-2.1.3.save/crypto/compat]diff arc4random_hpux.h arc4random_aix.h root@x064:[/data/prj/openbsd/libressl/libressl-2.1.3.save/crypto/compat]ls -l arc4random_hpux.h arc4random_aix.h
-rw-r--r-- 1 michael felt   2193 Feb  8 15:13 arc4random_aix.h
-rw-r--r-- 1 root    system 2193 Jan 21 11:46 arc4random_hpux.h

And the attachments:
root@x064:[/data/prj/openbsd/libressl/libressl-2.1.3.save/crypto/compat]ls -l *aix.c
-rw-r--r-- 1 michael felt 13110 Feb  9 17:19 getentropy_aix.c
-rw-r--r-- 1 michael felt  2401 Feb  9 17:19 issetugid_aix.c

As I do not understand, in detail, what the pseudo entrophy routines are doing I am guessing I made an error, i.e., may be introducing some non-randomness by using the mod (%) operator on the PURR register counters that run in nanoseconds. I may have left the size at sizeof(u_long_long_t) while the 'random' part is smaller (so high 0 bits not random).

To link on AIX - to support errlog() -lrts is needed (both non-root/root can write to errpt for this event). Whether you want to use the syslog_r addition - especially the part looking up the process name (depends on /proc, so also potentially affected by a chroot() environment).

Basically, ideas.

I have not change the makefile in compat to add the *aix.o files into the archive.

Comments welcome!

Michael

p.s. compiling on AIX 5.3 TL7 - 5300-07-10-0943, using IBM C compiler V11, on a Power6

/*      $OpenBSD: $     */

/*
 * Copyright (c) 2015 Michael Felt <aixto...@gmail.com>
 * Copyright (c) 2014 Theo de Raadt <dera...@openbsd.org>
 * Copyright (c) 2014 Bob Beck <b...@obtuse.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Intended to Emulate getentropy(2) as documented at:
 * http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
 */
/*
 * -lperfstat is needed for the psuedo entropy data
 * -lrst is needed for errlog
 * also, cc_r, or equivelent is needed for syslog_r (multi-thread safe 
libraries)
 */

#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/timers.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <termios.h>
#include <errno.h>

#include <openssl/sha.h>

#include <libperfstat.h>

#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))

#define HX(a, b) \
        do { \
                if ((a)) \
                        HD(errno); \
                else \
                        HD(b); \
        } while (0)

#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))

int     getentropy(void *buf, size_t len);

static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
    int devfscheck);
static int getentropy_fallback(void *buf, size_t len);

static const char URANDOM_DEVICE[] = "/dev/urandom";

#include <sys/err_rec.h>
#include <sys/errids.h>
static void aix_errlog(char *device, char *details)
{
/*
/usr/include/sys/err_rec.h:#define ERR_NAMESIZE 16
/usr/include/sys/errids.h:#define ERRID_OPMSG          0xaa8ab241
*/
/*
 * ERR_REC_MAX is the maximum amount of detail data that can be logged.
 * However, due to non-volatile memory constraints, it is possible for an
 * entry with more than 2048 bytes of detail data to be truncated across a
 * reboot in certain circumstances.
 * Entries with more than 2048 bytes of detail data are intended for
 * restricted system use only.
#define ERR_REC_MAX  4096
 */
        ERR_REC(1024) erN;

        erN.error_id = ERRID_OPMSG;
        strncpy(erN.resource_name, device, ERR_NAMESIZE);
        strcat(erN.detail_data, details);

/*
 * to these and any other OPERATOR messages use:
 * errpt -j aa8ab241
 * or
 * errpt -aj aa8ab241
 *
 * to read ONLY these messages about /dev/urandom use
 * errpt -N /dev/urandom
 * or
 * errpt -aN /dev/urandom
 * or
 * errpt -N /proc # for syslog problems
 */
        errlog((void *) &erN, sizeof(erN));
}

#include <sys/procfs.h>
static char * aix_procname(void)
{
        static char prgname[32];

        if (strlen(prgname) != 0) {
                return(prgname);
        } else {
                char str[128];
                int ret;
                psinfo_t psinfo;
                int errval = 0;

                int fd;

                sprintf(str,"/proc/%d/psinfo", getpid());
                fd = open(str,O_RDONLY);
                if (fd >= 0) { /* chroot() ed programs probably do not have 
/proc available ! */
                        ret = read(fd, &psinfo, sizeof(psinfo));
                        errval = errno;
                        close(fd);
                        fd = -1;
                        if (ret == sizeof(psinfo)) {
                                strncpy(prgname,psinfo.pr_fname,32);
                                return(prgname);
                        }
                        else {
                                static int counter;
                                char message[512];
                                /*
                                 * do not know how often this might be called
                                 * for now message once every 10 attempts
                                 */
                                if (!(counter++ % 10)) {
                                        sprintf(message,"%s: Unavailable: 
errno:%3d", str, errval);
                                        aix_errlog("/proc",message);
                                }
                        }
                }
        }
        return(NULL);
}

#include <sys/syslog.h>
static void aix_syslog(char *message)
{
        struct syslog_data syslogData = SYSLOG_DATA_INIT;
        struct syslog_data *sysLogDataPtr = &syslogData;
        static int log_open = 0;
        int     ret_v;
        char    tag[32];

        strncpy(tag,aix_procname(),32);
        if (!log_open) {
                ret_v = openlog_r (tag, LOG_PID|LOG_CONS|LOG_NDELAY|LOG_NOWAIT,
                                LOG_AUTH|LOG_USER, sysLogDataPtr);
                if (ret_v != 0)
                        aix_errlog("syslog_r", "openlog_r failed");
        }
        else
                log_open = 1;
        setlogmask_r (LOG_UPTO (LOG_WARNING), sysLogDataPtr);

        ret_v = syslog_r (LOG_WARNING, sysLogDataPtr, message);
        if (ret_v != 0) {
                char message[512];
                sprintf(message,"syslog_r: errno: %d\n",errno);
                aix_errorlog("syslog_r", message);
        }
}

int
getentropy(void *buf, size_t len)
{
        int ret = -1;

        if (len > 256) {
                errno = EIO;
                return -1;
        }

        /*
         * Try to get entropy with /dev/urandom
         */
        ret = getentropy_urandom(buf, len, URANDOM_DEVICE, 0);
        if (ret != -1)
                return (ret);

        /*
         * Entropy collection via /dev/urandom has failed.
         */

        aix_errlog((char *) URANDOM_DEVICE, "unavailable. getentropy_fallback() 
called");
        aix_syslog("/dev/urandom failed. getentropy_fallback() called");
        /*
         * No other API exists for collecting entropy
         *
         *     - Return EIO, to hint that arc4random's stir function
         *       should raise(SIGKILL)
         *     - Do the best under the circumstances....
         *
         * This code path exists to bring light to the issue that AIX
         * may not provide a failsafe API for entropy collection.
         *
         * We hope this demonstrates that AIX can provide limited information
         * in a chroot or when file descriptors are exhausted.
         */
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
        raise(SIGKILL);
#endif
        ret = getentropy_fallback(buf, len);
        if (ret != -1)
                return (ret);

        errno = EIO;
        return (ret);
}

/*
 * Basic sanity checking; wish we could do better.
 */
static int
gotdata(char *buf, size_t len)
{
        char    any_set = 0;
        size_t  i;

        for (i = 0; i < len; ++i)
                any_set |= buf[i];
        if (any_set == 0)
                return -1;
        return 0;
}

static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
        struct stat st;
        size_t i;
        int fd, flags;
        int save_errno = errno;

start:

        flags = O_RDONLY;
#ifdef O_NOFOLLOW
        flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
        flags |= O_CLOEXEC;
#endif
        fd = open(path, flags, 0);
        if (fd == -1) {
                if (errno == EINTR)
                        goto start;
                goto nodevrandom;
        }
#ifndef O_CLOEXEC
        fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif

        /* Lightly verify that the device node looks sane */
        if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
                close(fd);
                goto nodevrandom;
        }
        for (i = 0; i < len; ) {
                size_t wanted = len - i;
                ssize_t ret = read(fd, (char *)buf + i, wanted);

                if (ret == -1) {
                        if (errno == EAGAIN || errno == EINTR)
                                continue;
                        close(fd);
                        goto nodevrandom;
                }
                i += ret;
        }
        close(fd);
        if (gotdata(buf, len) == 0) {
                errno = save_errno;
                return 0;               /* satisfied */
        }
nodevrandom:
        errno = EIO;
        return -1;
}

static const int cl[] = {
        CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
        CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
        CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
        CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
        CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
        CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
        CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
        CLOCK_THREAD_CPUTIME_ID,
#endif
};

static int
getentropy_fallback(void *buf, size_t len)
{
        uint8_t results[SHA512_DIGEST_LENGTH];
        int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, 
repeat;
        static int cnt;
        struct timespec ts;
        struct timeval tv;
        struct rusage ru;
        sigset_t sigset;
        struct stat st;
        SHA512_CTX ctx;
        static pid_t lastpid;
        pid_t pid;
        size_t i, ii, m;
        char *p;

        pid = getpid();
        if (lastpid == pid) {
                faster = 1;
                repeat = 2;
        } else {
                faster = 0;
                lastpid = pid;
                repeat = REPEAT;
        }
        for (i = 0; i < len; ) {
                int j;
                perfstat_partition_total_t lparstats;

                SHA512_Init(&ctx);
                HX((e = perfstat_partition_total(NULL, &lparstats, 
sizeof(perfstat_partition_total_t), 1)) != 0, lparstats);
                if (e != 0) {
                        perror("perfstat_partition_total");
                }
                else
                {
                        u_longlong_t ul;
                        cnt += (int) ((lparstats.puser + lparstats.psys) % 
100000);
                        ul = (lparstats.pool_idle_time % 1000000);
                        if (ul == 0) {  /* dedicated partition or no access to 
pool stats OR maybe just zero! */
                                ul = (lparstats.puser % 1000000);
                                HD(ul);
                                ul = (lparstats.psys % 1000000);
                                HD(ul);
                                ul = (lparstats.pwait % 10000);
                                HD(ul);
                        }
                        else
                        {
                                HD(ul);
                                ul = (lparstats.shcpu_scaled_busy_time % 
1000000);
                                HD(ul);
                        }
                }
                for (j = 0; j < repeat; j++) {
                        HX((e = gettimeofday(&tv, NULL)) == -1, tv);
                        if (e != -1) {
                                cnt += (int)tv.tv_sec;
                                cnt += (int)tv.tv_usec;
                        }

                        for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
                                HX(clock_gettime(cl[ii], &ts) == -1, ts);

                        HX((pid = getpid()) == -1, pid);
                        HX((pid = getsid(pid)) == -1, pid);
                        HX((pid = getppid()) == -1, pid);
                        HX((pid = getpgid(0)) == -1, pid);
                        HX((e = getpriority(0, 0)) == -1, e);

                        if (!faster) {
                                ts.tv_sec = 0;
                                ts.tv_nsec = 1;
                                (void) nanosleep(&ts, NULL);
                        }

                        HX(sigpending(&sigset) == -1, sigset);
                        HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
                            sigset);

                        HF(getentropy); /* an addr in this library */
                        HF(printf);             /* an addr in libc */
                        p = (char *)&p;
                        HD(p);          /* an addr on stack */
                        p = (char *)&errno;
                        HD(p);          /* the addr of errno */

                        if (i == 0) {
                                struct sockaddr_storage ss;
                                struct statvfs stvfs;
                                struct termios tios;
                                socklen_t ssl;
                                off_t off;

                                /*
                                 * Prime-sized mappings encourage fragmentation;
                                 * thus exposing some address entropy.
                                 */
                                struct mm {
                                        size_t  npg;
                                        void    *p;
                                } mm[] =         {
                                        { 17, MAP_FAILED }, { 3, MAP_FAILED },
                                        { 11, MAP_FAILED }, { 2, MAP_FAILED },
                                        { 5, MAP_FAILED }, { 3, MAP_FAILED },
                                        { 7, MAP_FAILED }, { 1, MAP_FAILED },
                                        { 57, MAP_FAILED }, { 3, MAP_FAILED },
                                        { 131, MAP_FAILED }, { 1, MAP_FAILED },
                                };

                                for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
                                        HX(mm[m].p = mmap(NULL,
                                            mm[m].npg * pgs,
                                            PROT_READ|PROT_WRITE,
                                            MAP_PRIVATE|MAP_ANON, -1,
                                            (off_t)0), mm[m].p);
                                        if (mm[m].p != MAP_FAILED) {
                                                size_t mo;

                                                /* Touch some memory... */
                                                p = mm[m].p;
                                                mo = cnt %
                                                    (mm[m].npg * pgs - 1);
                                                p[mo] = 1;
                                                cnt += (int)((long)(mm[m].p)
                                                    / pgs);
                                        }

                                        /* Check cnts and times... */
                                        for (ii = 0; ii < 
sizeof(cl)/sizeof(cl[0]);
                                            ii++) {
                                                HX((e = clock_gettime(cl[ii],
                                                    &ts)) == -1, ts);
                                                if (e != -1)
                                                        cnt += (int)ts.tv_nsec;
                                        }

                                        HX((e = getrusage(RUSAGE_SELF,
                                            &ru)) == -1, ru);
                                        if (e != -1) {
                                                cnt += (int)ru.ru_utime.tv_sec;
                                                cnt += (int)ru.ru_utime.tv_usec;
                                        }
                                }

                                for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
                                        if (mm[m].p != MAP_FAILED)
                                                munmap(mm[m].p, mm[m].npg * 
pgs);
                                        mm[m].p = MAP_FAILED;
                                }

                                HX(stat(".", &st) == -1, st);
                                HX(statvfs(".", &stvfs) == -1, stvfs);

                                HX(stat("/", &st) == -1, st);
                                HX(statvfs("/", &stvfs) == -1, stvfs);

                                HX((e = fstat(0, &st)) == -1, st);
                                if (e == -1) {
                                        if (S_ISREG(st.st_mode) ||
                                            S_ISFIFO(st.st_mode) ||
                                            S_ISSOCK(st.st_mode)) {
                                                HX(fstatvfs(0, &stvfs) == -1,
                                                    stvfs);
                                                HX((off = lseek(0, (off_t)0,
                                                    SEEK_CUR)) < 0, off);
                                        }
                                        if (S_ISCHR(st.st_mode)) {
                                                HX(tcgetattr(0, &tios) == -1,
                                                    tios);
                                        } else if (S_ISSOCK(st.st_mode)) {
                                                memset(&ss, 0, sizeof ss);
                                                ssl = sizeof(ss);
                                                HX(getpeername(0,
                                                    (void *)&ss, &ssl) == -1,
                                                    ss);
                                        }
                                }

                                HX((e = getrusage(RUSAGE_CHILDREN,
                                    &ru)) == -1, ru);
                                if (e != -1) {
                                        cnt += (int)ru.ru_utime.tv_sec;
                                        cnt += (int)ru.ru_utime.tv_usec;
                                }
                        } else {
                                /* Subsequent hashes absorb previous result */
                                HD(results);
                        }

                        HX((e = gettimeofday(&tv, NULL)) == -1, tv);
                        if (e != -1) {
                                cnt += (int)tv.tv_sec;
                                cnt += (int)tv.tv_usec;
                        }

                        HD(cnt);
                }
                SHA512_Final(results, &ctx);
                memcpy((char *)buf + i, results, min(sizeof(results), len - i));
                i += min(sizeof(results), len - i);
        }
        explicit_bzero(&ctx, sizeof ctx);
        explicit_bzero(results, sizeof results);
        if (gotdata(buf, len) == 0) {
                errno = save_errno;
                return 0;               /* satisfied */
        }
        errno = EIO;
        return -1;
}
/*      $OpenBSD: $     */

/*
 * Copyright (c) 2015 Michael Felt <aixto...@gmail.com>
 * Copyright (c) 2014 Theo de Raadt <dera...@openbsd.org>
 * Copyright (c) 2014 Bob Beck <b...@obtuse.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/pstat.h>

/*
 * AIX does not have issetugid().
 * This experimental implementation uses getpriv() and get*id().
 * First, try getpriv() and check equality of pv_priv values
 * When these values are equal, using get*id() including login uid.
 *
 */
int issetugid(void)
{
        /*
         * effective priv is what I can do now
         * inherited priv is what the caller gave or could have given
         * basically when inherited == 0 and effective != 0 then
         * some kind of priv escalation has occurred
         * when 'demoted' -- inherited != 0 but effective == 0
         * there is also a change, so, will report 1 as well - to be safe
         */
        priv_t  epriv,ipriv;
        int     luid;
        int     euid,ruid;
        int pe0,pe1;
        int pi0,pi1;
        getpriv(PRIV_EFFECTIVE, &epriv,sizeof(priv_t));
        getpriv(PRIV_INHERITED, &ipriv,sizeof(priv_t));
        pe0 = epriv.pv_priv[0];
        pe1 = epriv.pv_priv[1];
        pi0 = ipriv.pv_priv[0];
        pi1 = ipriv.pv_priv[1];

        if ((pe0 != 0) || (pe1 !=0)) {
                if ((pi1 == 0) && (pi0 == 0))
                        return(1)
        }
        else { /* epriv == 0,0 */
                if (pi0 || pi1)
                        return 1;
        }
        ruid = getuid();
        euid = geteuid();
        if(euid != ruid)
            return 1;
        if(getgid() != getegid())
            return 1;
        /*
         * luid == login id, su/sudo do not/cannot change this afaik
         * perhaps this is "too strict", but same as in 
         * issetugid_win.c - err on the safe side for now
         */
        luid = getuidx(ID_LOGIN);
        if(euid != luid)
            return 1;
        return 0;
}

Reply via email to