c103ab8d8cc1a9c731cc6cc27e0a5fd984bec827
[asterisk/asterisk.git] / main / stun.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  *
22  * \brief STUN Support
23  *
24  * \author Mark Spencer <markster@digium.com>
25  *
26  * \note STUN is defined in RFC 3489.
27  */
28
29 /*** MODULEINFO
30         <support_level>core</support_level>
31  ***/
32
33 #include "asterisk.h"
34
35 #include "asterisk/_private.h"
36 #include "asterisk/stun.h"
37 #include "asterisk/cli.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/channel.h"
40
41 static int stundebug;                   /*!< Are we debugging stun? */
42
43 /*!
44  * \brief STUN support code
45  *
46  * This code provides some support for doing STUN transactions.
47  * Eventually it should be moved elsewhere as other protocols
48  * than RTP can benefit from it - e.g. SIP.
49  * STUN is described in RFC3489 and it is based on the exchange
50  * of UDP packets between a client and one or more servers to
51  * determine the externally visible address (and port) of the client
52  * once it has gone through the NAT boxes that connect it to the
53  * outside.
54  * The simplest request packet is just the header defined in
55  * struct stun_header, and from the response we may just look at
56  * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
57  * By doing more transactions with different server addresses we
58  * may determine more about the behaviour of the NAT boxes, of
59  * course - the details are in the RFC.
60  *
61  * All STUN packets start with a simple header made of a type,
62  * length (excluding the header) and a 16-byte random transaction id.
63  * Following the header we may have zero or more attributes, each
64  * structured as a type, length and a value (whose format depends
65  * on the type, but often contains addresses).
66  * Of course all fields are in network format.
67  */
68
69 typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
70
71 struct stun_header {
72         unsigned short msgtype;
73         unsigned short msglen;
74         stun_trans_id  id;
75         unsigned char ies[0];
76 } __attribute__((packed));
77
78 struct stun_attr {
79         unsigned short attr;
80         unsigned short len;
81         unsigned char value[0];
82 } __attribute__((packed));
83
84 /*
85  * The format normally used for addresses carried by STUN messages.
86  */
87 struct stun_addr {
88         unsigned char unused;
89         unsigned char family;
90         unsigned short port;
91         unsigned int addr;
92 } __attribute__((packed));
93
94 /*! \brief STUN message types
95  * 'BIND' refers to transactions used to determine the externally
96  * visible addresses. 'SEC' refers to transactions used to establish
97  * a session key for subsequent requests.
98  * 'SEC' functionality is not supported here.
99  */
100
101 #define STUN_BINDREQ    0x0001
102 #define STUN_BINDRESP   0x0101
103 #define STUN_BINDERR    0x0111
104 #define STUN_SECREQ     0x0002
105 #define STUN_SECRESP    0x0102
106 #define STUN_SECERR     0x0112
107
108 /*! \brief Basic attribute types in stun messages.
109  * Messages can also contain custom attributes (codes above 0x7fff)
110  */
111 #define STUN_MAPPED_ADDRESS     0x0001
112 #define STUN_RESPONSE_ADDRESS   0x0002
113 #define STUN_CHANGE_REQUEST     0x0003
114 #define STUN_SOURCE_ADDRESS     0x0004
115 #define STUN_CHANGED_ADDRESS    0x0005
116 #define STUN_USERNAME           0x0006
117 #define STUN_PASSWORD           0x0007
118 #define STUN_MESSAGE_INTEGRITY  0x0008
119 #define STUN_ERROR_CODE         0x0009
120 #define STUN_UNKNOWN_ATTRIBUTES 0x000a
121 #define STUN_REFLECTED_FROM     0x000b
122
123 /*! \brief helper function to print message names */
124 static const char *stun_msg2str(int msg)
125 {
126         switch (msg) {
127         case STUN_BINDREQ:
128                 return "Binding Request";
129         case STUN_BINDRESP:
130                 return "Binding Response";
131         case STUN_BINDERR:
132                 return "Binding Error Response";
133         case STUN_SECREQ:
134                 return "Shared Secret Request";
135         case STUN_SECRESP:
136                 return "Shared Secret Response";
137         case STUN_SECERR:
138                 return "Shared Secret Error Response";
139         }
140         return "Non-RFC3489 Message";
141 }
142
143 /*! \brief helper function to print attribute names */
144 static const char *stun_attr2str(int msg)
145 {
146         switch (msg) {
147         case STUN_MAPPED_ADDRESS:
148                 return "Mapped Address";
149         case STUN_RESPONSE_ADDRESS:
150                 return "Response Address";
151         case STUN_CHANGE_REQUEST:
152                 return "Change Request";
153         case STUN_SOURCE_ADDRESS:
154                 return "Source Address";
155         case STUN_CHANGED_ADDRESS:
156                 return "Changed Address";
157         case STUN_USERNAME:
158                 return "Username";
159         case STUN_PASSWORD:
160                 return "Password";
161         case STUN_MESSAGE_INTEGRITY:
162                 return "Message Integrity";
163         case STUN_ERROR_CODE:
164                 return "Error Code";
165         case STUN_UNKNOWN_ATTRIBUTES:
166                 return "Unknown Attributes";
167         case STUN_REFLECTED_FROM:
168                 return "Reflected From";
169         }
170         return "Non-RFC3489 Attribute";
171 }
172
173 /*! \brief here we store credentials extracted from a message */
174 struct stun_state {
175         const char *username;
176         const char *password;
177 };
178
179 static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
180 {
181         if (stundebug)
182                 ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
183                             stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr), ntohs(attr->len));
184         switch (ntohs(attr->attr)) {
185         case STUN_USERNAME:
186                 state->username = (const char *) (attr->value);
187                 break;
188         case STUN_PASSWORD:
189                 state->password = (const char *) (attr->value);
190                 break;
191         default:
192                 if (stundebug)
193                         ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
194                                     stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr), ntohs(attr->len));
195         }
196         return 0;
197 }
198
199 /*! \brief append a string to an STUN message */
200 static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
201 {
202         int str_length = strlen(s);
203         int attr_length = str_length + ((~(str_length - 1)) & 0x3);
204         int size = sizeof(**attr) + attr_length;
205         if (*left > size) {
206                 (*attr)->attr = htons(attrval);
207                 (*attr)->len = htons(attr_length);
208                 memcpy((*attr)->value, s, str_length);
209                 memset((*attr)->value + str_length, 0, attr_length - str_length);
210                 (*attr) = (struct stun_attr *)((*attr)->value + attr_length);
211                 *len += size;
212                 *left -= size;
213         }
214 }
215
216 /*! \brief append an address to an STUN message */
217 static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
218 {
219         int size = sizeof(**attr) + 8;
220         struct stun_addr *addr;
221         if (*left > size) {
222                 (*attr)->attr = htons(attrval);
223                 (*attr)->len = htons(8);
224                 addr = (struct stun_addr *)((*attr)->value);
225                 addr->unused = 0;
226                 addr->family = 0x01;
227                 addr->port = sin->sin_port;
228                 addr->addr = sin->sin_addr.s_addr;
229                 (*attr) = (struct stun_attr *)((*attr)->value + 8);
230                 *len += size;
231                 *left -= size;
232         }
233 }
234
235 /*! \brief wrapper to send an STUN message */
236 static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
237 {
238         return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
239                       (struct sockaddr *)dst, sizeof(*dst));
240 }
241
242 /*!
243  * \internal
244  * \brief Compare the STUN tranaction IDs.
245  *
246  * \param left Transaction ID.
247  * \param right Transaction ID.
248  *
249  * \retval 0 if match.
250  * \retval non-zero if not match.
251  */
252 static int stun_id_cmp(stun_trans_id *left, stun_trans_id *right)
253 {
254         return memcmp(left, right, sizeof(*left));
255 }
256
257 /*! \brief helper function to generate a random request id */
258 static void stun_req_id(struct stun_header *req)
259 {
260         int x;
261         for (x = 0; x < 4; x++)
262                 req->id.id[x] = ast_random();
263 }
264
265 int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
266 {
267         struct stun_header *hdr = (struct stun_header *)data;
268         struct stun_attr *attr;
269         struct stun_state st;
270         int ret = AST_STUN_IGNORE;
271         int x;
272
273         /* On entry, 'len' is the length of the udp payload. After the
274          * initial checks it becomes the size of unprocessed options,
275          * while 'data' is advanced accordingly.
276          */
277         if (len < sizeof(struct stun_header)) {
278                 ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
279                 return -1;
280         }
281         len -= sizeof(struct stun_header);
282         data += sizeof(struct stun_header);
283         x = ntohs(hdr->msglen); /* len as advertised in the message */
284         if (stundebug)
285                 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), (unsigned)ntohs(hdr->msgtype), x);
286         if (x > len) {
287                 ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
288         } else
289                 len = x;
290         memset(&st, 0, sizeof(st));
291         while (len) {
292                 if (len < sizeof(struct stun_attr)) {
293                         ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
294                         break;
295                 }
296                 attr = (struct stun_attr *)data;
297                 /* compute total attribute length */
298                 x = ntohs(attr->len) + sizeof(struct stun_attr);
299                 if (x > len) {
300                         ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
301                         break;
302                 }
303                 if (stun_cb)
304                         stun_cb(attr, arg);
305                 if (stun_process_attr(&st, attr)) {
306                         ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr));
307                         break;
308                 }
309                 /* Clear attribute id: in case previous entry was a string,
310                  * this will act as the terminator for the string.
311                  */
312                 attr->attr = 0;
313                 data += x;
314                 len -= x;
315         }
316         /* Null terminate any string.
317          * XXX NOTE, we write past the size of the buffer passed by the
318          * caller, so this is potentially dangerous. The only thing that
319          * saves us is that usually we read the incoming message in a
320          * much larger buffer in the struct ast_rtp
321          */
322         *data = '\0';
323
324         /* Now prepare to generate a reply, which at the moment is done
325          * only for properly formed (len == 0) STUN_BINDREQ messages.
326          */
327         if (len == 0) {
328                 unsigned char respdata[1024];
329                 struct stun_header *resp = (struct stun_header *)respdata;
330                 int resplen = 0;        /* len excluding header */
331                 int respleft = sizeof(respdata) - sizeof(struct stun_header);
332                 char combined[33];
333
334                 resp->id = hdr->id;
335                 resp->msgtype = 0;
336                 resp->msglen = 0;
337                 attr = (struct stun_attr *)resp->ies;
338                 switch (ntohs(hdr->msgtype)) {
339                 case STUN_BINDREQ:
340                         if (stundebug)
341                                 ast_verbose("STUN Bind Request, username: %s\n",
342                                             st.username ? st.username : "<none>");
343                         if (st.username) {
344                                 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
345                                 snprintf(combined, sizeof(combined), "%16s%16s", st.username + 16, st.username);
346                         } else {
347                                 combined[0] = '\0';
348                         }
349
350                         append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
351                         resp->msglen = htons(resplen);
352                         resp->msgtype = htons(STUN_BINDRESP);
353                         stun_send(s, src, resp);
354                         ast_stun_request(s, src, combined, NULL);
355                         ret = AST_STUN_ACCEPT;
356                         break;
357                 default:
358                         if (stundebug)
359                                 ast_verbose("Dunno what to do with STUN message %04x (%s)\n", (unsigned)ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
360                 }
361         }
362         return ret;
363 }
364
365 /*! \brief Extract the STUN_MAPPED_ADDRESS from the stun response.
366  * This is used as a callback for stun_handle_response
367  * when called from ast_stun_request.
368  */
369 static int stun_get_mapped(struct stun_attr *attr, void *arg)
370 {
371         struct stun_addr *addr = (struct stun_addr *)(attr + 1);
372         struct sockaddr_in *sa = (struct sockaddr_in *)arg;
373
374         if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
375                 return 1;       /* not us. */
376         sa->sin_port = addr->port;
377         sa->sin_addr.s_addr = addr->addr;
378         return 0;
379 }
380
381 int ast_stun_request(int s, struct sockaddr_in *dst,
382         const char *username, struct sockaddr_in *answer)
383 {
384         struct stun_header *req;
385         struct stun_header *rsp;
386         unsigned char req_buf[1024];
387         unsigned char rsp_buf[1024];
388         int reqlen, reqleft;
389         struct stun_attr *attr;
390         int res = -1;
391         int retry;
392
393         if (answer) {
394                 /* Always clear answer in case the request fails. */
395                 memset(answer, 0, sizeof(struct sockaddr_in));
396         }
397
398         /* Create STUN bind request */
399         req = (struct stun_header *) req_buf;
400         stun_req_id(req);
401         reqlen = 0;
402         reqleft = sizeof(req_buf) - sizeof(struct stun_header);
403         attr = (struct stun_attr *) req->ies;
404         if (username) {
405                 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
406         }
407         req->msglen = htons(reqlen);
408         req->msgtype = htons(STUN_BINDREQ);
409
410         for (retry = 0; retry++ < 3;) { /* XXX make retries configurable */
411                 /* send request, possibly wait for reply */
412                 struct sockaddr_in src;
413                 socklen_t srclen;
414                 struct timeval start;
415
416                 /* Send STUN message. */
417                 res = stun_send(s, dst, req);
418                 if (res < 0) {
419                         ast_debug(1, "stun_send try %d failed: %s\n", retry, strerror(errno));
420                         break;
421                 }
422                 if (!answer) {
423                         /* Successful send since we don't care about any response. */
424                         res = 0;
425                         break;
426                 }
427
428                 start = ast_tvnow();
429 try_again:
430                 /* Wait for response. */
431                 {
432                         struct pollfd pfds = { .fd = s, .events = POLLIN };
433                         int ms;
434
435                         ms = ast_remaining_ms(start, 3000);
436                         if (ms <= 0) {
437                                 /* No response, timeout */
438                                 res = 1;
439                                 continue;
440                         }
441                         res = ast_poll(&pfds, 1, ms);
442                         if (res < 0) {
443                                 /* Error */
444                                 continue;
445                         }
446                         if (!res) {
447                                 /* No response, timeout */
448                                 res = 1;
449                                 continue;
450                         }
451                 }
452
453                 /* Read STUN response. */
454                 memset(&src, 0, sizeof(src));
455                 srclen = sizeof(src);
456                 /* XXX pass sizeof(rsp_buf) - 1 in the size, because stun_handle_packet might
457                  * write past the end of the buffer.
458                  */
459                 res = recvfrom(s, rsp_buf, sizeof(rsp_buf) - 1,
460                         0, (struct sockaddr *) &src, &srclen);
461                 if (res < 0) {
462                         ast_debug(1, "recvfrom try %d failed: %s\n", retry, strerror(errno));
463                         break;
464                 }
465
466                 /* Process the STUN response. */
467                 rsp = (struct stun_header *) rsp_buf;
468                 if (ast_stun_handle_packet(s, &src, rsp_buf, res, stun_get_mapped, answer)
469                         || (rsp->msgtype != htons(STUN_BINDRESP)
470                                 && rsp->msgtype != htons(STUN_BINDERR))
471                         || stun_id_cmp(&req->id, &rsp->id)) {
472                         /* Bad STUN packet, not right type, or transaction ID did not match. */
473                         memset(answer, 0, sizeof(struct sockaddr_in));
474
475                         /* Was not a resonse to our request. */
476                         goto try_again;
477                 }
478                 /* Success.  answer contains the external address if available. */
479                 res = 0;
480                 break;
481         }
482         return res;
483 }
484
485 static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
486 {
487         switch (cmd) {
488         case CLI_INIT:
489                 e->command = "stun set debug {on|off}";
490                 e->usage =
491                         "Usage: stun set debug {on|off}\n"
492                         "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
493                         "       debugging\n";
494                 return NULL;
495         case CLI_GENERATE:
496                 return NULL;
497         }
498
499         if (a->argc != e->args)
500                 return CLI_SHOWUSAGE;
501
502         if (!strncasecmp(a->argv[e->args-1], "on", 2))
503                 stundebug = 1;
504         else if (!strncasecmp(a->argv[e->args-1], "off", 3))
505                 stundebug = 0;
506         else
507                 return CLI_SHOWUSAGE;
508
509         ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
510         return CLI_SUCCESS;
511 }
512
513 static struct ast_cli_entry cli_stun[] = {
514         AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
515 };
516
517 static void stun_shutdown(void)
518 {
519         ast_cli_unregister_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
520 }
521
522 /*! \brief Initialize the STUN system in Asterisk */
523 void ast_stun_init(void)
524 {
525         ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
526         ast_register_cleanup(stun_shutdown);
527 }