xref: /illumos-gate/usr/src/lib/smbsrv/libsmb/common/smb_door_encdec.c (revision 8d96b23e24cf8db8618f698bfa580a25d7dc6029)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdlib.h>
27 #include <strings.h>
28 #include <rpc/xdr.h>
29 #include <errno.h>
30 #include <smbsrv/libsmb.h>
31 #include <smbsrv/smb_xdr.h>
32 #include <smbsrv/smb_common_door.h>
33 #include <smbsrv/smb_door_svc.h>
34 
35 /*
36  * smb_dr_decode_common
37  *
38  * This function can be used to decode both door request and result buffer.
39  * pre-condition: data is non-null pointer, and is bzero'd.
40  */
41 int
42 smb_dr_decode_common(char *buf, size_t len, xdrproc_t proc, void *data)
43 {
44 	XDR xdrs;
45 	int rc = 0;
46 
47 	if (!data)
48 		return (-1);
49 
50 	xdrmem_create(&xdrs, buf, len, XDR_DECODE);
51 	if (!proc(&xdrs, data))
52 		rc = -1;
53 
54 	xdr_destroy(&xdrs);
55 	return (rc);
56 }
57 
58 /*
59  * smb_dr_encode_common
60  *
61  * This function can be used to encode both request and result door buffer.
62  * The 'opcode' paramater is set to the 'opcode' of the operation to be invoked
63  * on the server, by the client. The server sets the same 'opcode' paramater
64  * to indicate the 'status' of the door call.
65  *
66  * This function will first encode integer value 'opcode' (opcode/status),
67  * followed by the data (which will be encoded via the specified XDR routine).
68  *
69  * Returns encoded buffer upon success. Otherwise, returns NULL.
70  */
71 char *
72 smb_dr_encode_common(uint_t opcode, void *data, xdrproc_t proc, size_t *len)
73 {
74 	XDR xdrs;
75 	char *buf;
76 
77 	if (proc && !data) {
78 		syslog(LOG_ERR, "smb_dr_encode_common: invalid param");
79 		*len = 0;
80 		return (NULL);
81 	}
82 
83 	*len = xdr_sizeof(xdr_uint32_t, &opcode);
84 	if (proc)
85 		*len += xdr_sizeof(proc, data);
86 	buf = (char *)malloc(*len);
87 	if (!buf) {
88 		syslog(LOG_ERR, "smb_dr_encode_common: resource shortage");
89 		*len = 0;
90 		return (NULL);
91 	}
92 	xdrmem_create(&xdrs, buf, *len, XDR_ENCODE);
93 	if (!xdr_uint32_t(&xdrs, &opcode)) {
94 		syslog(LOG_DEBUG, "smb_dr_encode_common: encode error 1");
95 		free(buf);
96 		*len = 0;
97 		xdr_destroy(&xdrs);
98 		return (NULL);
99 	}
100 
101 	if (proc && !proc(&xdrs, data)) {
102 		syslog(LOG_DEBUG, "smb_dr_encode_common: encode error 2");
103 		free(buf);
104 		buf = NULL;
105 		*len = 0;
106 	}
107 
108 	xdr_destroy(&xdrs);
109 	return (buf);
110 }
111 
112 /*
113  * Get the opcode of the door argument buffer.
114  */
115 int
116 smb_dr_get_opcode(char *argp, size_t arg_size)
117 {
118 	int opcode;
119 
120 	if (smb_dr_decode_common(argp, arg_size, xdr_uint32_t, &opcode) != 0)
121 		opcode = -1;
122 	return (opcode);
123 }
124 
125 /*
126  * Set the opcode of the door argument buffer.
127  */
128 char *
129 smb_dr_set_opcode(uint32_t opcode, size_t *len)
130 {
131 	char *buf;
132 
133 	buf = smb_dr_encode_common(opcode, NULL, NULL, len);
134 	return (buf);
135 }
136 
137 /*
138  * Get the status of the door result buffer.
139  */
140 int
141 smb_dr_get_res_stat(char *rbufp, size_t rbuf_size)
142 {
143 	int status;
144 
145 	if (smb_dr_decode_common(rbufp, rbuf_size, xdr_uint32_t, &status) != 0)
146 		status = -1;
147 
148 	return (status);
149 }
150 
151 /*
152  * Set the status of the door result buffer.
153  */
154 char *
155 smb_dr_set_res_stat(uint32_t stat, size_t *len)
156 {
157 	char *buf;
158 
159 	buf = smb_dr_encode_common(stat, NULL, NULL, len);
160 	return (buf);
161 }
162 
163 char *
164 smb_dr_encode_res_token(smb_token_t *token, size_t *len)
165 {
166 	smb_dr_bytes_t res;
167 	char *buf = NULL;
168 
169 	res.bytes_val = smb_token_mkselfrel(token, &res.bytes_len);
170 	if (!res.bytes_val) {
171 		syslog(LOG_ERR, "smb_dr_encode_res_token: mkselfrel error");
172 		*len = 0;
173 		return (NULL);
174 	}
175 
176 	if ((buf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &res,
177 	    xdr_smb_dr_bytes_t, len)) == NULL) {
178 		syslog(LOG_ERR, "smb_dr_encode_res_token: failed");
179 		*len = 0;
180 		free(res.bytes_val);
181 		return (NULL);
182 
183 	}
184 	free(res.bytes_val);
185 	return (buf);
186 }
187 
188 char *
189 smb_dr_encode_kshare(smb_dr_kshare_t *kshare, size_t *buflen)
190 {
191 	smb_dr_bytes_t res;
192 	char *buf = NULL;
193 
194 	res.bytes_val = smb_kshare_mkselfrel(kshare, &res.bytes_len);
195 	if (!res.bytes_val)
196 		return (NULL);
197 
198 	buf = smb_dr_encode_common(SMB_KDR_SHARE, &res, xdr_smb_dr_bytes_t,
199 	    buflen);
200 
201 	free(res.bytes_val);
202 	return (buf);
203 }
204 
205 /*
206  * smb_kshare_mkselfrel
207  *
208  * encode: structure -> flat buffer (buffer size)
209  * Pre-condition: kshare is non-null.
210  */
211 
212 uint8_t *
213 smb_kshare_mkselfrel(smb_dr_kshare_t *kshare, uint32_t *len)
214 {
215 	uint8_t *buf;
216 	XDR xdrs;
217 
218 	if (!kshare)
219 		return (NULL);
220 
221 	*len = xdr_sizeof(xdr_smb_dr_kshare_t, kshare);
222 	buf = (uint8_t *)malloc(*len);
223 	if (!buf)
224 		return (NULL);
225 
226 	xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE);
227 
228 	if (!xdr_smb_dr_kshare_t(&xdrs, kshare)) {
229 		*len = 0;
230 		free(buf);
231 		buf = NULL;
232 	}
233 
234 	xdr_destroy(&xdrs);
235 	return (buf);
236 }
237 
238 char *
239 smb_dr_encode_string(uint32_t opcode, char *str, size_t *len)
240 {
241 	char *buf;
242 	smb_dr_string_t res;
243 
244 	res.buf = str;
245 
246 	if ((buf = smb_dr_encode_common(opcode, &res,
247 	    xdr_smb_dr_string_t, len)) == NULL)
248 		syslog(LOG_ERR, "smb_dr_encode_string: failed");
249 	return (buf);
250 }
251 
252 char *
253 smb_dr_decode_string(char *buf, size_t len)
254 {
255 	smb_dr_string_t res;
256 	char *str = NULL;
257 
258 	bzero(&res, sizeof (smb_dr_string_t));
259 	if (smb_dr_decode_common(buf, len, xdr_smb_dr_string_t,
260 	    &res) == 0) {
261 		str = res.buf;
262 	} else {
263 		syslog(LOG_ERR, "smb_dr_decode_string: failed");
264 	}
265 	return (str);
266 }
267 
268 netr_client_t *
269 smb_dr_decode_arg_get_token(char *buf, size_t len)
270 {
271 	smb_dr_bytes_t arg;
272 	netr_client_t *clnt_info;
273 
274 	bzero(&arg, sizeof (smb_dr_bytes_t));
275 	if (smb_dr_decode_common(buf, len, xdr_smb_dr_bytes_t, &arg)
276 	    != 0) {
277 		syslog(LOG_ERR, "smb_dr_decode_arg_get_token: failed");
278 		xdr_free(xdr_smb_dr_bytes_t, (char *)&arg);
279 		return (NULL);
280 	}
281 	clnt_info = netr_client_mkabsolute(arg.bytes_val,
282 	    arg.bytes_len);
283 	xdr_free(xdr_smb_dr_bytes_t, (char *)&arg);
284 	return (clnt_info);
285 }
286 
287 void
288 smb_dr_ulist_free(smb_dr_ulist_t *ulist)
289 {
290 	int i;
291 	smb_opipe_context_t *uinfo;
292 
293 	if (!ulist)
294 		return;
295 
296 	for (i = 0; i < ulist->dul_cnt; i++) {
297 		uinfo = &ulist->dul_users[i];
298 
299 		if (!uinfo)
300 			continue;
301 
302 		xdr_free(xdr_smb_dr_ulist_t, (char *)ulist);
303 	}
304 
305 	free(ulist);
306 }
307