1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
5 * Authors: Doug Rabson <dfr@rabson.org>
6 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33#ifdef _KERNEL
34#include <sys/malloc.h>
35#else
36#include <stdlib.h>
37#include <string.h>
38#endif
39
40#include <rpc/rpc.h>
41#include <rpc/rpc_com.h>
42
43#include "gssd.h"
44
45bool_t
46xdr_gss_buffer_desc(XDR *xdrs, gss_buffer_desc *buf)
47{
48	char *val;
49	u_int len;
50
51	len = buf->length;
52	val = buf->value;
53	if (!xdr_bytes(xdrs, &val, &len, ~0))
54		return (FALSE);
55	buf->length = len;
56	buf->value = val;
57
58	return (TRUE);
59}
60
61bool_t
62xdr_gss_OID_desc(XDR *xdrs, gss_OID_desc *oid)
63{
64	char *val;
65	u_int len;
66
67	len = oid->length;
68	val = oid->elements;
69	if (!xdr_bytes(xdrs, &val, &len, ~0))
70		return (FALSE);
71	oid->length = len;
72	oid->elements = val;
73
74	return (TRUE);
75}
76
77bool_t
78xdr_gss_OID(XDR *xdrs, gss_OID *oidp)
79{
80	gss_OID oid;
81	bool_t is_null;
82
83	switch (xdrs->x_op) {
84	case XDR_ENCODE:
85		oid = *oidp;
86		if (oid) {
87			is_null = FALSE;
88			if (!xdr_bool(xdrs, &is_null)
89			    || !xdr_gss_OID_desc(xdrs, oid))
90				return (FALSE);
91		} else {
92			is_null = TRUE;
93			if (!xdr_bool(xdrs, &is_null))
94				return (FALSE);
95		}
96		break;
97
98	case XDR_DECODE:
99		if (!xdr_bool(xdrs, &is_null))
100			return (FALSE);
101		if (is_null) {
102			*oidp = GSS_C_NO_OID;
103		} else {
104			oid = mem_alloc(sizeof(gss_OID_desc));
105			memset(oid, 0, sizeof(*oid));
106			if (!xdr_gss_OID_desc(xdrs, oid)) {
107				mem_free(oid, sizeof(gss_OID_desc));
108				return (FALSE);
109			}
110			*oidp = oid;
111		}
112		break;
113
114	case XDR_FREE:
115		oid = *oidp;
116		if (oid) {
117			xdr_gss_OID_desc(xdrs, oid);
118			mem_free(oid, sizeof(gss_OID_desc));
119		}
120	}
121
122	return (TRUE);
123}
124
125bool_t
126xdr_gss_OID_set_desc(XDR *xdrs, gss_OID_set_desc *set)
127{
128	caddr_t addr;
129	u_int len;
130
131	len = set->count;
132	addr = (caddr_t) set->elements;
133	if (!xdr_array(xdrs, &addr, &len, ~0, sizeof(gss_OID_desc),
134		(xdrproc_t) xdr_gss_OID_desc))
135		return (FALSE);
136	set->count = len;
137	set->elements = (gss_OID) addr;
138
139	return (TRUE);
140}
141
142bool_t
143xdr_gss_OID_set(XDR *xdrs, gss_OID_set *setp)
144{
145	gss_OID_set set;
146	bool_t is_null;
147
148	switch (xdrs->x_op) {
149	case XDR_ENCODE:
150		set = *setp;
151		if (set) {
152			is_null = FALSE;
153			if (!xdr_bool(xdrs, &is_null)
154			    || !xdr_gss_OID_set_desc(xdrs, set))
155				return (FALSE);
156		} else {
157			is_null = TRUE;
158			if (!xdr_bool(xdrs, &is_null))
159				return (FALSE);
160		}
161		break;
162
163	case XDR_DECODE:
164		if (!xdr_bool(xdrs, &is_null))
165			return (FALSE);
166		if (is_null) {
167			*setp = GSS_C_NO_OID_SET;
168		} else {
169			set = mem_alloc(sizeof(gss_OID_set_desc));
170			memset(set, 0, sizeof(*set));
171			if (!xdr_gss_OID_set_desc(xdrs, set)) {
172				mem_free(set, sizeof(gss_OID_set_desc));
173				return (FALSE);
174			}
175			*setp = set;
176		}
177		break;
178
179	case XDR_FREE:
180		set = *setp;
181		if (set) {
182			xdr_gss_OID_set_desc(xdrs, set);
183			mem_free(set, sizeof(gss_OID_set_desc));
184		}
185	}
186
187	return (TRUE);
188}
189
190bool_t
191xdr_gss_channel_bindings_t(XDR *xdrs, gss_channel_bindings_t *chp)
192{
193	gss_channel_bindings_t ch;
194	bool_t is_null;
195
196	switch (xdrs->x_op) {
197	case XDR_ENCODE:
198		ch = *chp;
199		if (ch) {
200			is_null = FALSE;
201			if (!xdr_bool(xdrs, &is_null)
202			    || !xdr_uint32_t(xdrs, &ch->initiator_addrtype)
203			    || !xdr_gss_buffer_desc(xdrs,
204				&ch->initiator_address)
205			    || !xdr_uint32_t(xdrs, &ch->acceptor_addrtype)
206			    || !xdr_gss_buffer_desc(xdrs,
207				&ch->acceptor_address)
208			    || !xdr_gss_buffer_desc(xdrs,
209				&ch->application_data))
210				return (FALSE);
211		} else {
212			is_null = TRUE;
213			if (!xdr_bool(xdrs, &is_null))
214				return (FALSE);
215		}
216		break;
217
218	case XDR_DECODE:
219		if (!xdr_bool(xdrs, &is_null))
220			return (FALSE);
221		if (is_null) {
222			*chp = GSS_C_NO_CHANNEL_BINDINGS;
223		} else {
224			ch = mem_alloc(sizeof(*ch));
225			memset(ch, 0, sizeof(*ch));
226			if (!xdr_uint32_t(xdrs, &ch->initiator_addrtype)
227			    || !xdr_gss_buffer_desc(xdrs,
228				&ch->initiator_address)
229			    || !xdr_uint32_t(xdrs, &ch->acceptor_addrtype)
230			    || !xdr_gss_buffer_desc(xdrs,
231				&ch->acceptor_address)
232			    || !xdr_gss_buffer_desc(xdrs,
233				&ch->application_data)) {
234				mem_free(ch, sizeof(*ch));
235				return (FALSE);
236			}
237			*chp = ch;
238		}
239		break;
240
241	case XDR_FREE:
242		ch = *chp;
243		if (ch) {
244			xdr_gss_buffer_desc(xdrs, &ch->initiator_address);
245			xdr_gss_buffer_desc(xdrs, &ch->acceptor_address);
246			xdr_gss_buffer_desc(xdrs, &ch->application_data);
247			mem_free(ch, sizeof(*ch));
248		}
249	}
250
251	return (TRUE);
252}
253