#if !defined(lint) && !defined(__CODECENTER__)
static char *rcsid = "$Header$";
#endif
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#include <winsock.h>
#else
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include <errno.h>
#include <autoconf.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#include <gssapi/gssapi_generic.h>
#include "gss-misc.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
extern char *malloc();
#endif
FILE *display_file;
gss_buffer_desc empty_token_buf = { 0, (void *) "" };
gss_buffer_t empty_token = &empty_token_buf;
static void display_status_1(char *m, OM_uint32 code, int type);
static int
write_all(int fildes, char *buf, unsigned int nbyte)
{
int ret;
char *ptr;
for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
ret = send(fildes, ptr, nbyte, 0);
if (ret < 0) {
if (errno == EINTR)
continue;
return (ret);
} else if (ret == 0) {
return (ptr - buf);
}
}
return (ptr - buf);
}
static int
read_all(int fildes, char *buf, unsigned int nbyte)
{
int ret;
char *ptr;
fd_set rfds;
struct timeval tv;
FD_ZERO(&rfds);
FD_SET(fildes, &rfds);
tv.tv_sec = 10;
tv.tv_usec = 0;
for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {
if (select(FD_SETSIZE, &rfds, NULL, NULL, &tv) <= 0
|| !FD_ISSET(fildes, &rfds))
return (ptr - buf);
ret = recv(fildes, ptr, nbyte, 0);
if (ret < 0) {
if (errno == EINTR)
continue;
return (ret);
} else if (ret == 0) {
return (ptr - buf);
}
}
return (ptr - buf);
}
int
send_token(s, flags, tok)
int s;
int flags;
gss_buffer_t tok;
{
int ret;
unsigned char char_flags = (unsigned char) flags;
unsigned char lenbuf[4];
if (char_flags) {
ret = write_all(s, (char *) &char_flags, 1);
if (ret != 1) {
perror("sending token flags");
return -1;
}
}
if (tok->length > 0xffffffffUL)
abort();
lenbuf[0] = (tok->length >> 24) & 0xff;
lenbuf[1] = (tok->length >> 16) & 0xff;
lenbuf[2] = (tok->length >> 8) & 0xff;
lenbuf[3] = tok->length & 0xff;
ret = write_all(s, lenbuf, 4);
if (ret < 0) {
perror("sending token length");
return -1;
} else if (ret != 4) {
if (display_file)
fprintf(display_file,
"sending token length: %d of %d bytes written\n", ret, 4);
return -1;
}
ret = write_all(s, tok->value, tok->length);
if (ret < 0) {
perror("sending token data");
return -1;
} else if (ret != tok->length) {
if (display_file)
fprintf(display_file,
"sending token data: %d of %d bytes written\n",
ret, (int) tok->length);
return -1;
}
return 0;
}
int
recv_token(s, flags, tok)
int s;
int *flags;
gss_buffer_t tok;
{
int ret;
unsigned char char_flags;
unsigned char lenbuf[4];
ret = read_all(s, (char *) &char_flags, 1);
if (ret < 0) {
perror("reading token flags");
return -1;
} else if (!ret) {
if (display_file)
fputs("reading token flags: 0 bytes read\n", display_file);
return -1;
} else {
*flags = (int) char_flags;
}
if (char_flags == 0) {
lenbuf[0] = 0;
ret = read_all(s, &lenbuf[1], 3);
if (ret < 0) {
perror("reading token length");
return -1;
} else if (ret != 3) {
if (display_file)
fprintf(display_file,
"reading token length: %d of %d bytes read\n", ret, 3);
return -1;
}
} else {
ret = read_all(s, lenbuf, 4);
if (ret < 0) {
perror("reading token length");
return -1;
} else if (ret != 4) {
if (display_file)
fprintf(display_file,
"reading token length: %d of %d bytes read\n", ret, 4);
return -1;
}
}
tok->length = ((lenbuf[0] << 24)
| (lenbuf[1] << 16)
| (lenbuf[2] << 8)
| lenbuf[3]);
tok->value = (char *) malloc(tok->length ? tok->length : 1);
if (tok->length && tok->value == NULL) {
if (display_file)
fprintf(display_file, "Out of memory allocating token data\n");
return -1;
}
ret = read_all(s, (char *) tok->value, tok->length);
if (ret < 0) {
perror("reading token data");
free(tok->value);
return -1;
} else if (ret != tok->length) {
fprintf(stderr, "sending token data: %d of %d bytes written\n",
ret, (int) tok->length);
free(tok->value);
return -1;
}
return 0;
}
static void
display_status_1(m, code, type)
char *m;
OM_uint32 code;
int type;
{
OM_uint32 maj_stat, min_stat;
gss_buffer_desc msg;
OM_uint32 msg_ctx;
msg_ctx = 0;
while (1) {
maj_stat = gss_display_status(&min_stat, code,
type, GSS_C_NULL_OID, &msg_ctx, &msg);
if (display_file)
fprintf(display_file, "GSS-API error %s: %s\n", m,
(char *) msg.value);
(void) gss_release_buffer(&min_stat, &msg);
if (!msg_ctx)
break;
}
}
void
display_status(msg, maj_stat, min_stat)
char *msg;
OM_uint32 maj_stat;
OM_uint32 min_stat;
{
display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
display_status_1(msg, min_stat, GSS_C_MECH_CODE);
}
void
display_ctx_flags(flags)
OM_uint32 flags;
{
if (flags & GSS_C_DELEG_FLAG)
fprintf(display_file, "context flag: GSS_C_DELEG_FLAG\n");
if (flags & GSS_C_MUTUAL_FLAG)
fprintf(display_file, "context flag: GSS_C_MUTUAL_FLAG\n");
if (flags & GSS_C_REPLAY_FLAG)
fprintf(display_file, "context flag: GSS_C_REPLAY_FLAG\n");
if (flags & GSS_C_SEQUENCE_FLAG)
fprintf(display_file, "context flag: GSS_C_SEQUENCE_FLAG\n");
if (flags & GSS_C_CONF_FLAG)
fprintf(display_file, "context flag: GSS_C_CONF_FLAG \n");
if (flags & GSS_C_INTEG_FLAG)
fprintf(display_file, "context flag: GSS_C_INTEG_FLAG \n");
}
void
print_token(tok)
gss_buffer_t tok;
{
int i;
unsigned char *p = tok->value;
if (!display_file)
return;
for (i = 0; i < tok->length; i++, p++) {
fprintf(display_file, "%02x ", *p);
if ((i % 16) == 15) {
fprintf(display_file, "\n");
}
}
fprintf(display_file, "\n");
fflush(display_file);
}
#ifdef _WIN32
#include <sys\timeb.h>
#include <time.h>
int
gettimeofday(struct timeval *tv, void *ignore_tz)
{
struct _timeb tb;
_tzset();
_ftime(&tb);
if (tv) {
tv->tv_sec = tb.time;
tv->tv_usec = tb.millitm * 1000;
}
return 0;
}
#endif