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.
35 $Id: authgss_prot.c,v 1.18 2000/09/01 04:14:03 dugsong Exp $
44 #include <rpc/rpcsec_gss.h>
45 #include "rpcsec_gss_int.h"
47 #define MAX_GSS_SIZE 10240 /* XXX */
50 xdr_gss_buffer_desc(XDR *xdrs, gss_buffer_desc *p)
58 ret = xdr_bytes(xdrs, &val, &len, MAX_GSS_SIZE);
66 xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
73 ret = (xdr_u_int(xdrs, &p->gc_version) &&
74 xdr_enum(xdrs, &proc) &&
75 xdr_u_int(xdrs, &p->gc_seq) &&
76 xdr_enum(xdrs, &svc) &&
77 xdr_gss_buffer_desc(xdrs, &p->gc_handle));
85 xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
88 return (xdr_gss_buffer_desc(xdrs, &p->gr_handle) &&
89 xdr_u_int(xdrs, &p->gr_major) &&
90 xdr_u_int(xdrs, &p->gr_minor) &&
91 xdr_u_int(xdrs, &p->gr_win) &&
92 xdr_gss_buffer_desc(xdrs, &p->gr_token));
96 xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
97 gss_ctx_id_t ctx, gss_qop_t qop,
98 rpc_gss_service_t svc, u_int seq)
100 gss_buffer_desc databuf, wrapbuf;
101 OM_uint32 maj_stat, min_stat;
102 int start, end, conf_state;
106 /* Skip databody length. */
107 start = XDR_GETPOS(xdrs);
108 XDR_SETPOS(xdrs, start + 4);
110 /* Marshal rpc_gss_data_t (sequence number + arguments). */
111 if (!xdr_u_int(xdrs, &seq) || !xdr_func(xdrs, xdr_ptr))
113 end = XDR_GETPOS(xdrs);
115 /* Set databuf to marshalled rpc_gss_data_t. */
116 databuf.length = end - start - 4;
117 XDR_SETPOS(xdrs, start + 4);
118 databuf.value = XDR_INLINE(xdrs, databuf.length);
122 if (svc == rpc_gss_svc_integrity) {
123 /* Marshal databody_integ length. */
124 XDR_SETPOS(xdrs, start);
125 len = databuf.length;
126 if (!xdr_u_int(xdrs, &len))
129 /* Checksum rpc_gss_data_t. */
130 maj_stat = gss_get_mic(&min_stat, ctx, qop,
132 if (maj_stat != GSS_S_COMPLETE) {
133 log_debug("gss_get_mic failed");
136 /* Marshal checksum. */
137 XDR_SETPOS(xdrs, end);
138 xdr_stat = xdr_gss_buffer_desc(xdrs, &wrapbuf);
139 gss_release_buffer(&min_stat, &wrapbuf);
141 else if (svc == rpc_gss_svc_privacy) {
142 /* Encrypt rpc_gss_data_t. */
143 maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
144 &conf_state, &wrapbuf);
145 if (maj_stat != GSS_S_COMPLETE) {
146 log_status("gss_wrap", NULL, maj_stat, min_stat);
149 /* Marshal databody_priv. */
150 XDR_SETPOS(xdrs, start);
151 xdr_stat = xdr_gss_buffer_desc(xdrs, &wrapbuf);
152 gss_release_buffer(&min_stat, &wrapbuf);
158 xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
159 gss_ctx_id_t ctx, gss_qop_t qop,
160 rpc_gss_service_t svc, u_int seq)
163 gss_buffer_desc databuf, wrapbuf;
164 OM_uint32 maj_stat, min_stat;
165 u_int seq_num, conf_state, qop_state;
168 if (xdr_func == (xdrproc_t) xdr_void || xdr_ptr == NULL)
171 memset(&databuf, 0, sizeof(databuf));
172 memset(&wrapbuf, 0, sizeof(wrapbuf));
174 if (svc == rpc_gss_svc_integrity) {
175 /* Decode databody_integ. */
176 if (!xdr_gss_buffer_desc(xdrs, &databuf)) {
177 log_debug("xdr decode databody_integ failed");
180 /* Decode checksum. */
181 if (!xdr_gss_buffer_desc(xdrs, &wrapbuf)) {
182 mem_free(databuf.value, databuf.length);
183 log_debug("xdr decode checksum failed");
186 /* Verify checksum and QOP. */
187 maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
188 &wrapbuf, &qop_state);
189 mem_free(wrapbuf.value, wrapbuf.length);
191 if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
192 mem_free(databuf.value, databuf.length);
193 log_status("gss_verify_mic", NULL, maj_stat, min_stat);
196 } else if (svc == rpc_gss_svc_privacy) {
197 /* Decode databody_priv. */
198 if (!xdr_gss_buffer_desc(xdrs, &wrapbuf)) {
199 log_debug("xdr decode databody_priv failed");
202 /* Decrypt databody. */
203 maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
204 &conf_state, &qop_state);
206 mem_free(wrapbuf.value, wrapbuf.length);
208 /* Verify encryption and QOP. */
209 if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||
210 conf_state != TRUE) {
211 gss_release_buffer(&min_stat, &databuf);
212 log_status("gss_unwrap", NULL, maj_stat, min_stat);
216 /* Decode rpc_gss_data_t (sequence number + arguments). */
217 xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
218 xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) &&
219 xdr_func(&tmpxdrs, xdr_ptr));
220 XDR_DESTROY(&tmpxdrs);
223 * Integrity service allocates databuf via XDR so free it the
226 if (svc == rpc_gss_svc_integrity) {
227 xdr_free((xdrproc_t) xdr_gss_buffer_desc, (char *) &databuf);
229 gss_release_buffer(&min_stat, &databuf);
232 /* Verify sequence number. */
233 if (xdr_stat == TRUE && seq_num != seq) {
234 log_debug("wrong sequence number in databody");
244 log_debug(const char *fmt, ...)
249 fprintf(stderr, "rpcsec_gss: ");
250 vfprintf(stderr, fmt, ap);
251 fprintf(stderr, "\n");
256 log_status(const char *m, gss_OID mech, OM_uint32 maj_stat, OM_uint32 min_stat)
262 fprintf(stderr, "rpcsec_gss: %s: ", m);
264 gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
266 fprintf(stderr, "%s - ", (char *)msg.value);
267 gss_release_buffer(&min, &msg);
269 gss_display_status(&min, min_stat, GSS_C_MECH_CODE, mech,
271 fprintf(stderr, "%s\n", (char *)msg.value);
272 gss_release_buffer(&min, &msg);
278 log_debug(__unused const char *fmt, ...)
283 log_status(__unused const char *m, __unused gss_OID mech,
284 __unused OM_uint32 maj_stat, __unused OM_uint32 min_stat)