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