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