1 /*
2    Unix SMB/CIFS implementation.
3 
4    SMB2 client library header
5 
6    Copyright (C) Andrew Tridgell 2005
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #ifndef __LIBCLI_SMB2_SMB2_H__
23 #define __LIBCLI_SMB2_SMB2_H__
24 
25 #include "libcli/raw/request.h"
26 #include "libcli/raw/libcliraw.h"
27 
28 struct smb2_handle;
29 struct smb2_lease_break;
30 
31 struct smb2_request_buffer {
32 	/* the raw SMB2 buffer, including the 4 byte length header */
33 	uint8_t *buffer;
34 
35 	/* the size of the raw buffer, including 4 byte header */
36 	size_t size;
37 
38 	/* how much has been allocated - on reply the buffer is over-allocated to
39 	   prevent too many realloc() calls
40 	*/
41 	size_t allocated;
42 
43 	/* the start of the SMB2 header - this is always buffer+4 */
44 	uint8_t *hdr;
45 
46 	/* the packet body */
47 	uint8_t *body;
48 	size_t body_fixed;
49 	size_t body_size;
50 
51 	/* this point to the next dynamic byte that can be used
52 	 * this will be moved when some dynamic data is pushed
53 	 */
54 	uint8_t *dynamic;
55 
56 	/* this is used to range check and align strings and buffers */
57 	struct request_bufinfo bufinfo;
58 };
59 
60 /* this is the context for the smb2 transport layer */
61 struct smb2_transport {
62 	struct tevent_context *ev; /* TODO: remove this !!! */
63 	struct smbXcli_conn *conn;
64 
65 	/* the details for coumpounded requests */
66 	struct {
67 		bool related;
68 		struct tevent_req **reqs;
69 	} compound;
70 
71 	/* an idle function - if this is defined then it will be
72 	   called once every period microseconds while we are waiting
73 	   for a packet */
74 	struct {
75 		void (*func)(struct smb2_transport *, void *);
76 		void *private_data;
77 		unsigned int period;
78 		struct tevent_timer *te;
79 	} idle;
80 
81 	struct {
82 		/* a oplock break request handler */
83 		bool (*handler)(struct smb2_transport *transport,
84 				const struct smb2_handle *handle,
85 				uint8_t level, void *private_data);
86 		/* private data passed to the oplock handler */
87 		void *private_data;
88 	} oplock;
89 
90 	struct {
91 		/* a lease break request handler */
92 		bool (*handler)(struct smb2_transport *transport,
93 				const struct smb2_lease_break *lease_break,
94 				void *private_data);
95 		/* private data passed to the oplock handler */
96 		void *private_data;
97 	} lease;
98 	struct tevent_req *break_subreq;
99 
100 	struct smbcli_options options;
101 };
102 
103 
104 /*
105   SMB2 tree context
106 */
107 struct smb2_tree {
108 	struct smb2_session *session;
109 	struct smbXcli_tcon *smbXcli;
110 };
111 
112 /*
113   SMB2 session context
114 */
115 struct smb2_session {
116 	struct smb2_transport *transport;
117 	struct gensec_security *gensec;
118 	struct smbXcli_session *smbXcli;
119 	bool needs_bind;
120 };
121 
122 
123 
124 /*
125   a client request moves between the following 4 states.
126 */
127 enum smb2_request_state {SMB2_REQUEST_INIT, /* we are creating the request */
128 			SMB2_REQUEST_RECV, /* we are waiting for a matching reply */
129 			SMB2_REQUEST_DONE, /* the request is finished */
130 			SMB2_REQUEST_ERROR}; /* a packet or transport level error has occurred */
131 
132 /* the context for a single SMB2 request */
133 struct smb2_request {
134 	/* each request is in one of 3 possible states */
135 	enum smb2_request_state state;
136 
137 	struct tevent_req *subreq;
138 
139 	struct smb2_transport *transport;
140 	struct smb2_session   *session;
141 	struct smb2_tree      *tree;
142 
143 	struct {
144 		bool can_cancel;
145 	} cancel;
146 
147 	/* the NT status for this request. Set by packet receive code
148 	   or code detecting error. */
149 	NTSTATUS status;
150 
151 	struct smb2_request_buffer in;
152 	struct smb2_request_buffer out;
153 	struct iovec *recv_iov;
154 
155 	uint16_t credit_charge;
156 
157 	/* information on what to do with a reply when it is received
158 	   asyncronously. If this is not setup when a reply is received then
159 	   the reply is discarded
160 
161 	   The private pointer is private to the caller of the client
162 	   library (the application), not private to the library
163 	*/
164 	struct {
165 		void (*fn)(struct smb2_request *);
166 		void *private_data;
167 	} async;
168 };
169 
170 
171 #define SMB2_MIN_SIZE 0x42
172 #define SMB2_MIN_SIZE_NO_BODY 0x40
173 
174 /*
175   check that a body has the expected size
176 */
177 #define SMB2_CHECK_PACKET_RECV(req, size, dynamic) do { \
178 	size_t is_size = req->in.body_size; \
179 	uint16_t field_size = SVAL(req->in.body, 0); \
180 	uint16_t want_size = ((dynamic)?(size)+1:(size)); \
181 	if (is_size < (size)) { \
182 		DEBUG(0,("%s: buffer too small 0x%x. Expected 0x%x\n", \
183 			 __location__, (unsigned)is_size, (unsigned)want_size)); \
184 		return NT_STATUS_BUFFER_TOO_SMALL; \
185 	}\
186 	if (field_size != want_size) { \
187 		DEBUG(0,("%s: unexpected fixed body size 0x%x. Expected 0x%x\n", \
188 			 __location__, (unsigned)field_size, (unsigned)want_size)); \
189 		return NT_STATUS_INVALID_PARAMETER; \
190 	} \
191 } while (0)
192 
193 #endif
194