1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Ken Rice, <krice at freeswitch.org> (work sponsored by Comet Signaling LLC, CopperCom, Inc and Asteria Solutions Group, Inc)
28 * Paul D. Tinsley <pdt at jackhammer.org>
29 * Bret McDanel <trixter AT 0xdecafbad.com>
30 * Marcel Barbulescu <marcelbarbulescu@gmail.com>
31 * David Knell <david.knell@telng.com>
32 * Eliot Gable <egable AT.AT broadvox.com>
33 * Leon de Rooij <leon@scarlet-internet.nl>
34 * Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
35 * William King <william.king@quentustech.com>
36 *
37 * sofia_reg.c -- SOFIA SIP Endpoint (registration code)
38 *
39 */
40 #include "mod_sofia.h"
41
sofia_reg_new_handle(sofia_gateway_t * gateway_ptr,int attach)42 static void sofia_reg_new_handle(sofia_gateway_t *gateway_ptr, int attach)
43 {
44 int ss_state = nua_callstate_authenticating;
45
46 if (gateway_ptr->nh) {
47 nua_handle_bind(gateway_ptr->nh, NULL);
48 nua_handle_destroy(gateway_ptr->nh);
49 gateway_ptr->nh = NULL;
50 sofia_private_free(gateway_ptr->sofia_private);
51 }
52
53 gateway_ptr->nh = nua_handle(gateway_ptr->profile->nua, NULL,
54 SIPTAG_CALL_ID_STR(gateway_ptr->uuid_str),
55 SIPTAG_TO_STR(gateway_ptr->register_to),
56 NUTAG_CALLSTATE_REF(ss_state), SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END());
57 if (attach) {
58 if (!gateway_ptr->sofia_private) {
59 switch_zmalloc(gateway_ptr->sofia_private, sizeof(*gateway_ptr->sofia_private));
60 }
61
62 switch_set_string(gateway_ptr->sofia_private->gateway_name, gateway_ptr->name);
63 nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private);
64 }
65 }
66
sofia_reg_new_sub_handle(sofia_gateway_subscription_t * gw_sub_ptr)67 static void sofia_reg_new_sub_handle(sofia_gateway_subscription_t *gw_sub_ptr)
68 {
69 sofia_gateway_t *gateway_ptr = gw_sub_ptr->gateway;
70 char *user_via = NULL;
71 char *register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
72 int ss_state = nua_callstate_authenticating;
73
74
75 /* check for NAT and place a Via header if necessary (hostname or non-local IP) */
76 if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
77 user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport);
78 }
79
80 if (gw_sub_ptr->nh) {
81 nua_handle_bind(gw_sub_ptr->nh, NULL);
82 nua_handle_destroy(gw_sub_ptr->nh);
83 gw_sub_ptr->nh = NULL;
84 sofia_private_free(gw_sub_ptr->sofia_private);
85 }
86
87 gw_sub_ptr->nh = nua_handle(gateway_ptr->profile->nua, NULL,
88 NUTAG_URL(gateway_ptr->register_proxy),
89 TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
90 SIPTAG_TO_STR(gateway_ptr->register_to),
91 NUTAG_CALLSTATE_REF(ss_state), SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END());
92 if (!gw_sub_ptr->sofia_private) {
93 switch_zmalloc(gw_sub_ptr->sofia_private, sizeof(*gw_sub_ptr->sofia_private));
94 }
95
96 switch_set_string(gw_sub_ptr->sofia_private->gateway_name, gateway_ptr->name);
97 nua_handle_bind(gw_sub_ptr->nh, gw_sub_ptr->sofia_private);
98
99 switch_safe_free(register_host);
100 switch_safe_free(user_via);
101 }
102
sofia_reg_kill_sub(sofia_gateway_subscription_t * gw_sub_ptr)103 static void sofia_reg_kill_sub(sofia_gateway_subscription_t *gw_sub_ptr)
104 {
105 sofia_gateway_t *gateway_ptr = gw_sub_ptr->gateway;
106
107 sofia_private_free(gw_sub_ptr->sofia_private);
108
109 if (gw_sub_ptr->nh) {
110 nua_handle_bind(gw_sub_ptr->nh, NULL);
111 }
112
113 if (gw_sub_ptr->state != SUB_STATE_SUBED && gw_sub_ptr->state != SUB_STATE_UNSUBSCRIBE) {
114 if (gw_sub_ptr->nh) {
115 nua_handle_destroy(gw_sub_ptr->nh);
116 gw_sub_ptr->nh = NULL;
117 }
118 return;
119 }
120
121 if (gw_sub_ptr->nh) {
122 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Subbing %s %s\n", gateway_ptr->name, gw_sub_ptr->event);
123 nua_unsubscribe(gw_sub_ptr->nh, NUTAG_URL(gw_sub_ptr->request_uri), TAG_END());
124 }
125 }
126
sofia_reg_kill_reg(sofia_gateway_t * gateway_ptr)127 static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr)
128 {
129
130 if (!gateway_ptr->nh) {
131 return;
132 }
133
134 if (gateway_ptr->state == REG_STATE_REGED || gateway_ptr->state == REG_STATE_UNREGISTER) {
135 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Registering %s\n", gateway_ptr->name);
136 nua_unregister(gateway_ptr->nh, NUTAG_URL(gateway_ptr->register_url), NUTAG_REGISTRAR(gateway_ptr->register_proxy), TAG_END());
137 } else {
138 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Destroying registration handle for %s\n", gateway_ptr->name);
139 }
140
141 sofia_private_free(gateway_ptr->sofia_private);
142 nua_handle_bind(gateway_ptr->nh, NULL);
143 nua_handle_destroy(gateway_ptr->nh);
144 gateway_ptr->nh = NULL;
145 }
146
sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t * gateway,int status,const char * phrase)147 void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int status, const char *phrase)
148 {
149 switch_event_t *s_event;
150 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_GATEWAY_STATE) == SWITCH_STATUS_SUCCESS) {
151 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Gateway", gateway->name);
152 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "State", sofia_state_string(gateway->state));
153 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Ping-Status", sofia_gateway_status_name(gateway->status));
154 if (!zstr_buf(gateway->register_network_ip)) {
155 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Register-Network-IP", gateway->register_network_ip);
156 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "Register-Network-Port", "%d", gateway->register_network_port);
157 }
158
159 if (!zstr(phrase)) {
160 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Phrase", phrase);
161 }
162 if (status) {
163 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "Status", "%d", status);
164 }
165 switch_event_fire(&s_event);
166 }
167 }
168
sofia_reg_fire_custom_sip_user_state_event(sofia_profile_t * profile,const char * sip_user,const char * contact,const char * from_user,const char * from_host,const char * call_id,sofia_sip_user_status_t status,int options_res,const char * phrase)169 void sofia_reg_fire_custom_sip_user_state_event(sofia_profile_t *profile, const char *sip_user, const char *contact,
170 const char* from_user, const char* from_host, const char *call_id, sofia_sip_user_status_t status, int options_res, const char *phrase)
171 {
172 switch_event_t *s_event;
173 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_SIP_USER_STATE) == SWITCH_STATUS_SUCCESS) {
174 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_contact", contact);
175 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
176 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_user", sip_user);
177 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", from_user);
178 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", from_host);
179 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
180 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Ping-Status", sofia_sip_user_status_name(status));
181 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "Status", "%d", options_res);
182 if (!zstr(phrase)) {
183 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Phrase", phrase);
184 }
185 switch_event_fire(&s_event);
186 }
187 }
188
sofia_reg_unregister(sofia_profile_t * profile)189 void sofia_reg_unregister(sofia_profile_t *profile)
190 {
191 sofia_gateway_t *gateway_ptr;
192 sofia_gateway_subscription_t *gw_sub_ptr;
193
194 switch_mutex_lock(mod_sofia_globals.hash_mutex);
195 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
196
197 if (gateway_ptr->nh) {
198 nua_handle_bind(gateway_ptr->nh, NULL);
199 }
200
201 if (gateway_ptr->state == REG_STATE_REGED) {
202 sofia_reg_kill_reg(gateway_ptr);
203 }
204
205 for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
206
207 if (gw_sub_ptr->state == SUB_STATE_SUBED) {
208 sofia_reg_kill_sub(gw_sub_ptr);
209 }
210 }
211
212 gateway_ptr->subscriptions = NULL;
213 }
214 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
215 }
216
sofia_sub_check_gateway(sofia_profile_t * profile,time_t now)217 void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
218 {
219 /* NOTE: A lot of the mechanism in place here for refreshing subscriptions is
220 * pretty much redundant, as the sofia stack takes it upon itself to
221 * refresh subscriptions on its own, based on the value of the Expires
222 * header (which we control in the outgoing subscription request)
223 */
224 sofia_gateway_t *gateway_ptr;
225
226 switch_mutex_lock(profile->gw_mutex);
227 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
228 sofia_gateway_subscription_t *gw_sub_ptr;
229
230 for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
231 sub_state_t ostate = gw_sub_ptr->state;
232
233 if (!now) {
234 gw_sub_ptr->state = ostate = SUB_STATE_UNSUBED;
235 gw_sub_ptr->expires_str = "0";
236 }
237
238 //gateway_ptr->sub_state = gw_sub_ptr->state;
239
240 switch (ostate) {
241 case SUB_STATE_NOSUB:
242 break;
243 case SUB_STATE_SUBSCRIBE:
244 gw_sub_ptr->expires = now + gw_sub_ptr->freq;
245 gw_sub_ptr->state = SUB_STATE_SUBED;
246 break;
247 case SUB_STATE_UNSUBSCRIBE:
248 gw_sub_ptr->state = SUB_STATE_NOSUB;
249 sofia_reg_kill_sub(gw_sub_ptr);
250 break;
251 case SUB_STATE_UNSUBED:
252
253 sofia_reg_new_sub_handle(gw_sub_ptr);
254
255 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "subscribing to [%s] on gateway [%s]\n", gw_sub_ptr->event, gateway_ptr->name);
256
257 if (now) {
258 nua_subscribe(gw_sub_ptr->nh,
259 NUTAG_URL(gw_sub_ptr->request_uri),
260 SIPTAG_EVENT_STR(gw_sub_ptr->event),
261 TAG_IF(strcmp(gw_sub_ptr->content_type, "NO_CONTENT_TYPE"), SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type)),
262 SIPTAG_TO_STR(gateway_ptr->register_from),
263 SIPTAG_FROM_STR(gateway_ptr->register_from),
264 SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
265 SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str), /* sofia stack bases its auto-refresh stuff on this */
266 TAG_NULL());
267 gw_sub_ptr->retry = now + gw_sub_ptr->retry_seconds;
268 } else {
269 nua_unsubscribe(gw_sub_ptr->nh,
270 NUTAG_URL(gw_sub_ptr->request_uri),
271 SIPTAG_EVENT_STR(gw_sub_ptr->event),
272 TAG_IF(strcmp(gw_sub_ptr->content_type, "NO_CONTENT_TYPE"), SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type)),
273 SIPTAG_FROM_STR(gateway_ptr->register_from),
274 SIPTAG_TO_STR(gateway_ptr->register_from),
275 SIPTAG_CONTACT_STR(gateway_ptr->register_contact), SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str), TAG_NULL());
276 }
277 gw_sub_ptr->state = SUB_STATE_TRYING;
278 break;
279
280 case SUB_STATE_FAILED:
281 gw_sub_ptr->expires = now;
282 gw_sub_ptr->retry = now + gw_sub_ptr->retry_seconds;
283 gw_sub_ptr->state = SUB_STATE_FAIL_WAIT;
284 break;
285 case SUB_STATE_FAIL_WAIT:
286 if (!gw_sub_ptr->retry || now >= gw_sub_ptr->retry) {
287 gw_sub_ptr->state = SUB_STATE_UNSUBED;
288 }
289 break;
290 case SUB_STATE_TRYING:
291 if (gw_sub_ptr->retry && now >= gw_sub_ptr->retry) {
292 gw_sub_ptr->state = SUB_STATE_UNSUBED;
293 gw_sub_ptr->retry = 0;
294 }
295 break;
296 default:
297 if (now >= gw_sub_ptr->expires) {
298 gw_sub_ptr->state = SUB_STATE_UNSUBED;
299 }
300 break;
301 }
302
303 }
304 }
305 switch_mutex_unlock(profile->gw_mutex);
306 }
307
sofia_reg_check_gateway(sofia_profile_t * profile,time_t now)308 void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
309 {
310 sofia_gateway_t *check, *gateway_ptr, *last = NULL;
311 switch_event_t *event;
312 int delta = 0;
313
314 switch_mutex_lock(profile->gw_mutex);
315 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
316 if (gateway_ptr->deleted) {
317 if ((check = switch_core_hash_find(mod_sofia_globals.gateway_hash, gateway_ptr->name)) && check == gateway_ptr) {
318 char *pkey = switch_mprintf("%s::%s", profile->name, gateway_ptr->name);
319 switch_assert(pkey);
320 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing gateway %s from hash.\n", pkey);
321 switch_core_hash_delete(mod_sofia_globals.gateway_hash, pkey);
322 switch_core_hash_delete(mod_sofia_globals.gateway_hash, gateway_ptr->name);
323 free(pkey);
324 }
325
326 if (gateway_ptr->state == REG_STATE_NOREG) {
327
328 if (last) {
329 last->next = gateway_ptr->next;
330 } else {
331 profile->gateways = gateway_ptr->next;
332 }
333
334 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleted gateway %s\n", gateway_ptr->name);
335 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_GATEWAY_DEL) == SWITCH_STATUS_SUCCESS) {
336 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "profile-name", gateway_ptr->profile->name);
337 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Gateway", gateway_ptr->name);
338 switch_event_fire(&event);
339 }
340 if (gateway_ptr->ob_vars) {
341 switch_event_destroy(&gateway_ptr->ob_vars);
342 }
343 if (gateway_ptr->ib_vars) {
344 switch_event_destroy(&gateway_ptr->ib_vars);
345 }
346 } else {
347 last = gateway_ptr;
348 }
349 } else {
350 last = gateway_ptr;
351 }
352 }
353
354 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
355 reg_state_t ostate = gateway_ptr->state;
356 char *user_via = NULL;
357 char *register_host = NULL;
358
359 if (!now) {
360 gateway_ptr->state = ostate = REG_STATE_UNREGED;
361 gateway_ptr->expires_str = "0";
362 }
363
364 if (gateway_ptr->ping && !gateway_ptr->pinging && (now >= gateway_ptr->ping && (ostate == REG_STATE_NOREG || ostate == REG_STATE_REGED)) &&
365 !gateway_ptr->deleted) {
366 nua_handle_t *nh = nua_handle(profile->nua, NULL, NUTAG_URL(gateway_ptr->register_url), TAG_END());
367 sofia_private_t *pvt;
368
369 register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
370
371 /* check for NAT and place a Via header if necessary (hostname or non-local IP) */
372 if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
373 user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport);
374 }
375
376 switch_safe_free(register_host);
377
378 pvt = malloc(sizeof(*pvt));
379 switch_assert(pvt);
380 memset(pvt, 0, sizeof(*pvt));
381 pvt->destroy_nh = 1;
382 pvt->destroy_me = 1;
383 switch_copy_string(pvt->gateway_name, gateway_ptr->name, sizeof(pvt->gateway_name));
384 nua_handle_bind(nh, pvt);
385
386 gateway_ptr->pinging = 1;
387 gateway_ptr->ping_sent = switch_time_now();
388 nua_options(nh,
389 TAG_IF(gateway_ptr->register_sticky_proxy, NUTAG_PROXY(gateway_ptr->register_sticky_proxy)),
390 TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
391 SIPTAG_TO_STR(gateway_ptr->options_to_uri), SIPTAG_FROM_STR(gateway_ptr->options_from_uri),
392 TAG_IF(gateway_ptr->contact_in_ping, SIPTAG_CONTACT_STR(gateway_ptr->register_contact)),
393 TAG_IF(gateway_ptr->options_user_agent, SIPTAG_USER_AGENT_STR(gateway_ptr->options_user_agent)),
394 TAG_END());
395
396 switch_safe_free(user_via);
397 user_via = NULL;
398 }
399
400 switch (ostate) {
401 case REG_STATE_NOREG:
402 if (!gateway_ptr->ping && !gateway_ptr->pinging && gateway_ptr->status != SOFIA_GATEWAY_UP) {
403 gateway_ptr->status = SOFIA_GATEWAY_UP;
404 gateway_ptr->uptime = switch_time_now();
405 }
406 break;
407 case REG_STATE_REGISTER:
408 if (profile->debug) {
409 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Registered %s\n", gateway_ptr->name);
410 }
411
412 gateway_ptr->failures = 0;
413
414 if (gateway_ptr->freq > 30) {
415 delta = (gateway_ptr->freq - 15);
416 } else {
417 delta = (gateway_ptr->freq / 2);
418 }
419
420 if (delta < 1) {
421 delta = 1;
422 }
423
424 gateway_ptr->expires = now + delta;
425
426 gateway_ptr->state = REG_STATE_REGED;
427 if (gateway_ptr->status != SOFIA_GATEWAY_UP) {
428 gateway_ptr->status = SOFIA_GATEWAY_UP;
429 gateway_ptr->uptime = switch_time_now();
430 }
431 break;
432
433 case REG_STATE_UNREGISTER:
434 sofia_reg_kill_reg(gateway_ptr);
435 gateway_ptr->state = REG_STATE_NOREG;
436 gateway_ptr->status = SOFIA_GATEWAY_DOWN;
437 break;
438 case REG_STATE_UNREGED:
439 gateway_ptr->retry = 0;
440
441 if (!gateway_ptr->nh) {
442 sofia_reg_new_handle(gateway_ptr, now ? 1 : 0);
443 }
444
445 register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
446
447 /* check for NAT and place a Via header if necessary (hostname or non-local IP) */
448 if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
449 user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport);
450 }
451
452 switch_safe_free(register_host);
453
454 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Registering %s\n", gateway_ptr->name);
455
456 if (now) {
457 nua_register(gateway_ptr->nh,
458 NUTAG_URL(gateway_ptr->register_url),
459 TAG_IF(gateway_ptr->register_sticky_proxy, NUTAG_PROXY(gateway_ptr->register_sticky_proxy)),
460 TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
461 SIPTAG_TO_STR(gateway_ptr->distinct_to ? gateway_ptr->register_to : gateway_ptr->register_from),
462 SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
463 SIPTAG_FROM_STR(gateway_ptr->register_from),
464 SIPTAG_EXPIRES_STR(gateway_ptr->expires_str),
465 NUTAG_REGISTRAR(gateway_ptr->register_proxy),
466 NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL());
467 gateway_ptr->retry = now + gateway_ptr->retry_seconds;
468 } else {
469 gateway_ptr->status = SOFIA_GATEWAY_DOWN;
470 nua_unregister(gateway_ptr->nh,
471 NUTAG_URL(gateway_ptr->register_url),
472 TAG_IF(gateway_ptr->register_sticky_proxy, NUTAG_PROXY(gateway_ptr->register_sticky_proxy)),
473 TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
474 SIPTAG_FROM_STR(gateway_ptr->register_from),
475 SIPTAG_TO_STR(gateway_ptr->distinct_to ? gateway_ptr->register_to : gateway_ptr->register_from),
476 SIPTAG_EXPIRES_STR(gateway_ptr->expires_str),
477 NUTAG_REGISTRAR(gateway_ptr->register_proxy),
478 NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL());
479 }
480 gateway_ptr->reg_timeout = now + gateway_ptr->reg_timeout_seconds;
481 gateway_ptr->state = REG_STATE_TRYING;
482 switch_safe_free(user_via);
483 user_via = NULL;
484 break;
485
486 case REG_STATE_TIMEOUT:
487 {
488 nua_handle_t *nh = gateway_ptr->nh;
489
490 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Timeout Registering %s\n", gateway_ptr->name);
491
492 gateway_ptr->nh = NULL;
493 nua_handle_destroy(nh);
494 gateway_ptr->state = REG_STATE_FAILED;
495 gateway_ptr->failures++;
496 gateway_ptr->failure_status = 908;
497 }
498 break;
499 case REG_STATE_FAILED:
500 {
501 int sec;
502
503 if (gateway_ptr->fail_908_retry_seconds && gateway_ptr->failure_status == 908) {
504 sec = gateway_ptr->fail_908_retry_seconds;
505 } else if (gateway_ptr->failure_status == 503 || gateway_ptr->failure_status == 908 || gateway_ptr->failures < 1) {
506 sec = gateway_ptr->retry_seconds;
507 } else {
508 sec = gateway_ptr->retry_seconds * gateway_ptr->failures;
509 }
510
511 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s Failed Registration [%d], setting retry to %d seconds.\n",
512 gateway_ptr->name, gateway_ptr->failure_status, sec);
513
514 gateway_ptr->retry = switch_epoch_time_now(NULL) + sec;
515 gateway_ptr->status = SOFIA_GATEWAY_DOWN;
516 gateway_ptr->state = REG_STATE_FAIL_WAIT;
517 gateway_ptr->failure_status = 0;
518
519 }
520 break;
521 case REG_STATE_FAIL_WAIT:
522 if (!gateway_ptr->retry || now >= gateway_ptr->retry) {
523 gateway_ptr->state = REG_STATE_UNREGED;
524 }
525 break;
526 case REG_STATE_TRYING:
527 if (now >= gateway_ptr->reg_timeout) {
528 gateway_ptr->state = REG_STATE_TIMEOUT;
529 }
530 break;
531 default:
532 if (now >= gateway_ptr->expires) {
533 gateway_ptr->state = REG_STATE_UNREGED;
534 }
535 break;
536 }
537 if (ostate != gateway_ptr->state) {
538 sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
539 }
540 }
541 switch_mutex_unlock(profile->gw_mutex);
542 }
543
544
sofia_reg_find_callback(void * pArg,int argc,char ** argv,char ** columnNames)545 int sofia_reg_find_callback(void *pArg, int argc, char **argv, char **columnNames)
546 {
547 struct callback_t *cbt = (struct callback_t *) pArg;
548
549 if (!cbt->len) {
550 switch_console_push_match(&cbt->list, argv[0]);
551 cbt->matches++;
552 return 0;
553 }
554
555 switch_copy_string(cbt->val, argv[0], cbt->len);
556 cbt->matches++;
557 return cbt->matches == 1 ? 0 : 1;
558 }
559
560
sofia_reg_find_reg_with_positive_expires_callback(void * pArg,int argc,char ** argv,char ** columnNames)561 int sofia_reg_find_reg_with_positive_expires_callback(void *pArg, int argc, char **argv, char **columnNames)
562 {
563 struct callback_t *cbt = (struct callback_t *) pArg;
564 sofia_destination_t *dst = NULL;
565 long int expires;
566 char *contact = NULL;
567
568 if (zstr(argv[0])) {
569 return 0;
570 }
571
572 if (cbt->contact_str && !strcasecmp(argv[0], cbt->contact_str)) {
573 expires = cbt->exptime;
574 } else {
575 expires = atol(argv[1]) - 60 - (long) cbt->time;
576 }
577
578 if (expires > 0) {
579 dst = sofia_glue_get_destination(argv[0]);
580 contact = switch_mprintf("<%s>;expires=%ld", dst->contact, expires);
581
582 if (!cbt->len) {
583 switch_console_push_match(&cbt->list, contact);
584 switch_safe_free(contact);
585 sofia_glue_free_destination(dst);
586 cbt->matches++;
587 return 0;
588 }
589
590 switch_copy_string(cbt->val, contact, cbt->len);
591 switch_safe_free(contact);
592 sofia_glue_free_destination(dst);
593 cbt->matches++;
594 return cbt->matches == 1 ? 0 : 1;
595 }
596
597 return 0;
598 }
599
600
sofia_reg_nat_callback(void * pArg,int argc,char ** argv,char ** columnNames)601 int sofia_reg_nat_callback(void *pArg, int argc, char **argv, char **columnNames)
602 {
603 sofia_profile_t *profile = (sofia_profile_t *) pArg;
604 nua_handle_t *nh;
605 char to[512] = "", call_id[512] = "";
606 sofia_destination_t *dst = NULL;
607 switch_uuid_t uuid;
608 sofia_private_t *pvt;
609
610 switch_snprintf(to, sizeof(to), "sip:%s@%s", argv[1], argv[2]);
611
612 // create call-id for OPTIONS in the form "<uuid>_<original-register-call-id>"
613 switch_uuid_get(&uuid);
614 switch_uuid_format(call_id, &uuid);
615 strcat(call_id, "_");
616 strncat(call_id, argv[0], sizeof(call_id) - SWITCH_UUID_FORMATTED_LENGTH - 2);
617
618 dst = sofia_glue_get_destination(argv[3]);
619 switch_assert(dst);
620
621 nh = nua_handle(profile->nua, NULL, SIPTAG_FROM_STR(profile->url), SIPTAG_TO_STR(to), NUTAG_URL(dst->contact), SIPTAG_CONTACT_STR(profile->url),
622 SIPTAG_CALL_ID_STR(call_id), TAG_END());
623
624 pvt = malloc(sizeof(*pvt));
625 switch_assert(pvt);
626 memset(pvt, 0, sizeof(*pvt));
627 pvt->destroy_nh = 1;
628 pvt->destroy_me = 1;
629 pvt->ping_sent = switch_time_now();
630 nua_handle_bind(nh, pvt);
631
632 nua_options(nh,
633 NTATAG_SIP_T2(5000),
634 NTATAG_SIP_T4(10000),
635 TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), TAG_END());
636
637 sofia_glue_free_destination(dst);
638
639 return 0;
640 }
641
642
sofia_reg_send_reboot(sofia_profile_t * profile,const char * callid,const char * user,const char * host,const char * contact,const char * user_agent,const char * network_ip)643 void sofia_reg_send_reboot(sofia_profile_t *profile, const char *callid, const char *user, const char *host, const char *contact, const char *user_agent,
644 const char *network_ip)
645 {
646 const char *event = "check-sync";
647 const char *contenttype = "application/simple-message-summary";
648 char *body = NULL;
649
650 if (switch_stristr("snom", user_agent) || switch_stristr("yealink", user_agent)) {
651 event = "check-sync;reboot=true";
652 } else if (switch_stristr("Linksys/SPA8000", user_agent)) {
653 event = "check-sync";
654 } else if (switch_stristr("linksys", user_agent)) {
655 event = "reboot_now";
656 } else if (switch_stristr("spa", user_agent)) {
657 event = "reboot";
658 } else if (switch_stristr("Cisco-CP7960G", user_agent) || switch_stristr("Cisco-CP7940G", user_agent)) {
659 event = "check-sync";
660 } else if (switch_stristr("cisco", user_agent)) {
661 event = "service-control";
662 contenttype = "text/plain";
663 body = switch_mprintf("action=restart\n"
664 "RegisterCallId={%s}\n"
665 "ConfigVersionStamp={0000000000000000}\n"
666 "DialplanVersionStamp={0000000000000000}\n"
667 "SoftkeyVersionStamp={0000000000000000}", callid);
668 }
669
670 sofia_glue_send_notify(profile, user, host, event, contenttype, body ? body : "", contact, network_ip, callid);
671
672 switch_safe_free(body);
673 }
674
sofia_sla_dialog_del_callback(void * pArg,int argc,char ** argv,char ** columnNames)675 int sofia_sla_dialog_del_callback(void *pArg, int argc, char **argv, char **columnNames)
676 {
677 sofia_profile_t *profile = (sofia_profile_t *) pArg;
678 nua_handle_t *nh = NULL;
679
680 if ((nh = nua_handle_by_call_id(profile->nua, argv[0]))) {
681 nua_handle_destroy(nh);
682 }
683
684 return 0;
685 }
686
sofia_reg_check_socket(sofia_profile_t * profile,const char * call_id,const char * network_addr,const char * network_ip)687 void sofia_reg_check_socket(sofia_profile_t *profile, const char *call_id, const char *network_addr, const char *network_ip)
688 {
689 char key[256] = "";
690 nua_handle_t *hnh;
691
692 switch_snprintf(key, sizeof(key), "%s%s%s", call_id, network_addr, network_ip);
693 switch_mutex_lock(profile->flag_mutex);
694 if ((hnh = switch_core_hash_find(profile->reg_nh_hash, key))) {
695 switch_core_hash_delete(profile->reg_nh_hash, key);
696 nua_handle_unref(hnh);
697 nua_handle_destroy(hnh);
698 }
699 switch_mutex_unlock(profile->flag_mutex);
700 }
701
702
703
sofia_reg_del_callback(void * pArg,int argc,char ** argv,char ** columnNames)704 int sofia_reg_del_callback(void *pArg, int argc, char **argv, char **columnNames)
705 {
706 switch_event_t *s_event;
707 sofia_profile_t *profile = (sofia_profile_t *) pArg;
708
709 if (argc > 13 && atoi(argv[13]) == 1) {
710 sofia_reg_send_reboot(profile, argv[0], argv[1], argv[2], argv[3], argv[7], argv[11]);
711 }
712
713 sofia_reg_check_socket(profile, argv[0], argv[11], argv[12]);
714
715
716 if (argc >= 3) {
717 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_EXPIRE) == SWITCH_STATUS_SUCCESS) {
718 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", argv[10]);
719 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", argv[0]);
720 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user", argv[1]);
721 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", argv[1]);
722 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "host", argv[2]);
723 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", argv[3]);
724 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "expires", argv[6]);
725 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", argv[7]);
726 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", argv[14]);
727 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", argv[11]);
728 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", argv[12]);
729 sofia_event_fire(profile, &s_event);
730 }
731
732 if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
733 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
734 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "away");
735 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->url);
736
737 if (argv[4]) {
738 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", argv[4]);
739 }
740
741 if (argv[1] && argv[2]) {
742 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", argv[1], argv[2]);
743 }
744
745 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Unregistered");
746 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
747 sofia_event_fire(profile, &s_event);
748 }
749
750 }
751 return 0;
752 }
753
sofia_reg_expire_call_id(sofia_profile_t * profile,const char * call_id,int reboot)754 void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot)
755 {
756 char *sql = NULL;
757 char *sqlextra = NULL;
758 char *dup = strdup(call_id);
759 char *host = NULL, *user = NULL;
760
761 switch_assert(dup);
762
763 if ((host = strchr(dup, '@'))) {
764 *host++ = '\0';
765 user = dup;
766 } else {
767 host = dup;
768 }
769
770 if (zstr(host)) {
771 host = "none";
772 }
773
774 if (zstr(user)) {
775 sqlextra = switch_mprintf(" or (sip_host='%q')", host);
776 } else {
777 sqlextra = switch_mprintf(" or (sip_user='%q' and sip_host='%q')", user, host);
778 }
779
780 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
781 ",user_agent,server_user,server_host,profile_name,network_ip,network_port"
782 ",%d,sip_realm from sip_registrations where call_id='%q' %s", reboot, call_id, sqlextra);
783
784
785 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_del_callback, profile);
786 switch_safe_free(sql);
787
788 sql = switch_mprintf("delete from sip_registrations where call_id='%q' %s", call_id, sqlextra);
789 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
790
791 switch_safe_free(sqlextra);
792 switch_safe_free(sql);
793 switch_safe_free(dup);
794
795 }
796
sofia_reg_check_expire(sofia_profile_t * profile,time_t now,int reboot)797 void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
798 {
799 char *sql;
800
801 if (now) {
802 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
803 ",user_agent,server_user,server_host,profile_name,network_ip, network_port"
804 ",%d,sip_realm from sip_registrations where expires > 0 and expires <= %ld", reboot, (long) now);
805 } else {
806 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
807 ",user_agent,server_user,server_host,profile_name,network_ip, network_port" ",%d,sip_realm from sip_registrations where expires > 0", reboot);
808 }
809
810 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_del_callback, profile);
811 free(sql);
812
813 if (now) {
814 sql = switch_mprintf("delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%q'",
815 (long) now, mod_sofia_globals.hostname);
816 } else {
817 sql = switch_mprintf("delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
818 }
819 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
820
821
822
823
824 if (now) {
825 sql = switch_mprintf("select call_id from sip_shared_appearance_dialogs where hostname='%q' "
826 "and profile_name='%q' and expires <= %ld", mod_sofia_globals.hostname, profile->name, (long) now);
827
828 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_sla_dialog_del_callback, profile);
829 free(sql);
830
831 sql = switch_mprintf("delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%q' and expires <= %ld",
832 mod_sofia_globals.hostname, (long) now);
833
834
835 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
836 }
837
838
839 if (now) {
840 sql = switch_mprintf("delete from sip_presence where expires > 0 and expires <= %ld and hostname='%q'",
841 (long) now, mod_sofia_globals.hostname);
842 } else {
843 sql = switch_mprintf("delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
844 }
845
846 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
847
848 if (now) {
849 sql = switch_mprintf("delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%q'",
850 (long) now, mod_sofia_globals.hostname);
851 } else {
852 sql = switch_mprintf("delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
853 }
854
855 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
856
857 sofia_presence_check_subscriptions(profile, now);
858
859 if (now) {
860 sql = switch_mprintf("delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'",
861 (long) now, mod_sofia_globals.hostname);
862 } else {
863 sql = switch_mprintf("delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
864 }
865
866 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
867
868 }
869
sofia_reg_uniform_distribution(int max)870 long sofia_reg_uniform_distribution(int max)
871 {
872 /*
873 * Generate a random number following a uniform distribution between 0 and max
874 */
875 int result;
876 int range = max + 1;
877
878 srand((unsigned)((intptr_t) switch_thread_self() + switch_micro_time_now()));
879 result = (int)((double)rand() / (((double)RAND_MAX + (double)1) / range));
880
881 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Generated random %ld, max is %d\n", (long) result, max);
882 return (long) result;
883 }
884
sofia_reg_check_ping_expire(sofia_profile_t * profile,time_t now,int interval)885 void sofia_reg_check_ping_expire(sofia_profile_t *profile, time_t now, int interval)
886 {
887 char *sql;
888 int mean = interval / 2;
889 long next, irand;
890 char buf[32] = "";
891 int count;
892
893 if (now) {
894 if (sofia_test_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING)) {
895 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,"
896 "expires,user_agent,server_user,server_host,profile_name "
897 "from sip_registrations where hostname='%q' and "
898 "profile_name='%q' and orig_hostname='%q' and "
899 "ping_expires > 0 and ping_expires <= %ld",
900 mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname, (long) now);
901
902 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
903 switch_safe_free(sql);
904 } else if (sofia_test_pflag(profile, PFLAG_UDP_NAT_OPTIONS_PING)) {
905 sql = switch_mprintf(" select call_id,sip_user,sip_host,contact,status,rpid, "
906 " expires,user_agent,server_user,server_host,profile_name "
907 " from sip_registrations where (status like '%%UDP-NAT%%' or force_ping=1)"
908 " and hostname='%q' and profile_name='%q' and ping_expires > 0 and ping_expires <= %ld ",
909 mod_sofia_globals.hostname, profile->name, (long) now);
910
911 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
912 switch_safe_free(sql);
913 } else if (sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) {
914 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,"
915 "expires,user_agent,server_user,server_host,profile_name "
916 "from sip_registrations where (status like '%%NAT%%' "
917 "or contact like '%%fs_nat=yes%%' or force_ping=1) and hostname='%q' "
918 "and profile_name='%q' and orig_hostname='%q' and "
919 "ping_expires > 0 and ping_expires <= %ld",
920 mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname, (long) now);
921
922 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
923 switch_safe_free(sql);
924 } else {
925 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,"
926 "expires,user_agent,server_user,server_host,profile_name "
927 "from sip_registrations where force_ping=1 and hostname='%q' "
928 "and profile_name='%q' and orig_hostname='%q' and "
929 "ping_expires > 0 and ping_expires <= %ld",
930 mod_sofia_globals.hostname, profile->name, mod_sofia_globals.hostname, (long) now);
931
932 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nat_callback, profile);
933 switch_safe_free(sql);
934 }
935
936 sql = switch_mprintf("select count(*) from sip_registrations where hostname='%q' and profile_name='%q' and ping_expires <= %ld",
937 mod_sofia_globals.hostname, profile->name, (long) now);
938
939 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
940 switch_safe_free(sql);
941 count = atoi(buf);
942
943 /* only update if needed */
944 if (count) {
945 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, "Updating ping expires for profile %s\n", profile->name);
946 irand = mean + sofia_reg_uniform_distribution(interval);
947 next = (long) now + irand;
948
949 sql = switch_mprintf("update sip_registrations set ping_expires = %ld where hostname='%q' and profile_name='%q' and ping_expires <= %ld ",
950 next, mod_sofia_globals.hostname, profile->name, (long) now);
951 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
952 }
953 }
954 }
955
956
sofia_reg_check_callback(void * pArg,int argc,char ** argv,char ** columnNames)957 int sofia_reg_check_callback(void *pArg, int argc, char **argv, char **columnNames)
958 {
959 sofia_profile_t *profile = (sofia_profile_t *) pArg;
960
961 sofia_reg_send_reboot(profile, argv[0], argv[1], argv[2], argv[3], argv[7], argv[11]);
962
963 return 0;
964 }
965
sofia_reg_check_call_id(sofia_profile_t * profile,const char * call_id)966 void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id)
967 {
968 char *sql = NULL;
969 char *sqlextra = NULL;
970 char *dup = strdup(call_id);
971 char *host = NULL, *user = NULL;
972
973 switch_assert(dup);
974
975 if ((host = strchr(dup, '@'))) {
976 *host++ = '\0';
977 user = dup;
978 } else {
979 host = dup;
980 }
981
982 if (zstr(host)) {
983 host = "none";
984 }
985
986 if (zstr(user)) {
987 sqlextra = switch_mprintf(" or (sip_host='%q')", host);
988 } else {
989 sqlextra = switch_mprintf(" or (sip_user='%q' and sip_host='%q')", user, host);
990 }
991
992 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
993 ",user_agent,server_user,server_host,profile_name,network_ip"
994 " from sip_registrations where call_id='%q' %s", call_id, sqlextra);
995
996
997 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_check_callback, profile);
998
999
1000 switch_safe_free(sql);
1001 switch_safe_free(sqlextra);
1002 switch_safe_free(dup);
1003
1004 }
1005
sofia_reg_check_sync(sofia_profile_t * profile)1006 void sofia_reg_check_sync(sofia_profile_t *profile)
1007 {
1008 char *sql;
1009
1010 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
1011 ",user_agent,server_user,server_host,profile_name,network_ip,network_port,0,sip_realm"
1012 " from sip_registrations where expires > 0");
1013
1014
1015 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_del_callback, profile);
1016 switch_safe_free(sql);
1017
1018 sql = switch_mprintf("delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
1019 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1020
1021 sql = switch_mprintf("delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
1022 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1023
1024 sql = switch_mprintf("delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
1025 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1026
1027 sql = switch_mprintf("delete from sip_subscriptions where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
1028 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1029
1030 sql = switch_mprintf("delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
1031 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1032
1033 }
1034
sofia_reg_find_reg_url(sofia_profile_t * profile,const char * user,const char * host,char * val,switch_size_t len)1035 char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const char *host, char *val, switch_size_t len)
1036 {
1037 struct callback_t cbt = { 0 };
1038 char *sql;
1039
1040 if (!user) {
1041 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Called with null user!\n");
1042 return NULL;
1043 }
1044
1045 cbt.val = val;
1046 cbt.len = len;
1047
1048 if (host) {
1049 sql = switch_mprintf("select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
1050 user, host, host);
1051 } else {
1052 sql = switch_mprintf("select contact from sip_registrations where sip_user='%q'", user);
1053 }
1054
1055
1056 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_find_callback, &cbt);
1057
1058 switch_safe_free(sql);
1059
1060 if (cbt.list) {
1061 switch_console_free_matches(&cbt.list);
1062 }
1063
1064 if (cbt.matches) {
1065 return val;
1066 } else {
1067 return NULL;
1068 }
1069 }
1070
1071
sofia_reg_find_reg_url_multi(sofia_profile_t * profile,const char * user,const char * host)1072 switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *profile, const char *user, const char *host)
1073 {
1074 struct callback_t cbt = { 0 };
1075 char *sql;
1076
1077 if (!user) {
1078 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Called with null user!\n");
1079 return NULL;
1080 }
1081
1082 if (host) {
1083 sql = switch_mprintf("select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
1084 user, host, host);
1085 } else {
1086 sql = switch_mprintf("select contact from sip_registrations where sip_user='%q'", user);
1087 }
1088
1089
1090 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_find_callback, &cbt);
1091
1092 switch_safe_free(sql);
1093
1094 return cbt.list;
1095 }
1096
1097
sofia_reg_find_reg_url_with_positive_expires_multi(sofia_profile_t * profile,const char * user,const char * host,time_t reg_time,const char * contact_str,long exptime)1098 switch_console_callback_match_t *sofia_reg_find_reg_url_with_positive_expires_multi(sofia_profile_t *profile, const char *user, const char *host, time_t reg_time, const char *contact_str, long exptime)
1099 {
1100 struct callback_t cbt = { 0 };
1101 char *sql;
1102
1103 if (!user) {
1104 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Called with null user!\n");
1105 return NULL;
1106 }
1107
1108 if (host) {
1109 sql = switch_mprintf("select contact,expires from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
1110 user, host, host);
1111 } else {
1112 sql = switch_mprintf("select contact,expires from sip_registrations where sip_user='%q'", user);
1113 }
1114
1115 cbt.time = reg_time;
1116 cbt.contact_str = contact_str;
1117 cbt.exptime = exptime;
1118
1119 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_find_reg_with_positive_expires_callback, &cbt);
1120 free(sql);
1121
1122 return cbt.list;
1123 }
1124
1125
sofia_reg_auth_challenge(sofia_profile_t * profile,nua_handle_t * nh,sofia_dispatch_event_t * de,sofia_regtype_t regtype,const char * realm,int stale,long exptime)1126 void sofia_reg_auth_challenge(sofia_profile_t *profile, nua_handle_t *nh, sofia_dispatch_event_t *de,
1127 sofia_regtype_t regtype, const char *realm, int stale, long exptime)
1128 {
1129 switch_uuid_t uuid;
1130 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
1131 char *sql, *auth_str;
1132 msg_t *msg = NULL;
1133
1134
1135 if (de && de->data) {
1136 msg = de->data->e_msg;
1137 }
1138
1139 switch_uuid_get(&uuid);
1140 switch_uuid_format(uuid_str, &uuid);
1141
1142 sql = switch_mprintf("insert into sip_authentication (nonce,expires,profile_name,hostname, last_nc) "
1143 "values('%q', %ld, '%q', '%q', 0)", uuid_str,
1144 (long) switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL) + exptime,
1145 profile->name, mod_sofia_globals.hostname);
1146 switch_assert(sql != NULL);
1147 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1148
1149 auth_str = switch_mprintf("Digest realm=\"%q\", nonce=\"%q\",%s algorithm=MD5, qop=\"auth\"", realm, uuid_str, stale ? " stale=true," : "");
1150
1151 if (regtype == REG_REGISTER) {
1152 nua_respond(nh, SIP_401_UNAUTHORIZED, TAG_IF(msg, NUTAG_WITH_THIS_MSG(msg)), SIPTAG_WWW_AUTHENTICATE_STR(auth_str), TAG_END());
1153 } else if (regtype == REG_INVITE) {
1154 nua_respond(nh, SIP_407_PROXY_AUTH_REQUIRED,
1155 TAG_IF(msg, NUTAG_WITH_THIS_MSG(msg)),
1156 SIPTAG_PROXY_AUTHENTICATE_STR(auth_str), TAG_END());
1157 }
1158
1159 switch_safe_free(auth_str);
1160 }
1161
sofia_reg_reg_count(sofia_profile_t * profile,const char * user,const char * host)1162 uint32_t sofia_reg_reg_count(sofia_profile_t *profile, const char *user, const char *host)
1163 {
1164 char buf[32] = "";
1165 char *sql;
1166
1167 sql = switch_mprintf("select count(*) from sip_registrations where profile_name='%q' and "
1168 "sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", profile->name, user, host, host);
1169
1170 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
1171 switch_safe_free(sql);
1172 return atoi(buf);
1173 }
1174
debounce_check(sofia_profile_t * profile,const char * user,const char * host)1175 static int debounce_check(sofia_profile_t *profile, const char *user, const char *host)
1176 {
1177 char key[512] = "";
1178 int r = 0;
1179 time_t *last, now = switch_epoch_time_now(NULL);
1180
1181 snprintf(key, sizeof(key)-1, "%s%s", user, host);
1182 key[sizeof(key)-1] = '\0';
1183
1184 switch_mutex_lock(profile->ireg_mutex);
1185 if ((last = switch_core_hash_find(profile->mwi_debounce_hash, key))) {
1186 if (now - *last > 30) {
1187 *last = now;
1188 r = 1;
1189 }
1190 } else {
1191 last = switch_core_alloc(profile->pool, sizeof(*last));
1192 *last = now;
1193
1194 switch_core_hash_insert(profile->mwi_debounce_hash, key, last);
1195 r = 1;
1196 }
1197 switch_mutex_unlock(profile->ireg_mutex);
1198
1199 return r;
1200 }
1201
sofia_reg_close_handles(sofia_profile_t * profile)1202 void sofia_reg_close_handles(sofia_profile_t *profile)
1203 {
1204 nua_handle_t *nh = NULL;
1205 switch_hash_index_t *hi = NULL;
1206 const void *var;
1207 void *val;
1208
1209
1210 switch_mutex_lock(profile->flag_mutex);
1211 if (profile->reg_nh_hash) {
1212 top:
1213 for (hi = switch_core_hash_first_iter( profile->reg_nh_hash, hi); hi; hi = switch_core_hash_next(&hi)) {
1214 switch_core_hash_this(hi, &var, NULL, &val);
1215 if ((nh = (nua_handle_t *) val)) {
1216 nua_handle_unref(nh);
1217 nua_handle_destroy(nh);
1218 switch_core_hash_delete(profile->reg_nh_hash, (char *) var);
1219 goto top;
1220 }
1221 }
1222 switch_safe_free(hi);
1223
1224 }
1225 switch_mutex_unlock(profile->flag_mutex);
1226
1227 return;
1228
1229 }
1230
1231
sofia_reg_handle_register_token(nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sip_t const * sip,sofia_dispatch_event_t * de,sofia_regtype_t regtype,char * key,uint32_t keylen,switch_event_t ** v_event,const char * is_nat,sofia_private_t ** sofia_private_p,switch_xml_t * user_xml,const char * sw_acl_token)1232 uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
1233 sofia_dispatch_event_t *de, sofia_regtype_t regtype, char *key,
1234 uint32_t keylen, switch_event_t **v_event, const char *is_nat, sofia_private_t **sofia_private_p, switch_xml_t *user_xml, const char *sw_acl_token)
1235 {
1236 sip_to_t const *to = NULL;
1237 sip_from_t const *from = NULL;
1238 sip_expires_t const *expires = NULL;
1239 sip_authorization_t const *authorization = NULL;
1240 sip_contact_t const *contact = NULL;
1241 char *sql;
1242 switch_event_t *s_event;
1243 const char *reg_meta = NULL;
1244 const char *to_user = NULL;
1245 const char *to_host = NULL;
1246 char *mwi_account = NULL;
1247 char *dup_mwi_account = NULL;
1248 char *display_m = NULL;
1249 char *mwi_user = NULL;
1250 char *mwi_host = NULL;
1251 char *var = NULL;
1252 const char *from_user = NULL;
1253 const char *from_host = NULL;
1254 const char *reg_host = profile->reg_db_domain;
1255 const char *sub_host = profile->sub_domain;
1256 char contact_str[1024] = "";
1257 uint8_t multi_reg = 0, multi_reg_contact = 0, avoid_multi_reg = 0;
1258 uint8_t stale = 0, forbidden = 0;
1259 auth_res_t auth_res = AUTH_OK;
1260 long exptime = 300;
1261 switch_event_t *event;
1262 const char *rpid = "unknown";
1263 const char *display = "\"user\"";
1264 char network_ip[80];
1265 char network_port_c[6];
1266 char url_ip[80];
1267 int network_port;
1268 const char *reg_desc = "Registered";
1269 const char *call_id = NULL;
1270 char *force_user;
1271 char received_data[128] = "";
1272 char *path_val = NULL;
1273 switch_event_t *auth_params = NULL;
1274 int r = 0;
1275 long reg_count = 0;
1276 const char *agent = "unknown";
1277 const char *pres_on_reg = NULL;
1278 int send_pres = 0;
1279 int send_message_query = 0;
1280 int force_ping = 0;
1281 int is_tls = 0, is_tcp = 0, is_ws = 0, is_wss = 0;
1282 char expbuf[35] = "";
1283 time_t reg_time = switch_epoch_time_now(NULL);
1284 const char *vproto = NULL;
1285 const char *proto = "sip";
1286 const char *uparams = NULL;
1287 const char *p;
1288 char *utmp = NULL;
1289 sofia_private_t *sofia_private = NULL;
1290 char *sw_to_user;
1291 char *sw_reg_host;
1292 char *token_val = NULL;
1293
1294
1295 if (sofia_private_p) {
1296 sofia_private = *sofia_private_p;
1297 }
1298
1299 if (sip && sip->sip_contact && sip->sip_contact->m_url->url_params) {
1300 uparams = sip->sip_contact->m_url->url_params;
1301 } else {
1302 uparams = NULL;
1303 }
1304
1305
1306 if (sip && sip->sip_via && (vproto = sip->sip_via->v_protocol)) {
1307 if (!strcasecmp(vproto, "sip/2.0/ws")) {
1308 is_ws = 1;
1309 is_nat = "ws";
1310 } else if (!strcasecmp(vproto, "sip/2.0/wss")) {
1311 is_wss = 1;
1312 is_nat = "wss";
1313
1314 if (uparams && (p = switch_stristr("transport=ws", uparams))) {
1315 if (p[12] != 's') {
1316 utmp = switch_string_replace(uparams, "transport=ws", "transport=wss");
1317 }
1318 }
1319 }
1320 }
1321
1322 if (v_event && *v_event) pres_on_reg = switch_event_get_header(*v_event, "send-presence-on-register");
1323
1324 if (!(send_pres = switch_true(pres_on_reg))) {
1325 if (pres_on_reg && !strcasecmp(pres_on_reg, "first-only")) {
1326 send_pres = 2;
1327 }
1328 }
1329
1330 /* all callers must confirm that sip and sip->sip_request are not NULL */
1331 switch_assert(sip != NULL && sip->sip_request != NULL);
1332
1333 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
1334
1335 snprintf(network_port_c, sizeof(network_port_c), "%d", network_port);
1336
1337 snprintf(url_ip, sizeof(url_ip), (msg_addrinfo(de->data->e_msg))->ai_addr->sa_family == AF_INET6 ? "[%s]" : "%s", network_ip);
1338
1339 expires = sip->sip_expires;
1340 authorization = sip->sip_authorization;
1341 contact = sip->sip_contact;
1342 to = sip->sip_to;
1343 from = sip->sip_from;
1344 call_id = sip->sip_call_id->i_id;
1345 switch_assert(call_id);
1346
1347 if (sip->sip_user_agent) {
1348 agent = sip->sip_user_agent->g_string;
1349 }
1350
1351 if (from) {
1352 from_user = from->a_url->url_user;
1353 from_host = from->a_url->url_host;
1354 }
1355
1356 if (to) {
1357 to_user = to->a_url->url_user;
1358 to_host = to->a_url->url_host;
1359 }
1360
1361 if (!to_user) {
1362 to_user = from_user;
1363 }
1364 if (!to_host) {
1365 to_host = from_host;
1366 }
1367
1368 if (!to_user || !to_host) {
1369 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can not do authorization without a complete header in REGISTER request from %s:%d\n",
1370 network_ip, network_port);
1371
1372 nua_respond(nh, SIP_401_UNAUTHORIZED, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
1373 switch_goto_int(r, 1, end);
1374 }
1375
1376 if (zstr(reg_host)) {
1377 reg_host = to_host;
1378 }
1379 if (zstr(sub_host)) {
1380 sub_host = to_host;
1381 }
1382
1383 if (contact) {
1384 const char *port = contact->m_url->url_port;
1385 char new_port[25] = "";
1386 const char *contact_host = contact->m_url->url_host;
1387 char *path_encoded = NULL;
1388 int path_encoded_len = 0;
1389
1390
1391 if (uparams && switch_stristr("transport=tls", uparams)) {
1392 is_tls += 1;
1393 if (sofia_test_pflag(profile, PFLAG_TLS_ALWAYS_NAT)) {
1394 is_nat = "tls";
1395 }
1396 }
1397
1398 if (sip->sip_contact->m_url->url_type == url_sips) {
1399 proto = "sips";
1400 is_tls += 2;
1401 if (sofia_test_pflag(profile, PFLAG_TLS_ALWAYS_NAT)) {
1402 is_nat = "tls";
1403 }
1404 }
1405
1406 if (uparams && switch_stristr("transport=tcp", uparams)) {
1407 is_tcp = 1;
1408 if (sofia_test_pflag(profile, PFLAG_TCP_ALWAYS_NAT)) {
1409 is_nat = "tcp";
1410 }
1411 }
1412
1413 display = contact->m_display;
1414
1415 if (is_nat) {
1416 if (is_tls) {
1417 reg_desc = "Registered(TLS-NAT)";
1418 } else if (is_tcp) {
1419 reg_desc = "Registered(TCP-NAT)";
1420 } else if (is_ws) {
1421 reg_desc = "Registered(WS-NAT)";
1422 } else if (is_wss) {
1423 reg_desc = "Registered(WSS-NAT)";
1424 } else {
1425 reg_desc = "Registered(UDP-NAT)";
1426 }
1427 //contact_host = url_ip;
1428 //switch_snprintf(new_port, sizeof(new_port), ":%d", network_port);
1429 //port = NULL;
1430 } else {
1431 if (is_tls) {
1432 reg_desc = "Registered(TLS)";
1433 } else if (is_tcp) {
1434 reg_desc = "Registered(TCP)";
1435 } else {
1436 reg_desc = "Registered(UDP)";
1437 }
1438 }
1439
1440 if (zstr(display)) {
1441 if (to) {
1442 display = to->a_display;
1443 if (zstr(display)) {
1444 display = "\"\"";
1445 }
1446 }
1447 }
1448
1449 if (display && !strchr(display, '"')) {
1450 display_m = switch_mprintf("\"%q\"", display);
1451 display = display_m;
1452 }
1453
1454
1455 if (sip->sip_path) {
1456 char *path_stripped = NULL;
1457 char *path_val_to_encode = NULL;
1458 su_strlst_t *path_list = su_strlst_create(nua_handle_home(nh));
1459 sip_path_t *next_path = sip->sip_path;
1460 for (; next_path; next_path = next_path->r_next) {
1461 path_val = sip_header_as_string(nua_handle_home(nh), (void *) next_path);
1462 if (path_val) {
1463 path_stripped = sofia_glue_get_url_from_contact(path_val, SWITCH_TRUE);
1464 su_free(nua_handle_home(nh), path_val);
1465 su_strlst_dup_append(path_list, path_stripped);
1466 switch_safe_free(path_stripped);
1467 }
1468 }
1469
1470 path_val = su_strlst_join(path_list, nua_handle_home(nh), ",");
1471 path_val_to_encode = su_strlst_join(path_list, nua_handle_home(nh), "%2C");
1472 su_strlst_destroy(path_list);
1473 if (path_val_to_encode) {
1474 path_encoded_len = (int)(strlen(path_val_to_encode) * 3) + 1;
1475 switch_zmalloc(path_encoded, path_encoded_len);
1476 switch_copy_string(path_encoded, ";fs_path=", 10);
1477 switch_url_encode(path_val_to_encode, path_encoded + 9, path_encoded_len - 9);
1478 su_free(nua_handle_home(nh), path_val_to_encode);
1479 }
1480 } else if (is_nat) {
1481 char my_contact_str[1024];
1482 if (uparams) {
1483 switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d;%s", proto,
1484 contact->m_url->url_user, url_ip, network_port, utmp ? utmp : uparams);
1485 } else {
1486 switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d", proto, contact->m_url->url_user, url_ip, network_port);
1487 }
1488
1489 path_encoded_len = (int)(strlen(my_contact_str) * 3) + 1;
1490
1491 switch_zmalloc(path_encoded, path_encoded_len);
1492 switch_copy_string(path_encoded, ";fs_path=", 10);
1493 switch_url_encode(my_contact_str, path_encoded + 9, path_encoded_len - 9);
1494 exptime = 30;
1495 }
1496
1497 if (port) {
1498 switch_snprintf(new_port, sizeof(new_port), ":%s", port);
1499 }
1500
1501 if (is_nat && sofia_test_pflag(profile, PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) {
1502 switch_snprintf(received_data, sizeof(received_data), ";received=%s:%d", url_ip, network_port);
1503 }
1504
1505 if (uparams) {
1506 switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s%s;%s%s%s%s>",
1507 display, proto, contact->m_url->url_user, contact_host, new_port,
1508 uparams,
1509 received_data, is_nat ? ";fs_nat=yes" : "", path_encoded ? path_encoded : "");
1510
1511 } else {
1512 switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s%s%s%s%s>", display, proto, contact->m_url->url_user, contact_host, new_port,
1513 received_data, is_nat ? ";fs_nat=yes" : "", path_encoded ? path_encoded : "");
1514 }
1515
1516 switch_safe_free(path_encoded);
1517 }
1518
1519 if (expires) {
1520 exptime = expires->ex_delta;
1521 } else if (contact && contact->m_expires) {
1522 exptime = atol(contact->m_expires);
1523 }
1524
1525 if (regtype == REG_REGISTER) {
1526 authorization = sip->sip_authorization;
1527 } else if (regtype == REG_INVITE) {
1528 authorization = sip->sip_proxy_authorization;
1529 }
1530
1531 if (regtype == REG_AUTO_REGISTER || (regtype == REG_REGISTER && sofia_test_pflag(profile, PFLAG_BLIND_REG))) {
1532 regtype = REG_REGISTER;
1533 if (!zstr(sw_acl_token)) {
1534 token_val = strdup(sw_acl_token);
1535
1536 switch_split_user_domain(token_val, &sw_to_user, &sw_reg_host);
1537 to_user = sw_to_user;
1538 reg_host = sw_reg_host;
1539 }
1540 goto reg;
1541 }
1542
1543 if (authorization) {
1544 char *v_contact_str = NULL;
1545 const char *username = "unknown";
1546 const char *realm = reg_host;
1547 if ((auth_res = sofia_reg_parse_auth(profile, authorization, sip, de, sip->sip_request->rq_method_name,
1548 key, keylen, network_ip, network_port, v_event, exptime, regtype, to_user, &auth_params, ®_count, user_xml)) == AUTH_STALE) {
1549 stale = 1;
1550 }
1551
1552
1553 if (auth_params) {
1554 username = switch_event_get_header(auth_params, "sip_auth_username");
1555 realm = switch_event_get_header(auth_params, "sip_auth_realm");
1556 }
1557 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER_ATTEMPT) == SWITCH_STATUS_SUCCESS) {
1558 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1559 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
1560 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);
1561 if (contact)
1562 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);
1563 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
1564 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);
1565 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc);
1566 if (contact)
1567 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);
1568 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user);
1569 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host);
1570 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
1571 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
1572 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", username);
1573 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", realm);
1574 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
1575
1576 switch (auth_res) {
1577 case AUTH_OK:
1578 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth-result", "SUCCESS");
1579 break;
1580 case AUTH_RENEWED:
1581 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth-result", "RENEWED");
1582 break;
1583 case AUTH_STALE:
1584 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth-result", "STALE");
1585 break;
1586 case AUTH_FORBIDDEN:
1587 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "auth-result", "FORBIDDEN");
1588 break;
1589 }
1590 switch_event_fire(&s_event);
1591 }
1592
1593 if (contact && exptime && v_event && *v_event) {
1594 uint32_t exp_var;
1595 uint32_t exp_max_deviation_var;
1596 char *allow_multireg = NULL;
1597 int auto_connectile = 0;
1598
1599 allow_multireg = switch_event_get_header(*v_event, "sip-allow-multiple-registrations");
1600 if (allow_multireg && switch_false(allow_multireg)) {
1601 avoid_multi_reg = 1;
1602 }
1603
1604 /* Allow us to force the SIP user to be something specific - needed if
1605 * we - for example - want to be able to ensure that the username a UA can
1606 * be contacted at is the same one that they used for authentication.
1607 */
1608 if ((force_user = switch_event_get_header(*v_event, "sip-force-user"))) {
1609 to_user = force_user;
1610 }
1611
1612 if (!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) &&
1613 profile->server_rport_level >= 2 && sip->sip_user_agent &&
1614 sip->sip_user_agent->g_string &&
1615 ( !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) ||
1616 !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) ||
1617 !strncasecmp(sip->sip_user_agent->g_string, "ADTRAN_Total_Access", 19) )) {
1618 if (sip->sip_via) {
1619 const char *host = sip->sip_via->v_host;
1620 const char *c_port = sip->sip_via->v_port;
1621 int port = 0;
1622
1623 if (c_port) port = atoi(c_port);
1624 if (!port) port = 5060;
1625
1626 if (host && strcmp(network_ip, host)) {
1627 auto_connectile = 1;
1628 } else if (port != network_port) {
1629 auto_connectile = 1;
1630 }
1631 } else {
1632 auto_connectile = 1;
1633 }
1634 }
1635
1636 if (auto_connectile || (v_contact_str = switch_event_get_header(*v_event, "sip-force-contact"))) {
1637 if (auto_connectile || (!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0"))) {
1638 char *path_encoded = NULL;
1639 size_t path_encoded_len;
1640 char my_contact_str[1024];
1641
1642 switch_snprintf(my_contact_str, sizeof(my_contact_str), "%s:%s@%s:%d", proto, contact->m_url->url_user, url_ip, network_port);
1643 path_encoded_len = (strlen(my_contact_str) * 3) + 1;
1644
1645 if (!switch_stristr("fs_path=", contact_str)) {
1646 switch_zmalloc(path_encoded, path_encoded_len);
1647 switch_copy_string(path_encoded, ";fs_nat=yes;fs_path=", 21);
1648 switch_url_encode(my_contact_str, path_encoded + 20, path_encoded_len - 20);
1649 reg_desc = "Registered(AUTO-NAT-2.0)";
1650 exptime = 30;
1651
1652 /* place fs_path (the encoded path) inside the <...> of the contact string, if possible */
1653 if (contact_str[strlen(contact_str) - 1] == '>') {
1654 switch_snprintf(contact_str + strlen(contact_str) - 1, sizeof(contact_str) - strlen(contact_str) + 1, "%s>", path_encoded);
1655 } else {
1656 switch_snprintf(contact_str + strlen(contact_str), sizeof(contact_str) - strlen(contact_str), "%s", path_encoded);
1657 }
1658 switch_safe_free(path_encoded);
1659 }
1660 } else {
1661 if (*received_data && sofia_test_pflag(profile, PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) {
1662 switch_snprintf(received_data, sizeof(received_data), ";received=%s:%d", url_ip, network_port);
1663 }
1664
1665 if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") ||
1666 !strcasecmp(v_contact_str, "NDLB-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-tls-connectile-dysfunction")) {
1667 if (uparams) {
1668 switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s:%d;%s%s;fs_nat=yes>",
1669 display, proto, contact->m_url->url_user, url_ip, network_port, uparams, received_data);
1670 } else {
1671 switch_snprintf(contact_str, sizeof(contact_str), "%s <%s:%s@%s:%d%s;fs_nat=yes>", display, proto,
1672 contact->m_url->url_user, url_ip,
1673 network_port, received_data);
1674 }
1675 if (switch_stristr(v_contact_str, "transport=tls")) {
1676 reg_desc = "Registered(TLSHACK)";
1677 } else {
1678 reg_desc = "Registered(AUTO-NAT)";
1679 exptime = 30;
1680 }
1681 } else {
1682 char *p;
1683 switch_copy_string(contact_str, v_contact_str, sizeof(contact_str));
1684 for (p = contact_str; p && *p; p++) {
1685 if (*p == '\'' || *p == '[' || *p == ']') {
1686 *p = '"';
1687 }
1688 }
1689 }
1690 }
1691 }
1692
1693 if ( (( exp_var = atoi(switch_event_get_header_nil(*v_event, "sip-force-expires-min")) )) ||
1694 (( exp_var = profile->sip_force_expires_min )) ) {
1695 if ( (exp_var > 0) && (exptime < exp_var) ) {
1696 exptime = exp_var;
1697 }
1698 }
1699 if ( (( exp_var = atoi(switch_event_get_header_nil(*v_event, "sip-force-expires-max")) )) ||
1700 (( exp_var = profile->sip_force_expires_max )) ) {
1701 if ( (exp_var > 0) && (exptime > exp_var) ) {
1702 exptime = exp_var;
1703 }
1704 }
1705 if ( (( exp_var = atoi(switch_event_get_header_nil(*v_event, "sip-force-expires")) )) ||
1706 (( exp_var = profile->sip_force_expires )) ) {
1707 if (exp_var > 0) {
1708 exptime = exp_var;
1709 }
1710 }
1711
1712 if ( (( exp_max_deviation_var = atoi(switch_event_get_header_nil(*v_event, "sip-expires-max-deviation")) )) ||
1713 (( exp_max_deviation_var = profile->sip_expires_max_deviation )) ) {
1714 if (exp_max_deviation_var > 0) {
1715 int exp_deviation;
1716 srand( (unsigned) ( (unsigned)(intptr_t)switch_thread_self() + switch_micro_time_now() ) );
1717 /* random number between negative exp_max_deviation_var and positive exp_max_deviation_var: */
1718 exp_deviation = ( rand() % ( exp_max_deviation_var * 2 ) ) - exp_max_deviation_var;
1719 exptime += exp_deviation;
1720 }
1721 }
1722
1723 }
1724
1725 if (auth_res != AUTH_OK && auth_res != AUTH_RENEWED && !stale) {
1726 if (auth_res == AUTH_FORBIDDEN) {
1727 nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
1728 forbidden = 1;
1729 } else {
1730 nua_respond(nh, SIP_401_UNAUTHORIZED, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
1731 }
1732
1733 if (profile->debug) {
1734 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send %s for [%s@%s]\n",
1735 forbidden ? "forbidden" : "challenge", to_user, to_host);
1736 }
1737 /* Log line added to support Fail2Ban */
1738 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
1739 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth %s (%s) on sofia profile '%s' "
1740 "for [%s@%s] from ip %s\n", forbidden ? "failure" : "challenge",
1741 (regtype == REG_INVITE) ? "INVITE" : "REGISTER", profile->name, to_user, to_host, network_ip);
1742 }
1743
1744 if (forbidden && switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER_FAILURE) == SWITCH_STATUS_SUCCESS) {
1745 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1746 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", to_user);
1747 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", to_host);
1748 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
1749 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
1750 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1751 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
1752 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "registration-type", (regtype == REG_INVITE) ? "INVITE" : "REGISTER");
1753 switch_event_fire(&s_event);
1754 }
1755 switch_goto_int(r, 1, end);
1756 }
1757 }
1758
1759 if (!authorization || stale) {
1760 const char *realm = profile->challenge_realm;
1761
1762 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_PRE_REGISTER) == SWITCH_STATUS_SUCCESS) {
1763 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
1764 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
1765 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);
1766 if (contact)
1767 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);
1768 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
1769 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);
1770 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc);
1771 if (contact)
1772 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);
1773 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user);
1774 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host);
1775 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
1776 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
1777 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
1778 switch_event_fire(&s_event);
1779 }
1780
1781 if (zstr(realm) || !strcasecmp(realm, "auto_to")) {
1782 realm = to_host;
1783 } else if (!strcasecmp(realm, "auto_from")) {
1784 realm = from_host;
1785 }
1786
1787 sofia_reg_auth_challenge(profile, nh, de, regtype, realm, stale, exptime);
1788
1789 if (profile->debug) {
1790 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send challenge for [%s@%s]\n", to_user, to_host);
1791 }
1792 /* Log line added to support Fail2Ban */
1793 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
1794 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth challenge (%s) on sofia profile '%s' "
1795 "for [%s@%s] from ip %s\n", (regtype == REG_INVITE) ? "INVITE" : "REGISTER",
1796 profile->name, to_user, to_host, network_ip);
1797 }
1798
1799 switch_goto_int(r, 1, end);
1800 }
1801
1802 if (!contact)
1803 goto respond_200_ok;
1804
1805 reg:
1806
1807
1808 if (v_event && *v_event && (var = switch_event_get_header(*v_event, "sip-force-extension"))) {
1809 to_user = var;
1810 }
1811
1812 if (v_event && *v_event && (var = switch_event_get_header(*v_event, "registration_metadata"))) {
1813 reg_meta = var;
1814 }
1815
1816 /* associated MWI account */
1817 if (v_event && *v_event && (mwi_account = switch_event_get_header(*v_event, "mwi-account"))) {
1818 dup_mwi_account = strdup(mwi_account);
1819 switch_assert(dup_mwi_account != NULL);
1820 switch_split_user_domain(dup_mwi_account, &mwi_user, &mwi_host);
1821 }
1822
1823 if (!mwi_user) {
1824 mwi_user = (char *) to_user;
1825 }
1826 if (!mwi_host) {
1827 mwi_host = (char *) reg_host;
1828 }
1829
1830 /* per-profile unsolicited MWI on register */
1831 if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER)) {
1832 send_message_query = 2;
1833 } else if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER)) {
1834 send_message_query = 1;
1835 } else {
1836 send_message_query = 0;
1837 }
1838
1839 /* per-account unsolicited MWI on register */
1840 if (v_event && *v_event && (var = switch_event_get_header(*v_event, "send-message-query-on-register"))) {
1841 if (switch_true(var)) {
1842 send_message_query = 2;
1843 } else if (!strcasecmp(var, "first-only")) {
1844 send_message_query = 1;
1845 } else {
1846 send_message_query = 0;
1847 }
1848 }
1849
1850 /* per-account enable options ping on register */
1851 if (v_event && *v_event && (var = switch_event_get_header(*v_event, "force_ping"))) {
1852 if (switch_true(var)) {
1853 force_ping = 1;
1854 } else {
1855 force_ping = 0;
1856 }
1857 }
1858
1859 if (regtype != REG_REGISTER) {
1860 switch_goto_int(r, 0, end);
1861 }
1862
1863
1864 /* Does this profile supports multiple registrations ? */
1865 multi_reg = (sofia_test_pflag(profile, PFLAG_MULTIREG)) ? 1 : 0;
1866 multi_reg_contact = (sofia_test_pflag(profile, PFLAG_MULTIREG_CONTACT)) ? 1 : 0;
1867
1868
1869 if (multi_reg && avoid_multi_reg) {
1870 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
1871 "Disabling multiple registrations on a per-user basis for %s@%s\n", switch_str_nil(to_user), switch_str_nil(to_host));
1872 multi_reg = 0;
1873 }
1874
1875 if (exptime) {
1876 char guess_ip4[256];
1877 const char *username = "unknown";
1878 const char *realm = reg_host;
1879 char *url = NULL;
1880 char *contact = NULL;
1881 switch_bool_t update_registration = SWITCH_FALSE;
1882
1883 if (auth_params) {
1884 username = switch_event_get_header(auth_params, "sip_auth_username");
1885 realm = switch_event_get_header(auth_params, "sip_auth_realm");
1886 }
1887
1888 if (auth_res != AUTH_RENEWED || !multi_reg) {
1889 if (multi_reg) {
1890 if (multi_reg_contact) {
1891 sql =
1892 switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
1893 } else {
1894 sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
1895 }
1896 } else {
1897 sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
1898 }
1899
1900 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1901 } else {
1902 char buf[32] = "";
1903
1904
1905 sql = switch_mprintf("select count(*) from sip_registrations where sip_user='%q' and sip_username='%q' and sip_host='%q' and contact='%q'",
1906 to_user, username, reg_host, contact_str);
1907
1908
1909
1910 sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
1911 switch_safe_free(sql);
1912 if (atoi(buf) > 0) {
1913 update_registration = SWITCH_TRUE;
1914 }
1915 }
1916
1917 switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
1918
1919 contact = sofia_glue_get_url_from_contact(contact_str, 1);
1920 url = switch_mprintf("sofia/%q/%s:%q", profile->name, proto, sofia_glue_strip_proto(contact));
1921
1922 switch_core_add_registration(to_user, reg_host, call_id, url, (long) reg_time + (long) exptime + profile->sip_expires_late_margin,
1923 network_ip, network_port_c, is_tls ? "tls" : is_tcp ? "tcp" : "udp", reg_meta);
1924
1925 switch_safe_free(url);
1926 switch_safe_free(contact);
1927
1928 if ((is_wss || is_ws || (sofia_test_pflag(profile, PFLAG_TCP_UNREG_ON_SOCKET_CLOSE) && (is_tcp || is_tls))) && !sofia_private) {
1929 char key[256] = "";
1930 nua_handle_t *hnh;
1931 switch_snprintf(key, sizeof(key), "%s%s%s", call_id, network_ip, network_port_c);
1932
1933 switch_mutex_lock(profile->flag_mutex);
1934 hnh = switch_core_hash_find(profile->reg_nh_hash, key);
1935 switch_mutex_unlock(profile->flag_mutex);
1936
1937 if (!hnh) {
1938 if (!(sofia_private = su_alloc(nh->nh_home, sizeof(*sofia_private)))) {
1939 abort();
1940 }
1941
1942 memset(sofia_private, 0, sizeof(*sofia_private));
1943 sofia_private->call_id = su_strdup(nh->nh_home, call_id);
1944 sofia_private->network_ip = su_strdup(nh->nh_home, network_ip);
1945 sofia_private->network_port = su_strdup(nh->nh_home, network_port_c);
1946 sofia_private->key = su_strdup(nh->nh_home, key);
1947 sofia_private->user = su_strdup(nh->nh_home, to_user);
1948 sofia_private->realm = su_strdup(nh->nh_home, reg_host);
1949
1950 sofia_private->is_static++;
1951 *sofia_private_p = sofia_private;
1952 nua_handle_bind(nh, sofia_private);
1953 nua_handle_ref(nh);
1954 switch_core_hash_insert(profile->reg_nh_hash, key, nh);
1955 }
1956 }
1957
1958
1959 if (!update_registration) {
1960 sql = switch_mprintf("insert into sip_registrations "
1961 "(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
1962 "user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm,"
1963 "mwi_user,mwi_host, orig_server_host, orig_hostname, sub_host, ping_status, ping_count, force_ping) "
1964 "values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q','%q', '%q', %d, %d)",
1965 call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : "",
1966 contact_str, reg_desc, rpid, (long) reg_time + (long) exptime + profile->sip_expires_late_margin,
1967 agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm,
1968 mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname, sub_host, "Reachable", 0, force_ping);
1969 } else {
1970 sql = switch_mprintf("update sip_registrations set call_id='%q',"
1971 "sub_host='%q', network_ip='%q',network_port='%q',"
1972 "presence_hosts='%q', server_host='%q', orig_server_host='%q',"
1973 "hostname='%q', orig_hostname='%q',"
1974 "expires = %ld, force_ping=%d where sip_user='%q' and sip_username='%q' and sip_host='%q' and contact='%q'",
1975 call_id, sub_host, network_ip, network_port_c,
1976 profile->presence_hosts ? profile->presence_hosts : "", guess_ip4, guess_ip4,
1977 mod_sofia_globals.hostname, mod_sofia_globals.hostname,
1978 (long) reg_time + (long) exptime + profile->sip_expires_late_margin, force_ping,
1979 to_user, username, reg_host, contact_str);
1980 }
1981
1982 if (sql) {
1983 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1984 }
1985
1986 if (!update_registration && sofia_reg_reg_count(profile, to_user, reg_host) == 1) {
1987 sql = switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' and profile_name='%q' and open_closed='closed'",
1988 to_user, reg_host, profile->name);
1989 if (mod_sofia_globals.debug_presence > 0) {
1990 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DELETE PRESENCE SQL: %s\n", sql);
1991 }
1992 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
1993 }
1994
1995 if (multi_reg) {
1996 if (multi_reg_contact) {
1997 sql = switch_mprintf("delete from sip_registrations where contact='%q' and expires!=%ld", contact_str, (long) reg_time + (long) exptime + profile->sip_expires_late_margin);
1998 } else {
1999 sql = switch_mprintf("delete from sip_registrations where call_id='%q' and expires!=%ld", call_id, (long) reg_time + (long) exptime + profile->sip_expires_late_margin);
2000 }
2001
2002 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
2003 }
2004
2005
2006
2007 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER) == SWITCH_STATUS_SUCCESS) {
2008 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
2009 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
2010 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);
2011 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-hosts", profile->presence_hosts ? profile->presence_hosts : "n/a");
2012 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);
2013 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
2014 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);
2015 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", reg_desc);
2016 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);
2017 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-user", from_user);
2018 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-host", from_host);
2019 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
2020 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
2021 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", username);
2022 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", realm);
2023 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
2024 if (update_registration) {
2025 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "update-reg", "true");
2026 }
2027 if (v_event && *v_event) {
2028 switch_event_merge(s_event, *v_event);
2029 }
2030 switch_event_fire(&s_event);
2031 }
2032
2033
2034
2035 if (profile->debug) {
2036 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
2037 "Register:\nFrom: [%s@%s]\nContact: [%s]\nExpires: [%ld]\n", to_user, reg_host, contact_str, (long) exptime);
2038 }
2039
2040 } else {
2041 int send = 1;
2042
2043 if (multi_reg) {
2044 if (sofia_reg_reg_count(profile, to_user, sub_host) > 0) {
2045 send = 0;
2046 }
2047 }
2048
2049 sofia_reg_check_socket(profile, call_id, network_ip, network_port_c);
2050
2051 if (send && switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
2052 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
2053 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
2054 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
2055 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
2056 (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
2057 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
2058 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Unregistered");
2059 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-source", "register");
2060 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
2061 switch_event_fire(&event);
2062 }
2063
2064
2065 if (multi_reg) {
2066 char *icontact, *p;
2067 icontact = sofia_glue_get_url_from_contact(contact_str, 1);
2068 if ((p = strchr(icontact, ';'))) {
2069 *p = '\0';
2070 }
2071 if ((p = strchr(icontact + 4, ':'))) {
2072 *p = '\0';
2073 }
2074
2075 if (multi_reg_contact) {
2076 sql =
2077 switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
2078 } else {
2079 sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
2080 }
2081
2082 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
2083
2084 switch_safe_free(icontact);
2085 } else {
2086
2087 if ((sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host))) {
2088 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
2089 }
2090 }
2091 }
2092
2093 respond_200_ok:
2094
2095 if (regtype == REG_REGISTER) {
2096 char exp_param[128] = "";
2097 char date[80] = "";
2098 switch_event_t *s_mwi_event = NULL;
2099
2100 switch_console_callback_match_t *contact_list = NULL;
2101 tagi_t *contact_tags;
2102 switch_console_callback_match_node_t *m;
2103 int i;
2104
2105 s_event = NULL;
2106
2107 if (contact) {
2108 if (exptime) {
2109 int debounce_ok = debounce_check(profile, mwi_user, mwi_host);
2110
2111 switch_snprintf(exp_param, sizeof(exp_param), "expires=%ld", exptime);
2112 sip_contact_add_param(nua_handle_home(nh), sip->sip_contact, exp_param);
2113
2114 /* send unsolicited MWI if configured */
2115 if (send_message_query == 2 || (reg_count == 1 && send_message_query == 1 && debounce_ok)) {
2116 if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) {
2117 switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "%s:%s@%s", proto, mwi_user, mwi_host);
2118 switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name);
2119 switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Call-ID", call_id);
2120 }
2121 }
2122
2123 if ((sofia_test_pflag(profile, PFLAG_PRESENCE_ON_REGISTER) ||
2124 (reg_count == 1 && sofia_test_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER))
2125 || send_pres == 1 || (reg_count == 1 && send_pres == 2)) && debounce_ok) {
2126
2127 if (sofia_test_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER)) {
2128 if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
2129 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
2130 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
2131 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
2132 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host);
2133 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
2134 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register");
2135 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
2136 switch_event_fire(&s_event);
2137 }
2138 } else {
2139 if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
2140 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
2141 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
2142 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register");
2143 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
2144 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
2145 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered");
2146 switch_event_fire(&s_event);
2147 }
2148 }
2149 }
2150 } else {
2151 const char *username = "unknown";
2152 const char *realm = "unknown";
2153
2154 if (auth_params) {
2155 username = switch_event_get_header(auth_params, "sip_auth_username");
2156 realm = switch_event_get_header(auth_params, "sip_auth_realm");
2157 }
2158
2159 switch_core_del_registration(to_user, reg_host, call_id);
2160
2161 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) {
2162 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
2163 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", username);
2164 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user);
2165 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host);
2166 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str);
2167 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id);
2168 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid);
2169 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "realm", realm);
2170 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-ip", network_ip);
2171 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network-port", network_port_c);
2172 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", agent);
2173 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long) exptime);
2174
2175 if (v_event && *v_event) {
2176 switch_event_merge(s_event, *v_event);
2177 }
2178
2179 }
2180 }
2181 }
2182
2183 switch_rfc822_date(date, switch_micro_time_now());
2184
2185 /* generate and respond a 200 OK */
2186
2187 if ((profile->ndlb & PFLAG_NDLB_EXPIRES_IN_REGISTER_RESPONSE)) {
2188 switch_snprintf(expbuf, sizeof(expbuf), "%ld", exptime);
2189 }
2190
2191 if (mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup) {
2192 /* handle backwards compatibility - contacts will not be looked up but only copied from the request into the response
2193 remove this condition later if nobody complains about the extra select of the below new behavior
2194 also remove the parts in mod_sofia.h, sofia.c and sofia_reg.c that refer to reg_deny_binding_fetch_and_no_lookup */
2195 nua_respond(nh, SIP_200_OK, TAG_IF(contact, SIPTAG_CONTACT(sip->sip_contact)), TAG_IF(path_val, SIPTAG_PATH_STR(path_val)),
2196 TAG_IF(!zstr(expbuf), SIPTAG_EXPIRES_STR(expbuf)),
2197 NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_DATE_STR(date), TAG_END());
2198
2199 } else if ((contact_list = sofia_reg_find_reg_url_with_positive_expires_multi(profile, from_user, reg_host, reg_time, contact_str, exptime))) {
2200 /* all + 1 tag_i elements initialized as NULL - last one implies TAG_END() */
2201 switch_zmalloc(contact_tags, sizeof(*contact_tags) * (contact_list->count + 1));
2202 i = 0;
2203 for (m = contact_list->head; m; m = m->next) {
2204 contact_tags[i].t_tag = siptag_contact_str;
2205 contact_tags[i].t_value = (tag_value_t) m->val;
2206 ++i;
2207 }
2208
2209
2210 nua_respond(nh, SIP_200_OK, TAG_IF(path_val, SIPTAG_PATH_STR(path_val)),
2211 TAG_IF(!zstr(expbuf), SIPTAG_EXPIRES_STR(expbuf)),
2212 NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_DATE_STR(date), TAG_NEXT(contact_tags));
2213
2214 switch_safe_free(contact_tags);
2215 switch_console_free_matches(&contact_list);
2216
2217 } else {
2218 /* respond without any contacts */
2219 nua_respond(nh, SIP_200_OK, TAG_IF(path_val, SIPTAG_PATH_STR(path_val)),
2220 TAG_IF(!zstr(expbuf), SIPTAG_EXPIRES_STR(expbuf)),
2221 NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_DATE_STR(date), TAG_END());
2222 }
2223
2224
2225 if (s_event) {
2226 switch_event_fire(&s_event);
2227 }
2228
2229 if (s_mwi_event) {
2230 switch_event_fire(&s_mwi_event);
2231 }
2232
2233 switch_goto_int(r, 1, end);
2234 }
2235
2236
2237 end:
2238 switch_safe_free(display_m);
2239 switch_safe_free(dup_mwi_account);
2240 switch_safe_free(utmp);
2241 su_free(nua_handle_home(nh), path_val);
2242 switch_safe_free(token_val);
2243
2244 if (auth_params) {
2245 switch_event_destroy(&auth_params);
2246 }
2247
2248 return (uint8_t) r;
2249 }
2250
2251
2252
sofia_reg_handle_sip_i_register(nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t ** sofia_private_p,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])2253 void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t **sofia_private_p, sip_t const *sip,
2254 sofia_dispatch_event_t *de,
2255 tagi_t tags[])
2256 {
2257 char key[128] = "";
2258 switch_event_t *v_event = NULL;
2259 char network_ip[80];
2260 sofia_regtype_t type = REG_REGISTER;
2261 int network_port = 0;
2262 char *is_nat = NULL;
2263 const char *acl_token = NULL;
2264
2265
2266 #if 0 /* This seems to cause undesirable effects so nevermind */
2267 if (sip->sip_to && sip->sip_to->a_url && sip->sip_to->a_url->url_host) {
2268 const char *to_host = sip->sip_to->a_url->url_host;
2269 if (profile->reg_db_domain) {
2270 if (!sofia_glue_profile_exists(to_host)) {
2271 if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) {
2272 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name);
2273 }
2274 }
2275 }
2276 }
2277 #endif
2278
2279 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
2280
2281 /* backwards compatibility */
2282 if (mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup && !sip->sip_contact) {
2283 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO CONTACT! ip: %s, port: %i\n", network_ip, network_port);
2284 nua_respond(nh, 400, "Missing Contact Header", TAG_END());
2285 goto end;
2286 }
2287
2288 if (!(profile->mflags & MFLAG_REGISTER)) {
2289 nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
2290 goto end;
2291 }
2292
2293 if (sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION)) {
2294 if (sip && sip->sip_via) {
2295 const char *port = sip->sip_via->v_port;
2296 const char *host = sip->sip_via->v_host;
2297
2298 if (host && sip->sip_via->v_received) {
2299 is_nat = "via received";
2300 } else if (host && strcmp(network_ip, host)) {
2301 is_nat = "via host";
2302 } else if (port && atoi(port) != network_port) {
2303 is_nat = "via port";
2304 }
2305
2306 if (!is_nat && sip->sip_via->v_port &&
2307 atoi(sip->sip_via->v_port) == 5060 && network_port != 5060 ) {
2308 is_nat = "via port";
2309 }
2310 }
2311 }
2312
2313 if (!is_nat && profile->nat_acl_count) {
2314 uint32_t x = 0;
2315 int ok = 1;
2316 char *last_acl = NULL;
2317 const char *contact_host = NULL;
2318
2319 if (sip && sip->sip_contact) {
2320 contact_host = sip->sip_contact->m_url->url_host;
2321 }
2322
2323 if (!zstr(contact_host)) {
2324 for (x = 0; x < profile->nat_acl_count; x++) {
2325 last_acl = profile->nat_acl[x];
2326 if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) {
2327 break;
2328 }
2329 }
2330
2331 if (ok) {
2332 is_nat = last_acl;
2333 }
2334 }
2335 }
2336
2337 if (profile->reg_acl_count) {
2338 uint32_t x = 0;
2339 int ok = 1;
2340 char *last_acl = NULL;
2341 const char *token_sw = NULL;
2342
2343 for (x = 0; x < profile->reg_acl_count; x++) {
2344 last_acl = profile->reg_acl[x];
2345 if (!(ok = switch_check_network_list_ip_token(network_ip, last_acl, &token_sw))) {
2346 break;
2347 }
2348 }
2349
2350 if (ok && !sofia_test_pflag(profile, PFLAG_BLIND_REG)) {
2351 type = REG_AUTO_REGISTER;
2352 acl_token = token_sw;
2353 } else if (!ok) {
2354 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by register acl \"%s\"\n", network_ip, profile->reg_acl[x]);
2355 nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
2356 goto end;
2357 }
2358 }
2359
2360 if (!sip || !sip->sip_request || !sip->sip_request->rq_method_name) {
2361 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received an invalid packet!\n");
2362 nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
2363 goto end;
2364 }
2365
2366 if (is_nat && profile->local_network && switch_check_network_list_ip(network_ip, profile->local_network)) {
2367 if (profile->debug) {
2368 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s is on local network, not seting NAT mode.\n", network_ip);
2369 }
2370 is_nat = NULL;
2371 }
2372
2373 sofia_reg_handle_register_token(nua, profile, nh, sip, de, type, key, sizeof(key), &v_event, is_nat, sofia_private_p, NULL, acl_token);
2374
2375 if (v_event) {
2376 switch_event_destroy(&v_event);
2377 }
2378
2379 end:
2380
2381 if (!sofia_private_p || !*sofia_private_p) nua_handle_destroy(nh);
2382
2383 }
2384
2385
sofia_reg_handle_sip_r_register(int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])2386 void sofia_reg_handle_sip_r_register(int status,
2387 char const *phrase,
2388 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
2389 sofia_dispatch_event_t *de,
2390 tagi_t tags[])
2391 {
2392 sofia_gateway_t *gateway = NULL;
2393
2394
2395 if (!sofia_private) {
2396 nua_handle_destroy(nh);
2397 return;
2398 }
2399
2400 if (!zstr(sofia_private->gateway_name)) {
2401 gateway = sofia_reg_find_gateway(sofia_private->gateway_name);
2402 }
2403
2404 if (gateway) {
2405 reg_state_t ostate = gateway->state;
2406 char oregister_network_ip[80] = { 0 };
2407 char network_ip[80] = { 0 };
2408
2409 if (de && de->data && de->data->e_msg) {
2410 if (!zstr_buf(gateway->register_network_ip)) {
2411 snprintf(oregister_network_ip, sizeof(oregister_network_ip), "%s", gateway->register_network_ip);
2412 }
2413 sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &gateway->register_network_port);
2414 if (!zstr_buf(network_ip)) {
2415 snprintf(gateway->register_network_ip, sizeof(gateway->register_network_ip), (msg_addrinfo(de->data->e_msg))->ai_addr->sa_family == AF_INET6 ? "[%s]" : "%s", network_ip);
2416 }
2417 }
2418
2419 switch (status) {
2420 case 200:
2421 if (sip && sip->sip_contact) {
2422 sip_contact_t *contact = sip->sip_contact;
2423 const char *new_expires;
2424 uint32_t expi;
2425 if (contact->m_next) {
2426 char *full;
2427
2428 for (; contact; contact = contact->m_next) {
2429 if ((full = sip_header_as_string(nh->nh_home, (void *) contact))) {
2430 if (switch_stristr(gateway->register_contact, full)) {
2431 break;
2432 }
2433
2434 su_free(nh->nh_home, full);
2435 }
2436 }
2437 }
2438
2439 if (!contact) {
2440 contact = sip->sip_contact;
2441 }
2442
2443 if (contact->m_expires) {
2444 new_expires = contact->m_expires;
2445 expi = (uint32_t) atoi(new_expires);
2446
2447 if (expi > 0 && expi != gateway->freq) {
2448 //gateway->freq = expi;
2449 //gateway->expires_str = switch_core_sprintf(gateway->pool, "%d", expi);
2450
2451 if (expi > 60) {
2452 gateway->expires = switch_epoch_time_now(NULL) + (expi - 15);
2453 } else {
2454 gateway->expires = switch_epoch_time_now(NULL) + (expi - 2);
2455 }
2456
2457
2458 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
2459 "Changing expire time to %d by request of proxy %s\n", expi, gateway->register_proxy);
2460 }
2461 }
2462 }
2463 gateway->state = REG_STATE_REGISTER;
2464 break;
2465 case 100:
2466 break;
2467 default:
2468 gateway->state = REG_STATE_FAILED;
2469 gateway->failure_status = status;
2470 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s Failed Registration with status %s [%d]. failure #%d\n",
2471 gateway->name, switch_str_nil(phrase), status, ++gateway->failures);
2472 break;
2473 }
2474 if (ostate != gateway->state ||
2475 (!zstr_buf(gateway->register_network_ip) &&
2476 (zstr_buf(oregister_network_ip) || strcmp(oregister_network_ip, gateway->register_network_ip)))) {
2477 sofia_reg_fire_custom_gateway_state_event(gateway, status, phrase);
2478 }
2479 }
2480
2481 if (gateway) {
2482 sofia_reg_release_gateway(gateway);
2483 }
2484
2485 }
2486
sofia_reg_handle_sip_r_challenge(int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,switch_core_session_t * session,sofia_gateway_t * gateway,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])2487 void sofia_reg_handle_sip_r_challenge(int status,
2488 char const *phrase,
2489 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private,
2490 switch_core_session_t *session, sofia_gateway_t *gateway, sip_t const *sip,
2491 sofia_dispatch_event_t *de, tagi_t tags[])
2492 {
2493 sip_www_authenticate_t const *authenticate = NULL;
2494 char const *realm = NULL;
2495 char const *scheme = NULL;
2496 int indexnum;
2497 char *cur;
2498 char authentication[256] = "";
2499 int ss_state;
2500 sofia_gateway_t *var_gateway = NULL;
2501 const char *gw_name = NULL;
2502 switch_channel_t *channel = NULL;
2503 const char *sip_auth_username = NULL;
2504 const char *sip_auth_password = NULL;
2505 char *dup_user = NULL;
2506 char *dup_pass = NULL;
2507
2508 if (session && (channel = switch_core_session_get_channel(session))) {
2509 sip_auth_username = switch_channel_get_variable(channel, "sip_auth_username");
2510 sip_auth_password = switch_channel_get_variable(channel, "sip_auth_password");
2511 }
2512
2513 if (sofia_private) {
2514 if (*sofia_private->auth_gateway_name) {
2515 gw_name = sofia_private->auth_gateway_name;
2516 } else if (*sofia_private->gateway_name) {
2517 gw_name = sofia_private->gateway_name;
2518 }
2519 }
2520
2521 if (session) {
2522 private_object_t *tech_pvt;
2523
2524 if ((tech_pvt = switch_core_session_get_private(session)) && sofia_test_flag(tech_pvt, TFLAG_REFER)) {
2525 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Received reply from REFER\n");
2526 goto end;
2527 }
2528
2529 gw_name = switch_channel_get_variable(switch_core_session_get_channel(session), "sip_use_gateway");
2530 }
2531
2532
2533 if (sip->sip_www_authenticate) {
2534 authenticate = sip->sip_www_authenticate;
2535 } else if (sip->sip_proxy_authenticate) {
2536 authenticate = sip->sip_proxy_authenticate;
2537 } else {
2538 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Missing Authenticate Header!\n");
2539 goto end;
2540 }
2541
2542
2543 scheme = (char const *) authenticate->au_scheme;
2544
2545 if (zstr(scheme)) {
2546 scheme = "Digest";
2547 }
2548
2549 if (authenticate->au_params) {
2550 for (indexnum = 0; (cur = (char *) authenticate->au_params[indexnum]); indexnum++) {
2551 if ((realm = strstr(cur, "realm="))) {
2552 realm += 6;
2553 break;
2554 }
2555 }
2556
2557 if (zstr(realm)) {
2558 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Realm: [%s] is invalid\n", switch_str_nil(realm));
2559
2560 for (indexnum = 0; (cur = (char *) authenticate->au_params[indexnum]); indexnum++) {
2561 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "DUMP: [%s]\n", cur);
2562 }
2563 goto end;
2564 }
2565 } else {
2566 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "NO AUTHENTICATE PARAMS\n");
2567 goto end;
2568 }
2569
2570 if (!gateway) {
2571 if (gw_name) {
2572 var_gateway = sofia_reg_find_gateway((char *) gw_name);
2573 }
2574
2575
2576 if (!var_gateway && realm) {
2577 char rb[512] = "";
2578 char *p = (char *) realm;
2579 while (*p == '"') {
2580 p++;
2581 }
2582 switch_set_string(rb, p);
2583 if ((p = strchr(rb, '"'))) {
2584 *p = '\0';
2585 }
2586 if (!(var_gateway = sofia_reg_find_gateway(rb))) {
2587 var_gateway = sofia_reg_find_gateway_by_realm(rb);
2588 }
2589 }
2590
2591 if (!var_gateway && sip && sip->sip_to) {
2592 var_gateway = sofia_reg_find_gateway(sip->sip_to->a_url->url_host);
2593 }
2594
2595 if (var_gateway) {
2596 gateway = var_gateway;
2597 }
2598 }
2599
2600 if (!gateway && !sip_auth_username && sip && sip->sip_to && sip->sip_to->a_url->url_user && sip->sip_to->a_url->url_host) {
2601 switch_xml_t x_user, x_param, x_params;
2602 switch_event_t *locate_params;
2603
2604 switch_event_create(&locate_params, SWITCH_EVENT_REQUEST_PARAMS);
2605 switch_assert(locate_params);
2606
2607 switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "action", "reverse-auth-lookup");
2608
2609 if ( sip->sip_call_id ) {
2610 switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "sip_call_id", sip->sip_call_id->i_id);
2611 }
2612
2613 if (switch_xml_locate_user_merged("id", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, NULL,
2614 &x_user, locate_params) == SWITCH_STATUS_SUCCESS) {
2615 if ((x_params = switch_xml_child(x_user, "params"))) {
2616 for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
2617 const char *var = switch_xml_attr_soft(x_param, "name");
2618 const char *val = switch_xml_attr_soft(x_param, "value");
2619
2620 if (!strcasecmp(var, "reverse-auth-user")) {
2621 dup_user = strdup(val);
2622 sip_auth_username = dup_user;
2623 } else if (!strcasecmp(var, "reverse-auth-pass")) {
2624 dup_pass = strdup(val);
2625 sip_auth_password = dup_pass;
2626 }
2627 }
2628 }
2629 switch_xml_free(x_user);
2630 }
2631
2632 switch_event_destroy(&locate_params);
2633 }
2634
2635 if (sip_auth_username && sip_auth_password) {
2636 switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, sip_auth_username, sip_auth_password);
2637 } else if (gateway) {
2638 switch_snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, realm, gateway->auth_username, gateway->register_password);
2639 } else {
2640 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
2641 "Cannot locate any authentication credentials to complete an authentication request for realm '%s'\n", realm);
2642 goto cancel;
2643 }
2644
2645 if (profile->debug) {
2646 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Authenticating '%s' with '%s'.\n",
2647 (sip_auth_username && sip_auth_password) ? sip_auth_username : gateway->auth_username, authentication);
2648 }
2649
2650 ss_state = nua_callstate_authenticating;
2651
2652 tl_gets(tags, NUTAG_CALLSTATE_REF(ss_state), SIPTAG_WWW_AUTHENTICATE_REF(authenticate), TAG_END());
2653
2654 nua_authenticate(nh,
2655 TAG_IF(sofia_private && !zstr(sofia_private->gateway_name), SIPTAG_EXPIRES_STR(gateway ? gateway->expires_str : "3600")),
2656 NUTAG_AUTH(authentication), TAG_END());
2657
2658 goto end;
2659
2660 cancel:
2661
2662 if (session) {
2663 switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_MANDATORY_IE_MISSING);
2664 } else {
2665 nua_cancel(nh, SIPTAG_CONTACT(SIP_NONE), TAG_END());
2666 }
2667
2668 end:
2669
2670
2671 switch_safe_free(dup_user);
2672 switch_safe_free(dup_pass);
2673
2674 if (var_gateway) {
2675 sofia_reg_release_gateway(var_gateway);
2676 }
2677
2678 return;
2679
2680
2681
2682 }
2683
2684 typedef struct {
2685 char *nonce;
2686 switch_size_t nplen;
2687 int last_nc;
2688 } nonce_cb_t;
2689
sofia_reg_nonce_callback(void * pArg,int argc,char ** argv,char ** columnNames)2690 static int sofia_reg_nonce_callback(void *pArg, int argc, char **argv, char **columnNames)
2691 {
2692 nonce_cb_t *cb = (nonce_cb_t *) pArg;
2693 switch_copy_string(cb->nonce, argv[0], cb->nplen);
2694 if (argc == 2) {
2695 cb->last_nc = zstr(argv[1]) ? 0 : atoi(argv[1]);
2696 } else {
2697 cb->last_nc = 0;
2698 }
2699 return 0;
2700 }
2701
sofia_reg_regcount_callback(void * pArg,int argc,char ** argv,char ** columnNames)2702 static int sofia_reg_regcount_callback(void *pArg, int argc, char **argv, char **columnNames)
2703 {
2704 int *ret = (int *) pArg;
2705 if (argc == 1) {
2706 *ret = atoi(argv[0]);
2707 }
2708 return 0;
2709 }
2710
sofia_reg_parse_auth(sofia_profile_t * profile,sip_authorization_t const * authorization,sip_t const * sip,sofia_dispatch_event_t * de,const char * regstr,char * np,size_t nplen,char * ip,int network_port,switch_event_t ** v_event,long exptime,sofia_regtype_t regtype,const char * to_user,switch_event_t ** auth_params,long * reg_count,switch_xml_t * user_xml)2711 auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
2712 sip_authorization_t const *authorization,
2713 sip_t const *sip,
2714 sofia_dispatch_event_t *de,
2715 const char *regstr,
2716 char *np,
2717 size_t nplen,
2718 char *ip,
2719 int network_port,
2720 switch_event_t **v_event,
2721 long exptime, sofia_regtype_t regtype, const char *to_user, switch_event_t **auth_params, long *reg_count, switch_xml_t *user_xml)
2722 {
2723 int indexnum;
2724 const char *cur;
2725 char uridigest[SWITCH_MD5_DIGEST_STRING_SIZE];
2726 char bigdigest[SWITCH_MD5_DIGEST_STRING_SIZE];
2727 char *username, *realm, *nonce, *uri, *qop, *cnonce, *nc, *response, *input = NULL, *input2 = NULL;
2728 auth_res_t ret = AUTH_FORBIDDEN;
2729 int first = 0;
2730 const char *passwd = NULL;
2731 const char *a1_hash = NULL;
2732 const char *mwi_account = NULL;
2733 switch_bool_t allow_empty_password = SWITCH_TRUE;
2734 const char *call_id = NULL;
2735 char *sql;
2736 char *number_alias = NULL;
2737 switch_xml_t user = NULL, param, uparams;
2738 char hexdigest[SWITCH_MD5_DIGEST_STRING_SIZE] = "";
2739 char *domain_name = NULL;
2740 switch_event_t *params = NULL;
2741 const char *auth_acl = NULL;
2742 long ncl = 0;
2743 sip_unknown_t *un;
2744 const char *user_agent = NULL;
2745 const char *user_agent_filter = profile->user_agent_filter;
2746 uint32_t max_registrations_perext = profile->max_registrations_perext;
2747 char client_port[16];
2748 snprintf(client_port, 15, "%d", network_port);
2749
2750 username = realm = nonce = uri = qop = cnonce = nc = response = NULL;
2751
2752 if (authorization->au_params) {
2753 for (indexnum = 0; (cur = authorization->au_params[indexnum]); indexnum++) {
2754 char *var, *val, *p, *work;
2755 var = val = work = NULL;
2756 if ((work = strdup(cur))) {
2757 var = work;
2758 if ((val = strchr(var, '='))) {
2759 *val++ = '\0';
2760 while (*val == '"') {
2761 *val++ = '\0';
2762 }
2763 if ((p = strchr(val, '"'))) {
2764 *p = '\0';
2765 }
2766
2767 if (!strcasecmp(var, "username") && !username) {
2768 username = strdup(val);
2769 } else if (!strcasecmp(var, "realm") && !realm) {
2770 realm = strdup(val);
2771 } else if (!strcasecmp(var, "nonce") && !nonce) {
2772 nonce = strdup(val);
2773 } else if (!strcasecmp(var, "uri") && !uri) {
2774 uri = strdup(val);
2775 } else if (!strcasecmp(var, "qop") && !qop) {
2776 qop = strdup(val);
2777 } else if (!strcasecmp(var, "cnonce") && !cnonce) {
2778 cnonce = strdup(val);
2779 } else if (!strcasecmp(var, "response") && !response) {
2780 response = strdup(val);
2781 } else if (!strcasecmp(var, "nc") && !nc) {
2782 nc = strdup(val);
2783 }
2784 }
2785
2786 free(work);
2787 }
2788 }
2789 }
2790
2791 if (!(username && realm && nonce && uri && response)) {
2792 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Authorization header!\n");
2793 ret = AUTH_STALE;
2794 goto end;
2795 }
2796
2797 /* Optional check that auth name == SIP username */
2798 if ((regtype == REG_REGISTER) && sofia_test_pflag(profile, PFLAG_CHECKUSER)) {
2799 if (zstr(username) || zstr(to_user) || strcasecmp(to_user, username)) {
2800 /* Names don't match, so fail */
2801 if (profile->debug) {
2802 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SIP username %s does not match auth username\n", switch_str_nil(to_user));
2803 }
2804 goto end;
2805 }
2806 }
2807
2808 user_agent = (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown";
2809
2810 if (zstr(np)) {
2811 nonce_cb_t cb = { 0 };
2812 long nc_long = 0;
2813
2814 first = 1;
2815
2816 if (nc) {
2817 nc_long = strtoul(nc, 0, 16);
2818 sql = switch_mprintf("select nonce,last_nc from sip_authentication where nonce='%q' and last_nc < %lu", nonce, nc_long);
2819 } else {
2820 sql = switch_mprintf("select nonce from sip_authentication where nonce='%q'", nonce);
2821 }
2822
2823 cb.nonce = np;
2824 cb.nplen = nplen;
2825
2826 switch_assert(sql != NULL);
2827
2828 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sofia_reg_nonce_callback, &cb);
2829 free(sql);
2830
2831 //if (!sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, np, nplen)) {
2832 if (zstr(np) || (profile->max_auth_validity != 0 && (uint32_t)cb.last_nc >= profile->max_auth_validity )) {
2833 sql = switch_mprintf("delete from sip_authentication where nonce='%q'", nonce);
2834 sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
2835 ret = AUTH_STALE;
2836 goto end;
2837 }
2838
2839 if (reg_count) {
2840 *reg_count = cb.last_nc + 1;
2841 }
2842 }
2843
2844 switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
2845 switch_assert(params);
2846 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "sip_auth");
2847 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_profile", profile->name);
2848 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_user_agent", user_agent);
2849 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_username", username);
2850 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_realm", realm);
2851 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_nonce", nonce);
2852 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_uri", uri);
2853
2854 if (sip->sip_contact) {
2855 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_contact_user", sip->sip_contact->m_url->url_user);
2856 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_contact_host", sip->sip_contact->m_url->url_host);
2857 }
2858
2859 if (sip->sip_to) {
2860 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_to_user", sip->sip_to->a_url->url_user);
2861 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_to_host", sip->sip_to->a_url->url_host);
2862 if (sip->sip_to->a_url->url_port) {
2863 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_to_port", sip->sip_to->a_url->url_port);
2864 }
2865 }
2866
2867 if (sip->sip_via) {
2868 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_via_protocol", sofia_glue_transport2str(sofia_glue_via2transport(sip->sip_via)));
2869 }
2870
2871
2872 if (sip->sip_from) {
2873 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_from_user", sip->sip_from->a_url->url_user);
2874 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_from_host", sip->sip_from->a_url->url_host);
2875 if (sip->sip_from->a_url->url_port) {
2876 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_from_port", sip->sip_from->a_url->url_port);
2877 }
2878 }
2879
2880 if (sip->sip_call_id && sip->sip_call_id->i_id) {
2881 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_call_id", sip->sip_call_id->i_id);
2882 }
2883
2884
2885 if (sip->sip_request) {
2886 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_request_user", sip->sip_request->rq_url->url_user);
2887 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_request_host", sip->sip_request->rq_url->url_host);
2888 if (sip->sip_request->rq_url->url_port) {
2889 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_request_port", sip->sip_request->rq_url->url_port);
2890 }
2891 }
2892
2893 for (un = sip->sip_unknown; un; un = un->un_next) {
2894 if (!strncasecmp(un->un_name, "X-", 2)) {
2895 if (!zstr(un->un_value)) {
2896 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "adding %s => %s to xml_curl request\n", un->un_name, un->un_value);
2897 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, un->un_name, un->un_value);
2898 }
2899 } else {
2900 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "skipping %s => %s from xml_curl request\n", un->un_name, un->un_value);
2901 }
2902 }
2903
2904 if (qop) {
2905 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_qop", qop);
2906 }
2907 if (cnonce) {
2908 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_cnonce", cnonce);
2909 }
2910 if (nc) {
2911 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_nc", nc);
2912 }
2913 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_response", response);
2914
2915 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "sip_auth_method", (sip && sip->sip_request) ? sip->sip_request->rq_method_name : NULL);
2916
2917 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "client_port", client_port);
2918 if (auth_params) {
2919 switch_event_dup(auth_params, params);
2920 }
2921
2922
2923 if (!zstr(profile->reg_domain)) {
2924 domain_name = profile->reg_domain;
2925 } else {
2926 domain_name = realm;
2927 }
2928
2929 if (switch_xml_locate_user_merged("id", zstr(username) ? "nobody" : username, domain_name, ip, &user, params) != SWITCH_STATUS_SUCCESS) {
2930 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find user [%s@%s] from %s\n"
2931 "You must define a domain called '%s' in your directory and add a user with the id=\"%s\" attribute\n"
2932 "and you must configure your device to use the proper domain in its authentication credentials.\n", username, domain_name,
2933 ip, domain_name, username);
2934
2935 ret = AUTH_FORBIDDEN;
2936 goto end;
2937 } else {
2938 const char *type = switch_xml_attr(user, "type");
2939 if (type && !strcasecmp(type, "pointer")) {
2940 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't register a pointer.\n");
2941 ret = AUTH_FORBIDDEN;
2942 goto end;
2943 }
2944 }
2945
2946 if (!(number_alias = (char *) switch_xml_attr(user, "number-alias"))) {
2947 number_alias = zstr(username) ? "nobody" : username;
2948 }
2949
2950 if (!(uparams = switch_xml_child(user, "params"))) {
2951 ret = AUTH_OK;
2952 goto skip_auth;
2953 } else {
2954 for (param = switch_xml_child(uparams, "param"); param; param = param->next) {
2955 const char *var = switch_xml_attr_soft(param, "name");
2956 const char *val = switch_xml_attr_soft(param, "value");
2957
2958 if (!strcasecmp(var, "sip-forbid-register") && switch_true(val)) {
2959 ret = AUTH_FORBIDDEN;
2960 goto end;
2961 }
2962
2963 if (!strcasecmp(var, "password")) {
2964 passwd = val;
2965 }
2966
2967 if (!strcasecmp(var, "auth-acl")) {
2968 auth_acl = val;
2969 }
2970
2971 if (!strcasecmp(var, "a1-hash")) {
2972 a1_hash = val;
2973 }
2974 if (!strcasecmp(var, "mwi-account")) {
2975 mwi_account = val;
2976 }
2977 if (!strcasecmp(var, "allow-empty-password")) {
2978 allow_empty_password = switch_true(val);
2979 }
2980 if (!strcasecmp(var, "user-agent-filter")) {
2981 user_agent_filter = val;
2982 }
2983 if (!strcasecmp(var, "max-registrations-per-extension")) {
2984 max_registrations_perext = atoi(val);
2985 }
2986 }
2987 }
2988
2989 if (auth_acl) {
2990 if (!switch_check_network_list_ip(ip, auth_acl)) {
2991 int network_ip_is_proxy = 0;
2992 uint32_t x = 0;
2993 char *last_acl = NULL;
2994 if (profile->proxy_acl_count == 0) {
2995 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by user acl [%s] and no proxy acl present\n", ip, auth_acl);
2996 ret = AUTH_FORBIDDEN;
2997 goto end;
2998 } else {
2999 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Rejected by user acl [%s] checking proxy ACLs now\n", ip, auth_acl);
3000 }
3001 /* Check if network_ip is a proxy allowed to send us calls */
3002 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%d acls to check for proxy\n", profile->proxy_acl_count);
3003
3004 for (x = 0; x < profile->proxy_acl_count; x++) {
3005 last_acl = profile->proxy_acl[x];
3006 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "checking %s against acl %s\n", ip, last_acl);
3007 if (switch_check_network_list_ip(ip, last_acl)) {
3008 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s is a proxy according to the %s acl\n", ip, last_acl);
3009 network_ip_is_proxy = 1;
3010 break;
3011 }
3012 }
3013 /*
3014 * if network_ip is a proxy allowed to send traffic, check for auth
3015 * ip header and see if it matches against the auth acl
3016 */
3017 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "network ip is a proxy [%d]\n", network_ip_is_proxy);
3018 if (network_ip_is_proxy) {
3019 int x_auth_ip = 0;
3020 for (un = sip->sip_unknown; un; un = un->un_next) {
3021 if (!strcasecmp(un->un_name, "X-AUTH-IP")) {
3022 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found auth ip [%s] header of [%s]\n", un->un_name, un->un_value);
3023 if (!zstr(un->un_value)) {
3024 if (!switch_check_network_list_ip(un->un_value, auth_acl)) {
3025 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by user acl %s\n", un->un_value, auth_acl);
3026 ret = AUTH_FORBIDDEN;
3027 goto end;
3028 } else {
3029 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
3030 "IP %s allowed by acl %s, checking credentials\n", un->un_value, auth_acl);
3031 x_auth_ip = 1;
3032 break;
3033 }
3034 }
3035 }
3036 }
3037 if (!x_auth_ip) {
3038 ret = AUTH_FORBIDDEN;
3039 goto end;
3040 }
3041 }
3042 } else {
3043 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP [%s] passed ACL check [%s]\n", ip, auth_acl);
3044 }
3045 }
3046
3047 if (!allow_empty_password && zstr(passwd) && zstr(a1_hash)) {
3048 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Empty password denied for user %s@%s\n", username, domain_name);
3049 ret = AUTH_FORBIDDEN;
3050 goto end;
3051 }
3052
3053 if (zstr(passwd) && zstr(a1_hash)) {
3054 ret = AUTH_OK;
3055 goto skip_auth;
3056 }
3057
3058 if (!a1_hash) {
3059 input = switch_mprintf("%s:%s:%s", username, realm, passwd);
3060 switch_md5_string(hexdigest, (void *) input, strlen(input));
3061 switch_safe_free(input);
3062 a1_hash = hexdigest;
3063
3064 }
3065
3066 if (user_agent_filter) {
3067 if (switch_regex_match(user_agent, user_agent_filter) == SWITCH_STATUS_SUCCESS) {
3068 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
3069 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
3070 "SIP auth OK (REGISTER) due to user-agent-filter. Filter \"%s\" User-Agent \"%s\"\n", user_agent_filter, user_agent);
3071 }
3072 } else {
3073 ret = AUTH_FORBIDDEN;
3074 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
3075 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
3076 "SIP auth failure (REGISTER) due to user-agent-filter. Filter \"%s\" User-Agent \"%s\"\n", user_agent_filter,
3077 user_agent);
3078 }
3079 goto end;
3080 }
3081 }
3082
3083 /* The max-registrations-per-extension-option only affects REGISTER-authentications */
3084 if ((REG_REGISTER == regtype || REG_AUTO_REGISTER == regtype) && max_registrations_perext > 0 && (sip && sip->sip_contact && (sip->sip_contact->m_expires == NULL || atol(sip->sip_contact->m_expires) > 0))) {
3085 /* if expires is null still process */
3086 /* expires == 0 means the phone is going to unregiser, so don't count against max */
3087 uint32_t count = 0;
3088
3089 call_id = sip->sip_call_id->i_id;
3090 switch_assert(call_id);
3091
3092 sql = switch_mprintf("select count(sip_user) from sip_registrations where sip_user='%q' AND call_id <> '%q' AND sip_host='%q'",
3093 sip->sip_to->a_url->url_user, call_id, domain_name);
3094 switch_assert(sql != NULL);
3095 sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_regcount_callback, &count);
3096 free(sql);
3097
3098 if (count + 1 > max_registrations_perext) {
3099 ret = AUTH_FORBIDDEN;
3100 if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
3101 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
3102 "SIP auth failure (REGISTER) due to reaching max allowed registrations. Count: %d\n", count);
3103 }
3104 goto end;
3105 }
3106 }
3107
3108 for_the_sake_of_interop:
3109
3110 if ((input = switch_mprintf("%s:%q", regstr, uri))) {
3111 switch_md5_string(uridigest, (void *) input, strlen(input));
3112 }
3113
3114 if (nc && cnonce && qop) {
3115 input2 = switch_mprintf("%s:%s:%s:%s:%s:%s", a1_hash, nonce, nc, cnonce, qop, uridigest);
3116 } else {
3117 input2 = switch_mprintf("%s:%s:%s", a1_hash, nonce, uridigest);
3118 }
3119
3120 if (input2) {
3121 switch_md5_string(bigdigest, (void *) input2, strlen(input2));
3122 }
3123
3124 if (input2 && !strcasecmp(bigdigest, response)) {
3125 ret = AUTH_OK;
3126 } else {
3127 if ((profile->ndlb & PFLAG_NDLB_BROKEN_AUTH_HASH) && strcasecmp(regstr, "REGISTER") && strcasecmp(regstr, "INVITE")) {
3128 /* some clients send an ACK with the method 'INVITE' in the hash which will break auth so we will
3129 try again with INVITE so we don't get people complaining to us when someone else's client has a bug......
3130 */
3131 switch_safe_free(input);
3132 switch_safe_free(input2);
3133 regstr = "INVITE";
3134 goto for_the_sake_of_interop;
3135 }
3136
3137 ret = AUTH_FORBIDDEN;
3138 }
3139
3140 switch_safe_free(input2);
3141
3142 skip_auth:
3143 if (first && (ret == AUTH_OK || ret == AUTH_RENEWED)) {
3144 if (v_event && !*v_event) {
3145 switch_event_create_plain(v_event, SWITCH_EVENT_REQUEST_PARAMS);
3146 }
3147
3148
3149 if (v_event && *v_event) {
3150 short int xparams_type[6];
3151 switch_xml_t xparams[6];
3152 int i = 0;
3153
3154 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "sip_number_alias", number_alias);
3155 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "sip_auth_username", username);
3156 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "sip_auth_realm", realm);
3157 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "number_alias", number_alias);
3158 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "user_name", username);
3159 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "domain_name", domain_name);
3160
3161 if (mwi_account) {
3162 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, "mwi-account", mwi_account);
3163 }
3164
3165 if ((uparams = switch_xml_child(user, "params"))) {
3166 xparams_type[i] = 0;
3167 xparams[i++] = uparams;
3168 }
3169
3170 if ((uparams = switch_xml_child(user, "variables"))) {
3171 xparams_type[i] = 1;
3172 xparams[i++] = uparams;
3173 }
3174
3175 if (i <= 6) {
3176 int j = 0;
3177 const char *gw_val = NULL;
3178
3179 for (j = 0; j < i; j++) {
3180 for (param = switch_xml_child(xparams[j], (xparams_type[j] ? "variable" : "param")); param; param = param->next) {
3181 const char *var = switch_xml_attr_soft(param, "name");
3182 const char *val = switch_xml_attr_soft(param, "value");
3183
3184 if (!zstr(var) && !zstr(val) && (xparams_type[j] == 1 || !strncasecmp(var, "sip-", 4) || !strcasecmp(var, "register-gateway"))) {
3185 if (profile->debug) {
3186 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "event_add_header -> '%s' = '%s'\n", var, val);
3187 }
3188 switch_event_add_header_string(*v_event, SWITCH_STACK_BOTTOM, var, val);
3189 }
3190 }
3191 }
3192 if ((gw_val = switch_event_get_header(*v_event, "register-gateway"))) {
3193 sofia_gateway_t *gateway_ptr = NULL;
3194 if (!strcasecmp(gw_val, "all")) {
3195 switch_xml_t gateways_tag, gateway_tag;
3196 if ((gateways_tag = switch_xml_child(user, "gateways"))) {
3197 for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
3198 char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
3199 if (zstr(name)) {
3200 name = "anonymous";
3201 }
3202
3203 if ((gateway_ptr = sofia_reg_find_gateway(name))) {
3204 reg_state_t ostate = gateway_ptr->state;
3205 gateway_ptr->retry = 0;
3206 if (exptime) {
3207 gateway_ptr->state = REG_STATE_UNREGED;
3208 } else {
3209 gateway_ptr->state = REG_STATE_UNREGISTER;
3210 }
3211 if (ostate != gateway_ptr->state) {
3212 sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
3213 }
3214 sofia_reg_release_gateway(gateway_ptr);
3215 }
3216
3217 }
3218 }
3219 } else {
3220 int x, argc;
3221 char *mydata, *argv[50];
3222
3223 mydata = strdup(gw_val);
3224 switch_assert(mydata != NULL);
3225
3226 argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
3227
3228 for (x = 0; x < argc; x++) {
3229 if ((gateway_ptr = sofia_reg_find_gateway((char *) argv[x]))) {
3230 reg_state_t ostate = gateway_ptr->state;
3231 gateway_ptr->retry = 0;
3232 if (exptime) {
3233 gateway_ptr->state = REG_STATE_UNREGED;
3234 } else {
3235 gateway_ptr->state = REG_STATE_UNREGISTER;
3236 }
3237 if (ostate != gateway_ptr->state) {
3238 sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
3239 }
3240 sofia_reg_release_gateway(gateway_ptr);
3241 } else {
3242 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Gateway '%s' not found.\n", argv[x]);
3243 }
3244 }
3245
3246 free(mydata);
3247 }
3248 }
3249 }
3250 }
3251 }
3252 end:
3253
3254
3255 if (nc && cnonce && qop) {
3256 ncl = strtoul(nc, 0, 16);
3257
3258 sql = switch_mprintf("update sip_authentication set expires='%ld',last_nc=%lu where nonce='%q'",
3259 (long)switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL) + exptime, ncl, nonce);
3260
3261 switch_assert(sql != NULL);
3262 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
3263
3264 if (ret == AUTH_OK)
3265 ret = AUTH_RENEWED;
3266 }
3267
3268 switch_event_destroy(¶ms);
3269
3270 if (user) {
3271 if (user_xml) {
3272 *user_xml = user;
3273 } else {
3274 switch_xml_free(user);
3275 }
3276 }
3277
3278 switch_safe_free(input);
3279 switch_safe_free(username);
3280 switch_safe_free(realm);
3281 switch_safe_free(nonce);
3282 switch_safe_free(uri);
3283 switch_safe_free(qop);
3284 switch_safe_free(cnonce);
3285 switch_safe_free(nc);
3286 switch_safe_free(response);
3287
3288 if (reg_count && !*reg_count) {
3289 if ((ret == AUTH_OK || ret == AUTH_RENEWED)) {
3290 if (ncl) {
3291 *reg_count = ncl;
3292 } else {
3293 *reg_count = 1;
3294 }
3295 } else {
3296 *reg_count = 0;
3297 }
3298 }
3299
3300 return ret;
3301
3302 }
3303
3304
sofia_reg_find_gateway__(const char * file,const char * func,int line,const char * key)3305 sofia_gateway_t *sofia_reg_find_gateway__(const char *file, const char *func, int line, const char *key)
3306 {
3307 sofia_gateway_t *gateway = NULL;
3308
3309 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3310 if ((gateway = (sofia_gateway_t *) switch_core_hash_find(mod_sofia_globals.gateway_hash, key))) {
3311 if (!sofia_test_pflag(gateway->profile, PFLAG_RUNNING) || gateway->deleted) {
3312 gateway = NULL;
3313 goto done;
3314 }
3315 if (sofia_reg_gateway_rdlock__(file, func, line, gateway) != SWITCH_STATUS_SUCCESS) {
3316 gateway = NULL;
3317 }
3318 }
3319
3320 done:
3321 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3322 return gateway;
3323 }
3324
3325
sofia_reg_find_gateway_by_realm__(const char * file,const char * func,int line,const char * key)3326 sofia_gateway_t *sofia_reg_find_gateway_by_realm__(const char *file, const char *func, int line, const char *key)
3327 {
3328 sofia_gateway_t *gateway = NULL;
3329 switch_hash_index_t *hi;
3330 const void *var;
3331 void *val;
3332
3333 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3334 for (hi = switch_core_hash_first(mod_sofia_globals.gateway_hash); hi; hi = switch_core_hash_next(&hi)) {
3335 switch_core_hash_this(hi, &var, NULL, &val);
3336 if (key && (gateway = (sofia_gateway_t *) val) && !gateway->deleted && gateway->register_realm && !strcasecmp(gateway->register_realm, key)) {
3337 break;
3338 } else {
3339 gateway = NULL;
3340 }
3341 }
3342 switch_safe_free(hi);
3343
3344 if (gateway) {
3345 if (!sofia_test_pflag(gateway->profile, PFLAG_RUNNING) || gateway->deleted) {
3346 gateway = NULL;
3347 goto done;
3348 }
3349 if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) {
3350 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is locked\n", gateway->profile->name);
3351 gateway = NULL;
3352 }
3353 }
3354 if (gateway) {
3355 #ifdef SOFIA_DEBUG_RWLOCKS
3356 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX GW LOCK %s\n", gateway->profile->name);
3357 #endif
3358 }
3359
3360 done:
3361 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3362 return gateway;
3363 }
3364
sofia_reg_gateway_rdlock__(const char * file,const char * func,int line,sofia_gateway_t * gateway)3365 switch_status_t sofia_reg_gateway_rdlock__(const char *file, const char *func, int line, sofia_gateway_t *gateway)
3366 {
3367 switch_status_t status = sofia_glue_profile_rdlock__(file, func, line, gateway->profile);
3368
3369 #ifdef SOFIA_DEBUG_RWLOCKS
3370 if (status == SWITCH_STATUS_SUCCESS) {
3371 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX GW LOCK %s\n", gateway->profile->name);
3372 }
3373 #endif
3374
3375 return status;
3376 }
3377
3378
sofia_reg_release_gateway__(const char * file,const char * func,int line,sofia_gateway_t * gateway)3379 void sofia_reg_release_gateway__(const char *file, const char *func, int line, sofia_gateway_t *gateway)
3380 {
3381 switch_thread_rwlock_unlock(gateway->profile->rwlock);
3382 #ifdef SOFIA_DEBUG_RWLOCKS
3383 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX GW UNLOCK %s\n", gateway->profile->name);
3384 #endif
3385 }
3386
sofia_reg_add_gateway(sofia_profile_t * profile,const char * key,sofia_gateway_t * gateway)3387 switch_status_t sofia_reg_add_gateway(sofia_profile_t *profile, const char *key, sofia_gateway_t *gateway)
3388 {
3389 switch_status_t status = SWITCH_STATUS_FALSE;
3390 char *pkey = switch_mprintf("%s::%s", profile->name, key);
3391 sofia_gateway_t *gp;
3392
3393 switch_mutex_lock(profile->gw_mutex);
3394
3395 gateway->next = profile->gateways;
3396 profile->gateways = gateway;
3397
3398 switch_mutex_unlock(profile->gw_mutex);
3399
3400 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3401
3402 if ((gp = switch_core_hash_find(mod_sofia_globals.gateway_hash, key))) {
3403 if (gp->deleted) {
3404 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing deleted gateway from hash.\n");
3405 switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->name);
3406 switch_core_hash_delete(mod_sofia_globals.gateway_hash, pkey);
3407 switch_core_hash_delete(mod_sofia_globals.gateway_hash, key);
3408 }
3409 }
3410
3411 if (!switch_core_hash_find(mod_sofia_globals.gateway_hash, key) && !switch_core_hash_find(mod_sofia_globals.gateway_hash, pkey)) {
3412 status = switch_core_hash_insert(mod_sofia_globals.gateway_hash, key, gateway);
3413 status |= switch_core_hash_insert(mod_sofia_globals.gateway_hash, pkey, gateway);
3414 if (status != SWITCH_STATUS_SUCCESS) {
3415 status = SWITCH_STATUS_FALSE;
3416 }
3417 } else {
3418 status = SWITCH_STATUS_FALSE;
3419 }
3420 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3421
3422 free(pkey);
3423
3424 if (status == SWITCH_STATUS_SUCCESS) {
3425 switch_event_t *s_event;
3426 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Added gateway '%s' to profile '%s'\n", gateway->name, gateway->profile->name);
3427 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_GATEWAY_ADD) == SWITCH_STATUS_SUCCESS) {
3428 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Gateway", gateway->name);
3429 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", gateway->profile->name);
3430 switch_event_fire(&s_event);
3431 }
3432 }
3433
3434 return status;
3435 }
3436
3437 /* For Emacs:
3438 * Local Variables:
3439 * mode:c
3440 * indent-tabs-mode:t
3441 * tab-width:4
3442 * c-basic-offset:4
3443 * End:
3444 * For VIM:
3445 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3446 */
3447