diff options
Diffstat (limited to 'libapol/src/render.c')
-rw-r--r-- | libapol/src/render.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/libapol/src/render.c b/libapol/src/render.c new file mode 100644 index 0000000..4bc19b6 --- /dev/null +++ b/libapol/src/render.c @@ -0,0 +1,158 @@ +/** + * @file + * + * Routines to render various data structures used by libapol. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * @author David Windsor dwindsor@tresys.com + * + * Copyright (C) 2003-2007 Tresys Technology, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> + +#include <apol/context-query.h> +#include <apol/policy.h> +#include <apol/render.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#ifndef WORDS_BIGENDIAN +extern void swab(const void *from, void *to, ssize_t n); +#endif + +#if LINK_SHARED == 1 +__asm__(".symver apol_ipv4_addr_render_old,apol_ipv4_addr_render@"); +__asm__(".symver apol_ipv4_addr_render_new,apol_ipv4_addr_render@@VERS_4.1"); +#endif + +/** + * @brief Internal version of apol_ipv4_addr_render() version 4.1 + * + * Implementation of the exported function apol_ipv4_addr_render() + * for version 4.1; this symbol name is not exported. + */ +char *apol_ipv4_addr_render_new(const apol_policy_t * policydb, uint32_t addr[4]) +{ + char buf[40], *b; + unsigned char *p = (unsigned char *)&(addr[0]); + snprintf(buf, sizeof(buf), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + if ((b = strdup(buf)) == NULL) { + ERR(policydb, "%s", strerror(ENOMEM)); + } + return b; +} + +#if LINK_SHARED == 0 +char *apol_ipv4_addr_render(const apol_policy_t * policydb, uint32_t addr[4]) +{ + return apol_ipv4_addr_render_new(policydb, addr); +} +#endif + +/** + * @brief Internal version of apol_ipv4_addr_render() version 4.0 or earlier + * @deprecated use the 4.1 version. + * @see apol_ipv4_addr_render() + */ +char *apol_ipv4_addr_render_old(apol_policy_t * policydb, uint32_t addr) +{ + char buf[40], *b; + unsigned char *p = (unsigned char *)&addr; + snprintf(buf, sizeof(buf), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + if ((b = strdup(buf)) == NULL) { + ERR(policydb, "%s", strerror(ENOMEM)); + } + return b; +} + +char *apol_ipv6_addr_render(const apol_policy_t * policydb, uint32_t addr[4]) +{ + uint16_t tmp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int i, sz = 0, retv; + char buf[40], *b; /* 8 * 4 hex digits + 7 * ':' + '\0' == max size of string */ + int contract = 0, prev_contr = 0, contr_idx_end = -1; + for (i = 0; i < 4; i++) { + uint32_t a; +#ifdef WORDS_BIGENDIAN + a = addr[i]; +#else + swab(addr + i, &a, sizeof(a)); +#endif + /* have to use division and mod here, so as to ignore + * host system's byte ordering */ + tmp[2 * i] = a % (1 << 16); + tmp[2 * i + 1] = a / (1 << 16); + } + + for (i = 0; i < 8; i++) { + if (tmp[i] == 0) { + contract++; + if (i == 7 && contr_idx_end == -1) + contr_idx_end = 8; + } else { + if (contract > prev_contr) { + contr_idx_end = i; + } + prev_contr = contract; + contract = 0; + } + } + + if (prev_contr > contract) + contract = prev_contr; + + for (i = 0; i < 8; i++) { + if (i == contr_idx_end - contract) { + retv = snprintf(buf + sz, 40 - sz, i ? ":" : "::"); + sz += retv; + } else if (i > contr_idx_end - contract && i < contr_idx_end) { + continue; + } else { + retv = snprintf(buf + sz, 40 - sz, i == 7 ? "%04x" : "%04x:", tmp[i]); + sz += retv; + } + } + + buf[sz] = '\0'; + if ((b = strdup(buf)) == NULL) { + ERR(policydb, "%s", strerror(ENOMEM)); + } + return b; +} + +char *apol_qpol_context_render(const apol_policy_t * p, const qpol_context_t * context) +{ + apol_context_t *c = NULL; + char *rendered_context; + + if (p == NULL || context == NULL) { + ERR(p, "%s", strerror(EINVAL)); + errno = EINVAL; + return NULL; + } + + if ((c = apol_context_create_from_qpol_context(p, context)) == NULL) { + return NULL; + } + rendered_context = apol_context_render(p, c); + apol_context_destroy(&c); + return rendered_context; +} |