diff options
author | Michael Biebl <biebl@debian.org> | 2008-03-29 12:14:44 +0100 |
---|---|---|
committer | Michael Biebl <biebl@debian.org> | 2008-03-29 12:14:44 +0100 |
commit | 12e8c69354614a03f06a8617f25d145ab091f504 (patch) | |
tree | 3b19dc723cc0ce48020bc3f077e7d5d27b3a1cfe /gss-misc.c | |
parent | 81367522c83c4b1b8cb157925e103edc9f148cd4 (diff) | |
download | rsyslog-12e8c69354614a03f06a8617f25d145ab091f504.tar.gz |
Imported Upstream version 1.20.1upstream/1.20.1
Diffstat (limited to 'gss-misc.c')
-rw-r--r-- | gss-misc.c | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/gss-misc.c b/gss-misc.c new file mode 100644 index 0000000..68197f0 --- /dev/null +++ b/gss-misc.c @@ -0,0 +1,210 @@ +#include "config.h" +#if defined(SYSLOG_INET) && defined(USE_GSSAPI) +#include "rsyslog.h" +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <fnmatch.h> +#include <assert.h> +#include <errno.h> +#include <ctype.h> +#include <unistd.h> +#ifdef USE_PTHREADS +#include <pthread.h> +#else +#include <fcntl.h> +#endif +#include <gssapi.h> +#include "syslogd.h" +#include "syslogd-types.h" +#include "srUtils.h" +#include "net.h" +#include "omfwd.h" +#include "template.h" +#include "msg.h" +#include "tcpsyslog.h" +#include "module-template.h" +#include "gss-misc.h" + + +static void display_status_(char *m, OM_uint32 code, int type) +{ + OM_uint32 maj_stat, min_stat, msg_ctx = 0; + gss_buffer_desc msg; + + do { + maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NO_OID, &msg_ctx, &msg); + if (maj_stat != GSS_S_COMPLETE) { + logerrorSz("GSS-API error in gss_display_status called from <%s>\n", m); + break; + } else { + char buf[1024]; + snprintf(buf, sizeof(buf), "GSS-API error %s: %s\n", m, (char *) msg.value); + buf[sizeof(buf)/sizeof(char) - 1] = '\0'; + logerror(buf); + } + if (msg.length != 0) + gss_release_buffer(&min_stat, &msg); + } while (msg_ctx); +} + + +void display_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat) +{ + display_status_(m, maj_stat, GSS_C_GSS_CODE); + display_status_(m, min_stat, GSS_C_MECH_CODE); +} + + +void display_ctx_flags(OM_uint32 flags) +{ + if (flags & GSS_C_DELEG_FLAG) + dbgprintf("GSS_C_DELEG_FLAG\n"); + if (flags & GSS_C_MUTUAL_FLAG) + dbgprintf("GSS_C_MUTUAL_FLAG\n"); + if (flags & GSS_C_REPLAY_FLAG) + dbgprintf("GSS_C_REPLAY_FLAG\n"); + if (flags & GSS_C_SEQUENCE_FLAG) + dbgprintf("GSS_C_SEQUENCE_FLAG\n"); + if (flags & GSS_C_CONF_FLAG) + dbgprintf("GSS_C_CONF_FLAG\n"); + if (flags & GSS_C_INTEG_FLAG) + dbgprintf("GSS_C_INTEG_FLAG\n"); +} + + +static int read_all(int fd, char *buf, unsigned int nbyte) +{ + int ret; + char *ptr; + fd_set rfds; + struct timeval tv; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + tv.tv_sec = 1; + tv.tv_usec = 0; + + for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { + if ((ret = select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) <= 0 + || !FD_ISSET(fd, &rfds)) + return ret; + ret = recv(fd, ptr, nbyte, 0); + if (ret < 0) { + if (errno == EINTR) + continue; + return (ret); + } else if (ret == 0) { + return (ptr - buf); + } + } + + return (ptr - buf); +} + + +static int write_all(int fd, char *buf, unsigned int nbyte) +{ + int ret; + char *ptr; + + for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { + ret = send(fd, ptr, nbyte, 0); + if (ret < 0) { + if (errno == EINTR) + continue; + return (ret); + } else if (ret == 0) { + return (ptr - buf); + } + } + + return (ptr - buf); +} + + +int recv_token(int s, gss_buffer_t tok) +{ + int ret; + unsigned char lenbuf[4]; + unsigned int len; + + ret = read_all(s, (char *) lenbuf, 4); + if (ret < 0) { + logerror("GSS-API error reading token length"); + return -1; + } else if (!ret) { + return 0; + } else if (ret != 4) { + logerror("GSS-API error reading token length"); + return -1; + } + + len = ((lenbuf[0] << 24) + | (lenbuf[1] << 16) + | (lenbuf[2] << 8) + | lenbuf[3]); + tok->length = ntohl(len); + + tok->value = (char *) malloc(tok->length ? tok->length : 1); + if (tok->length && tok->value == NULL) { + logerror("Out of memory allocating token data\n"); + return -1; + } + + ret = read_all(s, (char *) tok->value, tok->length); + if (ret < 0) { + logerror("GSS-API error reading token data"); + free(tok->value); + return -1; + } else if (ret != (int) tok->length) { + logerror("GSS-API error reading token data"); + free(tok->value); + return -1; + } + + return 1; +} + + +int send_token(int s, gss_buffer_t tok) +{ + int ret; + unsigned char lenbuf[4]; + unsigned int len; + + if (tok->length > 0xffffffffUL) + abort(); /* TODO: we need to reconsider this, abort() is not really a solution - degrade, but keep running */ + len = htonl(tok->length); + lenbuf[0] = (len >> 24) & 0xff; + lenbuf[1] = (len >> 16) & 0xff; + lenbuf[2] = (len >> 8) & 0xff; + lenbuf[3] = len & 0xff; + + ret = write_all(s, (char *) lenbuf, 4); + if (ret < 0) { + logerror("GSS-API error sending token length"); + return -1; + } else if (ret != 4) { + logerror("GSS-API error sending token length"); + return -1; + } + + ret = write_all(s, tok->value, tok->length); + if (ret < 0) { + logerror("GSS-API error sending token data"); + return -1; + } else if (ret != (int) tok->length) { + logerror("GSS-API error sending token data"); + return -1; + } + + return 0; +} + +#endif /* #if defined(SYSLOG_INET) && defined(USE_GSSAPI) */ |