/src/samba/source3/smbd/smb2_process.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | process incoming packets - main loop |
4 | | Copyright (C) Andrew Tridgell 1992-1998 |
5 | | Copyright (C) Volker Lendecke 2005-2007 |
6 | | |
7 | | This program is free software; you can redistribute it and/or modify |
8 | | it under the terms of the GNU General Public License as published by |
9 | | the Free Software Foundation; either version 3 of the License, or |
10 | | (at your option) any later version. |
11 | | |
12 | | This program is distributed in the hope that it will be useful, |
13 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | GNU General Public License for more details. |
16 | | |
17 | | You should have received a copy of the GNU General Public License |
18 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include "includes.h" |
22 | | #include "../lib/tsocket/tsocket.h" |
23 | | #include "system/filesys.h" |
24 | | #include "smbd/smbd.h" |
25 | | #include "smbd/globals.h" |
26 | | #include "source3/smbd/smbXsrv_session.h" |
27 | | #include "smbd/smbXsrv_open.h" |
28 | | #include "librpc/gen_ndr/netlogon.h" |
29 | | #include "../lib/async_req/async_sock.h" |
30 | | #include "ctdbd_conn.h" |
31 | | #include "../lib/util/select.h" |
32 | | #include "printing/queue_process.h" |
33 | | #include "system/select.h" |
34 | | #include "passdb.h" |
35 | | #include "auth.h" |
36 | | #include "messages.h" |
37 | | #include "lib/messages_ctdb.h" |
38 | | #include "smbprofile.h" |
39 | | #include "rpc_server/spoolss/srv_spoolss_nt.h" |
40 | | #include "../lib/util/tevent_ntstatus.h" |
41 | | #include "../libcli/security/dom_sid.h" |
42 | | #include "../libcli/security/security_token.h" |
43 | | #include "lib/id_cache.h" |
44 | | #include "lib/util/sys_rw_data.h" |
45 | | #include "system/threads.h" |
46 | | #include "lib/pthreadpool/pthreadpool_tevent.h" |
47 | | #include "util_event.h" |
48 | | #include "libcli/smb/smbXcli_base.h" |
49 | | #include "lib/util/time_basic.h" |
50 | | #include "source3/lib/substitute.h" |
51 | | #include "source3/smbd/dir.h" |
52 | | |
53 | | /* Internal message queue for deferred opens. */ |
54 | | struct pending_message_list { |
55 | | struct pending_message_list *next, *prev; |
56 | | struct timeval request_time; /* When was this first issued? */ |
57 | | struct smbd_server_connection *sconn; |
58 | | struct smbXsrv_connection *xconn; |
59 | | struct tevent_timer *te; |
60 | | uint32_t seqnum; |
61 | | bool encrypted; |
62 | | bool processed; |
63 | | DATA_BLOB buf; |
64 | | struct deferred_open_record *open_rec; |
65 | | }; |
66 | | |
67 | | static struct pending_message_list *get_deferred_open_message_smb( |
68 | | struct smbd_server_connection *sconn, uint64_t mid); |
69 | | |
70 | | #if !defined(WITH_SMB1SERVER) |
71 | | bool smb1_srv_send(struct smbXsrv_connection *xconn, |
72 | | char *buffer, |
73 | | bool do_signing, |
74 | | uint32_t seqnum, |
75 | | bool do_encrypt) |
76 | | { |
77 | | size_t len = 0; |
78 | | ssize_t ret; |
79 | | len = smb_len_large(buffer) + 4; |
80 | | ret = write_data(xconn->transport.sock, buffer, len); |
81 | | return (ret > 0); |
82 | | } |
83 | | #endif |
84 | | |
85 | | /******************************************************************* |
86 | | Setup the word count and byte count for a smb1 message. |
87 | | ********************************************************************/ |
88 | | |
89 | | size_t srv_smb1_set_message(char *buf, |
90 | | size_t num_words, |
91 | | size_t num_bytes, |
92 | | bool zero) |
93 | 0 | { |
94 | 0 | if (zero && (num_words || num_bytes)) { |
95 | 0 | memset(buf + smb_size,'\0',num_words*2 + num_bytes); |
96 | 0 | } |
97 | 0 | SCVAL(buf,smb_wct,num_words); |
98 | 0 | SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); |
99 | 0 | smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4)); |
100 | 0 | return (smb_size + num_words*2 + num_bytes); |
101 | 0 | } |
102 | | |
103 | | NTSTATUS read_packet_remainder(int fd, char *buffer, |
104 | | unsigned int timeout, ssize_t len) |
105 | 0 | { |
106 | 0 | NTSTATUS status; |
107 | |
|
108 | 0 | if (len <= 0) { |
109 | 0 | return NT_STATUS_OK; |
110 | 0 | } |
111 | | |
112 | 0 | status = read_fd_with_timeout(fd, buffer, len, len, timeout, NULL); |
113 | 0 | if (!NT_STATUS_IS_OK(status)) { |
114 | 0 | char addr[INET6_ADDRSTRLEN]; |
115 | 0 | DEBUG(0, ("read_fd_with_timeout failed for client %s read " |
116 | 0 | "error = %s.\n", |
117 | 0 | get_peer_addr(fd, addr, sizeof(addr)), |
118 | 0 | nt_errstr(status))); |
119 | 0 | } |
120 | 0 | return status; |
121 | 0 | } |
122 | | |
123 | | #if !defined(WITH_SMB1SERVER) |
124 | | static NTSTATUS smb2_receive_raw_talloc(TALLOC_CTX *mem_ctx, |
125 | | struct smbXsrv_connection *xconn, |
126 | | int sock, |
127 | | char **buffer, unsigned int timeout, |
128 | | size_t *p_unread, size_t *plen) |
129 | | { |
130 | | char lenbuf[4]; |
131 | | size_t len; |
132 | | NTSTATUS status; |
133 | | |
134 | | *p_unread = 0; |
135 | | |
136 | | status = read_smb_length_return_keepalive(sock, lenbuf, timeout, |
137 | | &len); |
138 | | if (!NT_STATUS_IS_OK(status)) { |
139 | | return status; |
140 | | } |
141 | | |
142 | | /* |
143 | | * The +4 here can't wrap, we've checked the length above already. |
144 | | */ |
145 | | |
146 | | *buffer = talloc_array(mem_ctx, char, len+4); |
147 | | |
148 | | if (*buffer == NULL) { |
149 | | DEBUG(0, ("Could not allocate inbuf of length %d\n", |
150 | | (int)len+4)); |
151 | | return NT_STATUS_NO_MEMORY; |
152 | | } |
153 | | |
154 | | memcpy(*buffer, lenbuf, sizeof(lenbuf)); |
155 | | |
156 | | status = read_packet_remainder(sock, (*buffer)+4, timeout, len); |
157 | | if (!NT_STATUS_IS_OK(status)) { |
158 | | return status; |
159 | | } |
160 | | |
161 | | *plen = len + 4; |
162 | | return NT_STATUS_OK; |
163 | | } |
164 | | |
165 | | static NTSTATUS smb2_receive_talloc(TALLOC_CTX *mem_ctx, |
166 | | struct smbXsrv_connection *xconn, |
167 | | int sock, |
168 | | char **buffer, unsigned int timeout, |
169 | | size_t *p_unread, bool *p_encrypted, |
170 | | size_t *p_len, |
171 | | uint32_t *seqnum, |
172 | | bool trusted_channel) |
173 | | { |
174 | | size_t len = 0; |
175 | | NTSTATUS status; |
176 | | |
177 | | *p_encrypted = false; |
178 | | |
179 | | status = smb2_receive_raw_talloc(mem_ctx, xconn, sock, buffer, timeout, |
180 | | p_unread, &len); |
181 | | if (!NT_STATUS_IS_OK(status)) { |
182 | | DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1, |
183 | | ("smb2_receive_raw_talloc failed for client %s " |
184 | | "read error = %s.\n", |
185 | | smbXsrv_connection_dbg(xconn), |
186 | | nt_errstr(status)) ); |
187 | | return status; |
188 | | } |
189 | | |
190 | | *p_len = len; |
191 | | return NT_STATUS_OK; |
192 | | } |
193 | | #endif |
194 | | |
195 | | NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, |
196 | | struct smbXsrv_connection *xconn, |
197 | | int sock, |
198 | | char **buffer, unsigned int timeout, |
199 | | size_t *p_unread, bool *p_encrypted, |
200 | | size_t *p_len, |
201 | | uint32_t *seqnum, |
202 | | bool trusted_channel) |
203 | 0 | { |
204 | 0 | #if defined(WITH_SMB1SERVER) |
205 | 0 | return smb1_receive_talloc(mem_ctx, xconn, sock, buffer, timeout, |
206 | 0 | p_unread, p_encrypted, p_len, seqnum, |
207 | 0 | trusted_channel); |
208 | | #else |
209 | | return smb2_receive_talloc(mem_ctx, xconn, sock, buffer, timeout, |
210 | | p_unread, p_encrypted, p_len, seqnum, |
211 | | trusted_channel); |
212 | | #endif |
213 | 0 | } |
214 | | |
215 | | /**************************************************************************** |
216 | | Function to delete a sharing violation open message by mid. |
217 | | ****************************************************************************/ |
218 | | |
219 | | void remove_deferred_open_message_smb(struct smbXsrv_connection *xconn, |
220 | | uint64_t mid) |
221 | 0 | { |
222 | 0 | struct smbd_server_connection *sconn = xconn->client->sconn; |
223 | 0 | struct pending_message_list *pml; |
224 | |
|
225 | 0 | if (conn_using_smb2(sconn)) { |
226 | 0 | remove_deferred_open_message_smb2(xconn, mid); |
227 | 0 | return; |
228 | 0 | } |
229 | | |
230 | 0 | for (pml = sconn->deferred_open_queue; pml; pml = pml->next) { |
231 | 0 | if (mid == (uint64_t)SVAL(pml->buf.data,smb_mid)) { |
232 | 0 | DEBUG(10,("remove_deferred_open_message_smb: " |
233 | 0 | "deleting mid %llu len %u\n", |
234 | 0 | (unsigned long long)mid, |
235 | 0 | (unsigned int)pml->buf.length )); |
236 | 0 | DLIST_REMOVE(sconn->deferred_open_queue, pml); |
237 | 0 | TALLOC_FREE(pml); |
238 | 0 | return; |
239 | 0 | } |
240 | 0 | } |
241 | 0 | } |
242 | | |
243 | | static void smbd_deferred_open_timer(struct tevent_context *ev, |
244 | | struct tevent_timer *te, |
245 | | struct timeval _tval, |
246 | | void *private_data) |
247 | 0 | { |
248 | 0 | struct pending_message_list *msg = talloc_get_type(private_data, |
249 | 0 | struct pending_message_list); |
250 | 0 | struct smbd_server_connection *sconn = msg->sconn; |
251 | 0 | struct smbXsrv_connection *xconn = msg->xconn; |
252 | 0 | TALLOC_CTX *mem_ctx = talloc_tos(); |
253 | 0 | uint64_t mid = (uint64_t)SVAL(msg->buf.data,smb_mid); |
254 | 0 | uint8_t *inbuf; |
255 | |
|
256 | 0 | inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data, |
257 | 0 | msg->buf.length); |
258 | 0 | if (inbuf == NULL) { |
259 | 0 | exit_server("smbd_deferred_open_timer: talloc failed\n"); |
260 | 0 | return; |
261 | 0 | } |
262 | | |
263 | | /* We leave this message on the queue so the open code can |
264 | | know this is a retry. */ |
265 | 0 | DEBUG(5,("smbd_deferred_open_timer: trigger mid %llu.\n", |
266 | 0 | (unsigned long long)mid )); |
267 | | |
268 | | /* Mark the message as processed so this is not |
269 | | * re-processed in error. */ |
270 | 0 | msg->processed = true; |
271 | |
|
272 | 0 | process_smb(xconn, |
273 | 0 | inbuf, |
274 | 0 | msg->buf.length, |
275 | 0 | 0, |
276 | 0 | msg->seqnum, |
277 | 0 | msg->encrypted); |
278 | | |
279 | | /* If it's still there and was processed, remove it. */ |
280 | 0 | msg = get_deferred_open_message_smb(sconn, mid); |
281 | 0 | if (msg && msg->processed) { |
282 | 0 | remove_deferred_open_message_smb(xconn, mid); |
283 | 0 | } |
284 | 0 | } |
285 | | |
286 | | /**************************************************************************** |
287 | | Move a sharing violation open retry message to the front of the list and |
288 | | schedule it for immediate processing. |
289 | | ****************************************************************************/ |
290 | | |
291 | | bool schedule_deferred_open_message_smb(struct smbXsrv_connection *xconn, |
292 | | uint64_t mid) |
293 | 0 | { |
294 | 0 | struct smbd_server_connection *sconn = xconn->client->sconn; |
295 | 0 | struct pending_message_list *pml; |
296 | 0 | int i = 0; |
297 | |
|
298 | 0 | if (conn_using_smb2(sconn)) { |
299 | 0 | return schedule_deferred_open_message_smb2(xconn, mid); |
300 | 0 | } |
301 | | |
302 | 0 | for (pml = sconn->deferred_open_queue; pml; pml = pml->next) { |
303 | 0 | uint64_t msg_mid = (uint64_t)SVAL(pml->buf.data,smb_mid); |
304 | |
|
305 | 0 | DEBUG(10,("schedule_deferred_open_message_smb: [%d] " |
306 | 0 | "msg_mid = %llu\n", |
307 | 0 | i++, |
308 | 0 | (unsigned long long)msg_mid )); |
309 | |
|
310 | 0 | if (mid == msg_mid) { |
311 | 0 | struct tevent_timer *te; |
312 | |
|
313 | 0 | if (pml->processed) { |
314 | | /* A processed message should not be |
315 | | * rescheduled. */ |
316 | 0 | DEBUG(0,("schedule_deferred_open_message_smb: LOGIC ERROR " |
317 | 0 | "message mid %llu was already processed\n", |
318 | 0 | (unsigned long long)msg_mid )); |
319 | 0 | continue; |
320 | 0 | } |
321 | | |
322 | 0 | DEBUG(10,("schedule_deferred_open_message_smb: " |
323 | 0 | "scheduling mid %llu\n", |
324 | 0 | (unsigned long long)mid )); |
325 | | |
326 | | /* |
327 | | * smbd_deferred_open_timer() calls |
328 | | * process_smb() to redispatch the request |
329 | | * including the required impersonation. |
330 | | * |
331 | | * So we can just use the raw tevent_context. |
332 | | */ |
333 | 0 | te = tevent_add_timer(xconn->client->raw_ev_ctx, |
334 | 0 | pml, |
335 | 0 | timeval_zero(), |
336 | 0 | smbd_deferred_open_timer, |
337 | 0 | pml); |
338 | 0 | if (!te) { |
339 | 0 | DEBUG(10,("schedule_deferred_open_message_smb: " |
340 | 0 | "event_add_timed() failed, " |
341 | 0 | "skipping mid %llu\n", |
342 | 0 | (unsigned long long)msg_mid )); |
343 | 0 | } |
344 | |
|
345 | 0 | TALLOC_FREE(pml->te); |
346 | 0 | pml->te = te; |
347 | 0 | DLIST_PROMOTE(sconn->deferred_open_queue, pml); |
348 | 0 | return true; |
349 | 0 | } |
350 | 0 | } |
351 | | |
352 | 0 | DEBUG(10,("schedule_deferred_open_message_smb: failed to " |
353 | 0 | "find message mid %llu\n", |
354 | 0 | (unsigned long long)mid )); |
355 | |
|
356 | 0 | return false; |
357 | 0 | } |
358 | | |
359 | | /**************************************************************************** |
360 | | Return true if this mid is on the deferred queue and was not yet processed. |
361 | | ****************************************************************************/ |
362 | | |
363 | | bool open_was_deferred(struct smbXsrv_connection *xconn, uint64_t mid) |
364 | 0 | { |
365 | 0 | struct smbd_server_connection *sconn = xconn->client->sconn; |
366 | 0 | struct pending_message_list *pml; |
367 | |
|
368 | 0 | if (conn_using_smb2(sconn)) { |
369 | 0 | return open_was_deferred_smb2(xconn, mid); |
370 | 0 | } |
371 | | |
372 | 0 | for (pml = sconn->deferred_open_queue; pml; pml = pml->next) { |
373 | 0 | if (((uint64_t)SVAL(pml->buf.data,smb_mid)) == mid && !pml->processed) { |
374 | 0 | return True; |
375 | 0 | } |
376 | 0 | } |
377 | 0 | return False; |
378 | 0 | } |
379 | | |
380 | | /**************************************************************************** |
381 | | Return the message queued by this mid. |
382 | | ****************************************************************************/ |
383 | | |
384 | | static struct pending_message_list *get_deferred_open_message_smb( |
385 | | struct smbd_server_connection *sconn, uint64_t mid) |
386 | 0 | { |
387 | 0 | struct pending_message_list *pml; |
388 | |
|
389 | 0 | for (pml = sconn->deferred_open_queue; pml; pml = pml->next) { |
390 | 0 | if (((uint64_t)SVAL(pml->buf.data,smb_mid)) == mid) { |
391 | 0 | return pml; |
392 | 0 | } |
393 | 0 | } |
394 | 0 | return NULL; |
395 | 0 | } |
396 | | |
397 | | /**************************************************************************** |
398 | | Get the state data queued by this mid. |
399 | | ****************************************************************************/ |
400 | | |
401 | | bool get_deferred_open_message_state(struct smb_request *smbreq, |
402 | | struct timeval *p_request_time, |
403 | | struct deferred_open_record **open_rec) |
404 | 0 | { |
405 | 0 | struct pending_message_list *pml; |
406 | |
|
407 | 0 | if (conn_using_smb2(smbreq->sconn)) { |
408 | 0 | return get_deferred_open_message_state_smb2(smbreq->smb2req, |
409 | 0 | p_request_time, |
410 | 0 | open_rec); |
411 | 0 | } |
412 | | |
413 | 0 | pml = get_deferred_open_message_smb(smbreq->sconn, smbreq->mid); |
414 | 0 | if (!pml) { |
415 | 0 | return false; |
416 | 0 | } |
417 | 0 | if (p_request_time) { |
418 | 0 | *p_request_time = pml->request_time; |
419 | 0 | } |
420 | 0 | if (open_rec != NULL) { |
421 | 0 | *open_rec = pml->open_rec; |
422 | 0 | } |
423 | 0 | return true; |
424 | 0 | } |
425 | | |
426 | | bool push_deferred_open_message_smb(struct smb_request *req, |
427 | | struct timeval timeout, |
428 | | struct file_id id, |
429 | | struct deferred_open_record *open_rec) |
430 | 0 | { |
431 | 0 | #if defined(WITH_SMB1SERVER) |
432 | 0 | if (req->smb2req) { |
433 | 0 | #endif |
434 | 0 | return push_deferred_open_message_smb2(req->smb2req, |
435 | 0 | req->request_time, |
436 | 0 | timeout, |
437 | 0 | id, |
438 | 0 | open_rec); |
439 | 0 | #if defined(WITH_SMB1SERVER) |
440 | 0 | } else { |
441 | 0 | return push_deferred_open_message_smb1(req, timeout, |
442 | 0 | id, open_rec); |
443 | 0 | } |
444 | 0 | #endif |
445 | 0 | } |
446 | | |
447 | | static void construct_smb1_reply_common(uint8_t cmd, const uint8_t *inbuf, |
448 | | char *outbuf) |
449 | 0 | { |
450 | 0 | uint16_t in_flags2 = SVAL(inbuf,smb_flg2); |
451 | 0 | uint16_t out_flags2 = common_flags2; |
452 | |
|
453 | 0 | out_flags2 |= in_flags2 & FLAGS2_UNICODE_STRINGS; |
454 | 0 | out_flags2 |= in_flags2 & FLAGS2_SMB_SECURITY_SIGNATURES; |
455 | 0 | out_flags2 |= in_flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED; |
456 | |
|
457 | 0 | srv_smb1_set_message(outbuf,0,0,false); |
458 | |
|
459 | 0 | SCVAL(outbuf, smb_com, cmd); |
460 | 0 | SIVAL(outbuf,smb_rcls,0); |
461 | 0 | SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); |
462 | 0 | SSVAL(outbuf,smb_flg2, out_flags2); |
463 | 0 | memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh)); |
464 | 0 | memcpy(outbuf+smb_ss_field, inbuf+smb_ss_field, 8); |
465 | |
|
466 | 0 | SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); |
467 | 0 | SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); |
468 | 0 | SSVAL(outbuf,smb_pidhigh,SVAL(inbuf,smb_pidhigh)); |
469 | 0 | SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); |
470 | 0 | SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); |
471 | 0 | } |
472 | | |
473 | | void construct_smb1_reply_common_req(struct smb_request *req, char *outbuf) |
474 | 0 | { |
475 | 0 | construct_smb1_reply_common(req->cmd, req->inbuf, outbuf); |
476 | 0 | } |
477 | | |
478 | | /******************************************************************* |
479 | | allocate and initialize a reply packet |
480 | | ********************************************************************/ |
481 | | |
482 | | bool create_smb1_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req, |
483 | | const uint8_t *inbuf, char **outbuf, |
484 | | uint8_t num_words, uint32_t num_bytes) |
485 | 0 | { |
486 | 0 | size_t smb_len = MIN_SMB_SIZE + VWV(num_words) + num_bytes; |
487 | | |
488 | | /* |
489 | | * Protect against integer wrap. |
490 | | * The SMB layer reply can be up to 0xFFFFFF bytes. |
491 | | */ |
492 | 0 | if ((num_bytes > 0xffffff) || (smb_len > 0xffffff)) { |
493 | 0 | char *msg; |
494 | 0 | if (asprintf(&msg, "num_bytes too large: %u", |
495 | 0 | (unsigned)num_bytes) == -1) { |
496 | 0 | msg = discard_const_p(char, "num_bytes too large"); |
497 | 0 | } |
498 | 0 | smb_panic(msg); |
499 | 0 | } |
500 | | |
501 | | /* |
502 | | * Here we include the NBT header for now. |
503 | | */ |
504 | 0 | *outbuf = talloc_array(mem_ctx, char, |
505 | 0 | NBT_HDR_SIZE + smb_len); |
506 | 0 | if (*outbuf == NULL) { |
507 | 0 | return false; |
508 | 0 | } |
509 | | |
510 | 0 | construct_smb1_reply_common(req->cmd, inbuf, *outbuf); |
511 | 0 | srv_smb1_set_message(*outbuf, num_words, num_bytes, false); |
512 | | /* |
513 | | * Zero out the word area, the caller has to take care of the bcc area |
514 | | * himself |
515 | | */ |
516 | 0 | if (num_words != 0) { |
517 | 0 | memset(*outbuf + (NBT_HDR_SIZE + HDR_VWV), 0, VWV(num_words)); |
518 | 0 | } |
519 | |
|
520 | 0 | return true; |
521 | 0 | } |
522 | | |
523 | | void reply_smb1_outbuf(struct smb_request *req, uint8_t num_words, uint32_t num_bytes) |
524 | 0 | { |
525 | 0 | char *outbuf; |
526 | 0 | if (!create_smb1_outbuf(req, req, req->inbuf, &outbuf, num_words, |
527 | 0 | num_bytes)) { |
528 | 0 | smb_panic("could not allocate output buffer\n"); |
529 | 0 | } |
530 | 0 | req->outbuf = (uint8_t *)outbuf; |
531 | 0 | } |
532 | | |
533 | | bool valid_smb1_header(const uint8_t *inbuf) |
534 | 0 | { |
535 | 0 | if (is_encrypted_packet(inbuf)) { |
536 | 0 | return true; |
537 | 0 | } |
538 | | /* |
539 | | * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0) |
540 | | * but it just looks weird to call strncmp for this one. |
541 | | */ |
542 | 0 | return (IVAL(smb_base(inbuf), 0) == 0x424D53FF); |
543 | 0 | } |
544 | | |
545 | | /**************************************************************************** |
546 | | Process an smb from the client |
547 | | ****************************************************************************/ |
548 | | |
549 | | static void process_smb2(struct smbXsrv_connection *xconn, |
550 | | uint8_t *inbuf, |
551 | | size_t nread, |
552 | | size_t unread_bytes, |
553 | | uint32_t seqnum, |
554 | | bool encrypted) |
555 | 0 | { |
556 | 0 | const uint8_t *inpdu = inbuf + NBT_HDR_SIZE; |
557 | 0 | size_t pdulen = nread - NBT_HDR_SIZE; |
558 | 0 | NTSTATUS status = smbd_smb2_process_negprot(xconn, 0, inpdu, pdulen); |
559 | 0 | if (!NT_STATUS_IS_OK(status)) { |
560 | 0 | exit_server_cleanly("SMB2 negprot fail"); |
561 | 0 | } |
562 | 0 | } |
563 | | |
564 | | void process_smb(struct smbXsrv_connection *xconn, |
565 | | uint8_t *inbuf, |
566 | | size_t nread, |
567 | | size_t unread_bytes, |
568 | | uint32_t seqnum, |
569 | | bool encrypted) |
570 | 0 | { |
571 | 0 | struct smbd_server_connection *sconn = xconn->client->sconn; |
572 | 0 | int msg_type = CVAL(inbuf,0); |
573 | |
|
574 | 0 | DO_PROFILE_INC(request); |
575 | |
|
576 | 0 | DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, |
577 | 0 | smb_len(inbuf) ) ); |
578 | 0 | DEBUG(3, ("Transaction %d of length %d (%u toread)\n", |
579 | 0 | sconn->trans_num, (int)nread, (unsigned int)unread_bytes)); |
580 | |
|
581 | 0 | if (msg_type != NBSSmessage) { |
582 | | /* |
583 | | * NetBIOS session request, keepalive, etc. |
584 | | */ |
585 | 0 | reply_special(xconn, (char *)inbuf, nread); |
586 | 0 | goto done; |
587 | 0 | } |
588 | | |
589 | 0 | #if defined(WITH_SMB1SERVER) |
590 | 0 | if (lp_server_max_protocol() >= PROTOCOL_SMB2_02) { |
591 | | /* At this point we're not really using smb2, |
592 | | * we make the decision here.. */ |
593 | 0 | if (smbd_is_smb2_header(inbuf, nread)) { |
594 | 0 | #endif |
595 | 0 | process_smb2(xconn, |
596 | 0 | inbuf, |
597 | 0 | nread, |
598 | 0 | unread_bytes, |
599 | 0 | seqnum, |
600 | 0 | encrypted); |
601 | 0 | return; |
602 | 0 | #if defined(WITH_SMB1SERVER) |
603 | 0 | } |
604 | 0 | if (nread >= smb_size && valid_smb1_header(inbuf) |
605 | 0 | && CVAL(inbuf, smb_com) != 0x72) { |
606 | | /* This is a non-negprot SMB1 packet. |
607 | | Disable SMB2 from now on. */ |
608 | 0 | lp_do_parameter(-1, "server max protocol", "NT1"); |
609 | 0 | } |
610 | 0 | } |
611 | 0 | process_smb1(xconn, inbuf, nread, unread_bytes, seqnum, encrypted); |
612 | 0 | #endif |
613 | |
|
614 | 0 | done: |
615 | 0 | sconn->num_requests++; |
616 | | |
617 | | /* The timeout_processing function isn't run nearly |
618 | | often enough to implement 'max log size' without |
619 | | overrunning the size of the file by many megabytes. |
620 | | This is especially true if we are running at debug |
621 | | level 10. Checking every 50 SMBs is a nice |
622 | | tradeoff of performance vs log file size overrun. */ |
623 | |
|
624 | 0 | if ((sconn->num_requests % 50) == 0 && |
625 | 0 | need_to_check_log_size()) { |
626 | 0 | change_to_root_user(); |
627 | 0 | check_log_size(); |
628 | 0 | } |
629 | 0 | } |
630 | | |
631 | | NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn, |
632 | | enum protocol_types protocol) |
633 | 0 | { |
634 | 0 | NTSTATUS status; |
635 | |
|
636 | 0 | conn->protocol = protocol; |
637 | |
|
638 | 0 | if (conn->client->session_table != NULL) { |
639 | 0 | return NT_STATUS_OK; |
640 | 0 | } |
641 | | |
642 | 0 | if (protocol >= PROTOCOL_SMB2_02) { |
643 | 0 | status = smb2srv_session_table_init(conn); |
644 | 0 | if (!NT_STATUS_IS_OK(status)) { |
645 | 0 | conn->protocol = PROTOCOL_NONE; |
646 | 0 | return status; |
647 | 0 | } |
648 | | |
649 | 0 | status = smb2srv_open_table_init(conn); |
650 | 0 | if (!NT_STATUS_IS_OK(status)) { |
651 | 0 | conn->protocol = PROTOCOL_NONE; |
652 | 0 | return status; |
653 | 0 | } |
654 | 0 | } else { |
655 | 0 | #if defined(WITH_SMB1SERVER) |
656 | 0 | status = smb1srv_session_table_init(conn); |
657 | 0 | if (!NT_STATUS_IS_OK(status)) { |
658 | 0 | conn->protocol = PROTOCOL_NONE; |
659 | 0 | return status; |
660 | 0 | } |
661 | | |
662 | 0 | status = smb1srv_tcon_table_init(conn); |
663 | 0 | if (!NT_STATUS_IS_OK(status)) { |
664 | 0 | conn->protocol = PROTOCOL_NONE; |
665 | 0 | return status; |
666 | 0 | } |
667 | | |
668 | 0 | status = smb1srv_open_table_init(conn); |
669 | 0 | if (!NT_STATUS_IS_OK(status)) { |
670 | 0 | conn->protocol = PROTOCOL_NONE; |
671 | 0 | return status; |
672 | 0 | } |
673 | | #else |
674 | | conn->protocol = PROTOCOL_NONE; |
675 | | return NT_STATUS_INVALID_NETWORK_RESPONSE; |
676 | | #endif |
677 | 0 | } |
678 | | |
679 | 0 | set_Protocol(protocol); |
680 | 0 | return NT_STATUS_OK; |
681 | 0 | } |
682 | | |
683 | | /** |
684 | | * Create a debug string for the connection |
685 | | * |
686 | | * This is allocated to talloc_tos() or a string constant |
687 | | * in certain corner cases. The returned string should |
688 | | * hence not be free'd directly but only via the talloc stack. |
689 | | */ |
690 | | const char *smbXsrv_connection_dbg(const struct smbXsrv_connection *xconn) |
691 | 0 | { |
692 | 0 | const char *ret = NULL; |
693 | 0 | char *raddr = NULL; |
694 | 0 | char *laddr = NULL; |
695 | 0 | struct GUID_txt_buf guid_buf = {}; |
696 | | |
697 | | /* |
698 | | * TODO: this can be improved further later... |
699 | | */ |
700 | |
|
701 | 0 | raddr = tsocket_address_string(xconn->remote_address, talloc_tos()); |
702 | 0 | if (raddr == NULL) { |
703 | 0 | return "<tsocket_address_string() failed>"; |
704 | 0 | } |
705 | 0 | laddr = tsocket_address_string(xconn->local_address, talloc_tos()); |
706 | 0 | if (laddr == NULL) { |
707 | 0 | return "<tsocket_address_string() failed>"; |
708 | 0 | } |
709 | | |
710 | 0 | ret = talloc_asprintf(talloc_tos(), |
711 | 0 | "PID=%d,CLIENT=%s,channel=%"PRIu64",remote=%s,local=%s", |
712 | 0 | getpid(), |
713 | 0 | GUID_buf_string(&xconn->smb2.client.guid, &guid_buf), |
714 | 0 | xconn->channel_id, |
715 | 0 | raddr, |
716 | 0 | laddr); |
717 | 0 | TALLOC_FREE(raddr); |
718 | 0 | TALLOC_FREE(laddr); |
719 | 0 | if (ret == NULL) { |
720 | 0 | return "<talloc_asprintf() failed>"; |
721 | 0 | } |
722 | | |
723 | 0 | return ret; |
724 | 0 | } |
725 | | |
726 | | /* |
727 | | * Initialize a struct smb_request from an inbuf |
728 | | */ |
729 | | |
730 | | bool init_smb1_request(struct smb_request *req, |
731 | | struct smbd_server_connection *sconn, |
732 | | struct smbXsrv_connection *xconn, |
733 | | const uint8_t *inbuf, |
734 | | size_t unread_bytes, bool encrypted, |
735 | | uint32_t seqnum) |
736 | 0 | { |
737 | 0 | struct smbXsrv_tcon *tcon; |
738 | 0 | NTSTATUS status; |
739 | 0 | NTTIME now; |
740 | 0 | size_t req_size = smb_len(inbuf) + 4; |
741 | | |
742 | | /* Ensure we have at least smb_size bytes. */ |
743 | 0 | if (req_size < smb_size) { |
744 | 0 | DBG_ERR("invalid request size %zu\n", req_size); |
745 | 0 | return false; |
746 | 0 | } |
747 | | |
748 | 0 | *req = (struct smb_request) { .cmd = 0}; |
749 | |
|
750 | 0 | req->request_time = timeval_current(); |
751 | 0 | now = timeval_to_nttime(&req->request_time); |
752 | |
|
753 | 0 | req->cmd = CVAL(inbuf, smb_com); |
754 | 0 | req->flags2 = SVAL(inbuf, smb_flg2); |
755 | 0 | req->smbpid = SVAL(inbuf, smb_pid); |
756 | 0 | req->mid = (uint64_t)SVAL(inbuf, smb_mid); |
757 | 0 | req->seqnum = seqnum; |
758 | 0 | req->vuid = SVAL(inbuf, smb_uid); |
759 | 0 | req->tid = SVAL(inbuf, smb_tid); |
760 | 0 | req->wct = CVAL(inbuf, smb_wct); |
761 | 0 | req->vwv = (const uint16_t *)(inbuf+smb_vwv); |
762 | 0 | req->buflen = smb_buflen(inbuf); |
763 | 0 | req->buf = (const uint8_t *)smb_buf_const(inbuf); |
764 | 0 | req->unread_bytes = unread_bytes; |
765 | 0 | req->encrypted = encrypted; |
766 | 0 | req->sconn = sconn; |
767 | 0 | req->xconn = xconn; |
768 | 0 | if (xconn != NULL) { |
769 | 0 | status = smb1srv_tcon_lookup(xconn, req->tid, now, &tcon); |
770 | 0 | if (NT_STATUS_IS_OK(status)) { |
771 | 0 | req->conn = tcon->compat; |
772 | 0 | } |
773 | |
|
774 | 0 | #if defined(WITH_SMB1SERVER) |
775 | 0 | req->posix_pathnames = (xconn->smb1.unix_info.client_cap_low & |
776 | 0 | CIFS_UNIX_POSIX_PATHNAMES_CAP) != 0; |
777 | 0 | #endif |
778 | 0 | } |
779 | | |
780 | | /* Ensure we have at least wct words and 2 bytes of bcc. */ |
781 | 0 | if (smb_size + req->wct*2 > req_size) { |
782 | 0 | DBG_ERR("invalid wct number %" PRIu8 " (size %zu)\n", |
783 | 0 | req->wct, |
784 | 0 | req_size); |
785 | 0 | return false; |
786 | 0 | } |
787 | | /* Ensure bcc is correct. */ |
788 | 0 | if (((const uint8_t *)smb_buf_const(inbuf)) + req->buflen > inbuf + req_size) { |
789 | 0 | DBG_ERR("invalid bcc number %" PRIu16 " " |
790 | 0 | "(wct = %" PRIu8 ", size %zu)\n", |
791 | 0 | req->buflen, |
792 | 0 | req->wct, |
793 | 0 | req_size); |
794 | 0 | return false; |
795 | 0 | } |
796 | | |
797 | 0 | return true; |
798 | 0 | } |
799 | | |
800 | | /**************************************************************************** |
801 | | Construct a reply to the incoming packet. |
802 | | ****************************************************************************/ |
803 | | |
804 | | static void construct_reply_smb1negprot(struct smbXsrv_connection *xconn, |
805 | | char *inbuf, int size, |
806 | | size_t unread_bytes) |
807 | 0 | { |
808 | 0 | struct smbd_server_connection *sconn = xconn->client->sconn; |
809 | 0 | struct smb_request *req; |
810 | 0 | NTSTATUS status; |
811 | |
|
812 | 0 | if (!(req = talloc(talloc_tos(), struct smb_request))) { |
813 | 0 | smb_panic("could not allocate smb_request"); |
814 | 0 | } |
815 | | |
816 | 0 | if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes, |
817 | 0 | false, 0)) { |
818 | 0 | exit_server_cleanly("Invalid SMB request"); |
819 | 0 | } |
820 | | |
821 | 0 | req->inbuf = (uint8_t *)talloc_move(req, &inbuf); |
822 | |
|
823 | 0 | status = smb2_multi_protocol_reply_negprot(req); |
824 | 0 | if (req->outbuf == NULL) { |
825 | | /* |
826 | | * req->outbuf == NULL means we bootstrapped into SMB2. |
827 | | */ |
828 | 0 | return; |
829 | 0 | } |
830 | 0 | if (!NT_STATUS_IS_OK(status)) { |
831 | 0 | if (!smb1_srv_send(req->xconn, |
832 | 0 | (char *)req->outbuf, |
833 | 0 | true, |
834 | 0 | req->seqnum + 1, |
835 | 0 | IS_CONN_ENCRYPTED(req->conn) || |
836 | 0 | req->encrypted)) { |
837 | 0 | exit_server_cleanly("construct_reply_smb1negprot: " |
838 | 0 | "smb1_srv_send failed."); |
839 | 0 | } |
840 | 0 | TALLOC_FREE(req); |
841 | 0 | } else { |
842 | | /* This code path should only *ever* bootstrap into SMB2. */ |
843 | 0 | exit_server_cleanly("Internal error SMB1negprot didn't reply " |
844 | 0 | "with an SMB2 packet"); |
845 | 0 | } |
846 | 0 | } |
847 | | |
848 | | static void smbd_server_connection_write_handler( |
849 | | struct smbXsrv_connection *xconn) |
850 | 0 | { |
851 | | /* TODO: make write nonblocking */ |
852 | 0 | } |
853 | | |
854 | | static void smbd_smb2_server_connection_read_handler( |
855 | | struct smbXsrv_connection *xconn, int fd) |
856 | 0 | { |
857 | 0 | char lenbuf[NBT_HDR_SIZE]; |
858 | 0 | size_t len = 0; |
859 | 0 | uint8_t *buffer = NULL; |
860 | 0 | size_t bufferlen = 0; |
861 | 0 | NTSTATUS status; |
862 | 0 | uint8_t msg_type = 0; |
863 | | |
864 | | /* Read the first 4 bytes - contains length of remainder. */ |
865 | 0 | status = read_smb_length_return_keepalive(fd, lenbuf, 0, &len); |
866 | 0 | if (!NT_STATUS_IS_OK(status)) { |
867 | 0 | exit_server_cleanly("failed to receive request length"); |
868 | 0 | return; |
869 | 0 | } |
870 | | |
871 | | /* Integer wrap check. */ |
872 | 0 | if (len + NBT_HDR_SIZE < len) { |
873 | 0 | exit_server_cleanly("Invalid length on initial request"); |
874 | 0 | return; |
875 | 0 | } |
876 | | |
877 | | /* |
878 | | * The +4 here can't wrap, we've checked the length above already. |
879 | | */ |
880 | 0 | bufferlen = len+NBT_HDR_SIZE; |
881 | |
|
882 | 0 | buffer = talloc_array(talloc_tos(), uint8_t, bufferlen); |
883 | 0 | if (buffer == NULL) { |
884 | 0 | DBG_ERR("Could not allocate request inbuf of length %zu\n", |
885 | 0 | bufferlen); |
886 | 0 | exit_server_cleanly("talloc fail"); |
887 | 0 | return; |
888 | 0 | } |
889 | | |
890 | | /* Copy the NBT_HDR_SIZE length. */ |
891 | 0 | memcpy(buffer, lenbuf, sizeof(lenbuf)); |
892 | |
|
893 | 0 | status = read_packet_remainder(fd, (char *)buffer+NBT_HDR_SIZE, 0, len); |
894 | 0 | if (!NT_STATUS_IS_OK(status)) { |
895 | 0 | exit_server_cleanly("Failed to read remainder of initial request"); |
896 | 0 | return; |
897 | 0 | } |
898 | | |
899 | | /* Check the message type. */ |
900 | 0 | msg_type = PULL_LE_U8(buffer,0); |
901 | 0 | if (msg_type == NBSSrequest) { |
902 | | /* |
903 | | * clients can send this request before |
904 | | * bootstrapping into SMB2. Cope with this |
905 | | * message only, don't allow any other strange |
906 | | * NBSS types. |
907 | | */ |
908 | 0 | reply_special(xconn, (char *)buffer, bufferlen); |
909 | 0 | xconn->client->sconn->num_requests++; |
910 | 0 | return; |
911 | 0 | } |
912 | | |
913 | | /* Only a 'normal' message type allowed now. */ |
914 | 0 | if (msg_type != NBSSmessage) { |
915 | 0 | DBG_ERR("Invalid message type %d\n", msg_type); |
916 | 0 | exit_server_cleanly("Invalid message type for initial request"); |
917 | 0 | return; |
918 | 0 | } |
919 | | |
920 | | /* Could this be an SMB1 negprot bootstrap into SMB2 ? */ |
921 | 0 | if (bufferlen < smb_size) { |
922 | 0 | exit_server_cleanly("Invalid initial SMB1 or SMB2 packet"); |
923 | 0 | return; |
924 | 0 | } |
925 | 0 | if (valid_smb1_header(buffer)) { |
926 | | /* Can *only* allow an SMB1 negprot here. */ |
927 | 0 | uint8_t cmd = PULL_LE_U8(buffer, smb_com); |
928 | 0 | if (cmd != SMBnegprot) { |
929 | 0 | DBG_ERR("Incorrect SMB1 command 0x%hhx, " |
930 | 0 | "should be SMBnegprot (0x72)\n", |
931 | 0 | cmd); |
932 | 0 | exit_server_cleanly("Invalid initial SMB1 packet"); |
933 | 0 | } |
934 | | /* Minimal process_smb(). */ |
935 | 0 | show_msg((char *)buffer); |
936 | 0 | construct_reply_smb1negprot(xconn, (char *)buffer, |
937 | 0 | bufferlen, 0); |
938 | 0 | xconn->client->sconn->trans_num++; |
939 | 0 | xconn->client->sconn->num_requests++; |
940 | 0 | return; |
941 | 0 | } |
942 | | |
943 | 0 | if (!smbd_is_smb2_header(buffer, bufferlen)) { |
944 | 0 | exit_server_cleanly("Invalid initial SMB2 packet"); |
945 | 0 | return; |
946 | 0 | } |
947 | | |
948 | | /* Here we know we're a valid SMB2 packet. */ |
949 | | |
950 | | /* |
951 | | * Point at the start of the SMB2 PDU. |
952 | | * len is the length of the SMB2 PDU. |
953 | | */ |
954 | | |
955 | 0 | status = smbd_smb2_process_negprot(xconn, |
956 | 0 | 0, |
957 | 0 | (const uint8_t *)buffer+NBT_HDR_SIZE, |
958 | 0 | len); |
959 | 0 | if (!NT_STATUS_IS_OK(status)) { |
960 | 0 | exit_server_cleanly("SMB2 negprot fail"); |
961 | 0 | } |
962 | 0 | return; |
963 | 0 | } |
964 | | |
965 | | static void smbd_server_connection_handler(struct tevent_context *ev, |
966 | | struct tevent_fd *fde, |
967 | | uint16_t flags, |
968 | | void *private_data) |
969 | 0 | { |
970 | 0 | struct smbXsrv_connection *xconn = |
971 | 0 | talloc_get_type_abort(private_data, |
972 | 0 | struct smbXsrv_connection); |
973 | |
|
974 | 0 | if (!NT_STATUS_IS_OK(xconn->transport.status)) { |
975 | | /* |
976 | | * we're not supposed to do any io |
977 | | */ |
978 | 0 | TEVENT_FD_NOT_READABLE(xconn->transport.fde); |
979 | 0 | TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde); |
980 | 0 | return; |
981 | 0 | } |
982 | | |
983 | 0 | if (flags & TEVENT_FD_WRITE) { |
984 | 0 | smbd_server_connection_write_handler(xconn); |
985 | 0 | return; |
986 | 0 | } |
987 | 0 | if (flags & TEVENT_FD_READ) { |
988 | 0 | #if defined(WITH_SMB1SERVER) |
989 | 0 | if (lp_server_min_protocol() > PROTOCOL_NT1) { |
990 | 0 | #endif |
991 | 0 | smbd_smb2_server_connection_read_handler(xconn, |
992 | 0 | xconn->transport.sock); |
993 | 0 | #if defined(WITH_SMB1SERVER) |
994 | 0 | } else { |
995 | 0 | smbd_smb1_server_connection_read_handler(xconn, |
996 | 0 | xconn->transport.sock); |
997 | 0 | } |
998 | 0 | #endif |
999 | 0 | return; |
1000 | 0 | } |
1001 | 0 | } |
1002 | | |
1003 | | struct smbd_release_ip_state { |
1004 | | struct smbXsrv_connection *xconn; |
1005 | | struct tevent_immediate *im; |
1006 | | struct sockaddr_storage srv; |
1007 | | struct sockaddr_storage clnt; |
1008 | | char addr[INET6_ADDRSTRLEN]; |
1009 | | }; |
1010 | | |
1011 | | static int release_ip(struct tevent_context *ev, |
1012 | | uint32_t src_vnn, |
1013 | | uint32_t dst_vnn, |
1014 | | uint64_t dst_srvid, |
1015 | | const uint8_t *msg, |
1016 | | size_t msglen, |
1017 | | void *private_data); |
1018 | | |
1019 | | static int smbd_release_ip_state_destructor(struct smbd_release_ip_state *s) |
1020 | 0 | { |
1021 | 0 | struct ctdbd_connection *cconn = messaging_ctdb_connection(); |
1022 | 0 | struct smbXsrv_connection *xconn = s->xconn; |
1023 | |
|
1024 | 0 | if (cconn == NULL) { |
1025 | 0 | return 0; |
1026 | 0 | } |
1027 | | |
1028 | 0 | if (NT_STATUS_EQUAL(xconn->transport.status, NT_STATUS_CONNECTION_IN_USE)) { |
1029 | 0 | ctdbd_passed_ips(cconn, &s->srv, &s->clnt, release_ip, s); |
1030 | 0 | } else { |
1031 | 0 | ctdbd_unregister_ips(cconn, &s->srv, &s->clnt, release_ip, s); |
1032 | 0 | } |
1033 | |
|
1034 | 0 | return 0; |
1035 | 0 | } |
1036 | | |
1037 | | static void smbd_release_ip_immediate(struct tevent_context *ctx, |
1038 | | struct tevent_immediate *im, |
1039 | | void *private_data) |
1040 | 0 | { |
1041 | 0 | struct smbd_release_ip_state *state = |
1042 | 0 | talloc_get_type_abort(private_data, |
1043 | 0 | struct smbd_release_ip_state); |
1044 | 0 | struct smbXsrv_connection *xconn = state->xconn; |
1045 | |
|
1046 | 0 | if (!NT_STATUS_EQUAL(xconn->transport.status, NT_STATUS_ADDRESS_CLOSED)) { |
1047 | | /* |
1048 | | * smbd_server_connection_terminate() already triggered ? |
1049 | | */ |
1050 | 0 | return; |
1051 | 0 | } |
1052 | | |
1053 | 0 | smbd_server_connection_terminate(xconn, "CTDB_SRVID_RELEASE_IP"); |
1054 | 0 | } |
1055 | | |
1056 | | /**************************************************************************** |
1057 | | received when we should release a specific IP |
1058 | | ****************************************************************************/ |
1059 | | static int release_ip(struct tevent_context *ev, |
1060 | | uint32_t src_vnn, uint32_t dst_vnn, |
1061 | | uint64_t dst_srvid, |
1062 | | const uint8_t *msg, size_t msglen, |
1063 | | void *private_data) |
1064 | 0 | { |
1065 | 0 | struct smbd_release_ip_state *state = |
1066 | 0 | talloc_get_type_abort(private_data, |
1067 | 0 | struct smbd_release_ip_state); |
1068 | 0 | struct smbXsrv_connection *xconn = state->xconn; |
1069 | 0 | const char *ip; |
1070 | 0 | const char *addr = state->addr; |
1071 | 0 | const char *p = addr; |
1072 | |
|
1073 | 0 | if (msglen == 0) { |
1074 | 0 | return 0; |
1075 | 0 | } |
1076 | 0 | if (msg[msglen-1] != '\0') { |
1077 | 0 | return 0; |
1078 | 0 | } |
1079 | | |
1080 | 0 | ip = (const char *)msg; |
1081 | |
|
1082 | 0 | if (!NT_STATUS_IS_OK(xconn->transport.status)) { |
1083 | | /* avoid recursion */ |
1084 | 0 | return 0; |
1085 | 0 | } |
1086 | | |
1087 | 0 | if (strncmp("::ffff:", addr, 7) == 0) { |
1088 | 0 | p = addr + 7; |
1089 | 0 | } |
1090 | |
|
1091 | 0 | DEBUG(10, ("Got release IP message for %s, " |
1092 | 0 | "our address is %s\n", ip, p)); |
1093 | |
|
1094 | 0 | if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) { |
1095 | 0 | DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n", |
1096 | 0 | ip)); |
1097 | | /* |
1098 | | * With SMB2 we should do a clean disconnect, |
1099 | | * the previous_session_id in the session setup |
1100 | | * will cleanup the old session, tcons and opens. |
1101 | | * |
1102 | | * A clean disconnect is needed in order to support |
1103 | | * durable handles. |
1104 | | * |
1105 | | * Note: typically this is never triggered |
1106 | | * as we got a TCP RST (triggered by ctdb event scripts) |
1107 | | * before we get CTDB_SRVID_RELEASE_IP. |
1108 | | * |
1109 | | * We used to call _exit(1) here, but as this was mostly never |
1110 | | * triggered and has implication on our process model, |
1111 | | * we can just use smbd_server_connection_terminate() |
1112 | | * (also for SMB1). |
1113 | | * |
1114 | | * We don't call smbd_server_connection_terminate() directly |
1115 | | * as we might be called from within ctdbd_migrate(), |
1116 | | * we need to defer our action to the next event loop |
1117 | | */ |
1118 | 0 | tevent_schedule_immediate(state->im, |
1119 | 0 | xconn->client->raw_ev_ctx, |
1120 | 0 | smbd_release_ip_immediate, |
1121 | 0 | state); |
1122 | | |
1123 | | /* |
1124 | | * Make sure we don't get any io on the connection. |
1125 | | */ |
1126 | 0 | xconn->transport.status = NT_STATUS_ADDRESS_CLOSED; |
1127 | 0 | return EADDRNOTAVAIL; |
1128 | 0 | } |
1129 | | |
1130 | 0 | return 0; |
1131 | 0 | } |
1132 | | |
1133 | | static int match_cluster_movable_ip(uint32_t total_ip_count, |
1134 | | const struct sockaddr_storage *ip, |
1135 | | bool is_movable_ip, |
1136 | | void *private_data) |
1137 | 0 | { |
1138 | 0 | const struct sockaddr_storage *srv = private_data; |
1139 | 0 | struct samba_sockaddr pub_ip = { |
1140 | 0 | .u = { |
1141 | 0 | .ss = *ip, |
1142 | 0 | }, |
1143 | 0 | }; |
1144 | 0 | struct samba_sockaddr srv_ip = { |
1145 | 0 | .u = { |
1146 | 0 | .ss = *srv, |
1147 | 0 | }, |
1148 | 0 | }; |
1149 | |
|
1150 | 0 | if (is_movable_ip && sockaddr_equal(&pub_ip.u.sa, &srv_ip.u.sa)) { |
1151 | 0 | return EADDRNOTAVAIL; |
1152 | 0 | } |
1153 | | |
1154 | 0 | return 0; |
1155 | 0 | } |
1156 | | |
1157 | | static NTSTATUS smbd_register_ips(struct smbXsrv_connection *xconn, |
1158 | | struct sockaddr_storage *srv, |
1159 | | struct sockaddr_storage *clnt) |
1160 | 0 | { |
1161 | 0 | struct smbd_release_ip_state *state; |
1162 | 0 | struct ctdbd_connection *cconn; |
1163 | 0 | int ret; |
1164 | |
|
1165 | 0 | cconn = messaging_ctdb_connection(); |
1166 | 0 | if (cconn == NULL) { |
1167 | 0 | return NT_STATUS_NO_MEMORY; |
1168 | 0 | } |
1169 | | |
1170 | 0 | state = talloc_zero(xconn, struct smbd_release_ip_state); |
1171 | 0 | if (state == NULL) { |
1172 | 0 | return NT_STATUS_NO_MEMORY; |
1173 | 0 | } |
1174 | 0 | state->xconn = xconn; |
1175 | 0 | state->im = tevent_create_immediate(state); |
1176 | 0 | if (state->im == NULL) { |
1177 | 0 | return NT_STATUS_NO_MEMORY; |
1178 | 0 | } |
1179 | 0 | state->srv = *srv; |
1180 | 0 | state->clnt = *clnt; |
1181 | 0 | if (print_sockaddr(state->addr, sizeof(state->addr), srv) == NULL) { |
1182 | 0 | return NT_STATUS_NO_MEMORY; |
1183 | 0 | } |
1184 | | |
1185 | 0 | if (xconn->client->server_multi_channel_enabled) { |
1186 | 0 | ret = ctdbd_public_ip_foreach(cconn, |
1187 | 0 | match_cluster_movable_ip, |
1188 | 0 | srv); |
1189 | 0 | if (ret == EADDRNOTAVAIL) { |
1190 | 0 | xconn->has_cluster_movable_ip = true; |
1191 | 0 | DBG_DEBUG("cluster movable IP on %s\n", |
1192 | 0 | smbXsrv_connection_dbg(xconn)); |
1193 | 0 | } else if (ret != 0) { |
1194 | 0 | DBG_ERR("failed to iterate cluster IPs: %s\n", |
1195 | 0 | strerror(ret)); |
1196 | 0 | return NT_STATUS_INTERNAL_ERROR; |
1197 | 0 | } |
1198 | 0 | } |
1199 | | |
1200 | 0 | ret = ctdbd_register_ips(cconn, srv, clnt, release_ip, state); |
1201 | 0 | if (ret != 0) { |
1202 | 0 | return map_nt_error_from_unix(ret); |
1203 | 0 | } |
1204 | | |
1205 | 0 | talloc_set_destructor(state, smbd_release_ip_state_destructor); |
1206 | |
|
1207 | 0 | return NT_STATUS_OK; |
1208 | 0 | } |
1209 | | |
1210 | | static int smbXsrv_connection_destructor(struct smbXsrv_connection *xconn) |
1211 | 0 | { |
1212 | 0 | DBG_DEBUG("xconn[%s]\n", smbXsrv_connection_dbg(xconn)); |
1213 | 0 | return 0; |
1214 | 0 | } |
1215 | | |
1216 | | NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd, |
1217 | | enum smb_transport_type transport_type, |
1218 | | NTTIME now, struct smbXsrv_connection **_xconn) |
1219 | 0 | { |
1220 | 0 | TALLOC_CTX *frame = talloc_stackframe(); |
1221 | 0 | struct smbXsrv_connection *xconn; |
1222 | 0 | struct sockaddr_storage ss_srv; |
1223 | 0 | void *sp_srv = (void *)&ss_srv; |
1224 | 0 | struct sockaddr *sa_srv = (struct sockaddr *)sp_srv; |
1225 | 0 | struct sockaddr_storage ss_clnt; |
1226 | 0 | void *sp_clnt = (void *)&ss_clnt; |
1227 | 0 | struct sockaddr *sa_clnt = (struct sockaddr *)sp_clnt; |
1228 | 0 | socklen_t sa_socklen; |
1229 | 0 | struct tsocket_address *local_address = NULL; |
1230 | 0 | struct tsocket_address *remote_address = NULL; |
1231 | 0 | const char *remaddr = NULL; |
1232 | 0 | char *p; |
1233 | 0 | const char *rhost = NULL; |
1234 | 0 | int ret; |
1235 | 0 | int tmp; |
1236 | |
|
1237 | 0 | *_xconn = NULL; |
1238 | |
|
1239 | 0 | DO_PROFILE_INC(connect); |
1240 | |
|
1241 | 0 | xconn = talloc_zero(client, struct smbXsrv_connection); |
1242 | 0 | if (xconn == NULL) { |
1243 | 0 | DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n")); |
1244 | 0 | TALLOC_FREE(frame); |
1245 | 0 | return NT_STATUS_NO_MEMORY; |
1246 | 0 | } |
1247 | 0 | talloc_set_destructor(xconn, smbXsrv_connection_destructor); |
1248 | 0 | talloc_steal(frame, xconn); |
1249 | 0 | xconn->client = client; |
1250 | 0 | xconn->connect_time = now; |
1251 | 0 | if (client->next_channel_id != 0) { |
1252 | 0 | xconn->channel_id = client->next_channel_id++; |
1253 | 0 | } |
1254 | |
|
1255 | 0 | xconn->transport.sock = sock_fd; |
1256 | 0 | xconn->transport.type = transport_type; |
1257 | 0 | #if defined(WITH_SMB1SERVER) |
1258 | 0 | smbd_echo_init(xconn); |
1259 | 0 | #endif |
1260 | 0 | xconn->protocol = PROTOCOL_NONE; |
1261 | | |
1262 | | /* Ensure child is set to blocking mode */ |
1263 | 0 | set_blocking(sock_fd,True); |
1264 | |
|
1265 | 0 | set_socket_options(sock_fd, "SO_KEEPALIVE"); |
1266 | 0 | set_socket_options(sock_fd, lp_socket_options()); |
1267 | |
|
1268 | 0 | sa_socklen = sizeof(ss_clnt); |
1269 | 0 | ret = getpeername(sock_fd, sa_clnt, &sa_socklen); |
1270 | 0 | if (ret != 0) { |
1271 | 0 | int saved_errno = errno; |
1272 | 0 | int level = (errno == ENOTCONN)?2:0; |
1273 | 0 | DEBUG(level,("getpeername() failed - %s\n", |
1274 | 0 | strerror(saved_errno))); |
1275 | 0 | TALLOC_FREE(frame); |
1276 | 0 | return map_nt_error_from_unix_common(saved_errno); |
1277 | 0 | } |
1278 | 0 | ret = tsocket_address_bsd_from_sockaddr(xconn, |
1279 | 0 | sa_clnt, sa_socklen, |
1280 | 0 | &remote_address); |
1281 | 0 | if (ret != 0) { |
1282 | 0 | int saved_errno = errno; |
1283 | 0 | DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n", |
1284 | 0 | __location__, strerror(saved_errno))); |
1285 | 0 | TALLOC_FREE(frame); |
1286 | 0 | return map_nt_error_from_unix_common(saved_errno); |
1287 | 0 | } |
1288 | | |
1289 | 0 | sa_socklen = sizeof(ss_srv); |
1290 | 0 | ret = getsockname(sock_fd, sa_srv, &sa_socklen); |
1291 | 0 | if (ret != 0) { |
1292 | 0 | int saved_errno = errno; |
1293 | 0 | int level = (errno == ENOTCONN)?2:0; |
1294 | 0 | DEBUG(level,("getsockname() failed - %s\n", |
1295 | 0 | strerror(saved_errno))); |
1296 | 0 | TALLOC_FREE(frame); |
1297 | 0 | return map_nt_error_from_unix_common(saved_errno); |
1298 | 0 | } |
1299 | 0 | ret = tsocket_address_bsd_from_sockaddr(xconn, |
1300 | 0 | sa_srv, sa_socklen, |
1301 | 0 | &local_address); |
1302 | 0 | if (ret != 0) { |
1303 | 0 | int saved_errno = errno; |
1304 | 0 | DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n", |
1305 | 0 | __location__, strerror(saved_errno))); |
1306 | 0 | TALLOC_FREE(frame); |
1307 | 0 | return map_nt_error_from_unix_common(saved_errno); |
1308 | 0 | } |
1309 | | |
1310 | 0 | if (tsocket_address_is_inet(remote_address, "ip")) { |
1311 | 0 | remaddr = tsocket_address_inet_addr_string(remote_address, |
1312 | 0 | talloc_tos()); |
1313 | 0 | if (remaddr == NULL) { |
1314 | 0 | DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n", |
1315 | 0 | __location__, strerror(errno))); |
1316 | 0 | TALLOC_FREE(frame); |
1317 | 0 | return NT_STATUS_NO_MEMORY; |
1318 | 0 | } |
1319 | 0 | } else { |
1320 | 0 | remaddr = "0.0.0.0"; |
1321 | 0 | } |
1322 | | |
1323 | | /* |
1324 | | * Before the first packet, check the global hosts allow/ hosts deny |
1325 | | * parameters before doing any parsing of packets passed to us by the |
1326 | | * client. This prevents attacks on our parsing code from hosts not in |
1327 | | * the hosts allow list. |
1328 | | */ |
1329 | | |
1330 | 0 | ret = get_remote_hostname(remote_address, |
1331 | 0 | &p, talloc_tos()); |
1332 | 0 | if (ret < 0) { |
1333 | 0 | int saved_errno = errno; |
1334 | 0 | DEBUG(0,("%s: get_remote_hostname failed - %s\n", |
1335 | 0 | __location__, strerror(saved_errno))); |
1336 | 0 | TALLOC_FREE(frame); |
1337 | 0 | return map_nt_error_from_unix_common(saved_errno); |
1338 | 0 | } |
1339 | 0 | rhost = p; |
1340 | 0 | if (strequal(rhost, "UNKNOWN")) { |
1341 | 0 | rhost = remaddr; |
1342 | 0 | } |
1343 | |
|
1344 | 0 | xconn->local_address = local_address; |
1345 | 0 | xconn->remote_address = remote_address; |
1346 | 0 | xconn->remote_hostname = talloc_strdup(xconn, rhost); |
1347 | 0 | if (xconn->remote_hostname == NULL) { |
1348 | 0 | return NT_STATUS_NO_MEMORY; |
1349 | 0 | } |
1350 | | |
1351 | 0 | if (!srv_init_signing(xconn)) { |
1352 | 0 | DEBUG(0, ("Failed to init smb_signing\n")); |
1353 | 0 | TALLOC_FREE(frame); |
1354 | 0 | return NT_STATUS_INTERNAL_ERROR; |
1355 | 0 | } |
1356 | | |
1357 | 0 | if (!allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1), |
1358 | 0 | xconn->remote_hostname, |
1359 | 0 | remaddr)) { |
1360 | 0 | DEBUG( 1, ("Connection denied from %s to %s\n", |
1361 | 0 | tsocket_address_string(remote_address, talloc_tos()), |
1362 | 0 | tsocket_address_string(local_address, talloc_tos()))); |
1363 | | |
1364 | | /* |
1365 | | * We return a valid xconn |
1366 | | * so that the caller can return an error message |
1367 | | * to the client |
1368 | | */ |
1369 | 0 | DLIST_ADD_END(client->connections, xconn); |
1370 | 0 | talloc_steal(client, xconn); |
1371 | |
|
1372 | 0 | *_xconn = xconn; |
1373 | 0 | TALLOC_FREE(frame); |
1374 | 0 | return NT_STATUS_NETWORK_ACCESS_DENIED; |
1375 | 0 | } |
1376 | | |
1377 | 0 | DEBUG(10, ("Connection allowed from %s to %s\n", |
1378 | 0 | tsocket_address_string(remote_address, talloc_tos()), |
1379 | 0 | tsocket_address_string(local_address, talloc_tos()))); |
1380 | |
|
1381 | 0 | if (lp_clustering()) { |
1382 | | /* |
1383 | | * We need to tell ctdb about our client's TCP |
1384 | | * connection, so that for failover ctdbd can send |
1385 | | * tickle acks, triggering a reconnection by the |
1386 | | * client. |
1387 | | */ |
1388 | 0 | NTSTATUS status; |
1389 | |
|
1390 | 0 | status = smbd_register_ips(xconn, &ss_srv, &ss_clnt); |
1391 | 0 | if (!NT_STATUS_IS_OK(status)) { |
1392 | 0 | DEBUG(0, ("ctdbd_register_ips failed: %s\n", |
1393 | 0 | nt_errstr(status))); |
1394 | 0 | } |
1395 | 0 | } |
1396 | |
|
1397 | 0 | tmp = lp_max_xmit(); |
1398 | 0 | tmp = MAX(tmp, SMB_BUFFER_SIZE_MIN); |
1399 | 0 | tmp = MIN(tmp, SMB_BUFFER_SIZE_MAX); |
1400 | |
|
1401 | 0 | #if defined(WITH_SMB1SERVER) |
1402 | 0 | xconn->smb1.negprot.max_recv = tmp; |
1403 | |
|
1404 | 0 | xconn->smb1.sessions.done_sesssetup = false; |
1405 | 0 | xconn->smb1.sessions.max_send = SMB_BUFFER_SIZE_MAX; |
1406 | 0 | #endif |
1407 | |
|
1408 | 0 | xconn->transport.fde = tevent_add_fd(client->raw_ev_ctx, |
1409 | 0 | xconn, |
1410 | 0 | sock_fd, |
1411 | 0 | TEVENT_FD_READ, |
1412 | 0 | smbd_server_connection_handler, |
1413 | 0 | xconn); |
1414 | 0 | if (!xconn->transport.fde) { |
1415 | 0 | TALLOC_FREE(frame); |
1416 | 0 | return NT_STATUS_NO_MEMORY; |
1417 | 0 | } |
1418 | 0 | tevent_fd_set_auto_close(xconn->transport.fde); |
1419 | | |
1420 | | /* for now we only have one connection */ |
1421 | 0 | DLIST_ADD_END(client->connections, xconn); |
1422 | 0 | talloc_steal(client, xconn); |
1423 | |
|
1424 | 0 | *_xconn = xconn; |
1425 | 0 | TALLOC_FREE(frame); |
1426 | 0 | return NT_STATUS_OK; |
1427 | 0 | } |
1428 | | |
1429 | | static bool uid_in_use(struct auth_session_info *session_info, |
1430 | | uid_t uid) |
1431 | 0 | { |
1432 | 0 | if (session_info->unix_token->uid == uid) { |
1433 | 0 | return true; |
1434 | 0 | } |
1435 | 0 | return false; |
1436 | 0 | } |
1437 | | |
1438 | | static bool gid_in_use(struct auth_session_info *session_info, |
1439 | | gid_t gid) |
1440 | 0 | { |
1441 | 0 | uint32_t i; |
1442 | 0 | struct security_unix_token *utok = NULL; |
1443 | |
|
1444 | 0 | utok = session_info->unix_token; |
1445 | 0 | if (utok->gid == gid) { |
1446 | 0 | return true; |
1447 | 0 | } |
1448 | | |
1449 | 0 | for(i = 0; i < utok->ngroups; i++) { |
1450 | 0 | if (utok->groups[i] == gid) { |
1451 | 0 | return true; |
1452 | 0 | } |
1453 | 0 | } |
1454 | 0 | return false; |
1455 | 0 | } |
1456 | | |
1457 | | static bool sid_in_use(struct auth_session_info *session_info, |
1458 | | const struct dom_sid *psid) |
1459 | 0 | { |
1460 | 0 | struct security_token *tok = NULL; |
1461 | |
|
1462 | 0 | tok = session_info->security_token; |
1463 | 0 | if (tok == NULL) { |
1464 | | /* |
1465 | | * Not sure session_info->security_token can |
1466 | | * ever be NULL. This check might be not |
1467 | | * necessary. |
1468 | | */ |
1469 | 0 | return false; |
1470 | 0 | } |
1471 | 0 | if (security_token_has_sid(tok, psid)) { |
1472 | 0 | return true; |
1473 | 0 | } |
1474 | 0 | return false; |
1475 | 0 | } |
1476 | | |
1477 | | struct id_in_use_state { |
1478 | | const struct id_cache_ref *id; |
1479 | | bool match; |
1480 | | }; |
1481 | | |
1482 | | static int id_in_use_cb(struct smbXsrv_session *session, |
1483 | | void *private_data) |
1484 | 0 | { |
1485 | 0 | struct id_in_use_state *state = (struct id_in_use_state *) |
1486 | 0 | private_data; |
1487 | 0 | struct auth_session_info *session_info = |
1488 | 0 | session->global->auth_session_info; |
1489 | |
|
1490 | 0 | switch(state->id->type) { |
1491 | 0 | case UID: |
1492 | 0 | state->match = uid_in_use(session_info, state->id->id.uid); |
1493 | 0 | break; |
1494 | 0 | case GID: |
1495 | 0 | state->match = gid_in_use(session_info, state->id->id.gid); |
1496 | 0 | break; |
1497 | 0 | case SID: |
1498 | 0 | state->match = sid_in_use(session_info, &state->id->id.sid); |
1499 | 0 | break; |
1500 | 0 | default: |
1501 | 0 | state->match = false; |
1502 | 0 | break; |
1503 | 0 | } |
1504 | 0 | if (state->match) { |
1505 | 0 | return -1; |
1506 | 0 | } |
1507 | 0 | return 0; |
1508 | 0 | } |
1509 | | |
1510 | | static bool id_in_use(struct smbd_server_connection *sconn, |
1511 | | const struct id_cache_ref *id) |
1512 | 0 | { |
1513 | 0 | struct id_in_use_state state; |
1514 | 0 | NTSTATUS status; |
1515 | |
|
1516 | 0 | state = (struct id_in_use_state) { |
1517 | 0 | .id = id, |
1518 | 0 | .match = false, |
1519 | 0 | }; |
1520 | |
|
1521 | 0 | status = smbXsrv_session_local_traverse(sconn->client, |
1522 | 0 | id_in_use_cb, |
1523 | 0 | &state); |
1524 | 0 | if (!NT_STATUS_IS_OK(status)) { |
1525 | 0 | return false; |
1526 | 0 | } |
1527 | | |
1528 | 0 | return state.match; |
1529 | 0 | } |
1530 | | |
1531 | | /**************************************************************************** |
1532 | | Check if services need reloading. |
1533 | | ****************************************************************************/ |
1534 | | |
1535 | | static void check_reload(struct smbd_server_connection *sconn, time_t t) |
1536 | 0 | { |
1537 | |
|
1538 | 0 | if (last_smb_conf_reload_time == 0) { |
1539 | 0 | last_smb_conf_reload_time = t; |
1540 | 0 | } |
1541 | |
|
1542 | 0 | if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) { |
1543 | 0 | reload_services(sconn, conn_snum_used, true); |
1544 | 0 | last_smb_conf_reload_time = t; |
1545 | 0 | } |
1546 | 0 | } |
1547 | | |
1548 | | static void msg_kill_client_ip(struct messaging_context *msg_ctx, |
1549 | | void *private_data, uint32_t msg_type, |
1550 | | struct server_id server_id, DATA_BLOB *data) |
1551 | 0 | { |
1552 | 0 | struct smbd_server_connection *sconn = talloc_get_type_abort( |
1553 | 0 | private_data, struct smbd_server_connection); |
1554 | 0 | const char *ip = (char *) data->data; |
1555 | 0 | char *client_ip; |
1556 | |
|
1557 | 0 | DBG_DEBUG("Got kill request for client IP %s\n", ip); |
1558 | |
|
1559 | 0 | client_ip = tsocket_address_inet_addr_string(sconn->remote_address, |
1560 | 0 | talloc_tos()); |
1561 | 0 | if (client_ip == NULL) { |
1562 | 0 | return; |
1563 | 0 | } |
1564 | | |
1565 | 0 | if (strequal(ip, client_ip)) { |
1566 | 0 | DBG_WARNING("Got kill client message for %s - " |
1567 | 0 | "exiting immediately\n", ip); |
1568 | 0 | exit_server_cleanly("Forced disconnect for client"); |
1569 | 0 | } |
1570 | | |
1571 | 0 | TALLOC_FREE(client_ip); |
1572 | 0 | } |
1573 | | |
1574 | | static void msg_kill_client_with_server_ip(struct messaging_context *msg_ctx, |
1575 | | void *private_data, |
1576 | | uint32_t msg_type, |
1577 | | struct server_id server_id, |
1578 | | DATA_BLOB *data) |
1579 | 0 | { |
1580 | 0 | struct smbd_server_connection *sconn = talloc_get_type_abort( |
1581 | 0 | private_data, struct smbd_server_connection); |
1582 | 0 | const char *ip = (char *) data->data; |
1583 | 0 | char *server_ip = NULL; |
1584 | 0 | TALLOC_CTX *ctx = NULL; |
1585 | |
|
1586 | 0 | DBG_NOTICE("Got kill request for source IP %s\n", ip); |
1587 | 0 | ctx = talloc_stackframe(); |
1588 | |
|
1589 | 0 | server_ip = tsocket_address_inet_addr_string(sconn->local_address, ctx); |
1590 | 0 | if (server_ip == NULL) { |
1591 | 0 | goto out_free; |
1592 | 0 | } |
1593 | | |
1594 | 0 | if (strequal(ip, server_ip)) { |
1595 | 0 | DBG_NOTICE( |
1596 | 0 | "Got ip dropped message for %s - exiting immediately\n", |
1597 | 0 | ip); |
1598 | 0 | TALLOC_FREE(ctx); |
1599 | 0 | exit_server_cleanly("Forced disconnect for client"); |
1600 | 0 | } |
1601 | | |
1602 | 0 | out_free: |
1603 | 0 | TALLOC_FREE(ctx); |
1604 | 0 | } |
1605 | | |
1606 | | /* |
1607 | | * Do the recurring check if we're idle |
1608 | | */ |
1609 | | static bool deadtime_fn(const struct timeval *now, void *private_data) |
1610 | 0 | { |
1611 | 0 | struct smbd_server_connection *sconn = |
1612 | 0 | (struct smbd_server_connection *)private_data; |
1613 | |
|
1614 | 0 | if ((conn_num_open(sconn) == 0) |
1615 | 0 | || (conn_idle_all(sconn, now->tv_sec))) { |
1616 | 0 | DEBUG( 2, ( "Closing idle connection\n" ) ); |
1617 | 0 | messaging_send(sconn->msg_ctx, |
1618 | 0 | messaging_server_id(sconn->msg_ctx), |
1619 | 0 | MSG_SHUTDOWN, &data_blob_null); |
1620 | 0 | return False; |
1621 | 0 | } |
1622 | | |
1623 | 0 | return True; |
1624 | 0 | } |
1625 | | |
1626 | | /* |
1627 | | * Do the recurring log file and smb.conf reload checks. |
1628 | | */ |
1629 | | |
1630 | | static bool housekeeping_fn(const struct timeval *now, void *private_data) |
1631 | 0 | { |
1632 | 0 | struct smbd_server_connection *sconn = talloc_get_type_abort( |
1633 | 0 | private_data, struct smbd_server_connection); |
1634 | |
|
1635 | 0 | DEBUG(5, ("housekeeping\n")); |
1636 | |
|
1637 | 0 | change_to_root_user(); |
1638 | | |
1639 | | /* check if we need to reload services */ |
1640 | 0 | check_reload(sconn, time_mono(NULL)); |
1641 | | |
1642 | | /* |
1643 | | * Force a log file check. |
1644 | | */ |
1645 | 0 | force_check_log_size(); |
1646 | 0 | check_log_size(); |
1647 | 0 | return true; |
1648 | 0 | } |
1649 | | |
1650 | | static void smbd_sig_term_handler(struct tevent_context *ev, |
1651 | | struct tevent_signal *se, |
1652 | | int signum, |
1653 | | int count, |
1654 | | void *siginfo, |
1655 | | void *private_data) |
1656 | 0 | { |
1657 | 0 | exit_server_cleanly("termination signal"); |
1658 | 0 | } |
1659 | | |
1660 | | static void smbd_setup_sig_term_handler(struct smbd_server_connection *sconn) |
1661 | 0 | { |
1662 | 0 | struct tevent_signal *se; |
1663 | |
|
1664 | 0 | se = tevent_add_signal(sconn->ev_ctx, |
1665 | 0 | sconn, |
1666 | 0 | SIGTERM, 0, |
1667 | 0 | smbd_sig_term_handler, |
1668 | 0 | sconn); |
1669 | 0 | if (!se) { |
1670 | 0 | exit_server("failed to setup SIGTERM handler"); |
1671 | 0 | } |
1672 | 0 | } |
1673 | | |
1674 | | static void smbd_sig_hup_handler(struct tevent_context *ev, |
1675 | | struct tevent_signal *se, |
1676 | | int signum, |
1677 | | int count, |
1678 | | void *siginfo, |
1679 | | void *private_data) |
1680 | 0 | { |
1681 | 0 | struct smbd_server_connection *sconn = |
1682 | 0 | talloc_get_type_abort(private_data, |
1683 | 0 | struct smbd_server_connection); |
1684 | |
|
1685 | 0 | change_to_root_user(); |
1686 | 0 | DBG_NOTICE("Reloading services after SIGHUP\n"); |
1687 | 0 | reload_services(sconn, conn_snum_used, false); |
1688 | 0 | } |
1689 | | |
1690 | | static void smbd_setup_sig_hup_handler(struct smbd_server_connection *sconn) |
1691 | 0 | { |
1692 | 0 | struct tevent_signal *se; |
1693 | |
|
1694 | 0 | se = tevent_add_signal(sconn->ev_ctx, |
1695 | 0 | sconn, |
1696 | 0 | SIGHUP, 0, |
1697 | 0 | smbd_sig_hup_handler, |
1698 | 0 | sconn); |
1699 | 0 | if (!se) { |
1700 | 0 | exit_server("failed to setup SIGHUP handler"); |
1701 | 0 | } |
1702 | 0 | } |
1703 | | |
1704 | | static void smbd_conf_updated(struct messaging_context *msg, |
1705 | | void *private_data, |
1706 | | uint32_t msg_type, |
1707 | | struct server_id server_id, |
1708 | | DATA_BLOB *data) |
1709 | 0 | { |
1710 | 0 | struct smbd_server_connection *sconn = |
1711 | 0 | talloc_get_type_abort(private_data, |
1712 | 0 | struct smbd_server_connection); |
1713 | |
|
1714 | 0 | DEBUG(10,("smbd_conf_updated: Got message saying smb.conf was " |
1715 | 0 | "updated. Reloading.\n")); |
1716 | 0 | change_to_root_user(); |
1717 | 0 | reload_services(sconn, conn_snum_used, false); |
1718 | 0 | } |
1719 | | |
1720 | | static void smbd_id_cache_kill(struct messaging_context *msg_ctx, |
1721 | | void *private_data, |
1722 | | uint32_t msg_type, |
1723 | | struct server_id server_id, |
1724 | | DATA_BLOB* data) |
1725 | 0 | { |
1726 | 0 | const char *msg = (data && data->data) |
1727 | 0 | ? (const char *)data->data : "<NULL>"; |
1728 | 0 | struct id_cache_ref id; |
1729 | 0 | struct smbd_server_connection *sconn = |
1730 | 0 | talloc_get_type_abort(private_data, |
1731 | 0 | struct smbd_server_connection); |
1732 | |
|
1733 | 0 | if (!id_cache_ref_parse(msg, &id)) { |
1734 | 0 | DEBUG(0, ("Invalid ?ID: %s\n", msg)); |
1735 | 0 | return; |
1736 | 0 | } |
1737 | | |
1738 | 0 | if (id_in_use(sconn, &id)) { |
1739 | 0 | exit_server_cleanly(msg); |
1740 | 0 | } |
1741 | 0 | id_cache_delete_from_cache(&id); |
1742 | 0 | } |
1743 | | |
1744 | | struct smbd_tevent_trace_state { |
1745 | | struct tevent_context *ev; |
1746 | | TALLOC_CTX *frame; |
1747 | | struct smbd_server_connection *sconn; |
1748 | | SMBPROFILE_BASIC_ASYNC_STATE(profile_idle); |
1749 | | struct timeval before_wait_tv; |
1750 | | struct timeval after_wait_tv; |
1751 | | }; |
1752 | | |
1753 | | static inline void smbd_tevent_trace_callback_before_wait( |
1754 | | struct smbd_tevent_trace_state *state) |
1755 | 0 | { |
1756 | 0 | struct timeval now = timeval_current(); |
1757 | 0 | struct timeval diff; |
1758 | |
|
1759 | 0 | diff = tevent_timeval_until(&state->after_wait_tv, &now); |
1760 | 0 | if (diff.tv_sec > 3) { |
1761 | 0 | DBG_ERR("Handling event took %ld seconds!\n", (long)diff.tv_sec); |
1762 | 0 | } |
1763 | 0 | state->before_wait_tv = now; |
1764 | 0 | } |
1765 | | |
1766 | | static inline void smbd_tevent_trace_callback_after_wait( |
1767 | | struct smbd_tevent_trace_state *state) |
1768 | 0 | { |
1769 | 0 | struct timeval now = timeval_current(); |
1770 | 0 | struct timeval diff; |
1771 | |
|
1772 | 0 | diff = tevent_timeval_until(&state->before_wait_tv, &now); |
1773 | 0 | if (diff.tv_sec > 30) { |
1774 | 0 | DBG_NOTICE("No event for %ld seconds!\n", (long)diff.tv_sec); |
1775 | 0 | } |
1776 | 0 | state->after_wait_tv = now; |
1777 | 0 | } |
1778 | | |
1779 | | static inline void smbd_tevent_trace_callback_before_loop_once( |
1780 | | struct smbd_tevent_trace_state *state) |
1781 | 0 | { |
1782 | 0 | talloc_free(state->frame); |
1783 | 0 | state->frame = talloc_stackframe_pool(8192); |
1784 | 0 | } |
1785 | | |
1786 | | static inline void smbd_tevent_trace_callback_after_loop_once( |
1787 | | struct smbd_tevent_trace_state *state) |
1788 | 0 | { |
1789 | 0 | TALLOC_FREE(state->frame); |
1790 | 0 | } |
1791 | | |
1792 | | static void smbd_tevent_trace_callback(enum tevent_trace_point point, |
1793 | | void *private_data) |
1794 | 0 | { |
1795 | 0 | struct smbd_tevent_trace_state *state = |
1796 | 0 | (struct smbd_tevent_trace_state *)private_data; |
1797 | |
|
1798 | 0 | switch (point) { |
1799 | 0 | case TEVENT_TRACE_BEFORE_WAIT: |
1800 | 0 | break; |
1801 | 0 | case TEVENT_TRACE_AFTER_WAIT: |
1802 | 0 | break; |
1803 | 0 | case TEVENT_TRACE_BEFORE_LOOP_ONCE: |
1804 | 0 | smbd_tevent_trace_callback_before_loop_once(state); |
1805 | 0 | break; |
1806 | 0 | case TEVENT_TRACE_AFTER_LOOP_ONCE: |
1807 | 0 | smbd_tevent_trace_callback_after_loop_once(state); |
1808 | 0 | break; |
1809 | 0 | } |
1810 | | |
1811 | 0 | errno = 0; |
1812 | 0 | } |
1813 | | |
1814 | | static void smbd_tevent_trace_callback_debug(enum tevent_trace_point point, |
1815 | | void *private_data) |
1816 | 0 | { |
1817 | 0 | struct smbd_tevent_trace_state *state = |
1818 | 0 | (struct smbd_tevent_trace_state *)private_data; |
1819 | |
|
1820 | 0 | switch (point) { |
1821 | 0 | case TEVENT_TRACE_BEFORE_WAIT: |
1822 | 0 | smbd_tevent_trace_callback_before_wait(state); |
1823 | 0 | break; |
1824 | 0 | case TEVENT_TRACE_AFTER_WAIT: |
1825 | 0 | smbd_tevent_trace_callback_after_wait(state); |
1826 | 0 | break; |
1827 | 0 | case TEVENT_TRACE_BEFORE_LOOP_ONCE: |
1828 | 0 | smbd_tevent_trace_callback_before_loop_once(state); |
1829 | 0 | break; |
1830 | 0 | case TEVENT_TRACE_AFTER_LOOP_ONCE: |
1831 | 0 | smbd_tevent_trace_callback_after_loop_once(state); |
1832 | 0 | break; |
1833 | 0 | } |
1834 | | |
1835 | 0 | errno = 0; |
1836 | 0 | } |
1837 | | |
1838 | | static void smbd_tevent_trace_callback_profile(enum tevent_trace_point point, |
1839 | | void *private_data) |
1840 | 0 | { |
1841 | 0 | struct smbd_tevent_trace_state *state = |
1842 | 0 | (struct smbd_tevent_trace_state *)private_data; |
1843 | |
|
1844 | 0 | switch (point) { |
1845 | 0 | case TEVENT_TRACE_BEFORE_WAIT: |
1846 | 0 | smbd_tevent_trace_callback_before_wait(state); |
1847 | 0 | if (!smbprofile_dump_pending()) { |
1848 | | /* |
1849 | | * If there's no dump pending |
1850 | | * we don't want to schedule a new 1 sec timer. |
1851 | | * |
1852 | | * Instead we want to sleep as long as nothing happens. |
1853 | | */ |
1854 | 0 | smbprofile_dump_setup(NULL, NULL); |
1855 | 0 | } |
1856 | 0 | SMBPROFILE_BASIC_ASYNC_START(idle, profile_p, state->profile_idle); |
1857 | 0 | break; |
1858 | 0 | case TEVENT_TRACE_AFTER_WAIT: |
1859 | 0 | smbd_tevent_trace_callback_after_wait(state); |
1860 | 0 | SMBPROFILE_BASIC_ASYNC_END(state->profile_idle); |
1861 | 0 | if (!smbprofile_dump_pending()) { |
1862 | | /* |
1863 | | * We need to flush our state after sleeping |
1864 | | * (hopefully a long time). |
1865 | | */ |
1866 | 0 | smbprofile_dump(state->sconn); |
1867 | | /* |
1868 | | * future profiling events should trigger timers |
1869 | | * on our main event context. |
1870 | | */ |
1871 | 0 | smbprofile_dump_setup(state->ev, state->sconn); |
1872 | 0 | } |
1873 | 0 | break; |
1874 | 0 | case TEVENT_TRACE_BEFORE_LOOP_ONCE: |
1875 | 0 | smbd_tevent_trace_callback_before_loop_once(state); |
1876 | 0 | break; |
1877 | 0 | case TEVENT_TRACE_AFTER_LOOP_ONCE: |
1878 | 0 | smbd_tevent_trace_callback_after_loop_once(state); |
1879 | 0 | break; |
1880 | 0 | } |
1881 | | |
1882 | 0 | errno = 0; |
1883 | 0 | } |
1884 | | |
1885 | | /**************************************************************************** |
1886 | | Process commands from the client |
1887 | | ****************************************************************************/ |
1888 | | |
1889 | | void smbd_process(struct tevent_context *ev_ctx, |
1890 | | struct messaging_context *msg_ctx, |
1891 | | int sock_fd, |
1892 | | bool interactive, |
1893 | | enum smb_transport_type transport_type) |
1894 | 0 | { |
1895 | 0 | const struct loadparm_substitution *lp_sub = |
1896 | 0 | loadparm_s3_global_substitution(); |
1897 | 0 | struct smbXsrv_client *client = NULL; |
1898 | 0 | struct smbd_server_connection *sconn = NULL; |
1899 | 0 | struct smbXsrv_connection *xconn = NULL; |
1900 | 0 | const char *locaddr = NULL; |
1901 | 0 | const char *remaddr = NULL; |
1902 | 0 | int ret; |
1903 | 0 | NTSTATUS status; |
1904 | 0 | struct timeval tv = timeval_current(); |
1905 | 0 | struct smbd_tevent_trace_state trace_state = { |
1906 | 0 | .ev = ev_ctx, |
1907 | 0 | .frame = talloc_stackframe(), |
1908 | 0 | .before_wait_tv = tv, |
1909 | 0 | .after_wait_tv = tv, |
1910 | 0 | }; |
1911 | 0 | bool debug = lp_parm_bool(GLOBAL_SECTION_SNUM, |
1912 | 0 | "smbd", |
1913 | 0 | "debug events", |
1914 | 0 | CHECK_DEBUGLVL(DBGLVL_DEBUG)); |
1915 | 0 | NTTIME now = timeval_to_nttime(&tv); |
1916 | 0 | char *chroot_dir = NULL; |
1917 | 0 | int rc; |
1918 | |
|
1919 | 0 | status = smbXsrv_client_create(ev_ctx, ev_ctx, msg_ctx, now, &client); |
1920 | 0 | if (!NT_STATUS_IS_OK(status)) { |
1921 | 0 | DBG_ERR("smbXsrv_client_create(): %s\n", nt_errstr(status)); |
1922 | 0 | exit_server_cleanly("talloc_zero(struct smbXsrv_client).\n"); |
1923 | 0 | } |
1924 | | |
1925 | | /* |
1926 | | * TODO: remove this...:-) |
1927 | | */ |
1928 | 0 | global_smbXsrv_client = client; |
1929 | |
|
1930 | 0 | sconn = talloc_zero(client, struct smbd_server_connection); |
1931 | 0 | if (sconn == NULL) { |
1932 | 0 | exit_server("failed to create smbd_server_connection"); |
1933 | 0 | } |
1934 | 0 | trace_state.sconn = sconn; |
1935 | |
|
1936 | 0 | client->sconn = sconn; |
1937 | 0 | sconn->client = client; |
1938 | |
|
1939 | 0 | sconn->ev_ctx = ev_ctx; |
1940 | 0 | sconn->msg_ctx = msg_ctx; |
1941 | |
|
1942 | 0 | ret = pthreadpool_tevent_init(sconn, lp_aio_max_threads(), |
1943 | 0 | &sconn->pool); |
1944 | 0 | if (ret != 0) { |
1945 | 0 | exit_server("pthreadpool_tevent_init() failed."); |
1946 | 0 | } |
1947 | | |
1948 | 0 | if (!interactive) { |
1949 | 0 | smbd_setup_sig_term_handler(sconn); |
1950 | 0 | smbd_setup_sig_hup_handler(sconn); |
1951 | 0 | } |
1952 | |
|
1953 | 0 | status = smbd_add_connection(client, |
1954 | 0 | sock_fd, |
1955 | 0 | transport_type, |
1956 | 0 | now, |
1957 | 0 | &xconn); |
1958 | 0 | if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) { |
1959 | | /* |
1960 | | * send a negative session response "not listening on calling |
1961 | | * name" |
1962 | | */ |
1963 | 0 | unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; |
1964 | 0 | (void)smb1_srv_send(xconn, (char *)buf, false, 0, false); |
1965 | 0 | exit_server_cleanly("connection denied"); |
1966 | 0 | } else if (!NT_STATUS_IS_OK(status)) { |
1967 | 0 | exit_server_cleanly(nt_errstr(status)); |
1968 | 0 | } |
1969 | | |
1970 | 0 | sconn->local_address = |
1971 | 0 | tsocket_address_copy(xconn->local_address, sconn); |
1972 | 0 | if (sconn->local_address == NULL) { |
1973 | 0 | exit_server_cleanly("tsocket_address_copy() failed"); |
1974 | 0 | } |
1975 | 0 | sconn->remote_address = |
1976 | 0 | tsocket_address_copy(xconn->remote_address, sconn); |
1977 | 0 | if (sconn->remote_address == NULL) { |
1978 | 0 | exit_server_cleanly("tsocket_address_copy() failed"); |
1979 | 0 | } |
1980 | 0 | sconn->remote_hostname = |
1981 | 0 | talloc_strdup(sconn, xconn->remote_hostname); |
1982 | 0 | if (sconn->remote_hostname == NULL) { |
1983 | 0 | exit_server_cleanly("tsocket_strdup() failed"); |
1984 | 0 | } |
1985 | | |
1986 | 0 | client->global->local_address = |
1987 | 0 | tsocket_address_string(sconn->local_address, |
1988 | 0 | client->global); |
1989 | 0 | if (client->global->local_address == NULL) { |
1990 | 0 | exit_server_cleanly("tsocket_address_string() failed"); |
1991 | 0 | } |
1992 | 0 | client->global->remote_address = |
1993 | 0 | tsocket_address_string(sconn->remote_address, |
1994 | 0 | client->global); |
1995 | 0 | if (client->global->remote_address == NULL) { |
1996 | 0 | exit_server_cleanly("tsocket_address_string() failed"); |
1997 | 0 | } |
1998 | 0 | client->global->remote_name = |
1999 | 0 | talloc_strdup(client->global, sconn->remote_hostname); |
2000 | 0 | if (client->global->remote_name == NULL) { |
2001 | 0 | exit_server_cleanly("tsocket_strdup() failed"); |
2002 | 0 | } |
2003 | | |
2004 | 0 | if (tsocket_address_is_inet(sconn->local_address, "ip")) { |
2005 | 0 | locaddr = tsocket_address_inet_addr_string( |
2006 | 0 | sconn->local_address, |
2007 | 0 | talloc_tos()); |
2008 | 0 | if (locaddr == NULL) { |
2009 | 0 | DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n", |
2010 | 0 | __location__, strerror(errno))); |
2011 | 0 | exit_server_cleanly("tsocket_address_inet_addr_string remote failed.\n"); |
2012 | 0 | } |
2013 | 0 | } else { |
2014 | 0 | locaddr = "0.0.0.0"; |
2015 | 0 | } |
2016 | | |
2017 | 0 | if (tsocket_address_is_inet(sconn->remote_address, "ip")) { |
2018 | 0 | remaddr = tsocket_address_inet_addr_string( |
2019 | 0 | sconn->remote_address, |
2020 | 0 | talloc_tos()); |
2021 | 0 | if (remaddr == NULL) { |
2022 | 0 | DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n", |
2023 | 0 | __location__, strerror(errno))); |
2024 | 0 | exit_server_cleanly("tsocket_address_inet_addr_string remote failed.\n"); |
2025 | 0 | } |
2026 | 0 | } else { |
2027 | 0 | remaddr = "0.0.0.0"; |
2028 | 0 | } |
2029 | | |
2030 | | /* this is needed so that we get decent entries |
2031 | | in smbstatus for port 445 connects */ |
2032 | 0 | set_remote_machine_name(remaddr, false); |
2033 | 0 | reload_services(sconn, conn_snum_used, true); |
2034 | 0 | sub_set_socket_ids(remaddr, |
2035 | 0 | sconn->remote_hostname, |
2036 | 0 | locaddr); |
2037 | |
|
2038 | 0 | if (lp_preload_modules()) { |
2039 | 0 | smb_load_all_modules_absoute_path(lp_preload_modules()); |
2040 | 0 | } |
2041 | |
|
2042 | 0 | if (!init_account_policy()) { |
2043 | 0 | exit_server("Could not open account policy tdb.\n"); |
2044 | 0 | } |
2045 | | |
2046 | 0 | chroot_dir = lp_root_directory(talloc_tos(), lp_sub); |
2047 | 0 | if (chroot_dir[0] != '\0') { |
2048 | 0 | rc = chdir(chroot_dir); |
2049 | 0 | if (rc != 0) { |
2050 | 0 | DBG_ERR("Failed to chdir to %s\n", chroot_dir); |
2051 | 0 | exit_server("Failed to chdir()"); |
2052 | 0 | } |
2053 | | |
2054 | 0 | rc = chroot(chroot_dir); |
2055 | 0 | if (rc != 0) { |
2056 | 0 | DBG_ERR("Failed to change root to %s\n", chroot_dir); |
2057 | 0 | exit_server("Failed to chroot()"); |
2058 | 0 | } |
2059 | 0 | DBG_WARNING("Changed root to %s\n", chroot_dir); |
2060 | |
|
2061 | 0 | TALLOC_FREE(chroot_dir); |
2062 | 0 | } |
2063 | | |
2064 | 0 | if (!file_init(sconn)) { |
2065 | 0 | exit_server("file_init() failed"); |
2066 | 0 | } |
2067 | | |
2068 | | /* Setup oplocks */ |
2069 | 0 | if (!init_oplocks(sconn)) |
2070 | 0 | exit_server("Failed to init oplocks"); |
2071 | | |
2072 | | /* register our message handlers */ |
2073 | 0 | messaging_register(sconn->msg_ctx, sconn, |
2074 | 0 | MSG_SMB_FORCE_TDIS, msg_force_tdis); |
2075 | 0 | messaging_register( |
2076 | 0 | sconn->msg_ctx, |
2077 | 0 | sconn, |
2078 | 0 | MSG_SMB_FORCE_TDIS_DENIED, |
2079 | 0 | msg_force_tdis_denied); |
2080 | 0 | messaging_register(sconn->msg_ctx, sconn, |
2081 | 0 | MSG_SMB_CLOSE_FILE, msg_close_file); |
2082 | 0 | messaging_register(sconn->msg_ctx, sconn, |
2083 | 0 | MSG_SMB_FILE_RENAME, msg_file_was_renamed); |
2084 | |
|
2085 | 0 | id_cache_register_msgs(sconn->msg_ctx); |
2086 | 0 | messaging_deregister(sconn->msg_ctx, ID_CACHE_KILL, NULL); |
2087 | 0 | messaging_register(sconn->msg_ctx, sconn, |
2088 | 0 | ID_CACHE_KILL, smbd_id_cache_kill); |
2089 | |
|
2090 | 0 | messaging_deregister(sconn->msg_ctx, |
2091 | 0 | MSG_SMB_CONF_UPDATED, sconn->ev_ctx); |
2092 | 0 | messaging_register(sconn->msg_ctx, sconn, |
2093 | 0 | MSG_SMB_CONF_UPDATED, smbd_conf_updated); |
2094 | |
|
2095 | 0 | messaging_deregister(sconn->msg_ctx, MSG_SMB_KILL_CLIENT_IP, |
2096 | 0 | NULL); |
2097 | 0 | messaging_register(sconn->msg_ctx, sconn, |
2098 | 0 | MSG_SMB_KILL_CLIENT_IP, |
2099 | 0 | msg_kill_client_ip); |
2100 | |
|
2101 | 0 | messaging_deregister(sconn->msg_ctx, MSG_SMB_TELL_NUM_CHILDREN, NULL); |
2102 | |
|
2103 | 0 | messaging_deregister(sconn->msg_ctx, MSG_RELOAD_TLS_CERTIFICATES, NULL); |
2104 | | |
2105 | | /* |
2106 | | * Use the default MSG_DEBUG handler to avoid rebroadcasting |
2107 | | * MSGs to all child processes |
2108 | | */ |
2109 | 0 | messaging_deregister(sconn->msg_ctx, |
2110 | 0 | MSG_DEBUG, NULL); |
2111 | 0 | messaging_register(sconn->msg_ctx, NULL, |
2112 | 0 | MSG_DEBUG, debug_message); |
2113 | |
|
2114 | 0 | messaging_deregister(sconn->msg_ctx, MSG_SMB_IP_DROPPED, NULL); |
2115 | 0 | messaging_register(sconn->msg_ctx, |
2116 | 0 | sconn, |
2117 | 0 | MSG_SMB_IP_DROPPED, |
2118 | 0 | msg_kill_client_with_server_ip); |
2119 | |
|
2120 | 0 | #if defined(WITH_SMB1SERVER) |
2121 | 0 | if ((lp_keepalive() != 0) && |
2122 | 0 | !(event_add_idle(ev_ctx, |
2123 | 0 | NULL, |
2124 | 0 | tevent_timeval_set(lp_keepalive(), 0), |
2125 | 0 | "keepalive", |
2126 | 0 | keepalive_fn, |
2127 | 0 | sconn))) |
2128 | 0 | { |
2129 | 0 | DEBUG(0, ("Could not add keepalive event\n")); |
2130 | 0 | exit(1); |
2131 | 0 | } |
2132 | 0 | #endif |
2133 | | |
2134 | 0 | if (!(event_add_idle(ev_ctx, |
2135 | 0 | NULL, |
2136 | 0 | tevent_timeval_set(IDLE_CLOSED_TIMEOUT, 0), |
2137 | 0 | "deadtime", |
2138 | 0 | deadtime_fn, |
2139 | 0 | sconn))) |
2140 | 0 | { |
2141 | 0 | DEBUG(0, ("Could not add deadtime event\n")); |
2142 | 0 | exit(1); |
2143 | 0 | } |
2144 | | |
2145 | 0 | if (!(event_add_idle(ev_ctx, |
2146 | 0 | NULL, |
2147 | 0 | tevent_timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0), |
2148 | 0 | "housekeeping", |
2149 | 0 | housekeeping_fn, |
2150 | 0 | sconn))) |
2151 | 0 | { |
2152 | 0 | DEBUG(0, ("Could not add housekeeping event\n")); |
2153 | 0 | exit(1); |
2154 | 0 | } |
2155 | | |
2156 | 0 | smbprofile_dump_setup(ev_ctx, sconn); |
2157 | |
|
2158 | 0 | if (!init_dptrs(sconn)) { |
2159 | 0 | exit_server("init_dptrs() failed"); |
2160 | 0 | } |
2161 | | |
2162 | 0 | TALLOC_FREE(trace_state.frame); |
2163 | |
|
2164 | 0 | if (smbprofile_active()) { |
2165 | 0 | tevent_set_trace_callback(ev_ctx, |
2166 | 0 | smbd_tevent_trace_callback_profile, |
2167 | 0 | &trace_state); |
2168 | 0 | } else if (debug) { |
2169 | 0 | tevent_set_trace_callback(ev_ctx, |
2170 | 0 | smbd_tevent_trace_callback_debug, |
2171 | 0 | &trace_state); |
2172 | 0 | } else { |
2173 | 0 | tevent_set_trace_callback(ev_ctx, |
2174 | 0 | smbd_tevent_trace_callback, |
2175 | 0 | &trace_state); |
2176 | 0 | } |
2177 | |
|
2178 | 0 | ret = tevent_loop_wait(ev_ctx); |
2179 | 0 | if (ret != 0) { |
2180 | 0 | DEBUG(1, ("tevent_loop_wait failed: %d, %s," |
2181 | 0 | " exiting\n", ret, strerror(errno))); |
2182 | 0 | } |
2183 | |
|
2184 | 0 | TALLOC_FREE(trace_state.frame); |
2185 | |
|
2186 | | exit_server_cleanly(NULL); |
2187 | 0 | } |