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));
104184588Sdfr			if (!xdr_gss_OID_desc(xdrs, oid))
105184588Sdfr				return (FALSE);
106184588Sdfr			*oidp = oid;
107184588Sdfr		}
108184588Sdfr		break;
109184588Sdfr
110184588Sdfr	case XDR_FREE:
111184588Sdfr		oid = *oidp;
112184588Sdfr		if (oid) {
113184588Sdfr			xdr_gss_OID_desc(xdrs, oid);
114184588Sdfr			mem_free(oid, sizeof(gss_OID_desc));
115184588Sdfr		}
116184588Sdfr	}
117184588Sdfr
118184588Sdfr	return (TRUE);
119184588Sdfr}
120184588Sdfr
121184588Sdfrbool_t
122184588Sdfrxdr_gss_OID_set_desc(XDR *xdrs, gss_OID_set_desc *set)
123184588Sdfr{
124184588Sdfr	caddr_t addr;
125184588Sdfr	u_int len;
126184588Sdfr
127184588Sdfr	len = set->count;
128184588Sdfr	addr = (caddr_t) set->elements;
129184588Sdfr	if (!xdr_array(xdrs, &addr, &len, ~0, sizeof(gss_OID_desc),
130184588Sdfr		(xdrproc_t) xdr_gss_OID_desc))
131184588Sdfr		return (FALSE);
132184588Sdfr	set->count = len;
133184588Sdfr	set->elements = (gss_OID) addr;
134184588Sdfr
135184588Sdfr	return (TRUE);
136184588Sdfr}
137184588Sdfr
138184588Sdfrbool_t
139184588Sdfrxdr_gss_OID_set(XDR *xdrs, gss_OID_set *setp)
140184588Sdfr{
141184588Sdfr	gss_OID_set set;
142184588Sdfr	bool_t is_null;
143184588Sdfr
144184588Sdfr	switch (xdrs->x_op) {
145184588Sdfr	case XDR_ENCODE:
146184588Sdfr		set = *setp;
147184588Sdfr		if (set) {
148184588Sdfr			is_null = FALSE;
149184588Sdfr			if (!xdr_bool(xdrs, &is_null)
150184588Sdfr			    || !xdr_gss_OID_set_desc(xdrs, set))
151184588Sdfr				return (FALSE);
152184588Sdfr		} else {
153184588Sdfr			is_null = TRUE;
154184588Sdfr			if (!xdr_bool(xdrs, &is_null))
155184588Sdfr				return (FALSE);
156184588Sdfr		}
157184588Sdfr		break;
158184588Sdfr
159184588Sdfr	case XDR_DECODE:
160184588Sdfr		if (!xdr_bool(xdrs, &is_null))
161184588Sdfr			return (FALSE);
162184588Sdfr		if (is_null) {
163184588Sdfr			*setp = GSS_C_NO_OID_SET;
164184588Sdfr		} else {
165184588Sdfr			set = mem_alloc(sizeof(gss_OID_set_desc));
166184588Sdfr			memset(set, 0, sizeof(*set));
167184588Sdfr			if (!xdr_gss_OID_set_desc(xdrs, set))
168184588Sdfr				return (FALSE);
169184588Sdfr			*setp = set;
170184588Sdfr		}
171184588Sdfr		break;
172184588Sdfr
173184588Sdfr	case XDR_FREE:
174184588Sdfr		set = *setp;
175184588Sdfr		if (set) {
176184588Sdfr			xdr_gss_OID_set_desc(xdrs, set);
177184588Sdfr			mem_free(set, sizeof(gss_OID_set_desc));
178184588Sdfr		}
179184588Sdfr	}
180184588Sdfr
181184588Sdfr	return (TRUE);
182184588Sdfr}
183184588Sdfr
184184588Sdfrbool_t
185184588Sdfrxdr_gss_channel_bindings_t(XDR *xdrs, gss_channel_bindings_t *chp)
186184588Sdfr{
187184588Sdfr	gss_channel_bindings_t ch;
188184588Sdfr	bool_t is_null;
189184588Sdfr
190184588Sdfr	switch (xdrs->x_op) {
191184588Sdfr	case XDR_ENCODE:
192184588Sdfr		ch = *chp;
193184588Sdfr		if (ch) {
194184588Sdfr			is_null = FALSE;
195184588Sdfr			if (!xdr_bool(xdrs, &is_null)
196184588Sdfr			    || !xdr_uint32_t(xdrs, &ch->initiator_addrtype)
197184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
198184588Sdfr				&ch->initiator_address)
199184588Sdfr			    || !xdr_uint32_t(xdrs, &ch->acceptor_addrtype)
200184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
201184588Sdfr				&ch->acceptor_address)
202184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
203184588Sdfr				&ch->application_data))
204184588Sdfr				return (FALSE);
205184588Sdfr		} else {
206184588Sdfr			is_null = TRUE;
207184588Sdfr			if (!xdr_bool(xdrs, &is_null))
208184588Sdfr				return (FALSE);
209184588Sdfr		}
210184588Sdfr		break;
211184588Sdfr
212184588Sdfr	case XDR_DECODE:
213184588Sdfr		if (!xdr_bool(xdrs, &is_null))
214184588Sdfr			return (FALSE);
215184588Sdfr		if (is_null) {
216184588Sdfr			*chp = GSS_C_NO_CHANNEL_BINDINGS;
217184588Sdfr		} else {
218184588Sdfr			ch = mem_alloc(sizeof(*ch));
219184588Sdfr			memset(ch, 0, sizeof(*ch));
220184588Sdfr			if (!xdr_uint32_t(xdrs, &ch->initiator_addrtype)
221184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
222184588Sdfr				&ch->initiator_address)
223184588Sdfr			    || !xdr_uint32_t(xdrs, &ch->acceptor_addrtype)
224184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
225184588Sdfr				&ch->acceptor_address)
226184588Sdfr			    || !xdr_gss_buffer_desc(xdrs,
227184588Sdfr				&ch->application_data))
228184588Sdfr				return (FALSE);
229184588Sdfr			*chp = ch;
230184588Sdfr		}
231184588Sdfr		break;
232184588Sdfr
233184588Sdfr	case XDR_FREE:
234184588Sdfr		ch = *chp;
235184588Sdfr		if (ch) {
236184588Sdfr			xdr_gss_buffer_desc(xdrs, &ch->initiator_address);
237184588Sdfr			xdr_gss_buffer_desc(xdrs, &ch->acceptor_address);
238184588Sdfr			xdr_gss_buffer_desc(xdrs, &ch->application_data);
239184588Sdfr			mem_free(ch, sizeof(*ch));
240184588Sdfr		}
241184588Sdfr	}
242184588Sdfr
243184588Sdfr	return (TRUE);
244184588Sdfr}
245