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