1184588Sdfr/*-
2184588Sdfr * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3184588Sdfr * Authors: Doug Rabson <dfr@rabson.org>
4184588Sdfr * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
5184588Sdfr *
6184588Sdfr * Redistribution and use in source and binary forms, with or without
7184588Sdfr * modification, are permitted provided that the following conditions
8184588Sdfr * are met:
9184588Sdfr * 1. Redistributions of source code must retain the above copyright
10184588Sdfr *    notice, this list of conditions and the following disclaimer.
11184588Sdfr * 2. Redistributions in binary form must reproduce the above copyright
12184588Sdfr *    notice, this list of conditions and the following disclaimer in the
13184588Sdfr *    documentation and/or other materials provided with the distribution.
14184588Sdfr *
15184588Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16184588Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17184588Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18184588Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19184588Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20184588Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21184588Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22184588Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23184588Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24184588Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25184588Sdfr * SUCH DAMAGE.
26184588Sdfr */
27184588Sdfr
28184588Sdfr#include <sys/cdefs.h>
29184588Sdfr__FBSDID("$FreeBSD$");
30184588Sdfr
31184588Sdfr#ifdef _KERNEL
32184588Sdfr#include <sys/malloc.h>
33184588Sdfr#else
34184588Sdfr#include <stdlib.h>
35184588Sdfr#include <string.h>
36184588Sdfr#endif
37184588Sdfr
38184588Sdfr#include <rpc/rpc.h>
39184588Sdfr#include <rpc/rpc_com.h>
40184588Sdfr
41184588Sdfr#include "gssd.h"
42184588Sdfr
43184588Sdfrbool_t
44184588Sdfrxdr_gss_buffer_desc(XDR *xdrs, gss_buffer_desc *buf)
45184588Sdfr{
46184588Sdfr	char *val;
47184588Sdfr	u_int len;
48184588Sdfr
49184588Sdfr	len = buf->length;
50184588Sdfr	val = buf->value;
51184588Sdfr	if (!xdr_bytes(xdrs, &val, &len, ~0))
52184588Sdfr		return (FALSE);
53184588Sdfr	buf->length = len;
54184588Sdfr	buf->value = val;
55184588Sdfr
56184588Sdfr	return (TRUE);
57184588Sdfr}
58184588Sdfr
59184588Sdfrbool_t
60184588Sdfrxdr_gss_OID_desc(XDR *xdrs, gss_OID_desc *oid)
61184588Sdfr{
62184588Sdfr	char *val;
63184588Sdfr	u_int len;
64184588Sdfr
65184588Sdfr	len = oid->length;
66184588Sdfr	val = oid->elements;
67184588Sdfr	if (!xdr_bytes(xdrs, &val, &len, ~0))
68184588Sdfr		return (FALSE);
69184588Sdfr	oid->length = len;
70184588Sdfr	oid->elements = val;
71184588Sdfr
72184588Sdfr	return (TRUE);
73184588Sdfr}
74184588Sdfr
75184588Sdfrbool_t
76184588Sdfrxdr_gss_OID(XDR *xdrs, gss_OID *oidp)
77184588Sdfr{
78184588Sdfr	gss_OID oid;
79184588Sdfr	bool_t is_null;
80184588Sdfr
81184588Sdfr	switch (xdrs->x_op) {
82184588Sdfr	case XDR_ENCODE:
83184588Sdfr		oid = *oidp;
84184588Sdfr		if (oid) {
85184588Sdfr			is_null = FALSE;
86184588Sdfr			if (!xdr_bool(xdrs, &is_null)
87184588Sdfr			    || !xdr_gss_OID_desc(xdrs, oid))
88184588Sdfr				return (FALSE);
89184588Sdfr		} else {
90184588Sdfr			is_null = TRUE;
91184588Sdfr			if (!xdr_bool(xdrs, &is_null))
92184588Sdfr				return (FALSE);
93184588Sdfr		}
94184588Sdfr		break;
95184588Sdfr
96184588Sdfr	case XDR_DECODE:
97184588Sdfr		if (!xdr_bool(xdrs, &is_null))
98184588Sdfr			return (FALSE);
99184588Sdfr		if (is_null) {
100184588Sdfr			*oidp = GSS_C_NO_OID;
101184588Sdfr		} else {
102184588Sdfr			oid = mem_alloc(sizeof(gss_OID_desc));
103184588Sdfr			memset(oid, 0, sizeof(*oid));
104298655Scem			if (!xdr_gss_OID_desc(xdrs, oid)) {
105298655Scem				mem_free(oid, sizeof(gss_OID_desc));
106184588Sdfr				return (FALSE);
107298655Scem			}
108184588Sdfr			*oidp = oid;
109184588Sdfr		}
110184588Sdfr		break;
111184588Sdfr
112184588Sdfr	case XDR_FREE:
113184588Sdfr		oid = *oidp;
114184588Sdfr		if (oid) {
115184588Sdfr			xdr_gss_OID_desc(xdrs, oid);
116184588Sdfr			mem_free(oid, sizeof(gss_OID_desc));
117184588Sdfr		}
118184588Sdfr	}
119184588Sdfr
120184588Sdfr	return (TRUE);
121184588Sdfr}
122184588Sdfr
123184588Sdfrbool_t
124184588Sdfrxdr_gss_OID_set_desc(XDR *xdrs, gss_OID_set_desc *set)
125184588Sdfr{
126184588Sdfr	caddr_t addr;
127184588Sdfr	u_int len;
128184588Sdfr
129184588Sdfr	len = set->count;
130184588Sdfr	addr = (caddr_t) set->elements;
131184588Sdfr	if (!xdr_array(xdrs, &addr, &len, ~0, sizeof(gss_OID_desc),
132184588Sdfr		(xdrproc_t) xdr_gss_OID_desc))
133184588Sdfr		return (FALSE);
134184588Sdfr	set->count = len;
135184588Sdfr	set->elements = (gss_OID) addr;
136184588Sdfr
137184588Sdfr	return (TRUE);
138184588Sdfr}
139184588Sdfr
140184588Sdfrbool_t
141184588Sdfrxdr_gss_OID_set(XDR *xdrs, gss_OID_set *setp)
142184588Sdfr{
143184588Sdfr	gss_OID_set set;
144184588Sdfr	bool_t is_null;
145184588Sdfr
146184588Sdfr	switch (xdrs->x_op) {
147184588Sdfr	case XDR_ENCODE:
148184588Sdfr		set = *setp;
149184588Sdfr		if (set) {
150184588Sdfr			is_null = FALSE;
151184588Sdfr			if (!xdr_bool(xdrs, &is_null)
152184588Sdfr			    || !xdr_gss_OID_set_desc(xdrs, set))
153184588Sdfr				return (FALSE);
154184588Sdfr		} else {
155184588Sdfr			is_null = TRUE;
156184588Sdfr			if (!xdr_bool(xdrs, &is_null))
157184588Sdfr				return (FALSE);
158184588Sdfr		}
159184588Sdfr		break;
160184588Sdfr
161184588Sdfr	case XDR_DECODE:
162184588Sdfr		if (!xdr_bool(xdrs, &is_null))
163184588Sdfr			return (FALSE);
164184588Sdfr		if (is_null) {
165184588Sdfr			*setp = GSS_C_NO_OID_SET;
166184588Sdfr		} else {
167184588Sdfr			set = mem_alloc(sizeof(gss_OID_set_desc));
168184588Sdfr			memset(set, 0, sizeof(*set));
169298655Scem			if (!xdr_gss_OID_set_desc(xdrs, set)) {
170298655Scem				mem_free(set, sizeof(gss_OID_set_desc));
171184588Sdfr				return (FALSE);
172298655Scem			}
173184588Sdfr			*setp = set;
174184588Sdfr		}
175184588Sdfr		break;
176184588Sdfr
177184588Sdfr	case XDR_FREE:
178184588Sdfr		set = *setp;
179184588Sdfr		if (set) {
180184588Sdfr			xdr_gss_OID_set_desc(xdrs, set);
181184588Sdfr			mem_free(set, sizeof(gss_OID_set_desc));
182184588Sdfr		}
183184588Sdfr	}
184184588Sdfr
185184588Sdfr	return (TRUE);
186184588Sdfr}
187184588Sdfr
188184588Sdfrbool_t
189184588Sdfrxdr_gss_channel_bindings_t(XDR *xdrs, gss_channel_bindings_t *chp)
190184588Sdfr{
191184588Sdfr	gss_channel_bindings_t ch;
192184588Sdfr	bool_t is_null;
193184588Sdfr
194184588Sdfr	switch (xdrs->x_op) {
195184588Sdfr	case XDR_ENCODE:
196184588Sdfr		ch = *chp;
197184588Sdfr		if (ch) {
198184588Sdfr			is_null = FALSE;
199184588Sdfr			if (!xdr_bool(xdrs, &is_null)
200184588Sdfr			    || !xdr_uint32_t(xdrs, &ch->initiator_addrtype)
201184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
202184588Sdfr				&ch->initiator_address)
203184588Sdfr			    || !xdr_uint32_t(xdrs, &ch->acceptor_addrtype)
204184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
205184588Sdfr				&ch->acceptor_address)
206184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
207184588Sdfr				&ch->application_data))
208184588Sdfr				return (FALSE);
209184588Sdfr		} else {
210184588Sdfr			is_null = TRUE;
211184588Sdfr			if (!xdr_bool(xdrs, &is_null))
212184588Sdfr				return (FALSE);
213184588Sdfr		}
214184588Sdfr		break;
215184588Sdfr
216184588Sdfr	case XDR_DECODE:
217184588Sdfr		if (!xdr_bool(xdrs, &is_null))
218184588Sdfr			return (FALSE);
219184588Sdfr		if (is_null) {
220184588Sdfr			*chp = GSS_C_NO_CHANNEL_BINDINGS;
221184588Sdfr		} else {
222184588Sdfr			ch = mem_alloc(sizeof(*ch));
223184588Sdfr			memset(ch, 0, sizeof(*ch));
224184588Sdfr			if (!xdr_uint32_t(xdrs, &ch->initiator_addrtype)
225184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
226184588Sdfr				&ch->initiator_address)
227184588Sdfr			    || !xdr_uint32_t(xdrs, &ch->acceptor_addrtype)
228184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
229184588Sdfr				&ch->acceptor_address)
230184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
231298655Scem				&ch->application_data)) {
232298655Scem				mem_free(ch, sizeof(*ch));
233184588Sdfr				return (FALSE);
234298655Scem			}
235184588Sdfr			*chp = ch;
236184588Sdfr		}
237184588Sdfr		break;
238184588Sdfr
239184588Sdfr	case XDR_FREE:
240184588Sdfr		ch = *chp;
241184588Sdfr		if (ch) {
242184588Sdfr			xdr_gss_buffer_desc(xdrs, &ch->initiator_address);
243184588Sdfr			xdr_gss_buffer_desc(xdrs, &ch->acceptor_address);
244184588Sdfr			xdr_gss_buffer_desc(xdrs, &ch->application_data);
245184588Sdfr			mem_free(ch, sizeof(*ch));
246184588Sdfr		}
247184588Sdfr	}
248184588Sdfr
249184588Sdfr	return (TRUE);
250184588Sdfr}
251