Path: blob/main/crypto/krb5/src/appl/gss-sample/gss-misc.c
34907 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/*2* Copyright 1994 by OpenVision Technologies, Inc.3*4* Permission to use, copy, modify, distribute, and sell this software5* and its documentation for any purpose is hereby granted without fee,6* provided that the above copyright notice appears in all copies and7* that both that copyright notice and this permission notice appear in8* supporting documentation, and that the name of OpenVision not be used9* in advertising or publicity pertaining to distribution of the software10* without specific, written prior permission. OpenVision makes no11* representations about the suitability of this software for any12* purpose. It is provided "as is" without express or implied warranty.13*14* OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,15* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO16* EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR17* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF18* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR19* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR20* PERFORMANCE OF THIS SOFTWARE.21*/22/*23* Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology.24* All rights reserved.25*26* Export of this software from the United States of America may27* require a specific license from the United States Government.28* It is the responsibility of any person or organization contemplating29* export to obtain such a license before exporting.30*31* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and32* distribute this software and its documentation for any purpose and33* without fee is hereby granted, provided that the above copyright34* notice appear in all copies and that both that copyright notice and35* this permission notice appear in supporting documentation, and that36* the name of M.I.T. not be used in advertising or publicity pertaining37* to distribution of the software without specific, written prior38* permission. Furthermore if you modify this software you must label39* your software as modified software and not distribute it in such a40* fashion that it might be confused with the original M.I.T. software.41* M.I.T. makes no representations about the suitability of42* this software for any purpose. It is provided "as is" without express43* or implied warranty.44*/4546#include <autoconf.h>4748#include <stdio.h>49#ifdef _WIN3250#include <windows.h>51#include <winsock.h>52#else53#include <sys/types.h>54#include <netinet/in.h>55#include <sys/socket.h>56#endif57#include <errno.h>5859#ifdef HAVE_UNISTD_H60#include <unistd.h>61#endif62#include <string.h>6364/* need struct timeval */65#ifdef HAVE_SYS_TIME_H66#include <sys/time.h>67#else68#include <time.h>69#endif7071#include <gssapi/gssapi_generic.h>72#include "gss-misc.h"7374#ifdef HAVE_STDLIB_H75#include <stdlib.h>76#else77extern char *malloc();78#endif7980FILE *display_file;8182gss_buffer_desc empty_token_buf = { 0, (void *) "" };83gss_buffer_t empty_token = &empty_token_buf;8485static void display_status_1(char *m, OM_uint32 code, int type);8687static int88write_all(int fildes, const void *data, unsigned int nbyte)89{90int ret;91const char *ptr, *buf = data;9293for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {94ret = send(fildes, ptr, nbyte, 0);95if (ret < 0) {96if (errno == EINTR)97continue;98return (ret);99} else if (ret == 0) {100return (ptr - buf);101}102}103104return (ptr - buf);105}106107static int108read_all(int fildes, void *data, unsigned int nbyte)109{110int ret;111char *ptr, *buf = data;112fd_set rfds;113struct timeval tv;114115FD_ZERO(&rfds);116FD_SET(fildes, &rfds);117tv.tv_sec = 300;118tv.tv_usec = 0;119120for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) {121if (select(FD_SETSIZE, &rfds, NULL, NULL, &tv) <= 0122|| !FD_ISSET(fildes, &rfds))123return (ptr - buf);124ret = recv(fildes, ptr, nbyte, 0);125if (ret < 0) {126if (errno == EINTR)127continue;128return (ret);129} else if (ret == 0) {130return (ptr - buf);131}132}133134return (ptr - buf);135}136137/*138* Function: send_token139*140* Purpose: Writes a token to a file descriptor.141*142* Arguments:143*144* s (r) an open file descriptor145* flags (r) the flags to write146* tok (r) the token to write147*148* Returns: 0 on success, -1 on failure149*150* Effects:151*152* If the flags are non-null, send_token writes the token flags (a153* single byte, even though they're passed in in an integer). Next,154* the token length (as a network long) and then the token data are155* written to the file descriptor s. It returns 0 on success, and -1156* if an error occurs or if it could not write all the data.157*/158int159send_token(int s, int flags, gss_buffer_t tok)160{161int ret;162unsigned char char_flags = (unsigned char) flags;163unsigned char lenbuf[4];164165if (char_flags) {166ret = write_all(s, (char *) &char_flags, 1);167if (ret != 1) {168perror("sending token flags");169return -1;170}171}172if (tok->length > 0xffffffffUL)173abort();174lenbuf[0] = (tok->length >> 24) & 0xff;175lenbuf[1] = (tok->length >> 16) & 0xff;176lenbuf[2] = (tok->length >> 8) & 0xff;177lenbuf[3] = tok->length & 0xff;178179ret = write_all(s, lenbuf, 4);180if (ret < 0) {181perror("sending token length");182return -1;183} else if (ret != 4) {184if (display_file)185fprintf(display_file,186"sending token length: %d of %d bytes written\n", ret, 4);187return -1;188}189190ret = write_all(s, tok->value, tok->length);191if (ret < 0) {192perror("sending token data");193return -1;194} else if ((size_t)ret != tok->length) {195if (display_file)196fprintf(display_file,197"sending token data: %d of %d bytes written\n",198ret, (int) tok->length);199return -1;200}201202return 0;203}204205/*206* Function: recv_token207*208* Purpose: Reads a token from a file descriptor.209*210* Arguments:211*212* s (r) an open file descriptor213* flags (w) the read flags214* tok (w) the read token215*216* Returns: 0 on success, -1 on failure217*218* Effects:219*220* recv_token reads the token flags (a single byte, even though221* they're stored into an integer, then reads the token length (as a222* network long), allocates memory to hold the data, and then reads223* the token data from the file descriptor s. It blocks to read the224* length and data, if necessary. On a successful return, the token225* should be freed with gss_release_buffer. It returns 0 on success,226* and -1 if an error occurs or if it could not read all the data.227*/228int229recv_token(int s, int *flags, gss_buffer_t tok)230{231int ret;232unsigned char char_flags;233unsigned char lenbuf[4];234235ret = read_all(s, (char *) &char_flags, 1);236if (ret < 0) {237perror("reading token flags");238return -1;239} else if (!ret) {240if (display_file)241fputs("reading token flags: 0 bytes read\n", display_file);242return -1;243} else {244*flags = (int) char_flags;245}246247if (char_flags == 0) {248lenbuf[0] = 0;249ret = read_all(s, &lenbuf[1], 3);250if (ret < 0) {251perror("reading token length");252return -1;253} else if (ret != 3) {254if (display_file)255fprintf(display_file,256"reading token length: %d of %d bytes read\n", ret, 3);257return -1;258}259} else {260ret = read_all(s, lenbuf, 4);261if (ret < 0) {262perror("reading token length");263return -1;264} else if (ret != 4) {265if (display_file)266fprintf(display_file,267"reading token length: %d of %d bytes read\n", ret, 4);268return -1;269}270}271272tok->length = ((lenbuf[0] << 24)273| (lenbuf[1] << 16)274| (lenbuf[2] << 8)275| lenbuf[3]);276tok->value = (char *) malloc(tok->length ? tok->length : 1);277if (tok->length && tok->value == NULL) {278if (display_file)279fprintf(display_file, "Out of memory allocating token data\n");280return -1;281}282283ret = read_all(s, (char *) tok->value, tok->length);284if (ret < 0) {285perror("reading token data");286free(tok->value);287return -1;288} else if ((size_t)ret != tok->length) {289fprintf(stderr, "sending token data: %d of %d bytes written\n",290ret, (int) tok->length);291free(tok->value);292return -1;293}294295return 0;296}297298static void299display_status_1(char *m, OM_uint32 code, int type)300{301OM_uint32 min_stat;302gss_buffer_desc msg;303OM_uint32 msg_ctx;304305msg_ctx = 0;306while (1) {307(void) gss_display_status(&min_stat, code, type, GSS_C_NULL_OID,308&msg_ctx, &msg);309if (display_file)310fprintf(display_file, "GSS-API error %s: %s\n", m,311(char *) msg.value);312(void) gss_release_buffer(&min_stat, &msg);313314if (!msg_ctx)315break;316}317}318319/*320* Function: display_status321*322* Purpose: displays GSS-API messages323*324* Arguments:325*326* msg a string to be displayed with the message327* maj_stat the GSS-API major status code328* min_stat the GSS-API minor status code329*330* Effects:331*332* The GSS-API messages associated with maj_stat and min_stat are333* displayed on stderr, each preceded by "GSS-API error <msg>: " and334* followed by a newline.335*/336void337display_status(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat)338{339display_status_1(msg, maj_stat, GSS_C_GSS_CODE);340display_status_1(msg, min_stat, GSS_C_MECH_CODE);341}342343/*344* Function: display_ctx_flags345*346* Purpose: displays the flags returned by context initiation in347* a human-readable form348*349* Arguments:350*351* int ret_flags352*353* Effects:354*355* Strings corresponding to the context flags are printed on356* stdout, preceded by "context flag: " and followed by a newline357*/358359void360display_ctx_flags(OM_uint32 flags)361{362if (flags & GSS_C_DELEG_FLAG)363fprintf(display_file, "context flag: GSS_C_DELEG_FLAG\n");364if (flags & GSS_C_MUTUAL_FLAG)365fprintf(display_file, "context flag: GSS_C_MUTUAL_FLAG\n");366if (flags & GSS_C_REPLAY_FLAG)367fprintf(display_file, "context flag: GSS_C_REPLAY_FLAG\n");368if (flags & GSS_C_SEQUENCE_FLAG)369fprintf(display_file, "context flag: GSS_C_SEQUENCE_FLAG\n");370if (flags & GSS_C_CONF_FLAG)371fprintf(display_file, "context flag: GSS_C_CONF_FLAG \n");372if (flags & GSS_C_INTEG_FLAG)373fprintf(display_file, "context flag: GSS_C_INTEG_FLAG \n");374}375376void377print_token(gss_buffer_t tok)378{379unsigned int i;380unsigned char *p = tok->value;381382if (!display_file)383return;384for (i = 0; i < tok->length; i++, p++) {385fprintf(display_file, "%02x ", *p);386if ((i % 16) == 15) {387fprintf(display_file, "\n");388}389}390fprintf(display_file, "\n");391fflush(display_file);392}393394#ifdef _WIN32395#include <sys\timeb.h>396#include <time.h>397398int399gettimeofday(struct timeval *tv, void *ignore_tz)400{401struct _timeb tb;402_tzset();403_ftime(&tb);404if (tv) {405tv->tv_sec = tb.time;406tv->tv_usec = tb.millitm * 1000;407}408return 0;409}410#endif /* _WIN32 */411412413