#define _REENTRANT
#include <ctype.h>
#include <errno.h>
#include <grp.h>
#include <libintl.h>
#include <netdb.h>
#include <time.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <arpa/inet.h>
#include <bsm/audit.h>
#include <bsm/audit_record.h>
#include <bsm/libbsm.h>
#include <security/pam_appl.h>
#include <sys/inttypes.h>
#include <sys/mkdev.h>
#include <sys/types.h>
#include <aclutils.h>
#include "praudit.h"
#include "toktable.h"
#include "adt_xlate.h"
static void convertascii(char *p, char *c, int size);
static int convertbinary(char *p, char *c, int size);
static void eventmodifier2string(au_emod_t emodifier, char *modstring,
size_t modlen);
static int do_mtime32(pr_context_t *context, int status, int flag,
uint32_t scale);
static int do_mtime64(pr_context_t *context, int status, int flag,
uint64_t scale);
static uid_t lastuid = (uid_t)-1;
static gid_t lastgid = (gid_t)-1;
static char *lastuname = NULL;
static char *lastgname = NULL;
static char *getname(uid_t);
static char *getgroup(gid_t);
static struct cachenode *findincache(struct cachenode **, long);
#include <utmpx.h>
struct utmpx utmp;
#define NMAX (sizeof (utmp.ut_name))
#define SCPYN(a, b) (void) strncpy(a, b, NMAX)
struct cachenode {
struct cachenode *lesschild;
struct cachenode *grtrchild;
long val;
int initted;
char name[NMAX+1];
};
static struct cachenode *names, *groups;
static struct cachenode *
findincache(struct cachenode **head, long val)
{
struct cachenode **parent = head;
struct cachenode *c = *parent;
while (c != NULL) {
if (val == c->val) {
return (c);
} else if (val < c->val) {
parent = &c->lesschild;
c = c->lesschild;
} else {
parent = &c->grtrchild;
c = c->grtrchild;
}
}
c = calloc(1, sizeof (struct cachenode));
if (c == NULL) {
perror("praudit");
exit(2);
}
*parent = c;
c->val = val;
return (c);
}
static char *
getname(uid_t uid)
{
struct passwd *pwent;
struct cachenode *c;
if ((uid == lastuid) && lastuname)
return (lastuname);
c = findincache(&names, uid);
if (c->initted == 0) {
if ((pwent = getpwuid(uid)) != NULL) {
SCPYN(&c->name[0], pwent->pw_name);
} else {
(void) sprintf(&c->name[0], "%u", (int)uid);
}
c->initted = 1;
}
lastuid = uid;
lastuname = &c->name[0];
return (lastuname);
}
static char *
getgroup(gid_t gid)
{
struct group *grent;
struct cachenode *c;
if ((gid == lastgid) && lastgname)
return (lastgname);
c = findincache(&groups, gid);
if (c->initted == 0) {
if ((grent = getgrgid(gid)) != NULL) {
SCPYN(&c->name[0], grent->gr_name);
} else {
(void) sprintf(&c->name[0], "%u", (int)gid);
}
c->initted = 1;
}
lastgid = gid;
lastgname = &c->name[0];
return (lastgname);
}
void
loadnames(FILE *pf)
{
struct passwd *pwent;
struct cachenode *c;
while ((pwent = fgetpwent(pf)) != NULL) {
c = findincache(&names, pwent->pw_uid);
if (c->initted == 0) {
SCPYN(&c->name[0], pwent->pw_name);
c->initted = 1;
}
}
}
void
loadgroups(FILE *gf)
{
struct group *grent;
struct cachenode *c;
while ((grent = fgetgrent(gf)) != NULL) {
c = findincache(&groups, grent->gr_gid);
if (c->initted == 0) {
SCPYN(&c->name[0], grent->gr_name);
c->initted = 1;
}
}
}
static struct fw {
char basic_unit;
struct {
char print_base;
int field_width;
} pwidth[5];
} fwidth[] = {
AUR_CHAR, AUP_BINARY, 12,
AUP_OCTAL, 6,
AUP_DECIMAL, 6,
AUP_HEX, 6,
AUP_STRING, 1,
AUR_BYTE, AUP_BINARY, 12,
AUP_OCTAL, 6,
AUP_DECIMAL, 6,
AUP_HEX, 6,
AUP_STRING, 1,
AUR_SHORT, AUP_BINARY, 20,
AUP_OCTAL, 10,
AUP_DECIMAL, 10,
AUP_HEX, 8,
AUP_STRING, 6,
AUR_INT32, AUP_BINARY, 36,
AUP_OCTAL, 18,
AUP_DECIMAL, 18,
AUP_HEX, 12,
AUP_STRING, 10,
AUR_INT64, AUP_BINARY, 68,
AUP_OCTAL, 34,
AUP_DECIMAL, 34,
AUP_HEX, 20,
AUP_STRING, 20};
static int numwidthentries = sizeof (fwidth)
/ sizeof (struct fw);
int
do_newline(pr_context_t *context, int flag)
{
int retstat = 0;
if (!(context->format & PRF_ONELINE) && (flag == 1))
retstat = pr_putchar(context, '\n');
else if (!(context->format & PRF_XMLM))
retstat = pr_printf(context, "%s", context->SEPARATOR);
return (retstat);
}
int
open_tag(pr_context_t *context, int tagnum)
{
int err = 0;
token_desc_t *tag;
if (!(context->format & PRF_XMLM))
return (0);
tag = &tokentable[tagnum];
if (context->pending_flag && (tag->t_type != T_ATTRIBUTE)) {
err = pr_putchar(context, '>');
if (err != 0)
return (err);
context->pending_flag = 0;
}
if (is_header_token(tagnum) || is_file_token(tagnum)) {
err = pr_putchar(context, '\n');
} else if (is_token(tagnum)) {
err = do_newline(context, 1);
}
if (err != 0)
return (err);
switch (tag->t_type) {
case T_ATTRIBUTE:
err = pr_printf(context, " %s=\"", tag->t_tagname);
break;
case T_ELEMENT:
err = pr_printf(context, "<%s>", tag->t_tagname);
break;
case T_ENCLOSED:
err = pr_printf(context, "<%s", tag->t_tagname);
break;
case T_EXTENDED:
err = pr_printf(context, "<%s", tag->t_tagname);
if (err == 0)
context->pending_flag = tagnum;
break;
default:
break;
}
if (is_header_token(tagnum) && (err == 0))
context->current_rec = tagnum;
return (err);
}
int
check_close_rec(pr_context_t *context, int tagnum)
{
int err = 0;
if (!(context->format & PRF_XMLM))
return (0);
if ((is_header_token(tagnum) || is_file_token(tagnum)) &&
context->current_rec) {
err = do_newline(context, 1);
if (err == 0)
err = close_tag(context, context->current_rec);
}
return (err);
}
int
finish_open_tag(pr_context_t *context)
{
int err = 0;
if (!(context->format & PRF_XMLM))
return (0);
if (context->pending_flag) {
err = pr_putchar(context, '>');
if (err == 0)
context->pending_flag = 0;
}
return (err);
}
int
close_tag(pr_context_t *context, int tagnum)
{
int err = 0;
token_desc_t *tag;
if (!(context->format & PRF_XMLM))
return (0);
tag = &tokentable[tagnum];
switch (tag->t_type) {
case T_ATTRIBUTE:
err = pr_putchar(context, '\"');
break;
case T_ELEMENT:
err = pr_printf(context, "</%s>", tag->t_tagname);
break;
case T_ENCLOSED:
err = pr_printf(context, "/>");
break;
case T_EXTENDED:
err = pr_printf(context, "</%s>", tag->t_tagname);
break;
default:
break;
}
if (is_header_token(tagnum) && (err == 0))
context->current_rec = 0;
return (err);
}
int
process_tag(pr_context_t *context, int tagnum, int status, int flag)
{
int retstat;
retstat = status;
if (retstat)
return (retstat);
if ((tagnum > 0) && (tagnum <= MAXTAG) &&
(tokentable[tagnum].func != NOFUNC)) {
retstat = open_tag(context, tagnum);
if (!retstat)
retstat = (*tokentable[tagnum].func)(context, status,
flag);
if (!retstat)
retstat = close_tag(context, tagnum);
return (retstat);
}
(void) fprintf(stderr, gettext("praudit: No code associated with "
"tag id %d\n"), tagnum);
return (0);
}
void
get_Hname(uint32_t addr, char *buf, size_t buflen)
{
extern char *inet_ntoa(const struct in_addr);
struct hostent *phe;
struct in_addr ia;
phe = gethostbyaddr((const char *)&addr, 4, AF_INET);
if (phe == (struct hostent *)0) {
ia.s_addr = addr;
(void) snprintf(buf, buflen, "%s", inet_ntoa(ia));
return;
}
ia.s_addr = addr;
(void) snprintf(buf, buflen, "%s", phe->h_name);
}
void
get_Hname_ex(uint32_t *addr, char *buf, size_t buflen)
{
struct hostent *phe;
int err;
phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err);
if (phe == (struct hostent *)0) {
(void) inet_ntop(AF_INET6, (void *)addr, buf, buflen);
} else
(void) snprintf(buf, buflen, "%s", phe->h_name);
if (phe)
freehostent(phe);
}
int
pa_hostname(pr_context_t *context, int status, int flag)
{
int returnstat;
uint32_t ip_addr;
struct in_addr ia;
uval_t uval;
char buf[256];
if (status < 0)
return (status);
if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
return (returnstat);
uval.uvaltype = PRA_STRING;
if (!(context->format & PRF_RAWM)) {
uval.string_val = buf;
get_Hname(ip_addr, buf, sizeof (buf));
returnstat = pa_print(context, &uval, flag);
} else {
ia.s_addr = ip_addr;
if ((uval.string_val = inet_ntoa(ia)) == NULL)
return (-1);
returnstat = pa_print(context, &uval, flag);
}
return (returnstat);
}
int
pa_hostname_ex(pr_context_t *context, int status, int flag)
{
int returnstat;
uint32_t ip_type;
uint32_t ip_addr[4];
struct in_addr ia;
char buf[256];
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_int32(context, (int32_t *)&ip_type, 1)) != 0)
return (returnstat);
if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
return (-1);
if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
return (returnstat);
if ((returnstat = open_tag(context, TAG_HOSTID)) != 0)
return (returnstat);
uval.uvaltype = PRA_STRING;
if (ip_type == AU_IPv4) {
if (!(context->format & PRF_RAWM)) {
uval.string_val = buf;
get_Hname(ip_addr[0], buf, sizeof (buf));
returnstat = pa_print(context, &uval, flag);
} else {
ia.s_addr = ip_addr[0];
if ((uval.string_val = inet_ntoa(ia)) == NULL)
return (-1);
returnstat = pa_print(context, &uval, flag);
}
} else if (ip_type == AU_IPv6) {
if (!(context->format & PRF_RAWM)) {
uval.string_val = buf;
get_Hname_ex(ip_addr, buf, sizeof (buf));
returnstat = pa_print(context, &uval, flag);
} else {
uval.string_val = (char *)buf;
(void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
sizeof (buf));
returnstat = pa_print(context, &uval, flag);
}
}
if (returnstat != 0)
return (returnstat);
return (close_tag(context, TAG_HOSTID));
}
int
pa_hostname_so(pr_context_t *context, int status, int flag)
{
int returnstat;
short ip_type;
ushort_t ip_port;
uint32_t ip_addr[4];
struct in_addr ia;
char buf[256];
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_short(context, &ip_type, 1)) != 0)
return (returnstat);
if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
return (-1);
if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
return (returnstat);
if ((returnstat = open_tag(context, TAG_SOCKEXLPORT)) != 0)
return (returnstat);
uval.uvaltype = PRA_STRING;
uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
sizeof (ip_port));
if (uval.string_val) {
returnstat = pa_print(context, &uval, 0);
free(uval.string_val);
} else
returnstat = -1;
if (returnstat)
return (returnstat);
if ((returnstat = close_tag(context, TAG_SOCKEXLPORT)) != 0)
return (returnstat);
if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
return (returnstat);
if ((returnstat = open_tag(context, TAG_SOCKEXLADDR)) != 0)
return (returnstat);
if (ip_type == AU_IPv4) {
if (!(context->format & PRF_RAWM)) {
uval.string_val = buf;
get_Hname(ip_addr[0], buf, sizeof (buf));
returnstat = pa_print(context, &uval, 0);
} else {
ia.s_addr = ip_addr[0];
if ((uval.string_val = inet_ntoa(ia)) == NULL)
return (-1);
returnstat = pa_print(context, &uval, 0);
}
} else if (ip_type == AU_IPv6) {
if (!(context->format & PRF_RAWM)) {
uval.string_val = buf;
get_Hname_ex(ip_addr, buf, sizeof (buf));
returnstat = pa_print(context, &uval, 0);
} else {
uval.string_val = (char *)buf;
(void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
sizeof (buf));
returnstat = pa_print(context, &uval, 0);
}
} else
returnstat = -1;
if (returnstat)
return (returnstat);
if ((returnstat = close_tag(context, TAG_SOCKEXLADDR)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
return (returnstat);
if ((returnstat = open_tag(context, TAG_SOCKEXFPORT)) != 0)
return (returnstat);
uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
sizeof (ip_port));
if (uval.string_val) {
returnstat = pa_print(context, &uval, 0);
free(uval.string_val);
} else
returnstat = -1;
if (returnstat)
return (returnstat);
if ((returnstat = close_tag(context, TAG_SOCKEXFPORT)) != 0)
return (returnstat);
if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
return (returnstat);
if ((returnstat = open_tag(context, TAG_SOCKEXFADDR)) != 0)
return (returnstat);
if (ip_type == AU_IPv4) {
if (!(context->format & PRF_RAWM)) {
uval.string_val = buf;
get_Hname(ip_addr[0], buf, sizeof (buf));
returnstat = pa_print(context, &uval, flag);
} else {
ia.s_addr = ip_addr[0];
if ((uval.string_val = inet_ntoa(ia)) == NULL)
return (-1);
returnstat = pa_print(context, &uval, flag);
}
} else if (ip_type == AU_IPv6) {
if (!(context->format & PRF_RAWM)) {
uval.string_val = buf;
get_Hname_ex(ip_addr, buf, sizeof (buf));
returnstat = pa_print(context, &uval, flag);
} else {
uval.string_val = (char *)buf;
(void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
sizeof (buf));
returnstat = pa_print(context, &uval, flag);
}
} else
returnstat = -1;
if (returnstat)
return (returnstat);
if ((returnstat = close_tag(context, TAG_SOCKEXFADDR)) != 0)
return (returnstat);
return (returnstat);
}
#define NBITSMAJOR64 32
#define NBITSMINOR64 32
#define MAXMAJ64 0xfffffffful
#define MAXMIN64 0xfffffffful
#define NBITSMAJOR32 14
#define NBITSMINOR32 18
#define NMAXMAJ32 0x3fff
#define NMAXMIN32 0x3ffff
static int32_t
minor_64(uint64_t dev)
{
if (dev == NODEV) {
errno = EINVAL;
return (NODEV);
}
return (int32_t)(dev & MAXMIN64);
}
static int32_t
major_64(uint64_t dev)
{
uint32_t maj;
maj = (uint32_t)(dev >> NBITSMINOR64);
if (dev == NODEV || maj > MAXMAJ64) {
errno = EINVAL;
return (NODEV);
}
return (int32_t)(maj);
}
static int32_t
minor_32(uint32_t dev)
{
if (dev == NODEV) {
errno = EINVAL;
return (NODEV);
}
return (int32_t)(dev & MAXMIN32);
}
static int32_t
major_32(uint32_t dev)
{
uint32_t maj;
maj = (uint32_t)(dev >> NBITSMINOR32);
if (dev == NODEV || maj > MAXMAJ32) {
errno = EINVAL;
return (NODEV);
}
return (int32_t)(maj);
}
int
pa_tid32(pr_context_t *context, int status, int flag)
{
int returnstat;
int32_t dev_maj_min;
uint32_t ip_addr;
struct in_addr ia;
char *ipstring;
char buf[256];
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
return (returnstat);
uval.uvaltype = PRA_STRING;
uval.string_val = buf;
if (!(context->format & PRF_RAWM)) {
char hostname[256];
get_Hname(ip_addr, hostname, sizeof (hostname));
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_32(dev_maj_min),
minor_32(dev_maj_min),
hostname);
return (pa_print(context, &uval, flag));
}
ia.s_addr = ip_addr;
if ((ipstring = inet_ntoa(ia)) == NULL)
return (-1);
(void) snprintf(buf, sizeof (buf), "%d %d %s", major_32(dev_maj_min),
minor_32(dev_maj_min),
ipstring);
return (pa_print(context, &uval, flag));
}
int
pa_tid32_ex(pr_context_t *context, int status, int flag)
{
int returnstat;
int32_t dev_maj_min;
uint32_t ip_addr[16];
uint32_t ip_type;
struct in_addr ia;
char *ipstring;
char hostname[256];
char buf[256];
char tbuf[256];
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
return (returnstat);
if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
return (-1);
if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
return (returnstat);
uval.uvaltype = PRA_STRING;
if (ip_type == AU_IPv4) {
uval.string_val = buf;
if (!(context->format & PRF_RAWM)) {
get_Hname(ip_addr[0], hostname, sizeof (hostname));
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_32(dev_maj_min), minor_32(dev_maj_min),
hostname);
return (pa_print(context, &uval, flag));
}
ia.s_addr = ip_addr[0];
if ((ipstring = inet_ntoa(ia)) == NULL)
return (-1);
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_32(dev_maj_min), minor_32(dev_maj_min), ipstring);
return (pa_print(context, &uval, flag));
} else {
uval.string_val = buf;
if (!(context->format & PRF_RAWM)) {
get_Hname_ex(ip_addr, hostname, sizeof (hostname));
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_32(dev_maj_min), minor_32(dev_maj_min),
hostname);
return (pa_print(context, &uval, flag));
}
(void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
sizeof (tbuf));
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_32(dev_maj_min), minor_32(dev_maj_min), tbuf);
return (pa_print(context, &uval, flag));
}
}
int
pa_ip_addr(pr_context_t *context, int status, int flag)
{
int returnstat;
uval_t uval;
uint32_t ip_addr[4];
uint32_t ip_type;
struct in_addr ia;
char *ipstring;
char hostname[256];
char buf[256];
char tbuf[256];
if (status < 0)
return (status);
if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
return (returnstat);
if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
return (-1);
if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
return (returnstat);
uval.uvaltype = PRA_STRING;
if (ip_type == AU_IPv4) {
uval.string_val = buf;
if (!(context->format & PRF_RAWM)) {
get_Hname(ip_addr[0], hostname, sizeof (hostname));
(void) snprintf(buf, sizeof (buf), "%s", hostname);
return (pa_print(context, &uval, flag));
}
ia.s_addr = ip_addr[0];
if ((ipstring = inet_ntoa(ia)) == NULL)
return (-1);
(void) snprintf(buf, sizeof (buf), "%s", ipstring);
return (pa_print(context, &uval, flag));
} else {
uval.string_val = buf;
if (!(context->format & PRF_RAWM)) {
get_Hname_ex(ip_addr, hostname, sizeof (hostname));
(void) snprintf(buf, sizeof (buf), "%s",
hostname);
return (pa_print(context, &uval, flag));
}
(void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
sizeof (tbuf));
(void) snprintf(buf, sizeof (buf), "%s", tbuf);
return (pa_print(context, &uval, flag));
}
}
int
pa_tid64(pr_context_t *context, int status, int flag)
{
int returnstat;
int64_t dev_maj_min;
uint32_t ip_addr;
struct in_addr ia;
char *ipstring;
char buf[256];
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
return (returnstat);
uval.uvaltype = PRA_STRING;
uval.string_val = buf;
if (!(context->format & PRF_RAWM)) {
char hostname[256];
get_Hname(ip_addr, hostname, sizeof (hostname));
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_64(dev_maj_min), minor_64(dev_maj_min), hostname);
return (pa_print(context, &uval, flag));
}
ia.s_addr = ip_addr;
if ((ipstring = inet_ntoa(ia)) == NULL)
return (-1);
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_64(dev_maj_min), minor_64(dev_maj_min), ipstring);
return (pa_print(context, &uval, flag));
}
int
pa_tid64_ex(pr_context_t *context, int status, int flag)
{
int returnstat;
int64_t dev_maj_min;
uint32_t ip_addr[4];
uint32_t ip_type;
struct in_addr ia;
char *ipstring;
char hostname[256];
char buf[256];
char tbuf[256];
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
return (returnstat);
if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
return (-1);
if ((returnstat = pr_adr_char(context, (char *)&ip_addr, ip_type)) != 0)
return (returnstat);
uval.uvaltype = PRA_STRING;
if (ip_type == AU_IPv4) {
uval.string_val = buf;
if (!(context->format & PRF_RAWM)) {
get_Hname(ip_addr[0], hostname, sizeof (hostname));
uval.string_val = buf;
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_64(dev_maj_min), minor_64(dev_maj_min),
hostname);
return (pa_print(context, &uval, flag));
}
ia.s_addr = ip_addr[0];
if ((ipstring = inet_ntoa(ia)) == NULL)
return (-1);
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_64(dev_maj_min), minor_64(dev_maj_min), ipstring);
return (pa_print(context, &uval, flag));
} else {
uval.string_val = buf;
if (!(context->format & PRF_RAWM)) {
get_Hname_ex(ip_addr, hostname, sizeof (hostname));
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_64(dev_maj_min), minor_64(dev_maj_min),
hostname);
return (pa_print(context, &uval, flag));
}
(void) inet_ntop(AF_INET6, (void *)ip_addr, tbuf,
sizeof (tbuf));
(void) snprintf(buf, sizeof (buf), "%d %d %s",
major_64(dev_maj_min), minor_64(dev_maj_min), tbuf);
return (pa_print(context, &uval, flag));
}
}
int
findfieldwidth(char basicunit, char howtoprint)
{
int i, j;
for (i = 0; i < numwidthentries; i++) {
if (fwidth[i].basic_unit == basicunit) {
for (j = 0; j <= 4; j++) {
if (fwidth[i].pwidth[j].print_base ==
howtoprint) {
return (
fwidth[i].pwidth[j].field_width);
}
}
return (0);
}
}
return (0);
}
int
pa_cmd(pr_context_t *context, int status, int flag)
{
char *cmd;
short length;
int returnstat;
uval_t uval;
if (status >= 0) {
if (pr_adr_short(context, &length, 1) == 0) {
if ((cmd = (char *)malloc(length + 1)) == NULL)
return (-1);
if (pr_adr_char(context, cmd, length) == 0) {
uval.uvaltype = PRA_STRING;
uval.string_val = cmd;
returnstat = pa_print(context, &uval, flag);
} else {
returnstat = -1;
}
free(cmd);
return (returnstat);
} else
return (-1);
} else
return (status);
}
int
pa_adr_byte(pr_context_t *context, int status, int flag)
{
char c;
uval_t uval;
if (status >= 0) {
if (pr_adr_char(context, &c, 1) == 0) {
uval.uvaltype = PRA_BYTE;
uval.char_val = c;
return (pa_print(context, &uval, flag));
} else
return (-1);
} else
return (status);
}
int
pa_adr_charhex(pr_context_t *context, int status, int flag)
{
char p[2];
int returnstat;
uval_t uval;
if (status >= 0) {
p[0] = p[1] = 0;
if ((returnstat = pr_adr_char(context, p, 1)) == 0) {
uval.uvaltype = PRA_STRING;
uval.string_val = hexconvert(p, sizeof (char),
sizeof (char));
if (uval.string_val) {
returnstat = pa_print(context, &uval, flag);
free(uval.string_val);
}
}
return (returnstat);
} else
return (status);
}
int
pa_adr_int32(pr_context_t *context, int status, int flag)
{
int32_t c;
uval_t uval;
if (status >= 0) {
if (pr_adr_int32(context, &c, 1) == 0) {
uval.uvaltype = PRA_INT32;
uval.int32_val = c;
return (pa_print(context, &uval, flag));
} else
return (-1);
} else
return (status);
}
int
pa_adr_int64(pr_context_t *context, int status, int flag)
{
int64_t c;
uval_t uval;
if (status >= 0) {
if (pr_adr_int64(context, &c, 1) == 0) {
uval.uvaltype = PRA_INT64;
uval.int64_val = c;
return (pa_print(context, &uval, flag));
} else
return (-1);
} else
return (status);
}
int
pa_adr_int32hex(pr_context_t *context, int status, int flag)
{
int32_t l;
int returnstat;
uval_t uval;
if (status >= 0) {
if ((returnstat = pr_adr_int32(context, &l, 1)) == 0) {
uval.uvaltype = PRA_HEX32;
uval.int32_val = l;
returnstat = pa_print(context, &uval, flag);
}
return (returnstat);
} else
return (status);
}
int
pa_adr_int64hex(pr_context_t *context, int status, int flag)
{
int64_t l;
int returnstat;
uval_t uval;
if (status >= 0) {
if ((returnstat = pr_adr_int64(context, &l, 1)) == 0) {
uval.uvaltype = PRA_HEX64;
uval.int64_val = l;
returnstat = pa_print(context, &uval, flag);
}
return (returnstat);
} else
return (status);
}
char *
bu2string(char basic_unit)
{
register int i;
struct bu_map_ent {
char basic_unit;
char *string;
};
static struct bu_map_ent bu_map[] = {
{ AUR_BYTE, "byte" },
{ AUR_CHAR, "char" },
{ AUR_SHORT, "short" },
{ AUR_INT32, "int32" },
{ AUR_INT64, "int64" } };
for (i = 0; i < sizeof (bu_map) / sizeof (struct bu_map_ent); i++)
if (basic_unit == bu_map[i].basic_unit)
return (gettext(bu_map[i].string));
return (gettext("unknown basic unit type"));
}
static void
eventmodifier2string(au_emod_t emodifier, char *modstring, size_t modlen)
{
register int i, j;
struct em_map_ent {
int mask;
char *string;
};
static struct em_map_ent em_map[] = {
{ (int)PAD_READ, "rd" },
{ (int)PAD_WRITE, "wr" },
{ (int)PAD_SPRIVUSE, "sp" },
{ (int)PAD_FPRIVUSE, "fp" },
{ (int)PAD_NONATTR, "na" },
{ (int)PAD_FAILURE, "fe" }
};
modstring[0] = '\0';
for (i = 0, j = 0; i < sizeof (em_map) / sizeof (struct em_map_ent);
i++) {
if ((int)emodifier & em_map[i].mask) {
if (j++)
(void) strlcat(modstring, ":", modlen);
(void) strlcat(modstring, em_map[i].string, modlen);
}
}
}
int
convert_char_to_string(char printmode, char c, char *p)
{
union {
char c1[4];
int c2;
} dat;
dat.c2 = 0;
dat.c1[3] = c;
if (printmode == AUP_BINARY)
(void) convertbinary(p, &c, sizeof (char));
else if (printmode == AUP_OCTAL)
(void) sprintf(p, "%o", (int)dat.c2);
else if (printmode == AUP_DECIMAL)
(void) sprintf(p, "%d", c);
else if (printmode == AUP_HEX)
(void) sprintf(p, "0x%x", (int)dat.c2);
else if (printmode == AUP_STRING)
convertascii(p, &c, sizeof (char));
return (0);
}
int
convert_short_to_string(char printmode, short c, char *p)
{
union {
short c1[2];
int c2;
} dat;
dat.c2 = 0;
dat.c1[1] = c;
if (printmode == AUP_BINARY)
(void) convertbinary(p, (char *)&c, sizeof (short));
else if (printmode == AUP_OCTAL)
(void) sprintf(p, "%o", (int)dat.c2);
else if (printmode == AUP_DECIMAL)
(void) sprintf(p, "%hd", c);
else if (printmode == AUP_HEX)
(void) sprintf(p, "0x%x", (int)dat.c2);
else if (printmode == AUP_STRING)
convertascii(p, (char *)&c, sizeof (short));
return (0);
}
int
convert_int32_to_string(char printmode, int32_t c, char *p)
{
if (printmode == AUP_BINARY)
(void) convertbinary(p, (char *)&c, sizeof (int32_t));
else if (printmode == AUP_OCTAL)
(void) sprintf(p, "%o", c);
else if (printmode == AUP_DECIMAL)
(void) sprintf(p, "%d", c);
else if (printmode == AUP_HEX)
(void) sprintf(p, "0x%x", c);
else if (printmode == AUP_STRING)
convertascii(p, (char *)&c, sizeof (int));
return (0);
}
int
convert_int64_to_string(char printmode, int64_t c, char *p)
{
if (printmode == AUP_BINARY)
(void) convertbinary(p, (char *)&c, sizeof (int64_t));
else if (printmode == AUP_OCTAL)
(void) sprintf(p, "%"PRIo64, c);
else if (printmode == AUP_DECIMAL)
(void) sprintf(p, "%"PRId64, c);
else if (printmode == AUP_HEX)
(void) sprintf(p, "0x%"PRIx64, c);
else if (printmode == AUP_STRING)
convertascii(p, (char *)&c, sizeof (int64_t));
return (0);
}
int
convertbinary(char *p, char *c, int size)
{
char *s, *t, *ss;
int i, j;
if ((s = (char *)malloc(8 * size + 1)) == NULL)
return (0);
ss = s;
t = s;
for (i = 0; i < size; i++) {
for (j = 0; j < 8; j++)
(void) sprintf(t++, "%d", ((*c >> (7 - j)) & (0x01)));
c++;
}
*t = '\0';
j = strlen(s) - 1;
for (i = 0; i < j; i++) {
if (*s != '0')
break;
else
s++;
}
t = p;
for (i = 0; i < (8 * size + 1); i++) {
if (*s == '\0') {
*t = '\0';
break;
}
*t++ = *s++;
}
free(ss);
return (1);
}
static char hex[] = "0123456789abcdef";
char *
hexconvert(char *c, int size, int chunk)
{
register char *s, *t;
register int i, j, k;
int numchunks;
int leftovers;
if (size <= 0)
return (NULL);
if ((s = (char *)malloc((size * 5) + 1)) == NULL)
return (NULL);
if (chunk > size || chunk <= 0)
chunk = size;
numchunks = size / chunk;
leftovers = size % chunk;
t = s;
for (i = j = 0; i < numchunks; i++) {
if (j++) {
*t++ = ' ';
}
*t++ = '0';
*t++ = 'x';
for (k = 0; k < chunk; k++) {
*t++ = hex[(uint_t)((uchar_t)*c >> 4)];
*t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
c++;
}
}
if (leftovers) {
*t++ = ' ';
*t++ = '0';
*t++ = 'x';
for (i = 0; i < leftovers; i++) {
*t++ = hex[(uint_t)((uchar_t)*c >> 4)];
*t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
c++;
}
}
*t = '\0';
return (s);
}
char *
htp2string(char print_sugg)
{
register int i;
struct htp_map_ent {
char print_sugg;
char *print_string;
};
static struct htp_map_ent htp_map[] = {
{ AUP_BINARY, "binary" },
{ AUP_OCTAL, "octal" },
{ AUP_DECIMAL, "decimal" },
{ AUP_HEX, "hexadecimal" },
{ AUP_STRING, "string" } };
for (i = 0; i < sizeof (htp_map) / sizeof (struct htp_map_ent); i++)
if (print_sugg == htp_map[i].print_sugg)
return (gettext(htp_map[i].print_string));
return (gettext("unknown print suggestion"));
}
int
pa_adr_short(pr_context_t *context, int status, int flag)
{
short c;
uval_t uval;
if (status >= 0) {
if (pr_adr_short(context, &c, 1) == 0) {
uval.uvaltype = PRA_SHORT;
uval.short_val = c;
return (pa_print(context, &uval, flag));
} else
return (-1);
} else
return (status);
}
int
pa_adr_shorthex(pr_context_t *context, int status, int flag)
{
short s;
int returnstat;
uval_t uval;
if (status >= 0) {
if ((returnstat = pr_adr_short(context, &s, 1)) == 0) {
uval.uvaltype = PRA_STRING;
uval.string_val = hexconvert((char *)&s, sizeof (s),
sizeof (s));
if (uval.string_val) {
returnstat = pa_print(context, &uval, flag);
free(uval.string_val);
}
}
return (returnstat);
} else
return (status);
}
int
pa_adr_string(pr_context_t *context, int status, int flag)
{
char *c;
short length;
int returnstat;
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
return (returnstat);
if ((c = (char *)malloc(length + 1)) == NULL)
return (-1);
if ((returnstat = pr_adr_char(context, c, length)) != 0) {
free(c);
return (returnstat);
}
uval.uvaltype = PRA_STRING;
uval.string_val = c;
returnstat = pa_print(context, &uval, flag);
free(c);
return (returnstat);
}
int
pa_file_string(pr_context_t *context, int status, int flag)
{
char *c;
char *p;
short length;
int returnstat;
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
return (returnstat);
if ((c = (char *)malloc(length + 1)) == NULL)
return (-1);
if ((p = (char *)malloc((length * 4) + 1)) == NULL) {
free(c);
return (-1);
}
if ((returnstat = pr_adr_char(context, c, length)) != 0) {
free(c);
free(p);
return (returnstat);
}
if (is_file_token(context->tokenid))
context->audit_rec_len += length;
convertascii(p, c, length - 1);
uval.uvaltype = PRA_STRING;
uval.string_val = p;
if (returnstat == 0)
returnstat = finish_open_tag(context);
if (returnstat == 0)
returnstat = pa_print(context, &uval, flag);
free(c);
free(p);
return (returnstat);
}
static int
pa_putstr_xml(pr_context_t *context, int printable, char *str, size_t len)
{
int err;
if (!printable) {
do {
err = pr_printf(context, "\\%03o",
(unsigned char)*str++);
} while (err == 0 && --len != 0);
return (err);
}
if (len == 1) {
switch (*str) {
case '&':
err = pr_printf(context, "%s", "&");
break;
case '<':
err = pr_printf(context, "%s", "<");
break;
case '>':
err = pr_printf(context, "%s", ">");
break;
case '\"':
err = pr_printf(context, "%s", """);
break;
case '\'':
err = pr_printf(context, "%s", "'");
break;
default:
err = pr_putchar(context, *str);
break;
}
return (err);
}
do {
err = pr_putchar(context, *str++);
} while (err == 0 && --len != 0);
return (err);
}
static int
pa_putstr(pr_context_t *context, int printable, char *str, size_t len)
{
int err;
if (context->format & PRF_XMLM)
return (pa_putstr_xml(context, printable, str, len));
if (!printable) {
do {
err = pr_printf(context, "\\%03o",
(unsigned char)*str++);
} while (err == 0 && --len != 0);
return (err);
}
do {
err = pr_putchar(context, *str++);
} while (err == 0 && --len != 0);
return (err);
}
int
pa_string(pr_context_t *context, int status, int flag)
{
int rstat, wstat;
int i, printable, eos;
int mlen, rlen;
int mbmax = MB_CUR_MAX;
wchar_t wc;
char mbuf[MB_LEN_MAX + 1];
char c;
if (status < 0)
return (status);
rstat = wstat = 0;
if (mbmax == 1) {
while (wstat == 0) {
if ((rstat = pr_adr_char(context, &c, 1)) < 0)
break;
if (c == '\0')
break;
printable = isprint((unsigned char)c);
wstat = pa_putstr(context, printable, &c, 1);
}
goto done;
}
mlen = eos = 0;
while (wstat == 0) {
rlen = 0;
do {
if (!eos) {
rstat = pr_adr_char(context, &c, 1);
if (rstat != 0 || c == '\0')
eos = 1;
else
mbuf[mlen++] = c;
}
rlen = mbtowc(&wc, mbuf, mlen);
} while (!eos && mlen < mbmax && rlen <= 0);
if (mlen == 0)
break;
if (rlen <= 0) {
rlen = 1;
printable = 0;
} else {
printable = iswprint(wc);
}
wstat = pa_putstr(context, printable, mbuf, rlen);
mlen -= rlen;
if (mlen > 0) {
for (i = 0; i < mlen; i++)
mbuf[i] = mbuf[rlen + i];
}
}
done:
if (wstat == 0)
wstat = do_newline(context, flag);
return ((rstat != 0 || wstat != 0) ? -1 : 0);
}
int
pa_adr_u_int32(pr_context_t *context, int status, int flag)
{
uint32_t c;
uval_t uval;
if (status >= 0) {
if (pr_adr_u_int32(context, &c, 1) == 0) {
uval.uvaltype = PRA_UINT32;
uval.uint32_val = c;
return (pa_print(context, &uval, flag));
} else
return (-1);
} else
return (status);
}
int
pa_adr_u_int64(pr_context_t *context, int status, int flag)
{
uint64_t c;
uval_t uval;
if (status >= 0) {
if (pr_adr_u_int64(context, &c, 1) == 0) {
uval.uvaltype = PRA_UINT64;
uval.uint64_val = c;
return (pa_print(context, &uval, flag));
} else
return (-1);
} else
return (status);
}
int
pa_adr_u_short(pr_context_t *context, int status, int flag)
{
ushort_t c;
uval_t uval;
if (status >= 0) {
if (pr_adr_u_short(context, &c, 1) == 0) {
uval.uvaltype = PRA_USHORT;
uval.ushort_val = c;
return (pa_print(context, &uval, flag));
} else
return (-1);
} else
return (status);
}
int
pa_reclen(pr_context_t *context, int status)
{
uint32_t c;
uval_t uval;
if (status >= 0) {
if ((int)pr_adr_u_int32(context, &c, 1) == 0) {
context->audit_rec_len = c;
if (context->format & PRF_XMLM) {
return (0);
} else {
uval.uvaltype = PRA_UINT32;
uval.uint32_val = c;
return (pa_print(context, &uval, 0));
}
} else
return (-1);
} else
return (status);
}
int
pa_mode(pr_context_t *context, int status, int flag)
{
uint32_t c;
uval_t uval;
if (status >= 0) {
if (pr_adr_u_int32(context, &c, 1) == 0) {
uval.uvaltype = PRA_LOCT;
uval.uint32_val = c;
return (pa_print(context, &uval, flag));
} else
return (-1);
} else
return (status);
}
static int
pa_print_uid(pr_context_t *context, uid_t uid, int status, int flag)
{
int returnstat;
uval_t uval;
if (status < 0)
return (status);
if (context->format & PRF_RAWM) {
uval.uvaltype = PRA_INT32;
uval.int32_val = uid;
returnstat = pa_print(context, &uval, flag);
} else {
uval.uvaltype = PRA_STRING;
uval.string_val = getname(uid);
returnstat = pa_print(context, &uval, flag);
}
return (returnstat);
}
int
pa_pw_uid(pr_context_t *context, int status, int flag)
{
uint32_t uid;
if (status < 0)
return (status);
if (pr_adr_u_int32(context, &uid, 1) != 0)
return (-1);
return (pa_print_uid(context, uid, status, flag));
}
static int
pa_print_gid(pr_context_t *context, gid_t gid, int status, int flag)
{
int returnstat;
uval_t uval;
if (status < 0)
return (status);
if (context->format & PRF_RAWM) {
uval.uvaltype = PRA_INT32;
uval.int32_val = gid;
returnstat = pa_print(context, &uval, flag);
} else {
uval.uvaltype = PRA_STRING;
uval.string_val = getgroup(gid);
returnstat = pa_print(context, &uval, flag);
}
return (returnstat);
}
int
pa_gr_uid(pr_context_t *context, int status, int flag)
{
uint32_t gid;
if (status < 0)
return (status);
if (pr_adr_u_int32(context, &gid, 1) != 0)
return (-1);
return (pa_print_gid(context, gid, status, flag));
}
int
pa_pw_uid_gr_gid(pr_context_t *context, int status, int flag)
{
int returnstat;
uint32_t value;
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_u_int32(context, &value, 1)) != 0)
return (returnstat);
if ((returnstat = open_tag(context, TAG_ACLTYPE)) != 0)
return (returnstat);
uval.uvaltype = PRA_UINT32;
uval.uint32_val = value;
if ((returnstat = pa_print(context, &uval, flag)) != 0)
return (returnstat);
if ((returnstat = close_tag(context, TAG_ACLTYPE)) != 0)
return (returnstat);
if ((returnstat = open_tag(context, TAG_ACLVAL)) != 0)
return (returnstat);
switch (value) {
case USER_OBJ:
case USER:
returnstat = pa_pw_uid(context, returnstat, flag);
break;
case GROUP_OBJ:
case GROUP:
returnstat = pa_gr_uid(context, returnstat, flag);
break;
case CLASS_OBJ:
returnstat = pr_adr_u_int32(context, &value, 1);
if (returnstat != 0)
return (returnstat);
if (!(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_STRING;
uval.string_val = gettext("mask");
returnstat = pa_print(context, &uval, flag);
} else {
uval.uvaltype = PRA_UINT32;
uval.uint32_val = value;
if ((returnstat =
pa_print(context, &uval, flag)) != 0) {
return (returnstat);
}
}
break;
case OTHER_OBJ:
returnstat = pr_adr_u_int32(context, &value, 1);
if (returnstat != 0)
return (returnstat);
if (!(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_STRING;
uval.string_val = gettext("other");
returnstat = pa_print(context, &uval, flag);
} else {
uval.uvaltype = PRA_UINT32;
uval.uint32_val = value;
if ((returnstat =
pa_print(context, &uval, flag)) != 0) {
return (returnstat);
}
}
break;
default:
returnstat = pr_adr_u_int32(context, &value, 1);
if (returnstat != 0)
return (returnstat);
if (!(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_STRING;
uval.string_val = gettext("unrecognized");
returnstat = pa_print(context, &uval, flag);
} else {
uval.uvaltype = PRA_UINT32;
uval.uint32_val = value;
if ((returnstat =
pa_print(context, &uval, flag)) != 0) {
return (returnstat);
}
}
}
if ((returnstat = close_tag(context, TAG_ACLVAL)) != 0)
return (returnstat);
return (returnstat);
}
int
pa_event_modifier(pr_context_t *context, int status, int flag)
{
int returnstat;
au_emod_t emodifier;
uval_t uval;
char modstring[64];
if (status < 0)
return (status);
if ((returnstat = pr_adr_u_short(context, &emodifier, 1)) != 0)
return (returnstat);
if (!(context->format & PRF_XMLM) || (emodifier != 0)) {
uval.uvaltype = PRA_STRING;
returnstat = open_tag(context, TAG_EVMOD);
if (returnstat >= 0) {
if (!(context->format & PRF_RAWM)) {
eventmodifier2string(emodifier, modstring,
sizeof (modstring));
uval.string_val = modstring;
returnstat = pa_print(context, &uval, flag);
} else {
uval.string_val = hexconvert((char *)&emodifier,
sizeof (emodifier), sizeof (emodifier));
if (uval.string_val) {
returnstat = pa_print(context, &uval,
flag);
free(uval.string_val);
}
}
}
if (returnstat >= 0)
returnstat = close_tag(context, TAG_EVMOD);
}
return (returnstat);
}
int
pa_event_type(pr_context_t *context, int status, int flag)
{
au_event_t etype;
int returnstat;
au_event_ent_t *p_event = NULL;
uval_t uval;
if (status >= 0) {
if ((returnstat = pr_adr_u_short(context, &etype, 1)) == 0) {
if (!(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_STRING;
if (context->format & PRF_NOCACHE) {
p_event = getauevnum(etype);
} else {
(void) cacheauevent(&p_event, etype);
}
if (p_event != NULL) {
if (context->format & PRF_SHORTM)
uval.string_val =
p_event->ae_name;
else
uval.string_val =
p_event->ae_desc;
} else {
uval.string_val =
gettext("invalid event number");
}
returnstat = pa_print(context, &uval, flag);
} else {
uval.uvaltype = PRA_USHORT;
uval.ushort_val = etype;
returnstat = pa_print(context, &uval, flag);
}
}
return (returnstat);
} else
return (status);
}
int
pa_utime32(pr_context_t *context, int status, int flag)
{
uint32_t scale = 1000;
return (do_mtime32(context, status, flag, scale));
}
int
pa_ntime32(pr_context_t *context, int status, int flag)
{
uint32_t scale = 1000000;
return (do_mtime32(context, status, flag, scale));
}
#define MINS (24L * 60)
static void
tzone(struct tm *tm, time_t *tv_sec, char *p)
{
struct tm *gmt;
int min_off;
gmt = gmtime(tv_sec);
min_off = ((tm->tm_hour - gmt->tm_hour) * 60) +
(tm->tm_min - gmt->tm_min);
if (tm->tm_year < gmt->tm_year)
min_off -= MINS;
else if (tm->tm_year > gmt->tm_year)
min_off += MINS;
else if (tm->tm_yday < gmt->tm_yday)
min_off -= MINS;
else if (tm->tm_yday > gmt->tm_yday)
min_off += MINS;
if (min_off < 0) {
min_off = -min_off;
*p++ = '-';
} else {
*p++ = '+';
}
*p++ = min_off / 600 + '0';
min_off = min_off - min_off / 600 * 600;
*p++ = min_off / 60 % 10 + '0';
min_off = min_off - min_off / 60 * 60;
*p++ = ':';
*p++ = min_off / 10 + '0';
*p++ = min_off % 10 + '0';
*p = '\0';
}
static void
msec32(uint32_t msec, char *p)
{
*p++ = msec / 100 + '0';
msec = msec - msec / 100 * 100;
*p++ = msec / 10 + '0';
*p++ = msec % 10 +'0';
}
static int
do_mtime32(pr_context_t *context, int status, int flag, uint32_t scale)
{
uint32_t t32;
time_t tv_sec;
struct tm tm;
char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
int returnstat;
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = open_tag(context, TAG_ISO)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_int32(context,
(uint32_t *)&tv_sec, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_int32(context, &t32, 1)) == 0) {
if (!(context->format & PRF_RAWM)) {
(void) localtime_r(&tv_sec, &tm);
(void) strftime(time_created,
sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
"%Y-%m-%d %H:%M:%S.xxx ", &tm);
msec32(t32/scale,
&time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
tzone(&tm, &tv_sec,
&time_created[
sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
uval.uvaltype = PRA_STRING;
uval.string_val = time_created;
} else {
uval.uvaltype = PRA_UINT32;
uval.uint32_val = (uint32_t)tv_sec;
(void) pa_print(context, &uval, 0);
if (context->format & PRF_XMLM) {
uval.uvaltype = PRA_CHAR;
uval.char_val = '.';
(void) pa_print(context, &uval, 0);
}
uval.uvaltype = PRA_UINT32;
uval.uint32_val = t32;
}
returnstat = pa_print(context, &uval, flag);
}
if (returnstat == 0)
return (close_tag(context, TAG_ISO));
else
return (returnstat);
}
int
pa_utime64(pr_context_t *context, int status, int flag)
{
uint64_t scale = 1000;
return (do_mtime64(context, status, flag, scale));
}
int
pa_ntime64(pr_context_t *context, int status, int flag)
{
uint64_t scale = 1000000;
return (do_mtime64(context, status, flag, scale));
}
static void
msec64(uint64_t msec, char *p)
{
*p++ = msec / 100 + '0';
msec = msec - msec / 100 * 100;
*p++ = msec / 10 + '0';
*p++ = msec % 10 +'0';
}
static int
do_mtime64(pr_context_t *context, int status, int flag, uint64_t scale)
{
uint64_t t64_sec;
uint64_t t64_msec;
time_t tv_sec;
struct tm tm;
char time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
int returnstat;
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = open_tag(context, TAG_ISO)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_int64(context, &t64_sec, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_int64(context, &t64_msec, 1)) == 0) {
if (!(context->format & PRF_RAWM)) {
#ifndef _LP64
#endif
tv_sec = (time_t)t64_sec;
(void) localtime_r(&tv_sec, &tm);
(void) strftime(time_created,
sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
"%Y-%m-%d %H:%M:%S.xxx ", &tm);
msec64(t64_msec/scale,
&time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
tzone(&tm, &tv_sec,
&time_created[
sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
uval.uvaltype = PRA_STRING;
uval.string_val = time_created;
} else {
uval.uvaltype = PRA_UINT64;
uval.uint64_val = t64_sec;
(void) pa_print(context, &uval, 0);
if (context->format & PRF_XMLM) {
uval.uvaltype = PRA_CHAR;
uval.char_val = '.';
(void) pa_print(context, &uval, 0);
}
uval.uvaltype = PRA_UINT64;
uval.uint64_val = t64_msec;
}
returnstat = pa_print(context, &uval, flag);
}
if (returnstat < 0)
return (returnstat);
return (close_tag(context, TAG_ISO));
}
void
pa_error(const uchar_t err, char *buf, size_t buflen)
{
if (err == ADT_SUCCESS) {
(void) strlcpy(buf, gettext("success"), buflen);
} else if ((char)err == ADT_FAILURE) {
(void) strlcpy(buf, gettext("failure"), buflen);
} else {
char *emsg = strerror(err);
if (emsg != NULL) {
(void) strlcpy(buf, gettext("failure: "), buflen);
(void) strlcat(buf, emsg, buflen);
} else {
(void) snprintf(buf, buflen, "%s%d",
gettext("failure: "), err);
}
}
}
void
pa_retval(const uchar_t err, const int32_t retval, char *buf, size_t buflen)
{
struct msg_text *msglist;
char *emsg;
if (((char)err == ADT_SUCCESS) ||
(retval < 0)) {
(void) snprintf(buf, buflen, "%d", retval);
return;
}
msglist = &adt_msg_text[ADT_LIST_FAIL_VALUE];
if ((retval + msglist->ml_offset >= msglist->ml_min_index) &&
(retval + msglist->ml_offset <= msglist->ml_max_index)) {
(void) strlcpy(buf,
gettext(msglist->ml_msg_list[retval + msglist->ml_offset]),
buflen);
} else if ((retval >= ADT_FAIL_PAM) &&
(retval < ADT_FAIL_PAM + PAM_TOTAL_ERRNUM)) {
(void) strlcpy(buf, pam_strerror(NULL, retval - ADT_FAIL_PAM),
buflen);
} else if ((emsg = strerror(retval)) != NULL) {
(void) strlcpy(buf, emsg, buflen);
} else {
(void) snprintf(buf, buflen, "%d", retval);
}
}
static int
pa_printstr(pr_context_t *context, char *str)
{
int err = 0;
int len, printable;
int mbmax = MB_CUR_MAX;
wchar_t wc;
char c;
if (mbmax == 1) {
while (err == 0 && *str != '\0') {
c = *str++;
printable = isprint((unsigned char)c);
err = pa_putstr(context, printable, &c, 1);
}
return (err);
}
while (err == 0 && *str != '\0') {
len = mbtowc(&wc, str, mbmax);
if (len <= 0) {
len = 1;
printable = 0;
} else {
printable = iswprint(wc);
}
err = pa_putstr(context, printable, str, len);
str += len;
}
return (err);
}
int
pa_print(pr_context_t *context, uval_t *uval, int flag)
{
int returnstat = 0;
int last;
switch (uval->uvaltype) {
case PRA_INT32:
returnstat = pr_printf(context, "%d", uval->int32_val);
break;
case PRA_UINT32:
returnstat = pr_printf(context, "%u", uval->uint32_val);
break;
case PRA_INT64:
returnstat = pr_printf(context, "%"PRId64, uval->int64_val);
break;
case PRA_UINT64:
returnstat = pr_printf(context, "%"PRIu64, uval->uint64_val);
break;
case PRA_SHORT:
returnstat = pr_printf(context, "%hd", uval->short_val);
break;
case PRA_USHORT:
returnstat = pr_printf(context, "%hu", uval->ushort_val);
break;
case PRA_CHAR:
returnstat = pr_printf(context, "%c", uval->char_val);
break;
case PRA_BYTE:
returnstat = pr_printf(context, "%d", uval->char_val);
break;
case PRA_STRING:
returnstat = pa_printstr(context, uval->string_val);
break;
case PRA_HEX32:
returnstat = pr_printf(context, "0x%x", uval->int32_val);
break;
case PRA_HEX64:
returnstat = pr_printf(context, "0x%"PRIx64, uval->int64_val);
break;
case PRA_SHEX:
returnstat = pr_printf(context, "0x%hx", uval->short_val);
break;
case PRA_OCT:
returnstat = pr_printf(context, "%ho", uval->ushort_val);
break;
case PRA_LOCT:
returnstat = pr_printf(context, "%o", (int)uval->uint32_val);
break;
default:
(void) fprintf(stderr, gettext("praudit: Unknown type.\n"));
returnstat = -1;
break;
}
if (returnstat < 0)
return (returnstat);
last = (context->audit_adr->adr_now ==
(context->audit_rec_start + context->audit_rec_len));
if (!(context->format & PRF_XMLM)) {
if (!(context->format & PRF_ONELINE)) {
if ((flag == 1) || last)
returnstat = pr_putchar(context, '\n');
else
returnstat = pr_printf(context, "%s",
context->SEPARATOR);
} else {
if (!last)
returnstat = pr_printf(context, "%s",
context->SEPARATOR);
else
returnstat = pr_putchar(context, '\n');
}
}
return (returnstat);
}
static struct cntrl_mapping {
char from;
char to;
} cntrl_map[] = {
'\0', '0',
'\a', 'a',
'\b', 'b',
'\t', 't',
'\f', 'f',
'\n', 'n',
'\r', 'r',
'\v', 'v'
};
static int cntrl_map_entries = sizeof (cntrl_map)
/ sizeof (struct cntrl_mapping);
void
convertascii(char *p, char *c, int size)
{
int i, j, uc;
for (i = 0; i < size; i++) {
uc = (unsigned char)*(c + i);
if (isascii(uc)) {
if (iscntrl(uc)) {
for (j = 0; j < cntrl_map_entries; j++) {
if (cntrl_map[j].from == uc) {
*p++ = '\\';
*p++ = cntrl_map[j].to;
break;
}
}
if (j == cntrl_map_entries) {
*p++ = '^';
*p++ = (char)(uc ^ 0100);
}
} else {
*p++ = (char)uc;
}
} else {
p += sprintf(p, "\\%03o", uc);
}
}
*p = '\0';
}
int
pa_xgeneric(pr_context_t *context)
{
int returnstat;
returnstat = process_tag(context, TAG_XID, 0, 0);
return (process_tag(context, TAG_XCUID, returnstat, 1));
}
int
pa_liaison(pr_context_t *context, int status, int flag)
{
int returnstat;
int32_t li;
uval_t uval;
if (status >= 0) {
if ((returnstat = pr_adr_int32(context, &li, 1)) != 0) {
return (returnstat);
}
if (!(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_UINT32;
uval.uint32_val = li;
returnstat = pa_print(context, &uval, flag);
}
if ((context->format & PRF_RAWM) || (returnstat == 1)) {
uval.uvaltype = PRA_HEX32;
uval.uint32_val = li;
returnstat = pa_print(context, &uval, flag);
}
return (returnstat);
} else
return (status);
}
int
pa_xid(pr_context_t *context, int status, int flag)
{
int returnstat;
int32_t xid;
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = pr_adr_int32(context, (int32_t *)&xid, 1)) != 0)
return (returnstat);
if (!(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_STRING;
uval.string_val = hexconvert((char *)&xid, sizeof (xid),
sizeof (xid));
if (uval.string_val) {
returnstat = pa_print(context, &uval, flag);
free(uval.string_val);
}
} else {
uval.uvaltype = PRA_INT32;
uval.int32_val = xid;
returnstat = pa_print(context, &uval, flag);
}
return (returnstat);
}
static int
pa_ace_flags(pr_context_t *context, ace_t *ace, int status, int flag)
{
int returnstat;
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = open_tag(context, TAG_ACEFLAGS)) != 0)
return (returnstat);
if (!(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_STRING;
switch (ace->a_flags & ACE_TYPE_FLAGS) {
case ACE_OWNER:
uval.string_val = gettext(OWNERAT_TXT);
break;
case ACE_GROUP | ACE_IDENTIFIER_GROUP:
uval.string_val = gettext(GROUPAT_TXT);
break;
case ACE_IDENTIFIER_GROUP:
uval.string_val = gettext(GROUP_TXT);
break;
case ACE_EVERYONE:
uval.string_val = gettext(EVERYONEAT_TXT);
break;
case 0:
uval.string_val = gettext(USER_TXT);
break;
default:
uval.uvaltype = PRA_USHORT;
uval.uint32_val = ace->a_flags;
}
} else {
uval.uvaltype = PRA_USHORT;
uval.uint32_val = ace->a_flags;
}
if ((returnstat = pa_print(context, &uval, flag)) != 0)
return (returnstat);
return (close_tag(context, TAG_ACEFLAGS));
}
static int
pa_ace_who(pr_context_t *context, ace_t *ace, int status, int flag)
{
int returnstat;
if (status < 0)
return (status);
if ((returnstat = open_tag(context, TAG_ACEID)) != 0)
return (returnstat);
switch (ace->a_flags & ACE_TYPE_FLAGS) {
case ACE_IDENTIFIER_GROUP:
returnstat = pa_print_gid(context, ace->a_who, returnstat,
flag);
break;
default:
returnstat = pa_print_uid(context, ace->a_who, returnstat,
flag);
break;
}
if (returnstat < 0)
return (returnstat);
return (close_tag(context, TAG_ACEID));
}
#define INITIAL_ALLOC 256
static int
strappend(char **str, char *what, size_t *alloc)
{
char *s, *newstr;
size_t needed;
s = *str;
if (s == NULL) {
s = malloc(INITIAL_ALLOC);
if (s == NULL) {
*alloc = 0;
return (-1);
}
*alloc = INITIAL_ALLOC;
s[0] = '\0';
*str = s;
}
needed = strlen(s) + strlen(what) + 1;
if (*alloc < needed) {
newstr = realloc(s, needed);
if (newstr == NULL)
return (-1);
s = newstr;
*alloc = needed;
*str = s;
}
(void) strlcat(s, what, *alloc);
return (0);
}
static int
pa_ace_access_mask(pr_context_t *context, ace_t *ace, int status, int flag)
{
int returnstat, i;
uval_t uval;
char *permstr = NULL;
size_t permstr_alloc = 0;
if (status < 0)
return (status);
if ((returnstat = open_tag(context, TAG_ACEMASK)) != 0)
return (returnstat);
if (context->format & PRF_SHORTM &&
((permstr = malloc(15)) != NULL)) {
for (i = 0; i < 14; i++)
permstr[i] = '-';
if (ace->a_access_mask & ACE_READ_DATA)
permstr[0] = 'r';
if (ace->a_access_mask & ACE_WRITE_DATA)
permstr[1] = 'w';
if (ace->a_access_mask & ACE_EXECUTE)
permstr[2] = 'x';
if (ace->a_access_mask & ACE_APPEND_DATA)
permstr[3] = 'p';
if (ace->a_access_mask & ACE_DELETE)
permstr[4] = 'd';
if (ace->a_access_mask & ACE_DELETE_CHILD)
permstr[5] = 'D';
if (ace->a_access_mask & ACE_READ_ATTRIBUTES)
permstr[6] = 'a';
if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES)
permstr[7] = 'A';
if (ace->a_access_mask & ACE_READ_NAMED_ATTRS)
permstr[8] = 'R';
if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS)
permstr[9] = 'W';
if (ace->a_access_mask & ACE_READ_ACL)
permstr[10] = 'c';
if (ace->a_access_mask & ACE_WRITE_ACL)
permstr[11] = 'C';
if (ace->a_access_mask & ACE_WRITE_OWNER)
permstr[12] = 'o';
if (ace->a_access_mask & ACE_SYNCHRONIZE)
permstr[13] = 's';
permstr[14] = '\0';
uval.uvaltype = PRA_STRING;
uval.string_val = permstr;
} else if (!(context->format & PRF_RAWM)) {
if (ace->a_access_mask & ACE_LIST_DIRECTORY) {
returnstat = strappend(&permstr, gettext(READ_DIR_TXT),
&permstr_alloc);
}
if (ace->a_access_mask & ACE_ADD_FILE) {
returnstat = strappend(&permstr, gettext(ADD_FILE_TXT),
&permstr_alloc);
}
if (ace->a_access_mask & ACE_ADD_SUBDIRECTORY) {
returnstat = strappend(&permstr, gettext(ADD_DIR_TXT),
&permstr_alloc);
}
if (ace->a_access_mask & ACE_READ_NAMED_ATTRS) {
returnstat = strappend(&permstr,
gettext(READ_XATTR_TXT), &permstr_alloc);
}
if (ace->a_access_mask & ACE_WRITE_NAMED_ATTRS) {
returnstat = strappend(&permstr,
gettext(WRITE_XATTR_TXT), &permstr_alloc);
}
if (ace->a_access_mask & ACE_EXECUTE) {
returnstat = strappend(&permstr,
gettext(EXECUTE_TXT), &permstr_alloc);
}
if (ace->a_access_mask & ACE_DELETE_CHILD) {
returnstat = strappend(&permstr,
gettext(DELETE_CHILD_TXT), &permstr_alloc);
}
if (ace->a_access_mask & ACE_READ_ATTRIBUTES) {
returnstat = strappend(&permstr,
gettext(READ_ATTRIBUTES_TXT), &permstr_alloc);
}
if (ace->a_access_mask & ACE_WRITE_ATTRIBUTES) {
returnstat = strappend(&permstr,
gettext(WRITE_ATTRIBUTES_TXT), &permstr_alloc);
}
if (ace->a_access_mask & ACE_DELETE) {
returnstat = strappend(&permstr, gettext(DELETE_TXT),
&permstr_alloc);
}
if (ace->a_access_mask & ACE_READ_ACL) {
returnstat = strappend(&permstr, gettext(READ_ACL_TXT),
&permstr_alloc);
}
if (ace->a_access_mask & ACE_WRITE_ACL) {
returnstat = strappend(&permstr, gettext(WRITE_ACL_TXT),
&permstr_alloc);
}
if (ace->a_access_mask & ACE_WRITE_OWNER) {
returnstat = strappend(&permstr,
gettext(WRITE_OWNER_TXT), &permstr_alloc);
}
if (ace->a_access_mask & ACE_SYNCHRONIZE) {
returnstat = strappend(&permstr,
gettext(SYNCHRONIZE_TXT), &permstr_alloc);
}
if (permstr[strlen(permstr) - 1] == '/')
permstr[strlen(permstr) - 1] = '\0';
uval.uvaltype = PRA_STRING;
uval.string_val = permstr;
}
if ((permstr == NULL) || (returnstat != 0) ||
(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_UINT32;
uval.uint32_val = ace->a_access_mask;
}
returnstat = pa_print(context, &uval, flag);
if (permstr != NULL)
free(permstr);
if (returnstat != 0)
return (returnstat);
return (close_tag(context, TAG_ACEMASK));
}
static int
pa_ace_type(pr_context_t *context, ace_t *ace, int status, int flag)
{
int returnstat;
uval_t uval;
if (status < 0)
return (status);
if ((returnstat = open_tag(context, TAG_ACETYPE)) != 0)
return (returnstat);
if (!(context->format & PRF_RAWM)) {
uval.uvaltype = PRA_STRING;
switch (ace->a_type) {
case ACE_ACCESS_ALLOWED_ACE_TYPE:
uval.string_val = gettext(ALLOW_TXT);
break;
case ACE_ACCESS_DENIED_ACE_TYPE:
uval.string_val = gettext(DENY_TXT);
break;
case ACE_SYSTEM_AUDIT_ACE_TYPE:
uval.string_val = gettext(AUDIT_TXT);
break;
case ACE_SYSTEM_ALARM_ACE_TYPE:
uval.string_val = gettext(ALARM_TXT);
break;
default:
uval.string_val = gettext(UNKNOWN_TXT);
}
} else {
uval.uvaltype = PRA_USHORT;
uval.uint32_val = ace->a_type;
}
if ((returnstat = pa_print(context, &uval, flag)) != 0)
return (returnstat);
return (close_tag(context, TAG_ACETYPE));
}
int
pa_ace(pr_context_t *context, int status, int flag)
{
int returnstat;
ace_t ace;
if (status < 0)
return (status);
if ((returnstat = pr_adr_u_int32(context, &ace.a_who, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_int32(context, &ace.a_access_mask, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_short(context, &ace.a_flags, 1)) != 0)
return (returnstat);
if ((returnstat = pr_adr_u_short(context, &ace.a_type, 1)) != 0)
return (returnstat);
if ((returnstat = pa_ace_flags(context, &ace, returnstat, 0)) != 0)
return (returnstat);
if ((returnstat = pa_ace_who(context, &ace, returnstat, 0)) < 0)
return (returnstat);
if ((returnstat = pa_ace_access_mask(context, &ace,
returnstat, 0)) != 0)
return (returnstat);
return (pa_ace_type(context, &ace, returnstat, flag));
}