transport: fix use-after-free accesses
[siplcs.git] / src / core / sip-transport.c
blob743a91201c0d7f5c9348f909358c4848507a05fe
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-transport.h"
65 #include "sipe-backend.h"
66 #include "sipe-core.h"
67 #include "sipe-core-private.h"
68 #include "sipe-certificate.h"
69 #include "sipe-dialog.h"
70 #include "sipe-incoming.h"
71 #include "sipe-nls.h"
72 #include "sipe-notify.h"
73 #include "sipe-schedule.h"
74 #include "sipe-sign.h"
75 #include "sipe-subscriptions.h"
76 #include "sipe-utils.h"
78 struct sip_auth {
79 guint type;
80 struct sip_sec_context *gssapi_context;
81 gchar *gssapi_data;
82 gchar *opaque;
83 const gchar *protocol;
84 gchar *realm;
85 gchar *sts_uri;
86 gchar *target;
87 guint version;
88 guint retries;
89 guint ntlm_num;
90 guint expires;
93 /* sip-transport.c private data */
94 struct sip_transport {
95 struct sipe_transport_connection *connection;
97 gchar *server_name;
98 guint server_port;
99 gchar *server_version;
101 gchar *user_agent;
103 GSList *transactions;
105 struct sip_auth registrar;
106 struct sip_auth proxy;
108 guint cseq;
109 guint register_attempt;
111 gboolean processing_input; /* whether full header received */
112 gboolean auth_incomplete; /* whether authentication not completed */
113 gboolean reregister_set; /* whether reregister timer set */
114 gboolean reauthenticate_set; /* whether reauthenticate timer set */
115 gboolean subscribed; /* whether subscribed to events, except buddies presence */
116 gboolean deregister; /* whether in deregistration */
119 /* Keep in sync with sipe_transport_type! */
120 static const char *transport_descriptor[] = { "", "tls", "tcp"};
121 #define TRANSPORT_DESCRIPTOR (transport_descriptor[transport->connection->type])
123 static char *genbranch()
125 return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X",
126 rand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,
127 rand() & 0xFFFF, rand() & 0xFFFF);
130 static void sipe_auth_free(struct sip_auth *auth)
132 g_free(auth->opaque);
133 auth->opaque = NULL;
134 auth->protocol = NULL;
135 g_free(auth->realm);
136 auth->realm = NULL;
137 g_free(auth->sts_uri);
138 auth->sts_uri = NULL;
139 g_free(auth->target);
140 auth->target = NULL;
141 auth->version = 0;
142 auth->type = SIPE_AUTHENTICATION_TYPE_UNSET;
143 auth->retries = 0;
144 auth->expires = 0;
145 g_free(auth->gssapi_data);
146 auth->gssapi_data = NULL;
147 sip_sec_destroy_context(auth->gssapi_context);
148 auth->gssapi_context = NULL;
151 static void sipe_make_signature(struct sipe_core_private *sipe_private,
152 struct sipmsg *msg)
154 struct sip_transport *transport = sipe_private->transport;
155 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
156 struct sipmsg_breakdown msgbd;
157 gchar *signature_input_str;
158 msgbd.msg = msg;
159 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
160 transport->registrar.protocol);
161 msgbd.rand = g_strdup_printf("%08x", g_random_int());
162 transport->registrar.ntlm_num++;
163 msgbd.num = g_strdup_printf("%d", transport->registrar.ntlm_num);
164 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
165 if (signature_input_str != NULL) {
166 char *signature_hex = sip_sec_make_signature(transport->registrar.gssapi_context, signature_input_str);
167 msg->signature = signature_hex;
168 msg->rand = g_strdup(msgbd.rand);
169 msg->num = g_strdup(msgbd.num);
170 g_free(signature_input_str);
172 sipmsg_breakdown_free(&msgbd);
176 static const gchar *const auth_type_to_protocol[] = {
177 NULL, /* SIPE_AUTHENTICATION_TYPE_UNSET */
178 "NTLM", /* SIPE_AUTHENTICATION_TYPE_NTLM */
179 "Kerberos", /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
180 NULL, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
181 "TLS-DSK", /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
183 #define AUTH_PROTOCOLS (sizeof(auth_type_to_protocol)/sizeof(gchar *))
185 static gchar *msg_signature_to_auth(struct sip_auth *auth,
186 struct sipmsg *msg)
188 return(g_strdup_printf("%s qop=\"auth\", opaque=\"%s\", realm=\"%s\", targetname=\"%s\", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
189 auth->protocol,
190 auth->opaque, auth->realm, auth->target,
191 msg->rand, msg->num, msg->signature));
194 static gchar *initialize_auth_context(struct sipe_core_private *sipe_private,
195 struct sip_auth *auth,
196 struct sipmsg *msg)
198 struct sip_transport *transport = sipe_private->transport;
199 gchar *ret;
200 gchar *gssapi_data = NULL;
201 gchar *sign_str;
202 gchar *gssapi_str;
203 gchar *opaque_str;
204 gchar *version_str;
207 * If transport is de-registering when we reach this point then we
208 * are in the middle of the previous authentication context setup
209 * attempt. So we shouldn't try another attempt.
211 if (transport->deregister)
212 return NULL;
214 /* Create security context or handshake continuation? */
215 if (auth->gssapi_context) {
216 /* Perform next step in authentication handshake */
217 gboolean status = sip_sec_init_context_step(auth->gssapi_context,
218 auth->target,
219 auth->gssapi_data,
220 &gssapi_data,
221 &auth->expires);
223 /* If authentication is completed gssapi_data can be NULL */
224 if (!(status &&
225 (sip_sec_context_is_ready(auth->gssapi_context) || gssapi_data))) {
226 SIPE_DEBUG_ERROR_NOFORMAT("initialize_auth_context: security context continuation failed");
227 g_free(gssapi_data);
228 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
229 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
230 _("Failed to authenticate to server"));
231 return NULL;
234 } else {
235 /* Create security context */
236 gpointer password = sipe_private->password;
238 /* For TLS-DSK the "password" is a certificate */
239 if (auth->type == SIPE_AUTHENTICATION_TYPE_TLS_DSK) {
240 password = sipe_certificate_tls_dsk_find(sipe_private,
241 auth->target);
243 if (!password) {
244 if (auth->sts_uri) {
245 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK Certificate Provisioning URI %s",
246 auth->sts_uri);
247 if (!sipe_certificate_tls_dsk_generate(sipe_private,
248 auth->target,
249 auth->sts_uri)) {
250 gchar *tmp = g_strdup_printf(_("Can't request certificate from %s"),
251 auth->sts_uri);
252 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
253 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
254 tmp);
255 g_free(tmp);
257 } else {
258 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
259 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
260 _("No URI for certificate provisioning service provided"));
263 /* we can't authenticate the message yet */
264 transport->auth_incomplete = TRUE;
266 return(NULL);
267 } else {
268 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK certificate for target '%s' found.",
269 auth->target);
273 auth->gssapi_context = sip_sec_create_context(auth->type,
274 SIPE_CORE_PRIVATE_FLAG_IS(SSO),
275 FALSE, /* connection-less for SIP */
276 sipe_private->authdomain ? sipe_private->authdomain : "",
277 sipe_private->authuser,
278 password);
280 if (auth->gssapi_context) {
281 sip_sec_init_context_step(auth->gssapi_context,
282 auth->target,
283 NULL,
284 &gssapi_data,
285 &(auth->expires));
288 if (!gssapi_data || !auth->gssapi_context) {
289 g_free(gssapi_data);
290 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
291 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
292 _("Failed to authenticate to server"));
293 return NULL;
297 if ((auth->version > 3) &&
298 sip_sec_context_is_ready(auth->gssapi_context)) {
299 sipe_make_signature(sipe_private, msg);
300 sign_str = g_strdup_printf(", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
301 msg->rand, msg->num, msg->signature);
302 } else {
303 sign_str = g_strdup("");
306 if (gssapi_data) {
307 gssapi_str = g_strdup_printf(", gssapi-data=\"%s\"",
308 gssapi_data);
309 g_free(gssapi_data);
310 } else {
311 gssapi_str = g_strdup("");
314 opaque_str = auth->opaque ? g_strdup_printf(", opaque=\"%s\"", auth->opaque) : g_strdup("");
316 if (auth->version > 2) {
317 version_str = g_strdup_printf(", version=%d", auth->version);
318 } else {
319 version_str = g_strdup("");
322 ret = g_strdup_printf("%s qop=\"auth\"%s, realm=\"%s\", targetname=\"%s\"%s%s%s",
323 auth->protocol, opaque_str,
324 auth->realm, auth->target,
325 gssapi_str, version_str, sign_str);
326 g_free(version_str);
327 g_free(opaque_str);
328 g_free(gssapi_str);
329 g_free(sign_str);
331 return(ret);
334 static gchar *auth_header(struct sipe_core_private *sipe_private,
335 struct sip_auth *auth,
336 struct sipmsg *msg)
338 gchar *ret = NULL;
341 * If the message is already signed then we have an authentication
342 * context, i.e. the authentication handshake is complete. Generate
343 * authentication header from message signature.
345 if (msg->signature) {
346 ret = msg_signature_to_auth(auth, msg);
349 * We should reach this point only when the authentication context
350 * needs to be initialized.
352 } else {
353 ret = initialize_auth_context(sipe_private, auth, msg);
356 return(ret);
359 static void fill_auth(const gchar *hdr, struct sip_auth *auth)
361 const gchar *param;
363 /* skip authentication identifier */
364 hdr = strchr(hdr, ' ');
365 if (!hdr) {
366 SIPE_DEBUG_ERROR_NOFORMAT("fill_auth: corrupted authentication header");
367 return;
369 while (*hdr == ' ')
370 hdr++;
372 /* start of next parameter value */
373 while ((param = strchr(hdr, '=')) != NULL) {
374 const gchar *end;
376 /* parameter value type */
377 param++;
378 if (*param == '"') {
379 /* string: xyz="..."(,) */
380 end = strchr(++param, '"');
381 if (!end) {
382 SIPE_DEBUG_ERROR("fill_auth: corrupted string parameter near '%s'", hdr);
383 break;
385 } else {
386 /* number: xyz=12345(,) */
387 end = strchr(param, ',');
388 if (!end) {
389 /* last parameter */
390 end = param + strlen(param);
394 #if 0
395 SIPE_DEBUG_INFO("fill_auth: hdr '%s'", hdr);
396 SIPE_DEBUG_INFO("fill_auth: param '%s'", param);
397 SIPE_DEBUG_INFO("fill_auth: end '%s'", end);
398 #endif
400 /* parameter type */
401 if (g_str_has_prefix(hdr, "gssapi-data=\"")) {
402 g_free(auth->gssapi_data);
403 auth->gssapi_data = g_strndup(param, end - param);
404 } else if (g_str_has_prefix(hdr, "opaque=\"")) {
405 g_free(auth->opaque);
406 auth->opaque = g_strndup(param, end - param);
407 } else if (g_str_has_prefix(hdr, "realm=\"")) {
408 g_free(auth->realm);
409 auth->realm = g_strndup(param, end - param);
410 } else if (g_str_has_prefix(hdr, "sts-uri=\"")) {
411 /* Only used with SIPE_AUTHENTICATION_TYPE_TLS_DSK */
412 g_free(auth->sts_uri);
413 auth->sts_uri = g_strndup(param, end - param);
414 } else if (g_str_has_prefix(hdr, "targetname=\"")) {
415 g_free(auth->target);
416 auth->target = g_strndup(param, end - param);
417 } else if (g_str_has_prefix(hdr, "version=")) {
418 auth->version = atoi(param);
421 /* skip to next parameter */
422 while ((*end == '"') || (*end == ',') || (*end == ' '))
423 end++;
424 hdr = end;
427 return;
430 static void sign_outgoing_message(struct sipe_core_private *sipe_private,
431 struct sipmsg *msg)
433 struct sip_transport *transport = sipe_private->transport;
434 gchar *buf;
436 if (transport->registrar.type == SIPE_AUTHENTICATION_TYPE_UNSET) {
437 return;
440 sipe_make_signature(sipe_private, msg);
442 buf = auth_header(sipe_private, &transport->registrar, msg);
443 if (buf) {
444 sipmsg_add_header_now_pos(msg, "Authorization", buf, 5);
445 g_free(buf);
449 static const gchar *sip_transport_user_agent(struct sipe_core_private *sipe_private)
451 struct sip_transport *transport = sipe_private->transport;
453 if (!transport->user_agent) {
454 const gchar *useragent = sipe_backend_setting(SIPE_CORE_PUBLIC,
455 SIPE_SETTING_USER_AGENT);
456 if (is_empty(useragent)) {
457 /*@TODO: better approach to define _user_ OS, it's version and host architecture */
458 /* ref: lzodefs.h */
459 #if defined(__linux__) || defined(__linux) || defined(__LINUX__)
460 #define SIPE_TARGET_PLATFORM "linux"
461 #elif defined(__NetBSD__) ||defined( __OpenBSD__) || defined(__FreeBSD__)
462 #define SIPE_TARGET_PLATFORM "bsd"
463 #elif defined(__APPLE__) || defined(__MACOS__)
464 #define SIPE_TARGET_PLATFORM "macosx"
465 #elif defined(_AIX) || defined(__AIX__) || defined(__aix__)
466 #define SIPE_TARGET_PLATFORM "aix"
467 #elif defined(__solaris__) || defined(__sun)
468 #define SIPE_TARGET_PLATFORM "sun"
469 #elif defined(_WIN32)
470 #define SIPE_TARGET_PLATFORM "win"
471 #elif defined(__CYGWIN__)
472 #define SIPE_TARGET_PLATFORM "cygwin"
473 #elif defined(__hpux__)
474 #define SIPE_TARGET_PLATFORM "hpux"
475 #elif defined(__sgi__)
476 #define SIPE_TARGET_PLATFORM "irix"
477 #else
478 #define SIPE_TARGET_PLATFORM "unknown"
479 #endif
481 #if defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
482 #define SIPE_TARGET_ARCH "x86_64"
483 #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
484 #define SIPE_TARGET_ARCH "i386"
485 #elif defined(__ppc64__)
486 #define SIPE_TARGET_ARCH "ppc64"
487 #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
488 #define SIPE_TARGET_ARCH "ppc"
489 #elif defined(__hppa__) || defined(__hppa)
490 #define SIPE_TARGET_ARCH "hppa"
491 #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
492 #define SIPE_TARGET_ARCH "mips"
493 #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
494 #define SIPE_TARGET_ARCH "s390"
495 #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
496 #define SIPE_TARGET_ARCH "sparc"
497 #elif defined(__arm__)
498 #define SIPE_TARGET_ARCH "arm"
499 #else
500 #define SIPE_TARGET_ARCH "other"
501 #endif
502 gchar *backend = sipe_backend_version();
503 transport->user_agent = g_strdup_printf("%s Sipe/" PACKAGE_VERSION " (" SIPE_TARGET_PLATFORM "-" SIPE_TARGET_ARCH "; %s)",
504 backend,
505 transport->server_version ? transport->server_version : "");
506 g_free(backend);
507 } else {
508 transport->user_agent = g_strdup(useragent);
511 return(transport->user_agent);
514 void sip_transport_response(struct sipe_core_private *sipe_private,
515 struct sipmsg *msg,
516 guint code,
517 const char *text,
518 const char *body)
520 gchar *name;
521 gchar *value;
522 GString *outstr = g_string_new("");
523 gchar *contact;
524 GSList *tmp;
525 const gchar *keepers[] = { "To", "From", "Call-ID", "CSeq", "Via", "Record-Route", NULL };
527 /* Can return NULL! */
528 contact = get_contact(sipe_private);
529 if (contact) {
530 sipmsg_add_header(msg, "Contact", contact);
531 g_free(contact);
534 if (body) {
535 gchar *len = g_strdup_printf("%" G_GSIZE_FORMAT , (gsize) strlen(body));
536 sipmsg_add_header(msg, "Content-Length", len);
537 g_free(len);
538 } else {
539 sipmsg_add_header(msg, "Content-Length", "0");
542 sipmsg_add_header(msg, "User-Agent", sip_transport_user_agent(sipe_private));
544 msg->response = code;
546 sipmsg_strip_headers(msg, keepers);
547 sipmsg_merge_new_headers(msg);
548 sign_outgoing_message(sipe_private, msg);
550 g_string_append_printf(outstr, "SIP/2.0 %d %s\r\n", code, text);
551 tmp = msg->headers;
552 while (tmp) {
553 name = ((struct sipnameval*) (tmp->data))->name;
554 value = ((struct sipnameval*) (tmp->data))->value;
556 g_string_append_printf(outstr, "%s: %s\r\n", name, value);
557 tmp = g_slist_next(tmp);
559 g_string_append_printf(outstr, "\r\n%s", body ? body : "");
560 sipe_utils_message_debug("SIP", outstr->str, NULL, TRUE);
561 sipe_backend_transport_message(sipe_private->transport->connection, outstr->str);
562 g_string_free(outstr, TRUE);
565 static void transactions_remove(struct sipe_core_private *sipe_private,
566 struct transaction *trans)
568 struct sip_transport *transport = sipe_private->transport;
569 if (transport->transactions) {
570 transport->transactions = g_slist_remove(transport->transactions,
571 trans);
572 SIPE_DEBUG_INFO("SIP transactions count:%d after removal", g_slist_length(transport->transactions));
574 if (trans->msg) sipmsg_free(trans->msg);
575 if (trans->payload) {
576 if (trans->payload->destroy)
577 (*trans->payload->destroy)(trans->payload->data);
578 g_free(trans->payload);
580 g_free(trans->key);
581 if (trans->timeout_key) {
582 sipe_schedule_cancel(sipe_private, trans->timeout_key);
583 g_free(trans->timeout_key);
585 g_free(trans);
589 static struct transaction *transactions_find(struct sip_transport *transport,
590 struct sipmsg *msg)
592 GSList *transactions = transport->transactions;
593 const gchar *call_id = sipmsg_find_header(msg, "Call-ID");
594 const gchar *cseq = sipmsg_find_header(msg, "CSeq");
595 gchar *key;
597 if (!call_id || !cseq) {
598 SIPE_DEBUG_ERROR_NOFORMAT("transaction_find: no Call-ID or CSeq!");
599 return NULL;
602 key = g_strdup_printf("<%s><%s>", call_id, cseq);
603 while (transactions) {
604 struct transaction *trans = transactions->data;
605 if (!g_ascii_strcasecmp(trans->key, key)) {
606 g_free(key);
607 return trans;
609 transactions = transactions->next;
611 g_free(key);
613 return NULL;
616 static void transaction_timeout_cb(struct sipe_core_private *sipe_private,
617 gpointer data)
619 struct transaction *trans = data;
620 (trans->timeout_callback)(sipe_private, trans->msg, trans);
621 transactions_remove(sipe_private, trans);
624 struct transaction *sip_transport_request_timeout(struct sipe_core_private *sipe_private,
625 const gchar *method,
626 const gchar *url,
627 const gchar *to,
628 const gchar *addheaders,
629 const gchar *body,
630 struct sip_dialog *dialog,
631 TransCallback callback,
632 guint timeout,
633 TransCallback timeout_callback)
635 struct sip_transport *transport = sipe_private->transport;
636 char *buf;
637 struct sipmsg *msg;
638 gchar *ourtag = dialog && dialog->ourtag ? g_strdup(dialog->ourtag) : NULL;
639 gchar *theirtag = dialog && dialog->theirtag ? g_strdup(dialog->theirtag) : NULL;
640 gchar *theirepid = dialog && dialog->theirepid ? g_strdup(dialog->theirepid) : NULL;
641 gchar *callid = dialog && dialog->callid ? g_strdup(dialog->callid) : gencallid();
642 gchar *branch = dialog && dialog->callid ? NULL : genbranch();
643 gchar *route = g_strdup("");
644 gchar *epid = get_epid(sipe_private);
645 int cseq = dialog ? ++dialog->cseq : 1 /* as Call-Id is new in this case */;
646 struct transaction *trans = NULL;
648 if (dialog && dialog->routes)
650 GSList *iter = dialog->routes;
652 while(iter)
654 char *tmp = route;
655 route = g_strdup_printf("%sRoute: %s\r\n", route, (char *)iter->data);
656 g_free(tmp);
657 iter = g_slist_next(iter);
661 if (!ourtag && !dialog) {
662 ourtag = gentag();
665 if (sipe_strequal(method, "REGISTER")) {
666 if (sipe_private->register_callid) {
667 g_free(callid);
668 callid = g_strdup(sipe_private->register_callid);
669 } else {
670 sipe_private->register_callid = g_strdup(callid);
672 cseq = ++transport->cseq;
675 buf = g_strdup_printf("%s %s SIP/2.0\r\n"
676 "Via: SIP/2.0/%s %s:%d%s%s\r\n"
677 "From: <sip:%s>%s%s;epid=%s\r\n"
678 "To: <%s>%s%s%s%s\r\n"
679 "Max-Forwards: 70\r\n"
680 "CSeq: %d %s\r\n"
681 "User-Agent: %s\r\n"
682 "Call-ID: %s\r\n"
683 "%s%s"
684 "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n%s",
685 method,
686 dialog && dialog->request ? dialog->request : url,
687 TRANSPORT_DESCRIPTOR,
688 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
689 transport->connection->client_port,
690 branch ? ";branch=" : "",
691 branch ? branch : "",
692 sipe_private->username,
693 ourtag ? ";tag=" : "",
694 ourtag ? ourtag : "",
695 epid,
697 theirtag ? ";tag=" : "",
698 theirtag ? theirtag : "",
699 theirepid ? ";epid=" : "",
700 theirepid ? theirepid : "",
701 cseq,
702 method,
703 sip_transport_user_agent(sipe_private),
704 callid,
705 route,
706 addheaders ? addheaders : "",
707 body ? (gsize) strlen(body) : 0,
708 body ? body : "");
711 //printf ("parsing msg buf:\n%s\n\n", buf);
712 msg = sipmsg_parse_msg(buf);
714 g_free(buf);
715 g_free(ourtag);
716 g_free(theirtag);
717 g_free(theirepid);
718 g_free(branch);
719 g_free(route);
720 g_free(epid);
722 sign_outgoing_message(sipe_private, msg);
724 /* The authentication scheme is not ready so we can't send the message.
725 This should only happen for REGISTER messages. */
726 if (!transport->auth_incomplete) {
727 buf = sipmsg_to_string(msg);
729 /* add to ongoing transactions */
730 /* ACK isn't supposed to be answered ever. So we do not keep transaction for it. */
731 if (!sipe_strequal(method, "ACK")) {
732 trans = g_new0(struct transaction, 1);
733 trans->callback = callback;
734 trans->msg = msg;
735 trans->key = g_strdup_printf("<%s><%d %s>", callid, cseq, method);
736 if (timeout_callback) {
737 trans->timeout_callback = timeout_callback;
738 trans->timeout_key = g_strdup_printf("<transaction timeout>%s", trans->key);
739 sipe_schedule_seconds(sipe_private,
740 trans->timeout_key,
741 trans,
742 timeout,
743 transaction_timeout_cb,
744 NULL);
746 transport->transactions = g_slist_append(transport->transactions,
747 trans);
748 SIPE_DEBUG_INFO("SIP transactions count:%d after addition", g_slist_length(transport->transactions));
751 sipe_utils_message_debug("SIP", buf, NULL, TRUE);
752 sipe_backend_transport_message(transport->connection, buf);
753 g_free(buf);
756 if (!trans) sipmsg_free(msg);
757 g_free(callid);
758 return trans;
761 struct transaction *sip_transport_request(struct sipe_core_private *sipe_private,
762 const gchar *method,
763 const gchar *url,
764 const gchar *to,
765 const gchar *addheaders,
766 const gchar *body,
767 struct sip_dialog *dialog,
768 TransCallback callback)
770 return sip_transport_request_timeout(sipe_private,
771 method,
772 url,
774 addheaders,
775 body,
776 dialog,
777 callback,
779 NULL);
782 static void sip_transport_simple_request(struct sipe_core_private *sipe_private,
783 const gchar *method,
784 struct sip_dialog *dialog)
786 sip_transport_request(sipe_private,
787 method,
788 dialog->with,
789 dialog->with,
790 NULL,
791 NULL,
792 dialog,
793 NULL);
796 void sip_transport_ack(struct sipe_core_private *sipe_private,
797 struct sip_dialog *dialog)
799 sip_transport_simple_request(sipe_private, "ACK", dialog);
802 void sip_transport_bye(struct sipe_core_private *sipe_private,
803 struct sip_dialog *dialog)
805 sip_transport_simple_request(sipe_private, "BYE", dialog);
808 struct transaction *sip_transport_info(struct sipe_core_private *sipe_private,
809 const gchar *addheaders,
810 const gchar *body,
811 struct sip_dialog *dialog,
812 TransCallback callback)
814 return sip_transport_request(sipe_private,
815 "INFO",
816 dialog->with,
817 dialog->with,
818 addheaders,
819 body,
820 dialog,
821 callback);
824 struct transaction *sip_transport_invite(struct sipe_core_private *sipe_private,
825 const gchar *addheaders,
826 const gchar *body,
827 struct sip_dialog *dialog,
828 TransCallback callback)
830 return sip_transport_request(sipe_private,
831 "INVITE",
832 dialog->with,
833 dialog->with,
834 addheaders,
835 body,
836 dialog,
837 callback);
840 struct transaction *sip_transport_service(struct sipe_core_private *sipe_private,
841 const gchar *uri,
842 const gchar *addheaders,
843 const gchar *body,
844 TransCallback callback)
846 return sip_transport_request(sipe_private,
847 "SERVICE",
848 uri,
849 uri,
850 addheaders,
851 body,
852 NULL,
853 callback);
856 void sip_transport_subscribe(struct sipe_core_private *sipe_private,
857 const gchar *uri,
858 const gchar *addheaders,
859 const gchar *body,
860 struct sip_dialog *dialog,
861 TransCallback callback)
863 sip_transport_request(sipe_private,
864 "SUBSCRIBE",
865 uri,
866 uri,
867 addheaders,
868 body,
869 dialog,
870 callback);
873 static const gchar *get_auth_header(struct sipe_core_private *sipe_private,
874 struct sip_auth *auth,
875 struct sipmsg *msg)
877 auth->type = sipe_private->authentication_type;
878 auth->protocol = auth_type_to_protocol[auth->type];
880 return(sipmsg_find_auth_header(msg, auth->protocol));
883 static void do_register(struct sipe_core_private *sipe_private,
884 gboolean deregister);
886 static void do_reauthenticate_cb(struct sipe_core_private *sipe_private,
887 SIPE_UNUSED_PARAMETER gpointer unused)
889 struct sip_transport *transport = sipe_private->transport;
891 /* register again when security token expires */
892 /* we have to start a new authentication as the security token
893 * is almost expired by sending a not signed REGISTER message */
894 SIPE_DEBUG_INFO_NOFORMAT("do a full reauthentication");
895 sipe_auth_free(&transport->registrar);
896 sipe_auth_free(&transport->proxy);
897 sipe_schedule_cancel(sipe_private, "<registration>");
898 transport->reregister_set = FALSE;
899 transport->register_attempt = 0;
900 do_register(sipe_private, FALSE);
901 transport->reauthenticate_set = FALSE;
904 static void sip_transport_default_contact(struct sipe_core_private *sipe_private)
906 struct sip_transport *transport = sipe_private->transport;
907 sipe_private->contact = g_strdup_printf("<sip:%s:%d;maddr=%s;transport=%s>;proxy=replace",
908 sipe_private->username,
909 transport->connection->client_port,
910 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
911 TRANSPORT_DESCRIPTOR);
914 static void do_register_cb(struct sipe_core_private *sipe_private,
915 SIPE_UNUSED_PARAMETER void *unused)
917 do_register(sipe_private, FALSE);
920 static void sip_transport_set_reregister(struct sipe_core_private *sipe_private,
921 int expires)
923 sipe_schedule_seconds(sipe_private,
924 "<registration>",
925 NULL,
926 expires,
927 do_register_cb,
928 NULL);
931 static void sipe_server_register(struct sipe_core_private *sipe_private,
932 guint type,
933 gchar *server_name,
934 guint server_port);
936 static gboolean process_register_response(struct sipe_core_private *sipe_private,
937 struct sipmsg *msg,
938 SIPE_UNUSED_PARAMETER struct transaction *trans)
940 struct sip_transport *transport = sipe_private->transport;
941 const gchar *expires_header;
942 int expires, i;
943 GSList *hdr = msg->headers;
944 struct sipnameval *elem;
946 expires_header = sipmsg_find_header(msg, "Expires");
947 expires = expires_header != NULL ? strtol(expires_header, NULL, 10) : 0;
948 SIPE_DEBUG_INFO("process_register_response: got response to REGISTER; expires = %d", expires);
950 switch (msg->response) {
951 case 200:
952 if (expires) {
953 const gchar *contact_hdr;
954 const gchar *auth_hdr;
955 gchar *gruu = NULL;
956 gchar *uuid;
957 gchar *timeout;
958 const gchar *server_hdr = sipmsg_find_header(msg, "Server");
960 if (!transport->reregister_set) {
961 sip_transport_set_reregister(sipe_private,
962 expires);
963 transport->reregister_set = TRUE;
966 if (server_hdr && !transport->server_version) {
967 transport->server_version = g_strdup(server_hdr);
968 g_free(transport->user_agent);
969 transport->user_agent = NULL;
972 auth_hdr = get_auth_header(sipe_private, &transport->registrar, msg);
973 if (auth_hdr) {
974 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
975 fill_auth(auth_hdr, &transport->registrar);
978 if (!transport->reauthenticate_set) {
979 gchar *action_name = g_strdup_printf("<%s>", "+reauthentication");
980 guint reauth_timeout = transport->registrar.expires;
982 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully");
984 /* Does authentication scheme provide valid expiration time? */
985 if (reauth_timeout <= (5 * 60)) {
986 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: no expiration time - using default of 8 hours");
987 reauth_timeout = 8 * 60 * 60;
990 /* schedule reauthentication 5 minutes before expiration */
991 sipe_schedule_seconds(sipe_private,
992 action_name,
993 NULL,
994 reauth_timeout - 5 * 60,
995 do_reauthenticate_cb,
996 NULL);
997 g_free(action_name);
998 transport->reauthenticate_set = TRUE;
1001 sipe_backend_connection_completed(SIPE_CORE_PUBLIC);
1003 uuid = get_uuid(sipe_private);
1005 // There can be multiple Contact headers (one per location where the user is logged in) so
1006 // make sure to only get the one for this uuid
1007 for (i = 0; (contact_hdr = sipmsg_find_header_instance (msg, "Contact", i)); i++) {
1008 gchar * valid_contact = sipmsg_find_part_of_header (contact_hdr, uuid, NULL, NULL);
1009 if (valid_contact) {
1010 gruu = sipmsg_find_part_of_header(contact_hdr, "gruu=\"", "\"", NULL);
1011 //SIPE_DEBUG_INFO("process_register_response: got gruu %s from contact hdr w/ right uuid: %s", gruu, contact_hdr);
1012 g_free(valid_contact);
1013 break;
1014 } else {
1015 //SIPE_DEBUG_INFO("process_register_response: ignoring contact hdr b/c not right uuid: %s", contact_hdr);
1018 g_free(uuid);
1020 g_free(sipe_private->contact);
1021 if(gruu) {
1022 sipe_private->contact = g_strdup_printf("<%s>", gruu);
1023 g_free(gruu);
1024 } else {
1025 //SIPE_DEBUG_INFO_NOFORMAT("process_register_response: didn't find gruu in a Contact hdr");
1026 sip_transport_default_contact(sipe_private);
1028 SIPE_CORE_PRIVATE_FLAG_UNSET(OCS2007);
1029 SIPE_CORE_PRIVATE_FLAG_UNSET(REMOTE_USER);
1030 SIPE_CORE_PRIVATE_FLAG_UNSET(BATCHED_SUPPORT);
1032 while(hdr)
1034 elem = hdr->data;
1035 if (sipe_strcase_equal(elem->name, "Supported")) {
1036 if (sipe_strcase_equal(elem->value, "msrtc-event-categories")) {
1037 /* We interpret this as OCS2007+ indicator */
1038 SIPE_CORE_PRIVATE_FLAG_SET(OCS2007);
1039 SIPE_DEBUG_INFO("Supported: %s (indicates OCS2007+)", elem->value);
1041 if (sipe_strcase_equal(elem->value, "adhoclist")) {
1042 SIPE_CORE_PRIVATE_FLAG_SET(BATCHED_SUPPORT);
1043 SIPE_DEBUG_INFO("Supported: %s", elem->value);
1046 if (sipe_strcase_equal(elem->name, "Allow-Events")){
1047 gchar **caps = g_strsplit(elem->value,",",0);
1048 i = 0;
1049 while (caps[i]) {
1050 sipe_private->allowed_events = g_slist_append(sipe_private->allowed_events, g_strdup(caps[i]));
1051 SIPE_DEBUG_INFO("Allow-Events: %s", caps[i]);
1052 i++;
1054 g_strfreev(caps);
1056 if (sipe_strcase_equal(elem->name, "ms-user-logon-data")) {
1057 if (sipe_strcase_equal(elem->value, "RemoteUser")) {
1058 SIPE_CORE_PRIVATE_FLAG_SET(REMOTE_USER);
1059 SIPE_DEBUG_INFO_NOFORMAT("ms-user-logon-data: RemoteUser (connected "
1060 "via Edge Server)");
1063 hdr = g_slist_next(hdr);
1066 /* rejoin open chats to be able to use them by continue to send messages */
1067 sipe_backend_chat_rejoin_all(SIPE_CORE_PUBLIC);
1069 /* subscriptions */
1070 if (!transport->subscribed) { //do it just once, not every re-register
1072 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-roaming-contacts",
1073 (GCompareFunc)g_ascii_strcasecmp)) {
1074 sipe_subscribe_roaming_contacts(sipe_private);
1077 /* For 2007+ it does not make sence to subscribe to:
1078 * vnd-microsoft-roaming-ACL
1079 * vnd-microsoft-provisioning (not v2)
1080 * presence.wpending
1081 * These are for backward compatibility.
1083 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007))
1085 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-roaming-self",
1086 (GCompareFunc)g_ascii_strcasecmp)) {
1087 sipe_subscribe_roaming_self(sipe_private);
1089 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-provisioning-v2",
1090 (GCompareFunc)g_ascii_strcasecmp)) {
1091 sipe_subscribe_roaming_provisioning_v2(sipe_private);
1094 /* For 2005- servers */
1095 else
1097 //sipe_options_request(sip, sipe_private->public.sip_domain);
1099 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-roaming-ACL",
1100 (GCompareFunc)g_ascii_strcasecmp)) {
1101 sipe_subscribe_roaming_acl(sipe_private);
1103 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-provisioning",
1104 (GCompareFunc)g_ascii_strcasecmp)) {
1105 sipe_subscribe_roaming_provisioning(sipe_private);
1107 if (g_slist_find_custom(sipe_private->allowed_events, "presence.wpending",
1108 (GCompareFunc)g_ascii_strcasecmp)) {
1109 sipe_subscribe_presence_wpending(sipe_private,
1110 NULL);
1113 /* For 2007+ we publish our initial statuses and calendar data only after
1114 * received our existing publications in sipe_process_roaming_self()
1115 * Only in this case we know versions of current publications made
1116 * on our behalf.
1118 /* For 2005- we publish our initial statuses only after
1119 * received our existing UserInfo data in response to
1120 * self subscription.
1121 * Only in this case we won't override existing UserInfo data
1122 * set earlier or by other client on our behalf.
1126 transport->subscribed = TRUE;
1129 timeout = sipmsg_find_part_of_header(sipmsg_find_header(msg, "ms-keep-alive"),
1130 "timeout=", ";", NULL);
1131 if (timeout != NULL) {
1132 sscanf(timeout, "%u", &sipe_private->public.keepalive_timeout);
1133 SIPE_DEBUG_INFO("process_register_response: server determined keep alive timeout is %u seconds",
1134 sipe_private->public.keepalive_timeout);
1135 g_free(timeout);
1138 SIPE_DEBUG_INFO("process_register_response: got 200, removing CSeq: %d", transport->cseq);
1140 break;
1141 case 301:
1143 gchar *redirect = parse_from(sipmsg_find_header(msg, "Contact"));
1145 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully (with redirect)");
1147 if (redirect && (g_ascii_strncasecmp("sip:", redirect, 4) == 0)) {
1148 gchar **parts = g_strsplit(redirect + 4, ";", 0);
1149 gchar **tmp;
1150 gchar *hostname;
1151 int port = 0;
1152 guint transport_type = SIPE_TRANSPORT_TLS;
1153 int i = 1;
1155 tmp = g_strsplit(parts[0], ":", 0);
1156 hostname = g_strdup(tmp[0]);
1157 if (tmp[1]) port = strtoul(tmp[1], NULL, 10);
1158 g_strfreev(tmp);
1160 while (parts[i]) {
1161 tmp = g_strsplit(parts[i], "=", 0);
1162 if (tmp[1]) {
1163 if (g_ascii_strcasecmp("transport", tmp[0]) == 0) {
1164 if (g_ascii_strcasecmp("tcp", tmp[1]) == 0) {
1165 transport_type = SIPE_TRANSPORT_TCP;
1169 g_strfreev(tmp);
1170 i++;
1172 g_strfreev(parts);
1174 /* Close old connection */
1175 sipe_core_connection_cleanup(sipe_private);
1176 /* transport and sipe_private->transport are invalid after this */
1178 /* Create new connection */
1179 sipe_server_register(sipe_private, transport_type, hostname, port);
1180 /* sipe_private->transport has a new value */
1181 SIPE_DEBUG_INFO("process_register_response: redirected to host %s port %d transport %d",
1182 hostname, port, transport_type);
1184 g_free(redirect);
1186 break;
1187 case 401:
1189 const char *auth_hdr;
1191 SIPE_DEBUG_INFO("process_register_response: REGISTER retries %d", transport->registrar.retries);
1193 if (transport->reauthenticate_set) {
1194 SIPE_DEBUG_ERROR_NOFORMAT("process_register_response: RE-REGISTER rejected, triggering re-authentication");
1195 do_reauthenticate_cb(sipe_private, NULL);
1196 return TRUE;
1199 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1200 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake failed - giving up.");
1201 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1202 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
1203 _("Authentication failed"));
1204 return TRUE;
1207 auth_hdr = get_auth_header(sipe_private, &transport->registrar, msg);
1208 if (!auth_hdr) {
1209 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1210 SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
1211 _("Incompatible authentication scheme chosen"));
1212 return TRUE;
1214 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
1215 fill_auth(auth_hdr, &transport->registrar);
1216 transport->reregister_set = FALSE;
1217 transport->register_attempt = 0;
1218 do_register(sipe_private,
1219 sipe_backend_connection_is_disconnecting(SIPE_CORE_PUBLIC));
1221 break;
1222 case 403:
1224 gchar *reason;
1225 gchar *warning;
1226 sipmsg_parse_warning(msg, &reason);
1227 reason = reason ? reason : sipmsg_get_ms_diagnostics_public_reason(msg);
1228 warning = g_strdup_printf(_("You have been rejected by the server: %s"),
1229 reason ? reason : _("no reason given"));
1230 g_free(reason);
1232 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1233 SIPE_CONNECTION_ERROR_INVALID_SETTINGS,
1234 warning);
1235 g_free(warning);
1236 return TRUE;
1238 break;
1239 case 404:
1241 const gchar *diagnostics = sipmsg_find_header(msg, "ms-diagnostics");
1242 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1243 gchar *warning;
1244 warning = g_strdup_printf(_("Not found: %s. Please contact your Administrator"),
1245 diagnostics ? (reason ? reason : _("no reason given")) :
1246 _("SIP is either not enabled for the destination URI or it does not exist"));
1247 g_free(reason);
1249 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1250 SIPE_CONNECTION_ERROR_INVALID_USERNAME,
1251 warning);
1252 g_free(warning);
1253 return TRUE;
1255 break;
1256 case 504: /* Server time-out */
1257 /* first attempt + 5 retries */
1258 if (transport->register_attempt < 6) {
1259 SIPE_DEBUG_INFO("process_register_response: RE-REGISTER timeout on attempt %d, retrying later",
1260 transport->register_attempt);
1261 sip_transport_set_reregister(sipe_private, 60);
1262 return TRUE;
1264 /* FALLTHROUGH */
1265 case 503:
1267 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1268 gchar *warning;
1269 warning = g_strdup_printf(_("Service unavailable: %s"), reason ? reason : _("no reason given"));
1270 g_free(reason);
1272 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1273 SIPE_CONNECTION_ERROR_NETWORK,
1274 warning);
1275 g_free(warning);
1276 return TRUE;
1278 break;
1280 return TRUE;
1283 static gboolean register_response_timeout(struct sipe_core_private *sipe_private,
1284 SIPE_UNUSED_PARAMETER struct sipmsg *msg,
1285 SIPE_UNUSED_PARAMETER struct transaction *trans)
1287 struct sip_transport *transport = sipe_private->transport;
1288 if (transport->register_attempt < 6) {
1289 SIPE_DEBUG_INFO("register_response_timeout: no answer to attempt %d, retrying",
1290 transport->register_attempt);
1291 do_register(sipe_private, FALSE);
1292 } else {
1293 gchar *warning = g_strdup_printf(_("Service unavailable: %s"), _("no reason given"));
1294 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1295 SIPE_CONNECTION_ERROR_NETWORK,
1296 warning);
1297 g_free(warning);
1299 return TRUE;
1302 static void do_register(struct sipe_core_private *sipe_private,
1303 gboolean deregister)
1305 struct sip_transport *transport = sipe_private->transport;
1306 char *uri;
1307 char *to;
1308 char *hdr;
1309 char *uuid;
1311 if (!sipe_private->public.sip_domain) return;
1313 if (!deregister) {
1314 if (transport->reregister_set) {
1315 transport->reregister_set = FALSE;
1316 transport->register_attempt = 1;
1317 } else {
1318 transport->register_attempt++;
1322 transport->deregister = deregister;
1323 transport->auth_incomplete = FALSE;
1325 uuid = get_uuid(sipe_private);
1326 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"
1327 "Supported: gruu-10, adhoclist, msrtc-event-categories, com.microsoft.msrtc.presence\r\n"
1328 "Event: registration\r\n"
1329 "Allow-Events: presence\r\n"
1330 "ms-keep-alive: UAC;hop-hop=yes\r\n"
1331 "%s",
1332 sipe_backend_network_ip_address(SIPE_CORE_PUBLIC),
1333 transport->connection->client_port,
1334 TRANSPORT_DESCRIPTOR,
1335 uuid,
1336 deregister ? "Expires: 0\r\n" : "");
1337 g_free(uuid);
1339 uri = sip_uri_from_name(sipe_private->public.sip_domain);
1340 to = sip_uri_self(sipe_private);
1341 sip_transport_request_timeout(sipe_private,
1342 "REGISTER",
1343 uri,
1345 hdr,
1347 NULL,
1348 process_register_response,
1350 deregister ? NULL : register_response_timeout);
1351 g_free(to);
1352 g_free(uri);
1353 g_free(hdr);
1355 if (deregister) {
1356 /* Make sure that all messages are pushed to the server
1357 before the connection gets shut down */
1358 SIPE_DEBUG_INFO_NOFORMAT("De-register from server. Flushing outstanding messages.");
1359 sipe_backend_transport_flush(transport->connection);
1363 void sip_transport_deregister(struct sipe_core_private *sipe_private)
1365 do_register(sipe_private, TRUE);
1368 void sip_transport_disconnect(struct sipe_core_private *sipe_private)
1370 struct sip_transport *transport = sipe_private->transport;
1372 /* transport can be NULL during connection setup */
1373 if (transport) {
1374 sipe_backend_transport_disconnect(transport->connection);
1376 sipe_auth_free(&transport->registrar);
1377 sipe_auth_free(&transport->proxy);
1379 g_free(transport->server_name);
1380 g_free(transport->server_version);
1381 g_free(transport->user_agent);
1383 while (transport->transactions)
1384 transactions_remove(sipe_private,
1385 transport->transactions->data);
1387 g_free(transport);
1390 sipe_private->transport = NULL;
1391 sipe_private->service_data = NULL;
1392 sipe_private->address_data = NULL;
1394 if (sipe_private->dns_query)
1395 sipe_backend_dns_query_cancel(sipe_private->dns_query);
1399 void sip_transport_authentication_completed(struct sipe_core_private *sipe_private)
1401 do_reauthenticate_cb(sipe_private, NULL);
1404 guint sip_transport_port(struct sipe_core_private *sipe_private)
1406 return sipe_private->transport->server_port;
1409 static void process_input_message(struct sipe_core_private *sipe_private,
1410 struct sipmsg *msg)
1412 struct sip_transport *transport = sipe_private->transport;
1413 gboolean notfound = FALSE;
1414 const char *method = msg->method ? msg->method : "NOT FOUND";
1416 SIPE_DEBUG_INFO("process_input_message: msg->response(%d),msg->method(%s)",
1417 msg->response, method);
1419 if (msg->response == 0) { /* request */
1420 if (sipe_strequal(method, "MESSAGE")) {
1421 process_incoming_message(sipe_private, msg);
1422 } else if (sipe_strequal(method, "NOTIFY")) {
1423 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_notify");
1424 process_incoming_notify(sipe_private, msg, TRUE, FALSE);
1425 } else if (sipe_strequal(method, "BENOTIFY")) {
1426 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_benotify");
1427 process_incoming_notify(sipe_private, msg, TRUE, TRUE);
1428 } else if (sipe_strequal(method, "INVITE")) {
1429 process_incoming_invite(sipe_private, msg);
1430 } else if (sipe_strequal(method, "REFER")) {
1431 process_incoming_refer(sipe_private, msg);
1432 } else if (sipe_strequal(method, "OPTIONS")) {
1433 process_incoming_options(sipe_private, msg);
1434 } else if (sipe_strequal(method, "INFO")) {
1435 process_incoming_info(sipe_private, msg);
1436 } else if (sipe_strequal(method, "ACK")) {
1437 /* ACK's don't need any response */
1438 } else if (sipe_strequal(method, "PRACK")) {
1439 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1440 } else if (sipe_strequal(method, "SUBSCRIBE")) {
1441 /* LCS 2005 sends us these - just respond 200 OK */
1442 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1443 } else if (sipe_strequal(method, "CANCEL")) {
1444 process_incoming_cancel(sipe_private, msg);
1445 } else if (sipe_strequal(method, "BYE")) {
1446 process_incoming_bye(sipe_private, msg);
1447 } else {
1448 sip_transport_response(sipe_private, msg, 501, "Not implemented", NULL);
1449 notfound = TRUE;
1452 } else { /* response */
1453 struct transaction *trans = transactions_find(transport, msg);
1454 if (trans) {
1455 if (msg->response < 200) {
1456 /* ignore provisional response */
1457 SIPE_DEBUG_INFO("process_input_message: got provisional (%d) response, ignoring", msg->response);
1459 /* Transaction not yet completed */
1460 trans = NULL;
1462 } else if (msg->response == 401) { /* Unauthorized */
1464 if (sipe_strequal(trans->msg->method, "REGISTER")) {
1465 /* Expected response during authentication handshake */
1466 transport->registrar.retries++;
1467 SIPE_DEBUG_INFO("process_input_message: RE-REGISTER CSeq: %d", transport->cseq);
1468 } else {
1469 gchar *resend;
1471 /* Are we registered? */
1472 if (transport->reregister_set) {
1473 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Retrying with new authentication.");
1474 sign_outgoing_message(sipe_private,
1475 trans->msg);
1476 } else {
1478 * We don't have a valid authentication at the moment.
1479 * Resend message unchanged. It will be rejected again
1480 * and hopefully by then we have a valid authentication.
1482 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Bouncing...");
1485 /* Resend request */
1486 resend = sipmsg_to_string(trans->msg);
1487 sipe_utils_message_debug("SIP", resend, NULL, TRUE);
1488 sipe_backend_transport_message(sipe_private->transport->connection, resend);
1489 g_free(resend);
1491 /* Transaction not yet completed */
1492 trans = NULL;
1495 } else if (msg->response == 407) { /* Proxy Authentication Required */
1497 if (transport->proxy.retries > 30) {
1498 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: too many proxy authentication retries. Giving up.");
1499 } else {
1500 gchar *resend, *auth;
1501 const gchar *auth_hdr;
1503 transport->proxy.retries++;
1505 /* do proxy authentication */
1506 auth_hdr = sipmsg_find_header(msg, "Proxy-Authenticate");
1507 if (auth_hdr) {
1508 guint i;
1509 transport->proxy.type = SIPE_AUTHENTICATION_TYPE_UNSET;
1510 for (i = 0; i < AUTH_PROTOCOLS; i++) {
1511 const gchar *protocol = auth_type_to_protocol[i];
1512 if (protocol &&
1513 !g_ascii_strncasecmp(auth_hdr, protocol, strlen(protocol))) {
1514 SIPE_DEBUG_INFO("proxy auth: type %s", protocol);
1515 transport->proxy.type = i;
1516 transport->proxy.protocol = protocol;
1517 break;
1520 if (transport->proxy.type == SIPE_AUTHENTICATION_TYPE_UNSET)
1521 SIPE_DEBUG_ERROR("Unknown proxy authentication: %s", auth_hdr);
1522 fill_auth(auth_hdr, &transport->proxy);
1524 auth = auth_header(sipe_private, &transport->proxy, trans->msg);
1525 if (auth) {
1526 sipmsg_remove_header_now(trans->msg, "Proxy-Authorization");
1527 sipmsg_add_header_now_pos(trans->msg, "Proxy-Authorization", auth, 5);
1528 g_free(auth);
1531 /* resend request */
1532 resend = sipmsg_to_string(trans->msg);
1533 sipe_utils_message_debug("SIP", resend, NULL, TRUE);
1534 sipe_backend_transport_message(sipe_private->transport->connection, resend);
1535 g_free(resend);
1537 /* Transaction not yet completed */
1538 trans = NULL;
1541 } else {
1542 transport->registrar.retries = 0;
1543 transport->proxy.retries = 0;
1546 /* Is transaction completed? */
1547 if (trans) {
1548 if (trans->callback) {
1549 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: we have a transaction callback");
1550 /* call the callback to process response */
1551 (trans->callback)(sipe_private, msg, trans);
1552 /* transport && trans no longer valid after redirect */
1556 * Redirect case: sipe_private->transport is
1557 * the new transport with empty queue
1559 if (sipe_private->transport->transactions) {
1560 SIPE_DEBUG_INFO("process_input_message: removing CSeq %d", transport->cseq);
1561 transactions_remove(sipe_private, trans);
1564 } else {
1565 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: received response to unknown transaction");
1566 notfound = TRUE;
1570 if (notfound) {
1571 SIPE_DEBUG_INFO("received a unknown sip message with method %s and response %d", method, msg->response);
1575 static void sip_transport_input(struct sipe_transport_connection *conn)
1577 struct sipe_core_private *sipe_private = conn->user_data;
1578 struct sip_transport *transport = sipe_private->transport;
1579 gchar *cur = conn->buffer;
1581 /* according to the RFC remove CRLF at the beginning */
1582 while (*cur == '\r' || *cur == '\n') {
1583 cur++;
1585 if (cur != conn->buffer)
1586 sipe_utils_shrink_buffer(conn, cur);
1588 /* Received a full Header? */
1589 transport->processing_input = TRUE;
1590 while (transport->processing_input &&
1591 ((cur = strstr(conn->buffer, "\r\n\r\n")) != NULL)) {
1592 struct sipmsg *msg;
1593 guint remainder;
1595 cur += 2;
1596 cur[0] = '\0';
1597 msg = sipmsg_parse_header(conn->buffer);
1599 cur += 2;
1600 remainder = conn->buffer_used - (cur - conn->buffer);
1601 if (msg && remainder >= (guint) msg->bodylen) {
1602 char *dummy = g_malloc(msg->bodylen + 1);
1603 memcpy(dummy, cur, msg->bodylen);
1604 dummy[msg->bodylen] = '\0';
1605 msg->body = dummy;
1606 cur += msg->bodylen;
1607 sipe_utils_message_debug("SIP",
1608 conn->buffer,
1609 msg->body,
1610 FALSE);
1611 sipe_utils_shrink_buffer(conn, cur);
1612 } else {
1613 if (msg){
1614 SIPE_DEBUG_INFO("sipe_transport_input: body too short (%d < %d, strlen %d) - ignoring message", remainder, msg->bodylen, (int)strlen(conn->buffer));
1615 sipmsg_free(msg);
1618 /* restore header for next try */
1619 cur[-2] = '\r';
1620 return;
1623 // Verify the signature before processing it
1624 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1625 struct sipmsg_breakdown msgbd;
1626 gchar *signature_input_str;
1627 gchar *rspauth;
1628 msgbd.msg = msg;
1629 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
1630 transport->registrar.protocol);
1631 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
1633 rspauth = sipmsg_find_part_of_header(sipmsg_find_header(msg, "Authentication-Info"), "rspauth=\"", "\"", NULL);
1635 if (rspauth != NULL) {
1636 if (sip_sec_verify_signature(transport->registrar.gssapi_context, signature_input_str, rspauth)) {
1637 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message validated");
1638 process_input_message(sipe_private, msg);
1639 /* transport is invalid after redirect */
1640 } else {
1641 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message is invalid.");
1642 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1643 SIPE_CONNECTION_ERROR_NETWORK,
1644 _("Invalid message signature received"));
1646 } else if ((msg->response == 401) ||
1647 sipe_strequal(msg->method, "REGISTER")) {
1648 /* a) Retry non-REGISTER requests with updated authentication */
1649 /* b) We must always process REGISTER responses */
1650 process_input_message(sipe_private, msg);
1651 } else {
1652 /* OCS sends provisional messages that are *not* signed */
1653 if (msg->response >= 200) {
1654 /* We are not calling process_input_message(),
1655 so we need to drop the transaction here. */
1656 struct transaction *trans = transactions_find(transport, msg);
1657 if (trans) transactions_remove(sipe_private, trans);
1659 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: message without authentication data - ignoring");
1661 g_free(signature_input_str);
1663 g_free(rspauth);
1664 sipmsg_breakdown_free(&msgbd);
1665 } else {
1666 process_input_message(sipe_private, msg);
1669 sipmsg_free(msg);
1671 /* Redirect: old content of "transport" & "conn" is no longer valid */
1672 transport = sipe_private->transport;
1673 conn = transport->connection;
1677 static void sip_transport_connected(struct sipe_transport_connection *conn)
1679 struct sipe_core_private *sipe_private = conn->user_data;
1680 sipe_private->service_data = NULL;
1681 sipe_private->address_data = NULL;
1682 do_register(sipe_private, FALSE);
1685 static void resolve_next_service(struct sipe_core_private *sipe_private,
1686 const struct sip_service_data *start);
1687 static void resolve_next_address(struct sipe_core_private *sipe_private,
1688 gboolean initial);
1689 static void sip_transport_error(struct sipe_transport_connection *conn,
1690 const gchar *msg)
1692 struct sipe_core_private *sipe_private = conn->user_data;
1694 /* This failed attempt was based on a DNS SRV record */
1695 if (sipe_private->service_data) {
1696 resolve_next_service(sipe_private, NULL);
1697 /* This failed attempt was based on a DNS A record */
1698 } else if (sipe_private->address_data) {
1699 resolve_next_address(sipe_private, FALSE);
1700 } else {
1701 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1702 SIPE_CONNECTION_ERROR_NETWORK,
1703 msg);
1707 /* server_name must be g_alloc()'ed */
1708 static void sipe_server_register(struct sipe_core_private *sipe_private,
1709 guint type,
1710 gchar *server_name,
1711 guint server_port)
1713 sipe_connect_setup setup = {
1714 type,
1715 server_name,
1716 (server_port != 0) ? server_port :
1717 (type == SIPE_TRANSPORT_TLS) ? 5061 : 5060,
1718 sipe_private,
1719 sip_transport_connected,
1720 sip_transport_input,
1721 sip_transport_error
1723 struct sip_transport *transport = g_new0(struct sip_transport, 1);
1725 transport->server_name = server_name;
1726 transport->server_port = setup.server_port;
1727 transport->connection = sipe_backend_transport_connect(SIPE_CORE_PUBLIC,
1728 &setup);
1729 sipe_private->transport = transport;
1732 struct sip_service_data {
1733 const char *protocol;
1734 const char *transport;
1735 guint type;
1739 * Autodiscover using DNS SRV records. See RFC2782/3263
1741 * Service list for AUTO
1743 static const struct sip_service_data service_autodetect[] = {
1744 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1745 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1746 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1747 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1748 { NULL, NULL, 0 }
1751 /* Service list for SSL/TLS */
1752 static const struct sip_service_data service_tls[] = {
1753 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1754 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1755 { NULL, NULL, 0 }
1758 /* Service list for TCP */
1759 static const struct sip_service_data service_tcp[] = {
1760 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1761 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1762 { NULL, NULL, 0 }
1765 static const struct sip_service_data *services[] = {
1766 service_autodetect, /* SIPE_TRANSPORT_AUTO */
1767 service_tls, /* SIPE_TRANSPORT_TLS */
1768 service_tcp /* SIPE_TRANSPORT_TCP */
1771 struct sip_address_data {
1772 const char *prefix;
1773 guint port;
1777 * Autodiscover using DNS A records. This is an extension addded
1778 * by Microsoft. See http://support.microsoft.com/kb/2619522
1780 static const struct sip_address_data addresses[] = {
1781 { "sipinternal", 5061 },
1782 { "sipexternal", 443 },
1784 * Our implementation supports only one port per host name. If the host name
1785 * resolves OK, we abort the search and try to connect. If we would know if we
1786 * are trying to connect from "Intranet" or "Internet" then we could choose
1787 * between those two ports.
1789 * We drop port 5061 in order to cover the "Internet" case.
1791 * { "sip", 5061 },
1793 { "sip", 443 },
1794 { NULL, 0 }
1797 static void sipe_core_dns_resolved(struct sipe_core_public *sipe_public,
1798 const gchar *hostname, guint port)
1800 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1801 gboolean service = sipe_private->service_data != NULL;
1803 sipe_private->dns_query = NULL;
1805 if (hostname) {
1806 gchar *host;
1807 guint type;
1809 if (service) {
1810 host = g_strdup(hostname);
1811 type = sipe_private->service_data->type;
1812 } else {
1813 /* DNS A resolver returns an IP address */
1814 host = g_strdup_printf("%s.%s",
1815 sipe_private->address_data->prefix,
1816 sipe_private->public.sip_domain);
1817 port = sipe_private->address_data->port;
1818 type = sipe_private->transport_type;
1819 if (type == SIPE_TRANSPORT_AUTO)
1820 type = SIPE_TRANSPORT_TLS;
1823 SIPE_DEBUG_INFO("sipe_core_dns_resolved - %s hostname: %s port: %d",
1824 service ? "SRV" : "A", hostname, port);
1825 sipe_server_register(sipe_private, type, host, port);
1826 } else {
1827 if (service)
1828 resolve_next_service(SIPE_CORE_PRIVATE, NULL);
1829 else
1830 resolve_next_address(SIPE_CORE_PRIVATE, FALSE);
1834 static void resolve_next_service(struct sipe_core_private *sipe_private,
1835 const struct sip_service_data *start)
1837 if (start) {
1838 sipe_private->service_data = start;
1839 } else {
1840 sipe_private->service_data++;
1841 if (sipe_private->service_data->protocol == NULL) {
1843 /* We tried all services */
1844 sipe_private->service_data = NULL;
1846 /* Try A records list next */
1847 SIPE_DEBUG_INFO_NOFORMAT("no SRV records found; trying A records next");
1848 resolve_next_address(sipe_private, TRUE);
1849 return;
1853 /* Try to resolve next service */
1854 sipe_private->dns_query = sipe_backend_dns_query_srv(
1855 SIPE_CORE_PUBLIC,
1856 sipe_private->service_data->protocol,
1857 sipe_private->service_data->transport,
1858 sipe_private->public.sip_domain,
1859 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
1860 SIPE_CORE_PUBLIC);
1863 static void resolve_next_address(struct sipe_core_private *sipe_private,
1864 gboolean initial)
1866 gchar *hostname;
1868 if (initial) {
1869 sipe_private->address_data = addresses;
1870 } else {
1871 sipe_private->address_data++;
1872 if (sipe_private->address_data->prefix == NULL) {
1873 guint type = sipe_private->transport_type;
1875 /* We tried all addresss */
1876 sipe_private->address_data = NULL;
1878 /* Try connecting to the SIP hostname directly */
1879 SIPE_DEBUG_INFO_NOFORMAT("no SRV or A records found; using SIP domain as fallback");
1880 if (type == SIPE_TRANSPORT_AUTO)
1881 type = SIPE_TRANSPORT_TLS;
1883 sipe_server_register(sipe_private, type,
1884 g_strdup(sipe_private->public.sip_domain),
1886 return;
1890 /* Try to resolve next address */
1891 hostname = g_strdup_printf("%s.%s",
1892 sipe_private->address_data->prefix,
1893 sipe_private->public.sip_domain);
1894 sipe_private->dns_query = sipe_backend_dns_query_a(
1895 SIPE_CORE_PUBLIC,
1896 hostname,
1897 sipe_private->address_data->port,
1898 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
1899 SIPE_CORE_PUBLIC);
1900 g_free(hostname);
1904 * NOTE: this function can be called before sipe_core_allocate()!
1906 gboolean sipe_core_transport_sip_requires_password(guint authentication,
1907 gboolean sso)
1909 return(sip_sec_requires_password(authentication, sso));
1912 void sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public,
1913 guint transport,
1914 guint authentication,
1915 const gchar *server,
1916 const gchar *port)
1918 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1920 sipe_private->authentication_type = authentication;
1923 * Initializing the certificate sub-system will trigger the generation
1924 * of a cryptographic key pair which takes time. If we do this after we
1925 * have connected to the server then there is a risk that we run into a
1926 * SIP connection timeout. So let's get this out of the way now...
1928 * This is currently only needed if the user has selected TLS-DSK.
1930 if (sipe_private->authentication_type == SIPE_AUTHENTICATION_TYPE_TLS_DSK)
1931 sipe_certificate_init(sipe_private);
1933 if (server) {
1934 /* Use user specified server[:port] */
1935 int port_number = 0;
1937 if (port)
1938 port_number = atoi(port);
1940 SIPE_DEBUG_INFO("sipe_core_connect: user specified SIP server %s:%d",
1941 server, port_number);
1943 sipe_server_register(sipe_private, transport,
1944 g_strdup(server), port_number);
1945 } else {
1946 /* Server auto-discovery */
1948 /* Remember user specified transport type */
1949 sipe_private->transport_type = transport;
1950 resolve_next_service(sipe_private, services[transport]);
1954 void sipe_core_transport_sip_keepalive(struct sipe_core_public *sipe_public)
1956 SIPE_DEBUG_INFO("sending keep alive %d",
1957 sipe_public->keepalive_timeout);
1958 sipe_utils_message_debug("SIP", "", NULL, TRUE);
1959 sipe_backend_transport_message(SIPE_CORE_PRIVATE->transport->connection,
1960 "\r\n\r\n");
1963 int sip_transaction_cseq(struct transaction *trans)
1965 int cseq;
1967 g_return_val_if_fail(trans && trans->key, 0);
1969 sscanf(trans->key, "<%*[a-zA-Z0-9]><%d INVITE>", &cseq);
1970 return cseq;
1974 Local Variables:
1975 mode: c
1976 c-file-style: "bsd"
1977 indent-tabs-mode: t
1978 tab-width: 8
1979 End: