4 Copyright (c) 2000 The Regents of the University of Michigan.
7 Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
8 All rights reserved, all wrongs reversed.
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions
14 1. Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in the
18 documentation and/or other materials provided with the distribution.
19 3. Neither the name of the University nor the names of its
20 contributors may be used to endorse or promote products derived
21 from this software without specific prior written permission.
23 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include <rpc/types.h>
43 #include <rpc/auth_gss.h>
45 #include <gssapi/gssapi.h>
48 xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
52 xdr_stat = (xdr_u_int(xdrs, &p->gc_v) &&
53 xdr_enum(xdrs, (enum_t *)&p->gc_proc) &&
54 xdr_u_int(xdrs, &p->gc_seq) &&
55 xdr_enum(xdrs, (enum_t *)&p->gc_svc) &&
56 xdr_bytes(xdrs, (char **)&p->gc_ctx.value,
57 &p->gc_ctx.length, MAX_AUTH_BYTES));
59 log_debug("xdr_rpc_gss_cred: %s %s "
60 "(v %d, proc %d, seq %d, svc %d, ctx %p:%d)",
61 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
62 (xdr_stat == TRUE) ? "success" : "failure",
63 p->gc_v, p->gc_proc, p->gc_seq, p->gc_svc,
64 p->gc_ctx.value, p->gc_ctx.length);
70 xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p)
74 xdr_stat = xdr_bytes(xdrs, (char **)&p->value,
75 &p->length, MAX_NETOBJ_SZ);
77 log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)",
78 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
79 (xdr_stat == TRUE) ? "success" : "failure",
86 xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
90 xdr_stat = (xdr_bytes(xdrs, (char **)&p->gr_ctx.value,
91 &p->gr_ctx.length, MAX_NETOBJ_SZ) &&
92 xdr_u_int(xdrs, &p->gr_major) &&
93 xdr_u_int(xdrs, &p->gr_minor) &&
94 xdr_u_int(xdrs, &p->gr_win) &&
95 xdr_bytes(xdrs, (char **)&p->gr_token.value,
96 &p->gr_token.length, MAX_NETOBJ_SZ));
98 log_debug("xdr_rpc_gss_init_res %s %s "
99 "(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)",
100 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
101 (xdr_stat == TRUE) ? "success" : "failure",
102 p->gr_ctx.value, p->gr_ctx.length,
103 p->gr_major, p->gr_minor, p->gr_win,
104 p->gr_token.value, p->gr_token.length);
110 xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
111 gss_ctx_id_t ctx, gss_qop_t qop,
112 rpc_gss_svc_t svc, u_int seq)
114 gss_buffer_desc databuf, wrapbuf;
115 OM_uint32 maj_stat, min_stat;
116 int start, end, conf_state;
119 /* Skip databody length. */
120 start = XDR_GETPOS(xdrs);
121 XDR_SETPOS(xdrs, start + 4);
123 /* Marshal rpc_gss_data_t (sequence number + arguments). */
124 if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr))
126 end = XDR_GETPOS(xdrs);
128 /* Set databuf to marshalled rpc_gss_data_t. */
129 databuf.length = end - start - 4;
130 XDR_SETPOS(xdrs, start + 4);
131 databuf.value = XDR_INLINE(xdrs, databuf.length);
135 if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
136 /* Marshal databody_integ length. */
137 XDR_SETPOS(xdrs, start);
138 if (!xdr_u_int(xdrs, &databuf.length))
141 /* Checksum rpc_gss_data_t. */
142 maj_stat = gss_get_mic(&min_stat, ctx, qop,
144 if (maj_stat != GSS_S_COMPLETE) {
145 log_debug("gss_get_mic failed");
148 /* Marshal checksum. */
149 XDR_SETPOS(xdrs, end);
150 xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
151 &wrapbuf.length, MAX_NETOBJ_SZ);
152 gss_release_buffer(&min_stat, &wrapbuf);
154 else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
155 /* Encrypt rpc_gss_data_t. */
156 maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
157 &conf_state, &wrapbuf);
158 if (maj_stat != GSS_S_COMPLETE) {
159 log_status("gss_wrap", maj_stat, min_stat);
162 /* Marshal databody_priv. */
163 XDR_SETPOS(xdrs, start);
164 xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
165 &wrapbuf.length, MAX_NETOBJ_SZ);
166 gss_release_buffer(&min_stat, &wrapbuf);
172 xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
173 gss_ctx_id_t ctx, gss_qop_t qop,
174 rpc_gss_svc_t svc, u_int seq)
177 gss_buffer_desc databuf, wrapbuf;
178 OM_uint32 maj_stat, min_stat;
179 u_int seq_num, conf_state, qop_state;
182 if (xdr_func == xdr_void || xdr_ptr == NULL)
185 memset(&databuf, 0, sizeof(databuf));
186 memset(&wrapbuf, 0, sizeof(wrapbuf));
188 if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
189 /* Decode databody_integ. */
190 if (!xdr_bytes(xdrs, (char **)&databuf.value, &databuf.length,
192 log_debug("xdr decode databody_integ failed");
195 /* Decode checksum. */
196 if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, &wrapbuf.length,
198 gss_release_buffer(&min_stat, &databuf);
199 log_debug("xdr decode checksum failed");
202 /* Verify checksum and QOP. */
203 maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
204 &wrapbuf, &qop_state);
205 gss_release_buffer(&min_stat, &wrapbuf);
207 if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
208 gss_release_buffer(&min_stat, &databuf);
209 log_status("gss_verify_mic", maj_stat, min_stat);
213 else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
214 /* Decode databody_priv. */
215 if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, &wrapbuf.length,
217 log_debug("xdr decode databody_priv failed");
220 /* Decrypt databody. */
221 maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
222 &conf_state, &qop_state);
224 gss_release_buffer(&min_stat, &wrapbuf);
226 /* Verify encryption and QOP. */
227 if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||
228 conf_state != TRUE) {
229 gss_release_buffer(&min_stat, &databuf);
230 log_status("gss_unwrap", maj_stat, min_stat);
234 /* Decode rpc_gss_data_t (sequence number + arguments). */
235 xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
236 xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) &&
237 (*xdr_func)(&tmpxdrs, xdr_ptr));
238 XDR_DESTROY(&tmpxdrs);
239 gss_release_buffer(&min_stat, &databuf);
241 /* Verify sequence number. */
242 if (xdr_stat == TRUE && seq_num != seq) {
243 log_debug("wrong sequence number in databody");
250 xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
251 gss_ctx_id_t ctx, gss_qop_t qop,
252 rpc_gss_svc_t svc, u_int seq)
254 switch (xdrs->x_op) {
257 return (xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr,
258 ctx, qop, svc, seq));
260 return (xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr,
272 log_debug(const char *fmt, ...)
277 fprintf(stderr, "rpcsec_gss: ");
278 vfprintf(stderr, fmt, ap);
279 fprintf(stderr, "\n");
284 log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
290 fprintf(stderr, "rpcsec_gss: %s: ", m);
292 gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
294 fprintf(stderr, "%s - ", (char *)msg.value);
295 gss_release_buffer(&min, &msg);
297 gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID,
299 fprintf(stderr, "%s\n", (char *)msg.value);
300 gss_release_buffer(&min, &msg);
304 log_hexdump(const u_char *buf, int len, int offset)
309 fprintf(stderr, "\n");
310 for (i = 0; i < len; i += 0x10) {
311 fprintf(stderr, " %04x: ", (u_int)(i + offset));
313 jm = jm > 16 ? 16 : jm;
315 for (j = 0; j < jm; j++) {
317 fprintf(stderr, "%02x ", (u_int) buf[i+j]);
319 fprintf(stderr, "%02x", (u_int) buf[i+j]);
321 for (; j < 16; j++) {
322 if ((j % 2) == 1) printf(" ");
323 else fprintf(stderr, " ");
325 fprintf(stderr, " ");
327 for (j = 0; j < jm; j++) {
329 c = isprint(c) ? c : '.';
330 fprintf(stderr, "%c", c);
332 fprintf(stderr, "\n");
339 log_debug(const char *fmt, ...)
344 log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
349 log_hexdump(const u_char *buf, int len, int offset)