Blame src/gp_util.c

Packit Service 9f2c4a
/* Copyright (C) 2013 the GSS-PROXY contributors, see COPYING for license */
Packit Service 9f2c4a
Packit Service 9f2c4a
#include "config.h"
Packit Service 9f2c4a
#include <stdbool.h>
Packit Service 9f2c4a
#include <string.h>
Packit Service 9f2c4a
#include <stdlib.h>
Packit Service 9f2c4a
#include <stdio.h>
Packit Service 9f2c4a
#include <errno.h>
Packit Service 9f2c4a
#include <unistd.h>
Packit Service 9f2c4a
Packit Service 9f2c4a
#include "gp_common.h"
Packit Service 9f2c4a
Packit Service 9f2c4a
bool gp_same(const char *a, const char *b)
Packit Service 9f2c4a
{
Packit Service 9f2c4a
    if (a == b || (a && b && strcmp(a, b) == 0)) {
Packit Service 9f2c4a
        return true;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
    return false;
Packit Service 9f2c4a
}
Packit Service 9f2c4a
Packit Service 9f2c4a
bool gp_boolean_is_true(const char *s)
Packit Service 9f2c4a
{
Packit Service 9f2c4a
    if (strcasecmp(s, "1") == 0 ||
Packit Service 9f2c4a
        strcasecmp(s, "on") == 0 ||
Packit Service 9f2c4a
        strcasecmp(s, "true") == 0 ||
Packit Service 9f2c4a
        strcasecmp(s, "yes") == 0) {
Packit Service 9f2c4a
        return true;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    return false;
Packit Service 9f2c4a
}
Packit Service 9f2c4a
Packit Service 9f2c4a
char *gp_getenv(const char *name)
Packit Service 9f2c4a
{
Packit Service 9f2c4a
#if HAVE_SECURE_GETENV
Packit Service 9f2c4a
    return secure_getenv(name);
Packit Service 9f2c4a
#elif HAVE___SECURE_GETENV
Packit Service 9f2c4a
    return __secure_getenv(name);
Packit Service 9f2c4a
#else
Packit Service 9f2c4a
#include <unistd.h>
Packit Service 9f2c4a
#include <sys/types.h>
Packit Service 9f2c4a
#warning secure_getenv not available, falling back to poorman emulation
Packit Service 9f2c4a
    if ((getuid() == geteuid()) &&
Packit Service 9f2c4a
        (getgid() == getegid())) {
Packit Service 9f2c4a
        return getenv(name);
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
    return NULL;
Packit Service 9f2c4a
#endif
Packit Service 9f2c4a
}
Packit Service 9f2c4a
Packit Service 9f2c4a
/* NOTE: because strerror_r() is such a mess with glibc, we need to do some
Packit Service 9f2c4a
 * magic checking to find out what function prototype is being used of the
Packit Service 9f2c4a
 * two incompatible ones, and pray it doesn't change in the future.
Packit Service 9f2c4a
 * On top of that to avoid impacting the current code too much we've got to use
Packit Service 9f2c4a
 * thread-local storage to hold a buffer.
Packit Service 9f2c4a
 * gp_strerror() is basically a thread-safe version of strerror() that can
Packit Service 9f2c4a
 * never fail.
Packit Service 9f2c4a
 */
Packit Service 9f2c4a
const char gp_internal_err[] = "Internal strerror_r() error.";
Packit Service 9f2c4a
#define MAX_GP_STRERROR 1024
Packit Service 9f2c4a
char *gp_strerror(int errnum)
Packit Service 9f2c4a
{
Packit Service 9f2c4a
    static __thread char buf[MAX_GP_STRERROR];
Packit Service 9f2c4a
    int saved_errno = errno;
Packit Service 9f2c4a
Packit Service 9f2c4a
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
Packit Service 9f2c4a
    /* XSI version */
Packit Service 9f2c4a
    int ret;
Packit Service 9f2c4a
Packit Service 9f2c4a
    ret = strerror_r(errnum, buf, MAX_GP_STRERROR);
Packit Service 9f2c4a
    if (ret == -1) ret = errno;
Packit Service 9f2c4a
    switch (ret) {
Packit Service 9f2c4a
    case 0:
Packit Service 9f2c4a
        break;
Packit Service 9f2c4a
    case EINVAL:
Packit Service 9f2c4a
        ret = snprintf(buf, MAX_GP_STRERROR,
Packit Service 9f2c4a
                       "Unknown error code: %d", errnum);
Packit Service 9f2c4a
        if (ret > 0) break;
Packit Service 9f2c4a
        /* fallthrough */
Packit Service 9f2c4a
    default:
Packit Service 9f2c4a
        ret = snprintf(buf, MAX_GP_STRERROR,
Packit Service 9f2c4a
                       "Internal error describing error code: %d", errnum);
Packit Service 9f2c4a
        if (ret > 0) break;
Packit Service 9f2c4a
        memset(buf, 0, MAX_GP_STRERROR);
Packit Service 9f2c4a
        strncpy(buf, gp_internal_err, MAX_GP_STRERROR);
Packit Service 9f2c4a
        buf[MAX_GP_STRERROR -1] = '\0';
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
#else
Packit Service 9f2c4a
    /* GNU-specific version */
Packit Service 9f2c4a
    char *ret;
Packit Service 9f2c4a
Packit Service 9f2c4a
    ret = strerror_r(errnum, buf, MAX_GP_STRERROR);
Packit Service 9f2c4a
    if (ret == NULL) {
Packit Service 9f2c4a
        memset(buf, 0, MAX_GP_STRERROR);
Packit Service 9f2c4a
        strncpy(buf, gp_internal_err, MAX_GP_STRERROR);
Packit Service 9f2c4a
        buf[MAX_GP_STRERROR -1] = '\0';
Packit Service 9f2c4a
    } else if (ret != buf) {
Packit Service 9f2c4a
        memset(buf, 0, MAX_GP_STRERROR);
Packit Service 9f2c4a
        strncpy(buf, ret, MAX_GP_STRERROR);
Packit Service 9f2c4a
        buf[MAX_GP_STRERROR -1] = '\0';
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
#endif
Packit Service 9f2c4a
Packit Service 9f2c4a
    errno = saved_errno;
Packit Service 9f2c4a
    return buf;
Packit Service 9f2c4a
}
Packit Service 9f2c4a
Packit Service 9f2c4a
ssize_t gp_safe_read(int fd, void *buf, size_t count)
Packit Service 9f2c4a
{
Packit Service 9f2c4a
    char *b = (char *)buf;
Packit Service 9f2c4a
    size_t len = 0;
Packit Service 9f2c4a
    ssize_t ret;
Packit Service 9f2c4a
Packit Service 9f2c4a
    do {
Packit Service 9f2c4a
        ret = read(fd, &b[len], count - len);
Packit Service 9f2c4a
        if (ret == -1) {
Packit Service 9f2c4a
            if (errno == EINTR) continue;
Packit Service 9f2c4a
            return ret;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
        if (ret == 0) break; /* EOF */
Packit Service 9f2c4a
        len += ret;
Packit Service 9f2c4a
    } while (count > len);
Packit Service 9f2c4a
Packit Service 9f2c4a
    return len;
Packit Service 9f2c4a
}
Packit Service 9f2c4a
Packit Service 9f2c4a
ssize_t gp_safe_write(int fd, const void *buf, size_t count)
Packit Service 9f2c4a
{
Packit Service 9f2c4a
    const char *b = (const char *)buf;
Packit Service 9f2c4a
    size_t len = 0;
Packit Service 9f2c4a
    ssize_t ret;
Packit Service 9f2c4a
Packit Service 9f2c4a
    do {
Packit Service 9f2c4a
        ret = write(fd, &b[len], count - len);
Packit Service 9f2c4a
        if (ret == -1) {
Packit Service 9f2c4a
            if (errno == EINTR) continue;
Packit Service 9f2c4a
            return ret;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
        if (ret == 0) break; /* EOF */
Packit Service 9f2c4a
        len += ret;
Packit Service 9f2c4a
    } while (count > len);
Packit Service 9f2c4a
Packit Service 9f2c4a
    return len;
Packit Service 9f2c4a
}
Packit Service 9f2c4a
Packit Service 9f2c4a
uint32_t gp_add_option(gssx_option **options_val, u_int *options_len,
Packit Service 9f2c4a
                       const void *option, size_t option_len,
Packit Service 9f2c4a
                       const void *value, size_t value_len)
Packit Service 9f2c4a
{
Packit Service 9f2c4a
    gssx_option opt = { 0 };
Packit Service 9f2c4a
    gssx_option *out;
Packit Service 9f2c4a
    uint32_t ret;
Packit Service 9f2c4a
Packit Service 9f2c4a
    opt.option.octet_string_val = malloc(option_len);
Packit Service 9f2c4a
    if (!opt.option.octet_string_val) {
Packit Service 9f2c4a
        ret = ENOMEM;
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
    memcpy(opt.option.octet_string_val, option, option_len);
Packit Service 9f2c4a
    opt.option.octet_string_len = option_len;
Packit Service 9f2c4a
Packit Service 9f2c4a
    if (value_len != 0) {
Packit Service 9f2c4a
        opt.value.octet_string_val = malloc(value_len);
Packit Service 9f2c4a
        if (!opt.value.octet_string_val) {
Packit Service 9f2c4a
            ret = ENOMEM;
Packit Service 9f2c4a
            goto done;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
        memcpy(opt.value.octet_string_val, value, value_len);
Packit Service 9f2c4a
        opt.value.octet_string_len = value_len;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    out = realloc(*options_val, (*options_len + 1) * sizeof(gssx_option));
Packit Service 9f2c4a
    if (!out) {
Packit Service 9f2c4a
        ret = ENOMEM;
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    out[*options_len] = opt;
Packit Service 9f2c4a
    *options_val = out;
Packit Service 9f2c4a
    (*options_len)++;
Packit Service 9f2c4a
Packit Service 9f2c4a
    ret = 0;
Packit Service 9f2c4a
Packit Service 9f2c4a
done:
Packit Service 9f2c4a
    if (ret) {
Packit Service 9f2c4a
        xdr_free((xdrproc_t)xdr_gssx_option, (char *)&opt;;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
    return ret;
Packit Service 9f2c4a
}