xref: /onnv-gate/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c (revision 12508:edb7861a1533)
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 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * SMB ReadX functions.
28  */
29 
30 #include <strings.h>
31 
32 #include <smbsrv/libsmbrdr.h>
33 #include <smbsrv/netbios.h>
34 #include <smbrdr.h>
35 
36 #define	SMBRDR_READX_RSP_OVERHEAD \
37 	(NETBIOS_HDR_SZ + SMB_HEADER_LEN + sizeof (smb_read_andx_rsp_t))
38 #define	SMBRDR_READX_RSP_DATA_MAXLEN \
39 	(SMBRDR_REQ_BUFSZ - SMBRDR_READX_RSP_OVERHEAD)
40 
41 static int smbrdr_decode_readx_rsp(smb_msgbuf_t *, char *, unsigned,
42     smb_read_andx_rsp_t *);
43 
44 /*
45  * smbrdr_readx
46  *
47  * Send SMB_COM_READ_ANDX request.
48  */
49 int
smbrdr_readx(int fid,char * in_buf,int in_len)50 smbrdr_readx(int fid, char *in_buf, int in_len)
51 {
52 	struct sdb_netuse *netuse;
53 	struct sdb_ofile *ofile;
54 	smb_read_andx_rsp_t rsp;
55 	smbrdr_handle_t srh;
56 	smb_msgbuf_t *mb;
57 	DWORD status;
58 	int rc, max_return;
59 
60 	if ((ofile = smbrdr_ofile_get(fid)) == NULL)
61 		return (-1);
62 
63 	netuse = ofile->netuse;
64 
65 	status = smbrdr_request_init(&srh, SMB_COM_READ_ANDX,
66 	    netuse->session, &netuse->session->logon, netuse);
67 
68 	if (status != NT_STATUS_SUCCESS) {
69 		smb_log(smbrdr_log_hdl, LOG_DEBUG, "smbrdr_readx: %s",
70 		    xlate_nt_status(status));
71 		smbrdr_ofile_put(ofile);
72 		return (-1);
73 	}
74 
75 	mb = &(srh.srh_mbuf);
76 
77 	max_return = (in_len > SMBRDR_READX_RSP_DATA_MAXLEN) ?
78 	    SMBRDR_READX_RSP_DATA_MAXLEN : in_len;
79 
80 	rc = smb_msgbuf_encode(mb, "bbbwwlwwlwlw",
81 	    12,		/* Count of parameter words */
82 	    0xFF,	/* Secondary (X) command; 0xFF = none */
83 	    0,		/* Reserved (must be 0) */
84 	    0, 		/* Offset to next command WordCount */
85 	    ofile->fid,	/* File handle */
86 	    0,		/* Offset in file to begin read */
87 	    max_return,	/* Max number of bytes to return */
88 		/* Reserved for obsolescent requests [0 = non-blocking read] */
89 	    max_return,
90 		/*
91 		 * High 16 bits of MaxCount if CAP_LARGE_READX;
92 		 * else MUST BE ZERO
93 		 */
94 	    0,
95 	    max_return,	/* Reserved for obsolescent requests */
96 	    /* Upper 32 bits of offset (only if WordCount is 12) */
97 	    0,
98 	    0);		/* Count of data bytes = 0 */
99 
100 	if (rc < 0) {
101 		smb_log(smbrdr_log_hdl, LOG_DEBUG, "smbrdr_readx: prep failed");
102 		smbrdr_handle_free(&srh);
103 		smbrdr_ofile_put(ofile);
104 		return (rc);
105 	}
106 
107 	smbrdr_lock_transport();
108 
109 	status = smbrdr_send(&srh);
110 	if (status != NT_STATUS_SUCCESS) {
111 		smbrdr_unlock_transport();
112 		smbrdr_handle_free(&srh);
113 		smbrdr_ofile_put(ofile);
114 		smb_log(smbrdr_log_hdl, LOG_DEBUG, "smbrdr_readx: send failed");
115 		return (-1);
116 	}
117 
118 	status = smbrdr_rcv(&srh, 1);
119 
120 	if (status != NT_STATUS_SUCCESS) {
121 		smb_log(smbrdr_log_hdl, LOG_DEBUG,
122 		    "smbrdr_readx: nb_rcv failed");
123 		smbrdr_unlock_transport();
124 		smbrdr_handle_free(&srh);
125 		smbrdr_ofile_put(ofile);
126 		return (-1);
127 	}
128 
129 	rc = smbrdr_decode_readx_rsp(mb, in_buf, in_len, &rsp);
130 
131 	if (rc < 0) {
132 		smb_log(smbrdr_log_hdl, LOG_DEBUG,
133 		    "smbrdr_readx: decode failed");
134 		smbrdr_unlock_transport();
135 		smbrdr_handle_free(&srh);
136 		smbrdr_ofile_put(ofile);
137 		return (-1);
138 	}
139 
140 	smbrdr_unlock_transport();
141 	smbrdr_handle_free(&srh);
142 	smbrdr_ofile_put(ofile);
143 
144 	return ((rc < 0) ? rc : rsp.DataLength);
145 }
146 
147 /*
148  * smbrdr_decode_readx_rsp
149  *
150  * Decode the response from the SMB_COM_READ_ANDX request. The payload
151  * of the response is appended to the end of SmbTransact response data
152  * in the RPC receive buffer.
153  *
154  * Return -1 on error, 0 upon success.
155  */
156 static int
smbrdr_decode_readx_rsp(smb_msgbuf_t * mb,char * in,unsigned in_len,smb_read_andx_rsp_t * rsp)157 smbrdr_decode_readx_rsp(smb_msgbuf_t *mb,
158 			char *in,
159 			unsigned in_len,
160 			smb_read_andx_rsp_t *rsp)
161 {
162 	int rc;
163 
164 	rc = smb_msgbuf_decode(mb, "bbbwwwwwwlwwww",
165 	    &rsp->WordCount,
166 	    &rsp->AndXCmd,
167 	    &rsp->AndXReserved,
168 	    &rsp->AndXOffset,
169 	    &rsp->Remaining,
170 	    &rsp->DataCompactionMode,
171 	    &rsp->Reserved,
172 	    &rsp->DataLength,
173 	    &rsp->DataOffset,
174 	    &rsp->DataLengthHigh,
175 	    &rsp->Reserved2[0],
176 	    &rsp->Reserved2[1],
177 	    &rsp->Reserved2[2],
178 	    &rsp->ByteCount);
179 
180 	if (rc <= 0)
181 		return (-1);
182 
183 	if (rsp->DataLength > in_len)
184 		return (-1);
185 
186 	bcopy(mb->base + rsp->DataOffset, in, rsp->DataLength);
187 
188 	return (0);
189 }
190