xref: /freebsd/sys/kgssapi/gssd_prot.c (revision 4f52dfbb8d6c4d446500c5b097e3806ec219fbd4)
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 
45 bool_t
46 xdr_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 
61 bool_t
62 xdr_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 
77 bool_t
78 xdr_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 
125 bool_t
126 xdr_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 
142 bool_t
143 xdr_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 
190 bool_t
191 xdr_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