Fix #222: SIPE crashes when groupchat session expires (IV)
[siplcs.git] / src / core / sip-transport.c
blob15c10e59fe3a307c8ad55b2ab1bf8829d9db0312
1 /**
2 * @file sip-transport.c
4 * pidgin-sipe
6 * Copyright (C) 2010-2013 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.
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
55 #include <stdlib.h>
56 #include <string.h>
57 #include <stdio.h>
59 #include <glib.h>
61 #include "sipe-common.h"
62 #include "sipmsg.h"
63 #include "sip-sec.h"
64 #include "sip-sec-digest.h"
65 #include "sip-transport.h"
66 #include "sipe-backend.h"
67 #include "sipe-core.h"
68 #include "sipe-core-private.h"
69 #include "sipe-certificate.h"
70 #include "sipe-dialog.h"
71 #include "sipe-incoming.h"
72 #include "sipe-nls.h"
73 #include "sipe-notify.h"
74 #include "sipe-schedule.h"
75 #include "sipe-sign.h"
76 #include "sipe-subscriptions.h"
77 #include "sipe-utils.h"
79 struct sip_auth {
80 guint type;
81 struct sip_sec_context *gssapi_context;
82 gchar *gssapi_data;
83 gchar *opaque;
84 const gchar *protocol;
85 gchar *realm;
86 gchar *sts_uri;
87 gchar *target;
88 guint version;
89 guint retries;
90 guint ntlm_num;
91 guint expires;
94 /* sip-transport.c private data */
95 struct sip_transport {
96 struct sipe_transport_connection *connection;
98 gchar *server_name;
99 guint server_port;
100 gchar *server_version;
102 gchar *user_agent;
104 GSList *transactions;
106 struct sip_auth registrar;
107 struct sip_auth proxy;
109 guint cseq;
110 guint register_attempt;
112 gboolean processing_input; /* whether full header received */
113 gboolean auth_incomplete; /* whether authentication not completed */
114 gboolean reregister_set; /* whether reregister timer set */
115 gboolean reauthenticate_set; /* whether reauthenticate timer set */
116 gboolean subscribed; /* whether subscribed to events, except buddies presence */
117 gboolean deregister; /* whether in deregistration */
120 /* Keep in sync with sipe_transport_type! */
121 static const char *transport_descriptor[] = { "", "tls", "tcp"};
122 #define TRANSPORT_DESCRIPTOR (transport_descriptor[transport->connection->type])
124 static char *genbranch()
126 return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X",
127 rand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,
128 rand() & 0xFFFF, rand() & 0xFFFF);
131 static void sipe_auth_free(struct sip_auth *auth)
133 g_free(auth->opaque);
134 auth->opaque = NULL;
135 auth->protocol = NULL;
136 g_free(auth->realm);
137 auth->realm = NULL;
138 g_free(auth->sts_uri);
139 auth->sts_uri = NULL;
140 g_free(auth->target);
141 auth->target = NULL;
142 auth->version = 0;
143 auth->type = SIPE_AUTHENTICATION_TYPE_UNSET;
144 auth->retries = 0;
145 auth->expires = 0;
146 g_free(auth->gssapi_data);
147 auth->gssapi_data = NULL;
148 sip_sec_destroy_context(auth->gssapi_context);
149 auth->gssapi_context = NULL;
152 static void sipe_make_signature(struct sipe_core_private *sipe_private,
153 struct sipmsg *msg)
155 struct sip_transport *transport = sipe_private->transport;
156 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
157 struct sipmsg_breakdown msgbd;
158 gchar *signature_input_str;
159 msgbd.msg = msg;
160 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
161 transport->registrar.protocol);
162 msgbd.rand = g_strdup_printf("%08x", g_random_int());
163 transport->registrar.ntlm_num++;
164 msgbd.num = g_strdup_printf("%d", transport->registrar.ntlm_num);
165 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
166 if (signature_input_str != NULL) {
167 char *signature_hex = sip_sec_make_signature(transport->registrar.gssapi_context, signature_input_str);
168 msg->signature = signature_hex;
169 msg->rand = g_strdup(msgbd.rand);
170 msg->num = g_strdup(msgbd.num);
171 g_free(signature_input_str);
173 sipmsg_breakdown_free(&msgbd);
177 static const gchar *const auth_type_to_protocol[] = {
178 NULL, /* SIPE_AUTHENTICATION_TYPE_UNSET */
179 NULL, /* SIPE_AUTHENTICATION_TYPE_BASIC */
180 "NTLM", /* SIPE_AUTHENTICATION_TYPE_NTLM */
181 "Kerberos", /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
182 NULL, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
183 "TLS-DSK", /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
185 #define AUTH_PROTOCOLS (sizeof(auth_type_to_protocol)/sizeof(gchar *))
187 static gchar *msg_signature_to_auth(struct sip_auth *auth,
188 struct sipmsg *msg)
190 return(g_strdup_printf("%s qop=\"auth\", opaque=\"%s\", realm=\"%s\", targetname=\"%s\", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
191 auth->protocol,
192 auth->opaque, auth->realm, auth->target,
193 msg->rand, msg->num, msg->signature));
196 static gchar *initialize_auth_context(struct sipe_core_private *sipe_private,
197 struct sip_auth *auth,
198 struct sipmsg *msg)
200 struct sip_transport *transport = sipe_private->transport;
201 gchar *ret;
202 gchar *gssapi_data = NULL;
203 gchar *sign_str;
204 gchar *gssapi_str;
205 gchar *opaque_str;
206 gchar *version_str;
209 * If transport is de-registering when we reach this point then we
210 * are in the middle of the previous authentication context setup
211 * attempt. So we shouldn't try another attempt.
213 if (transport->deregister)
214 return NULL;
216 /* Create security context or handshake continuation? */
217 if (auth->gssapi_context) {
218 /* Perform next step in authentication handshake */
219 gboolean status = sip_sec_init_context_step(auth->gssapi_context,
220 auth->target,
221 auth->gssapi_data,
222 &gssapi_data,
223 &auth->expires);
225 /* If authentication is completed gssapi_data can be NULL */
226 if (!(status &&
227 (sip_sec_context_is_ready(auth->gssapi_context) || gssapi_data))) {
228 SIPE_DEBUG_ERROR_NOFORMAT("initialize_auth_context: security context continuation failed");
229 g_free(gssapi_data);
230 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
231 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
232 _("Failed to authenticate to server"));
233 return NULL;
236 } else {
237 /* Create security context */
238 gpointer password = sipe_private->password;
240 /* For TLS-DSK the "password" is a certificate */
241 if (auth->type == SIPE_AUTHENTICATION_TYPE_TLS_DSK) {
242 password = sipe_certificate_tls_dsk_find(sipe_private,
243 auth->target);
245 if (!password) {
246 if (auth->sts_uri) {
247 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK Certificate Provisioning URI %s",
248 auth->sts_uri);
249 if (!sipe_certificate_tls_dsk_generate(sipe_private,
250 auth->target,
251 auth->sts_uri)) {
252 gchar *tmp = g_strdup_printf(_("Can't request certificate from %s"),
253 auth->sts_uri);
254 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
255 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
256 tmp);
257 g_free(tmp);
259 } else {
260 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
261 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
262 _("No URI for certificate provisioning service provided"));
265 /* we can't authenticate the message yet */
266 transport->auth_incomplete = TRUE;
268 return(NULL);
269 } else {
270 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK certificate for target '%s' found.",
271 auth->target);
275 auth->gssapi_context = sip_sec_create_context(auth->type,
276 SIPE_CORE_PRIVATE_FLAG_IS(SSO),
277 FALSE, /* connection-less for SIP */
278 sipe_private->authdomain ? sipe_private->authdomain : "",
279 sipe_private->authuser,
280 password);
282 if (auth->gssapi_context) {
283 sip_sec_init_context_step(auth->gssapi_context,
284 auth->target,
285 NULL,
286 &gssapi_data,
287 &(auth->expires));
290 if (!gssapi_data || !auth->gssapi_context) {
291 g_free(gssapi_data);
292 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
293 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
294 _("Failed to authenticate to server"));
295 return NULL;
299 if ((auth->version > 3) &&
300 sip_sec_context_is_ready(auth->gssapi_context)) {
301 sipe_make_signature(sipe_private, msg);
302 sign_str = g_strdup_printf(", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
303 msg->rand, msg->num, msg->signature);
304 } else {
305 sign_str = g_strdup("");
308 if (gssapi_data) {
309 gssapi_str = g_strdup_printf(", gssapi-data=\"%s\"",
310 gssapi_data);
311 g_free(gssapi_data);
312 } else {
313 gssapi_str = g_strdup("");
316 opaque_str = auth->opaque ? g_strdup_printf(", opaque=\"%s\"", auth->opaque) : g_strdup("");
318 if (auth->version > 2) {
319 version_str = g_strdup_printf(", version=%d", auth->version);
320 } else {
321 version_str = g_strdup("");
324 ret = g_strdup_printf("%s qop=\"auth\"%s, realm=\"%s\", targetname=\"%s\"%s%s%s",
325 auth->protocol, opaque_str,
326 auth->realm, auth->target,
327 gssapi_str, version_str, sign_str);
328 g_free(version_str);
329 g_free(opaque_str);
330 g_free(gssapi_str);
331 g_free(sign_str);
333 return(ret);
336 static gchar *auth_header(struct sipe_core_private *sipe_private,
337 struct sip_auth *auth,
338 struct sipmsg *msg)
340 gchar *ret = NULL;
343 * If the message is already signed then we have an authentication
344 * context, i.e. the authentication handshake is complete. Generate
345 * authentication header from message signature.
347 if (msg->signature) {
348 ret = msg_signature_to_auth(auth, msg);
351 * We should reach this point only when the authentication context
352 * needs to be initialized.
354 } else {
355 ret = initialize_auth_context(sipe_private, auth, msg);
358 return(ret);
361 static void fill_auth(const gchar *hdr, struct sip_auth *auth)
363 const gchar *param;
365 /* skip authentication identifier */
366 hdr = strchr(hdr, ' ');
367 if (!hdr) {
368 SIPE_DEBUG_ERROR_NOFORMAT("fill_auth: corrupted authentication header");
369 return;
371 while (*hdr == ' ')
372 hdr++;
374 /* start of next parameter value */
375 while ((param = strchr(hdr, '=')) != NULL) {
376 const gchar *end;
378 /* parameter value type */
379 param++;
380 if (*param == '"') {
381 /* string: xyz="..."(,) */
382 end = strchr(++param, '"');
383 if (!end) {
384 SIPE_DEBUG_ERROR("fill_auth: corrupted string parameter near '%s'", hdr);
385 break;
387 } else {
388 /* number: xyz=12345(,) */
389 end = strchr(param, ',');
390 if (!end) {
391 /* last parameter */
392 end = param + strlen(param);
396 #if 0
397 SIPE_DEBUG_INFO("fill_auth: hdr '%s'", hdr);
398 SIPE_DEBUG_INFO("fill_auth: param '%s'", param);
399 SIPE_DEBUG_INFO("fill_auth: end '%s'", end);
400 #endif
402 /* parameter type */
403 if (g_str_has_prefix(hdr, "gssapi-data=\"")) {
404 g_free(auth->gssapi_data);
405 auth->gssapi_data = g_strndup(param, end - param);
406 } else if (g_str_has_prefix(hdr, "opaque=\"")) {
407 g_free(auth->opaque);
408 auth->opaque = g_strndup(param, end - param);
409 } else if (g_str_has_prefix(hdr, "realm=\"")) {
410 g_free(auth->realm);
411 auth->realm = g_strndup(param, end - param);
412 } else if (g_str_has_prefix(hdr, "sts-uri=\"")) {
413 /* Only used with SIPE_AUTHENTICATION_TYPE_TLS_DSK */
414 g_free(auth->sts_uri);
415 auth->sts_uri = g_strndup(param, end - param);
416 } else if (g_str_has_prefix(hdr, "targetname=\"")) {
417 g_free(auth->target);
418 auth->target = g_strndup(param, end - param);
419 } else if (g_str_has_prefix(hdr, "version=")) {
420 auth->version = atoi(param);
423 /* skip to next parameter */
424 while ((*end == '"') || (*end == ',') || (*end == ' '))
425 end++;
426 hdr = end;
429 return;
432 static void sign_outgoing_message(struct sipe_core_private *sipe_private,
433 struct sipmsg *msg)
435 struct sip_transport *transport = sipe_private->transport;
436 gchar *buf;
438 if (transport->registrar.type == SIPE_AUTHENTICATION_TYPE_UNSET) {
439 return;
442 sipe_make_signature(sipe_private, msg);
444 buf = auth_header(sipe_private, &transport->registrar, msg);
445 if (buf) {
446 sipmsg_add_header_now(msg, "Authorization", buf);
447 g_free(buf);
451 static const gchar *sip_transport_user_agent(struct sipe_core_private *sipe_private)
453 struct sip_transport *transport = sipe_private->transport;
455 if (!transport->user_agent) {
456 const gchar *useragent = sipe_backend_setting(SIPE_CORE_PUBLIC,
457 SIPE_SETTING_USER_AGENT);
458 if (is_empty(useragent)) {
459 /*@TODO: better approach to define _user_ OS, it's version and host architecture */
460 /* ref: lzodefs.h */
461 #if defined(__linux__) || defined(__linux) || defined(__LINUX__)
462 #define SIPE_TARGET_PLATFORM "linux"
463 #elif defined(__NetBSD__) ||defined( __OpenBSD__) || defined(__FreeBSD__)
464 #define SIPE_TARGET_PLATFORM "bsd"
465 #elif defined(__APPLE__) || defined(__MACOS__)
466 #define SIPE_TARGET_PLATFORM "macosx"
467 #elif defined(_AIX) || defined(__AIX__) || defined(__aix__)
468 #define SIPE_TARGET_PLATFORM "aix"
469 #elif defined(__solaris__) || defined(__sun)
470 #define SIPE_TARGET_PLATFORM "sun"
471 #elif defined(_WIN32)
472 #define SIPE_TARGET_PLATFORM "win"
473 #elif defined(__CYGWIN__)
474 #define SIPE_TARGET_PLATFORM "cygwin"
475 #elif defined(__hpux__)
476 #define SIPE_TARGET_PLATFORM "hpux"
477 #elif defined(__sgi__)
478 #define SIPE_TARGET_PLATFORM "irix"
479 #else
480 #define SIPE_TARGET_PLATFORM "unknown"
481 #endif
483 #if defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
484 #define SIPE_TARGET_ARCH "x86_64"
485 #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
486 #define SIPE_TARGET_ARCH "i386"
487 #elif defined(__ppc64__)
488 #define SIPE_TARGET_ARCH "ppc64"
489 #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
490 #define SIPE_TARGET_ARCH "ppc"
491 #elif defined(__hppa__) || defined(__hppa)
492 #define SIPE_TARGET_ARCH "hppa"
493 #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
494 #define SIPE_TARGET_ARCH "mips"
495 #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
496 #define SIPE_TARGET_ARCH "s390"
497 #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
498 #define SIPE_TARGET_ARCH "sparc"
499 #elif defined(__arm__)
500 #define SIPE_TARGET_ARCH "arm"
501 #else
502 #define SIPE_TARGET_ARCH "other"
503 #endif
504 gchar *backend = sipe_backend_version();
505 transport->user_agent = g_strdup_printf("%s Sipe/" PACKAGE_VERSION " (" SIPE_TARGET_PLATFORM "-" SIPE_TARGET_ARCH "; %s)",
506 backend,
507 transport->server_version ? transport->server_version : "");
508 g_free(backend);
509 } else {
510 transport->user_agent = g_strdup(useragent);
513 return(transport->user_agent);
516 void sip_transport_response(struct sipe_core_private *sipe_private,
517 struct sipmsg *msg,
518 guint code,
519 const char *text,
520 const char *body)
522 gchar *name;
523 gchar *value;
524 GString *outstr = g_string_new("");
525 gchar *contact;
526 GSList *tmp;
527 const gchar *keepers[] = { "To", "From", "Call-ID", "CSeq", "Via", "Record-Route", NULL };
529 /* Can return NULL! */
530 contact = get_contact(sipe_private);
531 if (contact) {
532 sipmsg_add_header(msg, "Contact", contact);
533 g_free(contact);
536 if (body) {
537 gchar *len = g_strdup_printf("%" G_GSIZE_FORMAT , (gsize) strlen(body));
538 sipmsg_add_header(msg, "Content-Length", len);
539 g_free(len);
540 } else {
541 sipmsg_add_header(msg, "Content-Length", "0");
544 sipmsg_add_header(msg, "User-Agent", sip_transport_user_agent(sipe_private));
546 msg->response = code;
548 sipmsg_strip_headers(msg, keepers);
549 sipmsg_merge_new_headers(msg);
550 sign_outgoing_message(sipe_private, msg);
552 g_string_append_printf(outstr, "SIP/2.0 %d %s\r\n", code, text);
553 tmp = msg->headers;
554 while (tmp) {
555 name = ((struct sipnameval*) (tmp->data))->name;
556 value = ((struct sipnameval*) (tmp->data))->value;
558 g_string_append_printf(outstr, "%s: %s\r\n", name, value);
559 tmp = g_slist_next(tmp);
561 g_string_append_printf(outstr, "\r\n%s", body ? body : "");
562 sipe_utils_message_debug("SIP", outstr->str, NULL, TRUE);
563 sipe_backend_transport_message(sipe_private->transport->connection, outstr->str);
564 g_string_free(outstr, TRUE);
567 static void transactions_remove(struct sipe_core_private *sipe_private,
568 struct transaction *trans)
570 struct sip_transport *transport = sipe_private->transport;
571 if (transport->transactions) {
572 transport->transactions = g_slist_remove(transport->transactions,
573 trans);
574 SIPE_DEBUG_INFO("SIP transactions count:%d after removal", g_slist_length(transport->transactions));
576 if (trans->msg) sipmsg_free(trans->msg);
577 if (trans->payload) {
578 if (trans->payload->destroy)
579 (*trans->payload->destroy)(trans->payload->data);
580 g_free(trans->payload);
582 g_free(trans->key);
583 if (trans->timeout_key) {
584 sipe_schedule_cancel(sipe_private, trans->timeout_key);
585 g_free(trans->timeout_key);
587 g_free(trans);
591 static struct transaction *transactions_find(struct sip_transport *transport,
592 struct sipmsg *msg)
594 GSList *transactions = transport->transactions;
595 const gchar *call_id = sipmsg_find_header(msg, "Call-ID");
596 const gchar *cseq = sipmsg_find_header(msg, "CSeq");
597 gchar *key;
599 if (!call_id || !cseq) {
600 SIPE_DEBUG_ERROR_NOFORMAT("transaction_find: no Call-ID or CSeq!");
601 return NULL;
604 key = g_strdup_printf("<%s><%s>", call_id, cseq);
605 while (transactions) {
606 struct transaction *trans = transactions->data;
607 if (!g_ascii_strcasecmp(trans->key, key)) {
608 g_free(key);
609 return trans;
611 transactions = transactions->next;
613 g_free(key);
615 return NULL;
618 static void transaction_timeout_cb(struct sipe_core_private *sipe_private,
619 gpointer data)
621 struct transaction *trans = data;
622 (trans->timeout_callback)(sipe_private, trans->msg, trans);
623 transactions_remove(sipe_private, trans);
626 struct transaction *sip_transport_request_timeout(struct sipe_core_private *sipe_private,
627 const gchar *method,
628 const gchar *url,
629 const gchar *to,
630 const gchar *addheaders,
631 const gchar *body,
632 struct sip_dialog *dialog,
633 TransCallback callback,
634 guint timeout,
635 TransCallback timeout_callback)
637 struct sip_transport *transport = sipe_private->transport;
638 char *buf;
639 struct sipmsg *msg;
640 gchar *ourtag = dialog && dialog->ourtag ? g_strdup(dialog->ourtag) : NULL;
641 gchar *theirtag = dialog && dialog->theirtag ? g_strdup(dialog->theirtag) : NULL;
642 gchar *theirepid = dialog && dialog->theirepid ? g_strdup(dialog->theirepid) : NULL;
643 gchar *callid = dialog && dialog->callid ? g_strdup(dialog->callid) : gencallid();
644 gchar *branch = dialog && dialog->callid ? NULL : genbranch();
645 gchar *route = g_strdup("");
646 gchar *epid = get_epid(sipe_private);
647 int cseq = dialog ? ++dialog->cseq : 1 /* as Call-Id is new in this case */;
648 struct transaction *trans = NULL;
650 if (dialog && dialog->routes)
652 GSList *iter = dialog->routes;
654 while(iter)
656 char *tmp = route;
657 route = g_strdup_printf("%sRoute: %s\r\n", route, (char *)iter->data);
658 g_free(tmp);
659 iter = g_slist_next(iter);
663 if (!ourtag && !dialog) {
664 ourtag = gentag();
667 if (sipe_strequal(method, "REGISTER")) {
668 if (sipe_private->register_callid) {
669 g_free(callid);
670 callid = g_strdup(sipe_private->register_callid);
671 } else {
672 sipe_private->register_callid = g_strdup(callid);
674 cseq = ++transport->cseq;
677 buf = g_strdup_printf("%s %s SIP/2.0\r\n"
678 "Via: SIP/2.0/%s %s:%d%s%s\r\n"
679 "From: <sip:%s>%s%s;epid=%s\r\n"
680 "To: <%s>%s%s%s%s\r\n"
681 "Max-Forwards: 70\r\n"
682 "CSeq: %d %s\r\n"
683 "User-Agent: %s\r\n"
684 "Call-ID: %s\r\n"
685 "%s%s"
686 "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n%s",
687 method,
688 dialog && dialog->request ? dialog->request : url,
689 TRANSPORT_DESCRIPTOR,
690 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
691 transport->connection->client_port,
692 branch ? ";branch=" : "",
693 branch ? branch : "",
694 sipe_private->username,
695 ourtag ? ";tag=" : "",
696 ourtag ? ourtag : "",
697 epid,
699 theirtag ? ";tag=" : "",
700 theirtag ? theirtag : "",
701 theirepid ? ";epid=" : "",
702 theirepid ? theirepid : "",
703 cseq,
704 method,
705 sip_transport_user_agent(sipe_private),
706 callid,
707 route,
708 addheaders ? addheaders : "",
709 body ? (gsize) strlen(body) : 0,
710 body ? body : "");
713 //printf ("parsing msg buf:\n%s\n\n", buf);
714 msg = sipmsg_parse_msg(buf);
716 g_free(buf);
717 g_free(ourtag);
718 g_free(theirtag);
719 g_free(theirepid);
720 g_free(branch);
721 g_free(route);
722 g_free(epid);
724 sign_outgoing_message(sipe_private, msg);
726 /* The authentication scheme is not ready so we can't send the message.
727 This should only happen for REGISTER messages. */
728 if (!transport->auth_incomplete) {
729 buf = sipmsg_to_string(msg);
731 /* add to ongoing transactions */
732 /* ACK isn't supposed to be answered ever. So we do not keep transaction for it. */
733 if (!sipe_strequal(method, "ACK")) {
734 trans = g_new0(struct transaction, 1);
735 trans->callback = callback;
736 trans->msg = msg;
737 trans->key = g_strdup_printf("<%s><%d %s>", callid, cseq, method);
738 if (timeout_callback) {
739 trans->timeout_callback = timeout_callback;
740 trans->timeout_key = g_strdup_printf("<transaction timeout>%s", trans->key);
741 sipe_schedule_seconds(sipe_private,
742 trans->timeout_key,
743 trans,
744 timeout,
745 transaction_timeout_cb,
746 NULL);
748 transport->transactions = g_slist_append(transport->transactions,
749 trans);
750 SIPE_DEBUG_INFO("SIP transactions count:%d after addition", g_slist_length(transport->transactions));
753 sipe_utils_message_debug("SIP", buf, NULL, TRUE);
754 sipe_backend_transport_message(transport->connection, buf);
755 g_free(buf);
758 if (!trans) sipmsg_free(msg);
759 g_free(callid);
760 return trans;
763 struct transaction *sip_transport_request(struct sipe_core_private *sipe_private,
764 const gchar *method,
765 const gchar *url,
766 const gchar *to,
767 const gchar *addheaders,
768 const gchar *body,
769 struct sip_dialog *dialog,
770 TransCallback callback)
772 return sip_transport_request_timeout(sipe_private,
773 method,
774 url,
776 addheaders,
777 body,
778 dialog,
779 callback,
781 NULL);
784 static void sip_transport_simple_request(struct sipe_core_private *sipe_private,
785 const gchar *method,
786 struct sip_dialog *dialog)
788 sip_transport_request(sipe_private,
789 method,
790 dialog->with,
791 dialog->with,
792 NULL,
793 NULL,
794 dialog,
795 NULL);
798 void sip_transport_ack(struct sipe_core_private *sipe_private,
799 struct sip_dialog *dialog)
801 sip_transport_simple_request(sipe_private, "ACK", dialog);
804 void sip_transport_bye(struct sipe_core_private *sipe_private,
805 struct sip_dialog *dialog)
807 sip_transport_simple_request(sipe_private, "BYE", dialog);
810 struct transaction *sip_transport_info(struct sipe_core_private *sipe_private,
811 const gchar *addheaders,
812 const gchar *body,
813 struct sip_dialog *dialog,
814 TransCallback callback)
816 return sip_transport_request(sipe_private,
817 "INFO",
818 dialog->with,
819 dialog->with,
820 addheaders,
821 body,
822 dialog,
823 callback);
826 struct transaction *sip_transport_invite(struct sipe_core_private *sipe_private,
827 const gchar *addheaders,
828 const gchar *body,
829 struct sip_dialog *dialog,
830 TransCallback callback)
832 return sip_transport_request(sipe_private,
833 "INVITE",
834 dialog->with,
835 dialog->with,
836 addheaders,
837 body,
838 dialog,
839 callback);
842 struct transaction *sip_transport_service(struct sipe_core_private *sipe_private,
843 const gchar *uri,
844 const gchar *addheaders,
845 const gchar *body,
846 TransCallback callback)
848 return sip_transport_request(sipe_private,
849 "SERVICE",
850 uri,
851 uri,
852 addheaders,
853 body,
854 NULL,
855 callback);
858 void sip_transport_subscribe(struct sipe_core_private *sipe_private,
859 const gchar *uri,
860 const gchar *addheaders,
861 const gchar *body,
862 struct sip_dialog *dialog,
863 TransCallback callback)
865 sip_transport_request(sipe_private,
866 "SUBSCRIBE",
867 uri,
868 uri,
869 addheaders,
870 body,
871 dialog,
872 callback);
875 void sip_transport_update(struct sipe_core_private *sipe_private,
876 struct sip_dialog *dialog,
877 TransCallback callback)
879 sip_transport_request(sipe_private,
880 "UPDATE",
881 dialog->with,
882 dialog->with,
883 NULL,
884 NULL,
885 dialog,
886 callback);
889 static const gchar *get_auth_header(struct sipe_core_private *sipe_private,
890 struct sip_auth *auth,
891 struct sipmsg *msg)
893 auth->type = sipe_private->authentication_type;
894 auth->protocol = auth_type_to_protocol[auth->type];
896 return(sipmsg_find_auth_header(msg, auth->protocol));
899 static void do_register(struct sipe_core_private *sipe_private,
900 gboolean deregister);
902 static void do_reauthenticate_cb(struct sipe_core_private *sipe_private,
903 SIPE_UNUSED_PARAMETER gpointer unused)
905 struct sip_transport *transport = sipe_private->transport;
907 /* register again when security token expires */
908 /* we have to start a new authentication as the security token
909 * is almost expired by sending a not signed REGISTER message */
910 SIPE_DEBUG_INFO_NOFORMAT("do a full reauthentication");
911 sipe_auth_free(&transport->registrar);
912 sipe_auth_free(&transport->proxy);
913 sipe_schedule_cancel(sipe_private, "<registration>");
914 transport->reregister_set = FALSE;
915 transport->register_attempt = 0;
916 do_register(sipe_private, FALSE);
917 transport->reauthenticate_set = FALSE;
920 static void sip_transport_default_contact(struct sipe_core_private *sipe_private)
922 struct sip_transport *transport = sipe_private->transport;
923 sipe_private->contact = g_strdup_printf("<sip:%s:%d;maddr=%s;transport=%s>;proxy=replace",
924 sipe_private->username,
925 transport->connection->client_port,
926 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
927 TRANSPORT_DESCRIPTOR);
930 static void do_register_cb(struct sipe_core_private *sipe_private,
931 SIPE_UNUSED_PARAMETER void *unused)
933 do_register(sipe_private, FALSE);
936 static void sip_transport_set_reregister(struct sipe_core_private *sipe_private,
937 int expires)
939 sipe_schedule_seconds(sipe_private,
940 "<registration>",
941 NULL,
942 expires,
943 do_register_cb,
944 NULL);
947 static void sipe_server_register(struct sipe_core_private *sipe_private,
948 guint type,
949 gchar *server_name,
950 guint server_port);
952 static gboolean process_register_response(struct sipe_core_private *sipe_private,
953 struct sipmsg *msg,
954 SIPE_UNUSED_PARAMETER struct transaction *trans)
956 struct sip_transport *transport = sipe_private->transport;
957 const gchar *expires_header;
958 int expires, i;
959 GSList *hdr = msg->headers;
960 struct sipnameval *elem;
962 expires_header = sipmsg_find_header(msg, "Expires");
963 expires = expires_header != NULL ? strtol(expires_header, NULL, 10) : 0;
964 SIPE_DEBUG_INFO("process_register_response: got response to REGISTER; expires = %d", expires);
966 switch (msg->response) {
967 case 200:
968 if (expires) {
969 const gchar *contact_hdr;
970 const gchar *auth_hdr;
971 gchar *gruu = NULL;
972 gchar *uuid;
973 gchar *timeout;
974 const gchar *server_hdr = sipmsg_find_header(msg, "Server");
976 if (!transport->reregister_set) {
977 sip_transport_set_reregister(sipe_private,
978 expires);
979 transport->reregister_set = TRUE;
982 if (server_hdr && !transport->server_version) {
983 transport->server_version = g_strdup(server_hdr);
984 g_free(transport->user_agent);
985 transport->user_agent = NULL;
988 auth_hdr = get_auth_header(sipe_private, &transport->registrar, msg);
989 if (auth_hdr) {
990 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
991 fill_auth(auth_hdr, &transport->registrar);
994 if (!transport->reauthenticate_set) {
995 gchar *action_name = g_strdup_printf("<%s>", "+reauthentication");
996 guint reauth_timeout = transport->registrar.expires;
998 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully");
1000 /* Does authentication scheme provide valid expiration time? */
1001 if (reauth_timeout <= (5 * 60)) {
1002 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: no expiration time - using default of 8 hours");
1003 reauth_timeout = 8 * 60 * 60;
1006 /* schedule reauthentication 5 minutes before expiration */
1007 sipe_schedule_seconds(sipe_private,
1008 action_name,
1009 NULL,
1010 reauth_timeout - 5 * 60,
1011 do_reauthenticate_cb,
1012 NULL);
1013 g_free(action_name);
1014 transport->reauthenticate_set = TRUE;
1017 sipe_backend_connection_completed(SIPE_CORE_PUBLIC);
1019 uuid = get_uuid(sipe_private);
1021 // There can be multiple Contact headers (one per location where the user is logged in) so
1022 // make sure to only get the one for this uuid
1023 for (i = 0; (contact_hdr = sipmsg_find_header_instance (msg, "Contact", i)); i++) {
1024 gchar * valid_contact = sipmsg_find_part_of_header (contact_hdr, uuid, NULL, NULL);
1025 if (valid_contact) {
1026 gruu = sipmsg_find_part_of_header(contact_hdr, "gruu=\"", "\"", NULL);
1027 //SIPE_DEBUG_INFO("process_register_response: got gruu %s from contact hdr w/ right uuid: %s", gruu, contact_hdr);
1028 g_free(valid_contact);
1029 break;
1030 } else {
1031 //SIPE_DEBUG_INFO("process_register_response: ignoring contact hdr b/c not right uuid: %s", contact_hdr);
1034 g_free(uuid);
1036 g_free(sipe_private->contact);
1037 if(gruu) {
1038 sipe_private->contact = g_strdup_printf("<%s>", gruu);
1039 g_free(gruu);
1040 } else {
1041 //SIPE_DEBUG_INFO_NOFORMAT("process_register_response: didn't find gruu in a Contact hdr");
1042 sip_transport_default_contact(sipe_private);
1044 SIPE_CORE_PRIVATE_FLAG_UNSET(OCS2007);
1045 SIPE_CORE_PRIVATE_FLAG_UNSET(REMOTE_USER);
1046 SIPE_CORE_PRIVATE_FLAG_UNSET(BATCHED_SUPPORT);
1048 while(hdr)
1050 elem = hdr->data;
1051 if (sipe_strcase_equal(elem->name, "Supported")) {
1052 if (sipe_strcase_equal(elem->value, "msrtc-event-categories")) {
1053 /* We interpret this as OCS2007+ indicator */
1054 SIPE_CORE_PRIVATE_FLAG_SET(OCS2007);
1055 SIPE_DEBUG_INFO("Supported: %s (indicates OCS2007+)", elem->value);
1057 if (sipe_strcase_equal(elem->value, "adhoclist")) {
1058 SIPE_CORE_PRIVATE_FLAG_SET(BATCHED_SUPPORT);
1059 SIPE_DEBUG_INFO("Supported: %s", elem->value);
1062 if (sipe_strcase_equal(elem->name, "Allow-Events")){
1063 gchar **caps = g_strsplit(elem->value,",",0);
1064 i = 0;
1065 while (caps[i]) {
1066 sipe_private->allowed_events = g_slist_append(sipe_private->allowed_events, g_strdup(caps[i]));
1067 SIPE_DEBUG_INFO("Allow-Events: %s", caps[i]);
1068 i++;
1070 g_strfreev(caps);
1072 if (sipe_strcase_equal(elem->name, "ms-user-logon-data")) {
1073 if (sipe_strcase_equal(elem->value, "RemoteUser")) {
1074 SIPE_CORE_PRIVATE_FLAG_SET(REMOTE_USER);
1075 SIPE_DEBUG_INFO_NOFORMAT("ms-user-logon-data: RemoteUser (connected "
1076 "via Edge Server)");
1079 hdr = g_slist_next(hdr);
1082 /* rejoin open chats to be able to use them by continue to send messages */
1083 sipe_backend_chat_rejoin_all(SIPE_CORE_PUBLIC);
1085 /* subscriptions, done only once */
1086 if (!transport->subscribed) {
1087 sipe_subscription_self_events(sipe_private);
1088 transport->subscribed = TRUE;
1091 timeout = sipmsg_find_part_of_header(sipmsg_find_header(msg, "ms-keep-alive"),
1092 "timeout=", ";", NULL);
1093 if (timeout != NULL) {
1094 sscanf(timeout, "%u", &sipe_private->public.keepalive_timeout);
1095 SIPE_DEBUG_INFO("process_register_response: server determined keep alive timeout is %u seconds",
1096 sipe_private->public.keepalive_timeout);
1097 g_free(timeout);
1100 SIPE_DEBUG_INFO("process_register_response: got 200, removing CSeq: %d", transport->cseq);
1102 break;
1103 case 301:
1105 gchar *redirect = parse_from(sipmsg_find_header(msg, "Contact"));
1107 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully (with redirect)");
1109 if (redirect && (g_ascii_strncasecmp("sip:", redirect, 4) == 0)) {
1110 gchar **parts = g_strsplit(redirect + 4, ";", 0);
1111 gchar **tmp;
1112 gchar *hostname;
1113 int port = 0;
1114 guint transport_type = SIPE_TRANSPORT_TLS;
1115 int i = 1;
1117 tmp = g_strsplit(parts[0], ":", 0);
1118 hostname = g_strdup(tmp[0]);
1119 if (tmp[1]) port = strtoul(tmp[1], NULL, 10);
1120 g_strfreev(tmp);
1122 while (parts[i]) {
1123 tmp = g_strsplit(parts[i], "=", 0);
1124 if (tmp[1]) {
1125 if (g_ascii_strcasecmp("transport", tmp[0]) == 0) {
1126 if (g_ascii_strcasecmp("tcp", tmp[1]) == 0) {
1127 transport_type = SIPE_TRANSPORT_TCP;
1131 g_strfreev(tmp);
1132 i++;
1134 g_strfreev(parts);
1136 /* Close old connection */
1137 sipe_core_connection_cleanup(sipe_private);
1138 /* transport and sipe_private->transport are invalid after this */
1140 /* Create new connection */
1141 sipe_server_register(sipe_private, transport_type, hostname, port);
1142 /* sipe_private->transport has a new value */
1143 SIPE_DEBUG_INFO("process_register_response: redirected to host %s port %d transport %d",
1144 hostname, port, transport_type);
1146 g_free(redirect);
1148 break;
1149 case 401:
1151 const char *auth_hdr;
1153 SIPE_DEBUG_INFO("process_register_response: REGISTER retries %d", transport->registrar.retries);
1155 if (transport->reauthenticate_set) {
1156 SIPE_DEBUG_ERROR_NOFORMAT("process_register_response: RE-REGISTER rejected, triggering re-authentication");
1157 do_reauthenticate_cb(sipe_private, NULL);
1158 return TRUE;
1161 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1162 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake failed - giving up.");
1163 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1164 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
1165 _("Authentication failed"));
1166 return TRUE;
1169 auth_hdr = get_auth_header(sipe_private, &transport->registrar, msg);
1170 if (!auth_hdr) {
1171 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1172 SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
1173 _("Incompatible authentication scheme chosen"));
1174 return TRUE;
1176 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
1177 fill_auth(auth_hdr, &transport->registrar);
1178 transport->reregister_set = FALSE;
1179 transport->register_attempt = 0;
1180 do_register(sipe_private,
1181 sipe_backend_connection_is_disconnecting(SIPE_CORE_PUBLIC));
1183 break;
1184 case 403:
1186 gchar *reason;
1187 gchar *warning;
1188 sipmsg_parse_warning(msg, &reason);
1189 reason = reason ? reason : sipmsg_get_ms_diagnostics_public_reason(msg);
1190 warning = g_strdup_printf(_("You have been rejected by the server: %s"),
1191 reason ? reason : _("no reason given"));
1192 g_free(reason);
1194 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1195 SIPE_CONNECTION_ERROR_INVALID_SETTINGS,
1196 warning);
1197 g_free(warning);
1198 return TRUE;
1200 break;
1201 case 404:
1203 const gchar *diagnostics = sipmsg_find_header(msg, "ms-diagnostics");
1204 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1205 gchar *warning;
1206 warning = g_strdup_printf(_("Not found: %s. Please contact your Administrator"),
1207 diagnostics ? (reason ? reason : _("no reason given")) :
1208 _("SIP is either not enabled for the destination URI or it does not exist"));
1209 g_free(reason);
1211 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1212 SIPE_CONNECTION_ERROR_INVALID_USERNAME,
1213 warning);
1214 g_free(warning);
1215 return TRUE;
1217 break;
1218 case 504: /* Server time-out */
1219 /* first attempt + 5 retries */
1220 if (transport->register_attempt < 6) {
1221 SIPE_DEBUG_INFO("process_register_response: RE-REGISTER timeout on attempt %d, retrying later",
1222 transport->register_attempt);
1223 sip_transport_set_reregister(sipe_private, 60);
1224 return TRUE;
1226 /* FALLTHROUGH */
1227 case 503:
1229 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1230 gchar *warning;
1231 warning = g_strdup_printf(_("Service unavailable: %s"), reason ? reason : _("no reason given"));
1232 g_free(reason);
1234 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1235 SIPE_CONNECTION_ERROR_NETWORK,
1236 warning);
1237 g_free(warning);
1238 return TRUE;
1240 break;
1242 return TRUE;
1245 static gboolean register_response_timeout(struct sipe_core_private *sipe_private,
1246 SIPE_UNUSED_PARAMETER struct sipmsg *msg,
1247 SIPE_UNUSED_PARAMETER struct transaction *trans)
1249 struct sip_transport *transport = sipe_private->transport;
1250 if (transport->register_attempt < 6) {
1251 SIPE_DEBUG_INFO("register_response_timeout: no answer to attempt %d, retrying",
1252 transport->register_attempt);
1253 do_register(sipe_private, FALSE);
1254 } else {
1255 gchar *warning = g_strdup_printf(_("Service unavailable: %s"), _("no reason given"));
1256 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1257 SIPE_CONNECTION_ERROR_NETWORK,
1258 warning);
1259 g_free(warning);
1261 return TRUE;
1264 static void do_register(struct sipe_core_private *sipe_private,
1265 gboolean deregister)
1267 struct sip_transport *transport = sipe_private->transport;
1268 char *uri;
1269 char *to;
1270 char *hdr;
1271 char *uuid;
1273 if (!sipe_private->public.sip_domain) return;
1275 if (!deregister) {
1276 if (transport->reregister_set) {
1277 transport->reregister_set = FALSE;
1278 transport->register_attempt = 1;
1279 } else {
1280 transport->register_attempt++;
1284 transport->deregister = deregister;
1285 transport->auth_incomplete = FALSE;
1287 uuid = get_uuid(sipe_private);
1288 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"
1289 "Supported: gruu-10, adhoclist, msrtc-event-categories, com.microsoft.msrtc.presence\r\n"
1290 "Event: registration\r\n"
1291 "Allow-Events: presence\r\n"
1292 "ms-keep-alive: UAC;hop-hop=yes\r\n"
1293 "%s",
1294 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
1295 transport->connection->client_port,
1296 TRANSPORT_DESCRIPTOR,
1297 uuid,
1298 deregister ? "Expires: 0\r\n" : "");
1299 g_free(uuid);
1301 uri = sip_uri_from_name(sipe_private->public.sip_domain);
1302 to = sip_uri_self(sipe_private);
1303 sip_transport_request_timeout(sipe_private,
1304 "REGISTER",
1305 uri,
1307 hdr,
1309 NULL,
1310 process_register_response,
1312 deregister ? NULL : register_response_timeout);
1313 g_free(to);
1314 g_free(uri);
1315 g_free(hdr);
1317 if (deregister) {
1318 /* Make sure that all messages are pushed to the server
1319 before the connection gets shut down */
1320 SIPE_DEBUG_INFO_NOFORMAT("De-register from server. Flushing outstanding messages.");
1321 sipe_backend_transport_flush(transport->connection);
1325 void sip_transport_deregister(struct sipe_core_private *sipe_private)
1327 do_register(sipe_private, TRUE);
1330 void sip_transport_disconnect(struct sipe_core_private *sipe_private)
1332 struct sip_transport *transport = sipe_private->transport;
1334 /* transport can be NULL during connection setup */
1335 if (transport) {
1336 sipe_backend_transport_disconnect(transport->connection);
1338 sipe_auth_free(&transport->registrar);
1339 sipe_auth_free(&transport->proxy);
1341 g_free(transport->server_name);
1342 g_free(transport->server_version);
1343 g_free(transport->user_agent);
1345 while (transport->transactions)
1346 transactions_remove(sipe_private,
1347 transport->transactions->data);
1349 g_free(transport);
1352 sipe_private->transport = NULL;
1353 sipe_private->service_data = NULL;
1354 sipe_private->address_data = NULL;
1356 if (sipe_private->dns_query)
1357 sipe_backend_dns_query_cancel(sipe_private->dns_query);
1361 void sip_transport_authentication_completed(struct sipe_core_private *sipe_private)
1363 do_reauthenticate_cb(sipe_private, NULL);
1366 guint sip_transport_port(struct sipe_core_private *sipe_private)
1368 return sipe_private->transport->server_port;
1371 static void process_input_message(struct sipe_core_private *sipe_private,
1372 struct sipmsg *msg)
1374 struct sip_transport *transport = sipe_private->transport;
1375 gboolean notfound = FALSE;
1376 const char *method = msg->method ? msg->method : "NOT FOUND";
1378 SIPE_DEBUG_INFO("process_input_message: msg->response(%d),msg->method(%s)",
1379 msg->response, method);
1381 if (msg->response == 0) { /* request */
1382 if (sipe_strequal(method, "MESSAGE")) {
1383 process_incoming_message(sipe_private, msg);
1384 } else if (sipe_strequal(method, "NOTIFY")) {
1385 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_notify");
1386 process_incoming_notify(sipe_private, msg);
1387 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1388 } else if (sipe_strequal(method, "BENOTIFY")) {
1389 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_benotify");
1390 process_incoming_notify(sipe_private, msg);
1391 } else if (sipe_strequal(method, "INVITE")) {
1392 process_incoming_invite(sipe_private, msg);
1393 } else if (sipe_strequal(method, "REFER")) {
1394 process_incoming_refer(sipe_private, msg);
1395 } else if (sipe_strequal(method, "OPTIONS")) {
1396 process_incoming_options(sipe_private, msg);
1397 } else if (sipe_strequal(method, "INFO")) {
1398 process_incoming_info(sipe_private, msg);
1399 } else if (sipe_strequal(method, "ACK")) {
1400 /* ACK's don't need any response */
1401 } else if (sipe_strequal(method, "PRACK")) {
1402 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1403 } else if (sipe_strequal(method, "SUBSCRIBE")) {
1404 /* LCS 2005 sends us these - just respond 200 OK */
1405 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1406 } else if (sipe_strequal(method, "CANCEL")) {
1407 process_incoming_cancel(sipe_private, msg);
1408 } else if (sipe_strequal(method, "BYE")) {
1409 process_incoming_bye(sipe_private, msg);
1410 } else {
1411 sip_transport_response(sipe_private, msg, 501, "Not implemented", NULL);
1412 notfound = TRUE;
1415 } else { /* response */
1416 struct transaction *trans = transactions_find(transport, msg);
1417 if (trans) {
1418 if (msg->response < 200) {
1419 /* ignore provisional response */
1420 SIPE_DEBUG_INFO("process_input_message: got provisional (%d) response, ignoring", msg->response);
1422 /* Transaction not yet completed */
1423 trans = NULL;
1425 } else if (msg->response == 401) { /* Unauthorized */
1427 if (sipe_strequal(trans->msg->method, "REGISTER")) {
1428 /* Expected response during authentication handshake */
1429 transport->registrar.retries++;
1430 SIPE_DEBUG_INFO("process_input_message: RE-REGISTER CSeq: %d", transport->cseq);
1431 } else {
1432 gchar *resend;
1434 /* Are we registered? */
1435 if (transport->reregister_set) {
1436 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Retrying with new authentication.");
1437 sipmsg_remove_header_now(trans->msg, "Authorization");
1438 sign_outgoing_message(sipe_private,
1439 trans->msg);
1440 } else {
1442 * We don't have a valid authentication at the moment.
1443 * Resend message unchanged. It will be rejected again
1444 * and hopefully by then we have a valid authentication.
1446 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Bouncing...");
1449 /* Resend request */
1450 resend = sipmsg_to_string(trans->msg);
1451 sipe_utils_message_debug("SIP", resend, NULL, TRUE);
1452 sipe_backend_transport_message(sipe_private->transport->connection, resend);
1453 g_free(resend);
1455 /* Transaction not yet completed */
1456 trans = NULL;
1459 } else if (msg->response == 407) { /* Proxy Authentication Required */
1461 if (transport->proxy.retries++ <= 30) {
1462 const gchar *proxy_hdr = sipmsg_find_header(msg, "Proxy-Authenticate");
1464 if (proxy_hdr) {
1465 gchar *auth = NULL;
1467 if (!g_ascii_strncasecmp(proxy_hdr, "Digest", 6)) {
1468 auth = sip_sec_digest_authorization(sipe_private,
1469 proxy_hdr + 7,
1470 msg->method,
1471 msg->target);
1472 } else {
1473 guint i;
1475 transport->proxy.type = SIPE_AUTHENTICATION_TYPE_UNSET;
1476 for (i = 0; i < AUTH_PROTOCOLS; i++) {
1477 const gchar *protocol = auth_type_to_protocol[i];
1478 if (protocol &&
1479 !g_ascii_strncasecmp(proxy_hdr, protocol, strlen(protocol))) {
1480 SIPE_DEBUG_INFO("process_input_message: proxy authentication scheme '%s'", protocol);
1481 transport->proxy.type = i;
1482 transport->proxy.protocol = protocol;
1483 fill_auth(proxy_hdr, &transport->proxy);
1484 auth = auth_header(sipe_private, &transport->proxy, trans->msg);
1485 break;
1490 if (auth) {
1491 gchar *resend;
1493 /* replace old proxy authentication with new one */
1494 sipmsg_remove_header_now(trans->msg, "Proxy-Authorization");
1495 sipmsg_add_header_now(trans->msg, "Proxy-Authorization", auth);
1496 g_free(auth);
1498 /* resend request with proxy authentication */
1499 resend = sipmsg_to_string(trans->msg);
1500 sipe_utils_message_debug("SIP", resend, NULL, TRUE);
1501 sipe_backend_transport_message(sipe_private->transport->connection, resend);
1502 g_free(resend);
1504 /* Transaction not yet completed */
1505 trans = NULL;
1507 } else
1508 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: can't generate proxy authentication. Giving up.");
1509 } else
1510 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: 407 response without 'Proxy-Authenticate' header. Giving up.");
1511 } else
1512 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: too many proxy authentication retries. Giving up.");
1514 } else {
1515 transport->registrar.retries = 0;
1516 transport->proxy.retries = 0;
1519 /* Is transaction completed? */
1520 if (trans) {
1521 if (trans->callback) {
1522 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: we have a transaction callback");
1523 /* call the callback to process response */
1524 (trans->callback)(sipe_private, msg, trans);
1525 /* transport && trans no longer valid after redirect */
1529 * Redirect case: sipe_private->transport is
1530 * the new transport with empty queue
1532 if (sipe_private->transport->transactions) {
1533 SIPE_DEBUG_INFO("process_input_message: removing CSeq %d", transport->cseq);
1534 transactions_remove(sipe_private, trans);
1537 } else {
1538 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: received response to unknown transaction");
1539 notfound = TRUE;
1543 if (notfound) {
1544 SIPE_DEBUG_INFO("received a unknown sip message with method %s and response %d", method, msg->response);
1548 static void sip_transport_input(struct sipe_transport_connection *conn)
1550 struct sipe_core_private *sipe_private = conn->user_data;
1551 struct sip_transport *transport = sipe_private->transport;
1552 gchar *cur = conn->buffer;
1554 /* according to the RFC remove CRLF at the beginning */
1555 while (*cur == '\r' || *cur == '\n') {
1556 cur++;
1558 if (cur != conn->buffer)
1559 sipe_utils_shrink_buffer(conn, cur);
1561 /* Received a full Header? */
1562 transport->processing_input = TRUE;
1563 while (transport->processing_input &&
1564 ((cur = strstr(conn->buffer, "\r\n\r\n")) != NULL)) {
1565 struct sipmsg *msg;
1566 guint remainder;
1568 cur += 2;
1569 cur[0] = '\0';
1570 msg = sipmsg_parse_header(conn->buffer);
1572 cur += 2;
1573 remainder = conn->buffer_used - (cur - conn->buffer);
1574 if (msg && remainder >= (guint) msg->bodylen) {
1575 char *dummy = g_malloc(msg->bodylen + 1);
1576 memcpy(dummy, cur, msg->bodylen);
1577 dummy[msg->bodylen] = '\0';
1578 msg->body = dummy;
1579 cur += msg->bodylen;
1580 sipe_utils_message_debug("SIP",
1581 conn->buffer,
1582 msg->body,
1583 FALSE);
1584 sipe_utils_shrink_buffer(conn, cur);
1585 } else {
1586 if (msg){
1587 SIPE_DEBUG_INFO("sipe_transport_input: body too short (%d < %d, strlen %d) - ignoring message", remainder, msg->bodylen, (int)strlen(conn->buffer));
1588 sipmsg_free(msg);
1591 /* restore header for next try */
1592 cur[-2] = '\r';
1593 return;
1596 // Verify the signature before processing it
1597 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1598 struct sipmsg_breakdown msgbd;
1599 gchar *signature_input_str;
1600 gchar *rspauth;
1601 msgbd.msg = msg;
1602 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
1603 transport->registrar.protocol);
1604 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
1606 rspauth = sipmsg_find_part_of_header(sipmsg_find_header(msg, "Authentication-Info"), "rspauth=\"", "\"", NULL);
1608 if (rspauth != NULL) {
1609 if (sip_sec_verify_signature(transport->registrar.gssapi_context, signature_input_str, rspauth)) {
1610 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message validated");
1611 process_input_message(sipe_private, msg);
1612 /* transport is invalid after redirect */
1613 } else {
1614 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message is invalid.");
1615 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1616 SIPE_CONNECTION_ERROR_NETWORK,
1617 _("Invalid message signature received"));
1619 } else if ((msg->response == 401) ||
1620 sipe_strequal(msg->method, "REGISTER")) {
1621 /* a) Retry non-REGISTER requests with updated authentication */
1622 /* b) We must always process REGISTER responses */
1623 process_input_message(sipe_private, msg);
1624 } else {
1625 /* OCS sends provisional messages that are *not* signed */
1626 if (msg->response >= 200) {
1627 /* We are not calling process_input_message(),
1628 so we need to drop the transaction here. */
1629 struct transaction *trans = transactions_find(transport, msg);
1630 if (trans) transactions_remove(sipe_private, trans);
1632 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: message without authentication data - ignoring");
1634 g_free(signature_input_str);
1636 g_free(rspauth);
1637 sipmsg_breakdown_free(&msgbd);
1638 } else {
1639 process_input_message(sipe_private, msg);
1642 sipmsg_free(msg);
1644 /* Redirect: old content of "transport" & "conn" is no longer valid */
1645 transport = sipe_private->transport;
1646 conn = transport->connection;
1650 static void sip_transport_connected(struct sipe_transport_connection *conn)
1652 struct sipe_core_private *sipe_private = conn->user_data;
1653 sipe_private->service_data = NULL;
1654 sipe_private->address_data = NULL;
1655 do_register(sipe_private, FALSE);
1658 static void resolve_next_service(struct sipe_core_private *sipe_private,
1659 const struct sip_service_data *start);
1660 static void resolve_next_address(struct sipe_core_private *sipe_private,
1661 gboolean initial);
1662 static void sip_transport_error(struct sipe_transport_connection *conn,
1663 const gchar *msg)
1665 struct sipe_core_private *sipe_private = conn->user_data;
1667 /* This failed attempt was based on a DNS SRV record */
1668 if (sipe_private->service_data) {
1669 resolve_next_service(sipe_private, NULL);
1670 /* This failed attempt was based on a DNS A record */
1671 } else if (sipe_private->address_data) {
1672 resolve_next_address(sipe_private, FALSE);
1673 } else {
1674 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1675 SIPE_CONNECTION_ERROR_NETWORK,
1676 msg);
1680 /* server_name must be g_alloc()'ed */
1681 static void sipe_server_register(struct sipe_core_private *sipe_private,
1682 guint type,
1683 gchar *server_name,
1684 guint server_port)
1686 sipe_connect_setup setup = {
1687 type,
1688 server_name,
1689 (server_port != 0) ? server_port :
1690 (type == SIPE_TRANSPORT_TLS) ? 5061 : 5060,
1691 sipe_private,
1692 sip_transport_connected,
1693 sip_transport_input,
1694 sip_transport_error
1696 struct sip_transport *transport = g_new0(struct sip_transport, 1);
1698 transport->server_name = server_name;
1699 transport->server_port = setup.server_port;
1700 transport->connection = sipe_backend_transport_connect(SIPE_CORE_PUBLIC,
1701 &setup);
1702 sipe_private->transport = transport;
1705 struct sip_service_data {
1706 const char *protocol;
1707 const char *transport;
1708 guint type;
1712 * Autodiscover using DNS SRV records. See RFC2782/3263
1714 * Service list for AUTO
1716 static const struct sip_service_data service_autodetect[] = {
1717 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1718 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1719 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1720 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1721 { NULL, NULL, 0 }
1724 /* Service list for SSL/TLS */
1725 static const struct sip_service_data service_tls[] = {
1726 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1727 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1728 { NULL, NULL, 0 }
1731 /* Service list for TCP */
1732 static const struct sip_service_data service_tcp[] = {
1733 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1734 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1735 { NULL, NULL, 0 }
1738 static const struct sip_service_data *services[] = {
1739 service_autodetect, /* SIPE_TRANSPORT_AUTO */
1740 service_tls, /* SIPE_TRANSPORT_TLS */
1741 service_tcp /* SIPE_TRANSPORT_TCP */
1744 struct sip_address_data {
1745 const char *prefix;
1746 guint port;
1750 * Autodiscover using DNS A records. This is an extension addded
1751 * by Microsoft. See http://support.microsoft.com/kb/2619522
1753 static const struct sip_address_data addresses[] = {
1754 { "sipinternal", 5061 },
1755 { "sipexternal", 443 },
1757 * Our implementation supports only one port per host name. If the host name
1758 * resolves OK, we abort the search and try to connect. If we would know if we
1759 * are trying to connect from "Intranet" or "Internet" then we could choose
1760 * between those two ports.
1762 * We drop port 5061 in order to cover the "Internet" case.
1764 * { "sip", 5061 },
1766 { "sip", 443 },
1767 { NULL, 0 }
1770 static void sipe_core_dns_resolved(struct sipe_core_public *sipe_public,
1771 const gchar *hostname, guint port)
1773 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1774 gboolean service = sipe_private->service_data != NULL;
1776 sipe_private->dns_query = NULL;
1778 if (hostname) {
1779 gchar *host;
1780 guint type;
1782 if (service) {
1783 host = g_strdup(hostname);
1784 type = sipe_private->service_data->type;
1785 } else {
1786 /* DNS A resolver returns an IP address */
1787 host = g_strdup_printf("%s.%s",
1788 sipe_private->address_data->prefix,
1789 sipe_private->public.sip_domain);
1790 port = sipe_private->address_data->port;
1791 type = sipe_private->transport_type;
1792 if (type == SIPE_TRANSPORT_AUTO)
1793 type = SIPE_TRANSPORT_TLS;
1796 SIPE_DEBUG_INFO("sipe_core_dns_resolved - %s hostname: %s port: %d",
1797 service ? "SRV" : "A", hostname, port);
1798 sipe_server_register(sipe_private, type, host, port);
1799 } else {
1800 if (service)
1801 resolve_next_service(SIPE_CORE_PRIVATE, NULL);
1802 else
1803 resolve_next_address(SIPE_CORE_PRIVATE, FALSE);
1807 static void resolve_next_service(struct sipe_core_private *sipe_private,
1808 const struct sip_service_data *start)
1810 if (start) {
1811 sipe_private->service_data = start;
1812 } else {
1813 sipe_private->service_data++;
1814 if (sipe_private->service_data->protocol == NULL) {
1816 /* We tried all services */
1817 sipe_private->service_data = NULL;
1819 /* Try A records list next */
1820 SIPE_DEBUG_INFO_NOFORMAT("no SRV records found; trying A records next");
1821 resolve_next_address(sipe_private, TRUE);
1822 return;
1826 /* Try to resolve next service */
1827 sipe_private->dns_query = sipe_backend_dns_query_srv(
1828 SIPE_CORE_PUBLIC,
1829 sipe_private->service_data->protocol,
1830 sipe_private->service_data->transport,
1831 sipe_private->public.sip_domain,
1832 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
1833 SIPE_CORE_PUBLIC);
1836 static void resolve_next_address(struct sipe_core_private *sipe_private,
1837 gboolean initial)
1839 gchar *hostname;
1841 if (initial) {
1842 sipe_private->address_data = addresses;
1843 } else {
1844 sipe_private->address_data++;
1845 if (sipe_private->address_data->prefix == NULL) {
1846 guint type = sipe_private->transport_type;
1848 /* We tried all addresss */
1849 sipe_private->address_data = NULL;
1851 /* Try connecting to the SIP hostname directly */
1852 SIPE_DEBUG_INFO_NOFORMAT("no SRV or A records found; using SIP domain as fallback");
1853 if (type == SIPE_TRANSPORT_AUTO)
1854 type = SIPE_TRANSPORT_TLS;
1856 sipe_server_register(sipe_private, type,
1857 g_strdup(sipe_private->public.sip_domain),
1859 return;
1863 /* Try to resolve next address */
1864 hostname = g_strdup_printf("%s.%s",
1865 sipe_private->address_data->prefix,
1866 sipe_private->public.sip_domain);
1867 sipe_private->dns_query = sipe_backend_dns_query_a(
1868 SIPE_CORE_PUBLIC,
1869 hostname,
1870 sipe_private->address_data->port,
1871 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
1872 SIPE_CORE_PUBLIC);
1873 g_free(hostname);
1877 * NOTE: this function can be called before sipe_core_allocate()!
1879 gboolean sipe_core_transport_sip_requires_password(guint authentication,
1880 gboolean sso)
1882 return(sip_sec_requires_password(authentication, sso));
1885 void sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public,
1886 guint transport,
1887 guint authentication,
1888 const gchar *server,
1889 const gchar *port)
1891 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1893 /* backend initialization is complete */
1894 sipe_core_backend_initialized(sipe_private, authentication);
1897 * Initializing the certificate sub-system will trigger the generation
1898 * of a cryptographic key pair which takes time. If we do this after we
1899 * have connected to the server then there is a risk that we run into a
1900 * SIP connection timeout. So let's get this out of the way now...
1902 * This is currently only needed if the user has selected TLS-DSK.
1904 if (sipe_private->authentication_type == SIPE_AUTHENTICATION_TYPE_TLS_DSK)
1905 sipe_certificate_init(sipe_private);
1907 if (server) {
1908 /* Use user specified server[:port] */
1909 int port_number = 0;
1911 if (port)
1912 port_number = atoi(port);
1914 SIPE_DEBUG_INFO("sipe_core_connect: user specified SIP server %s:%d",
1915 server, port_number);
1917 sipe_server_register(sipe_private, transport,
1918 g_strdup(server), port_number);
1919 } else {
1920 /* Server auto-discovery */
1922 /* Remember user specified transport type */
1923 sipe_private->transport_type = transport;
1924 resolve_next_service(sipe_private, services[transport]);
1928 void sipe_core_transport_sip_keepalive(struct sipe_core_public *sipe_public)
1930 SIPE_DEBUG_INFO("sending keep alive %d",
1931 sipe_public->keepalive_timeout);
1932 sipe_utils_message_debug("SIP", "", NULL, TRUE);
1933 sipe_backend_transport_message(SIPE_CORE_PRIVATE->transport->connection,
1934 "\r\n\r\n");
1937 const gchar *sipe_core_transport_sip_server_name(struct sipe_core_public *sipe_public)
1939 struct sip_transport *transport = SIPE_CORE_PRIVATE->transport;
1940 return(transport ? transport->server_name : NULL);
1943 int sip_transaction_cseq(struct transaction *trans)
1945 int cseq;
1947 g_return_val_if_fail(trans && trans->key, 0);
1949 sscanf(trans->key, "<%*[a-zA-Z0-9]><%d INVITE>", &cseq);
1950 return cseq;
1954 Local Variables:
1955 mode: c
1956 c-file-style: "bsd"
1957 indent-tabs-mode: t
1958 tab-width: 8
1959 End: