Path: blob/main/crypto/krb5/src/lib/rpc/authgss_prot.c
39536 views
/* lib/rpc/authgss_prot.c */1/*2Copyright (c) 2000 The Regents of the University of Michigan.3All rights reserved.45Copyright (c) 2000 Dug Song <[email protected]>.6All rights reserved, all wrongs reversed.78Redistribution and use in source and binary forms, with or without9modification, are permitted provided that the following conditions10are met:11121. Redistributions of source code must retain the above copyright13notice, this list of conditions and the following disclaimer.142. Redistributions in binary form must reproduce the above copyright15notice, this list of conditions and the following disclaimer in the16documentation and/or other materials provided with the distribution.173. Neither the name of the University nor the names of its18contributors may be used to endorse or promote products derived19from this software without specific prior written permission.2021THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF23MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE24DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF29LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING30NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS31SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.3233Id: authgss_prot.c,v 1.18 2000/09/01 04:14:03 dugsong Exp34*/3536#include <stdio.h>37#include <stdlib.h>38#include <stdarg.h>39#include <string.h>40#include <gssrpc/rpc.h>41#ifdef HAVE_HEIMDAL42#include <gssapi.h>43#else44#include <gssapi/gssapi.h>45#endif4647bool_t48xdr_rpc_gss_buf(XDR *xdrs, gss_buffer_t buf, u_int maxsize)49{50bool_t xdr_stat;51u_int tmplen;52char *cp;5354if (xdrs->x_op != XDR_DECODE) {55if (buf->length > UINT_MAX)56return (FALSE);57else58tmplen = buf->length;59}60cp = buf->value;61xdr_stat = xdr_bytes(xdrs, &cp, &tmplen, maxsize);62buf->value = cp;6364if (xdr_stat && xdrs->x_op == XDR_DECODE)65buf->length = tmplen;6667return (xdr_stat);68}6970bool_t71xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)72{73bool_t xdr_stat;7475xdr_stat = (xdr_u_int(xdrs, &p->gc_v) &&76xdr_enum(xdrs, (enum_t *)&p->gc_proc) &&77xdr_u_int32(xdrs, &p->gc_seq) &&78xdr_enum(xdrs, (enum_t *)&p->gc_svc) &&79xdr_rpc_gss_buf(xdrs, &p->gc_ctx, MAX_AUTH_BYTES));8081log_debug("xdr_rpc_gss_cred: %s %s "82"(v %d, proc %d, seq %d, svc %d, ctx %p:%d)",83(xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",84(xdr_stat == TRUE) ? "success" : "failure",85p->gc_v, p->gc_proc, p->gc_seq, p->gc_svc,86p->gc_ctx.value, p->gc_ctx.length);8788return (xdr_stat);89}9091bool_t92xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p)93{94bool_t xdr_stat;9596xdr_stat = xdr_rpc_gss_buf(xdrs, p, MAX_NETOBJ_SZ);9798log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)",99(xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",100(xdr_stat == TRUE) ? "success" : "failure",101p->value, p->length);102103return (xdr_stat);104}105106bool_t107xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)108{109bool_t xdr_stat;110111xdr_stat = (xdr_rpc_gss_buf(xdrs, &p->gr_ctx, MAX_NETOBJ_SZ) &&112xdr_u_int32(xdrs, &p->gr_major) &&113xdr_u_int32(xdrs, &p->gr_minor) &&114xdr_u_int32(xdrs, &p->gr_win) &&115xdr_rpc_gss_buf(xdrs, &p->gr_token, MAX_NETOBJ_SZ));116117log_debug("xdr_rpc_gss_init_res %s %s "118"(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)",119(xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",120(xdr_stat == TRUE) ? "success" : "failure",121p->gr_ctx.value, p->gr_ctx.length,122p->gr_major, p->gr_minor, p->gr_win,123p->gr_token.value, p->gr_token.length);124125return (xdr_stat);126}127128bool_t129xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,130gss_ctx_id_t ctx, gss_qop_t qop,131rpc_gss_svc_t svc, uint32_t seq)132{133XDR tmpxdrs;134gss_buffer_desc databuf, wrapbuf;135OM_uint32 maj_stat, min_stat;136int conf_state;137bool_t xdr_stat;138139xdralloc_create(&tmpxdrs, XDR_ENCODE);140141xdr_stat = FALSE;142143/* Marshal rpc_gss_data_t (sequence number + arguments). */144if (!xdr_u_int32(&tmpxdrs, &seq) || !(*xdr_func)(&tmpxdrs, xdr_ptr))145goto errout;146147/* Set databuf to marshalled rpc_gss_data_t. */148databuf.length = xdr_getpos(&tmpxdrs);149databuf.value = xdralloc_getdata(&tmpxdrs);150151if (svc == RPCSEC_GSS_SVC_INTEGRITY) {152if (!xdr_rpc_gss_buf(xdrs, &databuf, (unsigned int)-1))153goto errout;154155/* Checksum rpc_gss_data_t. */156maj_stat = gss_get_mic(&min_stat, ctx, qop,157&databuf, &wrapbuf);158if (maj_stat != GSS_S_COMPLETE) {159log_debug("gss_get_mic failed");160goto errout;161}162/* Marshal checksum. */163xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned int)-1);164gss_release_buffer(&min_stat, &wrapbuf);165}166else if (svc == RPCSEC_GSS_SVC_PRIVACY) {167/* Encrypt rpc_gss_data_t. */168maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,169&conf_state, &wrapbuf);170if (maj_stat != GSS_S_COMPLETE) {171log_status("gss_wrap", maj_stat, min_stat);172goto errout;173}174/* Marshal databody_priv. */175xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned int)-1);176gss_release_buffer(&min_stat, &wrapbuf);177}178errout:179xdr_destroy(&tmpxdrs);180return (xdr_stat);181}182183bool_t184xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,185gss_ctx_id_t ctx, gss_qop_t qop,186rpc_gss_svc_t svc, uint32_t seq)187{188XDR tmpxdrs;189gss_buffer_desc databuf, wrapbuf;190OM_uint32 maj_stat, min_stat;191uint32_t seq_num;192int conf_state;193gss_qop_t qop_state;194bool_t xdr_stat;195196if (xdr_func == xdr_void || xdr_ptr == NULL)197return (TRUE);198199memset(&databuf, 0, sizeof(databuf));200memset(&wrapbuf, 0, sizeof(wrapbuf));201202if (svc == RPCSEC_GSS_SVC_INTEGRITY) {203/* Decode databody_integ. */204if (!xdr_rpc_gss_buf(xdrs, &databuf, (unsigned int)-1)) {205log_debug("xdr decode databody_integ failed");206return (FALSE);207}208/* Decode checksum. */209if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned int)-1)) {210gss_release_buffer(&min_stat, &databuf);211log_debug("xdr decode checksum failed");212return (FALSE);213}214/* Verify checksum and QOP. */215maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,216&wrapbuf, &qop_state);217free(wrapbuf.value);218219if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {220gss_release_buffer(&min_stat, &databuf);221log_status("gss_verify_mic", maj_stat, min_stat);222return (FALSE);223}224}225else if (svc == RPCSEC_GSS_SVC_PRIVACY) {226/* Decode databody_priv. */227if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (unsigned int)-1)) {228log_debug("xdr decode databody_priv failed");229return (FALSE);230}231/* Decrypt databody. */232maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,233&conf_state, &qop_state);234235free(wrapbuf.value);236237/* Verify encryption and QOP. */238if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||239conf_state != TRUE) {240gss_release_buffer(&min_stat, &databuf);241log_status("gss_unwrap", maj_stat, min_stat);242return (FALSE);243}244}245/* Decode rpc_gss_data_t (sequence number + arguments). */246xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);247xdr_stat = (xdr_u_int32(&tmpxdrs, &seq_num) &&248(*xdr_func)(&tmpxdrs, xdr_ptr));249XDR_DESTROY(&tmpxdrs);250gss_release_buffer(&min_stat, &databuf);251252/* Verify sequence number. */253if (xdr_stat == TRUE && seq_num != seq) {254log_debug("wrong sequence number in databody");255return (FALSE);256}257return (xdr_stat);258}259260bool_t261xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,262gss_ctx_id_t ctx, gss_qop_t qop,263rpc_gss_svc_t svc, uint32_t seq)264{265switch (xdrs->x_op) {266267case XDR_ENCODE:268return (xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr,269ctx, qop, svc, seq));270case XDR_DECODE:271return (xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr,272ctx, qop,svc, seq));273case XDR_FREE:274return (TRUE);275}276return (FALSE);277}278279#ifdef DEBUG280#include <ctype.h>281282void283log_debug(const char *fmt, ...)284{285va_list ap;286287va_start(ap, fmt);288fprintf(stderr, "rpcsec_gss: ");289vfprintf(stderr, fmt, ap);290fprintf(stderr, "\n");291va_end(ap);292}293294void295log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)296{297OM_uint32 min, msg_ctx;298gss_buffer_desc msgg, msgm;299300msg_ctx = 0;301gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,302&msg_ctx, &msgg);303msg_ctx = 0;304gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID,305&msg_ctx, &msgm);306307log_debug("%s: %.*s - %.*s\n", m,308msgg.length, (char *)msgg.value,309msgm.length, (char *)msgm.value);310311gss_release_buffer(&min, &msgg);312gss_release_buffer(&min, &msgm);313}314315void316log_hexdump(const u_char *buf, int len, int offset)317{318u_int i, j, jm;319int c;320321fprintf(stderr, "\n");322for (i = 0; i < len; i += 0x10) {323fprintf(stderr, " %04x: ", (u_int)(i + offset));324jm = len - i;325jm = jm > 16 ? 16 : jm;326327for (j = 0; j < jm; j++) {328if ((j % 2) == 1)329fprintf(stderr, "%02x ", (u_int) buf[i+j]);330else331fprintf(stderr, "%02x", (u_int) buf[i+j]);332}333for (; j < 16; j++) {334if ((j % 2) == 1) printf(" ");335else fprintf(stderr, " ");336}337fprintf(stderr, " ");338339for (j = 0; j < jm; j++) {340c = buf[i+j];341c = isprint(c) ? c : '.';342fprintf(stderr, "%c", c);343}344fprintf(stderr, "\n");345}346}347348#else349350void351log_debug(const char *fmt, ...)352{353}354355void356log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)357{358}359360void361log_hexdump(const u_char *buf, int len, int offset)362{363}364365#endif366367368