Replace most uses of ast_register_atexit with ast_register_cleanup.
[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 str_length = strlen(s);
205         int attr_length = str_length + ((~(str_length - 1)) & 0x3);
206         int size = sizeof(**attr) + attr_length;
207         if (*left > size) {
208                 (*attr)->attr = htons(attrval);
209                 (*attr)->len = htons(attr_length);
210                 memcpy((*attr)->value, s, str_length);
211                 memset((*attr)->value + str_length, 0, attr_length - str_length);
212                 (*attr) = (struct stun_attr *)((*attr)->value + attr_length);
213                 *len += size;
214                 *left -= size;
215         }
216 }
217
218 /*! \brief append an address to an STUN message */
219 static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
220 {
221         int size = sizeof(**attr) + 8;
222         struct stun_addr *addr;
223         if (*left > size) {
224                 (*attr)->attr = htons(attrval);
225                 (*attr)->len = htons(8);
226                 addr = (struct stun_addr *)((*attr)->value);
227                 addr->unused = 0;
228                 addr->family = 0x01;
229                 addr->port = sin->sin_port;
230                 addr->addr = sin->sin_addr.s_addr;
231                 (*attr) = (struct stun_attr *)((*attr)->value + 8);
232                 *len += size;
233                 *left -= size;
234         }
235 }
236
237 /*! \brief wrapper to send an STUN message */
238 static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
239 {
240         return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
241                       (struct sockaddr *)dst, sizeof(*dst));
242 }
243
244 /*!
245  * \internal
246  * \brief Compare the STUN tranaction IDs.
247  *
248  * \param left Transaction ID.
249  * \param right Transaction ID.
250  *
251  * \retval 0 if match.
252  * \retval non-zero if not match.
253  */
254 static int stun_id_cmp(stun_trans_id *left, stun_trans_id *right)
255 {
256         return memcmp(left, right, sizeof(*left));
257 }
258
259 /*! \brief helper function to generate a random request id */
260 static void stun_req_id(struct stun_header *req)
261 {
262         int x;
263         for (x = 0; x < 4; x++)
264                 req->id.id[x] = ast_random();
265 }
266
267 int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
268 {
269         struct stun_header *hdr = (struct stun_header *)data;
270         struct stun_attr *attr;
271         struct stun_state st;
272         int ret = AST_STUN_IGNORE;
273         int x;
274
275         /* On entry, 'len' is the length of the udp payload. After the
276          * initial checks it becomes the size of unprocessed options,
277          * while 'data' is advanced accordingly.
278          */
279         if (len < sizeof(struct stun_header)) {
280                 ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
281                 return -1;
282         }
283         len -= sizeof(struct stun_header);
284         data += sizeof(struct stun_header);
285         x = ntohs(hdr->msglen); /* len as advertised in the message */
286         if (stundebug)
287                 ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), (unsigned)ntohs(hdr->msgtype), x);
288         if (x > len) {
289                 ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
290         } else
291                 len = x;
292         memset(&st, 0, sizeof(st));
293         while (len) {
294                 if (len < sizeof(struct stun_attr)) {
295                         ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
296                         break;
297                 }
298                 attr = (struct stun_attr *)data;
299                 /* compute total attribute length */
300                 x = ntohs(attr->len) + sizeof(struct stun_attr);
301                 if (x > len) {
302                         ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
303                         break;
304                 }
305                 if (stun_cb)
306                         stun_cb(attr, arg);
307                 if (stun_process_attr(&st, attr)) {
308                         ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), (unsigned)ntohs(attr->attr));
309                         break;
310                 }
311                 /* Clear attribute id: in case previous entry was a string,
312                  * this will act as the terminator for the string.
313                  */
314                 attr->attr = 0;
315                 data += x;
316                 len -= x;
317         }
318         /* Null terminate any string.
319          * XXX NOTE, we write past the size of the buffer passed by the
320          * caller, so this is potentially dangerous. The only thing that
321          * saves us is that usually we read the incoming message in a
322          * much larger buffer in the struct ast_rtp
323          */
324         *data = '\0';
325
326         /* Now prepare to generate a reply, which at the moment is done
327          * only for properly formed (len == 0) STUN_BINDREQ messages.
328          */
329         if (len == 0) {
330                 unsigned char respdata[1024];
331                 struct stun_header *resp = (struct stun_header *)respdata;
332                 int resplen = 0;        /* len excluding header */
333                 int respleft = sizeof(respdata) - sizeof(struct stun_header);
334                 char combined[33];
335
336                 resp->id = hdr->id;
337                 resp->msgtype = 0;
338                 resp->msglen = 0;
339                 attr = (struct stun_attr *)resp->ies;
340                 switch (ntohs(hdr->msgtype)) {
341                 case STUN_BINDREQ:
342                         if (stundebug)
343                                 ast_verbose("STUN Bind Request, username: %s\n",
344                                             st.username ? st.username : "<none>");
345                         if (st.username) {
346                                 append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
347                                 snprintf(combined, sizeof(combined), "%16s%16s", st.username + 16, st.username);
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         req->msgtype = 0;
404         req->msglen = 0;
405         attr = (struct stun_attr *) req->ies;
406         if (username) {
407                 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
408         }
409         req->msglen = htons(reqlen);
410         req->msgtype = htons(STUN_BINDREQ);
411
412         for (retry = 0; retry++ < 3;) { /* XXX make retries configurable */
413                 /* send request, possibly wait for reply */
414                 struct sockaddr_in src;
415                 socklen_t srclen;
416
417                 /* Send STUN message. */
418                 res = stun_send(s, dst, req);
419                 if (res < 0) {
420                         ast_debug(1, "stun_send try %d failed: %s\n", retry, strerror(errno));
421                         break;
422                 }
423                 if (!answer) {
424                         /* Successful send since we don't care about any response. */
425                         res = 0;
426                         break;
427                 }
428
429 try_again:
430                 /* Wait for response. */
431                 {
432                         struct pollfd pfds = { .fd = s, .events = POLLIN };
433
434                         res = ast_poll(&pfds, 1, 3000);
435                         if (res < 0) {
436                                 /* Error */
437                                 continue;
438                         }
439                         if (!res) {
440                                 /* No response, timeout */
441                                 res = 1;
442                                 continue;
443                         }
444                 }
445
446                 /* Read STUN response. */
447                 memset(&src, 0, sizeof(src));
448                 srclen = sizeof(src);
449                 /* XXX pass sizeof(rsp_buf) - 1 in the size, because stun_handle_packet might
450                  * write past the end of the buffer.
451                  */
452                 res = recvfrom(s, rsp_buf, sizeof(rsp_buf) - 1,
453                         0, (struct sockaddr *) &src, &srclen);
454                 if (res < 0) {
455                         ast_debug(1, "recvfrom try %d failed: %s\n", retry, strerror(errno));
456                         break;
457                 }
458
459                 /* Process the STUN response. */
460                 rsp = (struct stun_header *) rsp_buf;
461                 if (ast_stun_handle_packet(s, &src, rsp_buf, res, stun_get_mapped, answer)
462                         || (rsp->msgtype != htons(STUN_BINDRESP)
463                                 && rsp->msgtype != htons(STUN_BINDERR))
464                         || stun_id_cmp(&req->id, &rsp->id)) {
465                         /* Bad STUN packet, not right type, or transaction ID did not match. */
466                         memset(answer, 0, sizeof(struct sockaddr_in));
467
468                         /* Was not a resonse to our request. */
469                         goto try_again;
470                 }
471                 /* Success.  answer contains the external address if available. */
472                 res = 0;
473                 break;
474         }
475         return res;
476 }
477
478 static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
479 {
480         switch (cmd) {
481         case CLI_INIT:
482                 e->command = "stun set debug {on|off}";
483                 e->usage =
484                         "Usage: stun set debug {on|off}\n"
485                         "       Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
486                         "       debugging\n";
487                 return NULL;
488         case CLI_GENERATE:
489                 return NULL;
490         }
491
492         if (a->argc != e->args)
493                 return CLI_SHOWUSAGE;
494
495         if (!strncasecmp(a->argv[e->args-1], "on", 2))
496                 stundebug = 1;
497         else if (!strncasecmp(a->argv[e->args-1], "off", 3))
498                 stundebug = 0;
499         else
500                 return CLI_SHOWUSAGE;
501
502         ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
503         return CLI_SUCCESS;
504 }
505
506 static struct ast_cli_entry cli_stun[] = {
507         AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
508 };
509
510 static void stun_shutdown(void)
511 {
512         ast_cli_unregister_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
513 }
514
515 /*! \brief Initialize the STUN system in Asterisk */
516 void ast_stun_init(void)
517 {
518         ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
519         ast_register_cleanup(stun_shutdown);
520 }