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;
}