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