1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Shared routines for client and server for 29 * secure read(), write(), getc(), and putc(). 30 * Only one security context, thus only work on one fd at a time! 31 */ 32 33 #include "ftp_var.h" 34 #include <gssapi/gssapi.h> 35 #include <arpa/ftp.h> 36 #include <stdio.h> 37 #include <string.h> 38 #include <stdlib.h> 39 #include <sys/types.h> 40 #include <netinet/in.h> 41 #include <errno.h> 42 43 extern struct sockaddr_in hisaddr; 44 extern struct sockaddr_in myaddr; 45 extern int dlevel; 46 extern int auth_type; 47 extern uint_t maxbuf; /* maximum output buffer size */ 48 extern uchar_t *ucbuf; /* cleartext buffer */ 49 static uint_t nout; /* number of chars in ucbuf */ 50 static uint_t smaxbuf; /* Internal saved value of maxbuf */ 51 static uint_t smaxqueue; /* Maximum allowed to queue before flush */ 52 53 extern gss_ctx_id_t gcontext; 54 static int secure_putbuf(int, uchar_t *, uint_t); 55 56 static int 57 looping_write(int fd, const char *buf, int len) 58 { 59 int cc, len2 = 0; 60 61 if (len == 0) 62 return (0); 63 64 do { 65 cc = write(fd, buf, len); 66 if (cc < 0) { 67 if (errno == EINTR) 68 continue; 69 return (cc); 70 } else if (cc == 0) { 71 return (len2); 72 } else { 73 buf += cc; 74 len2 += cc; 75 len -= cc; 76 } 77 } while (len > 0); 78 return (len2); 79 } 80 81 static int 82 looping_read(int fd, char *buf, int len) 83 { 84 int cc, len2 = 0; 85 86 do { 87 cc = read(fd, buf, len); 88 if (cc < 0) { 89 if (errno == EINTR) 90 continue; 91 return (cc); /* errno is already set */ 92 } else if (cc == 0) { 93 return (len2); 94 } else { 95 buf += cc; 96 len2 += cc; 97 len -= cc; 98 } 99 } while (len > 0); 100 return (len2); 101 } 102 103 #define ERR -2 104 105 static void 106 secure_error(char *fmt, ...) 107 { 108 va_list ap; 109 110 va_start(ap, fmt); 111 vfprintf(stderr, fmt, ap); 112 va_end(ap); 113 putc('\n', stderr); 114 } 115 116 /* 117 * Given maxbuf as a buffer size, determine how much can we 118 * really transfer given the overhead of different algorithms 119 * 120 * Sets smaxbuf and smaxqueue 121 */ 122 123 static int 124 secure_determine_constants(void) 125 { 126 smaxbuf = maxbuf; 127 smaxqueue = maxbuf; 128 129 if (auth_type == AUTHTYPE_GSSAPI) { 130 OM_uint32 maj_stat, min_stat, mlen; 131 OM_uint32 msize = maxbuf; 132 133 maj_stat = gss_wrap_size_limit(&min_stat, gcontext, 134 (dlevel == PROT_P), 135 GSS_C_QOP_DEFAULT, 136 msize, &mlen); 137 if (maj_stat != GSS_S_COMPLETE) { 138 user_gss_error(maj_stat, min_stat, 139 "GSSAPI fudge determination"); 140 /* Return error how? */ 141 return (ERR); 142 } 143 smaxqueue = mlen; 144 } 145 146 return (0); 147 } 148 149 static uchar_t 150 secure_putbyte(int fd, uchar_t c) 151 { 152 int ret; 153 154 if ((smaxbuf == 0) || (smaxqueue == 0) || (smaxbuf != maxbuf)) { 155 ret = secure_determine_constants(); 156 if (ret) 157 return (ret); 158 } 159 ucbuf[nout++] = c; 160 if (nout == smaxqueue) { 161 nout = 0; 162 ret = secure_putbuf(fd, ucbuf, smaxqueue); 163 return (ret ? ret :c); 164 } 165 return (c); 166 } 167 168 /* 169 * returns: 170 * 0 on success 171 * -1 on error (errno set) 172 * -2 on security error 173 */ 174 int 175 secure_flush(int fd) 176 { 177 int ret; 178 179 if (dlevel == PROT_C) 180 return (0); 181 if (nout) 182 if (ret = secure_putbuf(fd, ucbuf, nout)) 183 return (ret); 184 return (secure_putbuf(fd, (uchar_t *)"", nout = 0)); 185 } 186 187 /* 188 * returns: 189 * >= 0 on success 190 * -1 on error 191 * -2 on security error 192 */ 193 int 194 secure_putc(int c, FILE *stream) 195 { 196 if (dlevel == PROT_C) 197 return (putc(c, stream)); 198 return (secure_putbyte(fileno(stream), (uchar_t)c)); 199 } 200 201 /* 202 * returns: 203 * nbyte on success 204 * -1 on error (errno set) 205 * -2 on security error 206 */ 207 ssize_t 208 secure_write(int fd, const void *inbuf, size_t nbyte) 209 { 210 uint_t i; 211 int c; 212 uchar_t *buf = (uchar_t *)inbuf; 213 214 if (dlevel == PROT_C) 215 return (write(fd, buf, nbyte)); 216 for (i = 0; nbyte > 0; nbyte--) 217 if ((c = secure_putbyte(fd, buf[i++])) < 0) 218 return (c); 219 return (i); 220 } 221 222 /* 223 * returns: 224 * 0 on success 225 * -1 on error, errno set 226 * -2 on security error 227 */ 228 static int secure_putbuf(int fd, uchar_t *buf, uint_t nbyte) 229 { 230 static char *outbuf; /* output ciphertext */ 231 static uint_t bufsize; /* size of outbuf */ 232 int length; 233 uint_t net_len; 234 235 /* Other auth types go here ... */ 236 237 if (auth_type == AUTHTYPE_GSSAPI) { 238 gss_buffer_desc in_buf, out_buf; 239 OM_uint32 maj_stat, min_stat; 240 int conf_state; 241 242 in_buf.value = buf; 243 in_buf.length = nbyte; 244 maj_stat = gss_seal(&min_stat, gcontext, 245 (dlevel == PROT_P), /* confidential */ 246 GSS_C_QOP_DEFAULT, 247 &in_buf, &conf_state, 248 &out_buf); 249 if (maj_stat != GSS_S_COMPLETE) { 250 /* 251 * generally need to deal 252 * ie. should loop, but for now just fail 253 */ 254 user_gss_error(maj_stat, min_stat, dlevel == PROT_P? 255 "GSSAPI seal failed" : "GSSAPI sign failed"); 256 return (ERR); 257 } 258 259 if (bufsize < out_buf.length) { 260 outbuf = outbuf ? 261 realloc(outbuf, (size_t)out_buf.length) : 262 malloc((size_t)out_buf.length); 263 if (outbuf) 264 bufsize = out_buf.length; 265 else { 266 bufsize = 0; 267 secure_error("%s (in malloc of PROT buffer)", 268 strerror(errno)); 269 return (ERR); 270 } 271 } 272 273 memcpy(outbuf, out_buf.value, length = out_buf.length); 274 gss_release_buffer(&min_stat, &out_buf); 275 } 276 net_len = htonl((uint32_t)length); 277 if (looping_write(fd, (char *)&net_len, 4) == -1) 278 return (-1); 279 if (looping_write(fd, outbuf, length) != length) 280 return (-1); 281 return (0); 282 } 283 284 static int 285 secure_getbyte(int fd) 286 { 287 /* number of chars in ucbuf, pointer into ucbuf */ 288 static uint_t nin, bufp; 289 int kerror; 290 uint_t length; 291 292 if (nin == 0) { 293 if ((kerror = 294 looping_read(fd, (char *)&length, sizeof (length))) 295 != sizeof (length)) { 296 secure_error("Couldn't read PROT buffer length: %d/%s", 297 kerror, (kerror == -1) ? strerror(errno) : 298 "premature EOF"); 299 return (ERR); 300 } 301 if ((length = ntohl((uint32_t)length)) > maxbuf) { 302 secure_error("Length (%d) of PROT buffer > PBSZ=%u", 303 length, maxbuf); 304 return (ERR); 305 } 306 if ((kerror = looping_read(fd, (char *)ucbuf, length)) 307 != length) { 308 secure_error("Couldn't read %u byte PROT buffer: %s", 309 length, kerror == -1 ? 310 strerror(errno) : "premature EOF"); 311 return (ERR); 312 } 313 /* Other auth types go here ... */ 314 315 if (auth_type == AUTHTYPE_GSSAPI) { 316 gss_buffer_desc xmit_buf, msg_buf; 317 OM_uint32 maj_stat, min_stat; 318 int conf_state; 319 320 xmit_buf.value = ucbuf; 321 xmit_buf.length = length; 322 conf_state = (dlevel == PROT_P); 323 /* decrypt/verify the message */ 324 maj_stat = gss_unseal(&min_stat, gcontext, &xmit_buf, 325 &msg_buf, &conf_state, NULL); 326 if (maj_stat != GSS_S_COMPLETE) { 327 user_gss_error(maj_stat, min_stat, 328 (dlevel == PROT_P)? 329 "failed unsealing ENC message": 330 "failed unsealing MIC message"); 331 return (ERR); 332 } 333 334 memcpy(ucbuf, msg_buf.value, 335 nin = bufp = msg_buf.length); 336 gss_release_buffer(&min_stat, &msg_buf); 337 } 338 /* Other auth types go here ... */ 339 } 340 return ((nin == 0) ? EOF : ucbuf[bufp - nin--]); 341 } 342 343 /* 344 * returns: 345 * 0 on success 346 * -1 on EOF 347 * -2 on security error 348 */ 349 int 350 secure_getc(FILE *stream) 351 { 352 if (dlevel == PROT_C) 353 return (getc(stream)); 354 return (secure_getbyte(fileno(stream))); 355 } 356 357 /* 358 * returns: 359 * > 0 on success (n == # of bytes read) 360 * 0 on EOF 361 * -1 on error, errno set, only for PROT_C 362 * -2 on security error (ERR = -2) 363 */ 364 ssize_t 365 secure_read(int fd, void *inbuf, size_t nbyte) 366 { 367 int c, i; 368 char *buf = (char *)inbuf; 369 370 if (dlevel == PROT_C) 371 return (read(fd, buf, nbyte)); 372 if (goteof) 373 return (goteof = 0); 374 375 for (i = 0; nbyte > 0; nbyte--) 376 switch (c = secure_getbyte(fd)) { 377 case ERR: 378 return (c); 379 case EOF: 380 goteof = i ? 1 : 0; 381 return (i); 382 default: 383 buf[i++] = c; 384 } 385 return (i); 386 } 387