352de85fd2c417496f075b3d7b32cc04a7711075
[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         uint8_t called_type;
180         const char *calling_name;
181         uint8_t calling_type;
182         struct tevent_req *req_139;
183         struct tevent_req *req_445;
184         int sock;
185         uint16_t port;
186 };
187
188 static int smbsock_connect_state_destructor(
189         struct smbsock_connect_state *state);
190 static void smbsock_connect_connected(struct tevent_req *subreq);
191 static void smbsock_connect_do_139(struct tevent_req *subreq);
192
193 struct tevent_req *smbsock_connect_send(TALLOC_CTX *mem_ctx,
194                                         struct tevent_context *ev,
195                                         const struct sockaddr_storage *addr,
196                                         uint16_t port,
197                                         const char *called_name,
198                                         int called_type,
199                                         const char *calling_name,
200                                         int calling_type)
201 {
202         struct tevent_req *req, *subreq;
203         struct smbsock_connect_state *state;
204
205         req = tevent_req_create(mem_ctx, &state, struct smbsock_connect_state);
206         if (req == NULL) {
207                 return NULL;
208         }
209         state->ev = ev;
210         state->addr = addr;
211         state->sock = -1;
212         state->called_name =
213                 (called_name != NULL) ? called_name : "*SMBSERVER";
214         state->called_type =
215                 (called_type != -1) ? called_type : 0x20;
216         state->calling_name =
217                 (calling_name != NULL) ? calling_name : global_myname();
218         state->calling_type =
219                 (calling_type != -1) ? calling_type : 0x00;
220
221         talloc_set_destructor(state, smbsock_connect_state_destructor);
222
223         if (port == 139) {
224                 subreq = tevent_wakeup_send(state, ev, timeval_set(0, 0));
225                 if (tevent_req_nomem(subreq, req)) {
226                         return tevent_req_post(req, ev);
227                 }
228                 tevent_req_set_callback(subreq, smbsock_connect_do_139, req);
229                 return req;
230         }
231         if (port != 0) {
232                 state->req_445 = open_socket_out_send(state, ev, addr, port,
233                                                       5000);
234                 if (tevent_req_nomem(state->req_445, req)) {
235                         return tevent_req_post(req, ev);
236                 }
237                 tevent_req_set_callback(
238                         state->req_445, smbsock_connect_connected, req);
239                 return req;
240         }
241
242         /*
243          * port==0, try both
244          */
245
246         state->req_445 = open_socket_out_send(state, ev, addr, 445, 5000);
247         if (tevent_req_nomem(state->req_445, req)) {
248                 return tevent_req_post(req, ev);
249         }
250         tevent_req_set_callback(state->req_445, smbsock_connect_connected,
251                                 req);
252
253         /*
254          * After 5 msecs, fire the 139 request
255          */
256         state->req_139 = tevent_wakeup_send(
257                 state, ev, timeval_current_ofs(0, 5000));
258         if (tevent_req_nomem(state->req_139, req)) {
259                 TALLOC_FREE(state->req_445);
260                 return tevent_req_post(req, ev);
261         }
262         tevent_req_set_callback(state->req_139, smbsock_connect_do_139,
263                                 req);
264         return req;
265 }
266
267 static int smbsock_connect_state_destructor(
268         struct smbsock_connect_state *state)
269 {
270         if (state->sock != -1) {
271                 close(state->sock);
272         }
273         return 0;
274 }
275
276 static void smbsock_connect_do_139(struct tevent_req *subreq)
277 {
278         struct tevent_req *req = tevent_req_callback_data(
279                 subreq, struct tevent_req);
280         struct smbsock_connect_state *state = tevent_req_data(
281                 req, struct smbsock_connect_state);
282         bool ret;
283
284         ret = tevent_wakeup_recv(subreq);
285         TALLOC_FREE(subreq);
286         if (!ret) {
287                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
288                 return;
289         }
290         state->req_139 = nb_connect_send(state, state->ev, state->addr,
291                                          state->called_name,
292                                          state->called_type,
293                                          state->calling_name,
294                                          state->calling_type);
295         if (tevent_req_nomem(state->req_139, req)) {
296                 return;
297         }
298         tevent_req_set_callback(state->req_139, smbsock_connect_connected,
299                                 req);
300 }
301
302 static void smbsock_connect_connected(struct tevent_req *subreq)
303 {
304         struct tevent_req *req = tevent_req_callback_data(
305                 subreq, struct tevent_req);
306         struct smbsock_connect_state *state = tevent_req_data(
307                 req, struct smbsock_connect_state);
308         struct tevent_req *unfinished_req;
309         NTSTATUS status;
310
311         if (subreq == state->req_445) {
312
313                 status = open_socket_out_recv(subreq, &state->sock);
314                 TALLOC_FREE(state->req_445);
315                 unfinished_req = state->req_139;
316                 state->port = 445;
317
318         } else if (subreq == state->req_139) {
319
320                 status = nb_connect_recv(subreq, &state->sock);
321                 TALLOC_FREE(state->req_139);
322                 unfinished_req = state->req_445;
323                 state->port = 139;
324
325         } else {
326                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
327                 return;
328         }
329
330         if (NT_STATUS_IS_OK(status)) {
331                 TALLOC_FREE(unfinished_req);
332                 state->req_139 = NULL;
333                 state->req_445 = NULL;
334                 tevent_req_done(req);
335                 return;
336         }
337         if (unfinished_req == NULL) {
338                 /*
339                  * Both requests failed
340                  */
341                 tevent_req_nterror(req, status);
342                 return;
343         }
344         /*
345          * Do nothing, wait for the second request to come here.
346          */
347 }
348
349 NTSTATUS smbsock_connect_recv(struct tevent_req *req, int *sock,
350                               uint16_t *ret_port)
351 {
352         struct smbsock_connect_state *state = tevent_req_data(
353                 req, struct smbsock_connect_state);
354         NTSTATUS status;
355
356         if (tevent_req_is_nterror(req, &status)) {
357                 return status;
358         }
359         *sock = state->sock;
360         state->sock = -1;
361         if (ret_port != NULL) {
362                 *ret_port = state->port;
363         }
364         return NT_STATUS_OK;
365 }
366
367 NTSTATUS smbsock_connect(const struct sockaddr_storage *addr, uint16_t port,
368                          const char *called_name, int called_type,
369                          const char *calling_name, int calling_type,
370                          int *pfd, uint16_t *ret_port)
371 {
372         TALLOC_CTX *frame = talloc_stackframe();
373         struct event_context *ev;
374         struct tevent_req *req;
375         NTSTATUS status = NT_STATUS_NO_MEMORY;
376
377         ev = event_context_init(frame);
378         if (ev == NULL) {
379                 goto fail;
380         }
381         req = smbsock_connect_send(frame, ev, addr, port,
382                                    called_name, called_type,
383                                    calling_name, calling_type);
384         if (req == NULL) {
385                 goto fail;
386         }
387         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
388                 goto fail;
389         }
390         status = smbsock_connect_recv(req, pfd, ret_port);
391  fail:
392         TALLOC_FREE(frame);
393         return status;
394 }
395
396 struct smbsock_any_connect_state {
397         struct tevent_context *ev;
398         const struct sockaddr_storage *addrs;
399         const char **called_names;
400         int *called_types;
401         const char **calling_names;
402         int *calling_types;
403         size_t num_addrs;
404         uint16_t port;
405
406         struct tevent_req **requests;
407         size_t num_sent;
408         size_t num_received;
409
410         int fd;
411         uint16_t chosen_port;
412         size_t chosen_index;
413 };
414
415 static bool smbsock_any_connect_send_next(
416         struct tevent_req *req, struct smbsock_any_connect_state *state);
417 static void smbsock_any_connect_trynext(struct tevent_req *subreq);
418 static void smbsock_any_connect_connected(struct tevent_req *subreq);
419
420 struct tevent_req *smbsock_any_connect_send(TALLOC_CTX *mem_ctx,
421                                             struct tevent_context *ev,
422                                             const struct sockaddr_storage *addrs,
423                                             const char **called_names,
424                                             int *called_types,
425                                             const char **calling_names,
426                                             int *calling_types,
427                                             size_t num_addrs, uint16_t port)
428 {
429         struct tevent_req *req, *subreq;
430         struct smbsock_any_connect_state *state;
431
432         req = tevent_req_create(mem_ctx, &state,
433                                 struct smbsock_any_connect_state);
434         if (req == NULL) {
435                 return NULL;
436         }
437         state->ev = ev;
438         state->addrs = addrs;
439         state->num_addrs = num_addrs;
440         state->called_names = called_names;
441         state->called_types = called_types;
442         state->calling_names = calling_names;
443         state->calling_types = calling_types;
444         state->port = port;
445
446         if (num_addrs == 0) {
447                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
448                 return tevent_req_post(req, ev);
449         }
450
451         state->requests = talloc_zero_array(state, struct tevent_req *,
452                                             num_addrs);
453         if (tevent_req_nomem(state->requests, req)) {
454                 return tevent_req_post(req, ev);
455         }
456         if (!smbsock_any_connect_send_next(req, state)) {
457                 return tevent_req_post(req, ev);
458         }
459         if (state->num_sent >= state->num_addrs) {
460                 return req;
461         }
462         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0, 10000));
463         if (tevent_req_nomem(subreq, req)) {
464                 return tevent_req_post(req, ev);
465         }
466         tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
467         return req;
468 }
469
470 static void smbsock_any_connect_trynext(struct tevent_req *subreq)
471 {
472         struct tevent_req *req = tevent_req_callback_data(
473                 subreq, struct tevent_req);
474         struct smbsock_any_connect_state *state = tevent_req_data(
475                 req, struct smbsock_any_connect_state);
476         bool ret;
477
478         ret = tevent_wakeup_recv(subreq);
479         TALLOC_FREE(subreq);
480         if (!ret) {
481                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
482                 return;
483         }
484         if (!smbsock_any_connect_send_next(req, state)) {
485                 return;
486         }
487         if (state->num_sent >= state->num_addrs) {
488                 return;
489         }
490         subreq = tevent_wakeup_send(state, state->ev,
491                                     tevent_timeval_set(0, 10000));
492         if (tevent_req_nomem(subreq, req)) {
493                 return;
494         }
495         tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
496 }
497
498 static bool smbsock_any_connect_send_next(
499         struct tevent_req *req, struct smbsock_any_connect_state *state)
500 {
501         struct tevent_req *subreq;
502
503         if (state->num_sent >= state->num_addrs) {
504                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
505                 return false;
506         }
507         subreq = smbsock_connect_send(
508                 state->requests, state->ev, &state->addrs[state->num_sent],
509                 state->port,
510                 (state->called_names != NULL)
511                 ? state->called_names[state->num_sent] : NULL,
512                 (state->called_types != NULL)
513                 ? state->called_types[state->num_sent] : -1,
514                 (state->calling_names != NULL)
515                 ? state->calling_names[state->num_sent] : NULL,
516                 (state->calling_types != NULL)
517                 ? state->calling_types[state->num_sent] : -1);
518         if (tevent_req_nomem(subreq, req)) {
519                 return false;
520         }
521         tevent_req_set_callback(subreq, smbsock_any_connect_connected, req);
522
523         state->requests[state->num_sent] = subreq;
524         state->num_sent += 1;
525
526         return true;
527 }
528
529 static void smbsock_any_connect_connected(struct tevent_req *subreq)
530 {
531         struct tevent_req *req = tevent_req_callback_data(
532                 subreq, struct tevent_req);
533         struct smbsock_any_connect_state *state = tevent_req_data(
534                 req, struct smbsock_any_connect_state);
535         NTSTATUS status;
536         int fd;
537         uint16_t chosen_port;
538         size_t i;
539         size_t chosen_index = 0;
540
541         for (i=0; i<state->num_sent; i++) {
542                 if (state->requests[i] == subreq) {
543                         chosen_index = i;
544                         break;
545                 }
546         }
547         if (i == state->num_sent) {
548                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
549                 return;
550         }
551
552         status = smbsock_connect_recv(subreq, &fd, &chosen_port);
553
554         TALLOC_FREE(subreq);
555         state->requests[chosen_index] = NULL;
556
557         if (NT_STATUS_IS_OK(status)) {
558                 /*
559                  * This will kill all the other requests
560                  */
561                 TALLOC_FREE(state->requests);
562                 state->fd = fd;
563                 state->chosen_port = chosen_port;
564                 state->chosen_index = chosen_index;
565                 tevent_req_done(req);
566                 return;
567         }
568
569         state->num_received += 1;
570         if (state->num_received <= state->num_addrs) {
571                 /*
572                  * More addrs pending, wait for the others
573                  */
574                 return;
575         }
576
577         /*
578          * This is the last response, none succeeded.
579          */
580         tevent_req_nterror(req, status);
581         return;
582 }
583
584 NTSTATUS smbsock_any_connect_recv(struct tevent_req *req, int *pfd,
585                                   size_t *chosen_index,
586                                   uint16_t *chosen_port)
587 {
588         struct smbsock_any_connect_state *state = tevent_req_data(
589                 req, struct smbsock_any_connect_state);
590         NTSTATUS status;
591
592         if (tevent_req_is_nterror(req, &status)) {
593                 return status;
594         }
595         *pfd = state->fd;
596         if (chosen_index != NULL) {
597                 *chosen_index = state->chosen_index;
598         }
599         if (chosen_port != NULL) {
600                 *chosen_port = state->chosen_port;
601         }
602         return NT_STATUS_OK;
603 }
604
605 NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs,
606                              const char **called_names,
607                              int *called_types,
608                              const char **calling_names,
609                              int *calling_types,
610                              size_t num_addrs,
611                              uint16_t port,
612                              int *pfd, size_t *chosen_index,
613                              uint16_t *chosen_port)
614 {
615         TALLOC_CTX *frame = talloc_stackframe();
616         struct event_context *ev;
617         struct tevent_req *req;
618         NTSTATUS status = NT_STATUS_NO_MEMORY;
619
620         ev = event_context_init(frame);
621         if (ev == NULL) {
622                 goto fail;
623         }
624         req = smbsock_any_connect_send(frame, ev, addrs,
625                                        called_names, called_types,
626                                        calling_names, calling_types,
627                                        num_addrs, port);
628         if (req == NULL) {
629                 goto fail;
630         }
631         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
632                 goto fail;
633         }
634         status = smbsock_any_connect_recv(req, pfd, chosen_index, chosen_port);
635  fail:
636         TALLOC_FREE(frame);
637         return status;
638 }