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