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