17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*740638c8Sbw  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * Shared routines for client and server for
297c478bd9Sstevel@tonic-gate  * secure read(), write(), getc(), and putc().
307c478bd9Sstevel@tonic-gate  * Only one security context, thus only work on one fd at a time!
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include "ftp_var.h"
347c478bd9Sstevel@tonic-gate #include <gssapi/gssapi.h>
357c478bd9Sstevel@tonic-gate #include <arpa/ftp.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <netinet/in.h>
417c478bd9Sstevel@tonic-gate #include <errno.h>
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate extern struct	sockaddr_in hisaddr;
447c478bd9Sstevel@tonic-gate extern struct	sockaddr_in myaddr;
457c478bd9Sstevel@tonic-gate extern int	dlevel;
467c478bd9Sstevel@tonic-gate extern int	auth_type;
477c478bd9Sstevel@tonic-gate extern uint_t	maxbuf; 	/* maximum output buffer size */
487c478bd9Sstevel@tonic-gate extern uchar_t	*ucbuf;		/* cleartext buffer */
497c478bd9Sstevel@tonic-gate static uint_t	nout;		/* number of chars in ucbuf */
507c478bd9Sstevel@tonic-gate static uint_t	smaxbuf;	/* Internal saved value of maxbuf */
517c478bd9Sstevel@tonic-gate static uint_t	smaxqueue;	/* Maximum allowed to queue before flush */
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate extern gss_ctx_id_t gcontext;
547c478bd9Sstevel@tonic-gate static int secure_putbuf(int, uchar_t *, uint_t);
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static int
looping_write(int fd,const char * buf,int len)577c478bd9Sstevel@tonic-gate looping_write(int fd, const char *buf, int len)
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate 	int cc, len2 = 0;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 	if (len == 0)
627c478bd9Sstevel@tonic-gate 		return (0);
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	do {
657c478bd9Sstevel@tonic-gate 		cc = write(fd, buf, len);
667c478bd9Sstevel@tonic-gate 		if (cc < 0) {
677c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
687c478bd9Sstevel@tonic-gate 				continue;
697c478bd9Sstevel@tonic-gate 			return (cc);
707c478bd9Sstevel@tonic-gate 		} else if (cc == 0) {
717c478bd9Sstevel@tonic-gate 			return (len2);
727c478bd9Sstevel@tonic-gate 		} else {
737c478bd9Sstevel@tonic-gate 			buf += cc;
747c478bd9Sstevel@tonic-gate 			len2 += cc;
757c478bd9Sstevel@tonic-gate 			len -= cc;
767c478bd9Sstevel@tonic-gate 		}
777c478bd9Sstevel@tonic-gate 	} while (len > 0);
787c478bd9Sstevel@tonic-gate 	return (len2);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate static int
looping_read(int fd,char * buf,int len)827c478bd9Sstevel@tonic-gate looping_read(int fd, char *buf, int len)
837c478bd9Sstevel@tonic-gate {
847c478bd9Sstevel@tonic-gate 	int cc, len2 = 0;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	do {
877c478bd9Sstevel@tonic-gate 		cc = read(fd, buf, len);
887c478bd9Sstevel@tonic-gate 		if (cc < 0) {
897c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
907c478bd9Sstevel@tonic-gate 				continue;
917c478bd9Sstevel@tonic-gate 			return (cc);	/* errno is already set */
927c478bd9Sstevel@tonic-gate 		} else if (cc == 0) {
937c478bd9Sstevel@tonic-gate 			return (len2);
947c478bd9Sstevel@tonic-gate 		} else {
957c478bd9Sstevel@tonic-gate 			buf += cc;
967c478bd9Sstevel@tonic-gate 			len2 += cc;
977c478bd9Sstevel@tonic-gate 			len -= cc;
987c478bd9Sstevel@tonic-gate 		}
997c478bd9Sstevel@tonic-gate 	} while (len > 0);
1007c478bd9Sstevel@tonic-gate 	return (len2);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate #define	ERR	-2
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate static void
secure_error(char * fmt,...)1067c478bd9Sstevel@tonic-gate secure_error(char *fmt, ...)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	va_list ap;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
1117c478bd9Sstevel@tonic-gate 	vfprintf(stderr, fmt, ap);
1127c478bd9Sstevel@tonic-gate 	va_end(ap);
1137c478bd9Sstevel@tonic-gate 	putc('\n', stderr);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate  * Given maxbuf as a buffer size, determine how much can we
1187c478bd9Sstevel@tonic-gate  * really transfer given the overhead of different algorithms
1197c478bd9Sstevel@tonic-gate  *
1207c478bd9Sstevel@tonic-gate  * Sets smaxbuf and smaxqueue
1217c478bd9Sstevel@tonic-gate  */
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static int
secure_determine_constants(void)1247c478bd9Sstevel@tonic-gate secure_determine_constants(void)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	smaxbuf = maxbuf;
1277c478bd9Sstevel@tonic-gate 	smaxqueue = maxbuf;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	if (auth_type == AUTHTYPE_GSSAPI) {
1307c478bd9Sstevel@tonic-gate 		OM_uint32 maj_stat, min_stat, mlen;
1317c478bd9Sstevel@tonic-gate 		OM_uint32 msize = maxbuf;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 		maj_stat = gss_wrap_size_limit(&min_stat, gcontext,
1347c478bd9Sstevel@tonic-gate 			(dlevel == PROT_P),
1357c478bd9Sstevel@tonic-gate 			GSS_C_QOP_DEFAULT,
1367c478bd9Sstevel@tonic-gate 			msize, &mlen);
1377c478bd9Sstevel@tonic-gate 		if (maj_stat != GSS_S_COMPLETE) {
1387c478bd9Sstevel@tonic-gate 			user_gss_error(maj_stat, min_stat,
1397c478bd9Sstevel@tonic-gate 				"GSSAPI fudge determination");
1407c478bd9Sstevel@tonic-gate 			/* Return error how? */
1417c478bd9Sstevel@tonic-gate 			return (ERR);
1427c478bd9Sstevel@tonic-gate 		}
1437c478bd9Sstevel@tonic-gate 		smaxqueue = mlen;
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	return (0);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate static uchar_t
secure_putbyte(int fd,uchar_t c)1507c478bd9Sstevel@tonic-gate secure_putbyte(int fd, uchar_t c)
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate 	int ret;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	if ((smaxbuf == 0) || (smaxqueue == 0) || (smaxbuf != maxbuf)) {
1557c478bd9Sstevel@tonic-gate 	    ret = secure_determine_constants();
1567c478bd9Sstevel@tonic-gate 	    if (ret)
1577c478bd9Sstevel@tonic-gate 		return (ret);
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 	ucbuf[nout++] = c;
1607c478bd9Sstevel@tonic-gate 	if (nout == smaxqueue) {
1617c478bd9Sstevel@tonic-gate 		nout = 0;
1627c478bd9Sstevel@tonic-gate 		ret = secure_putbuf(fd, ucbuf, smaxqueue);
1637c478bd9Sstevel@tonic-gate 		return (ret ? ret :c);
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	return (c);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate  * returns:
1707c478bd9Sstevel@tonic-gate  *	 0  on success
1717c478bd9Sstevel@tonic-gate  *	-1  on error (errno set)
1727c478bd9Sstevel@tonic-gate  *	-2  on security error
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate int
secure_flush(int fd)1757c478bd9Sstevel@tonic-gate secure_flush(int fd)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	int ret;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	if (dlevel == PROT_C)
1807c478bd9Sstevel@tonic-gate 		return (0);
1817c478bd9Sstevel@tonic-gate 	if (nout)
1827c478bd9Sstevel@tonic-gate 		if (ret = secure_putbuf(fd, ucbuf, nout))
1837c478bd9Sstevel@tonic-gate 			return (ret);
1847c478bd9Sstevel@tonic-gate 	return (secure_putbuf(fd, (uchar_t *)"", nout = 0));
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate /*
1887c478bd9Sstevel@tonic-gate  * returns:
1897c478bd9Sstevel@tonic-gate  *	>= 0	on success
1907c478bd9Sstevel@tonic-gate  *	-1	on error
1917c478bd9Sstevel@tonic-gate  *	-2	on security error
1927c478bd9Sstevel@tonic-gate  */
1937c478bd9Sstevel@tonic-gate int
secure_putc(int c,FILE * stream)1947c478bd9Sstevel@tonic-gate secure_putc(int c, FILE *stream)
1957c478bd9Sstevel@tonic-gate {
1967c478bd9Sstevel@tonic-gate 	if (dlevel == PROT_C)
1977c478bd9Sstevel@tonic-gate 		return (putc(c, stream));
1987c478bd9Sstevel@tonic-gate 	return (secure_putbyte(fileno(stream), (uchar_t)c));
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate  * returns:
2037c478bd9Sstevel@tonic-gate  *	nbyte on success
2047c478bd9Sstevel@tonic-gate  *	-1  on error (errno set)
2057c478bd9Sstevel@tonic-gate  *	-2  on security error
2067c478bd9Sstevel@tonic-gate  */
2077c478bd9Sstevel@tonic-gate ssize_t
secure_write(int fd,const void * inbuf,size_t nbyte)2087c478bd9Sstevel@tonic-gate secure_write(int fd, const void *inbuf, size_t nbyte)
2097c478bd9Sstevel@tonic-gate {
2107c478bd9Sstevel@tonic-gate 	uint_t i;
2117c478bd9Sstevel@tonic-gate 	int c;
2127c478bd9Sstevel@tonic-gate 	uchar_t *buf = (uchar_t *)inbuf;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	if (dlevel == PROT_C)
2157c478bd9Sstevel@tonic-gate 		return (write(fd, buf, nbyte));
2167c478bd9Sstevel@tonic-gate 	for (i = 0; nbyte > 0; nbyte--)
2177c478bd9Sstevel@tonic-gate 		if ((c = secure_putbyte(fd, buf[i++])) < 0)
2187c478bd9Sstevel@tonic-gate 			return (c);
2197c478bd9Sstevel@tonic-gate 	return (i);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate  * returns:
2247c478bd9Sstevel@tonic-gate  *	 0  on success
2257c478bd9Sstevel@tonic-gate  *	-1  on error, errno set
2267c478bd9Sstevel@tonic-gate  *	-2  on security error
2277c478bd9Sstevel@tonic-gate  */
secure_putbuf(int fd,uchar_t * buf,uint_t nbyte)2287c478bd9Sstevel@tonic-gate static int secure_putbuf(int fd, uchar_t *buf, uint_t nbyte)
2297c478bd9Sstevel@tonic-gate {
2307c478bd9Sstevel@tonic-gate 	static char *outbuf;		/* output ciphertext */
2317c478bd9Sstevel@tonic-gate 	static uint_t bufsize;	/* size of outbuf */
2327c478bd9Sstevel@tonic-gate 	int length;
2337c478bd9Sstevel@tonic-gate 	uint_t net_len;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	/* Other auth types go here ... */
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	if (auth_type == AUTHTYPE_GSSAPI) {
2387c478bd9Sstevel@tonic-gate 		gss_buffer_desc in_buf, out_buf;
2397c478bd9Sstevel@tonic-gate 		OM_uint32 maj_stat, min_stat;
2407c478bd9Sstevel@tonic-gate 		int conf_state;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		in_buf.value = buf;
2437c478bd9Sstevel@tonic-gate 		in_buf.length = nbyte;
2447c478bd9Sstevel@tonic-gate 		maj_stat = gss_seal(&min_stat, gcontext,
2457c478bd9Sstevel@tonic-gate 				(dlevel == PROT_P), /* confidential */
2467c478bd9Sstevel@tonic-gate 				GSS_C_QOP_DEFAULT,
2477c478bd9Sstevel@tonic-gate 				&in_buf, &conf_state,
2487c478bd9Sstevel@tonic-gate 				&out_buf);
2497c478bd9Sstevel@tonic-gate 		if (maj_stat != GSS_S_COMPLETE) {
2507c478bd9Sstevel@tonic-gate 			/*
2517c478bd9Sstevel@tonic-gate 			 * generally need to deal
2527c478bd9Sstevel@tonic-gate 			 * ie. should loop, but for now just fail
2537c478bd9Sstevel@tonic-gate 			 */
2547c478bd9Sstevel@tonic-gate 			user_gss_error(maj_stat, min_stat, dlevel == PROT_P?
2557c478bd9Sstevel@tonic-gate 				"GSSAPI seal failed" : "GSSAPI sign failed");
2567c478bd9Sstevel@tonic-gate 			return (ERR);
2577c478bd9Sstevel@tonic-gate 		}
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 		if (bufsize < out_buf.length) {
2607c478bd9Sstevel@tonic-gate 			outbuf = outbuf ?
2617c478bd9Sstevel@tonic-gate 				realloc(outbuf, (size_t)out_buf.length) :
2627c478bd9Sstevel@tonic-gate 				malloc((size_t)out_buf.length);
2637c478bd9Sstevel@tonic-gate 			if (outbuf)
2647c478bd9Sstevel@tonic-gate 				bufsize = out_buf.length;
2657c478bd9Sstevel@tonic-gate 			else {
2667c478bd9Sstevel@tonic-gate 				bufsize = 0;
2677c478bd9Sstevel@tonic-gate 				secure_error("%s (in malloc of PROT buffer)",
2687c478bd9Sstevel@tonic-gate 					strerror(errno));
2697c478bd9Sstevel@tonic-gate 				return (ERR);
2707c478bd9Sstevel@tonic-gate 			}
2717c478bd9Sstevel@tonic-gate 		}
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 		memcpy(outbuf, out_buf.value, length = out_buf.length);
2747c478bd9Sstevel@tonic-gate 		gss_release_buffer(&min_stat, &out_buf);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 	net_len = htonl((uint32_t)length);
2777c478bd9Sstevel@tonic-gate 	if (looping_write(fd, (char *)&net_len, 4) == -1)
2787c478bd9Sstevel@tonic-gate 		return (-1);
2797c478bd9Sstevel@tonic-gate 	if (looping_write(fd, outbuf, length) != length)
2807c478bd9Sstevel@tonic-gate 		return (-1);
2817c478bd9Sstevel@tonic-gate 	return (0);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate 
284*740638c8Sbw static int
secure_getbyte(int fd)2857c478bd9Sstevel@tonic-gate secure_getbyte(int fd)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate 	/* number of chars in ucbuf, pointer into ucbuf */
2887c478bd9Sstevel@tonic-gate 	static uint_t nin, bufp;
2897c478bd9Sstevel@tonic-gate 	int kerror;
2907c478bd9Sstevel@tonic-gate 	uint_t length;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	if (nin == 0) {
2937c478bd9Sstevel@tonic-gate 		if ((kerror =
2947c478bd9Sstevel@tonic-gate 			looping_read(fd, (char *)&length, sizeof (length)))
2957c478bd9Sstevel@tonic-gate 			!= sizeof (length)) {
2967c478bd9Sstevel@tonic-gate 			secure_error("Couldn't read PROT buffer length: %d/%s",
2977c478bd9Sstevel@tonic-gate 				kerror, (kerror == -1) ? strerror(errno) :
2987c478bd9Sstevel@tonic-gate 				"premature EOF");
2997c478bd9Sstevel@tonic-gate 			return (ERR);
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 		if ((length = ntohl((uint32_t)length)) > maxbuf) {
3027c478bd9Sstevel@tonic-gate 			secure_error("Length (%d) of PROT buffer > PBSZ=%u",
3037c478bd9Sstevel@tonic-gate 				length, maxbuf);
3047c478bd9Sstevel@tonic-gate 			return (ERR);
3057c478bd9Sstevel@tonic-gate 		}
3067c478bd9Sstevel@tonic-gate 		if ((kerror = looping_read(fd, (char *)ucbuf, length))
3077c478bd9Sstevel@tonic-gate 			!= length) {
3087c478bd9Sstevel@tonic-gate 			secure_error("Couldn't read %u byte PROT buffer: %s",
3097c478bd9Sstevel@tonic-gate 					length, kerror == -1 ?
3107c478bd9Sstevel@tonic-gate 					strerror(errno) : "premature EOF");
3117c478bd9Sstevel@tonic-gate 			return (ERR);
3127c478bd9Sstevel@tonic-gate 		}
3137c478bd9Sstevel@tonic-gate 		/* Other auth types go here ... */
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 		if (auth_type == AUTHTYPE_GSSAPI) {
3167c478bd9Sstevel@tonic-gate 			gss_buffer_desc xmit_buf, msg_buf;
3177c478bd9Sstevel@tonic-gate 			OM_uint32 maj_stat, min_stat;
3187c478bd9Sstevel@tonic-gate 			int conf_state;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 			xmit_buf.value = ucbuf;
3217c478bd9Sstevel@tonic-gate 			xmit_buf.length = length;
3227c478bd9Sstevel@tonic-gate 			conf_state = (dlevel == PROT_P);
3237c478bd9Sstevel@tonic-gate 			/* decrypt/verify the message */
3247c478bd9Sstevel@tonic-gate 			maj_stat = gss_unseal(&min_stat, gcontext, &xmit_buf,
3257c478bd9Sstevel@tonic-gate 				&msg_buf, &conf_state, NULL);
3267c478bd9Sstevel@tonic-gate 			if (maj_stat != GSS_S_COMPLETE) {
3277c478bd9Sstevel@tonic-gate 				user_gss_error(maj_stat, min_stat,
3287c478bd9Sstevel@tonic-gate 				    (dlevel == PROT_P)?
3297c478bd9Sstevel@tonic-gate 				    "failed unsealing ENC message":
3307c478bd9Sstevel@tonic-gate 				    "failed unsealing MIC message");
3317c478bd9Sstevel@tonic-gate 				return (ERR);
3327c478bd9Sstevel@tonic-gate 			}
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 			memcpy(ucbuf, msg_buf.value,
3357c478bd9Sstevel@tonic-gate 				nin = bufp = msg_buf.length);
3367c478bd9Sstevel@tonic-gate 			gss_release_buffer(&min_stat, &msg_buf);
3377c478bd9Sstevel@tonic-gate 		}
3387c478bd9Sstevel@tonic-gate 		/* Other auth types go here ... */
3397c478bd9Sstevel@tonic-gate 	}
3407c478bd9Sstevel@tonic-gate 	return ((nin == 0) ? EOF : ucbuf[bufp - nin--]);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate /*
3447c478bd9Sstevel@tonic-gate  * returns:
3457c478bd9Sstevel@tonic-gate  *	 0	on success
3467c478bd9Sstevel@tonic-gate  *	-1	on EOF
3477c478bd9Sstevel@tonic-gate  *	-2	on security error
3487c478bd9Sstevel@tonic-gate  */
3497c478bd9Sstevel@tonic-gate int
secure_getc(FILE * stream)3507c478bd9Sstevel@tonic-gate secure_getc(FILE *stream)
3517c478bd9Sstevel@tonic-gate {
3527c478bd9Sstevel@tonic-gate 	if (dlevel == PROT_C)
3537c478bd9Sstevel@tonic-gate 		return (getc(stream));
3547c478bd9Sstevel@tonic-gate 	return (secure_getbyte(fileno(stream)));
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate /*
3587c478bd9Sstevel@tonic-gate  * returns:
3597c478bd9Sstevel@tonic-gate  *	> 0	on success (n == # of bytes read)
3607c478bd9Sstevel@tonic-gate  *	 0	on EOF
3617c478bd9Sstevel@tonic-gate  *	-1	on error, errno set, only for PROT_C
3627c478bd9Sstevel@tonic-gate  *	-2	on security error (ERR = -2)
3637c478bd9Sstevel@tonic-gate  */
3647c478bd9Sstevel@tonic-gate ssize_t
secure_read(int fd,void * inbuf,size_t nbyte)3657c478bd9Sstevel@tonic-gate secure_read(int fd, void *inbuf, size_t nbyte)
3667c478bd9Sstevel@tonic-gate {
3677c478bd9Sstevel@tonic-gate 	int c, i;
3687c478bd9Sstevel@tonic-gate 	char *buf = (char *)inbuf;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	if (dlevel == PROT_C)
3717c478bd9Sstevel@tonic-gate 		return (read(fd, buf, nbyte));
3727c478bd9Sstevel@tonic-gate 	if (goteof)
3737c478bd9Sstevel@tonic-gate 		return (goteof = 0);
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	for (i = 0; nbyte > 0; nbyte--)
3767c478bd9Sstevel@tonic-gate 		switch (c = secure_getbyte(fd)) {
3777c478bd9Sstevel@tonic-gate 			case ERR:
3787c478bd9Sstevel@tonic-gate 				return (c);
3797c478bd9Sstevel@tonic-gate 			case EOF:
3807c478bd9Sstevel@tonic-gate 				goteof = i ? 1 : 0;
3817c478bd9Sstevel@tonic-gate 				return (i);
3827c478bd9Sstevel@tonic-gate 			default:
3837c478bd9Sstevel@tonic-gate 				buf[i++] = c;
3847c478bd9Sstevel@tonic-gate 		}
3857c478bd9Sstevel@tonic-gate 	return (i);
3867c478bd9Sstevel@tonic-gate }
387