Path: blob/main/crypto/krb5/src/util/support/ipc_stream.c
34889 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* util/support/ipc_stream.c */2/*3* Copyright 2006, 2007, 2009 Massachusetts Institute of Technology.4* All Rights Reserved.5*6* Export of this software from the United States of America may7* require a specific license from the United States Government.8* It is the responsibility of any person or organization contemplating9* export to obtain such a license before exporting.10*11* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and12* distribute this software and its documentation for any purpose and13* without fee is hereby granted, provided that the above copyright14* notice appear in all copies and that both that copyright notice and15* this permission notice appear in supporting documentation, and that16* the name of M.I.T. not be used in advertising or publicity pertaining17* to distribution of the software without specific, written prior18* permission. Furthermore if you modify this software you must label19* your software as modified software and not distribute it in such a20* fashion that it might be confused with the original M.I.T. software.21* M.I.T. makes no representations about the suitability of22* this software for any purpose. It is provided "as is" without express23* or implied warranty.24*/2526#ifdef _WIN3227#include <winsock2.h>28#endif29#include "k5-ipc_stream.h"3031#if !defined(htonll)32#define htonll(x) k5_htonll(x)33#endif3435#if !defined(ntohll)36#define ntohll(x) k5_ntohll(x)37#endif3839/* Add debugging later */40#define k5_check_error(x) (x)4142struct k5_ipc_stream_s {43char *data;44uint64_t size;45uint64_t max_size;46};4748static const struct k5_ipc_stream_s k5_ipc_stream_initializer = { NULL, 0, 0 };4950#define K5_IPC_STREAM_SIZE_INCREMENT 1285152/* ------------------------------------------------------------------------ */5354static uint32_t krb5int_ipc_stream_reallocate (k5_ipc_stream io_stream,55uint64_t in_new_size)56{57int32_t err = 0;58uint64_t new_max_size = 0;5960if (!io_stream) { err = k5_check_error (EINVAL); }6162if (!err) {63uint64_t old_max_size = io_stream->max_size;64new_max_size = io_stream->max_size;6566if (in_new_size > old_max_size) {67/* Expand the stream */68while (in_new_size > new_max_size) {69new_max_size += K5_IPC_STREAM_SIZE_INCREMENT;70}717273} else if ((in_new_size + K5_IPC_STREAM_SIZE_INCREMENT) < old_max_size) {74/* Shrink the array, but never drop below K5_IPC_STREAM_SIZE_INCREMENT */75while ((in_new_size + K5_IPC_STREAM_SIZE_INCREMENT) < new_max_size &&76(new_max_size > K5_IPC_STREAM_SIZE_INCREMENT)) {77new_max_size -= K5_IPC_STREAM_SIZE_INCREMENT;78}79}80}8182if (!err && new_max_size != io_stream->max_size) {83char *data = io_stream->data;8485if (!data) {86data = malloc (new_max_size * sizeof (*data));87} else {88data = realloc (data, new_max_size * sizeof (*data));89}9091if (data) {92io_stream->data = data;93io_stream->max_size = new_max_size;94} else {95err = k5_check_error (ENOMEM);96}97}9899return k5_check_error (err);100}101102/* ------------------------------------------------------------------------ */103104int32_t krb5int_ipc_stream_new (k5_ipc_stream *out_stream)105{106int32_t err = 0;107k5_ipc_stream stream = NULL;108109if (!out_stream) { err = k5_check_error (EINVAL); }110111if (!err) {112stream = malloc (sizeof (*stream));113if (stream) {114*stream = k5_ipc_stream_initializer;115} else {116err = k5_check_error (ENOMEM);117}118}119120if (!err) {121*out_stream = stream;122stream = NULL;123}124125krb5int_ipc_stream_release (stream);126127return k5_check_error (err);128}129130131/* ------------------------------------------------------------------------ */132133uint32_t krb5int_ipc_stream_release (k5_ipc_stream io_stream)134{135int32_t err = 0;136137if (!err && io_stream) {138free (io_stream->data);139free (io_stream);140}141142return err;143}144145/* ------------------------------------------------------------------------ */146147uint64_t krb5int_ipc_stream_size (k5_ipc_stream in_stream)148{149return in_stream ? in_stream->size : 0;150}151152153/* ------------------------------------------------------------------------ */154155const char *krb5int_ipc_stream_data (k5_ipc_stream in_stream)156{157return in_stream ? in_stream->data : NULL;158}159160#ifdef TARGET_OS_MAC161#pragma mark -162#endif163164/* ------------------------------------------------------------------------ */165166uint32_t krb5int_ipc_stream_read (k5_ipc_stream io_stream,167void *io_data,168uint64_t in_size)169{170int32_t err = 0;171172if (!io_stream) { err = k5_check_error (EINVAL); }173if (!io_data ) { err = k5_check_error (EINVAL); }174175if (!err) {176if (in_size > io_stream->size) {177err = k5_check_error (EINVAL);178}179}180181if (!err) {182memcpy (io_data, io_stream->data, in_size);183memmove (io_stream->data, &io_stream->data[in_size],184io_stream->size - in_size);185186err = krb5int_ipc_stream_reallocate (io_stream, io_stream->size - in_size);187188if (!err) {189io_stream->size -= in_size;190}191}192193return k5_check_error (err);194}195196/* ------------------------------------------------------------------------ */197198uint32_t krb5int_ipc_stream_write (k5_ipc_stream io_stream,199const void *in_data,200uint64_t in_size)201{202int32_t err = 0;203204if (!io_stream) { err = k5_check_error (EINVAL); }205if (!in_data ) { err = k5_check_error (EINVAL); }206207if (!err) {208/* Security check: Do not let the caller overflow the length */209if (in_size > (UINT64_MAX - io_stream->size)) {210err = k5_check_error (EINVAL);211}212}213214if (!err) {215err = krb5int_ipc_stream_reallocate (io_stream, io_stream->size + in_size);216}217218if (!err) {219memcpy (&io_stream->data[io_stream->size], in_data, in_size);220io_stream->size += in_size;221}222223return k5_check_error (err);224}225226#ifdef TARGET_OS_MAC227#pragma mark -228#endif229230/* ------------------------------------------------------------------------ */231232void krb5int_ipc_stream_free_string (char *in_string)233{234free (in_string);235}236237/* ------------------------------------------------------------------------ */238239uint32_t krb5int_ipc_stream_read_string (k5_ipc_stream io_stream,240char **out_string)241{242int32_t err = 0;243uint32_t length = 0;244char *string = NULL;245246if (!io_stream ) { err = k5_check_error (EINVAL); }247if (!out_string) { err = k5_check_error (EINVAL); }248249if (!err) {250err = krb5int_ipc_stream_read_uint32 (io_stream, &length);251}252253if (!err) {254string = malloc (length);255if (!string) { err = k5_check_error (ENOMEM); }256}257258if (!err) {259err = krb5int_ipc_stream_read (io_stream, string, length);260}261262if (!err) {263*out_string = string;264string = NULL;265}266267free (string);268269return k5_check_error (err);270}271272/* ------------------------------------------------------------------------ */273274uint32_t krb5int_ipc_stream_write_string (k5_ipc_stream io_stream,275const char *in_string)276{277int32_t err = 0;278uint32_t length = 0;279280if (!io_stream) { err = k5_check_error (EINVAL); }281if (!in_string) { err = k5_check_error (EINVAL); }282283if (!err) {284length = strlen (in_string) + 1;285286err = krb5int_ipc_stream_write_uint32 (io_stream, length);287}288289if (!err) {290err = krb5int_ipc_stream_write (io_stream, in_string, length);291}292293return k5_check_error (err);294}295296#ifdef TARGET_OS_MAC297#pragma mark -298#endif299300/* ------------------------------------------------------------------------ */301302uint32_t krb5int_ipc_stream_read_int32 (k5_ipc_stream io_stream,303int32_t *out_int32)304{305int32_t err = 0;306int32_t int32 = 0;307308if (!io_stream) { err = k5_check_error (EINVAL); }309if (!out_int32) { err = k5_check_error (EINVAL); }310311if (!err) {312err = krb5int_ipc_stream_read (io_stream, &int32, sizeof (int32));313}314315if (!err) {316*out_int32 = ntohl (int32);317}318319return k5_check_error (err);320}321322/* ------------------------------------------------------------------------ */323324uint32_t krb5int_ipc_stream_write_int32 (k5_ipc_stream io_stream,325int32_t in_int32)326{327int32_t err = 0;328int32_t int32 = htonl (in_int32);329330if (!io_stream) { err = k5_check_error (EINVAL); }331332if (!err) {333err = krb5int_ipc_stream_write (io_stream, &int32, sizeof (int32));334}335336return k5_check_error (err);337}338339#ifdef TARGET_OS_MAC340#pragma mark -341#endif342343/* ------------------------------------------------------------------------ */344345uint32_t krb5int_ipc_stream_read_uint32 (k5_ipc_stream io_stream,346uint32_t *out_uint32)347{348int32_t err = 0;349uint32_t uint32 = 0;350351if (!io_stream) { err = k5_check_error (EINVAL); }352if (!out_uint32) { err = k5_check_error (EINVAL); }353354if (!err) {355err = krb5int_ipc_stream_read (io_stream, &uint32, sizeof (uint32));356}357358if (!err) {359*out_uint32 = ntohl (uint32);360}361362return k5_check_error (err);363}364365/* ------------------------------------------------------------------------ */366367uint32_t krb5int_ipc_stream_write_uint32 (k5_ipc_stream io_stream,368uint32_t in_uint32)369{370int32_t err = 0;371int32_t uint32 = htonl (in_uint32);372373if (!io_stream) { err = k5_check_error (EINVAL); }374375if (!err) {376err = krb5int_ipc_stream_write (io_stream, &uint32, sizeof (uint32));377}378379return k5_check_error (err);380}381382#ifdef TARGET_OS_MAC383#pragma mark -384#endif385386/* ------------------------------------------------------------------------ */387388uint32_t krb5int_ipc_stream_read_int64 (k5_ipc_stream io_stream,389int64_t *out_int64)390{391int32_t err = 0;392uint64_t int64 = 0;393394if (!io_stream) { err = k5_check_error (EINVAL); }395if (!out_int64) { err = k5_check_error (EINVAL); }396397if (!err) {398err = krb5int_ipc_stream_read (io_stream, &int64, sizeof (int64));399}400401if (!err) {402*out_int64 = ntohll (int64);403}404405return k5_check_error (err);406}407408/* ------------------------------------------------------------------------ */409410uint32_t krb5int_ipc_stream_write_int64 (k5_ipc_stream io_stream,411int64_t in_int64)412{413int32_t err = 0;414int64_t int64 = htonll (in_int64);415416if (!io_stream) { err = k5_check_error (EINVAL); }417418if (!err) {419err = krb5int_ipc_stream_write (io_stream, &int64, sizeof (int64));420}421422return k5_check_error (err);423}424425426#ifdef TARGET_OS_MAC427#pragma mark -428#endif429430/* ------------------------------------------------------------------------ */431432uint32_t krb5int_ipc_stream_read_uint64 (k5_ipc_stream io_stream,433uint64_t *out_uint64)434{435int32_t err = 0;436uint64_t uint64 = 0;437438if (!io_stream) { err = k5_check_error (EINVAL); }439if (!out_uint64) { err = k5_check_error (EINVAL); }440441if (!err) {442err = krb5int_ipc_stream_read (io_stream, &uint64, sizeof (uint64));443}444445if (!err) {446*out_uint64 = ntohll (uint64);447}448449return k5_check_error (err);450}451452/* ------------------------------------------------------------------------ */453454uint32_t krb5int_ipc_stream_write_uint64 (k5_ipc_stream io_stream,455uint64_t in_uint64)456{457int32_t err = 0;458int64_t uint64 = htonll (in_uint64);459460if (!io_stream) { err = k5_check_error (EINVAL); }461462if (!err) {463err = krb5int_ipc_stream_write (io_stream, &uint64, sizeof (uint64));464}465466return k5_check_error (err);467}468469470