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