s3: Fix connecting to port-139 only servers
[samba.git] / source3 / libsmb / smbsock_connect.c
1 /*
2    Unix SMB/CIFS implementation.
3    Connect to 445 and 139/nbsesssetup
4    Copyright (C) Volker Lendecke 2010
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "../lib/async_req/async_sock.h"
22 #include "async_smb.h"
23
24 struct nb_connect_state {
25         struct tevent_context *ev;
26         const struct sockaddr_storage *addr;
27         const char *called_name;
28         int sock;
29
30         struct nmb_name called;
31         struct nmb_name calling;
32 };
33
34 static int nb_connect_state_destructor(struct nb_connect_state *state);
35 static void nb_connect_connected(struct tevent_req *subreq);
36 static void nb_connect_done(struct tevent_req *subreq);
37
38 static struct tevent_req *nb_connect_send(TALLOC_CTX *mem_ctx,
39                                           struct tevent_context *ev,
40                                           const struct sockaddr_storage *addr,
41                                           const char *called_name,
42                                           int called_type,
43                                           const char *calling_name,
44                                           int calling_type)
45 {
46         struct tevent_req *req, *subreq;
47         struct nb_connect_state *state;
48
49         req = tevent_req_create(mem_ctx, &state, struct nb_connect_state);
50         if (req == NULL) {
51                 return NULL;
52         }
53         state->ev = ev;
54         state->called_name = called_name;
55         state->addr = addr;
56
57         state->sock = -1;
58         make_nmb_name(&state->called, called_name, called_type);
59         make_nmb_name(&state->calling, calling_name, calling_type);
60
61         talloc_set_destructor(state, nb_connect_state_destructor);
62
63         subreq = open_socket_out_send(state, ev, addr, 139, 5000);
64         if (tevent_req_nomem(subreq, req)) {
65                 return tevent_req_post(req, ev);
66         }
67         tevent_req_set_callback(subreq, nb_connect_connected, req);
68         return req;
69 }
70
71 static int nb_connect_state_destructor(struct nb_connect_state *state)
72 {
73         if (state->sock != -1) {
74                 close(state->sock);
75         }
76         return 0;
77 }
78
79 static void nb_connect_connected(struct tevent_req *subreq)
80 {
81         struct tevent_req *req = tevent_req_callback_data(
82                 subreq, struct tevent_req);
83         struct nb_connect_state *state = tevent_req_data(
84                 req, struct nb_connect_state);
85         NTSTATUS status;
86
87         status = open_socket_out_recv(subreq, &state->sock);
88         TALLOC_FREE(subreq);
89         if (!NT_STATUS_IS_OK(status)) {
90                 tevent_req_nterror(req, status);
91                 return;
92         }
93         subreq = cli_session_request_send(state, state->ev, state->sock,
94                                           &state->called, &state->calling);
95         if (tevent_req_nomem(subreq, req)) {
96                 return;
97         }
98         tevent_req_set_callback(subreq, nb_connect_done, req);
99 }
100
101 static void nb_connect_done(struct tevent_req *subreq)
102 {
103         struct tevent_req *req = tevent_req_callback_data(
104                 subreq, struct tevent_req);
105         struct nb_connect_state *state = tevent_req_data(
106                 req, struct nb_connect_state);
107         bool ret;
108         int err;
109         uint8_t resp;
110
111         ret = cli_session_request_recv(subreq, &err, &resp);
112         TALLOC_FREE(subreq);
113         if (!ret) {
114                 tevent_req_nterror(req, map_nt_error_from_unix(err));
115                 return;
116         }
117
118         /*
119          * RFC1002: 0x82 - POSITIVE SESSION RESPONSE
120          */
121
122         if (resp != 0x82) {
123                 /*
124                  * The server did not like our session request
125                  */
126                 close(state->sock);
127                 state->sock = -1;
128
129                 if (strequal(state->called_name, "*SMBSERVER")) {
130                         /*
131                          * Here we could try a name status request and
132                          * use the first 0x20 type name.
133                          */
134                         tevent_req_nterror(
135                                 req, NT_STATUS_RESOURCE_NAME_NOT_FOUND);
136                         return;
137                 }
138
139                 /*
140                  * We could be subtle and distinguish between
141                  * different failure modes, but what we do here
142                  * instead is just retry with *SMBSERVER type 0x20.
143                  */
144                 state->called_name = "*SMBSERVER";
145                 make_nmb_name(&state->called, state->called_name, 0x20);
146
147                 subreq = open_socket_out_send(state, state->ev, state->addr,
148                                               139, 5000);
149                 if (tevent_req_nomem(subreq, req)) {
150                         return;
151                 }
152                 tevent_req_set_callback(subreq, nb_connect_connected, req);
153                 return;
154         }
155
156         tevent_req_done(req);
157         return;
158
159 }
160
161 static NTSTATUS nb_connect_recv(struct tevent_req *req, int *sock)
162 {
163         struct nb_connect_state *state = tevent_req_data(
164                 req, struct nb_connect_state);
165         NTSTATUS status;
166
167         if (tevent_req_is_nterror(req, &status)) {
168                 return status;
169         }
170         *sock = state->sock;
171         state->sock = -1;
172         return NT_STATUS_OK;
173 }
174
175 struct smbsock_connect_state {
176         struct tevent_context *ev;
177         const struct sockaddr_storage *addr;
178         const char *called_name;
179         const char *calling_name;
180         struct tevent_req *req_139;
181         struct tevent_req *req_445;
182         int sock;
183         uint16_t port;
184 };
185
186 static int smbsock_connect_state_destructor(
187         struct smbsock_connect_state *state);
188 static void smbsock_connect_connected(struct tevent_req *subreq);
189 static void smbsock_connect_do_139(struct tevent_req *subreq);
190
191 struct tevent_req *smbsock_connect_send(TALLOC_CTX *mem_ctx,
192                                         struct tevent_context *ev,
193                                         const struct sockaddr_storage *addr,
194                                         const char *called_name,
195                                         const char *calling_name)
196 {
197         struct tevent_req *req, *subreq;
198         struct smbsock_connect_state *state;
199
200         req = tevent_req_create(mem_ctx, &state, struct smbsock_connect_state);
201         if (req == NULL) {
202                 return NULL;
203         }
204         state->ev = ev;
205         state->addr = addr;
206         state->sock = -1;
207         state->called_name =
208                 (called_name != NULL) ? called_name : "*SMBSERVER";
209         state->calling_name =
210                 (calling_name != NULL) ? calling_name : global_myname();
211
212         talloc_set_destructor(state, smbsock_connect_state_destructor);
213
214         state->req_445 = open_socket_out_send(state, ev, addr, 445, 5000);
215         if (tevent_req_nomem(state->req_445, req)) {
216                 return tevent_req_post(req, ev);
217         }
218         tevent_req_set_callback(state->req_445, smbsock_connect_connected,
219                                 req);
220
221         /*
222          * After 5 msecs, fire the 139 request
223          */
224         state->req_139 = tevent_wakeup_send(
225                 state, ev, timeval_current_ofs(0, 5000));
226         if (tevent_req_nomem(state->req_139, req)) {
227                 TALLOC_FREE(state->req_445);
228                 return tevent_req_post(req, ev);
229         }
230         tevent_req_set_callback(state->req_139, smbsock_connect_do_139,
231                                 req);
232         return req;
233 }
234
235 static int smbsock_connect_state_destructor(
236         struct smbsock_connect_state *state)
237 {
238         if (state->sock != -1) {
239                 close(state->sock);
240         }
241         return 0;
242 }
243
244 static void smbsock_connect_do_139(struct tevent_req *subreq)
245 {
246         struct tevent_req *req = tevent_req_callback_data(
247                 subreq, struct tevent_req);
248         struct smbsock_connect_state *state = tevent_req_data(
249                 req, struct smbsock_connect_state);
250         bool ret;
251
252         ret = tevent_wakeup_recv(subreq);
253         TALLOC_FREE(subreq);
254         if (!ret) {
255                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
256                 return;
257         }
258         state->req_139 = nb_connect_send(state, state->ev, state->addr,
259                                          state->called_name, 0x20,
260                                          state->calling_name, 0x0);
261         if (tevent_req_nomem(state->req_139, req)) {
262                 return;
263         }
264         tevent_req_set_callback(state->req_139, smbsock_connect_connected,
265                                 req);
266 }
267
268 static void smbsock_connect_connected(struct tevent_req *subreq)
269 {
270         struct tevent_req *req = tevent_req_callback_data(
271                 subreq, struct tevent_req);
272         struct smbsock_connect_state *state = tevent_req_data(
273                 req, struct smbsock_connect_state);
274         struct tevent_req *unfinished_req;
275         NTSTATUS status;
276
277         if (subreq == state->req_445) {
278
279                 status = open_socket_out_recv(subreq, &state->sock);
280                 TALLOC_FREE(state->req_445);
281                 unfinished_req = state->req_139;
282                 state->port = 445;
283
284         } else if (subreq == state->req_139) {
285
286                 status = nb_connect_recv(subreq, &state->sock);
287                 TALLOC_FREE(state->req_139);
288                 unfinished_req = state->req_445;
289                 state->port = 139;
290
291         } else {
292                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
293                 return;
294         }
295
296         if (NT_STATUS_IS_OK(status)) {
297                 TALLOC_FREE(unfinished_req);
298                 state->req_139 = NULL;
299                 state->req_445 = NULL;
300                 tevent_req_done(req);
301                 return;
302         }
303         if (unfinished_req == NULL) {
304                 /*
305                  * Both requests failed
306                  */
307                 tevent_req_nterror(req, status);
308                 return;
309         }
310         /*
311          * Do nothing, wait for the second request to come here.
312          */
313 }
314
315 NTSTATUS smbsock_connect_recv(struct tevent_req *req, int *sock,
316                           uint16_t *port)
317 {
318         struct smbsock_connect_state *state = tevent_req_data(
319                 req, struct smbsock_connect_state);
320         NTSTATUS status;
321
322         if (tevent_req_is_nterror(req, &status)) {
323                 return status;
324         }
325         *sock = state->sock;
326         state->sock = -1;
327         if (port != NULL) {
328                 *port = state->port;
329         }
330         return NT_STATUS_OK;
331 }
332
333 NTSTATUS smbsock_connect(const struct sockaddr_storage *addr,
334                          const char *called_name, const char *calling_name,
335                          int *pfd, uint16_t *port)
336 {
337         TALLOC_CTX *frame = talloc_stackframe();
338         struct event_context *ev;
339         struct tevent_req *req;
340         NTSTATUS status = NT_STATUS_NO_MEMORY;
341
342         ev = event_context_init(frame);
343         if (ev == NULL) {
344                 goto fail;
345         }
346         req = smbsock_connect_send(frame, ev, addr, called_name, calling_name);
347         if (req == NULL) {
348                 goto fail;
349         }
350         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
351                 goto fail;
352         }
353         status = smbsock_connect_recv(req, pfd, port);
354  fail:
355         TALLOC_FREE(frame);
356         return status;
357 }
358
359 struct smbsock_any_connect_state {
360         struct tevent_context *ev;
361         const struct sockaddr_storage *addrs;
362         const char **called_names;
363         size_t num_addrs;
364
365         struct tevent_req **requests;
366         size_t num_sent;
367         size_t num_received;
368
369         int fd;
370         uint16_t port;
371         size_t chosen_index;
372 };
373
374 static bool smbsock_any_connect_send_next(
375         struct tevent_req *req, struct smbsock_any_connect_state *state);
376 static void smbsock_any_connect_trynext(struct tevent_req *subreq);
377 static void smbsock_any_connect_connected(struct tevent_req *subreq);
378
379 struct tevent_req *smbsock_any_connect_send(TALLOC_CTX *mem_ctx,
380                                             struct tevent_context *ev,
381                                             const struct sockaddr_storage *addrs,
382                                             const char **called_names,
383                                             size_t num_addrs)
384 {
385         struct tevent_req *req, *subreq;
386         struct smbsock_any_connect_state *state;
387
388         req = tevent_req_create(mem_ctx, &state,
389                                 struct smbsock_any_connect_state);
390         if (req == NULL) {
391                 return NULL;
392         }
393         state->ev = ev;
394         state->addrs = addrs;
395         state->num_addrs = num_addrs;
396         state->called_names = called_names;
397
398         if (num_addrs == 0) {
399                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
400                 return tevent_req_post(req, ev);
401         }
402
403         state->requests = talloc_zero_array(state, struct tevent_req *,
404                                             num_addrs);
405         if (tevent_req_nomem(state->requests, req)) {
406                 return tevent_req_post(req, ev);
407         }
408         if (!smbsock_any_connect_send_next(req, state)) {
409                 return tevent_req_post(req, ev);
410         }
411         if (state->num_sent >= state->num_addrs) {
412                 return req;
413         }
414         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0, 10000));
415         if (tevent_req_nomem(subreq, req)) {
416                 return tevent_req_post(req, ev);
417         }
418         tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
419         return req;
420 }
421
422 static void smbsock_any_connect_trynext(struct tevent_req *subreq)
423 {
424         struct tevent_req *req = tevent_req_callback_data(
425                 subreq, struct tevent_req);
426         struct smbsock_any_connect_state *state = tevent_req_data(
427                 req, struct smbsock_any_connect_state);
428         bool ret;
429
430         ret = tevent_wakeup_recv(subreq);
431         TALLOC_FREE(subreq);
432         if (!ret) {
433                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
434                 return;
435         }
436         if (!smbsock_any_connect_send_next(req, state)) {
437                 return;
438         }
439         if (state->num_sent >= state->num_addrs) {
440                 return;
441         }
442         subreq = tevent_wakeup_send(state, state->ev,
443                                     tevent_timeval_set(0, 10000));
444         if (tevent_req_nomem(subreq, req)) {
445                 return;
446         }
447         tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
448 }
449
450 static bool smbsock_any_connect_send_next(
451         struct tevent_req *req, struct smbsock_any_connect_state *state)
452 {
453         struct tevent_req *subreq;
454
455         if (state->num_sent >= state->num_addrs) {
456                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
457                 return false;
458         }
459         subreq = smbsock_connect_send(
460                 state->requests, state->ev, &state->addrs[state->num_sent],
461                 (state->called_names != NULL)
462                 ? state->called_names[state->num_sent] : NULL,
463                 NULL);
464         if (tevent_req_nomem(subreq, req)) {
465                 return false;
466         }
467         tevent_req_set_callback(subreq, smbsock_any_connect_connected, req);
468
469         state->requests[state->num_sent] = subreq;
470         state->num_sent += 1;
471
472         return true;
473 }
474
475 static void smbsock_any_connect_connected(struct tevent_req *subreq)
476 {
477         struct tevent_req *req = tevent_req_callback_data(
478                 subreq, struct tevent_req);
479         struct smbsock_any_connect_state *state = tevent_req_data(
480                 req, struct smbsock_any_connect_state);
481         NTSTATUS status;
482         int fd;
483         uint16_t port;
484         size_t i;
485         size_t chosen_index = 0;
486
487         for (i=0; i<state->num_sent; i++) {
488                 if (state->requests[i] == subreq) {
489                         chosen_index = i;
490                         break;
491                 }
492         }
493         if (i == state->num_sent) {
494                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
495                 return;
496         }
497
498         status = smbsock_connect_recv(subreq, &fd, &port);
499
500         TALLOC_FREE(subreq);
501         state->requests[chosen_index] = NULL;
502
503         if (NT_STATUS_IS_OK(status)) {
504                 /*
505                  * This will kill all the other requests
506                  */
507                 TALLOC_FREE(state->requests);
508                 state->fd = fd;
509                 state->port = port;
510                 state->chosen_index = chosen_index;
511                 tevent_req_done(req);
512                 return;
513         }
514
515         state->num_received += 1;
516         if (state->num_received <= state->num_addrs) {
517                 /*
518                  * More addrs pending, wait for the others
519                  */
520                 return;
521         }
522
523         /*
524          * This is the last response, none succeeded.
525          */
526         tevent_req_nterror(req, status);
527         return;
528 }
529
530 NTSTATUS smbsock_any_connect_recv(struct tevent_req *req, int *pfd,
531                                   size_t *chosen_index, uint16_t *port)
532 {
533         struct smbsock_any_connect_state *state = tevent_req_data(
534                 req, struct smbsock_any_connect_state);
535         NTSTATUS status;
536
537         if (tevent_req_is_nterror(req, &status)) {
538                 return status;
539         }
540         *pfd = state->fd;
541         if (chosen_index != NULL) {
542                 *chosen_index = state->chosen_index;
543         }
544         if (port != NULL) {
545                 *port = state->port;
546         }
547         return NT_STATUS_OK;
548 }
549
550 NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs,
551                              const char **called_names, size_t num_addrs,
552                              int *pfd, size_t *chosen_index, uint16_t *port)
553 {
554         TALLOC_CTX *frame = talloc_stackframe();
555         struct event_context *ev;
556         struct tevent_req *req;
557         NTSTATUS status = NT_STATUS_NO_MEMORY;
558
559         ev = event_context_init(frame);
560         if (ev == NULL) {
561                 goto fail;
562         }
563         req = smbsock_any_connect_send(frame, ev, addrs, called_names,
564                                        num_addrs);
565         if (req == NULL) {
566                 goto fail;
567         }
568         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
569                 goto fail;
570         }
571         status = smbsock_any_connect_recv(req, pfd, chosen_index, port);
572  fail:
573         TALLOC_FREE(frame);
574         return status;
575 }