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