1 /*
2 authgss_prot.c
3
4 Copyright (c) 2000 The Regents of the University of Michigan.
5 All rights reserved.
6
7 Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
8 All rights reserved, all wrongs reversed.
9
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions
12 are met:
13
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.
22
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.
34
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdarg.h>
40 #include <rpc/types.h>
41 #include <rpc/xdr.h>
42 #include <rpc/auth.h>
43 #include <rpc/auth_gss.h>
44 #include <rpc/rpc.h>
45 #include <gssapi/gssapi.h>
46
47 bool_t
xdr_rpc_gss_cred(XDR * xdrs,struct rpc_gss_cred * p)48 xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
49 {
50 bool_t xdr_stat;
51
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 (u_int *)&p->gc_ctx.length, MAX_AUTH_BYTES));
58
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);
65
66 return (xdr_stat);
67 }
68
69 bool_t
xdr_rpc_gss_init_args(XDR * xdrs,gss_buffer_desc * p)70 xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p)
71 {
72 bool_t xdr_stat;
73
74 xdr_stat = xdr_bytes(xdrs, (char **)&p->value,
75 (u_int *)&p->length, MAX_NETOBJ_SZ);
76
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",
80 p->value, p->length);
81
82 return (xdr_stat);
83 }
84
85 bool_t
xdr_rpc_gss_init_res(XDR * xdrs,struct rpc_gss_init_res * p)86 xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
87 {
88 bool_t xdr_stat;
89
90 xdr_stat = (xdr_bytes(xdrs, (char **)&p->gr_ctx.value,
91 (u_int *)&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 (u_int *)&p->gr_token.length, MAX_NETOBJ_SZ));
97
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);
105
106 return (xdr_stat);
107 }
108
109 bool_t
xdr_rpc_gss_wrap_data(XDR * xdrs,xdrproc_t xdr_func,caddr_t xdr_ptr,gss_ctx_id_t ctx,gss_qop_t qop,rpc_gss_svc_t svc,u_int seq)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)
113 {
114 gss_buffer_desc databuf, wrapbuf;
115 OM_uint32 maj_stat, min_stat;
116 int start, end, conf_state;
117 bool_t xdr_stat;
118
119 /* Skip databody length. */
120 start = XDR_GETPOS(xdrs);
121 XDR_SETPOS(xdrs, start + 4);
122
123 /* Marshal rpc_gss_data_t (sequence number + arguments). */
124 if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr))
125 return (FALSE);
126 end = XDR_GETPOS(xdrs);
127
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);
132
133 xdr_stat = FALSE;
134
135 if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
136 /* Marshal databody_integ length. */
137 XDR_SETPOS(xdrs, start);
138 if (!xdr_u_int(xdrs, (u_int *)&databuf.length))
139 return (FALSE);
140
141 /* Checksum rpc_gss_data_t. */
142 maj_stat = gss_get_mic(&min_stat, ctx, qop,
143 &databuf, &wrapbuf);
144 if (maj_stat != GSS_S_COMPLETE) {
145 log_debug("gss_get_mic failed");
146 return (FALSE);
147 }
148 /* Marshal checksum. */
149 XDR_SETPOS(xdrs, end);
150 xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
151 (u_int *)&wrapbuf.length, MAX_NETOBJ_SZ);
152 gss_release_buffer(&min_stat, &wrapbuf);
153 }
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);
160 return (FALSE);
161 }
162 /* Marshal databody_priv. */
163 XDR_SETPOS(xdrs, start);
164 xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
165 (u_int *)&wrapbuf.length, MAX_NETOBJ_SZ);
166 gss_release_buffer(&min_stat, &wrapbuf);
167 }
168 return (xdr_stat);
169 }
170
171 bool_t
xdr_rpc_gss_unwrap_data(XDR * xdrs,xdrproc_t xdr_func,caddr_t xdr_ptr,gss_ctx_id_t ctx,gss_qop_t qop,rpc_gss_svc_t svc,u_int seq)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)
175 {
176 XDR tmpxdrs;
177 gss_buffer_desc databuf, wrapbuf;
178 OM_uint32 maj_stat, min_stat;
179 u_int seq_num, qop_state;
180 int conf_state;
181 bool_t xdr_stat;
182
183 if (xdr_func == (xdrproc_t)xdr_void || xdr_ptr == NULL)
184 return (TRUE);
185
186 memset(&databuf, 0, sizeof(databuf));
187 memset(&wrapbuf, 0, sizeof(wrapbuf));
188
189 if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
190 /* Decode databody_integ. */
191 if (!xdr_bytes(xdrs, (char **)&databuf.value, (u_int *)&databuf.length,
192 MAX_NETOBJ_SZ)) {
193 log_debug("xdr decode databody_integ failed");
194 return (FALSE);
195 }
196 /* Decode checksum. */
197 if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length,
198 MAX_NETOBJ_SZ)) {
199 gss_release_buffer(&min_stat, &databuf);
200 log_debug("xdr decode checksum failed");
201 return (FALSE);
202 }
203 /* Verify checksum and QOP. */
204 maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
205 &wrapbuf, &qop_state);
206 gss_release_buffer(&min_stat, &wrapbuf);
207
208 if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
209 gss_release_buffer(&min_stat, &databuf);
210 log_status("gss_verify_mic", maj_stat, min_stat);
211 return (FALSE);
212 }
213 }
214 else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
215 /* Decode databody_priv. */
216 if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, (u_int *)&wrapbuf.length,
217 MAX_NETOBJ_SZ)) {
218 log_debug("xdr decode databody_priv failed");
219 return (FALSE);
220 }
221 /* Decrypt databody. */
222 maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
223 &conf_state, &qop_state);
224
225 gss_release_buffer(&min_stat, &wrapbuf);
226
227 /* Verify encryption and QOP. */
228 if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||
229 conf_state != TRUE) {
230 gss_release_buffer(&min_stat, &databuf);
231 log_status("gss_unwrap", maj_stat, min_stat);
232 return (FALSE);
233 }
234 }
235 /* Decode rpc_gss_data_t (sequence number + arguments). */
236 xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
237 xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) &&
238 (*xdr_func)(&tmpxdrs, xdr_ptr));
239 XDR_DESTROY(&tmpxdrs);
240 gss_release_buffer(&min_stat, &databuf);
241
242 /* Verify sequence number. */
243 if (xdr_stat == TRUE && seq_num != seq) {
244 log_debug("wrong sequence number in databody");
245 return (FALSE);
246 }
247 return (xdr_stat);
248 }
249
250 bool_t
xdr_rpc_gss_data(XDR * xdrs,xdrproc_t xdr_func,caddr_t xdr_ptr,gss_ctx_id_t ctx,gss_qop_t qop,rpc_gss_svc_t svc,u_int seq)251 xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
252 gss_ctx_id_t ctx, gss_qop_t qop,
253 rpc_gss_svc_t svc, u_int seq)
254 {
255 switch (xdrs->x_op) {
256
257 case XDR_ENCODE:
258 return (xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr,
259 ctx, qop, svc, seq));
260 case XDR_DECODE:
261 return (xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr,
262 ctx, qop,svc, seq));
263 case XDR_FREE:
264 return (TRUE);
265 }
266 return (FALSE);
267 }
268
269 #ifdef DEBUG
270 #include <ctype.h>
271
272 void
log_debug(const char * fmt,...)273 log_debug(const char *fmt, ...)
274 {
275 va_list ap;
276
277 va_start(ap, fmt);
278 fprintf(stderr, "rpcsec_gss: ");
279 vfprintf(stderr, fmt, ap);
280 fprintf(stderr, "\n");
281 va_end(ap);
282 }
283
284 void
log_status(char * m,OM_uint32 maj_stat,OM_uint32 min_stat)285 log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
286 {
287 OM_uint32 min;
288 gss_buffer_desc msg;
289 int msg_ctx = 0;
290
291 fprintf(stderr, "rpcsec_gss: %s: ", m);
292
293 gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
294 &msg_ctx, &msg);
295 fprintf(stderr, "%s - ", (char *)msg.value);
296 gss_release_buffer(&min, &msg);
297
298 gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID,
299 &msg_ctx, &msg);
300 fprintf(stderr, "%s\n", (char *)msg.value);
301 gss_release_buffer(&min, &msg);
302 }
303
304 void
log_hexdump(const u_char * buf,int len,int offset)305 log_hexdump(const u_char *buf, int len, int offset)
306 {
307 u_int i, j, jm;
308 int c;
309
310 fprintf(stderr, "\n");
311 for (i = 0; i < len; i += 0x10) {
312 fprintf(stderr, " %04x: ", (u_int)(i + offset));
313 jm = len - i;
314 jm = jm > 16 ? 16 : jm;
315
316 for (j = 0; j < jm; j++) {
317 if ((j % 2) == 1)
318 fprintf(stderr, "%02x ", (u_int) buf[i+j]);
319 else
320 fprintf(stderr, "%02x", (u_int) buf[i+j]);
321 }
322 for (; j < 16; j++) {
323 if ((j % 2) == 1) printf(" ");
324 else fprintf(stderr, " ");
325 }
326 fprintf(stderr, " ");
327
328 for (j = 0; j < jm; j++) {
329 c = buf[i+j];
330 c = isprint(c) ? c : '.';
331 fprintf(stderr, "%c", c);
332 }
333 fprintf(stderr, "\n");
334 }
335 }
336
337 #else
338
339 void
log_debug(const char * fmt,...)340 log_debug(const char *fmt, ...)
341 {
342 }
343
344 void
log_status(char * m,OM_uint32 maj_stat,OM_uint32 min_stat)345 log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
346 {
347 }
348
349 void
log_hexdump(const u_char * buf,int len,int offset)350 log_hexdump(const u_char *buf, int len, int offset)
351 {
352 }
353
354 #endif
355
356
357