res_pjsip: Add ability to identify by Authorization username
[asterisk/asterisk.git] / res / res_pjsip_registrar.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@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 /*** MODULEINFO
20         <depend>pjproject</depend>
21         <depend>res_pjproject</depend>
22         <depend>res_pjsip</depend>
23         <support_level>core</support_level>
24  ***/
25
26 #include "asterisk.h"
27
28 #include <pjsip.h>
29 #include <pjsip_ua.h>
30
31 #include "asterisk/res_pjsip.h"
32 #include "asterisk/module.h"
33 #include "asterisk/test.h"
34 #include "asterisk/taskprocessor.h"
35 #include "asterisk/manager.h"
36 #include "asterisk/named_locks.h"
37 #include "asterisk/res_pjproject.h"
38 #include "res_pjsip/include/res_pjsip_private.h"
39
40 /*** DOCUMENTATION
41         <manager name="PJSIPShowRegistrationsInbound" language="en_US">
42                 <synopsis>
43                         Lists PJSIP inbound registrations.
44                 </synopsis>
45                 <syntax />
46                 <description>
47                         <para>
48                         In response <literal>InboundRegistrationDetail</literal> events showing configuration and status
49                         information are raised for each inbound registration object.  As well as <literal>AuthDetail</literal>
50                         events for each associated auth object.  Once all events are completed an
51                         <literal>InboundRegistrationDetailComplete</literal> is issued.
52                         </para>
53                 </description>
54         </manager>
55  ***/
56
57 static int pj_max_hostname = PJ_MAX_HOSTNAME;
58 static int pjsip_max_url_size = PJSIP_MAX_URL_SIZE;
59
60 /*! \brief Internal function which returns the expiration time for a contact */
61 static int registrar_get_expiration(const struct ast_sip_aor *aor, const pjsip_contact_hdr *contact, const pjsip_rx_data *rdata)
62 {
63         pjsip_expires_hdr *expires;
64         int expiration = aor->default_expiration;
65
66         if (contact && contact->expires != -1) {
67                 /* Expiration was provided with the contact itself */
68                 expiration = contact->expires;
69         } else if ((expires = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL))) {
70                 /* Expiration was provided using the Expires header */
71                 expiration = expires->ivalue;
72         }
73
74         /* If the value has explicitly been set to 0, do not enforce */
75         if (!expiration) {
76                 return expiration;
77         }
78
79         /* Enforce the range that we will allow for expiration */
80         if (expiration < aor->minimum_expiration) {
81                 expiration = aor->minimum_expiration;
82         } else if (expiration > aor->maximum_expiration) {
83                 expiration = aor->maximum_expiration;
84         }
85
86         return expiration;
87 }
88
89 /*! \brief Structure used for finding contact */
90 struct registrar_contact_details {
91         /*! \brief Pool used for parsing URI */
92         pj_pool_t *pool;
93         /*! \brief URI being looked for */
94         pjsip_sip_uri *uri;
95 };
96
97 /*! \brief Callback function for finding a contact */
98 static int registrar_find_contact(void *obj, void *arg, int flags)
99 {
100         struct ast_sip_contact *contact = obj;
101         const struct registrar_contact_details *details = arg;
102         pjsip_uri *contact_uri = pjsip_parse_uri(details->pool, (char*)contact->uri, strlen(contact->uri), 0);
103
104         return (pjsip_uri_cmp(PJSIP_URI_IN_CONTACT_HDR, details->uri, contact_uri) == PJ_SUCCESS) ? CMP_MATCH | CMP_STOP : 0;
105 }
106
107 /*! \brief Internal function which validates provided Contact headers to confirm that they are acceptable, and returns number of contacts */
108 static int registrar_validate_contacts(const pjsip_rx_data *rdata, struct ao2_container *contacts, struct ast_sip_aor *aor, int *added, int *updated, int *deleted)
109 {
110         pjsip_contact_hdr *previous = NULL, *contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
111         struct registrar_contact_details details = {
112                 .pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Contact Comparison", 256, 256),
113         };
114
115         if (!details.pool) {
116                 return -1;
117         }
118
119         while ((contact = (pjsip_contact_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact->next))) {
120                 int expiration = registrar_get_expiration(aor, contact, rdata);
121                 RAII_VAR(struct ast_sip_contact *, existing, NULL, ao2_cleanup);
122                 char contact_uri[pjsip_max_url_size];
123
124                 if (contact->star) {
125                         /* The expiration MUST be 0 when a '*' contact is used and there must be no other contact */
126                         if ((expiration != 0) || previous) {
127                                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
128                                 return -1;
129                         }
130                         continue;
131                 } else if (previous && previous->star) {
132                         /* If there is a previous contact and it is a '*' this is a deal breaker */
133                         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
134                         return -1;
135                 }
136                 previous = contact;
137
138                 if (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
139                         continue;
140                 }
141
142                 details.uri = pjsip_uri_get_uri(contact->uri);
143
144                 /* pjsip_uri_print returns -1 if there's not enough room in the buffer */
145                 if (pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, details.uri, contact_uri, sizeof(contact_uri)) < 0) {
146                         /* If the total length of the uri is greater than pjproject can handle, go no further */
147                         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
148                         return -1;
149                 }
150
151                 if (details.uri->host.slen >= pj_max_hostname) {
152                         /* If the length of the hostname is greater than pjproject can handle, go no further */
153                         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
154                         return -1;
155                 }
156
157                 /* Determine if this is an add, update, or delete for policy enforcement purposes */
158                 if (!(existing = ao2_callback(contacts, 0, registrar_find_contact, &details))) {
159                         if (expiration) {
160                                 (*added)++;
161                         }
162                 } else if (expiration) {
163                         (*updated)++;
164                 } else {
165                         (*deleted)++;
166                 }
167         }
168
169         /* The provided contacts are acceptable, huzzah! */
170         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
171         return 0;
172 }
173
174 /*! \brief Callback function which prunes static contacts */
175 static int registrar_prune_static(void *obj, void *arg, int flags)
176 {
177         struct ast_sip_contact *contact = obj;
178
179         return ast_tvzero(contact->expiration_time) ? CMP_MATCH : 0;
180 }
181
182 /*! \brief Internal function used to delete a contact from an AOR */
183 static int registrar_delete_contact(void *obj, void *arg, int flags)
184 {
185         struct ast_sip_contact *contact = obj;
186         const char *aor_name = arg;
187
188         ast_sip_location_delete_contact(contact);
189         if (!ast_strlen_zero(aor_name)) {
190                 ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact->uri, aor_name);
191                 ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
192                                 "Contact: %s\r\n"
193                                 "AOR: %s\r\n"
194                                 "UserAgent: %s",
195                                 contact->uri,
196                                 aor_name,
197                                 contact->user_agent);
198         }
199
200         return 0;
201 }
202
203 /*! \brief Internal function which adds a contact to a response */
204 static int registrar_add_contact(void *obj, void *arg, int flags)
205 {
206         struct ast_sip_contact *contact = obj;
207         pjsip_tx_data *tdata = arg;
208         pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(tdata->pool);
209         pj_str_t uri;
210
211         pj_strdup2_with_null(tdata->pool, &uri, contact->uri);
212         hdr->uri = pjsip_parse_uri(tdata->pool, uri.ptr, uri.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
213         hdr->expires = ast_tvdiff_ms(contact->expiration_time, ast_tvnow()) / 1000;
214
215         pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr);
216
217         return 0;
218 }
219
220 /*! \brief Helper function which adds a Date header to a response */
221 static void registrar_add_date_header(pjsip_tx_data *tdata)
222 {
223         char date[256];
224         struct tm tm;
225         time_t t = time(NULL);
226
227         gmtime_r(&t, &tm);
228         strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
229
230         ast_sip_add_header(tdata, "Date", date);
231 }
232
233 #define SERIALIZER_BUCKETS 59
234
235 static struct ao2_container *serializers;
236
237 /*! \brief Serializer with associated aor key */
238 struct serializer {
239         /* Serializer to distribute tasks to */
240         struct ast_taskprocessor *serializer;
241         /* The name of the aor to associate with the serializer */
242         char aor_name[0];
243 };
244
245 static void serializer_destroy(void *obj)
246 {
247         struct serializer *ser = obj;
248
249         ast_taskprocessor_unreference(ser->serializer);
250 }
251
252 static struct serializer *serializer_create(const char *aor_name)
253 {
254         char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
255         size_t size = strlen(aor_name) + 1;
256         struct serializer *ser = ao2_alloc(
257                 sizeof(*ser) + size, serializer_destroy);
258
259         if (!ser) {
260                 return NULL;
261         }
262
263         /* Create name with seq number appended. */
264         ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/aor/%s",
265                 aor_name);
266
267         if (!(ser->serializer = ast_sip_create_serializer(tps_name))) {
268                 ao2_ref(ser, -1);
269                 return NULL;
270         }
271
272         strcpy(ser->aor_name, aor_name);
273         return ser;
274 }
275
276 static struct serializer *serializer_find_or_create(const char *aor_name)
277 {
278         struct serializer *ser = ao2_find(serializers, aor_name, OBJ_SEARCH_KEY);
279
280         if (ser) {
281                 return ser;
282         }
283
284         if (!(ser = serializer_create(aor_name))) {
285                 return NULL;
286         }
287
288         ao2_link(serializers, ser);
289         return ser;
290 }
291
292 static int serializer_hash(const void *obj, const int flags)
293 {
294         const struct serializer *object;
295         const char *key;
296
297         switch (flags & OBJ_SEARCH_MASK) {
298         case OBJ_SEARCH_KEY:
299                 key = obj;
300                 return ast_str_hash(key);
301         case OBJ_SEARCH_OBJECT:
302                 object = obj;
303                 return ast_str_hash(object->aor_name);
304         default:
305                 /* Hash can only work on something with a full key. */
306                 ast_assert(0);
307                 return 0;
308         }
309 }
310
311 static int serializer_cmp(void *obj_left, void *obj_right, int flags)
312 {
313         const struct serializer *object_left = obj_left;
314         const struct serializer *object_right = obj_right;
315         const char *right_key = obj_right;
316         int cmp;
317
318         switch (flags & OBJ_SEARCH_MASK) {
319         case OBJ_SEARCH_OBJECT:
320                 right_key = object_right->aor_name;
321                 /* Fall through */
322         case OBJ_SEARCH_KEY:
323                 cmp = strcmp(object_left->aor_name, right_key);
324                 break;
325         case OBJ_SEARCH_PARTIAL_KEY:
326                 /*
327                  * We could also use a partial key struct containing a length
328                  * so strlen() does not get called for every comparison instead.
329                  */
330                 cmp = strncmp(object_left->aor_name, right_key, strlen(right_key));
331                 break;
332         default:
333                 cmp = 0;
334                 break;
335         }
336
337         return cmp ? 0 : CMP_MATCH;
338 }
339
340 struct rx_task_data {
341         pjsip_rx_data *rdata;
342         struct ast_sip_endpoint *endpoint;
343         struct ast_sip_aor *aor;
344 };
345
346 static void rx_task_data_destroy(void *obj)
347 {
348         struct rx_task_data *task_data = obj;
349
350         pjsip_rx_data_free_cloned(task_data->rdata);
351         ao2_cleanup(task_data->endpoint);
352         ao2_cleanup(task_data->aor);
353 }
354
355 static struct rx_task_data *rx_task_data_create(pjsip_rx_data *rdata,
356                                                 struct ast_sip_endpoint *endpoint,
357                                                 struct ast_sip_aor *aor)
358 {
359         struct rx_task_data *task_data = ao2_alloc(
360                 sizeof(*task_data), rx_task_data_destroy);
361
362         if (!task_data) {
363                 return NULL;
364         }
365
366         pjsip_rx_data_clone(rdata, 0, &task_data->rdata);
367
368         task_data->endpoint = endpoint;
369         ao2_ref(task_data->endpoint, +1);
370
371         task_data->aor = aor;
372         ao2_ref(task_data->aor, +1);
373
374         return task_data;
375 }
376
377 static const pj_str_t path_hdr_name = { "Path", 4 };
378
379 static int build_path_data(struct rx_task_data *task_data, struct ast_str **path_str)
380 {
381         pjsip_generic_string_hdr *path_hdr = pjsip_msg_find_hdr_by_name(task_data->rdata->msg_info.msg, &path_hdr_name, NULL);
382
383         if (!path_hdr) {
384                 return 0;
385         }
386
387         *path_str = ast_str_create(64);
388         if (!path_str) {
389                 return -1;
390         }
391
392         ast_str_set(path_str, 0, "%.*s", (int)path_hdr->hvalue.slen, path_hdr->hvalue.ptr);
393
394         while ((path_hdr = (pjsip_generic_string_hdr *) pjsip_msg_find_hdr_by_name(task_data->rdata->msg_info.msg, &path_hdr_name, path_hdr->next))) {
395                 ast_str_append(path_str, 0, ",%.*s", (int)path_hdr->hvalue.slen, path_hdr->hvalue.ptr);
396         }
397
398         return 0;
399 }
400
401 static int registrar_validate_path(struct rx_task_data *task_data, struct ast_str **path_str)
402 {
403         const pj_str_t path_supported_name = { "path", 4 };
404         pjsip_supported_hdr *supported_hdr;
405         int i;
406
407         if (!task_data->aor->support_path) {
408                 return 0;
409         }
410
411         if (build_path_data(task_data, path_str)) {
412                 return -1;
413         }
414
415         if (!*path_str) {
416                 return 0;
417         }
418
419         supported_hdr = pjsip_msg_find_hdr(task_data->rdata->msg_info.msg, PJSIP_H_SUPPORTED, NULL);
420         if (!supported_hdr) {
421                 return -1;
422         }
423
424         /* Find advertised path support */
425         for (i = 0; i < supported_hdr->count; i++) {
426                 if (!pj_stricmp(&supported_hdr->values[i], &path_supported_name)) {
427                         return 0;
428                 }
429         }
430
431         /* Path header present, but support not advertised */
432         return -1;
433 }
434
435 static int rx_task_core(struct rx_task_data *task_data, struct ao2_container *contacts,
436         const char *aor_name)
437 {
438         static const pj_str_t USER_AGENT = { "User-Agent", 10 };
439
440         int added = 0, updated = 0, deleted = 0;
441         pjsip_contact_hdr *contact_hdr = NULL;
442         struct registrar_contact_details details = { 0, };
443         pjsip_tx_data *tdata;
444         RAII_VAR(struct ast_str *, path_str, NULL, ast_free);
445         struct ast_sip_contact *response_contact;
446         char *user_agent = NULL;
447         pjsip_user_agent_hdr *user_agent_hdr;
448         pjsip_expires_hdr *expires_hdr;
449
450         /* So we don't count static contacts against max_contacts we prune them out from the container */
451         ao2_callback(contacts, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, registrar_prune_static, NULL);
452
453         if (registrar_validate_contacts(task_data->rdata, contacts, task_data->aor, &added, &updated, &deleted)) {
454                 /* The provided Contact headers do not conform to the specification */
455                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), task_data->rdata, 400, NULL, NULL, NULL);
456                 ast_sip_report_failed_acl(task_data->endpoint, task_data->rdata, "registrar_invalid_contacts_provided");
457                 ast_log(LOG_WARNING, "Failed to validate contacts in REGISTER request from '%s'\n",
458                                 ast_sorcery_object_get_id(task_data->endpoint));
459                 return PJ_TRUE;
460         }
461
462         if (registrar_validate_path(task_data, &path_str)) {
463                 /* Ensure that intervening proxies did not make invalid modifications to the request */
464                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), task_data->rdata, 420, NULL, NULL, NULL);
465                 ast_log(LOG_WARNING, "Invalid modifications made to REGISTER request from '%s' by intervening proxy\n",
466                                 ast_sorcery_object_get_id(task_data->endpoint));
467                 return PJ_TRUE;
468         }
469
470         if ((MAX(added - deleted, 0) + (!task_data->aor->remove_existing ? ao2_container_count(contacts) : 0)) > task_data->aor->max_contacts) {
471                 /* Enforce the maximum number of contacts */
472                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), task_data->rdata, 403, NULL, NULL, NULL);
473                 ast_sip_report_failed_acl(task_data->endpoint, task_data->rdata, "registrar_attempt_exceeds_maximum_configured_contacts");
474                 ast_log(LOG_WARNING, "Registration attempt from endpoint '%s' to AOR '%s' will exceed max contacts of %u\n",
475                                 ast_sorcery_object_get_id(task_data->endpoint), ast_sorcery_object_get_id(task_data->aor), task_data->aor->max_contacts);
476                 return PJ_TRUE;
477         }
478
479         if (!(details.pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Contact Comparison", 256, 256))) {
480                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), task_data->rdata, 500, NULL, NULL, NULL);
481                 return PJ_TRUE;
482         }
483
484         user_agent_hdr = pjsip_msg_find_hdr_by_name(task_data->rdata->msg_info.msg, &USER_AGENT, NULL);
485         if (user_agent_hdr) {
486                 size_t alloc_size = pj_strlen(&user_agent_hdr->hvalue) + 1;
487                 user_agent = ast_alloca(alloc_size);
488                 ast_copy_pj_str(user_agent, &user_agent_hdr->hvalue, alloc_size);
489         }
490
491         /* Iterate each provided Contact header and add, update, or delete */
492         while ((contact_hdr = pjsip_msg_find_hdr(task_data->rdata->msg_info.msg, PJSIP_H_CONTACT, contact_hdr ? contact_hdr->next : NULL))) {
493                 int expiration;
494                 char contact_uri[pjsip_max_url_size];
495                 RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);
496
497                 if (contact_hdr->star) {
498                         /* A star means to unregister everything, so do so for the possible contacts */
499                         ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE, registrar_delete_contact, (void *)aor_name);
500                         break;
501                 }
502
503                 if (!PJSIP_URI_SCHEME_IS_SIP(contact_hdr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact_hdr->uri)) {
504                         /* This registrar only currently supports sip: and sips: URI schemes */
505                         continue;
506                 }
507
508                 expiration = registrar_get_expiration(task_data->aor, contact_hdr, task_data->rdata);
509                 details.uri = pjsip_uri_get_uri(contact_hdr->uri);
510                 pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, details.uri, contact_uri, sizeof(contact_uri));
511
512                 if (!(contact = ao2_callback(contacts, OBJ_UNLINK, registrar_find_contact, &details))) {
513                         /* If they are actually trying to delete a contact that does not exist... be forgiving */
514                         if (!expiration) {
515                                 ast_verb(3, "Attempted to remove non-existent contact '%s' from AOR '%s' by request\n",
516                                         contact_uri, aor_name);
517                                 continue;
518                         }
519
520                         if (ast_sip_location_add_contact_nolock(task_data->aor, contact_uri, ast_tvadd(ast_tvnow(),
521                                 ast_samp2tv(expiration, 1)), path_str ? ast_str_buffer(path_str) : NULL,
522                                         user_agent, task_data->endpoint)) {
523                                 ast_log(LOG_ERROR, "Unable to bind contact '%s' to AOR '%s'\n",
524                                                 contact_uri, aor_name);
525                                 continue;
526                         }
527
528                         ast_verb(3, "Added contact '%s' to AOR '%s' with expiration of %d seconds\n",
529                                 contact_uri, aor_name, expiration);
530                         ast_test_suite_event_notify("AOR_CONTACT_ADDED",
531                                         "Contact: %s\r\n"
532                                         "AOR: %s\r\n"
533                                         "Expiration: %d\r\n"
534                                         "UserAgent: %s",
535                                         contact_uri,
536                                         aor_name,
537                                         expiration,
538                                         user_agent);
539                 } else if (expiration) {
540                         struct ast_sip_contact *contact_update;
541
542                         contact_update = ast_sorcery_copy(ast_sip_get_sorcery(), contact);
543                         if (!contact_update) {
544                                 ast_log(LOG_ERROR, "Failed to update contact '%s' expiration time to %d seconds.\n",
545                                         contact->uri, expiration);
546                                 continue;
547                         }
548
549                         contact_update->expiration_time = ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1));
550                         contact_update->qualify_frequency = task_data->aor->qualify_frequency;
551                         contact_update->authenticate_qualify = task_data->aor->authenticate_qualify;
552                         if (path_str) {
553                                 ast_string_field_set(contact_update, path, ast_str_buffer(path_str));
554                         }
555                         if (user_agent) {
556                                 ast_string_field_set(contact_update, user_agent, user_agent);
557                         }
558
559                         if (ast_sip_location_update_contact(contact_update)) {
560                                 ast_log(LOG_ERROR, "Failed to update contact '%s' expiration time to %d seconds.\n",
561                                         contact->uri, expiration);
562                                 ast_sip_location_delete_contact(contact);
563                                 continue;
564                         }
565                         ast_debug(3, "Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n",
566                                 contact_uri, aor_name, expiration);
567                         ast_test_suite_event_notify("AOR_CONTACT_REFRESHED",
568                                         "Contact: %s\r\n"
569                                         "AOR: %s\r\n"
570                                         "Expiration: %d\r\n"
571                                         "UserAgent: %s",
572                                         contact_uri,
573                                         aor_name,
574                                         expiration,
575                                         contact_update->user_agent);
576                         ao2_cleanup(contact_update);
577                 } else {
578                         /* We want to report the user agent that was actually in the removed contact */
579                         ast_sip_location_delete_contact(contact);
580                         ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact_uri, aor_name);
581                         ast_test_suite_event_notify("AOR_CONTACT_REMOVED",
582                                         "Contact: %s\r\n"
583                                         "AOR: %s\r\n"
584                                         "UserAgent: %s",
585                                         contact_uri,
586                                         aor_name,
587                                         contact->user_agent);
588                 }
589         }
590
591         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), details.pool);
592
593         /* If the AOR is configured to remove any existing contacts that have not been updated/added as a result of this REGISTER
594          * do so
595          */
596         if (task_data->aor->remove_existing) {
597                 ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE, registrar_delete_contact, NULL);
598         }
599
600         /* Re-retrieve contacts.  Caller will clean up the original container. */
601         contacts = ast_sip_location_retrieve_aor_contacts_nolock(task_data->aor);
602         response_contact = ao2_callback(contacts, 0, NULL, NULL);
603
604         /* Send a response containing all of the contacts (including static) that are present on this AOR */
605         if (ast_sip_create_response(task_data->rdata, 200, response_contact, &tdata) != PJ_SUCCESS) {
606                 ao2_cleanup(response_contact);
607                 ao2_cleanup(contacts);
608                 return PJ_TRUE;
609         }
610         ao2_cleanup(response_contact);
611
612         /* Add the date header to the response, some UAs use this to set their date and time */
613         registrar_add_date_header(tdata);
614
615         ao2_callback(contacts, 0, registrar_add_contact, tdata);
616         ao2_cleanup(contacts);
617
618         if ((expires_hdr = pjsip_msg_find_hdr(task_data->rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL))) {
619                 expires_hdr = pjsip_expires_hdr_create(tdata->pool, registrar_get_expiration(task_data->aor, NULL, task_data->rdata));
620                 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)expires_hdr);
621         }
622
623         ast_sip_send_stateful_response(task_data->rdata, tdata, task_data->endpoint);
624
625         return PJ_TRUE;
626 }
627
628 static int rx_task(void *data)
629 {
630         int res;
631         struct rx_task_data *task_data = data;
632         struct ao2_container *contacts = NULL;
633         struct ast_named_lock *lock;
634         const char *aor_name = ast_sorcery_object_get_id(task_data->aor);
635
636         lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_RWLOCK, "aor", aor_name);
637         if (!lock) {
638                 ao2_cleanup(task_data);
639                 return PJ_TRUE;
640         }
641
642         ao2_wrlock(lock);
643         contacts = ast_sip_location_retrieve_aor_contacts_nolock(task_data->aor);
644         if (!contacts) {
645                 ao2_unlock(lock);
646                 ast_named_lock_put(lock);
647                 ao2_cleanup(task_data);
648                 return PJ_TRUE;
649         }
650
651         res = rx_task_core(task_data, contacts, aor_name);
652         ao2_cleanup(contacts);
653         ao2_unlock(lock);
654         ast_named_lock_put(lock);
655         ao2_cleanup(task_data);
656
657         return res;
658 }
659
660 static int match_aor(const char *aor_name, const char *id)
661 {
662         if (ast_strlen_zero(aor_name)) {
663                 return 0;
664         }
665
666         if (!strcmp(aor_name, id)) {
667                 ast_debug(3, "Matched id '%s' to aor '%s'\n", id, aor_name);
668                 return 1;
669         }
670
671         return 0;
672 }
673
674 static char *find_aor_name(const char *username, const char *domain, const char *aors)
675 {
676         char *configured_aors;
677         char *aor_name;
678         char *id_domain;
679         struct ast_sip_domain_alias *alias;
680
681         id_domain = ast_alloca(strlen(username) + strlen(domain) + 2);
682         sprintf(id_domain, "%s@%s", username, domain);
683
684         /* Look for exact match on username@domain */
685         configured_aors = ast_strdupa(aors);
686         while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
687                 if (match_aor(aor_name, id_domain)) {
688                         return ast_strdup(aor_name);
689                 }
690         }
691
692         /* If there's a domain alias, look for exact match on username@domain_alias */
693         alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain);
694         if (alias) {
695                 char *id_domain_alias = ast_alloca(strlen(username) + strlen(alias->domain) + 2);
696
697                 sprintf(id_domain, "%s@%s", username, alias->domain);
698                 ao2_cleanup(alias);
699
700                 configured_aors = ast_strdupa(aors);
701                 while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
702                         if (match_aor(aor_name, id_domain_alias)) {
703                                 return ast_strdup(aor_name);
704                         }
705                 }
706         }
707
708         /* Look for exact match on username only */
709         configured_aors = ast_strdupa(aors);
710         while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) {
711                 if (match_aor(aor_name, username)) {
712                         return ast_strdup(aor_name);
713                 }
714         }
715
716         return NULL;
717 }
718
719 static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
720 {
721         RAII_VAR(struct serializer *, ser, NULL, ao2_cleanup);
722         struct rx_task_data *task_data;
723
724         RAII_VAR(struct ast_sip_endpoint *, endpoint,
725                  ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
726         RAII_VAR(struct ast_sip_aor *, aor, NULL, ao2_cleanup);
727         char *domain_name = NULL;
728         char *username = NULL;
729         RAII_VAR(char *, aor_name, NULL, ast_free);
730         int i;
731
732         if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method) || !endpoint) {
733                 return PJ_FALSE;
734         }
735
736         if (ast_strlen_zero(endpoint->aors)) {
737                 /* Short circuit early if the endpoint has no AORs configured on it, which means no registration possible */
738                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
739                 ast_sip_report_failed_acl(endpoint, rdata, "registrar_attempt_without_configured_aors");
740                 ast_log(LOG_WARNING, "Endpoint '%s' has no configured AORs\n", ast_sorcery_object_get_id(endpoint));
741                 return PJ_TRUE;
742         }
743
744         if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.to->uri) && !PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.to->uri)) {
745                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
746                 ast_sip_report_failed_acl(endpoint, rdata, "registrar_invalid_uri_in_to_received");
747                 ast_log(LOG_WARNING, "Endpoint '%s' attempted to register to an AOR with a non-SIP URI\n", ast_sorcery_object_get_id(endpoint));
748                 return PJ_TRUE;
749         }
750
751         for (i = 0; i < AST_VECTOR_SIZE(&endpoint->ident_method_order); i++) {
752                 pjsip_sip_uri *uri;
753                 pjsip_authorization_hdr *header = NULL;
754
755                 switch (AST_VECTOR_GET(&endpoint->ident_method_order, i)) {
756                 case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME :
757                         uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
758
759                         domain_name = ast_alloca(uri->host.slen + 1);
760                         ast_copy_pj_str(domain_name, &uri->host, uri->host.slen + 1);
761                         username = ast_alloca(uri->user.slen + 1);
762                         ast_copy_pj_str(username, &uri->user, uri->user.slen + 1);
763
764                         aor_name = find_aor_name(username, domain_name, endpoint->aors);
765                         if (aor_name) {
766                                 ast_debug(3, "Matched aor '%s' by To username\n", aor_name);
767                         }
768                         break;
769                 case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME :
770                         while ((header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION,
771                                 header ? header->next : NULL))) {
772                                 if (header && !pj_stricmp2(&header->scheme, "digest")) {
773                                         username = ast_alloca(header->credential.digest.username.slen + 1);
774                                         ast_copy_pj_str(username, &header->credential.digest.username, header->credential.digest.username.slen + 1);
775                                         domain_name = ast_alloca(header->credential.digest.realm.slen + 1);
776                                         ast_copy_pj_str(domain_name, &header->credential.digest.realm, header->credential.digest.realm.slen + 1);
777
778                                         aor_name = find_aor_name(username, domain_name, endpoint->aors);
779                                         if (aor_name) {
780                                                 ast_debug(3, "Matched aor '%s' by Authentication username\n", aor_name);
781                                                 break;
782                                         }
783                                 }
784                         }
785                         break;
786                 default:
787                         continue;
788                 }
789
790                 if (aor_name) {
791                         break;
792                 }
793         }
794
795         if (ast_strlen_zero(aor_name) || !(aor = ast_sip_location_retrieve_aor(aor_name))) {
796                 /* The provided AOR name was not found (be it within the configuration or sorcery itself) */
797                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL);
798                 ast_sip_report_req_no_support(endpoint, rdata, "registrar_requested_aor_not_found");
799                 ast_log(LOG_WARNING, "AOR '%s' not found for endpoint '%s'\n", username, ast_sorcery_object_get_id(endpoint));
800                 return PJ_TRUE;
801         }
802
803         if (!aor->max_contacts) {
804                 /* Registration is not permitted for this AOR */
805                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
806                 ast_sip_report_req_no_support(endpoint, rdata, "registrar_attempt_without_registration_permitted");
807                 ast_log(LOG_WARNING, "AOR '%s' has no configured max_contacts. Endpoint '%s' unable to register\n",
808                                 ast_sorcery_object_get_id(aor), ast_sorcery_object_get_id(endpoint));
809                 return PJ_TRUE;
810         }
811
812         if (!(ser = serializer_find_or_create(aor_name))) {
813                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
814                 ast_sip_report_mem_limit(endpoint, rdata);
815                 ast_log(LOG_WARNING, "Endpoint '%s' unable to register on AOR '%s' - could not get serializer\n",
816                         ast_sorcery_object_get_id(endpoint), ast_sorcery_object_get_id(aor));
817                 return PJ_TRUE;
818         }
819
820         if (!(task_data = rx_task_data_create(rdata, endpoint, aor))) {
821                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
822                 ast_sip_report_mem_limit(endpoint, rdata);
823                 ast_log(LOG_WARNING, "Endpoint '%s' unable to register on AOR '%s' - could not create rx_task_data\n",
824                         ast_sorcery_object_get_id(endpoint), ast_sorcery_object_get_id(aor));
825                 return PJ_TRUE;
826         }
827
828         if (ast_sip_push_task(ser->serializer, rx_task, task_data)) {
829                 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
830                 ast_sip_report_mem_limit(endpoint, rdata);
831                 ast_log(LOG_WARNING, "Endpoint '%s' unable to register on AOR '%s' - could not serialize task\n",
832                         ast_sorcery_object_get_id(endpoint), ast_sorcery_object_get_id(aor));
833                 ao2_ref(task_data, -1);
834         }
835         return PJ_TRUE;
836 }
837
838 /* function pointer to callback needs to be within the module
839    in order to avoid problems with an undefined symbol */
840 static int sip_contact_to_str(void *acp, void *arg, int flags)
841 {
842         return ast_sip_contact_to_str(acp, arg, flags);
843 }
844
845 static int ami_registrations_aor(void *obj, void *arg, int flags)
846 {
847         struct ast_sip_aor *aor = obj;
848         struct ast_sip_ami *ami = arg;
849         int *count = ami->arg;
850         RAII_VAR(struct ast_str *, buf,
851                  ast_sip_create_ami_event("InboundRegistrationDetail", ami), ast_free);
852
853         if (!buf) {
854                 return -1;
855         }
856
857         ast_sip_sorcery_object_to_ami(aor, &buf);
858         ast_str_append(&buf, 0, "Contacts: ");
859         ast_sip_for_each_contact(aor, sip_contact_to_str, &buf);
860         ast_str_append(&buf, 0, "\r\n");
861
862         astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
863         (*count)++;
864         return 0;
865 }
866
867 static int ami_registrations_endpoint(void *obj, void *arg, int flags)
868 {
869         struct ast_sip_endpoint *endpoint = obj;
870         return ast_sip_for_each_aor(
871                 endpoint->aors, ami_registrations_aor, arg);
872 }
873
874 static int ami_registrations_endpoints(void *arg)
875 {
876         RAII_VAR(struct ao2_container *, endpoints,
877                  ast_sip_get_endpoints(), ao2_cleanup);
878
879         if (!endpoints) {
880                 return 0;
881         }
882
883         ao2_callback(endpoints, OBJ_NODATA, ami_registrations_endpoint, arg);
884         return 0;
885 }
886
887 static int ami_show_registrations(struct mansession *s, const struct message *m)
888 {
889         int count = 0;
890         struct ast_sip_ami ami = { .s = s, .m = m, .arg = &count, .action_id = astman_get_header(m, "ActionID"), };
891
892         astman_send_listack(s, m, "Following are Events for each Inbound registration",
893                 "start");
894
895         ami_registrations_endpoints(&ami);
896
897         astman_send_list_complete_start(s, m, "InboundRegistrationDetailComplete", count);
898         astman_send_list_complete_end(s);
899         return 0;
900 }
901
902 #define AMI_SHOW_REGISTRATIONS "PJSIPShowRegistrationsInbound"
903
904 static pjsip_module registrar_module = {
905         .name = { "Registrar", 9 },
906         .id = -1,
907         .priority = PJSIP_MOD_PRIORITY_APPLICATION,
908         .on_rx_request = registrar_on_rx_request,
909 };
910
911 static int load_module(void)
912 {
913         const pj_str_t STR_REGISTER = { "REGISTER", 8 };
914
915         CHECK_PJPROJECT_MODULE_LOADED();
916
917         ast_pjproject_get_buildopt("PJ_MAX_HOSTNAME", "%d", &pj_max_hostname);
918         /* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
919         ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
920
921         CHECK_PJSIP_MODULE_LOADED();
922
923         if (!(serializers = ao2_container_alloc(
924                       SERIALIZER_BUCKETS, serializer_hash, serializer_cmp))) {
925                 return AST_MODULE_LOAD_DECLINE;
926         }
927
928         if (ast_sip_register_service(&registrar_module)) {
929                 return AST_MODULE_LOAD_DECLINE;
930         }
931
932         if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), NULL, PJSIP_H_ALLOW, NULL, 1, &STR_REGISTER) != PJ_SUCCESS) {
933                 ast_sip_unregister_service(&registrar_module);
934                 return AST_MODULE_LOAD_DECLINE;
935         }
936
937         ast_manager_register_xml(AMI_SHOW_REGISTRATIONS, EVENT_FLAG_SYSTEM,
938                                  ami_show_registrations);
939
940         return AST_MODULE_LOAD_SUCCESS;
941 }
942
943 static int unload_module(void)
944 {
945         ast_manager_unregister(AMI_SHOW_REGISTRATIONS);
946         ast_sip_unregister_service(&registrar_module);
947
948         ao2_cleanup(serializers);
949         return 0;
950 }
951
952 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Registrar Support",
953         .support_level = AST_MODULE_SUPPORT_CORE,
954         .load = load_module,
955         .unload = unload_module,
956         .load_pri = AST_MODPRI_APP_DEPEND,
957 );