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>
46 #include <gssapi/gssapi.h>
50 /* additional space needed for encoding */
51 #define RPC_SLACK_SPACE 1024
54 xdr_rpc_gss_buf(XDR *xdrs, gss_buffer_t buf, u_int maxsize)
59 if (xdrs->x_op != XDR_DECODE) {
60 if (buf->length > UINT_MAX)
65 xdr_stat = xdr_bytes(xdrs, (char **)&buf->value, &tmplen, maxsize);
67 if (xdr_stat && xdrs->x_op == XDR_DECODE)
70 gss_log_debug("xdr_rpc_gss_buf: %s %s (%p:%d)",
71 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
72 (xdr_stat == TRUE) ? "success" : "failure",
73 buf->value, buf->length);
79 xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
83 xdr_stat = (xdr_u_int(xdrs, &p->gc_v) &&
84 xdr_enum(xdrs, (enum_t *)&p->gc_proc) &&
85 xdr_u_int(xdrs, &p->gc_seq) &&
86 xdr_enum(xdrs, (enum_t *)&p->gc_svc) &&
87 xdr_rpc_gss_buf(xdrs, &p->gc_ctx, MAX_AUTH_BYTES));
89 gss_log_debug("xdr_rpc_gss_cred: %s %s "
90 "(v %d, proc %d, seq %d, svc %d, ctx %p:%d)",
91 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
92 (xdr_stat == TRUE) ? "success" : "failure",
93 p->gc_v, p->gc_proc, p->gc_seq, p->gc_svc,
94 p->gc_ctx.value, p->gc_ctx.length);
100 xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p)
103 u_int maxlen = (u_int)(p->length + RPC_SLACK_SPACE);
105 xdr_stat = xdr_rpc_gss_buf(xdrs, p, maxlen);
107 gss_log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)",
108 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
109 (xdr_stat == TRUE) ? "success" : "failure",
110 p->value, p->length);
116 xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
120 u_int ctx_maxlen = (u_int)(p->gr_ctx.length + RPC_SLACK_SPACE);
121 u_int tok_maxlen = (u_int)(p->gr_token.length + RPC_SLACK_SPACE);
123 xdr_stat = (xdr_rpc_gss_buf(xdrs, &p->gr_ctx, ctx_maxlen) &&
124 xdr_u_int(xdrs, &p->gr_major) &&
125 xdr_u_int(xdrs, &p->gr_minor) &&
126 xdr_u_int(xdrs, &p->gr_win) &&
127 xdr_rpc_gss_buf(xdrs, &p->gr_token, tok_maxlen));
129 gss_log_debug("xdr_rpc_gss_init_res %s %s "
130 "(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)",
131 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
132 (xdr_stat == TRUE) ? "success" : "failure",
133 p->gr_ctx.value, p->gr_ctx.length,
134 p->gr_major, p->gr_minor, p->gr_win,
135 p->gr_token.value, p->gr_token.length);
141 xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
142 gss_ctx_id_t ctx, gss_qop_t qop,
143 rpc_gss_svc_t svc, u_int seq)
145 gss_buffer_desc databuf, wrapbuf;
146 OM_uint32 maj_stat, min_stat;
147 int start, end, conf_state;
149 u_int databuflen, maxwrapsz;
151 /* Skip databody length. */
152 start = XDR_GETPOS(xdrs);
153 XDR_SETPOS(xdrs, start + 4);
155 memset(&databuf, 0, sizeof(databuf));
156 memset(&wrapbuf, 0, sizeof(wrapbuf));
158 /* Marshal rpc_gss_data_t (sequence number + arguments). */
159 if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr))
161 end = XDR_GETPOS(xdrs);
163 /* Set databuf to marshalled rpc_gss_data_t. */
164 databuflen = end - start - 4;
165 XDR_SETPOS(xdrs, start + 4);
166 databuf.value = XDR_INLINE(xdrs, databuflen);
167 databuf.length = databuflen;
171 if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
172 /* Marshal databody_integ length. */
173 XDR_SETPOS(xdrs, start);
174 if (!xdr_u_int(xdrs, (u_int *)&databuflen))
177 /* Checksum rpc_gss_data_t. */
178 maj_stat = gss_get_mic(&min_stat, ctx, qop,
180 if (maj_stat != GSS_S_COMPLETE) {
181 gss_log_status("xdr_rpc_gss_wrap_data: gss_get_mic",
185 /* Marshal checksum. */
186 XDR_SETPOS(xdrs, end);
187 maxwrapsz = (u_int)(wrapbuf.length + RPC_SLACK_SPACE);
188 xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, maxwrapsz);
189 gss_release_buffer(&min_stat, &wrapbuf);
191 else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
192 /* Encrypt rpc_gss_data_t. */
193 maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
194 &conf_state, &wrapbuf);
195 if (maj_stat != GSS_S_COMPLETE) {
196 gss_log_status("xdr_rpc_gss_wrap_data: gss_wrap",
200 /* Marshal databody_priv. */
201 XDR_SETPOS(xdrs, start);
202 maxwrapsz = (u_int)(wrapbuf.length + RPC_SLACK_SPACE);
203 xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, maxwrapsz);
204 gss_release_buffer(&min_stat, &wrapbuf);
210 xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
211 gss_ctx_id_t ctx, gss_qop_t qop,
212 rpc_gss_svc_t svc, u_int seq)
215 gss_buffer_desc databuf, wrapbuf;
216 OM_uint32 maj_stat, min_stat;
217 u_int seq_num, qop_state;
221 if (xdr_func == (xdrproc_t)xdr_void || xdr_ptr == NULL)
224 memset(&databuf, 0, sizeof(databuf));
225 memset(&wrapbuf, 0, sizeof(wrapbuf));
227 if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
228 /* Decode databody_integ. */
229 if (!xdr_rpc_gss_buf(xdrs, &databuf, (u_int)-1)) {
230 LIBTIRPC_DEBUG(1, ("xdr_rpc_gss_unwrap_data: decode databody_integ failed"));
233 /* Decode checksum. */
234 if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int)-1)) {
235 gss_release_buffer(&min_stat, &databuf);
236 LIBTIRPC_DEBUG(1, ("xdr_rpc_gss_unwrap_data: decode checksum failed"));
239 /* Verify checksum and QOP. */
240 maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
241 &wrapbuf, &qop_state);
242 gss_release_buffer(&min_stat, &wrapbuf);
244 if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
245 gss_release_buffer(&min_stat, &databuf);
246 gss_log_status("xdr_rpc_gss_unwrap_data: gss_verify_mic",
251 else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
252 /* Decode databody_priv. */
253 if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int)-1)) {
254 LIBTIRPC_DEBUG(1, ("xdr_rpc_gss_unwrap_data: decode databody_priv failed"));
257 /* Decrypt databody. */
258 maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
259 &conf_state, &qop_state);
261 gss_release_buffer(&min_stat, &wrapbuf);
263 /* Verify encryption and QOP. */
264 if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||
265 conf_state != TRUE) {
266 gss_release_buffer(&min_stat, &databuf);
267 gss_log_status("xdr_rpc_gss_unwrap_data: gss_unwrap",
272 /* Decode rpc_gss_data_t (sequence number + arguments). */
273 xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
274 xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) &&
275 (*xdr_func)(&tmpxdrs, xdr_ptr));
276 XDR_DESTROY(&tmpxdrs);
277 gss_release_buffer(&min_stat, &databuf);
279 /* Verify sequence number. */
280 if (xdr_stat == TRUE && seq_num != seq) {
282 ("xdr_rpc_gss_unwrap_data: wrong sequence number in databody"));
289 xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
290 gss_ctx_id_t ctx, gss_qop_t qop,
291 rpc_gss_svc_t svc, u_int seq)
293 switch (xdrs->x_op) {
296 return (xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr,
297 ctx, qop, svc, seq));
299 return (xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr,
308 gss_log_debug(const char *fmt, ...)
313 vlibtirpc_log_dbg(2, fmt, ap);
318 gss_log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
321 gss_buffer_desc maj_msg, min_msg;
322 u_int32_t msg_ctx = 0;
324 gss_display_status(&maj, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
326 gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID,
329 LIBTIRPC_DEBUG(1, ("%s: %s - %s", m, (char *)maj_msg.value, (char *)min_msg.value));
331 gss_release_buffer(&maj, &maj_msg);
332 gss_release_buffer(&min, &min_msg);
336 gss_log_hexdump(const u_char *buf, int len, int offset)
341 if (libtirpc_debug_level < 4 || log_stderr == 0)
344 fprintf(stderr, "\n");
345 for (i = 0; i < len; i += 0x10) {
346 fprintf(stderr, " %04x: ", (u_int)(i + offset));
348 jm = jm > 16 ? 16 : jm;
350 for (j = 0; j < jm; j++) {
352 fprintf(stderr, "%02x ", (u_int) buf[i+j]);
354 fprintf(stderr, "%02x", (u_int) buf[i+j]);
356 for (; j < 16; j++) {
357 if ((j % 2) == 1) printf(" ");
358 else fprintf(stderr, " ");
360 fprintf(stderr, " ");
362 for (j = 0; j < jm; j++) {
364 c = isprint(c) ? c : '.';
365 fprintf(stderr, "%c", c);
367 fprintf(stderr, "\n");