digest: add support for OpenSSL 1.1.0
[siplcs.git] / src / core / sip-transport.c
blob191eeee1f2aa92fbbce7c7e0972576eabc2f4476
1 /**
2 * @file sip-transport.c
4 * pidgin-sipe
6 * Copyright (C) 2010-2017 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /**
24 * This module incapsulates SIP (RFC3261) protocol and provides
25 * higher level API (a layer) to XML-based SIPE (SIP with Extensions).
26 * Underlying leyer for this is TCP/SSL layer.
28 * A diagram in pseudographics:
30 * === SIPE (XML-based) layer ======================
31 * === SIP RFC3261 transport layer (This module) ===
32 * === TCP/SSL layer ===============================
34 * Authentication (Kerberos and NTLM) is applicable to this layer only.
35 * The same with message integtity (signing). No sip-sec* code should
36 * be used ourside of this module.
38 * SIP errors as codes(both as a return codes and network conditions) should be
39 * escalated to higher leyer (SIPE). Network conditions include no response
40 * within timeout interval.
42 * This module should support redirect internally. No escalations to higher
43 * layers needed.
45 * NO SIP-messages (headers) composing and processing should be outside of
46 * this module (!) Like headers: Via, Route, Contact, Authorization, etc.
47 * It's all irrelevant to higher layer responsibilities.
49 * Specification references:
51 * - [MS-SIPAE]: http://msdn.microsoft.com/en-us/library/cc431510.aspx
54 #ifdef HAVE_CONFIG_H
55 #include "config.h"
56 #endif
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdio.h>
62 #include <glib.h>
64 #include "sipe-common.h"
65 #include "sipmsg.h"
66 #include "sip-sec.h"
67 #include "sip-sec-digest.h"
68 #include "sip-transport.h"
69 #include "sipe-backend.h"
70 #include "sipe-core.h"
71 #include "sipe-core-private.h"
72 #include "sipe-certificate.h"
73 #include "sipe-dialog.h"
74 #include "sipe-incoming.h"
75 #include "sipe-lync-autodiscover.h"
76 #include "sipe-nls.h"
77 #include "sipe-notify.h"
78 #include "sipe-schedule.h"
79 #include "sipe-sign.h"
80 #include "sipe-subscriptions.h"
81 #include "sipe-utils.h"
82 #include "uuid.h"
84 struct sip_auth {
85 guint type;
86 struct sip_sec_context *gssapi_context;
87 gchar *gssapi_data;
88 gchar *opaque;
89 const gchar *protocol;
90 gchar *realm;
91 gchar *sts_uri;
92 gchar *target;
93 guint version;
94 guint retries;
95 guint ntlm_num;
96 guint expires;
97 gboolean can_retry;
100 /* sip-transport.c private data */
101 struct sip_transport {
102 struct sipe_transport_connection *connection;
104 gchar *server_name;
105 guint server_port;
106 gchar *server_version;
108 gchar *epid;
109 gchar *ip_address; /* local IP address of transport socket */
111 gchar *user_agent;
113 GSList *transactions;
115 struct sip_auth registrar;
116 struct sip_auth proxy;
118 guint cseq;
119 guint register_attempt;
121 guint keepalive_timeout;
122 time_t last_message;
124 gboolean processing_input; /* whether full header received */
125 gboolean auth_incomplete; /* whether authentication not completed */
126 gboolean auth_retry; /* whether next authentication should be tried */
127 gboolean reregister_set; /* whether reregister timer set */
128 gboolean reauthenticate_set; /* whether reauthenticate timer set */
129 gboolean subscribed; /* whether subscribed to events, except buddies presence */
130 gboolean deregister; /* whether in deregistration */
133 /* Keep in sync with sipe_transport_type! */
134 static const char *transport_descriptor[] = { "", "tls", "tcp"};
135 #define TRANSPORT_DESCRIPTOR (transport_descriptor[transport->connection->type])
137 static char *genbranch()
139 return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X",
140 rand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,
141 rand() & 0xFFFF, rand() & 0xFFFF);
144 static void sipe_auth_free(struct sip_auth *auth)
146 g_free(auth->opaque);
147 auth->opaque = NULL;
148 auth->protocol = NULL;
149 g_free(auth->realm);
150 auth->realm = NULL;
151 g_free(auth->sts_uri);
152 auth->sts_uri = NULL;
153 g_free(auth->target);
154 auth->target = NULL;
155 auth->version = 0;
156 auth->type = SIPE_AUTHENTICATION_TYPE_UNSET;
157 auth->retries = 0;
158 auth->expires = 0;
159 auth->can_retry = FALSE;
160 g_free(auth->gssapi_data);
161 auth->gssapi_data = NULL;
162 sip_sec_destroy_context(auth->gssapi_context);
163 auth->gssapi_context = NULL;
166 static void sipe_make_signature(struct sipe_core_private *sipe_private,
167 struct sipmsg *msg)
169 struct sip_transport *transport = sipe_private->transport;
170 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
171 struct sipmsg_breakdown msgbd;
172 gchar *signature_input_str;
173 msgbd.msg = msg;
174 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
175 transport->registrar.protocol);
176 msgbd.rand = g_strdup_printf("%08x", g_random_int());
177 transport->registrar.ntlm_num++;
178 msgbd.num = g_strdup_printf("%d", transport->registrar.ntlm_num);
179 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
180 if (signature_input_str != NULL) {
181 char *signature_hex = sip_sec_make_signature(transport->registrar.gssapi_context, signature_input_str);
182 g_free(msg->signature);
183 msg->signature = signature_hex;
184 g_free(msg->rand);
185 msg->rand = g_strdup(msgbd.rand);
186 g_free(msg->num);
187 msg->num = g_strdup(msgbd.num);
188 g_free(signature_input_str);
190 sipmsg_breakdown_free(&msgbd);
194 static const gchar *const auth_type_to_protocol[] = {
195 NULL, /* SIPE_AUTHENTICATION_TYPE_UNSET */
196 NULL, /* SIPE_AUTHENTICATION_TYPE_BASIC */
197 "NTLM", /* SIPE_AUTHENTICATION_TYPE_NTLM */
198 "Kerberos", /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
199 NULL, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
200 "TLS-DSK", /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
201 NULL, /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */
203 #define AUTH_PROTOCOLS (sizeof(auth_type_to_protocol)/sizeof(gchar *))
205 static gchar *msg_signature_to_auth(struct sip_auth *auth,
206 struct sipmsg *msg)
208 return(g_strdup_printf("%s qop=\"auth\", opaque=\"%s\", realm=\"%s\", targetname=\"%s\", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
209 auth->protocol,
210 auth->opaque, auth->realm, auth->target,
211 msg->rand, msg->num, msg->signature));
214 static gboolean auth_can_retry(struct sip_transport *transport,
215 const struct sip_auth *auth)
217 /* NTLM is the scheme with lowest priority - don't retry */
218 gboolean retry =
219 auth->can_retry &&
220 (auth->type != SIPE_AUTHENTICATION_TYPE_NTLM);
221 if (retry)
222 transport->auth_retry = TRUE;
223 return(retry);
226 static void initialize_auth_retry(struct sipe_core_private *sipe_private,
227 struct sip_auth *auth)
229 struct sip_transport *transport = sipe_private->transport;
231 if (auth_can_retry(transport, auth)) {
232 if (auth->gssapi_context) {
233 /* need to drop context for retry */
234 sip_sec_destroy_context(auth->gssapi_context);
235 auth->gssapi_context = NULL;
237 } else {
238 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
239 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
240 _("Failed to authenticate to server"));
244 static gchar *initialize_auth_context(struct sipe_core_private *sipe_private,
245 struct sip_auth *auth,
246 struct sipmsg *msg)
248 struct sip_transport *transport = sipe_private->transport;
249 gchar *ret;
250 gchar *gssapi_data = NULL;
251 gchar *sign_str;
252 gchar *gssapi_str;
253 gchar *opaque_str;
254 gchar *version_str;
257 * If transport is de-registering when we reach this point then we
258 * are in the middle of the previous authentication context setup
259 * attempt. So we shouldn't try another attempt.
261 if (transport->deregister)
262 return NULL;
264 /* Create security context or handshake continuation? */
265 if (auth->gssapi_context) {
266 /* Perform next step in authentication handshake */
267 gboolean status = sip_sec_init_context_step(auth->gssapi_context,
268 auth->target,
269 auth->gssapi_data,
270 &gssapi_data,
271 &auth->expires);
273 /* If authentication is completed gssapi_data can be NULL */
274 if (!(status &&
275 (sip_sec_context_is_ready(auth->gssapi_context) || gssapi_data))) {
276 SIPE_DEBUG_ERROR_NOFORMAT("initialize_auth_context: security context continuation failed");
277 g_free(gssapi_data);
278 initialize_auth_retry(sipe_private, auth);
279 return NULL;
282 } else {
283 /* Create security context */
284 gpointer password = sipe_private->password;
286 /* For TLS-DSK the "password" is a certificate */
287 if (auth->type == SIPE_AUTHENTICATION_TYPE_TLS_DSK) {
288 password = sipe_certificate_tls_dsk_find(sipe_private,
289 auth->target);
291 if (!password) {
292 if (auth->sts_uri) {
293 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK Certificate Provisioning URI %s",
294 auth->sts_uri);
295 if (!sipe_certificate_tls_dsk_generate(sipe_private,
296 auth->target,
297 auth->sts_uri)) {
298 gchar *tmp = g_strdup_printf(_("Can't request certificate from %s"),
299 auth->sts_uri);
300 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
301 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
302 tmp);
303 g_free(tmp);
305 } else {
306 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
307 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
308 _("No URI for certificate provisioning service provided"));
311 /* we can't authenticate the message yet */
312 transport->auth_incomplete = TRUE;
314 return(NULL);
315 } else {
316 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK certificate for target '%s' found.",
317 auth->target);
321 auth->gssapi_context = sip_sec_create_context(auth->type,
322 SIPE_CORE_PRIVATE_FLAG_IS(SSO),
323 FALSE, /* connection-less for SIP */
324 sipe_private->authuser,
325 password);
327 if (auth->gssapi_context) {
328 sip_sec_init_context_step(auth->gssapi_context,
329 auth->target,
330 NULL,
331 &gssapi_data,
332 &(auth->expires));
335 /* if auth->gssapi_context is NULL then gssapi_data is still NULL */
336 if (!gssapi_data) {
337 SIPE_DEBUG_ERROR_NOFORMAT("initialize_auth_context: security context initialization failed");
338 initialize_auth_retry(sipe_private, auth);
339 return NULL;
343 if ((auth->version > 3) &&
344 sip_sec_context_is_ready(auth->gssapi_context)) {
345 sipe_make_signature(sipe_private, msg);
346 sign_str = g_strdup_printf(", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
347 msg->rand, msg->num, msg->signature);
348 } else {
349 sign_str = g_strdup("");
352 if (gssapi_data) {
353 gssapi_str = g_strdup_printf(", gssapi-data=\"%s\"",
354 gssapi_data);
355 g_free(gssapi_data);
356 } else {
357 gssapi_str = g_strdup("");
360 opaque_str = auth->opaque ? g_strdup_printf(", opaque=\"%s\"", auth->opaque) : g_strdup("");
362 if (auth->version > 2) {
363 version_str = g_strdup_printf(", version=%d", auth->version);
364 } else {
365 version_str = g_strdup("");
368 ret = g_strdup_printf("%s qop=\"auth\"%s, realm=\"%s\", targetname=\"%s\"%s%s%s",
369 auth->protocol, opaque_str,
370 auth->realm, auth->target,
371 gssapi_str, version_str, sign_str);
372 g_free(version_str);
373 g_free(opaque_str);
374 g_free(gssapi_str);
375 g_free(sign_str);
377 return(ret);
380 static gchar *auth_header(struct sipe_core_private *sipe_private,
381 struct sip_auth *auth,
382 struct sipmsg *msg)
384 gchar *ret = NULL;
387 * If the message is already signed then we have an authentication
388 * context, i.e. the authentication handshake is complete. Generate
389 * authentication header from message signature.
391 if (msg->signature) {
392 ret = msg_signature_to_auth(auth, msg);
395 * We should reach this point only when the authentication context
396 * needs to be initialized.
398 } else {
399 ret = initialize_auth_context(sipe_private, auth, msg);
402 return(ret);
405 static void fill_auth(const gchar *hdr, struct sip_auth *auth)
407 const gchar *param;
409 /* skip authentication identifier */
410 hdr = strchr(hdr, ' ');
411 if (!hdr) {
412 SIPE_DEBUG_ERROR_NOFORMAT("fill_auth: corrupted authentication header");
413 return;
415 while (*hdr == ' ')
416 hdr++;
418 /* start of next parameter value */
419 while ((param = strchr(hdr, '=')) != NULL) {
420 const gchar *end;
422 /* parameter value type */
423 param++;
424 if (*param == '"') {
425 /* string: xyz="..."(,) */
426 end = strchr(++param, '"');
427 if (!end) {
428 SIPE_DEBUG_ERROR("fill_auth: corrupted string parameter near '%s'", hdr);
429 break;
431 } else {
432 /* number: xyz=12345(,) */
433 end = strchr(param, ',');
434 if (!end) {
435 /* last parameter */
436 end = param + strlen(param);
440 #if 0
441 SIPE_DEBUG_INFO("fill_auth: hdr '%s'", hdr);
442 SIPE_DEBUG_INFO("fill_auth: param '%s'", param);
443 SIPE_DEBUG_INFO("fill_auth: end '%s'", end);
444 #endif
446 /* parameter type */
447 if (g_str_has_prefix(hdr, "gssapi-data=\"")) {
448 g_free(auth->gssapi_data);
449 auth->gssapi_data = g_strndup(param, end - param);
450 } else if (g_str_has_prefix(hdr, "opaque=\"")) {
451 g_free(auth->opaque);
452 auth->opaque = g_strndup(param, end - param);
453 } else if (g_str_has_prefix(hdr, "realm=\"")) {
454 g_free(auth->realm);
455 auth->realm = g_strndup(param, end - param);
456 } else if (g_str_has_prefix(hdr, "sts-uri=\"")) {
457 /* Only used with SIPE_AUTHENTICATION_TYPE_TLS_DSK */
458 g_free(auth->sts_uri);
459 auth->sts_uri = g_strndup(param, end - param);
460 } else if (g_str_has_prefix(hdr, "targetname=\"")) {
461 g_free(auth->target);
462 auth->target = g_strndup(param, end - param);
463 } else if (g_str_has_prefix(hdr, "version=")) {
464 auth->version = atoi(param);
467 /* skip to next parameter */
468 while ((*end == '"') || (*end == ',') || (*end == ' '))
469 end++;
470 hdr = end;
473 return;
476 static void sign_outgoing_message(struct sipe_core_private *sipe_private,
477 struct sipmsg *msg)
479 struct sip_transport *transport = sipe_private->transport;
480 gchar *buf;
482 if (transport->registrar.type == SIPE_AUTHENTICATION_TYPE_UNSET) {
483 return;
486 sipe_make_signature(sipe_private, msg);
488 buf = auth_header(sipe_private, &transport->registrar, msg);
489 if (buf) {
490 sipmsg_add_header_now(msg, "Authorization", buf);
491 g_free(buf);
495 static const gchar *sip_transport_user_agent(struct sipe_core_private *sipe_private)
497 struct sip_transport *transport = sipe_private->transport;
499 if (!transport->user_agent) {
500 const gchar *useragent = sipe_backend_setting(SIPE_CORE_PUBLIC,
501 SIPE_SETTING_USER_AGENT);
502 if (is_empty(useragent)) {
503 /*@TODO: better approach to define _user_ OS, it's version and host architecture */
504 /* ref: lzodefs.h */
505 #if defined(__linux__) || defined(__linux) || defined(__LINUX__)
506 #define SIPE_TARGET_PLATFORM "linux"
507 #elif defined(__NetBSD__) ||defined( __OpenBSD__) || defined(__FreeBSD__)
508 #define SIPE_TARGET_PLATFORM "bsd"
509 #elif defined(__APPLE__) || defined(__MACOS__)
510 #define SIPE_TARGET_PLATFORM "macosx"
511 #elif defined(_AIX) || defined(__AIX__) || defined(__aix__)
512 #define SIPE_TARGET_PLATFORM "aix"
513 #elif defined(__solaris__) || defined(__sun)
514 #define SIPE_TARGET_PLATFORM "sun"
515 #elif defined(_WIN32)
516 #define SIPE_TARGET_PLATFORM "win"
517 #elif defined(__CYGWIN__)
518 #define SIPE_TARGET_PLATFORM "cygwin"
519 #elif defined(__hpux__)
520 #define SIPE_TARGET_PLATFORM "hpux"
521 #elif defined(__sgi__)
522 #define SIPE_TARGET_PLATFORM "irix"
523 #else
524 #define SIPE_TARGET_PLATFORM "unknown"
525 #endif
527 #if defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
528 #define SIPE_TARGET_ARCH "x86_64"
529 #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
530 #define SIPE_TARGET_ARCH "i386"
531 #elif defined(__ppc64__)
532 #define SIPE_TARGET_ARCH "ppc64"
533 #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
534 #define SIPE_TARGET_ARCH "ppc"
535 #elif defined(__hppa__) || defined(__hppa)
536 #define SIPE_TARGET_ARCH "hppa"
537 #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
538 #define SIPE_TARGET_ARCH "mips"
539 #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
540 #define SIPE_TARGET_ARCH "s390"
541 #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
542 #define SIPE_TARGET_ARCH "sparc"
543 #elif defined(__arm__)
544 #define SIPE_TARGET_ARCH "arm"
545 #else
546 #define SIPE_TARGET_ARCH "other"
547 #endif
548 gchar *backend = sipe_backend_version();
549 transport->user_agent = g_strdup_printf("%s Sipe/" PACKAGE_VERSION " (" SIPE_TARGET_PLATFORM "-" SIPE_TARGET_ARCH "; %s)",
550 backend,
551 transport->server_version ? transport->server_version : "");
552 g_free(backend);
553 } else {
554 transport->user_agent = g_strdup(useragent);
557 return(transport->user_agent);
561 * NOTE: Do *NOT* call sipe_backend_transport_message(...) directly!
563 * All SIP messages must pass through this function in order to update
564 * the timestamp for keepalive tracking.
566 static void send_sip_message(struct sip_transport *transport,
567 const gchar *string)
569 sipe_utils_message_debug("SIP", string, NULL, TRUE);
570 transport->last_message = time(NULL);
571 sipe_backend_transport_message(transport->connection, string);
574 static void start_keepalive_timer(struct sipe_core_private *sipe_private,
575 guint seconds);
576 static void keepalive_timeout(struct sipe_core_private *sipe_private,
577 SIPE_UNUSED_PARAMETER gpointer data)
579 struct sip_transport *transport = sipe_private->transport;
580 if (transport) {
581 guint since_last = time(NULL) - transport->last_message;
582 guint restart = transport->keepalive_timeout;
583 if (since_last >= restart) {
584 SIPE_DEBUG_INFO("keepalive_timeout: expired %d", restart);
585 send_sip_message(transport, "\r\n\r\n");
586 } else {
587 /* timeout not reached since last message -> reschedule */
588 restart -= since_last;
590 start_keepalive_timer(sipe_private, restart);
594 static void start_keepalive_timer(struct sipe_core_private *sipe_private,
595 guint seconds)
597 sipe_schedule_seconds(sipe_private,
598 "<+keepalive-timeout>",
599 NULL,
600 seconds,
601 keepalive_timeout,
602 NULL);
605 void sip_transport_response(struct sipe_core_private *sipe_private,
606 struct sipmsg *msg,
607 guint code,
608 const char *text,
609 const char *body)
611 gchar *name;
612 gchar *value;
613 GString *outstr = g_string_new("");
614 gchar *contact;
615 GSList *tmp;
616 static const gchar *keepers[] = { "To", "From", "Call-ID", "CSeq", "Via", "Record-Route", NULL };
618 /* Can return NULL! */
619 contact = get_contact(sipe_private);
620 if (contact) {
621 sipmsg_add_header(msg, "Contact", contact);
622 g_free(contact);
625 if (body) {
626 gchar *len = g_strdup_printf("%" G_GSIZE_FORMAT , (gsize) strlen(body));
627 sipmsg_add_header(msg, "Content-Length", len);
628 g_free(len);
629 } else {
630 sipmsg_add_header(msg, "Content-Length", "0");
633 sipmsg_add_header(msg, "User-Agent", sip_transport_user_agent(sipe_private));
635 msg->response = code;
637 sipmsg_strip_headers(msg, keepers);
638 sipmsg_merge_new_headers(msg);
639 sign_outgoing_message(sipe_private, msg);
641 g_string_append_printf(outstr, "SIP/2.0 %d %s\r\n", code, text);
642 tmp = msg->headers;
643 while (tmp) {
644 name = ((struct sipnameval*) (tmp->data))->name;
645 value = ((struct sipnameval*) (tmp->data))->value;
647 g_string_append_printf(outstr, "%s: %s\r\n", name, value);
648 tmp = g_slist_next(tmp);
650 g_string_append_printf(outstr, "\r\n%s", body ? body : "");
651 send_sip_message(sipe_private->transport, outstr->str);
652 g_string_free(outstr, TRUE);
655 static void transactions_remove(struct sipe_core_private *sipe_private,
656 struct transaction *trans)
658 struct sip_transport *transport = sipe_private->transport;
659 if (transport->transactions) {
660 transport->transactions = g_slist_remove(transport->transactions,
661 trans);
662 SIPE_DEBUG_INFO("SIP transactions count:%d after removal", g_slist_length(transport->transactions));
664 if (trans->msg) sipmsg_free(trans->msg);
665 if (trans->payload) {
666 if (trans->payload->destroy)
667 (*trans->payload->destroy)(trans->payload->data);
668 g_free(trans->payload);
670 g_free(trans->key);
671 if (trans->timeout_key) {
672 sipe_schedule_cancel(sipe_private, trans->timeout_key);
673 g_free(trans->timeout_key);
675 g_free(trans);
679 static struct transaction *transactions_find(struct sip_transport *transport,
680 struct sipmsg *msg)
682 GSList *transactions = transport->transactions;
683 const gchar *call_id = sipmsg_find_header(msg, "Call-ID");
684 const gchar *cseq = sipmsg_find_header(msg, "CSeq");
685 gchar *key;
687 if (!call_id || !cseq) {
688 SIPE_DEBUG_ERROR_NOFORMAT("transaction_find: no Call-ID or CSeq!");
689 return NULL;
692 key = g_strdup_printf("<%s><%s>", call_id, cseq);
693 while (transactions) {
694 struct transaction *trans = transactions->data;
695 if (!g_ascii_strcasecmp(trans->key, key)) {
696 g_free(key);
697 return trans;
699 transactions = transactions->next;
701 g_free(key);
703 return NULL;
706 static void transaction_timeout_cb(struct sipe_core_private *sipe_private,
707 gpointer data)
709 struct transaction *trans = data;
710 (trans->timeout_callback)(sipe_private, trans->msg, trans);
711 transactions_remove(sipe_private, trans);
714 struct transaction *sip_transport_request_timeout(struct sipe_core_private *sipe_private,
715 const gchar *method,
716 const gchar *url,
717 const gchar *to,
718 const gchar *addheaders,
719 const gchar *body,
720 struct sip_dialog *dialog,
721 TransCallback callback,
722 guint timeout,
723 TransCallback timeout_callback)
725 struct sip_transport *transport = sipe_private->transport;
726 char *buf;
727 struct sipmsg *msg;
728 gchar *ourtag = dialog && dialog->ourtag ? g_strdup(dialog->ourtag) : NULL;
729 gchar *theirtag = dialog && dialog->theirtag ? g_strdup(dialog->theirtag) : NULL;
730 gchar *theirepid = dialog && dialog->theirepid ? g_strdup(dialog->theirepid) : NULL;
731 gchar *callid = dialog && dialog->callid ? g_strdup(dialog->callid) : gencallid();
732 gchar *branch = dialog && dialog->callid ? NULL : genbranch();
733 gchar *route = g_strdup("");
734 const gchar *epid = transport->epid;
735 int cseq = dialog ? ++dialog->cseq : 1 /* as Call-Id is new in this case */;
736 struct transaction *trans = NULL;
738 if (dialog && dialog->routes)
740 GSList *iter = dialog->routes;
742 while(iter)
744 char *tmp = route;
745 route = g_strdup_printf("%sRoute: %s\r\n", route, (char *)iter->data);
746 g_free(tmp);
747 iter = g_slist_next(iter);
751 if (!ourtag && !dialog) {
752 ourtag = gentag();
755 if (sipe_strequal(method, "REGISTER")) {
756 if (sipe_private->register_callid) {
757 g_free(callid);
758 callid = g_strdup(sipe_private->register_callid);
759 } else {
760 sipe_private->register_callid = g_strdup(callid);
762 cseq = ++transport->cseq;
765 buf = g_strdup_printf("%s %s SIP/2.0\r\n"
766 "Via: SIP/2.0/%s %s:%d%s%s\r\n"
767 "From: <sip:%s>%s%s;epid=%s\r\n"
768 "To: <%s>%s%s%s%s\r\n"
769 "Max-Forwards: 70\r\n"
770 "CSeq: %d %s\r\n"
771 "User-Agent: %s\r\n"
772 "Call-ID: %s\r\n"
773 "%s%s"
774 "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n%s",
775 method,
776 dialog && dialog->request ? dialog->request : url,
777 TRANSPORT_DESCRIPTOR,
778 transport->ip_address,
779 transport->connection->client_port,
780 branch ? ";branch=" : "",
781 branch ? branch : "",
782 sipe_private->username,
783 ourtag ? ";tag=" : "",
784 ourtag ? ourtag : "",
785 epid,
787 theirtag ? ";tag=" : "",
788 theirtag ? theirtag : "",
789 theirepid ? ";epid=" : "",
790 theirepid ? theirepid : "",
791 cseq,
792 method,
793 sip_transport_user_agent(sipe_private),
794 callid,
795 route,
796 addheaders ? addheaders : "",
797 body ? (gsize) strlen(body) : 0,
798 body ? body : "");
801 //printf ("parsing msg buf:\n%s\n\n", buf);
802 msg = sipmsg_parse_msg(buf);
804 g_free(buf);
805 g_free(ourtag);
806 g_free(theirtag);
807 g_free(theirepid);
808 g_free(branch);
809 g_free(route);
811 sign_outgoing_message(sipe_private, msg);
813 /* The authentication scheme is not ready so we can't send the message.
814 This should only happen for REGISTER messages. */
815 if (!transport->auth_incomplete) {
816 buf = sipmsg_to_string(msg);
818 /* add to ongoing transactions */
819 /* ACK isn't supposed to be answered ever. So we do not keep transaction for it. */
820 if (!sipe_strequal(method, "ACK")) {
821 trans = g_new0(struct transaction, 1);
822 trans->callback = callback;
823 trans->msg = msg;
824 trans->key = g_strdup_printf("<%s><%d %s>", callid, cseq, method);
825 if (timeout_callback) {
826 trans->timeout_callback = timeout_callback;
827 trans->timeout_key = g_strdup_printf("<transaction timeout>%s", trans->key);
828 sipe_schedule_seconds(sipe_private,
829 trans->timeout_key,
830 trans,
831 timeout,
832 transaction_timeout_cb,
833 NULL);
835 transport->transactions = g_slist_append(transport->transactions,
836 trans);
837 SIPE_DEBUG_INFO("SIP transactions count:%d after addition", g_slist_length(transport->transactions));
840 send_sip_message(transport, buf);
841 g_free(buf);
844 if (!trans) sipmsg_free(msg);
845 g_free(callid);
846 return trans;
849 struct transaction *sip_transport_request(struct sipe_core_private *sipe_private,
850 const gchar *method,
851 const gchar *url,
852 const gchar *to,
853 const gchar *addheaders,
854 const gchar *body,
855 struct sip_dialog *dialog,
856 TransCallback callback)
858 return sip_transport_request_timeout(sipe_private,
859 method,
860 url,
862 addheaders,
863 body,
864 dialog,
865 callback,
867 NULL);
870 static void sip_transport_simple_request(struct sipe_core_private *sipe_private,
871 const gchar *method,
872 struct sip_dialog *dialog)
874 sip_transport_request(sipe_private,
875 method,
876 dialog->with,
877 dialog->with,
878 NULL,
879 NULL,
880 dialog,
881 NULL);
884 void sip_transport_ack(struct sipe_core_private *sipe_private,
885 struct sip_dialog *dialog)
887 sip_transport_simple_request(sipe_private, "ACK", dialog);
890 void sip_transport_bye(struct sipe_core_private *sipe_private,
891 struct sip_dialog *dialog)
893 sip_transport_simple_request(sipe_private, "BYE", dialog);
896 struct transaction *sip_transport_info(struct sipe_core_private *sipe_private,
897 const gchar *addheaders,
898 const gchar *body,
899 struct sip_dialog *dialog,
900 TransCallback callback)
902 return sip_transport_request(sipe_private,
903 "INFO",
904 dialog->with,
905 dialog->with,
906 addheaders,
907 body,
908 dialog,
909 callback);
912 struct transaction *sip_transport_invite(struct sipe_core_private *sipe_private,
913 const gchar *addheaders,
914 const gchar *body,
915 struct sip_dialog *dialog,
916 TransCallback callback)
918 return sip_transport_request(sipe_private,
919 "INVITE",
920 dialog->with,
921 dialog->with,
922 addheaders,
923 body,
924 dialog,
925 callback);
928 struct transaction *sip_transport_service(struct sipe_core_private *sipe_private,
929 const gchar *uri,
930 const gchar *addheaders,
931 const gchar *body,
932 TransCallback callback)
934 return sip_transport_request(sipe_private,
935 "SERVICE",
936 uri,
937 uri,
938 addheaders,
939 body,
940 NULL,
941 callback);
944 void sip_transport_subscribe(struct sipe_core_private *sipe_private,
945 const gchar *uri,
946 const gchar *addheaders,
947 const gchar *body,
948 struct sip_dialog *dialog,
949 TransCallback callback)
951 sip_transport_request(sipe_private,
952 "SUBSCRIBE",
953 uri,
954 uri,
955 addheaders,
956 body,
957 dialog,
958 callback);
961 void sip_transport_update(struct sipe_core_private *sipe_private,
962 struct sip_dialog *dialog,
963 TransCallback callback)
965 sip_transport_request(sipe_private,
966 "UPDATE",
967 dialog->with,
968 dialog->with,
969 NULL,
970 NULL,
971 dialog,
972 callback);
975 static const gchar *get_auth_header(struct sipe_core_private *sipe_private,
976 guint type,
977 struct sipmsg *msg)
979 struct sip_auth *auth = &sipe_private->transport->registrar;
981 auth->type = type;
982 auth->protocol = auth_type_to_protocol[auth->type];
984 return(sipmsg_find_auth_header(msg, auth->protocol));
987 static void do_register(struct sipe_core_private *sipe_private,
988 gboolean deregister);
990 static void do_reauthenticate_cb(struct sipe_core_private *sipe_private,
991 SIPE_UNUSED_PARAMETER gpointer unused)
993 struct sip_transport *transport = sipe_private->transport;
995 /* register again when security token expires */
996 /* we have to start a new authentication as the security token
997 * is almost expired by sending a not signed REGISTER message */
998 SIPE_LOG_INFO_NOFORMAT("do_reauthenticate_cb: do a full reauthentication");
999 sipe_auth_free(&transport->registrar);
1000 sipe_auth_free(&transport->proxy);
1001 sipe_schedule_cancel(sipe_private, "<registration>");
1002 transport->auth_retry = TRUE;
1003 transport->reregister_set = FALSE;
1004 transport->register_attempt = 0;
1005 do_register(sipe_private, FALSE);
1006 transport->reauthenticate_set = FALSE;
1009 static void sip_transport_default_contact(struct sipe_core_private *sipe_private)
1011 struct sip_transport *transport = sipe_private->transport;
1012 sipe_private->contact = g_strdup_printf("<sip:%s:%d;maddr=%s;transport=%s>;proxy=replace",
1013 sipe_private->username,
1014 transport->connection->client_port,
1015 transport->ip_address,
1016 TRANSPORT_DESCRIPTOR);
1019 static void do_register_cb(struct sipe_core_private *sipe_private,
1020 SIPE_UNUSED_PARAMETER void *unused)
1022 do_register(sipe_private, FALSE);
1025 static void sip_transport_set_reregister(struct sipe_core_private *sipe_private,
1026 int expires)
1028 sipe_schedule_seconds(sipe_private,
1029 "<registration>",
1030 NULL,
1031 expires,
1032 do_register_cb,
1033 NULL);
1036 static void sipe_server_register(struct sipe_core_private *sipe_private,
1037 guint type,
1038 gchar *server_name,
1039 guint server_port);
1041 static gboolean process_register_response(struct sipe_core_private *sipe_private,
1042 struct sipmsg *msg,
1043 SIPE_UNUSED_PARAMETER struct transaction *trans)
1045 struct sip_transport *transport = sipe_private->transport;
1046 const gchar *expires_header;
1047 int expires, i;
1048 GSList *hdr = msg->headers;
1049 struct sipnameval *elem;
1051 expires_header = sipmsg_find_header(msg, "Expires");
1052 expires = expires_header != NULL ? strtol(expires_header, NULL, 10) : 0;
1053 SIPE_DEBUG_INFO("process_register_response: got response to REGISTER; expires = %d", expires);
1055 switch (msg->response) {
1056 case 200:
1057 if (expires) {
1058 const gchar *contact_hdr;
1059 const gchar *auth_hdr;
1060 gchar *gruu = NULL;
1061 gchar *uuid;
1062 gchar *timeout;
1063 const gchar *server_hdr = sipmsg_find_header(msg, "Server");
1065 if (!transport->reregister_set) {
1066 /* Schedule re-register 30 seconds before expiration */
1067 if (expires > 30)
1068 expires -= 30;
1069 sip_transport_set_reregister(sipe_private,
1070 expires);
1071 transport->reregister_set = TRUE;
1074 if (server_hdr && !transport->server_version) {
1075 transport->server_version = g_strdup(server_hdr);
1076 g_free(transport->user_agent);
1077 transport->user_agent = NULL;
1080 auth_hdr = sipmsg_find_auth_header(msg,
1081 transport->registrar.protocol);
1082 if (auth_hdr) {
1083 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
1084 fill_auth(auth_hdr, &transport->registrar);
1087 if (!transport->reauthenticate_set) {
1088 /* [MS-SIPAE] Section 3.2.2 Timers
1090 * When the ... authentication handshake completes
1091 * and the SA enters the "established" state, the
1092 * SIP protocol client MUST start an SA expiration
1093 * timer.
1094 * ...
1095 * The expiration timer value is the lesser of
1097 * - Kerberos: the service ticket expiry time
1098 * - TLS-DSK: the certificate expiration time
1100 * and eight hours, further reduced by some buffer
1101 * time.
1102 * ...
1103 * The protocol client MUST choose a sufficient
1104 * buffer time to allow for the ... authentication
1105 * handshake that reestablishes the SA to complete
1106 * ... This value SHOULD be five (5) minutes or
1107 * longer.
1109 guint reauth_timeout = transport->registrar.expires;
1111 SIPE_LOG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully");
1113 if ((reauth_timeout == 0) ||
1114 (reauth_timeout > 8 * 60 * 60))
1115 reauth_timeout = 8 * 60 * 60;
1116 if (reauth_timeout > 5 * 60)
1117 reauth_timeout -= 5 * 60;
1119 sipe_schedule_seconds(sipe_private,
1120 "<+reauthentication>",
1121 NULL,
1122 reauth_timeout,
1123 do_reauthenticate_cb,
1124 NULL);
1125 transport->reauthenticate_set = TRUE;
1128 uuid = get_uuid(sipe_private);
1130 // There can be multiple Contact headers (one per location where the user is logged in) so
1131 // make sure to only get the one for this uuid
1132 for (i = 0; (contact_hdr = sipmsg_find_header_instance (msg, "Contact", i)); i++) {
1133 gchar * valid_contact = sipmsg_find_part_of_header (contact_hdr, uuid, NULL, NULL);
1134 if (valid_contact) {
1135 gruu = sipmsg_find_part_of_header(contact_hdr, "gruu=\"", "\"", NULL);
1136 //SIPE_DEBUG_INFO("process_register_response: got gruu %s from contact hdr w/ right uuid: %s", gruu, contact_hdr);
1137 g_free(valid_contact);
1138 break;
1139 } else {
1140 //SIPE_DEBUG_INFO("process_register_response: ignoring contact hdr b/c not right uuid: %s", contact_hdr);
1143 g_free(uuid);
1145 g_free(sipe_private->contact);
1146 if(gruu) {
1147 sipe_private->contact = g_strdup_printf("<%s>", gruu);
1148 g_free(gruu);
1149 } else {
1150 //SIPE_DEBUG_INFO_NOFORMAT("process_register_response: didn't find gruu in a Contact hdr");
1151 sip_transport_default_contact(sipe_private);
1153 SIPE_CORE_PRIVATE_FLAG_UNSET(OCS2007);
1154 SIPE_CORE_PRIVATE_FLAG_UNSET(REMOTE_USER);
1155 SIPE_CORE_PRIVATE_FLAG_UNSET(BATCHED_SUPPORT);
1156 SIPE_CORE_PRIVATE_FLAG_UNSET(SFB);
1158 while(hdr)
1160 elem = hdr->data;
1161 if (sipe_strcase_equal(elem->name, "Supported")) {
1162 if (sipe_strcase_equal(elem->value, "msrtc-event-categories")) {
1163 /* We interpret this as OCS2007+ indicator */
1164 SIPE_CORE_PRIVATE_FLAG_SET(OCS2007);
1165 SIPE_LOG_INFO("process_register_response: Supported: %s (indicates OCS2007+)", elem->value);
1167 if (sipe_strcase_equal(elem->value, "adhoclist")) {
1168 SIPE_CORE_PRIVATE_FLAG_SET(BATCHED_SUPPORT);
1169 SIPE_DEBUG_INFO("process_register_response: Supported: %s", elem->value);
1171 } else if (sipe_strcase_equal(elem->name, "Allow-Events")){
1172 gchar **caps = g_strsplit(elem->value,",",0);
1173 i = 0;
1174 while (caps[i]) {
1175 sipe_private->allowed_events = g_slist_append(sipe_private->allowed_events, g_strdup(caps[i]));
1176 SIPE_DEBUG_INFO("process_register_response: Allow-Events: %s", caps[i]);
1177 i++;
1179 g_strfreev(caps);
1180 } else if (sipe_strcase_equal(elem->name, "ms-user-logon-data")) {
1181 if (sipe_strcase_equal(elem->value, "RemoteUser")) {
1182 SIPE_CORE_PRIVATE_FLAG_SET(REMOTE_USER);
1183 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: ms-user-logon-data: RemoteUser (connected "
1184 "via Edge Server)");
1186 } else if (sipe_strcase_equal(elem->name, "Server")) {
1187 /* Server string has format like 'RTC/6.0'.
1188 * We want to check the first digit. */
1189 gchar **parts = g_strsplit_set(elem->value, "/.", 3);
1190 if (g_strv_length(parts) > 1) {
1191 guint version = atoi(parts[1]);
1192 if (version >= 6) {
1193 SIPE_CORE_PRIVATE_FLAG_SET(SFB);
1194 SIPE_LOG_INFO("process_register_response: server version is %d >= 6 (indicates Skype for Business+)", version);
1197 g_strfreev(parts);
1199 hdr = g_slist_next(hdr);
1202 sipe_backend_connection_completed(SIPE_CORE_PUBLIC);
1204 /* rejoin open chats to be able to use them by continue to send messages */
1205 sipe_backend_chat_rejoin_all(SIPE_CORE_PUBLIC);
1207 /* subscriptions, done only once */
1208 if (!transport->subscribed) {
1209 sipe_subscription_self_events(sipe_private);
1210 transport->subscribed = TRUE;
1213 timeout = sipmsg_find_part_of_header(sipmsg_find_header(msg, "ms-keep-alive"),
1214 "timeout=", ";", NULL);
1215 if (timeout != NULL) {
1216 sscanf(timeout, "%u", &transport->keepalive_timeout);
1217 SIPE_DEBUG_INFO("process_register_response: server determined keep alive timeout is %u seconds",
1218 transport->keepalive_timeout);
1219 g_free(timeout);
1222 SIPE_DEBUG_INFO("process_register_response: got 200, removing CSeq: %d", transport->cseq);
1224 break;
1225 case 301:
1227 gchar *redirect = parse_from(sipmsg_find_header(msg, "Contact"));
1229 SIPE_LOG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully (with redirect)");
1231 if (redirect && (g_ascii_strncasecmp("sip:", redirect, 4) == 0)) {
1232 gchar **parts = g_strsplit(redirect + 4, ";", 0);
1233 gchar **tmp;
1234 gchar *hostname;
1235 int port = 0;
1236 guint transport_type = SIPE_TRANSPORT_TLS;
1237 int i = 1;
1239 tmp = g_strsplit(parts[0], ":", 0);
1240 hostname = g_strdup(tmp[0]);
1241 if (tmp[1]) port = strtoul(tmp[1], NULL, 10);
1242 g_strfreev(tmp);
1244 while (parts[i]) {
1245 tmp = g_strsplit(parts[i], "=", 0);
1246 if (tmp[1]) {
1247 if (g_ascii_strcasecmp("transport", tmp[0]) == 0) {
1248 if (g_ascii_strcasecmp("tcp", tmp[1]) == 0) {
1249 transport_type = SIPE_TRANSPORT_TCP;
1253 g_strfreev(tmp);
1254 i++;
1256 g_strfreev(parts);
1258 /* Close old connection */
1259 sipe_core_connection_cleanup(sipe_private);
1260 /* transport and sipe_private->transport are invalid after this */
1262 /* Create new connection */
1263 sipe_server_register(sipe_private, transport_type, hostname, port);
1264 /* sipe_private->transport has a new value */
1265 SIPE_DEBUG_INFO("process_register_response: redirected to host %s port %d transport %d",
1266 hostname, port, transport_type);
1268 g_free(redirect);
1270 break;
1271 case 401:
1273 const char *auth_hdr = NULL;
1275 SIPE_DEBUG_INFO("process_register_response: REGISTER retries %d", transport->registrar.retries);
1277 if (transport->reauthenticate_set) {
1278 SIPE_DEBUG_ERROR_NOFORMAT("process_register_response: RE-REGISTER rejected, triggering re-authentication");
1279 do_reauthenticate_cb(sipe_private, NULL);
1280 return TRUE;
1283 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1284 struct sip_auth *auth = &transport->registrar;
1286 /* NTLM is the scheme with lowest priority - don't retry */
1287 if (auth_can_retry(transport, auth)) {
1288 guint failed = auth->type;
1289 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake failed - trying next authentication scheme.");
1290 sipe_auth_free(auth);
1291 auth->type = failed;
1292 } else {
1293 SIPE_LOG_ERROR_NOFORMAT("process_register_response: authentication handshake failed - giving up.");
1294 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1295 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
1296 _("Authentication failed"));
1297 return TRUE;
1301 if (sipe_private->authentication_type == SIPE_AUTHENTICATION_TYPE_AUTOMATIC) {
1302 struct sip_auth *auth = &transport->registrar;
1303 guint try = auth->type;
1305 while (!auth_hdr) {
1307 * Determine next authentication
1308 * scheme in priority order
1310 if (transport->auth_retry)
1311 switch (try) {
1312 case SIPE_AUTHENTICATION_TYPE_UNSET:
1313 try = SIPE_AUTHENTICATION_TYPE_TLS_DSK;
1314 break;
1316 case SIPE_AUTHENTICATION_TYPE_TLS_DSK:
1317 #if defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_SSPI)
1318 try = SIPE_AUTHENTICATION_TYPE_KERBEROS;
1319 break;
1321 case SIPE_AUTHENTICATION_TYPE_KERBEROS:
1322 #endif
1323 try = SIPE_AUTHENTICATION_TYPE_NTLM;
1324 break;
1326 default:
1327 try = SIPE_AUTHENTICATION_TYPE_UNSET;
1328 break;
1331 auth->can_retry = (try != SIPE_AUTHENTICATION_TYPE_UNSET);
1333 if (!auth->can_retry) {
1334 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: no more authentication schemes to try");
1335 break;
1338 auth_hdr = get_auth_header(sipe_private,
1339 try,
1340 msg);
1343 transport->auth_retry = FALSE;
1345 } else
1346 auth_hdr = get_auth_header(sipe_private,
1347 sipe_private->authentication_type,
1348 msg);
1350 if (!auth_hdr) {
1351 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1352 SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
1353 _("Incompatible authentication scheme chosen"));
1354 return TRUE;
1356 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
1357 fill_auth(auth_hdr, &transport->registrar);
1358 transport->reregister_set = FALSE;
1359 transport->register_attempt = 0;
1360 do_register(sipe_private,
1361 sipe_backend_connection_is_disconnecting(SIPE_CORE_PUBLIC));
1363 break;
1364 case 403:
1366 gchar *reason;
1367 gchar *warning;
1368 sipmsg_parse_warning(msg, &reason);
1369 reason = reason ? reason : sipmsg_get_ms_diagnostics_public_reason(msg);
1370 warning = g_strdup_printf(_("You have been rejected by the server: %s"),
1371 reason ? reason : _("no reason given"));
1372 g_free(reason);
1374 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1375 SIPE_CONNECTION_ERROR_INVALID_SETTINGS,
1376 warning);
1377 g_free(warning);
1378 return TRUE;
1380 break;
1381 case 404:
1383 const gchar *diagnostics = sipmsg_find_header(msg, "ms-diagnostics");
1384 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1385 gchar *warning;
1386 warning = g_strdup_printf(_("Not found: %s. Please contact your Administrator"),
1387 diagnostics ? (reason ? reason : _("no reason given")) :
1388 _("SIP is either not enabled for the destination URI or it does not exist"));
1389 g_free(reason);
1391 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1392 SIPE_CONNECTION_ERROR_INVALID_USERNAME,
1393 warning);
1394 g_free(warning);
1395 return TRUE;
1397 break;
1398 case 504: /* Server time-out */
1399 /* first attempt + 5 retries */
1400 if (transport->register_attempt < 6) {
1401 SIPE_DEBUG_INFO("process_register_response: RE-REGISTER timeout on attempt %d, retrying later",
1402 transport->register_attempt);
1403 sip_transport_set_reregister(sipe_private, 60);
1404 return TRUE;
1406 /* FALLTHROUGH */
1407 case 503:
1409 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1410 gchar *warning;
1411 warning = g_strdup_printf(_("Service unavailable: %s"), reason ? reason : _("no reason given"));
1412 g_free(reason);
1414 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1415 SIPE_CONNECTION_ERROR_NETWORK,
1416 warning);
1417 g_free(warning);
1418 return TRUE;
1420 break;
1422 return TRUE;
1425 static gboolean register_response_timeout(struct sipe_core_private *sipe_private,
1426 SIPE_UNUSED_PARAMETER struct sipmsg *msg,
1427 SIPE_UNUSED_PARAMETER struct transaction *trans)
1429 struct sip_transport *transport = sipe_private->transport;
1430 if (transport->register_attempt < 6) {
1431 SIPE_DEBUG_INFO("register_response_timeout: no answer to attempt %d, retrying",
1432 transport->register_attempt);
1433 do_register(sipe_private, FALSE);
1434 } else {
1435 gchar *warning = g_strdup_printf(_("Service unavailable: %s"), _("no reason given"));
1436 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1437 SIPE_CONNECTION_ERROR_NETWORK,
1438 warning);
1439 g_free(warning);
1441 return TRUE;
1444 static void do_register(struct sipe_core_private *sipe_private,
1445 gboolean deregister)
1447 struct sip_transport *transport = sipe_private->transport;
1448 char *uri;
1449 char *to;
1450 char *hdr;
1451 char *uuid;
1453 if (!sipe_private->public.sip_domain) return;
1455 if (!deregister) {
1456 if (transport->reregister_set) {
1457 transport->reregister_set = FALSE;
1458 transport->register_attempt = 1;
1459 } else {
1460 transport->register_attempt++;
1464 transport->deregister = deregister;
1465 transport->auth_incomplete = FALSE;
1467 uuid = get_uuid(sipe_private);
1468 hdr = g_strdup_printf("Contact: <sip:%s:%d;transport=%s;ms-opaque=d3470f2e1d>;methods=\"INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER, BENOTIFY\";proxy=replace;+sip.instance=\"<urn:uuid:%s>\"\r\n"
1469 "Supported: gruu-10, adhoclist, msrtc-event-categories, com.microsoft.msrtc.presence\r\n"
1470 "Event: registration\r\n"
1471 "Allow-Events: presence\r\n"
1472 "ms-keep-alive: UAC;hop-hop=yes\r\n"
1473 "%s",
1474 transport->ip_address,
1475 transport->connection->client_port,
1476 TRANSPORT_DESCRIPTOR,
1477 uuid,
1478 deregister ? "Expires: 0\r\n" : "");
1479 g_free(uuid);
1481 uri = sip_uri_from_name(sipe_private->public.sip_domain);
1482 to = sip_uri_self(sipe_private);
1483 sip_transport_request_timeout(sipe_private,
1484 "REGISTER",
1485 uri,
1487 hdr,
1489 NULL,
1490 process_register_response,
1492 deregister ? NULL : register_response_timeout);
1493 g_free(to);
1494 g_free(uri);
1495 g_free(hdr);
1497 if (deregister) {
1498 /* Make sure that all messages are pushed to the server
1499 before the connection gets shut down */
1500 SIPE_LOG_INFO_NOFORMAT("De-register from server. Flushing outstanding messages.");
1501 sipe_backend_transport_flush(transport->connection);
1505 void sip_transport_deregister(struct sipe_core_private *sipe_private)
1507 do_register(sipe_private, TRUE);
1510 void sip_transport_disconnect(struct sipe_core_private *sipe_private)
1512 struct sip_transport *transport = sipe_private->transport;
1514 /* transport can be NULL during connection setup */
1515 if (transport) {
1516 SIPE_LOG_INFO("sip_transport_disconnect: dropping connection '%s:%u'",
1517 transport->server_name, transport->server_port);
1519 sipe_backend_transport_disconnect(transport->connection);
1521 sipe_auth_free(&transport->registrar);
1522 sipe_auth_free(&transport->proxy);
1524 g_free(transport->server_name);
1525 g_free(transport->server_version);
1526 g_free(transport->ip_address);
1527 g_free(transport->epid);
1528 g_free(transport->user_agent);
1530 while (transport->transactions)
1531 transactions_remove(sipe_private,
1532 transport->transactions->data);
1534 g_free(transport);
1537 sipe_private->transport = NULL;
1538 sipe_private->service_data = NULL;
1539 sipe_private->address_data = NULL;
1541 sipe_schedule_cancel(sipe_private, "<+keepalive-timeout>");
1543 if (sipe_private->dns_query)
1544 sipe_backend_dns_query_cancel(sipe_private->dns_query);
1548 void sip_transport_authentication_completed(struct sipe_core_private *sipe_private)
1550 do_reauthenticate_cb(sipe_private, NULL);
1553 guint sip_transport_port(struct sipe_core_private *sipe_private)
1555 return sipe_private->transport->server_port;
1558 static void process_input_message(struct sipe_core_private *sipe_private,
1559 struct sipmsg *msg)
1561 struct sip_transport *transport = sipe_private->transport;
1562 gboolean notfound = FALSE;
1563 const char *method = msg->method ? msg->method : "NOT FOUND";
1565 SIPE_DEBUG_INFO("process_input_message: msg->response(%d),msg->method(%s)",
1566 msg->response, method);
1568 if (msg->response == 0) { /* request */
1569 if (sipe_strequal(method, "MESSAGE")) {
1570 process_incoming_message(sipe_private, msg);
1571 } else if (sipe_strequal(method, "NOTIFY")) {
1572 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_notify");
1573 process_incoming_notify(sipe_private, msg);
1574 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1575 } else if (sipe_strequal(method, "BENOTIFY")) {
1576 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_benotify");
1577 process_incoming_notify(sipe_private, msg);
1578 } else if (sipe_strequal(method, "INVITE")) {
1579 process_incoming_invite(sipe_private, msg);
1580 } else if (sipe_strequal(method, "REFER")) {
1581 process_incoming_refer(sipe_private, msg);
1582 } else if (sipe_strequal(method, "OPTIONS")) {
1583 process_incoming_options(sipe_private, msg);
1584 } else if (sipe_strequal(method, "INFO")) {
1585 process_incoming_info(sipe_private, msg);
1586 } else if (sipe_strequal(method, "ACK")) {
1587 /* ACK's don't need any response */
1588 } else if (sipe_strequal(method, "PRACK")) {
1589 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1590 } else if (sipe_strequal(method, "SUBSCRIBE")) {
1591 /* LCS 2005 sends us these - just respond 200 OK */
1592 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1593 } else if (sipe_strequal(method, "CANCEL")) {
1594 process_incoming_cancel(sipe_private, msg);
1595 } else if (sipe_strequal(method, "BYE")) {
1596 process_incoming_bye(sipe_private, msg);
1597 } else {
1598 sip_transport_response(sipe_private, msg, 501, "Not implemented", NULL);
1599 notfound = TRUE;
1602 } else { /* response */
1603 struct transaction *trans = transactions_find(transport, msg);
1604 if (trans) {
1605 if (msg->response < 200) {
1606 /* ignore provisional response */
1607 SIPE_DEBUG_INFO("process_input_message: got provisional (%d) response, ignoring", msg->response);
1609 /* Transaction not yet completed */
1610 trans = NULL;
1612 } else if (msg->response == 401) { /* Unauthorized */
1614 if (sipe_strequal(trans->msg->method, "REGISTER")) {
1615 /* Expected response during authentication handshake */
1616 transport->registrar.retries++;
1617 SIPE_DEBUG_INFO("process_input_message: RE-REGISTER CSeq: %d", transport->cseq);
1618 } else {
1619 gchar *resend;
1621 /* Are we registered? */
1622 if (transport->reregister_set) {
1623 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Retrying with new authentication.");
1624 sipmsg_remove_header_now(trans->msg, "Authorization");
1625 sign_outgoing_message(sipe_private,
1626 trans->msg);
1627 } else {
1629 * We don't have a valid authentication at the moment.
1630 * Resend message unchanged. It will be rejected again
1631 * and hopefully by then we have a valid authentication.
1633 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Bouncing...");
1636 /* Resend request */
1637 resend = sipmsg_to_string(trans->msg);
1638 send_sip_message(sipe_private->transport, resend);
1639 g_free(resend);
1641 /* Transaction not yet completed */
1642 trans = NULL;
1645 } else if (msg->response == 407) { /* Proxy Authentication Required */
1647 if (transport->proxy.retries++ <= 30) {
1648 const gchar *proxy_hdr = sipmsg_find_header(msg, "Proxy-Authenticate");
1650 if (proxy_hdr) {
1651 gchar *auth = NULL;
1653 if (!g_ascii_strncasecmp(proxy_hdr, "Digest", 6)) {
1654 auth = sip_sec_digest_authorization(sipe_private,
1655 proxy_hdr + 7,
1656 msg->method,
1657 msg->target);
1658 } else {
1659 guint i;
1661 transport->proxy.type = SIPE_AUTHENTICATION_TYPE_UNSET;
1662 for (i = 0; i < AUTH_PROTOCOLS; i++) {
1663 const gchar *protocol = auth_type_to_protocol[i];
1664 if (protocol &&
1665 !g_ascii_strncasecmp(proxy_hdr, protocol, strlen(protocol))) {
1666 SIPE_DEBUG_INFO("process_input_message: proxy authentication scheme '%s'", protocol);
1667 transport->proxy.type = i;
1668 transport->proxy.protocol = protocol;
1669 fill_auth(proxy_hdr, &transport->proxy);
1670 auth = auth_header(sipe_private, &transport->proxy, trans->msg);
1671 break;
1676 if (auth) {
1677 gchar *resend;
1679 /* replace old proxy authentication with new one */
1680 sipmsg_remove_header_now(trans->msg, "Proxy-Authorization");
1681 sipmsg_add_header_now(trans->msg, "Proxy-Authorization", auth);
1682 g_free(auth);
1684 /* resend request with proxy authentication */
1685 resend = sipmsg_to_string(trans->msg);
1686 send_sip_message(sipe_private->transport, resend);
1687 g_free(resend);
1689 /* Transaction not yet completed */
1690 trans = NULL;
1692 } else
1693 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: can't generate proxy authentication. Giving up.");
1694 } else
1695 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: 407 response without 'Proxy-Authenticate' header. Giving up.");
1696 } else
1697 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: too many proxy authentication retries. Giving up.");
1699 } else {
1700 transport->registrar.retries = 0;
1701 transport->proxy.retries = 0;
1704 /* Is transaction completed? */
1705 if (trans) {
1706 if (trans->callback) {
1707 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: we have a transaction callback");
1708 /* call the callback to process response */
1709 (trans->callback)(sipe_private, msg, trans);
1710 /* transport && trans no longer valid after redirect */
1714 * Redirect case: sipe_private->transport is
1715 * the new transport with empty queue
1717 if (sipe_private->transport->transactions) {
1718 SIPE_DEBUG_INFO("process_input_message: removing CSeq %d", transport->cseq);
1719 transactions_remove(sipe_private, trans);
1722 } else {
1723 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: received response to unknown transaction");
1724 notfound = TRUE;
1728 if (notfound) {
1729 SIPE_DEBUG_INFO("received a unknown sip message with method %s and response %d", method, msg->response);
1733 static void sip_transport_input(struct sipe_transport_connection *conn)
1735 struct sipe_core_private *sipe_private = conn->user_data;
1736 struct sip_transport *transport = sipe_private->transport;
1737 gchar *cur = conn->buffer;
1739 /* according to the RFC remove CRLF at the beginning */
1740 while (*cur == '\r' || *cur == '\n') {
1741 cur++;
1743 if (cur != conn->buffer)
1744 sipe_utils_shrink_buffer(conn, cur);
1746 /* Received a full Header? */
1747 transport->processing_input = TRUE;
1748 while (transport->processing_input &&
1749 ((cur = strstr(conn->buffer, "\r\n\r\n")) != NULL)) {
1750 struct sipmsg *msg;
1751 guint remainder;
1753 cur += 2;
1754 cur[0] = '\0';
1755 msg = sipmsg_parse_header(conn->buffer);
1757 cur += 2;
1758 remainder = conn->buffer_used - (cur - conn->buffer);
1759 if (msg && remainder >= (guint) msg->bodylen) {
1760 char *dummy = g_malloc(msg->bodylen + 1);
1761 memcpy(dummy, cur, msg->bodylen);
1762 dummy[msg->bodylen] = '\0';
1763 msg->body = dummy;
1764 cur += msg->bodylen;
1765 sipe_utils_message_debug("SIP",
1766 conn->buffer,
1767 msg->body,
1768 FALSE);
1769 sipe_utils_shrink_buffer(conn, cur);
1770 } else {
1771 if (msg) {
1772 SIPE_DEBUG_INFO("sipe_transport_input: body too short (%d < %d, strlen %d) - ignoring message", remainder, msg->bodylen, (int)strlen(conn->buffer));
1773 sipmsg_free(msg);
1776 /* restore header for next try */
1777 cur[-2] = '\r';
1778 return;
1781 /* Fatal header parse error? */
1782 if (msg->response == SIPMSG_RESPONSE_FATAL_ERROR) {
1783 /* can't proceed -> drop connection */
1784 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1785 SIPE_CONNECTION_ERROR_NETWORK,
1786 _("Corrupted message received"));
1787 transport->processing_input = FALSE;
1789 /* Verify the signature before processing it */
1790 } else if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1791 struct sipmsg_breakdown msgbd;
1792 gchar *signature_input_str;
1793 gchar *rspauth;
1794 msgbd.msg = msg;
1795 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
1796 transport->registrar.protocol);
1797 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
1799 rspauth = sipmsg_find_part_of_header(sipmsg_find_header(msg, "Authentication-Info"), "rspauth=\"", "\"", NULL);
1801 if (rspauth != NULL) {
1802 if (sip_sec_verify_signature(transport->registrar.gssapi_context, signature_input_str, rspauth)) {
1803 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message validated");
1804 process_input_message(sipe_private, msg);
1805 /* transport is invalid after redirect */
1806 } else {
1807 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message is invalid.");
1808 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1809 SIPE_CONNECTION_ERROR_NETWORK,
1810 _("Invalid message signature received"));
1811 transport->processing_input = FALSE;
1813 } else if ((msg->response == 401) ||
1814 sipe_strequal(msg->method, "REGISTER")) {
1815 /* a) Retry non-REGISTER requests with updated authentication */
1816 /* b) We must always process REGISTER responses */
1817 process_input_message(sipe_private, msg);
1818 } else {
1819 /* OCS sends provisional messages that are *not* signed */
1820 if (msg->response >= 200) {
1821 /* We are not calling process_input_message(),
1822 so we need to drop the transaction here. */
1823 struct transaction *trans = transactions_find(transport, msg);
1824 if (trans) transactions_remove(sipe_private, trans);
1826 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: message without authentication data - ignoring");
1828 g_free(signature_input_str);
1830 g_free(rspauth);
1831 sipmsg_breakdown_free(&msgbd);
1832 } else {
1833 process_input_message(sipe_private, msg);
1836 sipmsg_free(msg);
1838 /* Redirect: old content of "transport" & "conn" is no longer valid */
1839 transport = sipe_private->transport;
1840 conn = transport->connection;
1844 static void sip_transport_connected(struct sipe_transport_connection *conn)
1846 struct sipe_core_private *sipe_private = conn->user_data;
1847 struct sip_transport *transport = sipe_private->transport;
1848 gchar *self_sip_uri = sip_uri_self(sipe_private);
1850 SIPE_LOG_INFO("sip_transport_connected: %s:%u",
1851 transport->server_name, transport->server_port);
1853 while (sipe_private->lync_autodiscover_servers)
1854 sipe_private->lync_autodiscover_servers =
1855 sipe_lync_autodiscover_pop(sipe_private->lync_autodiscover_servers);
1857 sipe_private->service_data = NULL;
1858 sipe_private->address_data = NULL;
1861 * Initial keepalive timeout during REGISTER phase
1863 * NOTE: 60 seconds is a guess. Needs more testing!
1865 transport->keepalive_timeout = 60;
1866 start_keepalive_timer(sipe_private, transport->keepalive_timeout);
1868 transport->ip_address = sipe_backend_transport_ip_address(conn);
1869 transport->epid = sipe_get_epid(self_sip_uri,
1870 g_get_host_name(),
1871 transport->ip_address);
1872 g_free(self_sip_uri);
1874 do_register(sipe_private, FALSE);
1877 static void resolve_next_lync(struct sipe_core_private *sipe_private);
1878 static void resolve_next_service(struct sipe_core_private *sipe_private,
1879 const struct sip_service_data *start);
1880 static void resolve_next_address(struct sipe_core_private *sipe_private,
1881 gboolean initial);
1882 static void sip_transport_error(struct sipe_transport_connection *conn,
1883 const gchar *msg)
1885 struct sipe_core_private *sipe_private = conn->user_data;
1887 /* This failed attempt was based on a Lync Autodiscover result */
1888 if (sipe_private->lync_autodiscover_servers) {
1889 resolve_next_lync(sipe_private);
1890 /* This failed attempt was based on a DNS SRV record */
1891 } else if (sipe_private->service_data) {
1892 resolve_next_service(sipe_private, NULL);
1893 /* This failed attempt was based on a DNS A record */
1894 } else if (sipe_private->address_data) {
1895 resolve_next_address(sipe_private, FALSE);
1896 } else {
1897 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1898 SIPE_CONNECTION_ERROR_NETWORK,
1899 msg);
1903 /* server_name must be g_alloc()'ed */
1904 static void sipe_server_register(struct sipe_core_private *sipe_private,
1905 guint type,
1906 gchar *server_name,
1907 guint server_port)
1909 sipe_connect_setup setup = {
1910 type,
1911 server_name,
1912 (server_port != 0) ? server_port :
1913 (type == SIPE_TRANSPORT_TLS) ? 5061 : 5060,
1914 sipe_private,
1915 sip_transport_connected,
1916 sip_transport_input,
1917 sip_transport_error
1919 struct sip_transport *transport = g_new0(struct sip_transport, 1);
1921 transport->auth_retry = TRUE;
1922 transport->server_name = server_name;
1923 transport->server_port = setup.server_port;
1924 transport->connection = sipe_backend_transport_connect(SIPE_CORE_PUBLIC,
1925 &setup);
1926 sipe_private->transport = transport;
1929 struct sip_service_data {
1930 const char *protocol;
1931 const char *transport;
1932 guint type;
1936 * Autodiscover using DNS SRV records. See RFC2782/3263
1938 * Service list for AUTO
1940 static const struct sip_service_data service_autodetect[] = {
1941 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1942 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1943 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1944 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1945 { NULL, NULL, 0 }
1948 /* Service list for SSL/TLS */
1949 static const struct sip_service_data service_tls[] = {
1950 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1951 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1952 { NULL, NULL, 0 }
1955 /* Service list for TCP */
1956 static const struct sip_service_data service_tcp[] = {
1957 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1958 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1959 { NULL, NULL, 0 }
1962 static const struct sip_service_data *services[] = {
1963 service_autodetect, /* SIPE_TRANSPORT_AUTO */
1964 service_tls, /* SIPE_TRANSPORT_TLS */
1965 service_tcp /* SIPE_TRANSPORT_TCP */
1968 struct sip_address_data {
1969 const char *prefix;
1970 guint port;
1974 * Autodiscover using DNS A records. This is an extension addded
1975 * by Microsoft. See http://support.microsoft.com/kb/2619522
1977 static const struct sip_address_data addresses[] = {
1978 { "sipinternal", 5061 },
1979 { "sipexternal", 443 },
1981 * Our implementation supports only one port per host name. If the host name
1982 * resolves OK, we abort the search and try to connect. If we would know if we
1983 * are trying to connect from "Intranet" or "Internet" then we could choose
1984 * between those two ports.
1986 * We drop port 5061 in order to cover the "Internet" case.
1988 * { "sip", 5061 },
1990 { "sip", 443 },
1991 { NULL, 0 }
1994 static void sipe_core_dns_resolved(struct sipe_core_public *sipe_public,
1995 const gchar *hostname, guint port)
1997 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1998 gboolean service = sipe_private->service_data != NULL;
2000 sipe_private->dns_query = NULL;
2002 if (hostname) {
2003 gchar *host;
2004 guint type;
2006 if (service) {
2007 host = g_strdup(hostname);
2008 type = sipe_private->service_data->type;
2009 } else {
2010 /* DNS A resolver returns an IP address */
2011 host = g_strdup_printf("%s.%s",
2012 sipe_private->address_data->prefix,
2013 sipe_private->public.sip_domain);
2014 port = sipe_private->address_data->port;
2015 type = sipe_private->transport_type;
2016 if (type == SIPE_TRANSPORT_AUTO)
2017 type = SIPE_TRANSPORT_TLS;
2020 SIPE_DEBUG_INFO("sipe_core_dns_resolved - %s hostname: %s port: %d",
2021 service ? "SRV" : "A", hostname, port);
2022 sipe_server_register(sipe_private, type, host, port);
2023 } else {
2024 if (service)
2025 resolve_next_service(SIPE_CORE_PRIVATE, NULL);
2026 else
2027 resolve_next_address(SIPE_CORE_PRIVATE, FALSE);
2031 static void resolve_next_lync(struct sipe_core_private *sipe_private)
2033 struct sipe_lync_autodiscover_data *lync_data = sipe_private->lync_autodiscover_servers->data;
2034 guint type = sipe_private->transport_type;
2036 if (lync_data) {
2037 /* Try to connect to next server on the list */
2038 if (type == SIPE_TRANSPORT_AUTO)
2039 type = SIPE_TRANSPORT_TLS;
2041 sipe_server_register(sipe_private,
2042 type,
2043 g_strdup(lync_data->server),
2044 lync_data->port);
2046 } else {
2047 /* We tried all servers -> try DNS SRV next */
2048 SIPE_LOG_INFO_NOFORMAT("no Lync Autodiscover servers found; trying SRV records next");
2049 resolve_next_service(sipe_private, services[type]);
2052 sipe_private->lync_autodiscover_servers =
2053 sipe_lync_autodiscover_pop(sipe_private->lync_autodiscover_servers);
2056 static void resolve_next_service(struct sipe_core_private *sipe_private,
2057 const struct sip_service_data *start)
2059 if (start) {
2060 sipe_private->service_data = start;
2061 } else {
2062 sipe_private->service_data++;
2063 if (sipe_private->service_data->protocol == NULL) {
2065 /* We tried all services */
2066 sipe_private->service_data = NULL;
2068 /* Try A records list next */
2069 SIPE_LOG_INFO_NOFORMAT("no SRV records found; trying A records next");
2070 resolve_next_address(sipe_private, TRUE);
2071 return;
2075 /* Try to resolve next service */
2076 sipe_private->dns_query = sipe_backend_dns_query_srv(
2077 SIPE_CORE_PUBLIC,
2078 sipe_private->service_data->protocol,
2079 sipe_private->service_data->transport,
2080 sipe_private->public.sip_domain,
2081 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
2082 SIPE_CORE_PUBLIC);
2085 static void resolve_next_address(struct sipe_core_private *sipe_private,
2086 gboolean initial)
2088 gchar *hostname;
2090 if (initial) {
2091 sipe_private->address_data = addresses;
2092 } else {
2093 sipe_private->address_data++;
2094 if (sipe_private->address_data->prefix == NULL) {
2095 guint type = sipe_private->transport_type;
2097 /* We tried all addresss */
2098 sipe_private->address_data = NULL;
2100 /* Try connecting to the SIP hostname directly */
2101 SIPE_LOG_INFO_NOFORMAT("no SRV or A records found; using SIP domain as fallback");
2102 if (type == SIPE_TRANSPORT_AUTO)
2103 type = SIPE_TRANSPORT_TLS;
2105 sipe_server_register(sipe_private, type,
2106 g_strdup(sipe_private->public.sip_domain),
2108 return;
2112 /* Try to resolve next address */
2113 hostname = g_strdup_printf("%s.%s",
2114 sipe_private->address_data->prefix,
2115 sipe_private->public.sip_domain);
2116 sipe_private->dns_query = sipe_backend_dns_query_a(
2117 SIPE_CORE_PUBLIC,
2118 hostname,
2119 sipe_private->address_data->port,
2120 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
2121 SIPE_CORE_PUBLIC);
2122 g_free(hostname);
2125 static void lync_autodiscover_cb(struct sipe_core_private *sipe_private,
2126 GSList *servers,
2127 SIPE_UNUSED_PARAMETER gpointer callback_data)
2129 if (servers) {
2130 /* Lync Autodiscover succeeded */
2131 SIPE_DEBUG_INFO_NOFORMAT("lync_autodiscover_cb: got server list");
2133 sipe_private->lync_autodiscover_servers = servers;
2134 resolve_next_lync(sipe_private);
2139 * NOTE: this function can be called before sipe_core_allocate()!
2141 gboolean sipe_core_transport_sip_requires_password(guint authentication,
2142 gboolean sso)
2144 return(sip_sec_requires_password(authentication, sso));
2147 void sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public,
2148 guint transport,
2149 guint authentication,
2150 const gchar *server,
2151 const gchar *port)
2153 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
2155 /* backend initialization is complete */
2156 sipe_core_backend_initialized(sipe_private, authentication);
2159 * Initializing the certificate sub-system will trigger the generation
2160 * of a cryptographic key pair which takes time. If we do this after we
2161 * have connected to the server then there is a risk that we run into a
2162 * SIP connection timeout. So let's get this out of the way now...
2164 * This is currently only needed if the user has selected TLS-DSK.
2166 if (sipe_private->authentication_type == SIPE_AUTHENTICATION_TYPE_TLS_DSK)
2167 sipe_certificate_init(sipe_private);
2169 if (server) {
2170 /* Use user specified server[:port] */
2171 int port_number = 0;
2173 if (port)
2174 port_number = atoi(port);
2176 SIPE_LOG_INFO("sipe_core_connect: user specified SIP server %s:%d",
2177 server, port_number);
2179 sipe_server_register(sipe_private, transport,
2180 g_strdup(server), port_number);
2181 } else {
2182 /* Server auto-discovery */
2184 /* Remember user specified transport type */
2185 sipe_private->transport_type = transport;
2187 /* Start with Lync Autodiscover first */
2188 sipe_lync_autodiscover_start(sipe_private,
2189 lync_autodiscover_cb,
2190 NULL);
2194 const gchar *sipe_core_transport_sip_server_name(struct sipe_core_public *sipe_public)
2196 struct sip_transport *transport = SIPE_CORE_PRIVATE->transport;
2197 return(transport ? transport->server_name : NULL);
2200 int sip_transaction_cseq(struct transaction *trans)
2202 int cseq;
2204 g_return_val_if_fail(trans && trans->key, 0);
2206 sscanf(trans->key, "<%*[a-zA-Z0-9]><%d INVITE>", &cseq);
2207 return cseq;
2210 const gchar *sip_transport_epid(struct sipe_core_private *sipe_private)
2212 return(sipe_private->transport ?
2213 sipe_private->transport->epid :
2214 "0123456789ab");
2217 const gchar *sip_transport_ip_address(struct sipe_core_private *sipe_private)
2219 return(sipe_private->transport ?
2220 sipe_private->transport->ip_address :
2221 "0.0.0.0");
2225 Local Variables:
2226 mode: c
2227 c-file-style: "bsd"
2228 indent-tabs-mode: t
2229 tab-width: 8
2230 End: