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
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.
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Shared routines for client and server for
31 * secure read(), write(), getc(), and putc().
32 * Only one security context, thus only work on one fd at a time!
36 #include <gssapi/gssapi.h>
41 #include <sys/types.h>
42 #include <netinet/in.h>
45 extern struct sockaddr_in hisaddr
;
46 extern struct sockaddr_in myaddr
;
49 extern uint_t maxbuf
; /* maximum output buffer size */
50 extern uchar_t
*ucbuf
; /* cleartext buffer */
51 static uint_t nout
; /* number of chars in ucbuf */
52 static uint_t smaxbuf
; /* Internal saved value of maxbuf */
53 static uint_t smaxqueue
; /* Maximum allowed to queue before flush */
55 extern gss_ctx_id_t gcontext
;
56 static int secure_putbuf(int, uchar_t
*, uint_t
);
59 looping_write(int fd
, const char *buf
, int len
)
67 cc
= write(fd
, buf
, len
);
84 looping_read(int fd
, char *buf
, int len
)
89 cc
= read(fd
, buf
, len
);
93 return (cc
); /* errno is already set */
108 secure_error(char *fmt
, ...)
113 vfprintf(stderr
, fmt
, ap
);
119 * Given maxbuf as a buffer size, determine how much can we
120 * really transfer given the overhead of different algorithms
122 * Sets smaxbuf and smaxqueue
126 secure_determine_constants(void)
131 if (auth_type
== AUTHTYPE_GSSAPI
) {
132 OM_uint32 maj_stat
, min_stat
, mlen
;
133 OM_uint32 msize
= maxbuf
;
135 maj_stat
= gss_wrap_size_limit(&min_stat
, gcontext
,
139 if (maj_stat
!= GSS_S_COMPLETE
) {
140 user_gss_error(maj_stat
, min_stat
,
141 "GSSAPI fudge determination");
142 /* Return error how? */
152 secure_putbyte(int fd
, uchar_t c
)
156 if ((smaxbuf
== 0) || (smaxqueue
== 0) || (smaxbuf
!= maxbuf
)) {
157 ret
= secure_determine_constants();
162 if (nout
== smaxqueue
) {
164 ret
= secure_putbuf(fd
, ucbuf
, smaxqueue
);
165 return (ret
? ret
:c
);
173 * -1 on error (errno set)
174 * -2 on security error
181 if (dlevel
== PROT_C
)
184 if (ret
= secure_putbuf(fd
, ucbuf
, nout
))
186 return (secure_putbuf(fd
, (uchar_t
*)"", nout
= 0));
193 * -2 on security error
196 secure_putc(int c
, FILE *stream
)
198 if (dlevel
== PROT_C
)
199 return (putc(c
, stream
));
200 return (secure_putbyte(fileno(stream
), (uchar_t
)c
));
206 * -1 on error (errno set)
207 * -2 on security error
210 secure_write(int fd
, const void *inbuf
, size_t nbyte
)
214 uchar_t
*buf
= (uchar_t
*)inbuf
;
216 if (dlevel
== PROT_C
)
217 return (write(fd
, buf
, nbyte
));
218 for (i
= 0; nbyte
> 0; nbyte
--)
219 if ((c
= secure_putbyte(fd
, buf
[i
++])) < 0)
227 * -1 on error, errno set
228 * -2 on security error
230 static int secure_putbuf(int fd
, uchar_t
*buf
, uint_t nbyte
)
232 static char *outbuf
; /* output ciphertext */
233 static uint_t bufsize
; /* size of outbuf */
237 /* Other auth types go here ... */
239 if (auth_type
== AUTHTYPE_GSSAPI
) {
240 gss_buffer_desc in_buf
, out_buf
;
241 OM_uint32 maj_stat
, min_stat
;
245 in_buf
.length
= nbyte
;
246 maj_stat
= gss_seal(&min_stat
, gcontext
,
247 (dlevel
== PROT_P
), /* confidential */
249 &in_buf
, &conf_state
,
251 if (maj_stat
!= GSS_S_COMPLETE
) {
253 * generally need to deal
254 * ie. should loop, but for now just fail
256 user_gss_error(maj_stat
, min_stat
, dlevel
== PROT_P
?
257 "GSSAPI seal failed" : "GSSAPI sign failed");
261 if (bufsize
< out_buf
.length
) {
263 realloc(outbuf
, (size_t)out_buf
.length
) :
264 malloc((size_t)out_buf
.length
);
266 bufsize
= out_buf
.length
;
269 secure_error("%s (in malloc of PROT buffer)",
275 memcpy(outbuf
, out_buf
.value
, length
= out_buf
.length
);
276 gss_release_buffer(&min_stat
, &out_buf
);
278 net_len
= htonl((uint32_t)length
);
279 if (looping_write(fd
, (char *)&net_len
, 4) == -1)
281 if (looping_write(fd
, outbuf
, length
) != length
)
287 secure_getbyte(int fd
)
289 /* number of chars in ucbuf, pointer into ucbuf */
290 static uint_t nin
, bufp
;
296 looping_read(fd
, (char *)&length
, sizeof (length
)))
297 != sizeof (length
)) {
298 secure_error("Couldn't read PROT buffer length: %d/%s",
299 kerror
, (kerror
== -1) ? strerror(errno
) :
303 if ((length
= ntohl((uint32_t)length
)) > maxbuf
) {
304 secure_error("Length (%d) of PROT buffer > PBSZ=%u",
308 if ((kerror
= looping_read(fd
, (char *)ucbuf
, length
))
310 secure_error("Couldn't read %u byte PROT buffer: %s",
311 length
, kerror
== -1 ?
312 strerror(errno
) : "premature EOF");
315 /* Other auth types go here ... */
317 if (auth_type
== AUTHTYPE_GSSAPI
) {
318 gss_buffer_desc xmit_buf
, msg_buf
;
319 OM_uint32 maj_stat
, min_stat
;
322 xmit_buf
.value
= ucbuf
;
323 xmit_buf
.length
= length
;
324 conf_state
= (dlevel
== PROT_P
);
325 /* decrypt/verify the message */
326 maj_stat
= gss_unseal(&min_stat
, gcontext
, &xmit_buf
,
327 &msg_buf
, &conf_state
, NULL
);
328 if (maj_stat
!= GSS_S_COMPLETE
) {
329 user_gss_error(maj_stat
, min_stat
,
331 "failed unsealing ENC message":
332 "failed unsealing MIC message");
336 memcpy(ucbuf
, msg_buf
.value
,
337 nin
= bufp
= msg_buf
.length
);
338 gss_release_buffer(&min_stat
, &msg_buf
);
340 /* Other auth types go here ... */
342 return ((nin
== 0) ? EOF
: ucbuf
[bufp
- nin
--]);
349 * -2 on security error
352 secure_getc(FILE *stream
)
354 if (dlevel
== PROT_C
)
355 return (getc(stream
));
356 return (secure_getbyte(fileno(stream
)));
361 * > 0 on success (n == # of bytes read)
363 * -1 on error, errno set, only for PROT_C
364 * -2 on security error (ERR = -2)
367 secure_read(int fd
, void *inbuf
, size_t nbyte
)
370 char *buf
= (char *)inbuf
;
372 if (dlevel
== PROT_C
)
373 return (read(fd
, buf
, nbyte
));
377 for (i
= 0; nbyte
> 0; nbyte
--)
378 switch (c
= secure_getbyte(fd
)) {