2 SPDX-License-Identifier: BSD-3-Clause
6 Copyright (c) 2000 The Regents of the University of Michigan.
9 Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
10 All rights reserved, all wrongs reversed.
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
18 2. Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the distribution.
21 3. Neither the name of the University nor the names of its
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
25 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 $Id: authgss_prot.c,v 1.18 2000/09/01 04:14:03 dugsong Exp $
46 #include <rpc/rpcsec_gss.h>
47 #include "rpcsec_gss_int.h"
49 #define MAX_GSS_SIZE 10240 /* XXX */
52 xdr_gss_buffer_desc(XDR *xdrs, gss_buffer_desc *p)
60 ret = xdr_bytes(xdrs, &val, &len, MAX_GSS_SIZE);
68 xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
75 ret = (xdr_u_int(xdrs, &p->gc_version) &&
76 xdr_enum(xdrs, &proc) &&
77 xdr_u_int(xdrs, &p->gc_seq) &&
78 xdr_enum(xdrs, &svc) &&
79 xdr_gss_buffer_desc(xdrs, &p->gc_handle));
87 xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
90 return (xdr_gss_buffer_desc(xdrs, &p->gr_handle) &&
91 xdr_u_int(xdrs, &p->gr_major) &&
92 xdr_u_int(xdrs, &p->gr_minor) &&
93 xdr_u_int(xdrs, &p->gr_win) &&
94 xdr_gss_buffer_desc(xdrs, &p->gr_token));
98 xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
99 gss_ctx_id_t ctx, gss_qop_t qop,
100 rpc_gss_service_t svc, u_int seq)
102 gss_buffer_desc databuf, wrapbuf;
103 OM_uint32 maj_stat, min_stat;
104 int start, end, conf_state;
108 /* Skip databody length. */
109 start = XDR_GETPOS(xdrs);
110 XDR_SETPOS(xdrs, start + 4);
112 /* Marshal rpc_gss_data_t (sequence number + arguments). */
113 if (!xdr_u_int(xdrs, &seq) || !xdr_func(xdrs, xdr_ptr))
115 end = XDR_GETPOS(xdrs);
117 /* Set databuf to marshalled rpc_gss_data_t. */
118 databuf.length = end - start - 4;
119 XDR_SETPOS(xdrs, start + 4);
120 databuf.value = XDR_INLINE(xdrs, databuf.length);
124 if (svc == rpc_gss_svc_integrity) {
125 /* Marshal databody_integ length. */
126 XDR_SETPOS(xdrs, start);
127 len = databuf.length;
128 if (!xdr_u_int(xdrs, &len))
131 /* Checksum rpc_gss_data_t. */
132 maj_stat = gss_get_mic(&min_stat, ctx, qop,
134 if (maj_stat != GSS_S_COMPLETE) {
135 log_debug("gss_get_mic failed");
138 /* Marshal checksum. */
139 XDR_SETPOS(xdrs, end);
140 xdr_stat = xdr_gss_buffer_desc(xdrs, &wrapbuf);
141 gss_release_buffer(&min_stat, &wrapbuf);
143 else if (svc == rpc_gss_svc_privacy) {
144 /* Encrypt rpc_gss_data_t. */
145 maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
146 &conf_state, &wrapbuf);
147 if (maj_stat != GSS_S_COMPLETE) {
148 log_status("gss_wrap", NULL, maj_stat, min_stat);
151 /* Marshal databody_priv. */
152 XDR_SETPOS(xdrs, start);
153 xdr_stat = xdr_gss_buffer_desc(xdrs, &wrapbuf);
154 gss_release_buffer(&min_stat, &wrapbuf);
160 xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
161 gss_ctx_id_t ctx, gss_qop_t qop,
162 rpc_gss_service_t svc, u_int seq)
165 gss_buffer_desc databuf, wrapbuf;
166 OM_uint32 maj_stat, min_stat;
167 u_int seq_num, conf_state, qop_state;
170 if (xdr_func == (xdrproc_t) xdr_void || xdr_ptr == NULL)
173 memset(&databuf, 0, sizeof(databuf));
174 memset(&wrapbuf, 0, sizeof(wrapbuf));
176 if (svc == rpc_gss_svc_integrity) {
177 /* Decode databody_integ. */
178 if (!xdr_gss_buffer_desc(xdrs, &databuf)) {
179 log_debug("xdr decode databody_integ failed");
182 /* Decode checksum. */
183 if (!xdr_gss_buffer_desc(xdrs, &wrapbuf)) {
184 mem_free(databuf.value, databuf.length);
185 log_debug("xdr decode checksum failed");
188 /* Verify checksum and QOP. */
189 maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
190 &wrapbuf, &qop_state);
191 mem_free(wrapbuf.value, wrapbuf.length);
193 if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
194 mem_free(databuf.value, databuf.length);
195 log_status("gss_verify_mic", NULL, maj_stat, min_stat);
198 } else if (svc == rpc_gss_svc_privacy) {
199 /* Decode databody_priv. */
200 if (!xdr_gss_buffer_desc(xdrs, &wrapbuf)) {
201 log_debug("xdr decode databody_priv failed");
204 /* Decrypt databody. */
205 maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
206 &conf_state, &qop_state);
208 mem_free(wrapbuf.value, wrapbuf.length);
210 /* Verify encryption and QOP. */
211 if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||
212 conf_state != TRUE) {
213 gss_release_buffer(&min_stat, &databuf);
214 log_status("gss_unwrap", NULL, maj_stat, min_stat);
218 /* Decode rpc_gss_data_t (sequence number + arguments). */
219 xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
220 xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) &&
221 xdr_func(&tmpxdrs, xdr_ptr));
222 XDR_DESTROY(&tmpxdrs);
225 * Integrity service allocates databuf via XDR so free it the
228 if (svc == rpc_gss_svc_integrity) {
229 xdr_free((xdrproc_t) xdr_gss_buffer_desc, (char *) &databuf);
231 gss_release_buffer(&min_stat, &databuf);
234 /* Verify sequence number. */
235 if (xdr_stat == TRUE && seq_num != seq) {
236 log_debug("wrong sequence number in databody");
246 log_debug(const char *fmt, ...)
251 fprintf(stderr, "rpcsec_gss: ");
252 vfprintf(stderr, fmt, ap);
253 fprintf(stderr, "\n");
258 log_status(const char *m, gss_OID mech, OM_uint32 maj_stat, OM_uint32 min_stat)
264 fprintf(stderr, "rpcsec_gss: %s: ", m);
266 gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
268 fprintf(stderr, "%s - ", (char *)msg.value);
269 gss_release_buffer(&min, &msg);
271 gss_display_status(&min, min_stat, GSS_C_MECH_CODE, mech,
273 fprintf(stderr, "%s\n", (char *)msg.value);
274 gss_release_buffer(&min, &msg);
280 log_debug(__unused const char *fmt, ...)
285 log_status(__unused const char *m, __unused gss_OID mech,
286 __unused OM_uint32 maj_stat, __unused OM_uint32 min_stat)