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