transport: fix potential memory leak when signing message
[siplcs.git] / src / core / sip-transport.c
blob573c4564d91b37048fe9b07343dd08682da153a8
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 guint keepalive_timeout;
113 time_t last_message;
115 gboolean processing_input; /* whether full header received */
116 gboolean auth_incomplete; /* whether authentication not completed */
117 gboolean reregister_set; /* whether reregister timer set */
118 gboolean reauthenticate_set; /* whether reauthenticate timer set */
119 gboolean subscribed; /* whether subscribed to events, except buddies presence */
120 gboolean deregister; /* whether in deregistration */
123 /* Keep in sync with sipe_transport_type! */
124 static const char *transport_descriptor[] = { "", "tls", "tcp"};
125 #define TRANSPORT_DESCRIPTOR (transport_descriptor[transport->connection->type])
127 static char *genbranch()
129 return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X",
130 rand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,
131 rand() & 0xFFFF, rand() & 0xFFFF);
134 static void sipe_auth_free(struct sip_auth *auth)
136 g_free(auth->opaque);
137 auth->opaque = NULL;
138 auth->protocol = NULL;
139 g_free(auth->realm);
140 auth->realm = NULL;
141 g_free(auth->sts_uri);
142 auth->sts_uri = NULL;
143 g_free(auth->target);
144 auth->target = NULL;
145 auth->version = 0;
146 auth->type = SIPE_AUTHENTICATION_TYPE_UNSET;
147 auth->retries = 0;
148 auth->expires = 0;
149 g_free(auth->gssapi_data);
150 auth->gssapi_data = NULL;
151 sip_sec_destroy_context(auth->gssapi_context);
152 auth->gssapi_context = NULL;
155 static void sipe_make_signature(struct sipe_core_private *sipe_private,
156 struct sipmsg *msg)
158 struct sip_transport *transport = sipe_private->transport;
159 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
160 struct sipmsg_breakdown msgbd;
161 gchar *signature_input_str;
162 msgbd.msg = msg;
163 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
164 transport->registrar.protocol);
165 msgbd.rand = g_strdup_printf("%08x", g_random_int());
166 transport->registrar.ntlm_num++;
167 msgbd.num = g_strdup_printf("%d", transport->registrar.ntlm_num);
168 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
169 if (signature_input_str != NULL) {
170 char *signature_hex = sip_sec_make_signature(transport->registrar.gssapi_context, signature_input_str);
171 g_free(msg->signature);
172 msg->signature = signature_hex;
173 g_free(msg->rand);
174 msg->rand = g_strdup(msgbd.rand);
175 g_free(msg->num);
176 msg->num = g_strdup(msgbd.num);
177 g_free(signature_input_str);
179 sipmsg_breakdown_free(&msgbd);
183 static const gchar *const auth_type_to_protocol[] = {
184 NULL, /* SIPE_AUTHENTICATION_TYPE_UNSET */
185 NULL, /* SIPE_AUTHENTICATION_TYPE_BASIC */
186 "NTLM", /* SIPE_AUTHENTICATION_TYPE_NTLM */
187 "Kerberos", /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
188 NULL, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
189 "TLS-DSK", /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
191 #define AUTH_PROTOCOLS (sizeof(auth_type_to_protocol)/sizeof(gchar *))
193 static gchar *msg_signature_to_auth(struct sip_auth *auth,
194 struct sipmsg *msg)
196 return(g_strdup_printf("%s qop=\"auth\", opaque=\"%s\", realm=\"%s\", targetname=\"%s\", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
197 auth->protocol,
198 auth->opaque, auth->realm, auth->target,
199 msg->rand, msg->num, msg->signature));
202 static gchar *initialize_auth_context(struct sipe_core_private *sipe_private,
203 struct sip_auth *auth,
204 struct sipmsg *msg)
206 struct sip_transport *transport = sipe_private->transport;
207 gchar *ret;
208 gchar *gssapi_data = NULL;
209 gchar *sign_str;
210 gchar *gssapi_str;
211 gchar *opaque_str;
212 gchar *version_str;
215 * If transport is de-registering when we reach this point then we
216 * are in the middle of the previous authentication context setup
217 * attempt. So we shouldn't try another attempt.
219 if (transport->deregister)
220 return NULL;
222 /* Create security context or handshake continuation? */
223 if (auth->gssapi_context) {
224 /* Perform next step in authentication handshake */
225 gboolean status = sip_sec_init_context_step(auth->gssapi_context,
226 auth->target,
227 auth->gssapi_data,
228 &gssapi_data,
229 &auth->expires);
231 /* If authentication is completed gssapi_data can be NULL */
232 if (!(status &&
233 (sip_sec_context_is_ready(auth->gssapi_context) || gssapi_data))) {
234 SIPE_DEBUG_ERROR_NOFORMAT("initialize_auth_context: security context continuation failed");
235 g_free(gssapi_data);
236 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
237 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
238 _("Failed to authenticate to server"));
239 return NULL;
242 } else {
243 /* Create security context */
244 gpointer password = sipe_private->password;
246 /* For TLS-DSK the "password" is a certificate */
247 if (auth->type == SIPE_AUTHENTICATION_TYPE_TLS_DSK) {
248 password = sipe_certificate_tls_dsk_find(sipe_private,
249 auth->target);
251 if (!password) {
252 if (auth->sts_uri) {
253 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK Certificate Provisioning URI %s",
254 auth->sts_uri);
255 if (!sipe_certificate_tls_dsk_generate(sipe_private,
256 auth->target,
257 auth->sts_uri)) {
258 gchar *tmp = g_strdup_printf(_("Can't request certificate from %s"),
259 auth->sts_uri);
260 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
261 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
262 tmp);
263 g_free(tmp);
265 } else {
266 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
267 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
268 _("No URI for certificate provisioning service provided"));
271 /* we can't authenticate the message yet */
272 transport->auth_incomplete = TRUE;
274 return(NULL);
275 } else {
276 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK certificate for target '%s' found.",
277 auth->target);
281 auth->gssapi_context = sip_sec_create_context(auth->type,
282 SIPE_CORE_PRIVATE_FLAG_IS(SSO),
283 FALSE, /* connection-less for SIP */
284 sipe_private->authdomain ? sipe_private->authdomain : "",
285 sipe_private->authuser,
286 password);
288 if (auth->gssapi_context) {
289 sip_sec_init_context_step(auth->gssapi_context,
290 auth->target,
291 NULL,
292 &gssapi_data,
293 &(auth->expires));
296 if (!gssapi_data || !auth->gssapi_context) {
297 g_free(gssapi_data);
298 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
299 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
300 _("Failed to authenticate to server"));
301 return NULL;
305 if ((auth->version > 3) &&
306 sip_sec_context_is_ready(auth->gssapi_context)) {
307 sipe_make_signature(sipe_private, msg);
308 sign_str = g_strdup_printf(", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
309 msg->rand, msg->num, msg->signature);
310 } else {
311 sign_str = g_strdup("");
314 if (gssapi_data) {
315 gssapi_str = g_strdup_printf(", gssapi-data=\"%s\"",
316 gssapi_data);
317 g_free(gssapi_data);
318 } else {
319 gssapi_str = g_strdup("");
322 opaque_str = auth->opaque ? g_strdup_printf(", opaque=\"%s\"", auth->opaque) : g_strdup("");
324 if (auth->version > 2) {
325 version_str = g_strdup_printf(", version=%d", auth->version);
326 } else {
327 version_str = g_strdup("");
330 ret = g_strdup_printf("%s qop=\"auth\"%s, realm=\"%s\", targetname=\"%s\"%s%s%s",
331 auth->protocol, opaque_str,
332 auth->realm, auth->target,
333 gssapi_str, version_str, sign_str);
334 g_free(version_str);
335 g_free(opaque_str);
336 g_free(gssapi_str);
337 g_free(sign_str);
339 return(ret);
342 static gchar *auth_header(struct sipe_core_private *sipe_private,
343 struct sip_auth *auth,
344 struct sipmsg *msg)
346 gchar *ret = NULL;
349 * If the message is already signed then we have an authentication
350 * context, i.e. the authentication handshake is complete. Generate
351 * authentication header from message signature.
353 if (msg->signature) {
354 ret = msg_signature_to_auth(auth, msg);
357 * We should reach this point only when the authentication context
358 * needs to be initialized.
360 } else {
361 ret = initialize_auth_context(sipe_private, auth, msg);
364 return(ret);
367 static void fill_auth(const gchar *hdr, struct sip_auth *auth)
369 const gchar *param;
371 /* skip authentication identifier */
372 hdr = strchr(hdr, ' ');
373 if (!hdr) {
374 SIPE_DEBUG_ERROR_NOFORMAT("fill_auth: corrupted authentication header");
375 return;
377 while (*hdr == ' ')
378 hdr++;
380 /* start of next parameter value */
381 while ((param = strchr(hdr, '=')) != NULL) {
382 const gchar *end;
384 /* parameter value type */
385 param++;
386 if (*param == '"') {
387 /* string: xyz="..."(,) */
388 end = strchr(++param, '"');
389 if (!end) {
390 SIPE_DEBUG_ERROR("fill_auth: corrupted string parameter near '%s'", hdr);
391 break;
393 } else {
394 /* number: xyz=12345(,) */
395 end = strchr(param, ',');
396 if (!end) {
397 /* last parameter */
398 end = param + strlen(param);
402 #if 0
403 SIPE_DEBUG_INFO("fill_auth: hdr '%s'", hdr);
404 SIPE_DEBUG_INFO("fill_auth: param '%s'", param);
405 SIPE_DEBUG_INFO("fill_auth: end '%s'", end);
406 #endif
408 /* parameter type */
409 if (g_str_has_prefix(hdr, "gssapi-data=\"")) {
410 g_free(auth->gssapi_data);
411 auth->gssapi_data = g_strndup(param, end - param);
412 } else if (g_str_has_prefix(hdr, "opaque=\"")) {
413 g_free(auth->opaque);
414 auth->opaque = g_strndup(param, end - param);
415 } else if (g_str_has_prefix(hdr, "realm=\"")) {
416 g_free(auth->realm);
417 auth->realm = g_strndup(param, end - param);
418 } else if (g_str_has_prefix(hdr, "sts-uri=\"")) {
419 /* Only used with SIPE_AUTHENTICATION_TYPE_TLS_DSK */
420 g_free(auth->sts_uri);
421 auth->sts_uri = g_strndup(param, end - param);
422 } else if (g_str_has_prefix(hdr, "targetname=\"")) {
423 g_free(auth->target);
424 auth->target = g_strndup(param, end - param);
425 } else if (g_str_has_prefix(hdr, "version=")) {
426 auth->version = atoi(param);
429 /* skip to next parameter */
430 while ((*end == '"') || (*end == ',') || (*end == ' '))
431 end++;
432 hdr = end;
435 return;
438 static void sign_outgoing_message(struct sipe_core_private *sipe_private,
439 struct sipmsg *msg)
441 struct sip_transport *transport = sipe_private->transport;
442 gchar *buf;
444 if (transport->registrar.type == SIPE_AUTHENTICATION_TYPE_UNSET) {
445 return;
448 sipe_make_signature(sipe_private, msg);
450 buf = auth_header(sipe_private, &transport->registrar, msg);
451 if (buf) {
452 sipmsg_add_header_now(msg, "Authorization", buf);
453 g_free(buf);
457 static const gchar *sip_transport_user_agent(struct sipe_core_private *sipe_private)
459 struct sip_transport *transport = sipe_private->transport;
461 if (!transport->user_agent) {
462 const gchar *useragent = sipe_backend_setting(SIPE_CORE_PUBLIC,
463 SIPE_SETTING_USER_AGENT);
464 if (is_empty(useragent)) {
465 /*@TODO: better approach to define _user_ OS, it's version and host architecture */
466 /* ref: lzodefs.h */
467 #if defined(__linux__) || defined(__linux) || defined(__LINUX__)
468 #define SIPE_TARGET_PLATFORM "linux"
469 #elif defined(__NetBSD__) ||defined( __OpenBSD__) || defined(__FreeBSD__)
470 #define SIPE_TARGET_PLATFORM "bsd"
471 #elif defined(__APPLE__) || defined(__MACOS__)
472 #define SIPE_TARGET_PLATFORM "macosx"
473 #elif defined(_AIX) || defined(__AIX__) || defined(__aix__)
474 #define SIPE_TARGET_PLATFORM "aix"
475 #elif defined(__solaris__) || defined(__sun)
476 #define SIPE_TARGET_PLATFORM "sun"
477 #elif defined(_WIN32)
478 #define SIPE_TARGET_PLATFORM "win"
479 #elif defined(__CYGWIN__)
480 #define SIPE_TARGET_PLATFORM "cygwin"
481 #elif defined(__hpux__)
482 #define SIPE_TARGET_PLATFORM "hpux"
483 #elif defined(__sgi__)
484 #define SIPE_TARGET_PLATFORM "irix"
485 #else
486 #define SIPE_TARGET_PLATFORM "unknown"
487 #endif
489 #if defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
490 #define SIPE_TARGET_ARCH "x86_64"
491 #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
492 #define SIPE_TARGET_ARCH "i386"
493 #elif defined(__ppc64__)
494 #define SIPE_TARGET_ARCH "ppc64"
495 #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
496 #define SIPE_TARGET_ARCH "ppc"
497 #elif defined(__hppa__) || defined(__hppa)
498 #define SIPE_TARGET_ARCH "hppa"
499 #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
500 #define SIPE_TARGET_ARCH "mips"
501 #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
502 #define SIPE_TARGET_ARCH "s390"
503 #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
504 #define SIPE_TARGET_ARCH "sparc"
505 #elif defined(__arm__)
506 #define SIPE_TARGET_ARCH "arm"
507 #else
508 #define SIPE_TARGET_ARCH "other"
509 #endif
510 gchar *backend = sipe_backend_version();
511 transport->user_agent = g_strdup_printf("%s Sipe/" PACKAGE_VERSION " (" SIPE_TARGET_PLATFORM "-" SIPE_TARGET_ARCH "; %s)",
512 backend,
513 transport->server_version ? transport->server_version : "");
514 g_free(backend);
515 } else {
516 transport->user_agent = g_strdup(useragent);
519 return(transport->user_agent);
523 * NOTE: Do *NOT* call sipe_backend_transport_message(...) directly!
525 * All SIP messages must pass through this function in order to update
526 * the timestamp for keepalive tracking.
528 static void send_sip_message(struct sip_transport *transport,
529 const gchar *string)
531 sipe_utils_message_debug("SIP", string, NULL, TRUE);
532 transport->last_message = time(NULL);
533 sipe_backend_transport_message(transport->connection, string);
536 static void start_keepalive_timer(struct sipe_core_private *sipe_private,
537 guint seconds);
538 static void keepalive_timeout(struct sipe_core_private *sipe_private,
539 SIPE_UNUSED_PARAMETER gpointer data)
541 struct sip_transport *transport = sipe_private->transport;
542 if (transport) {
543 guint since_last = time(NULL) - transport->last_message;
544 guint restart = transport->keepalive_timeout;
545 if (since_last >= restart) {
546 SIPE_DEBUG_INFO("keepalive_timeout: expired %d", restart);
547 send_sip_message(transport, "\r\n\r\n");
548 } else {
549 /* timeout not reached since last message -> reschedule */
550 restart -= since_last;
552 start_keepalive_timer(sipe_private, restart);
556 static void start_keepalive_timer(struct sipe_core_private *sipe_private,
557 guint seconds)
559 sipe_schedule_seconds(sipe_private,
560 "<+keepalive-timeout>",
561 NULL,
562 seconds,
563 keepalive_timeout,
564 NULL);
567 void sip_transport_response(struct sipe_core_private *sipe_private,
568 struct sipmsg *msg,
569 guint code,
570 const char *text,
571 const char *body)
573 gchar *name;
574 gchar *value;
575 GString *outstr = g_string_new("");
576 gchar *contact;
577 GSList *tmp;
578 const gchar *keepers[] = { "To", "From", "Call-ID", "CSeq", "Via", "Record-Route", NULL };
580 /* Can return NULL! */
581 contact = get_contact(sipe_private);
582 if (contact) {
583 sipmsg_add_header(msg, "Contact", contact);
584 g_free(contact);
587 if (body) {
588 gchar *len = g_strdup_printf("%" G_GSIZE_FORMAT , (gsize) strlen(body));
589 sipmsg_add_header(msg, "Content-Length", len);
590 g_free(len);
591 } else {
592 sipmsg_add_header(msg, "Content-Length", "0");
595 sipmsg_add_header(msg, "User-Agent", sip_transport_user_agent(sipe_private));
597 msg->response = code;
599 sipmsg_strip_headers(msg, keepers);
600 sipmsg_merge_new_headers(msg);
601 sign_outgoing_message(sipe_private, msg);
603 g_string_append_printf(outstr, "SIP/2.0 %d %s\r\n", code, text);
604 tmp = msg->headers;
605 while (tmp) {
606 name = ((struct sipnameval*) (tmp->data))->name;
607 value = ((struct sipnameval*) (tmp->data))->value;
609 g_string_append_printf(outstr, "%s: %s\r\n", name, value);
610 tmp = g_slist_next(tmp);
612 g_string_append_printf(outstr, "\r\n%s", body ? body : "");
613 send_sip_message(sipe_private->transport, outstr->str);
614 g_string_free(outstr, TRUE);
617 static void transactions_remove(struct sipe_core_private *sipe_private,
618 struct transaction *trans)
620 struct sip_transport *transport = sipe_private->transport;
621 if (transport->transactions) {
622 transport->transactions = g_slist_remove(transport->transactions,
623 trans);
624 SIPE_DEBUG_INFO("SIP transactions count:%d after removal", g_slist_length(transport->transactions));
626 if (trans->msg) sipmsg_free(trans->msg);
627 if (trans->payload) {
628 if (trans->payload->destroy)
629 (*trans->payload->destroy)(trans->payload->data);
630 g_free(trans->payload);
632 g_free(trans->key);
633 if (trans->timeout_key) {
634 sipe_schedule_cancel(sipe_private, trans->timeout_key);
635 g_free(trans->timeout_key);
637 g_free(trans);
641 static struct transaction *transactions_find(struct sip_transport *transport,
642 struct sipmsg *msg)
644 GSList *transactions = transport->transactions;
645 const gchar *call_id = sipmsg_find_header(msg, "Call-ID");
646 const gchar *cseq = sipmsg_find_header(msg, "CSeq");
647 gchar *key;
649 if (!call_id || !cseq) {
650 SIPE_DEBUG_ERROR_NOFORMAT("transaction_find: no Call-ID or CSeq!");
651 return NULL;
654 key = g_strdup_printf("<%s><%s>", call_id, cseq);
655 while (transactions) {
656 struct transaction *trans = transactions->data;
657 if (!g_ascii_strcasecmp(trans->key, key)) {
658 g_free(key);
659 return trans;
661 transactions = transactions->next;
663 g_free(key);
665 return NULL;
668 static void transaction_timeout_cb(struct sipe_core_private *sipe_private,
669 gpointer data)
671 struct transaction *trans = data;
672 (trans->timeout_callback)(sipe_private, trans->msg, trans);
673 transactions_remove(sipe_private, trans);
676 struct transaction *sip_transport_request_timeout(struct sipe_core_private *sipe_private,
677 const gchar *method,
678 const gchar *url,
679 const gchar *to,
680 const gchar *addheaders,
681 const gchar *body,
682 struct sip_dialog *dialog,
683 TransCallback callback,
684 guint timeout,
685 TransCallback timeout_callback)
687 struct sip_transport *transport = sipe_private->transport;
688 char *buf;
689 struct sipmsg *msg;
690 gchar *ourtag = dialog && dialog->ourtag ? g_strdup(dialog->ourtag) : NULL;
691 gchar *theirtag = dialog && dialog->theirtag ? g_strdup(dialog->theirtag) : NULL;
692 gchar *theirepid = dialog && dialog->theirepid ? g_strdup(dialog->theirepid) : NULL;
693 gchar *callid = dialog && dialog->callid ? g_strdup(dialog->callid) : gencallid();
694 gchar *branch = dialog && dialog->callid ? NULL : genbranch();
695 gchar *route = g_strdup("");
696 gchar *epid = get_epid(sipe_private);
697 int cseq = dialog ? ++dialog->cseq : 1 /* as Call-Id is new in this case */;
698 struct transaction *trans = NULL;
700 if (dialog && dialog->routes)
702 GSList *iter = dialog->routes;
704 while(iter)
706 char *tmp = route;
707 route = g_strdup_printf("%sRoute: %s\r\n", route, (char *)iter->data);
708 g_free(tmp);
709 iter = g_slist_next(iter);
713 if (!ourtag && !dialog) {
714 ourtag = gentag();
717 if (sipe_strequal(method, "REGISTER")) {
718 if (sipe_private->register_callid) {
719 g_free(callid);
720 callid = g_strdup(sipe_private->register_callid);
721 } else {
722 sipe_private->register_callid = g_strdup(callid);
724 cseq = ++transport->cseq;
727 buf = g_strdup_printf("%s %s SIP/2.0\r\n"
728 "Via: SIP/2.0/%s %s:%d%s%s\r\n"
729 "From: <sip:%s>%s%s;epid=%s\r\n"
730 "To: <%s>%s%s%s%s\r\n"
731 "Max-Forwards: 70\r\n"
732 "CSeq: %d %s\r\n"
733 "User-Agent: %s\r\n"
734 "Call-ID: %s\r\n"
735 "%s%s"
736 "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n%s",
737 method,
738 dialog && dialog->request ? dialog->request : url,
739 TRANSPORT_DESCRIPTOR,
740 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
741 transport->connection->client_port,
742 branch ? ";branch=" : "",
743 branch ? branch : "",
744 sipe_private->username,
745 ourtag ? ";tag=" : "",
746 ourtag ? ourtag : "",
747 epid,
749 theirtag ? ";tag=" : "",
750 theirtag ? theirtag : "",
751 theirepid ? ";epid=" : "",
752 theirepid ? theirepid : "",
753 cseq,
754 method,
755 sip_transport_user_agent(sipe_private),
756 callid,
757 route,
758 addheaders ? addheaders : "",
759 body ? (gsize) strlen(body) : 0,
760 body ? body : "");
763 //printf ("parsing msg buf:\n%s\n\n", buf);
764 msg = sipmsg_parse_msg(buf);
766 g_free(buf);
767 g_free(ourtag);
768 g_free(theirtag);
769 g_free(theirepid);
770 g_free(branch);
771 g_free(route);
772 g_free(epid);
774 sign_outgoing_message(sipe_private, msg);
776 /* The authentication scheme is not ready so we can't send the message.
777 This should only happen for REGISTER messages. */
778 if (!transport->auth_incomplete) {
779 buf = sipmsg_to_string(msg);
781 /* add to ongoing transactions */
782 /* ACK isn't supposed to be answered ever. So we do not keep transaction for it. */
783 if (!sipe_strequal(method, "ACK")) {
784 trans = g_new0(struct transaction, 1);
785 trans->callback = callback;
786 trans->msg = msg;
787 trans->key = g_strdup_printf("<%s><%d %s>", callid, cseq, method);
788 if (timeout_callback) {
789 trans->timeout_callback = timeout_callback;
790 trans->timeout_key = g_strdup_printf("<transaction timeout>%s", trans->key);
791 sipe_schedule_seconds(sipe_private,
792 trans->timeout_key,
793 trans,
794 timeout,
795 transaction_timeout_cb,
796 NULL);
798 transport->transactions = g_slist_append(transport->transactions,
799 trans);
800 SIPE_DEBUG_INFO("SIP transactions count:%d after addition", g_slist_length(transport->transactions));
803 send_sip_message(transport, buf);
804 g_free(buf);
807 if (!trans) sipmsg_free(msg);
808 g_free(callid);
809 return trans;
812 struct transaction *sip_transport_request(struct sipe_core_private *sipe_private,
813 const gchar *method,
814 const gchar *url,
815 const gchar *to,
816 const gchar *addheaders,
817 const gchar *body,
818 struct sip_dialog *dialog,
819 TransCallback callback)
821 return sip_transport_request_timeout(sipe_private,
822 method,
823 url,
825 addheaders,
826 body,
827 dialog,
828 callback,
830 NULL);
833 static void sip_transport_simple_request(struct sipe_core_private *sipe_private,
834 const gchar *method,
835 struct sip_dialog *dialog)
837 sip_transport_request(sipe_private,
838 method,
839 dialog->with,
840 dialog->with,
841 NULL,
842 NULL,
843 dialog,
844 NULL);
847 void sip_transport_ack(struct sipe_core_private *sipe_private,
848 struct sip_dialog *dialog)
850 sip_transport_simple_request(sipe_private, "ACK", dialog);
853 void sip_transport_bye(struct sipe_core_private *sipe_private,
854 struct sip_dialog *dialog)
856 sip_transport_simple_request(sipe_private, "BYE", dialog);
859 struct transaction *sip_transport_info(struct sipe_core_private *sipe_private,
860 const gchar *addheaders,
861 const gchar *body,
862 struct sip_dialog *dialog,
863 TransCallback callback)
865 return sip_transport_request(sipe_private,
866 "INFO",
867 dialog->with,
868 dialog->with,
869 addheaders,
870 body,
871 dialog,
872 callback);
875 struct transaction *sip_transport_invite(struct sipe_core_private *sipe_private,
876 const gchar *addheaders,
877 const gchar *body,
878 struct sip_dialog *dialog,
879 TransCallback callback)
881 return sip_transport_request(sipe_private,
882 "INVITE",
883 dialog->with,
884 dialog->with,
885 addheaders,
886 body,
887 dialog,
888 callback);
891 struct transaction *sip_transport_service(struct sipe_core_private *sipe_private,
892 const gchar *uri,
893 const gchar *addheaders,
894 const gchar *body,
895 TransCallback callback)
897 return sip_transport_request(sipe_private,
898 "SERVICE",
899 uri,
900 uri,
901 addheaders,
902 body,
903 NULL,
904 callback);
907 void sip_transport_subscribe(struct sipe_core_private *sipe_private,
908 const gchar *uri,
909 const gchar *addheaders,
910 const gchar *body,
911 struct sip_dialog *dialog,
912 TransCallback callback)
914 sip_transport_request(sipe_private,
915 "SUBSCRIBE",
916 uri,
917 uri,
918 addheaders,
919 body,
920 dialog,
921 callback);
924 void sip_transport_update(struct sipe_core_private *sipe_private,
925 struct sip_dialog *dialog,
926 TransCallback callback)
928 sip_transport_request(sipe_private,
929 "UPDATE",
930 dialog->with,
931 dialog->with,
932 NULL,
933 NULL,
934 dialog,
935 callback);
938 static const gchar *get_auth_header(struct sipe_core_private *sipe_private,
939 struct sip_auth *auth,
940 struct sipmsg *msg)
942 auth->type = sipe_private->authentication_type;
943 auth->protocol = auth_type_to_protocol[auth->type];
945 return(sipmsg_find_auth_header(msg, auth->protocol));
948 static void do_register(struct sipe_core_private *sipe_private,
949 gboolean deregister);
951 static void do_reauthenticate_cb(struct sipe_core_private *sipe_private,
952 SIPE_UNUSED_PARAMETER gpointer unused)
954 struct sip_transport *transport = sipe_private->transport;
956 /* register again when security token expires */
957 /* we have to start a new authentication as the security token
958 * is almost expired by sending a not signed REGISTER message */
959 SIPE_DEBUG_INFO_NOFORMAT("do a full reauthentication");
960 sipe_auth_free(&transport->registrar);
961 sipe_auth_free(&transport->proxy);
962 sipe_schedule_cancel(sipe_private, "<registration>");
963 transport->reregister_set = FALSE;
964 transport->register_attempt = 0;
965 do_register(sipe_private, FALSE);
966 transport->reauthenticate_set = FALSE;
969 static void sip_transport_default_contact(struct sipe_core_private *sipe_private)
971 struct sip_transport *transport = sipe_private->transport;
972 sipe_private->contact = g_strdup_printf("<sip:%s:%d;maddr=%s;transport=%s>;proxy=replace",
973 sipe_private->username,
974 transport->connection->client_port,
975 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
976 TRANSPORT_DESCRIPTOR);
979 static void do_register_cb(struct sipe_core_private *sipe_private,
980 SIPE_UNUSED_PARAMETER void *unused)
982 do_register(sipe_private, FALSE);
985 static void sip_transport_set_reregister(struct sipe_core_private *sipe_private,
986 int expires)
988 sipe_schedule_seconds(sipe_private,
989 "<registration>",
990 NULL,
991 expires,
992 do_register_cb,
993 NULL);
996 static void sipe_server_register(struct sipe_core_private *sipe_private,
997 guint type,
998 gchar *server_name,
999 guint server_port);
1001 static gboolean process_register_response(struct sipe_core_private *sipe_private,
1002 struct sipmsg *msg,
1003 SIPE_UNUSED_PARAMETER struct transaction *trans)
1005 struct sip_transport *transport = sipe_private->transport;
1006 const gchar *expires_header;
1007 int expires, i;
1008 GSList *hdr = msg->headers;
1009 struct sipnameval *elem;
1011 expires_header = sipmsg_find_header(msg, "Expires");
1012 expires = expires_header != NULL ? strtol(expires_header, NULL, 10) : 0;
1013 SIPE_DEBUG_INFO("process_register_response: got response to REGISTER; expires = %d", expires);
1015 switch (msg->response) {
1016 case 200:
1017 if (expires) {
1018 const gchar *contact_hdr;
1019 const gchar *auth_hdr;
1020 gchar *gruu = NULL;
1021 gchar *uuid;
1022 gchar *timeout;
1023 const gchar *server_hdr = sipmsg_find_header(msg, "Server");
1025 if (!transport->reregister_set) {
1026 sip_transport_set_reregister(sipe_private,
1027 expires);
1028 transport->reregister_set = TRUE;
1031 if (server_hdr && !transport->server_version) {
1032 transport->server_version = g_strdup(server_hdr);
1033 g_free(transport->user_agent);
1034 transport->user_agent = NULL;
1037 auth_hdr = get_auth_header(sipe_private, &transport->registrar, msg);
1038 if (auth_hdr) {
1039 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
1040 fill_auth(auth_hdr, &transport->registrar);
1043 if (!transport->reauthenticate_set) {
1044 guint reauth_timeout = transport->registrar.expires;
1046 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully");
1048 /* Does authentication scheme provide valid expiration time? */
1049 if (reauth_timeout == 0) {
1050 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: no expiration time - using default of 8 hours");
1051 reauth_timeout = 8 * 60 * 60;
1054 /* schedule reauthentication 5 minutes before expiration */
1055 if (reauth_timeout > 5 * 60)
1056 reauth_timeout -= 5 * 60;
1057 sipe_schedule_seconds(sipe_private,
1058 "<+reauthentication>",
1059 NULL,
1060 reauth_timeout,
1061 do_reauthenticate_cb,
1062 NULL);
1063 transport->reauthenticate_set = TRUE;
1066 sipe_backend_connection_completed(SIPE_CORE_PUBLIC);
1068 uuid = get_uuid(sipe_private);
1070 // There can be multiple Contact headers (one per location where the user is logged in) so
1071 // make sure to only get the one for this uuid
1072 for (i = 0; (contact_hdr = sipmsg_find_header_instance (msg, "Contact", i)); i++) {
1073 gchar * valid_contact = sipmsg_find_part_of_header (contact_hdr, uuid, NULL, NULL);
1074 if (valid_contact) {
1075 gruu = sipmsg_find_part_of_header(contact_hdr, "gruu=\"", "\"", NULL);
1076 //SIPE_DEBUG_INFO("process_register_response: got gruu %s from contact hdr w/ right uuid: %s", gruu, contact_hdr);
1077 g_free(valid_contact);
1078 break;
1079 } else {
1080 //SIPE_DEBUG_INFO("process_register_response: ignoring contact hdr b/c not right uuid: %s", contact_hdr);
1083 g_free(uuid);
1085 g_free(sipe_private->contact);
1086 if(gruu) {
1087 sipe_private->contact = g_strdup_printf("<%s>", gruu);
1088 g_free(gruu);
1089 } else {
1090 //SIPE_DEBUG_INFO_NOFORMAT("process_register_response: didn't find gruu in a Contact hdr");
1091 sip_transport_default_contact(sipe_private);
1093 SIPE_CORE_PRIVATE_FLAG_UNSET(OCS2007);
1094 SIPE_CORE_PRIVATE_FLAG_UNSET(REMOTE_USER);
1095 SIPE_CORE_PRIVATE_FLAG_UNSET(BATCHED_SUPPORT);
1097 while(hdr)
1099 elem = hdr->data;
1100 if (sipe_strcase_equal(elem->name, "Supported")) {
1101 if (sipe_strcase_equal(elem->value, "msrtc-event-categories")) {
1102 /* We interpret this as OCS2007+ indicator */
1103 SIPE_CORE_PRIVATE_FLAG_SET(OCS2007);
1104 SIPE_DEBUG_INFO("Supported: %s (indicates OCS2007+)", elem->value);
1106 if (sipe_strcase_equal(elem->value, "adhoclist")) {
1107 SIPE_CORE_PRIVATE_FLAG_SET(BATCHED_SUPPORT);
1108 SIPE_DEBUG_INFO("Supported: %s", elem->value);
1111 if (sipe_strcase_equal(elem->name, "Allow-Events")){
1112 gchar **caps = g_strsplit(elem->value,",",0);
1113 i = 0;
1114 while (caps[i]) {
1115 sipe_private->allowed_events = g_slist_append(sipe_private->allowed_events, g_strdup(caps[i]));
1116 SIPE_DEBUG_INFO("Allow-Events: %s", caps[i]);
1117 i++;
1119 g_strfreev(caps);
1121 if (sipe_strcase_equal(elem->name, "ms-user-logon-data")) {
1122 if (sipe_strcase_equal(elem->value, "RemoteUser")) {
1123 SIPE_CORE_PRIVATE_FLAG_SET(REMOTE_USER);
1124 SIPE_DEBUG_INFO_NOFORMAT("ms-user-logon-data: RemoteUser (connected "
1125 "via Edge Server)");
1128 hdr = g_slist_next(hdr);
1131 /* rejoin open chats to be able to use them by continue to send messages */
1132 sipe_backend_chat_rejoin_all(SIPE_CORE_PUBLIC);
1134 /* subscriptions, done only once */
1135 if (!transport->subscribed) {
1136 sipe_subscription_self_events(sipe_private);
1137 transport->subscribed = TRUE;
1140 timeout = sipmsg_find_part_of_header(sipmsg_find_header(msg, "ms-keep-alive"),
1141 "timeout=", ";", NULL);
1142 if (timeout != NULL) {
1143 sscanf(timeout, "%u", &transport->keepalive_timeout);
1144 SIPE_DEBUG_INFO("process_register_response: server determined keep alive timeout is %u seconds",
1145 transport->keepalive_timeout);
1146 g_free(timeout);
1149 SIPE_DEBUG_INFO("process_register_response: got 200, removing CSeq: %d", transport->cseq);
1151 break;
1152 case 301:
1154 gchar *redirect = parse_from(sipmsg_find_header(msg, "Contact"));
1156 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully (with redirect)");
1158 if (redirect && (g_ascii_strncasecmp("sip:", redirect, 4) == 0)) {
1159 gchar **parts = g_strsplit(redirect + 4, ";", 0);
1160 gchar **tmp;
1161 gchar *hostname;
1162 int port = 0;
1163 guint transport_type = SIPE_TRANSPORT_TLS;
1164 int i = 1;
1166 tmp = g_strsplit(parts[0], ":", 0);
1167 hostname = g_strdup(tmp[0]);
1168 if (tmp[1]) port = strtoul(tmp[1], NULL, 10);
1169 g_strfreev(tmp);
1171 while (parts[i]) {
1172 tmp = g_strsplit(parts[i], "=", 0);
1173 if (tmp[1]) {
1174 if (g_ascii_strcasecmp("transport", tmp[0]) == 0) {
1175 if (g_ascii_strcasecmp("tcp", tmp[1]) == 0) {
1176 transport_type = SIPE_TRANSPORT_TCP;
1180 g_strfreev(tmp);
1181 i++;
1183 g_strfreev(parts);
1185 /* Close old connection */
1186 sipe_core_connection_cleanup(sipe_private);
1187 /* transport and sipe_private->transport are invalid after this */
1189 /* Create new connection */
1190 sipe_server_register(sipe_private, transport_type, hostname, port);
1191 /* sipe_private->transport has a new value */
1192 SIPE_DEBUG_INFO("process_register_response: redirected to host %s port %d transport %d",
1193 hostname, port, transport_type);
1195 g_free(redirect);
1197 break;
1198 case 401:
1200 const char *auth_hdr;
1202 SIPE_DEBUG_INFO("process_register_response: REGISTER retries %d", transport->registrar.retries);
1204 if (transport->reauthenticate_set) {
1205 SIPE_DEBUG_ERROR_NOFORMAT("process_register_response: RE-REGISTER rejected, triggering re-authentication");
1206 do_reauthenticate_cb(sipe_private, NULL);
1207 return TRUE;
1210 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1211 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake failed - giving up.");
1212 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1213 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
1214 _("Authentication failed"));
1215 return TRUE;
1218 auth_hdr = get_auth_header(sipe_private, &transport->registrar, msg);
1219 if (!auth_hdr) {
1220 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1221 SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
1222 _("Incompatible authentication scheme chosen"));
1223 return TRUE;
1225 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
1226 fill_auth(auth_hdr, &transport->registrar);
1227 transport->reregister_set = FALSE;
1228 transport->register_attempt = 0;
1229 do_register(sipe_private,
1230 sipe_backend_connection_is_disconnecting(SIPE_CORE_PUBLIC));
1232 break;
1233 case 403:
1235 gchar *reason;
1236 gchar *warning;
1237 sipmsg_parse_warning(msg, &reason);
1238 reason = reason ? reason : sipmsg_get_ms_diagnostics_public_reason(msg);
1239 warning = g_strdup_printf(_("You have been rejected by the server: %s"),
1240 reason ? reason : _("no reason given"));
1241 g_free(reason);
1243 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1244 SIPE_CONNECTION_ERROR_INVALID_SETTINGS,
1245 warning);
1246 g_free(warning);
1247 return TRUE;
1249 break;
1250 case 404:
1252 const gchar *diagnostics = sipmsg_find_header(msg, "ms-diagnostics");
1253 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1254 gchar *warning;
1255 warning = g_strdup_printf(_("Not found: %s. Please contact your Administrator"),
1256 diagnostics ? (reason ? reason : _("no reason given")) :
1257 _("SIP is either not enabled for the destination URI or it does not exist"));
1258 g_free(reason);
1260 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1261 SIPE_CONNECTION_ERROR_INVALID_USERNAME,
1262 warning);
1263 g_free(warning);
1264 return TRUE;
1266 break;
1267 case 504: /* Server time-out */
1268 /* first attempt + 5 retries */
1269 if (transport->register_attempt < 6) {
1270 SIPE_DEBUG_INFO("process_register_response: RE-REGISTER timeout on attempt %d, retrying later",
1271 transport->register_attempt);
1272 sip_transport_set_reregister(sipe_private, 60);
1273 return TRUE;
1275 /* FALLTHROUGH */
1276 case 503:
1278 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1279 gchar *warning;
1280 warning = g_strdup_printf(_("Service unavailable: %s"), reason ? reason : _("no reason given"));
1281 g_free(reason);
1283 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1284 SIPE_CONNECTION_ERROR_NETWORK,
1285 warning);
1286 g_free(warning);
1287 return TRUE;
1289 break;
1291 return TRUE;
1294 static gboolean register_response_timeout(struct sipe_core_private *sipe_private,
1295 SIPE_UNUSED_PARAMETER struct sipmsg *msg,
1296 SIPE_UNUSED_PARAMETER struct transaction *trans)
1298 struct sip_transport *transport = sipe_private->transport;
1299 if (transport->register_attempt < 6) {
1300 SIPE_DEBUG_INFO("register_response_timeout: no answer to attempt %d, retrying",
1301 transport->register_attempt);
1302 do_register(sipe_private, FALSE);
1303 } else {
1304 gchar *warning = g_strdup_printf(_("Service unavailable: %s"), _("no reason given"));
1305 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1306 SIPE_CONNECTION_ERROR_NETWORK,
1307 warning);
1308 g_free(warning);
1310 return TRUE;
1313 static void do_register(struct sipe_core_private *sipe_private,
1314 gboolean deregister)
1316 struct sip_transport *transport = sipe_private->transport;
1317 char *uri;
1318 char *to;
1319 char *hdr;
1320 char *uuid;
1322 if (!sipe_private->public.sip_domain) return;
1324 if (!deregister) {
1325 if (transport->reregister_set) {
1326 transport->reregister_set = FALSE;
1327 transport->register_attempt = 1;
1328 } else {
1329 transport->register_attempt++;
1333 transport->deregister = deregister;
1334 transport->auth_incomplete = FALSE;
1336 uuid = get_uuid(sipe_private);
1337 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"
1338 "Supported: gruu-10, adhoclist, msrtc-event-categories, com.microsoft.msrtc.presence\r\n"
1339 "Event: registration\r\n"
1340 "Allow-Events: presence\r\n"
1341 "ms-keep-alive: UAC;hop-hop=yes\r\n"
1342 "%s",
1343 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
1344 transport->connection->client_port,
1345 TRANSPORT_DESCRIPTOR,
1346 uuid,
1347 deregister ? "Expires: 0\r\n" : "");
1348 g_free(uuid);
1350 uri = sip_uri_from_name(sipe_private->public.sip_domain);
1351 to = sip_uri_self(sipe_private);
1352 sip_transport_request_timeout(sipe_private,
1353 "REGISTER",
1354 uri,
1356 hdr,
1358 NULL,
1359 process_register_response,
1361 deregister ? NULL : register_response_timeout);
1362 g_free(to);
1363 g_free(uri);
1364 g_free(hdr);
1366 if (deregister) {
1367 /* Make sure that all messages are pushed to the server
1368 before the connection gets shut down */
1369 SIPE_DEBUG_INFO_NOFORMAT("De-register from server. Flushing outstanding messages.");
1370 sipe_backend_transport_flush(transport->connection);
1374 void sip_transport_deregister(struct sipe_core_private *sipe_private)
1376 do_register(sipe_private, TRUE);
1379 void sip_transport_disconnect(struct sipe_core_private *sipe_private)
1381 struct sip_transport *transport = sipe_private->transport;
1383 /* transport can be NULL during connection setup */
1384 if (transport) {
1385 sipe_backend_transport_disconnect(transport->connection);
1387 sipe_auth_free(&transport->registrar);
1388 sipe_auth_free(&transport->proxy);
1390 g_free(transport->server_name);
1391 g_free(transport->server_version);
1392 g_free(transport->user_agent);
1394 while (transport->transactions)
1395 transactions_remove(sipe_private,
1396 transport->transactions->data);
1398 g_free(transport);
1401 sipe_private->transport = NULL;
1402 sipe_private->service_data = NULL;
1403 sipe_private->address_data = NULL;
1405 sipe_schedule_cancel(sipe_private, "<+keepalive-timeout>");
1407 if (sipe_private->dns_query)
1408 sipe_backend_dns_query_cancel(sipe_private->dns_query);
1412 void sip_transport_authentication_completed(struct sipe_core_private *sipe_private)
1414 do_reauthenticate_cb(sipe_private, NULL);
1417 guint sip_transport_port(struct sipe_core_private *sipe_private)
1419 return sipe_private->transport->server_port;
1422 static void process_input_message(struct sipe_core_private *sipe_private,
1423 struct sipmsg *msg)
1425 struct sip_transport *transport = sipe_private->transport;
1426 gboolean notfound = FALSE;
1427 const char *method = msg->method ? msg->method : "NOT FOUND";
1429 SIPE_DEBUG_INFO("process_input_message: msg->response(%d),msg->method(%s)",
1430 msg->response, method);
1432 if (msg->response == 0) { /* request */
1433 if (sipe_strequal(method, "MESSAGE")) {
1434 process_incoming_message(sipe_private, msg);
1435 } else if (sipe_strequal(method, "NOTIFY")) {
1436 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_notify");
1437 process_incoming_notify(sipe_private, msg);
1438 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1439 } else if (sipe_strequal(method, "BENOTIFY")) {
1440 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_benotify");
1441 process_incoming_notify(sipe_private, msg);
1442 } else if (sipe_strequal(method, "INVITE")) {
1443 process_incoming_invite(sipe_private, msg);
1444 } else if (sipe_strequal(method, "REFER")) {
1445 process_incoming_refer(sipe_private, msg);
1446 } else if (sipe_strequal(method, "OPTIONS")) {
1447 process_incoming_options(sipe_private, msg);
1448 } else if (sipe_strequal(method, "INFO")) {
1449 process_incoming_info(sipe_private, msg);
1450 } else if (sipe_strequal(method, "ACK")) {
1451 /* ACK's don't need any response */
1452 } else if (sipe_strequal(method, "PRACK")) {
1453 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1454 } else if (sipe_strequal(method, "SUBSCRIBE")) {
1455 /* LCS 2005 sends us these - just respond 200 OK */
1456 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1457 } else if (sipe_strequal(method, "CANCEL")) {
1458 process_incoming_cancel(sipe_private, msg);
1459 } else if (sipe_strequal(method, "BYE")) {
1460 process_incoming_bye(sipe_private, msg);
1461 } else {
1462 sip_transport_response(sipe_private, msg, 501, "Not implemented", NULL);
1463 notfound = TRUE;
1466 } else { /* response */
1467 struct transaction *trans = transactions_find(transport, msg);
1468 if (trans) {
1469 if (msg->response < 200) {
1470 /* ignore provisional response */
1471 SIPE_DEBUG_INFO("process_input_message: got provisional (%d) response, ignoring", msg->response);
1473 /* Transaction not yet completed */
1474 trans = NULL;
1476 } else if (msg->response == 401) { /* Unauthorized */
1478 if (sipe_strequal(trans->msg->method, "REGISTER")) {
1479 /* Expected response during authentication handshake */
1480 transport->registrar.retries++;
1481 SIPE_DEBUG_INFO("process_input_message: RE-REGISTER CSeq: %d", transport->cseq);
1482 } else {
1483 gchar *resend;
1485 /* Are we registered? */
1486 if (transport->reregister_set) {
1487 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Retrying with new authentication.");
1488 sipmsg_remove_header_now(trans->msg, "Authorization");
1489 sign_outgoing_message(sipe_private,
1490 trans->msg);
1491 } else {
1493 * We don't have a valid authentication at the moment.
1494 * Resend message unchanged. It will be rejected again
1495 * and hopefully by then we have a valid authentication.
1497 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Bouncing...");
1500 /* Resend request */
1501 resend = sipmsg_to_string(trans->msg);
1502 send_sip_message(sipe_private->transport, resend);
1503 g_free(resend);
1505 /* Transaction not yet completed */
1506 trans = NULL;
1509 } else if (msg->response == 407) { /* Proxy Authentication Required */
1511 if (transport->proxy.retries++ <= 30) {
1512 const gchar *proxy_hdr = sipmsg_find_header(msg, "Proxy-Authenticate");
1514 if (proxy_hdr) {
1515 gchar *auth = NULL;
1517 if (!g_ascii_strncasecmp(proxy_hdr, "Digest", 6)) {
1518 auth = sip_sec_digest_authorization(sipe_private,
1519 proxy_hdr + 7,
1520 msg->method,
1521 msg->target);
1522 } else {
1523 guint i;
1525 transport->proxy.type = SIPE_AUTHENTICATION_TYPE_UNSET;
1526 for (i = 0; i < AUTH_PROTOCOLS; i++) {
1527 const gchar *protocol = auth_type_to_protocol[i];
1528 if (protocol &&
1529 !g_ascii_strncasecmp(proxy_hdr, protocol, strlen(protocol))) {
1530 SIPE_DEBUG_INFO("process_input_message: proxy authentication scheme '%s'", protocol);
1531 transport->proxy.type = i;
1532 transport->proxy.protocol = protocol;
1533 fill_auth(proxy_hdr, &transport->proxy);
1534 auth = auth_header(sipe_private, &transport->proxy, trans->msg);
1535 break;
1540 if (auth) {
1541 gchar *resend;
1543 /* replace old proxy authentication with new one */
1544 sipmsg_remove_header_now(trans->msg, "Proxy-Authorization");
1545 sipmsg_add_header_now(trans->msg, "Proxy-Authorization", auth);
1546 g_free(auth);
1548 /* resend request with proxy authentication */
1549 resend = sipmsg_to_string(trans->msg);
1550 send_sip_message(sipe_private->transport, resend);
1551 g_free(resend);
1553 /* Transaction not yet completed */
1554 trans = NULL;
1556 } else
1557 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: can't generate proxy authentication. Giving up.");
1558 } else
1559 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: 407 response without 'Proxy-Authenticate' header. Giving up.");
1560 } else
1561 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: too many proxy authentication retries. Giving up.");
1563 } else {
1564 transport->registrar.retries = 0;
1565 transport->proxy.retries = 0;
1568 /* Is transaction completed? */
1569 if (trans) {
1570 if (trans->callback) {
1571 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: we have a transaction callback");
1572 /* call the callback to process response */
1573 (trans->callback)(sipe_private, msg, trans);
1574 /* transport && trans no longer valid after redirect */
1578 * Redirect case: sipe_private->transport is
1579 * the new transport with empty queue
1581 if (sipe_private->transport->transactions) {
1582 SIPE_DEBUG_INFO("process_input_message: removing CSeq %d", transport->cseq);
1583 transactions_remove(sipe_private, trans);
1586 } else {
1587 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: received response to unknown transaction");
1588 notfound = TRUE;
1592 if (notfound) {
1593 SIPE_DEBUG_INFO("received a unknown sip message with method %s and response %d", method, msg->response);
1597 static void sip_transport_input(struct sipe_transport_connection *conn)
1599 struct sipe_core_private *sipe_private = conn->user_data;
1600 struct sip_transport *transport = sipe_private->transport;
1601 gchar *cur = conn->buffer;
1603 /* according to the RFC remove CRLF at the beginning */
1604 while (*cur == '\r' || *cur == '\n') {
1605 cur++;
1607 if (cur != conn->buffer)
1608 sipe_utils_shrink_buffer(conn, cur);
1610 /* Received a full Header? */
1611 transport->processing_input = TRUE;
1612 while (transport->processing_input &&
1613 ((cur = strstr(conn->buffer, "\r\n\r\n")) != NULL)) {
1614 struct sipmsg *msg;
1615 guint remainder;
1617 cur += 2;
1618 cur[0] = '\0';
1619 msg = sipmsg_parse_header(conn->buffer);
1621 cur += 2;
1622 remainder = conn->buffer_used - (cur - conn->buffer);
1623 if (msg && remainder >= (guint) msg->bodylen) {
1624 char *dummy = g_malloc(msg->bodylen + 1);
1625 memcpy(dummy, cur, msg->bodylen);
1626 dummy[msg->bodylen] = '\0';
1627 msg->body = dummy;
1628 cur += msg->bodylen;
1629 sipe_utils_message_debug("SIP",
1630 conn->buffer,
1631 msg->body,
1632 FALSE);
1633 sipe_utils_shrink_buffer(conn, cur);
1634 } else {
1635 if (msg){
1636 SIPE_DEBUG_INFO("sipe_transport_input: body too short (%d < %d, strlen %d) - ignoring message", remainder, msg->bodylen, (int)strlen(conn->buffer));
1637 sipmsg_free(msg);
1640 /* restore header for next try */
1641 cur[-2] = '\r';
1642 return;
1645 // Verify the signature before processing it
1646 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1647 struct sipmsg_breakdown msgbd;
1648 gchar *signature_input_str;
1649 gchar *rspauth;
1650 msgbd.msg = msg;
1651 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
1652 transport->registrar.protocol);
1653 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
1655 rspauth = sipmsg_find_part_of_header(sipmsg_find_header(msg, "Authentication-Info"), "rspauth=\"", "\"", NULL);
1657 if (rspauth != NULL) {
1658 if (sip_sec_verify_signature(transport->registrar.gssapi_context, signature_input_str, rspauth)) {
1659 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message validated");
1660 process_input_message(sipe_private, msg);
1661 /* transport is invalid after redirect */
1662 } else {
1663 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message is invalid.");
1664 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1665 SIPE_CONNECTION_ERROR_NETWORK,
1666 _("Invalid message signature received"));
1668 } else if ((msg->response == 401) ||
1669 sipe_strequal(msg->method, "REGISTER")) {
1670 /* a) Retry non-REGISTER requests with updated authentication */
1671 /* b) We must always process REGISTER responses */
1672 process_input_message(sipe_private, msg);
1673 } else {
1674 /* OCS sends provisional messages that are *not* signed */
1675 if (msg->response >= 200) {
1676 /* We are not calling process_input_message(),
1677 so we need to drop the transaction here. */
1678 struct transaction *trans = transactions_find(transport, msg);
1679 if (trans) transactions_remove(sipe_private, trans);
1681 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: message without authentication data - ignoring");
1683 g_free(signature_input_str);
1685 g_free(rspauth);
1686 sipmsg_breakdown_free(&msgbd);
1687 } else {
1688 process_input_message(sipe_private, msg);
1691 sipmsg_free(msg);
1693 /* Redirect: old content of "transport" & "conn" is no longer valid */
1694 transport = sipe_private->transport;
1695 conn = transport->connection;
1699 static void sip_transport_connected(struct sipe_transport_connection *conn)
1701 struct sipe_core_private *sipe_private = conn->user_data;
1702 struct sip_transport *transport = sipe_private->transport;
1704 sipe_private->service_data = NULL;
1705 sipe_private->address_data = NULL;
1708 * Initial keepalive timeout during REGISTER phase
1710 * NOTE: 60 seconds is a guess. Needs more testing!
1712 transport->keepalive_timeout = 60;
1713 start_keepalive_timer(sipe_private, transport->keepalive_timeout);
1715 do_register(sipe_private, FALSE);
1718 static void resolve_next_service(struct sipe_core_private *sipe_private,
1719 const struct sip_service_data *start);
1720 static void resolve_next_address(struct sipe_core_private *sipe_private,
1721 gboolean initial);
1722 static void sip_transport_error(struct sipe_transport_connection *conn,
1723 const gchar *msg)
1725 struct sipe_core_private *sipe_private = conn->user_data;
1727 /* This failed attempt was based on a DNS SRV record */
1728 if (sipe_private->service_data) {
1729 resolve_next_service(sipe_private, NULL);
1730 /* This failed attempt was based on a DNS A record */
1731 } else if (sipe_private->address_data) {
1732 resolve_next_address(sipe_private, FALSE);
1733 } else {
1734 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1735 SIPE_CONNECTION_ERROR_NETWORK,
1736 msg);
1740 /* server_name must be g_alloc()'ed */
1741 static void sipe_server_register(struct sipe_core_private *sipe_private,
1742 guint type,
1743 gchar *server_name,
1744 guint server_port)
1746 sipe_connect_setup setup = {
1747 type,
1748 server_name,
1749 (server_port != 0) ? server_port :
1750 (type == SIPE_TRANSPORT_TLS) ? 5061 : 5060,
1751 sipe_private,
1752 sip_transport_connected,
1753 sip_transport_input,
1754 sip_transport_error
1756 struct sip_transport *transport = g_new0(struct sip_transport, 1);
1758 transport->server_name = server_name;
1759 transport->server_port = setup.server_port;
1760 transport->connection = sipe_backend_transport_connect(SIPE_CORE_PUBLIC,
1761 &setup);
1762 sipe_private->transport = transport;
1765 struct sip_service_data {
1766 const char *protocol;
1767 const char *transport;
1768 guint type;
1772 * Autodiscover using DNS SRV records. See RFC2782/3263
1774 * Service list for AUTO
1776 static const struct sip_service_data service_autodetect[] = {
1777 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1778 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1779 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1780 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1781 { NULL, NULL, 0 }
1784 /* Service list for SSL/TLS */
1785 static const struct sip_service_data service_tls[] = {
1786 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1787 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1788 { NULL, NULL, 0 }
1791 /* Service list for TCP */
1792 static const struct sip_service_data service_tcp[] = {
1793 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1794 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1795 { NULL, NULL, 0 }
1798 static const struct sip_service_data *services[] = {
1799 service_autodetect, /* SIPE_TRANSPORT_AUTO */
1800 service_tls, /* SIPE_TRANSPORT_TLS */
1801 service_tcp /* SIPE_TRANSPORT_TCP */
1804 struct sip_address_data {
1805 const char *prefix;
1806 guint port;
1810 * Autodiscover using DNS A records. This is an extension addded
1811 * by Microsoft. See http://support.microsoft.com/kb/2619522
1813 static const struct sip_address_data addresses[] = {
1814 { "sipinternal", 5061 },
1815 { "sipexternal", 443 },
1817 * Our implementation supports only one port per host name. If the host name
1818 * resolves OK, we abort the search and try to connect. If we would know if we
1819 * are trying to connect from "Intranet" or "Internet" then we could choose
1820 * between those two ports.
1822 * We drop port 5061 in order to cover the "Internet" case.
1824 * { "sip", 5061 },
1826 { "sip", 443 },
1827 { NULL, 0 }
1830 static void sipe_core_dns_resolved(struct sipe_core_public *sipe_public,
1831 const gchar *hostname, guint port)
1833 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1834 gboolean service = sipe_private->service_data != NULL;
1836 sipe_private->dns_query = NULL;
1838 if (hostname) {
1839 gchar *host;
1840 guint type;
1842 if (service) {
1843 host = g_strdup(hostname);
1844 type = sipe_private->service_data->type;
1845 } else {
1846 /* DNS A resolver returns an IP address */
1847 host = g_strdup_printf("%s.%s",
1848 sipe_private->address_data->prefix,
1849 sipe_private->public.sip_domain);
1850 port = sipe_private->address_data->port;
1851 type = sipe_private->transport_type;
1852 if (type == SIPE_TRANSPORT_AUTO)
1853 type = SIPE_TRANSPORT_TLS;
1856 SIPE_DEBUG_INFO("sipe_core_dns_resolved - %s hostname: %s port: %d",
1857 service ? "SRV" : "A", hostname, port);
1858 sipe_server_register(sipe_private, type, host, port);
1859 } else {
1860 if (service)
1861 resolve_next_service(SIPE_CORE_PRIVATE, NULL);
1862 else
1863 resolve_next_address(SIPE_CORE_PRIVATE, FALSE);
1867 static void resolve_next_service(struct sipe_core_private *sipe_private,
1868 const struct sip_service_data *start)
1870 if (start) {
1871 sipe_private->service_data = start;
1872 } else {
1873 sipe_private->service_data++;
1874 if (sipe_private->service_data->protocol == NULL) {
1876 /* We tried all services */
1877 sipe_private->service_data = NULL;
1879 /* Try A records list next */
1880 SIPE_DEBUG_INFO_NOFORMAT("no SRV records found; trying A records next");
1881 resolve_next_address(sipe_private, TRUE);
1882 return;
1886 /* Try to resolve next service */
1887 sipe_private->dns_query = sipe_backend_dns_query_srv(
1888 SIPE_CORE_PUBLIC,
1889 sipe_private->service_data->protocol,
1890 sipe_private->service_data->transport,
1891 sipe_private->public.sip_domain,
1892 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
1893 SIPE_CORE_PUBLIC);
1896 static void resolve_next_address(struct sipe_core_private *sipe_private,
1897 gboolean initial)
1899 gchar *hostname;
1901 if (initial) {
1902 sipe_private->address_data = addresses;
1903 } else {
1904 sipe_private->address_data++;
1905 if (sipe_private->address_data->prefix == NULL) {
1906 guint type = sipe_private->transport_type;
1908 /* We tried all addresss */
1909 sipe_private->address_data = NULL;
1911 /* Try connecting to the SIP hostname directly */
1912 SIPE_DEBUG_INFO_NOFORMAT("no SRV or A records found; using SIP domain as fallback");
1913 if (type == SIPE_TRANSPORT_AUTO)
1914 type = SIPE_TRANSPORT_TLS;
1916 sipe_server_register(sipe_private, type,
1917 g_strdup(sipe_private->public.sip_domain),
1919 return;
1923 /* Try to resolve next address */
1924 hostname = g_strdup_printf("%s.%s",
1925 sipe_private->address_data->prefix,
1926 sipe_private->public.sip_domain);
1927 sipe_private->dns_query = sipe_backend_dns_query_a(
1928 SIPE_CORE_PUBLIC,
1929 hostname,
1930 sipe_private->address_data->port,
1931 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
1932 SIPE_CORE_PUBLIC);
1933 g_free(hostname);
1937 * NOTE: this function can be called before sipe_core_allocate()!
1939 gboolean sipe_core_transport_sip_requires_password(guint authentication,
1940 gboolean sso)
1942 return(sip_sec_requires_password(authentication, sso));
1945 void sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public,
1946 guint transport,
1947 guint authentication,
1948 const gchar *server,
1949 const gchar *port)
1951 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1953 /* backend initialization is complete */
1954 sipe_core_backend_initialized(sipe_private, authentication);
1957 * Initializing the certificate sub-system will trigger the generation
1958 * of a cryptographic key pair which takes time. If we do this after we
1959 * have connected to the server then there is a risk that we run into a
1960 * SIP connection timeout. So let's get this out of the way now...
1962 * This is currently only needed if the user has selected TLS-DSK.
1964 if (sipe_private->authentication_type == SIPE_AUTHENTICATION_TYPE_TLS_DSK)
1965 sipe_certificate_init(sipe_private);
1967 if (server) {
1968 /* Use user specified server[:port] */
1969 int port_number = 0;
1971 if (port)
1972 port_number = atoi(port);
1974 SIPE_DEBUG_INFO("sipe_core_connect: user specified SIP server %s:%d",
1975 server, port_number);
1977 sipe_server_register(sipe_private, transport,
1978 g_strdup(server), port_number);
1979 } else {
1980 /* Server auto-discovery */
1982 /* Remember user specified transport type */
1983 sipe_private->transport_type = transport;
1984 resolve_next_service(sipe_private, services[transport]);
1988 const gchar *sipe_core_transport_sip_server_name(struct sipe_core_public *sipe_public)
1990 struct sip_transport *transport = SIPE_CORE_PRIVATE->transport;
1991 return(transport ? transport->server_name : NULL);
1994 int sip_transaction_cseq(struct transaction *trans)
1996 int cseq;
1998 g_return_val_if_fail(trans && trans->key, 0);
2000 sscanf(trans->key, "<%*[a-zA-Z0-9]><%d INVITE>", &cseq);
2001 return cseq;
2005 Local Variables:
2006 mode: c
2007 c-file-style: "bsd"
2008 indent-tabs-mode: t
2009 tab-width: 8
2010 End: