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 2010 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 <syslog.h>
31 #include <smbsrv/libsmb.h>
32 #include <smbsrv/smb_xdr.h>
33 #include <smbsrv/smb_door.h>
34 
35 
36 /*
37  * Generic XDR encoder.
38  *
39  * Returns a malloc'd, encoded buffer upon success.
40  * Otherwise, returns NULL.
41  */
42 char *
43 smb_common_encode(void *data, xdrproc_t proc, size_t *rsize)
44 {
45 	XDR	xdrs;
46 	char	*buf;
47 	size_t	len;
48 
49 	if (proc == NULL || data == NULL || rsize == NULL) {
50 		syslog(LOG_ERR, "smb_common_encode: invalid parameter");
51 		return (NULL);
52 	}
53 
54 	len = xdr_sizeof(proc, data);
55 
56 	if ((buf = malloc(len)) == NULL) {
57 		syslog(LOG_ERR, "smb_common_encode: %m");
58 		*rsize = 0;
59 		return (NULL);
60 	}
61 
62 	xdrmem_create(&xdrs, buf, len, XDR_ENCODE);
63 	*rsize = len;
64 
65 	if (!proc(&xdrs, data)) {
66 		syslog(LOG_DEBUG, "smb_common_encode: encode error");
67 		free(buf);
68 		buf = NULL;
69 		*rsize = 0;
70 	}
71 
72 	xdr_destroy(&xdrs);
73 	return (buf);
74 }
75 
76 /*
77  * Generic XDR decoder.  Ensure that data is non-null and bzero'd.
78  */
79 int
80 smb_common_decode(char *buf, size_t len, xdrproc_t proc, void *data)
81 {
82 	XDR xdrs;
83 	int rc = 0;
84 
85 	if (data == NULL)
86 		return (-1);
87 
88 	xdrmem_create(&xdrs, buf, len, XDR_DECODE);
89 	if (!proc(&xdrs, data))
90 		rc = -1;
91 
92 	xdr_destroy(&xdrs);
93 	return (rc);
94 }
95 
96 /*
97  * smb_kshare_mkselfrel
98  *
99  * encode: structure -> flat buffer (buffer size)
100  * Pre-condition: kshare is non-null.
101  */
102 uint8_t *
103 smb_kshare_mkselfrel(smb_dr_kshare_t *kshare, uint32_t *len)
104 {
105 	uint8_t *buf;
106 	XDR xdrs;
107 
108 	if (!kshare)
109 		return (NULL);
110 
111 	*len = xdr_sizeof(smb_dr_kshare_xdr, kshare);
112 	buf = (uint8_t *)malloc(*len);
113 	if (!buf)
114 		return (NULL);
115 
116 	xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE);
117 
118 	if (!smb_dr_kshare_xdr(&xdrs, kshare)) {
119 		*len = 0;
120 		free(buf);
121 		buf = NULL;
122 	}
123 
124 	xdr_destroy(&xdrs);
125 	return (buf);
126 }
127 
128 char *
129 smb_string_encode(char *s, size_t *rsize)
130 {
131 	smb_string_t	obj;
132 	XDR		xdrs;
133 	char		*buf = NULL;
134 	size_t		len;
135 
136 	if ((obj.buf = s) == NULL) {
137 		syslog(LOG_DEBUG, "smb_string_encode: invalid param");
138 		goto smb_string_encode_failed;
139 	}
140 
141 	len = xdr_sizeof(smb_string_xdr, &obj);
142 	if ((buf = calloc(len, 1)) == NULL) {
143 		syslog(LOG_DEBUG, "smb_string_encode: %m");
144 		goto smb_string_encode_failed;
145 	}
146 
147 	xdrmem_create(&xdrs, buf, len, XDR_ENCODE);
148 
149 	if (!smb_string_xdr(&xdrs, &obj)) {
150 		syslog(LOG_DEBUG, "smb_string_encode: encode failed");
151 		xdr_destroy(&xdrs);
152 		free(buf);
153 		goto smb_string_encode_failed;
154 	}
155 
156 	xdr_destroy(&xdrs);
157 	if (rsize)
158 		*rsize = len;
159 	return (buf);
160 
161 smb_string_encode_failed:
162 	if (rsize)
163 		*rsize = 0;
164 	return (NULL);
165 }
166 
167 int
168 smb_string_decode(smb_string_t *obj, char *buf, size_t buflen)
169 {
170 	XDR xdrs;
171 	int rc = 0;
172 
173 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
174 
175 	bzero(obj, sizeof (smb_string_t));
176 	if (!smb_string_xdr(&xdrs, obj))
177 		rc = -1;
178 
179 	xdr_destroy(&xdrs);
180 	return (rc);
181 }
182 
183 /*
184  * Encode an lsa_account_t into a buffer.
185  */
186 int
187 lsa_account_encode(lsa_account_t *acct, uint8_t *buf, uint32_t buflen)
188 {
189 	XDR xdrs;
190 	int rc = 0;
191 
192 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_ENCODE);
193 
194 	if (!lsa_account_xdr(&xdrs, acct))
195 		rc = -1;
196 
197 	xdr_destroy(&xdrs);
198 	return (rc);
199 }
200 
201 /*
202  * Decode an XDR buffer into an lsa_account_t.
203  */
204 int
205 lsa_account_decode(lsa_account_t *acct, uint8_t *buf, uint32_t buflen)
206 {
207 	XDR xdrs;
208 	int rc = 0;
209 
210 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
211 
212 	bzero(acct, sizeof (lsa_account_t));
213 	if (!lsa_account_xdr(&xdrs, acct))
214 		rc = -1;
215 
216 	xdr_destroy(&xdrs);
217 	return (rc);
218 }
219 
220 bool_t
221 lsa_account_xdr(XDR *xdrs, lsa_account_t *objp)
222 {
223 	if (!xdr_uint16_t(xdrs, &objp->a_sidtype))
224 		return (FALSE);
225 	if (!xdr_uint32_t(xdrs, &objp->a_status))
226 		return (FALSE);
227 	if (!xdr_vector(xdrs, (char *)objp->a_domain, MAXNAMELEN,
228 	    sizeof (char), (xdrproc_t)xdr_char))
229 		return (FALSE);
230 	if (!xdr_vector(xdrs, (char *)objp->a_name, MAXNAMELEN,
231 	    sizeof (char), (xdrproc_t)xdr_char))
232 		return (FALSE);
233 	if (!xdr_vector(xdrs, (char *)objp->a_sid, SMB_SID_STRSZ,
234 	    sizeof (char), (xdrproc_t)xdr_char))
235 		return (FALSE);
236 	return (TRUE);
237 }
238